Age | Commit message (Collapse) | Author |
|
https://github.com/rubygems/rubygems/commit/06b4a7994d
|
|
Since we no longer have multiple global sources, each top level dependency is
always pinned to a single source, so it makes little sense to talk about
adding or removing a source. Instead, source changes always mean to
change the source one or more dependencies are pinned to. This logic can
now be much simpler.
https://github.com/rubygems/rubygems/commit/f1d33fa0df
|
|
We have two representations of a source. Once used for sorting, which
should not depend on the source's state, but solely on its static
information, like remotes. Another one used for error and informational
messages, which should properly inform about the exact state of the
source when the message is printed.
This commit makes the latter be the default implementation of `to_s`, so
that error and informational messages are more accurate by default.
https://github.com/rubygems/rubygems/commit/b5f2b88957
|
|
Otherwise we hide some useful message about dependency source changes.
https://github.com/rubygems/rubygems/commit/c926673c5b
|
|
https://github.com/rubygems/rubygems/commit/6f1b5f68de
|
|
Somehow this is trying to relax frozen mode constraints for path
sources. It doesn't make sense to me and it's not covered by any spec so
I'm killing it.
https://github.com/rubygems/rubygems/commit/17c978e161
|
|
It makes the code more consistent with the above line.
https://github.com/rubygems/rubygems/commit/f28d05a548
|
|
https://github.com/rubygems/rubygems/commit/11193be3f1
|
|
https://github.com/rubygems/rubygems/commit/d047b8935d
|
|
|
|
|
|
|
|
* Lazily create singletons on instance_{exec,eval}
Previously when instance_exec or instance_eval was called on an object,
that object would be given a singleton class so that method
definitions inside the block would be added to the object rather than
its class.
This commit aims to improve performance by delaying the creation of the
singleton class unless/until one is needed for method definition. Most
of the time instance_eval is used without any method definition.
This was implemented by adding a flag to the cref indicating that it
represents a singleton of the object rather than a class itself. In this
case CREF_CLASS returns the object's existing class, but in cases that
we are defining a method (either via definemethod or
VM_SPECIAL_OBJECT_CBASE which is used for undef and alias).
This also happens to fix what I believe is a bug. Previously
instance_eval behaved differently with regards to constant access for
true/false/nil than for all other objects. I don't think this was
intentional.
String::Foo = "foo"
"".instance_eval("Foo") # => "foo"
Integer::Foo = "foo"
123.instance_eval("Foo") # => "foo"
TrueClass::Foo = "foo"
true.instance_eval("Foo") # NameError: uninitialized constant Foo
This also slightly changes the error message when trying to define a method
through instance_eval on an object which can't have a singleton class.
Before:
$ ruby -e '123.instance_eval { def foo; end }'
-e:1:in `block in <main>': no class/module to add method (TypeError)
After:
$ ./ruby -e '123.instance_eval { def foo; end }'
-e:1:in `block in <main>': can't define singleton (TypeError)
IMO this error is a small improvement on the original and better matches
the (both old and new) message when definging a method using `def self.`
$ ruby -e '123.instance_eval{ def self.foo; end }'
-e:1:in `block in <main>': can't define singleton (TypeError)
Co-authored-by: Matthew Draper <matthew@trebex.net>
* Remove "under" argument from yield_under
* Move CREF_SINGLETON_SET into vm_cref_new
* Simplify vm_get_const_base
* Fix leaf VM_SPECIAL_OBJECT_CONST_BASE
Co-authored-by: Matthew Draper <matthew@trebex.net>
Notes:
Merged-By: jhawthorn <john@hawthorn.email>
|
|
recommended section.
https://github.com/rubygems/rubygems/commit/de6552ac30
|
|
ObjectSpace.trace_object_allocations can crash when auto-compaction is
enabled.
Notes:
Merged: https://github.com/ruby/ruby/pull/5202
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/5203
Merged-By: XrXr
|
|
Use in_keyword_case_scope?
Return fast
https://github.com/ruby/irb/commit/8acc7f8dc7
|
|
I pushed reline#389 for when convert-meta is not turned on in .inputrc.
Alt+D in irb also needs to be set to the keycode for not using convert-meta.
https://github.com/ruby/irb/commit/328eddf851
|
|
Fix bug infinite loop when pasting multilines fo code in Ruby 2.6.
This is not reproduced in Ruby 2.7.
Changes added in https://github.com/ruby/irb/pull/242/files#diff-612b926e42ed78aed1a889ac1944f7d22229b3a489cc08f837a7f75eca3d3399R155 are also reflected in Ruby 2.6.
https://github.com/ruby/irb/commit/0a77f75bf0
|
|
Checked in the previous line.
https://github.com/ruby/reline/commit/bf774c0f2c
|
|
|
|
References are being updated correctly, so this is no longer necessary
Notes:
Merged: https://github.com/ruby/ruby/pull/5198
|
|
https://github.com/ruby/reline/commit/c07b0ace6a
|
|
fix https://github.com/ruby/reline/issues/384
If `$TERM` is `vt102`, there are no `kend`, `khome`, `civis`, or `cnorm` in capabilities.
`TerminfoError` is raised in `Reline::Terminfo.tigetstr(capname)`, so it is rescued if it does not exist.
https://github.com/ruby/reline/commit/c9f5112702
|
|
Cache downloaded external libraries/gems, which are expected not
changed so frequently.
Also sometimes downloading from zlib returns the current time as
the date header in unexpected format, and checksums mismatch at
that time.
Notes:
Merged: https://github.com/ruby/ruby/pull/5201
Merged-By: nobu <nobu@ruby-lang.org>
|
|
|
|
Alias `#inspect` as `#to_s` also in the new `Ripper::Lexer::Elem`
class, so that `puts Ripper::Lexer.new(code).scan` shows the
attributes.
|
|
https://github.com/rubygems/rubygems/commit/8fa29e5e55
|
|
0.0.0.SNAPSHOT
The default prerelease requirement in rubygems doesn't actually match
things like "0.0.0.SNAPSHOT".
https://github.com/rubygems/rubygems/commit/711498b342
|
|
Since the default requirement in rubygems is ">= 0", it was failing to
match 0 prereleases. Changing the default globally to be ">= 0.a"
instead is a major refactoring that's quite tricky to make backwards
compatible, so I'm special casing this where needed for now to fix the
regression.
https://github.com/rubygems/rubygems/commit/68fe37937c
|
|
|
|
Discussed in https://github.com/ruby/ruby/pull/5093#issuecomment-964426481.
> it would be enough to mimic only [] for almost all cases
This adds back the `Lexer::Elem#[]` and `Lexer::State#[]` and adds deprecation warnings for them.
|
|
Instead of accessing the struct as an array, access it via methods. There are other places inside of this file already using this API (for example https://github.com/ruby/ruby/blob/e0a5c3d2b71dfad038d7562fdd33f02ffd79232d/lib/irb/ruby-lex.rb#L829-L830).
This commit moves all struct array-ish calls to use their method calls instead. It is also ~1.23 faster accessing values via a method instead of as an array according to this microbenchmark:
```ruby
Elem = Struct.new(:pos, :event, :tok, :state, :message) do
def initialize(pos, event, tok, state, message = nil)
super(pos, event, tok, State.new(state), message)
end
# ...
def to_a
a = super
a.pop unless a.empty?
a
end
end
class ElemClass
attr_accessor :pos, :event, :tok, :state, :message
def initialize(pos, event, tok, state, message = nil)
@pos = pos
@event = event
@tok = tok
@state = State.new(state)
@message = message
end
def to_a
if @message
[@pos, @event, @tok, @state, @message]
else
[@pos, @event, @tok, @state]
end
end
end
# stub state class creation for now
class State; def initialize(val); end; end
```
```ruby
Benchmark.ips do |x|
x.report("struct") { struct[1] }
x.report("class ") { from_class.event }
x.compare!
end; nil
```
```
Warming up --------------------------------------
struct 1.624M i/100ms
class 1.958M i/100ms
Calculating -------------------------------------
struct 17.139M (± 2.6%) i/s - 86.077M in 5.025801s
class 21.104M (± 3.4%) i/s - 105.709M in 5.015193s
Comparison:
class : 21103826.3 i/s
struct: 17139201.5 i/s - 1.23x (± 0.00) slower
```
Notes:
Merged: https://github.com/ruby/ruby/pull/5093
|
|
The last element in the `@buf` may be either an array or an `Elem`. In the case it is an `Elem` we iterate over every element, when we do not need to. This check guards that case by ensuring that we only iterate over an array of elements.
Notes:
Merged: https://github.com/ruby/ruby/pull/5093
|
|
## Concept
I am proposing we replace the Struct implementation of data structures inside of ripper with real classes.
This will improve performance and the implementation is not meaningfully more complicated.
## Example
Struct versus class comparison:
```ruby
Elem = Struct.new(:pos, :event, :tok, :state, :message) do
def initialize(pos, event, tok, state, message = nil)
super(pos, event, tok, State.new(state), message)
end
# ...
def to_a
a = super
a.pop unless a.empty?
a
end
end
class ElemClass
attr_accessor :pos, :event, :tok, :state, :message
def initialize(pos, event, tok, state, message = nil)
@pos = pos
@event = event
@tok = tok
@state = State.new(state)
@message = message
end
def to_a
if @message
[@pos, @event, @tok, @state, @message]
else
[@pos, @event, @tok, @state]
end
end
end
# stub state class creation for now
class State; def initialize(val); end; end
```
## MicroBenchmark creation
```ruby
require 'benchmark/ips'
require 'ripper'
pos = [1, 2]
event = :on_nl
tok = "\n".freeze
state = Ripper::EXPR_BEG
Benchmark.ips do |x|
x.report("struct") { Elem.new(pos, event, tok, state) }
x.report("class ") { ElemClass.new(pos, event, tok, state) }
x.compare!
end; nil
```
Gives ~1.2x faster creation:
```
Warming up --------------------------------------
struct 263.983k i/100ms
class 303.367k i/100ms
Calculating -------------------------------------
struct 2.638M (± 5.9%) i/s - 13.199M in 5.023460s
class 3.171M (± 4.6%) i/s - 16.078M in 5.082369s
Comparison:
class : 3170690.2 i/s
struct: 2638493.5 i/s - 1.20x (± 0.00) slower
```
## MicroBenchmark `to_a` (Called by Ripper.lex for every element)
```ruby
require 'benchmark/ips'
require 'ripper'
pos = [1, 2]
event = :on_nl
tok = "\n".freeze
state = Ripper::EXPR_BEG
struct = Elem.new(pos, event, tok, state)
from_class = ElemClass.new(pos, event, tok, state)
Benchmark.ips do |x|
x.report("struct") { struct.to_a }
x.report("class ") { from_class.to_a }
x.compare!
end; nil
```
Gives 1.46x faster `to_a`:
```
Warming up --------------------------------------
struct 612.094k i/100ms
class 893.233k i/100ms
Calculating -------------------------------------
struct 6.121M (± 5.4%) i/s - 30.605M in 5.015851s
class 8.931M (± 7.9%) i/s - 44.662M in 5.039733s
Comparison:
class : 8930619.0 i/s
struct: 6121358.9 i/s - 1.46x (± 0.00) slower
```
## MicroBenchmark data access
```ruby
require 'benchmark/ips'
require 'ripper'
pos = [1, 2]
event = :on_nl
tok = "\n".freeze
state = Ripper::EXPR_BEG
struct = Elem.new(pos, event, tok, state)
from_class = ElemClass.new(pos, event, tok, state)
Benchmark.ips do |x|
x.report("struct") { struct.pos[1] }
x.report("class ") { from_class.pos[1] }
x.compare!
end; nil
```
Gives ~1.17x faster data access:
```
Warming up --------------------------------------
struct 1.694M i/100ms
class 1.868M i/100ms
Calculating -------------------------------------
struct 16.149M (± 6.8%) i/s - 81.318M in 5.060633s
class 18.886M (± 2.9%) i/s - 95.262M in 5.048359s
Comparison:
class : 18885669.6 i/s
struct: 16149255.8 i/s - 1.17x (± 0.00) slower
```
## Full benchmark integration of this inside of Ripper.lex
Inside of this repo with this commit
```
$ cd ext/ripper
$ make
$ cat test.rb
file = File.join(__dir__, "../../array.rb")
source = File.read(file)
bench = Benchmark.measure do
10_000.times.each do
Ripper.lex(source)
end
end
puts bench
```
Then execute with and without this change 50 times:
```
rm new.txt
rm old.txt
for i in {0..50}
do
`ruby -Ilib -rripper -rbenchmark ./test.rb >> new.txt`
`ruby -rripper -rbenchmark ./test.rb >> old.txt`
done
```
I used derailed benchmarks internals to compare the results:
```
dir = Pathname(".")
branch_info = {}
branch_info["old"] = { desc: "Struct lex", time: Time.now, file: dir.join("old.txt"), name: "old" }
branch_info["new"] = { desc: "Class lex", time: Time.now, file: dir.join("new.txt"), name: "new" }
stats = DerailedBenchmarks::StatsFromDir.new(branch_info)
stats.call.banner
```
Which gave us:
```
❤️ ❤️ ❤️ (Statistically Significant) ❤️ ❤️ ❤️
[new] (3.3139 seconds) "Class lex" ref: "new"
FASTER 🚀🚀🚀 by:
1.1046x [older/newer]
9.4700% [(older - newer) / older * 100]
[old] (3.6606 seconds) "Struct lex" ref: "old"
Iterations per sample:
Samples: 51
Test type: Kolmogorov Smirnov
Confidence level: 99.0 %
Is significant? (max > critical): true
D critical: 0.30049534876137013
D max: 0.9607843137254902
Histograms (time ranges are in seconds):
[new] description: [old] description:
"Class lex" "Struct lex"
┌ ┐ ┌ ┐
[3.0, 3.3) ┤▇ 1 [3.0, 3.3) ┤ 0
[3.3, 3.6) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 47 [3.3, 3.6) ┤ 0
[3.5, 3.8) ┤▇▇ 2 [3.5, 3.8) ┤▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇▇ 46
[3.8, 4.1) ┤▇ 1 [3.8, 4.1) ┤▇▇▇ 4
[4.0, 4.3) ┤ 0 [4.0, 4.3) ┤ 0
[4.3, 4.6) ┤ 0 [4.3, 4.6) ┤▇ 1
└ ┘ └ ┘
# of runs in range # of runs in range
```
To sum this up, the "new" version of this code (using real classes instead of structs) is 10% faster across 50 runs with a statistical significance confidence level of 99%. Histograms are for visual checksum.
Notes:
Merged: https://github.com/ruby/ruby/pull/5093
|
|
suseconds_t, which is the type of tv_usec, may be defined with a longer
size type than tv_nsec's type (long). So usec to nsec conversion needs
an explicit casting.
Notes:
Merged: https://github.com/ruby/ruby/pull/5200
|
|
|
|
The methods aren't called for FIXNUM, and it's best to have
consistent behavior.
Fixes [Bug #18377]
Notes:
Merged: https://github.com/ruby/ruby/pull/5199
|
|
|
|
The main impetus for this change is to fix [Bug #13392]. Previously, we
fired the "return" TracePoint event after popping the stack frame for
the block running as method (BMETHOD). This gave undesirable source
location outputs as the return event normally fires right before the
frame going away.
The iseq for each block can run both as a block and as a method. To
accommodate that, this commit makes vm_trace() fire call/return events for
instructions that have b_call/b_return events attached when the iseq is
running as a BMETHOD. The logic for rewriting to "trace_*" instruction
is tweaked so that when the user listens to call/return events,
instructions with b_call/b_return become trace variants.
To continue to provide the return value for non-local returns done using
the "return" or "break" keyword inside BMETHODs, the stack unwinding
code is tweaked. b_return events now provide the same return value as
return events for these non-local cases. A pre-existing test deemed not
providing a return value for these b_return events as a limitation.
This commit removes the checks for call/return TracePoint events that
happen when calling into BMETHODs when no TracePoints are active.
Technically, migrating just the return event is enough to fix the bug,
but migrating both call and return removes our reliance on
`VM_FRAME_FLAG_FINISH` and re-entering the interpreter when the caller
is already in the interpreter.
Notes:
Merged: https://github.com/ruby/ruby/pull/4637
|
|
This reverts commit 119626da947bf6492ef7a27abf3bf12de5d0d95a.
|
|
If YJIT isn't enabled, or hasn't finished booting, cb / ocb could be
null. This commit just checks to make sure they're available before
marking as executable
Co-Authored-By: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@shopify.com>
Co-Authored-By: Kevin Newton <kddnewton@gmail.com>
Notes:
Merged: https://github.com/ruby/ruby/pull/5032
|
|
Some platforms don't want memory to be marked as writeable and
executable at the same time. When we write to the code block, we
calculate the OS page that the buffer position maps to. Then we call
`mprotect` to allow writes on that particular page. As an optimization,
we cache the "last written" aligned page which allows us to amortize the
cost of the `mprotect` call. In other words, sequential writes to the
same page will only call `mprotect` on the page once.
When we're done writing, we call `mprotect` on the entire JIT buffer.
This means we don't need to keep track of which pages were marked as
writeable, we let the OS take care of that.
Co-authored-by: John Hawthorn <john@hawthorn.email>
Notes:
Merged: https://github.com/ruby/ruby/pull/5032
|
|
It seems that since ruby openssl 2.1.0 [[1]], the distinguished name
submitted to `OpenSSL::X509::Name.parse` is not correctly parsed if it
does not contain the first slash:
~~~
$ ruby -v
ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x86_64-linux]
$ gem list | grep openssl
openssl (default: 2.2.0)
$ irb -r openssl
irb(main):001:0> OpenSSL::X509::Name.parse("CN=nobody/DC=example").to_s(OpenSSL::X509::Name::ONELINE)
=> "CN = nobody/DC=example"
irb(main):002:0> OpenSSL::X509::Name.parse("/CN=nobody/DC=example").to_s(OpenSSL::X509::Name::ONELINE)
=> "CN = nobody, DC = example"
~~~
Instead, use `OpenSSL::X509::Name.new` directly as suggested by upstream
maintainer.
[1]: https://github.com/ruby/openssl/commit/19c67cd10c57f3ab7b13966c36431ebc3fdd653b
https://github.com/rubygems/rubygems/commit/09ca0c2dae
Co-authored-by: Kazuki Yamaguchi <k@rhe.jp>
|
|
|
|
Previously, YJIT crashes with rb_bug() when asked to compile new methods
while out of executable memory.
To handle this situation gracefully, this change keeps track of all the
blocks compiled each invocation in case YJIT runs out of memory in the
middle of a compliation sequence. The list is used to free all blocks in
case compilation fails.
yjit_gen_block() is renamed to gen_single_block() to make it distinct from
gen_block_version(). Call to limit_block_version() and block_t
allocation is moved into the function to help tidy error checking in the
outer loop.
limit_block_version() now returns by value. I feel that an out parameter
with conditional mutation is unnecessarily hard to read in code that
does not need to go for last drop performance. There is a good chance
that the optimizer is able to output identical code anyways.
Notes:
Merged: https://github.com/ruby/ruby/pull/5191
|
|
Notes:
Merged: https://github.com/ruby/ruby/pull/5196
|
|
On Windows, as the input from console is encoded in the active
code page, convert the input to the internal encoding.
Notes:
Merged: https://github.com/ruby/ruby/pull/5196
|
|
|
|
|