This is designed to replace the newarraykwsplat instruction, which is
no longer used in the parse.y compiler after this commit. This avoids
an unnecessary array allocation in the case where ARGSCAT is followed
by LIST with keyword:
```ruby
a = []
kw = {}
[*a, 1, **kw]
```
Previous Instructions:
```
0000 newarray 0 ( 1)[Li]
0002 setlocal_WC_0 a@0
0004 newhash 0 ( 2)[Li]
0006 setlocal_WC_0 kw@1
0008 getlocal_WC_0 a@0 ( 3)[Li]
0010 splatarray true
0012 putobject_INT2FIX_1_
0013 putspecialobject 1
0015 newhash 0
0017 getlocal_WC_0 kw@1
0019 opt_send_without_block <calldata!mid:core#hash_merge_kwd, argc:2, ARGS_SIMPLE>
0021 newarraykwsplat 2
0023 concattoarray
0024 leave
```
New Instructions:
```
0000 newarray 0 ( 1)[Li]
0002 setlocal_WC_0 a@0
0004 newhash 0 ( 2)[Li]
0006 setlocal_WC_0 kw@1
0008 getlocal_WC_0 a@0 ( 3)[Li]
0010 splatarray true
0012 putobject_INT2FIX_1_
0013 pushtoarray 1
0015 putspecialobject 1
0017 newhash 0
0019 getlocal_WC_0 kw@1
0021 opt_send_without_block <calldata!mid:core#hash_merge_kwd, argc:2, ARGS_SIMPLE>
0023 pushtoarraykwsplat
0024 leave
```
pushtoarraykwsplat is designed to be simpler than newarraykwsplat.
It does not take a variable number of arguments from the stack, it
pops the top of the stack, and appends it to the second from the top,
unless the top of the stack is an empty hash.
During this work, I found the ARGSPUSH followed by HASH with keyword
did not compile correctly, as it pushed the generated hash to the
array even if the hash was empty. This fixes the behavior, to use
pushtoarraykwsplat instead of pushtoarray in that case:
```ruby
a = []
kw = {}
[*a, **kw]
[{}] # Before
[] # After
```
This does not remove the newarraykwsplat instruction, as it is still
referenced in the prism compiler (which should be updated similar
to this), YJIT (only in the bindings, it does not appear to be
implemented), and RJIT (in a couple comments). After those are
updated, the newarraykwsplat instruction should be removed.
This commit introduces a new instruction `opt_newarray_send` which is
used when there is an array literal followed by either the `hash`,
`min`, or `max` method.
```
[a, b, c].hash
```
Will emit an `opt_newarray_send` instruction. This instruction falls
back to a method call if the "interested" method has been monkey
patched.
Here are some examples of the instructions generated:
```
$ ./miniruby --dump=insns -e '[@a, @b].max'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,12)> (catch: FALSE)
0000 getinstancevariable :@a, <is:0> ( 1)[Li]
0003 getinstancevariable :@b, <is:1>
0006 opt_newarray_send 2, :max
0009 leave
$ ./miniruby --dump=insns -e '[@a, @b].min'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,12)> (catch: FALSE)
0000 getinstancevariable :@a, <is:0> ( 1)[Li]
0003 getinstancevariable :@b, <is:1>
0006 opt_newarray_send 2, :min
0009 leave
$ ./miniruby --dump=insns -e '[@a, @b].hash'
== disasm: #<ISeq:<main>@-e:1 (1,0)-(1,13)> (catch: FALSE)
0000 getinstancevariable :@a, <is:0> ( 1)[Li]
0003 getinstancevariable :@b, <is:1>
0006 opt_newarray_send 2, :hash
0009 leave
```
[Feature #18897] [ruby-core:109147]
Co-authored-by: John Hawthorn <jhawthorn@github.com>
This changes the following warnings:
* warning: class variable access from toplevel
* warning: class variable @foo of D is overtaken by C
into RuntimeErrors. Handle defined?(@@foo) at toplevel
by returning nil instead of raising an exception (the previous
behavior warned before returning nil when defined? was used).
Refactor the specs to avoid the warnings even in older versions.
The specs were checking for the warnings, but the purpose of
the related specs as evidenced from their description is to
test for behavior, not for warnings.
Fixes [Bug #14541]
This typo introduced memory corruption when __builtin_add_overflow
is not available but uint128_t is. GCC before 5 are one of such
situatins.
See also 20191009T120004Z.log.html.gz
In addition to detect dead canary, we try to detect the very moment
when we smash the stack top. Requested by k0kubun:
https://twitter.com/k0kubun/status/1085180749899194368
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66981 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
* template/limits.c.tmpl (Init_limits): rename RbConfig::Limits as
RbConfig::LIMITS, constants other than class or module are all
uppercase with underscores by convention.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58260 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
The same optimization used for "literal string".freeze
can easily apply to uminus without introducing any
compatibility problems.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57828 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Because our tests now have several places where FIXNUM_MAX is needed,
we decided to provide it along with several other constants.
* template/limits.c.tmpl: new file, defining RbConfig::Limits
* ext/rbconfig/sizeof/depend (limits.c): rule to generate limits.c
* test/-ext-/num2int/test_num2int.rb: use RbConfig::Limits
* bootstraptest/test_insns.rb: ditto.
* .gitignore: ignore new generated file.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57465 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
While I was developing my private topic branch I found that the VM
itself is not tested very much in `make test` tests. Of course
`make test-all` covers vast majority of the VM but running that task
is not an immediately possible thing when we are touching the VM. In
order to boost development in a rapid cycle I decided to add some
tests to the bootstraptest. Here it is.
* test_insns.rb: new test that covers insns.def.
* runner.rb (#assert_equal): pass extra options to the target
so that we can test frozen_string_literal: true situation.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57399 b2dd03c8-39d4-4d8f-98ff-823fe69b080e