z, ? | toggle help (this) |
space, → | next slide |
shift-space, ← | previous slide |
d | toggle debug mode |
## <ret> | go to slide # |
r | reload slides |
n | toggle notes |
meth(*a, **kw, &block)
meth(*a, **kw, &block)
# Ruby 3.3-dev: 1 arrays, 0 hashes
meth(*a, **kw, &block)
# Ruby 3.3-dev: 0 arrays, 0 hashes
meth(*a, **kw, &block)
# Ruby 3.3-dev: 0 arrays, 0 hashes
meth(*a, **kw, &block)
# block.to proc before kw.to_hash
# Ruby 3.3-dev: 0 arrays, 0 hashes
meth(*a, **kw, &block)
# kw.to_hash before block.to proc
# Ruby 3.3-dev: 0 arrays, 0 hashes
meth(*a, **kw, &block)
# kw.to_hash before block.to proc
# Ruby 3.3: 1 array, 0 hashes
meth(*a, **kw, &block)
# kw.to_hash before block.to proc
# Ruby 3.3: 1 arrays, 0 hashes
# Ruby 3.4: 0 arrays, 0 hashes
def foo(a:) = a
hash = {a: 10}
foo(**hash)
def foo(a:) = a
hash = {a: 10}
foo(**hash)
def foo(a:) = a
hash = {a: 10}
foo(**hash)
def foo(a:) = a
hash = {a: 10}
foo(**hash)
# Ruby 3.2: 0 arrays, 0 hashes
def foo(a:) = a
hash = {a: 10}
foo(**hash)
# Ruby 3.2: 0 arrays, 0 hashes
# Ruby 3.3: 0 arrays, 1 hashes
def foo(a:) = a
hash = {a: 10}
foo(**hash)
# Ruby 3.2: 0 arrays, 0 hashes
# Ruby 3.3: 0 arrays, 1 hashes
# Ruby 3.4: 0 arrays, 0 hashes
def foo(a:) = a
array = []
foo(*a, a: 1)
def foo(a:) = a
array = []
foo(*a, a: 1)
def foo(a:) = a
array = []
foo(*a, a: 1)
def foo(a:) = a
array = []
foo(*a, a: 1)
# Ruby 3.3: 0 arrays, 1 hashes
def foo(a:) = a
array = []
foo(*a, a: 1)
# Ruby 3.3: 0 arrays, 1 hashes
# Ruby 3.4-dev: 1 arrays, 1 hashes
def foo(a:) = a
array = []
foo(*a, a: 1)
# Ruby 3.3: 0 arrays, 1 hashes
# Ruby 3.4-dev: 0 arrays, 1 hashes
def foo(a:) = a
array = []
foo(*a, a: 1)
# Ruby 3.3: 0 arrays, 1 hashes
# Ruby 3.4: 0 arrays, 0 hashes
def required(x); end
def required(x); end
check_allocations(0, 0, "required(1)")
def required(x); end
check_allocations(0, 0, "required(1)")
def required(x); end
check_allocations(0, 0, "required(1)")
def required(x); end
check_allocations(0, 0, "required(1)")
def required(x); end
check_allocations(0, 0, "required(1)")
def required(x); end
check_allocations(0, 0, "required(1)")
check_allocations(0, 1, "required(**hash")
[]
# 1 array
[]
# 1 array
newarray 0
[1]
# 1 array
[1]
# 1 array
duparray [1]
[1, 2, ..., 1_000_000]
# 1 array
[1, 2, ..., 1_000_000]
# 1 array
duparray [1, 2, ..., 1_000_000]
v = 1
[v]
# 1 array
v = 1
[v]
# 1 array
getlocal_WC_0 v@0
newarray 1
v = 1
[v]
# 1 array
getlocal_WC_0 v@0
newarray 1
v = 1
[v]
# 1 array
getlocal_WC_0 v@0
newarray 1
v = 1
[v, v, ..., v] # 257 times
v = 1
[v, v, ..., v] # 257 times
# 3 arrays
v = 1
[v, v, ..., v] # 257 times
# 3 arrays
getlocal_WC_0 v@0
getlocal_WC_0 v@0
# 253 more times
getlocal_WC_0 v@0
newarray 256
getlocal_WC_0 v@0
newarray 1
concatarray
v = 1
[v, v, ..., v] # 257 times
# 3 arrays
getlocal_WC_0 v@0
getlocal_WC_0 v@0
# 253 more times
getlocal_WC_0 v@0
newarray 256
getlocal_WC_0 v@0
newarray 1
concatarray
v = 1
[v, v, ..., v] # 257 times
# 3 arrays
getlocal_WC_0 v@0
getlocal_WC_0 v@0
# 253 more times
getlocal_WC_0 v@0
newarray 256
getlocal_WC_0 v@0
newarray 1
concatarray
v = 1
[v, v, ..., v] # 257 times
# 3 arrays
getlocal_WC_0 v@0
getlocal_WC_0 v@0
# 253 more times
getlocal_WC_0 v@0
newarray 256
getlocal_WC_0 v@0
newarray 1
concatarray
v = 1
[v, v, ..., v] # 257 times
# 3 arrays
getlocal_WC_0 v@0
getlocal_WC_0 v@0
# 253 more times
getlocal_WC_0 v@0
newarray 256
getlocal_WC_0 v@0
newarray 1
concatarray
v = 1
[v, v, ..., v] # 257 times
# 3 arrays
getlocal_WC_0 v@0
getlocal_WC_0 v@0
# 253 more times
getlocal_WC_0 v@0
newarray 256
getlocal_WC_0 v@0
newarray 1
concatarray
v = 1
[v, v, ..., v] # 257 times
# 3 arrays
getlocal_WC_0 v@0
getlocal_WC_0 v@0
# 253 more times
getlocal_WC_0 v@0
newarray 256
getlocal_WC_0 v@0
newarray 1
concatarray
v = 1
[v, v, ..., v] # 257 times
# 3 arrays
getlocal_WC_0 v@0
getlocal_WC_0 v@0
# 253 more times
getlocal_WC_0 v@0
newarray 256
getlocal_WC_0 v@0
newarray 1
concatarray
v = 1
[v, v, ..., v] # 257 times
# 3 arrays
getlocal_WC_0 v@0
getlocal_WC_0 v@0
# 253 more times
getlocal_WC_0 v@0
newarray 256
getlocal_WC_0 v@0
newarray 1
concatarray
v = 1
[v, v, ..., v] # 257 times
# 3 arrays
getlocal_WC_0 v@0
getlocal_WC_0 v@0
# 253 more times
getlocal_WC_0 v@0
newarray 256
getlocal_WC_0 v@0
pushtoarray 1
v = 1
[v, v, ..., v] # 257 times
# 1 array
getlocal_WC_0 v@0
getlocal_WC_0 v@0
# 253 more times
getlocal_WC_0 v@0
newarray 256
getlocal_WC_0 v@0
pushtoarray 1
v = []
[v, *v, v]
v = []
[v, *v, v]
# 4 arrays
v = []
[v, *v, v]
# 4 arrays
getlocal_WC_0 v@0
newarray 1
getlocal_WC_0 v@0
concatarray
getlocal_WC_0 v@0
newarray 1
concatarray
v = []
[v, *v, v]
# 4 arrays
getlocal_WC_0 v@0
newarray 1
getlocal_WC_0 v@0
concatarray
getlocal_WC_0 v@0
newarray 1
concatarray
v = []
[v, *v, v]
# 4 arrays
getlocal_WC_0 v@0
newarray 1
getlocal_WC_0 v@0
concatarray
getlocal_WC_0 v@0
pushtoarray 1
v = []
[v, *v, v]
# 4 arrays
getlocal_WC_0 v@0
newarray 1
getlocal_WC_0 v@0
concatarray
getlocal_WC_0 v@0
pushtoarray 1
v = []
[v, *v, v]
# 4 arrays
getlocal_WC_0 v@0
newarray 1
getlocal_WC_0 v@0
concatarray
getlocal_WC_0 v@0
pushtoarray 1
v = []
[v, *v, v]
# 4 arrays
getlocal_WC_0 v@0
newarray 1
getlocal_WC_0 v@0
concattoarray
getlocal_WC_0 v@0
pushtoarray 1
v = []
[v, *v, v]
# 4 arrays
getlocal_WC_0 v@0
newarray 1
getlocal_WC_0 v@0
concattoarray
getlocal_WC_0 v@0
pushtoarray 1
v = []
[v, *v, v]
# 1 array
getlocal_WC_0 v@0
newarray 1
getlocal_WC_0 v@0
concattoarray
getlocal_WC_0 v@0
pushtoarray 1
v = []
h = {kw: 1}
[*v, **h]
v = []
h = {kw: 1}
[*v, **h]
# 3 arrays
v = []
h = {kw: 1}
[*v, **h]
# 3 arrays
getlocal_WC_0 v@0
splatarray true
putspecialobject 1
newhash 0
getlocal_WC_0 h@1
send #hash_merge_kwd, argc:2
newarraykwsplat 1
concatarray
v = []
h = {kw: 1}
[*v, **h]
# 3 arrays
getlocal_WC_0 v@0
splatarray true
putspecialobject 1
newhash 0
getlocal_WC_0 h@1
send #hash_merge_kwd, argc:2
newarraykwsplat 1
concatarray
v = []
h = {kw: 1}
[*v, **h]
# 3 arrays
getlocal_WC_0 v@0
splatarray true
putspecialobject 1
newhash 0
getlocal_WC_0 h@1
send #hash_merge_kwd, argc:2
newarraykwsplat 1
concatarray
v = []
h = {kw: 1}
[*v, **h]
# 3 arrays
getlocal_WC_0 v@0
splatarray true
putspecialobject 1
newhash 0
getlocal_WC_0 h@1
send #hash_merge_kwd, argc:2
newarraykwsplat 1
concatarray
v = []
h = {kw: 1}
[*v, **h]
# 3 arrays
getlocal_WC_0 v@0
splatarray true
putspecialobject 1
newhash 0
getlocal_WC_0 h@1
send #hash_merge_kwd, argc:2
newarraykwsplat 1
concatarray
v = []
h = {kw: 1}
[*v, **h]
# 3 arrays
getlocal_WC_0 v@0
splatarray true
putspecialobject 1
newhash 0
getlocal_WC_0 h@1
send #hash_merge_kwd, argc:2
newarraykwsplat 1
concatarray
v = []
h = {kw: 1}
[*v, **h]
# 3 arrays
getlocal_WC_0 v@0
splatarray true
putspecialobject 1
newhash 0
getlocal_WC_0 h@1
send #hash_merge_kwd, argc:2
newarraykwsplat 1
concattoarray
v = []
h = {kw: 1}
[*v, **h]
# 3 arrays
getlocal_WC_0 v@0
splatarray true
putspecialobject 1
newhash 0
getlocal_WC_0 h@1
send #hash_merge_kwd, argc:2
newarraykwsplat 1
concattoarray
v = []
h = {kw: 1}
[*v, **h]
# 3 arrays
getlocal_WC_0 v@0
splatarray true
putspecialobject 1
newhash 0
getlocal_WC_0 h@1
send #hash_merge_kwd, argc:2
pushtoarray 1
v = []
h = {kw: 1}
[*v, **h]
# 3 arrays
getlocal_WC_0 v@0
splatarray true
putspecialobject 1
newhash 0
getlocal_WC_0 h@1
send #hash_merge_kwd, argc:2
pushtoarraykwsplat
v = []
h = {kw: 1}
[*v, **h]
# 1 array
getlocal_WC_0 v@0
splatarray true
putspecialobject 1
newhash 0
getlocal_WC_0 h@1
send #hash_merge_kwd, argc:2
pushtoarraykwsplat
v = []
h = {}
[*v, **h]
v = []
h = {}
[*v, **h]
v = []
h = {}
[*v, **h]
v = []
h = {}
[*v, **h]
# => [{}]
v = []
h = {}
[*v, **h]
# => []
# No Array Allocated
a(1, *ary)
a(1, *ary, &block)
a(*ary, **kw)
a(*ary, **kw, &block)
a(*ary, kw: 1)
a(*ary, kw: 1, &block)
# No Array Allocated
a(1, *ary)
a(1, *ary, &block)
a(*ary, **kw)
a(*ary, **kw, &block)
a(*ary, kw: 1)
a(*ary, kw: 1, &block)
# Array Allocated
a(*ary, **kw, **kw)
a(*ary, **kw, **kw, &block)
a(*ary, kw: 1, **kw)
a(*ary, kw: 1, **kw, &block)
a(*ary, kw: lvar)
a(*ary, kw: lvar, &block)
a(*ary, kw: @ivar)
a(*ary, kw: @ivar, &block)
a(1, *ary, **kw, **kw)
a(1, *ary, **kw, **kw, &block)
a(1, *ary, kw: 1, **kw)
a(1, *ary, kw: 1, **kw, &block)
static int
setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
int dup_rest, unsigned int *flag_ptr,
struct rb_callinfo_kwarg **kwarg_ptr)
static int
setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
int dup_rest, unsigned int *flag_ptr,
struct rb_callinfo_kwarg **kwarg_ptr)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_SPLAT_MUT;
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, 1, NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
m(*ary, {kw: 1})
m(*ary, kw: 1)
m(*ary, **kw)
m(*ary, kw: 1, **kw)
m(*ary, **kw, **kw)
# No Array Allocated
a(1, *ary)
a(1, *ary, &block)
a(*ary, **kw)
a(*ary, **kw, &block)
a(*ary, kw: 1)
a(*ary, kw: 1, &block)
# No Array Allocated
a(*ary, **kw, **kw)
a(*ary, **kw, **kw, &block)
a(*ary, kw: 1, **kw)
a(*ary, kw: 1, **kw, &block)
a(*ary, kw: lvar)
a(*ary, kw: lvar, &block)
a(*ary, kw: @ivar)
a(*ary, kw: @ivar, &block)
# Array Allocated
a(1, *ary, **kw, **kw)
a(1, *ary, **kw, **kw, &block)
a(1, *ary, kw: 1, **kw)
a(1, *ary, kw: 1, **kw, &block)
# No Array Allocated
a(1, *ary)
a(1, *ary, &block)
a(*ary, **kw)
a(*ary, **kw, &block)
a(*ary, kw: 1)
a(*ary, kw: 1, &block)
# No Array Allocated
a(*ary, **kw, **kw)
a(*ary, **kw, **kw, &block)
a(*ary, kw: 1, **kw)
a(*ary, kw: 1, **kw, &block)
a(*ary, kw: lvar)
a(*ary, kw: lvar, &block)
a(*ary, kw: @ivar)
a(*ary, kw: @ivar, &block)
# Array Allocated
a(1, *ary, **kw, **kw)
a(1, *ary, **kw, **kw, &block)
a(1, *ary, kw: 1, **kw)
a(1, *ary, kw: 1, **kw, &block)
# No Array Allocated
a(1, *ary)
a(1, *ary, &block)
a(*ary, **kw)
a(*ary, **kw, &block)
a(*ary, kw: 1)
a(*ary, kw: 1, &block)
# No Array Allocated
a(*ary, **kw, **kw)
a(*ary, **kw, **kw, &block)
a(*ary, kw: 1, **kw)
a(*ary, kw: 1, **kw, &block)
a(*ary, kw: lvar)
a(*ary, kw: lvar, &block)
a(*ary, kw: @ivar)
a(*ary, kw: @ivar, &block)
# Array Allocated
a(1, *ary, **kw, **kw)
a(1, *ary, **kw, **kw, &block)
a(1, *ary, kw: 1, **kw)
a(1, *ary, kw: 1, **kw, &block)
a(*ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
a(*ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
a(*ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
a(*ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, *ary)
# NODE_FCALL
# NODE_ARGSCAT
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_LVAR
a(*ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, *ary)
# NODE_FCALL
# NODE_ARGSCAT
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_LVAR
a(*ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, *ary)
# NODE_FCALL
# NODE_ARGSCAT
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_LVAR
a(*ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw, **kw)
# NODE_FCALL
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, *ary)
# NODE_FCALL
# NODE_ARGSCAT
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_LVAR
static int
setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
int dup_rest, unsigned int *flag_ptr,
struct rb_callinfo_kwarg **kwarg_ptr)
static int
setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
int dup_rest, unsigned int *flag_ptr,
struct rb_callinfo_kwarg **kwarg_ptr)
static int
setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn,
unsigned int* dup_rest, unsigned int *flag_ptr,
struct rb_callinfo_kwarg **kwarg_ptr)
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int recurse_dup_rest = 1;
if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_head, NODE_SPLAT) &&
nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(argn)->nd_body)->nd_brace) {
recurse_dup_rest = 0;
}
else if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, recurse_dup_rest,
NULL, NULL);
case NODE_ARGSPUSH: {
if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT;
int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, dup_rest,
NULL, NULL);
case NODE_SPLAT: {
// f(*a)
NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head));
ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest));
if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT;
if (dup_rest) *flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
case NODE_SPLAT: {
// f(*a)
NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head));
ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest));
if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT;
if (dup_rest) *flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
case NODE_SPLAT: {
// f(*a)
NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head));
ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest));
if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT;
if (dup_rest) *flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
case NODE_SPLAT: {
// f(*a)
NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head));
ADD_INSN1(args, argn, splatarray, RBOOL(*dup_rest));
if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT;
if (dup_rest) *flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
case NODE_SPLAT: {
// f(*a)
NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head));
ADD_INSN1(args, argn, splatarray, RBOOL(*dup_rest));
if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT;
if (dup_rest) *flag_ptr |= VM_CALL_ARGS_SPLAT_MUT;
}
case NODE_SPLAT: {
// f(*a)
NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head));
ADD_INSN1(args, argn, splatarray, RBOOL(*dup_rest));
if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT;
}
case NODE_SPLAT: {
// f(*a)
NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head));
ADD_INSN1(args, argn, splatarray, RBOOL(*dup_rest));
if (*dup_rest) *dup_rest = 0;
if (flag_ptr) {
*flag_ptr |= VM_CALL_ARGS_SPLAT;
}
unsigned int dup_rest = 1;
if (should_not_allocate) {
dup_rest = 0;
}
setup_args_core(iseq, args, argn, &dup_rest, flag, keywords)
unsigned int dup_rest = 1;
if (should_not_allocate) {
dup_rest = 0;
}
setup_args_core(iseq, args, argn, &dup_rest, flag, keywords)
unsigned int dup_rest = 1;
if (should_not_allocate) {
dup_rest = 0;
}
setup_args_core(iseq, args, argn, &dup_rest, flag, keywords)
unsigned int dup_rest = 1;
if (should_not_allocate) {
dup_rest = 0;
}
setup_args_core(iseq, args, argn, &dup_rest, flag, keywords)
unsigned int dup_rest = 1;
if (should_not_allocate) {
dup_rest = 0;
}
setup_args_core(iseq, args, argn, &dup_rest, flag, keywords)
a(*ary)
a(*ary)
# NODE_SPLAT
# NODE_LVAR
a(*ary)
# NODE_SPLAT
# NODE_LVAR
case(NODE_SPLAT):
// avoid caller side array allocation for f(*arg)
dup_rest = 0;
break;
a(1, *ary)
a(1, *ary)
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
a(1, *ary)
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
case(NODE_ARGSCAT):
// avoid caller side array allocation for f(1, *arg)
dup_rest = !nd_type_p(RNODE_ARGSCAT(check_arg)->nd_head, NODE_LIST);
break;
a(1, *ary)
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
case(NODE_ARGSCAT):
// avoid caller side array allocation for f(1, *arg)
dup_rest = !nd_type_p(RNODE_ARGSCAT(check_arg)->nd_head, NODE_LIST);
break;
a(*ary, **kw)
a(*ary, **kw)
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(*ary, **kw)
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw)
a(*ary, **kw)
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw)
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
a(*ary, **kw)
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw)
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
case(NODE_ARGSPUSH):
// avoid caller side array allocation for f(*arg, **hash) and f(1, *arg, **hash)
dup_rest = !((nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_SPLAT) ||
(nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_ARGSCAT) &&
nd_type_p(RNODE_ARGSCAT(RNODE_ARGSPUSH(check_arg)->nd_head)->nd_head, NODE_LIST))) &&
nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_brace);
a(*ary, **kw)
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw)
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
case(NODE_ARGSPUSH):
// avoid caller side array allocation for f(*arg, **hash) and f(1, *arg, **hash)
dup_rest = !((nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_SPLAT) ||
(nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_ARGSCAT) &&
nd_type_p(RNODE_ARGSCAT(RNODE_ARGSPUSH(check_arg)->nd_head)->nd_head, NODE_LIST))) &&
nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_brace);
a(*ary, **kw)
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw)
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
case(NODE_ARGSPUSH):
// avoid caller side array allocation for f(*arg, **hash) and f(1, *arg, **hash)
dup_rest = !((nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_SPLAT) ||
(nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_ARGSCAT) &&
nd_type_p(RNODE_ARGSCAT(RNODE_ARGSPUSH(check_arg)->nd_head)->nd_head, NODE_LIST))) &&
nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_brace);
a(*ary, **kw)
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw)
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
case(NODE_ARGSPUSH):
// avoid caller side array allocation for f(*arg, **hash) and f(1, *arg, **hash)
dup_rest = !((nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_SPLAT) ||
(nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_ARGSCAT) &&
nd_type_p(RNODE_ARGSCAT(RNODE_ARGSPUSH(check_arg)->nd_head)->nd_head, NODE_LIST))) &&
nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_brace);
a(*ary, **kw)
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw)
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
case(NODE_ARGSPUSH):
// avoid caller side array allocation for f(*arg, **hash) and f(1, *arg, **hash)
dup_rest = !((nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_SPLAT) ||
(nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_ARGSCAT) &&
nd_type_p(RNODE_ARGSCAT(RNODE_ARGSPUSH(check_arg)->nd_head)->nd_head, NODE_LIST))) &&
nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_brace);
a(*ary, **kw)
# NODE_ARGSPUSH
# NODE_SPLAT
# NODE_LVAR
# NODE_HASH (keyword argument)
a(1, *ary, **kw)
# NODE_ARGSPUSH
# NODE_ARGSCAT
# NODE_LIST
# NODE_LIT: 1
# NODE_LVAR
# NODE_HASH (keyword argument)
case(NODE_ARGSPUSH):
// avoid caller side array allocation for f(*arg, **hash) and f(1, *arg, **hash)
dup_rest = !((nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_SPLAT) ||
(nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_ARGSCAT) &&
nd_type_p(RNODE_ARGSCAT(RNODE_ARGSPUSH(check_arg)->nd_head)->nd_head, NODE_LIST))) &&
nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_body, NODE_HASH) &&
!RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_brace);
static bool
setup_args_dup_rest_p(const NODE *argn)
{
switch(nd_type(argn)) {
case NODE_LVAR:
case NODE_DVAR:
case NODE_GVAR:
case NODE_IVAR:
case NODE_CVAR:
case NODE_CONST:
case NODE_COLON3:
case NODE_INTEGER:
case NODE_FLOAT:
case NODE_RATIONAL:
case NODE_IMAGINARY:
case NODE_STR:
case NODE_SYM:
case NODE_REGX:
case NODE_SELF:
case NODE_NIL:
case NODE_TRUE:
case NODE_FALSE:
case NODE_LAMBDA:
case NODE_NTH_REF:
case NODE_BACK_REF:
return false;
case NODE_COLON2:
return setup_args_dup_rest_p(RNODE_COLON2(argn)->nd_head);
default:
return true;
}
}
static bool
setup_args_dup_rest_p(const NODE *argn)
{
switch(nd_type(argn)) {
case NODE_LVAR:
case NODE_DVAR:
case NODE_GVAR:
case NODE_IVAR:
case NODE_CVAR:
case NODE_CONST:
case NODE_COLON3:
case NODE_INTEGER:
case NODE_FLOAT:
case NODE_RATIONAL:
case NODE_IMAGINARY:
case NODE_STR:
case NODE_SYM:
case NODE_REGX:
case NODE_SELF:
case NODE_NIL:
case NODE_TRUE:
case NODE_FALSE:
case NODE_LAMBDA:
case NODE_NTH_REF:
case NODE_BACK_REF:
return false;
case NODE_COLON2:
return setup_args_dup_rest_p(RNODE_COLON2(argn)->nd_head);
default:
return true;
}
}
static bool
setup_args_dup_rest_p(const NODE *argn)
{
switch(nd_type(argn)) {
case NODE_LVAR:
case NODE_DVAR:
case NODE_GVAR:
case NODE_IVAR:
case NODE_CVAR:
case NODE_CONST:
case NODE_COLON3:
case NODE_INTEGER:
case NODE_FLOAT:
case NODE_RATIONAL:
case NODE_IMAGINARY:
case NODE_STR:
case NODE_SYM:
case NODE_REGX:
case NODE_SELF:
case NODE_NIL:
case NODE_TRUE:
case NODE_FALSE:
case NODE_LAMBDA:
case NODE_NTH_REF:
case NODE_BACK_REF:
return false;
case NODE_COLON2:
return setup_args_dup_rest_p(RNODE_COLON2(argn)->nd_head);
default:
return true;
}
}
static bool
setup_args_dup_rest_p(const NODE *argn)
{
switch(nd_type(argn)) {
case NODE_LVAR:
case NODE_DVAR:
case NODE_GVAR:
case NODE_IVAR:
case NODE_CVAR:
case NODE_CONST:
case NODE_COLON3:
case NODE_INTEGER:
case NODE_FLOAT:
case NODE_RATIONAL:
case NODE_IMAGINARY:
case NODE_STR:
case NODE_SYM:
case NODE_REGX:
case NODE_SELF:
case NODE_NIL:
case NODE_TRUE:
case NODE_FALSE:
case NODE_LAMBDA:
case NODE_NTH_REF:
case NODE_BACK_REF:
return false;
case NODE_COLON2:
return setup_args_dup_rest_p(RNODE_COLON2(argn)->nd_head);
default:
return true;
}
}
static bool
setup_args_dup_rest_p(const NODE *argn)
{
switch(nd_type(argn)) {
case NODE_LVAR:
case NODE_DVAR:
case NODE_GVAR:
case NODE_IVAR:
case NODE_CVAR:
case NODE_CONST:
case NODE_COLON3:
case NODE_INTEGER:
case NODE_FLOAT:
case NODE_RATIONAL:
case NODE_IMAGINARY:
case NODE_STR:
case NODE_SYM:
case NODE_REGX:
case NODE_SELF:
case NODE_NIL:
case NODE_TRUE:
case NODE_FALSE:
case NODE_LAMBDA:
case NODE_NTH_REF:
case NODE_BACK_REF:
return false;
case NODE_COLON2:
return setup_args_dup_rest_p(RNODE_COLON2(argn)->nd_head);
default:
return true;
}
}
static bool
setup_args_dup_rest_p(const NODE *argn)
{
switch(nd_type(argn)) {
case NODE_LVAR:
case NODE_DVAR:
case NODE_GVAR:
case NODE_IVAR:
case NODE_CVAR:
case NODE_CONST:
case NODE_COLON3:
case NODE_INTEGER:
case NODE_FLOAT:
case NODE_RATIONAL:
case NODE_IMAGINARY:
case NODE_STR:
case NODE_SYM:
case NODE_REGX:
case NODE_SELF:
case NODE_NIL:
case NODE_TRUE:
case NODE_FALSE:
case NODE_LAMBDA:
case NODE_NTH_REF:
case NODE_BACK_REF:
return false;
case NODE_COLON2:
return setup_args_dup_rest_p(RNODE_COLON2(argn)->nd_head);
default:
return true;
}
}
Foo::Bar # safe
static bool
setup_args_dup_rest_p(const NODE *argn)
{
switch(nd_type(argn)) {
case NODE_LVAR:
case NODE_DVAR:
case NODE_GVAR:
case NODE_IVAR:
case NODE_CVAR:
case NODE_CONST:
case NODE_COLON3:
case NODE_INTEGER:
case NODE_FLOAT:
case NODE_RATIONAL:
case NODE_IMAGINARY:
case NODE_STR:
case NODE_SYM:
case NODE_REGX:
case NODE_SELF:
case NODE_NIL:
case NODE_TRUE:
case NODE_FALSE:
case NODE_LAMBDA:
case NODE_NTH_REF:
case NODE_BACK_REF:
return false;
case NODE_COLON2:
return setup_args_dup_rest_p(RNODE_COLON2(argn)->nd_head);
default:
return true;
}
}
Foo::Bar # safe
method_call::Bar # not safe
if (!dup_rest) {
// require allocation for keyword key/value/splat that may modify splatted argument
NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head;
while (node) {
NODE *key_node = RNODE_LIST(node)->nd_head;
if (key_node && setup_args_dup_rest_p(key_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
NODE *value_node = RNODE_LIST(node)->nd_head;
if (setup_args_dup_rest_p(value_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
}
}
if (!dup_rest) {
// require allocation for keyword key/value/splat that may modify splatted argument
NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head;
while (node) {
NODE *key_node = RNODE_LIST(node)->nd_head;
if (key_node && setup_args_dup_rest_p(key_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
NODE *value_node = RNODE_LIST(node)->nd_head;
if (setup_args_dup_rest_p(value_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
}
}
if (!dup_rest) {
// require allocation for keyword key/value/splat that may modify splatted argument
NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head;
while (node) {
NODE *key_node = RNODE_LIST(node)->nd_head;
if (key_node && setup_args_dup_rest_p(key_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
NODE *value_node = RNODE_LIST(node)->nd_head;
if (setup_args_dup_rest_p(value_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
}
}
if (!dup_rest) {
// require allocation for keyword key/value/splat that may modify splatted argument
NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head;
while (node) {
NODE *key_node = RNODE_LIST(node)->nd_head;
if (key_node && setup_args_dup_rest_p(key_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
NODE *value_node = RNODE_LIST(node)->nd_head;
if (setup_args_dup_rest_p(value_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
}
}
if (!dup_rest) {
// require allocation for keyword key/value/splat that may modify splatted argument
NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head;
while (node) {
NODE *key_node = RNODE_LIST(node)->nd_head;
if (key_node && setup_args_dup_rest_p(key_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
NODE *value_node = RNODE_LIST(node)->nd_head;
if (setup_args_dup_rest_p(value_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
}
}
if (!dup_rest) {
// require allocation for keyword key/value/splat that may modify splatted argument
NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head;
while (node) {
NODE *key_node = RNODE_LIST(node)->nd_head;
if (key_node && setup_args_dup_rest_p(key_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
NODE *value_node = RNODE_LIST(node)->nd_head;
if (setup_args_dup_rest_p(value_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
}
}
if (!dup_rest) {
// require allocation for keyword key/value/splat that may modify splatted argument
NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head;
while (node) {
NODE *key_node = RNODE_LIST(node)->nd_head;
if (key_node && setup_args_dup_rest_p(key_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
NODE *value_node = RNODE_LIST(node)->nd_head;
if (setup_args_dup_rest_p(value_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
}
}
if (!dup_rest) {
// require allocation for keyword key/value/splat that may modify splatted argument
NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head;
while (node) {
NODE *key_node = RNODE_LIST(node)->nd_head;
if (key_node && setup_args_dup_rest_p(key_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
NODE *value_node = RNODE_LIST(node)->nd_head;
if (setup_args_dup_rest_p(value_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
}
}
if (!dup_rest) {
// require allocation for keyword key/value/splat that may modify splatted argument
NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head;
while (node) {
NODE *key_node = RNODE_LIST(node)->nd_head;
if (key_node && setup_args_dup_rest_p(key_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
NODE *value_node = RNODE_LIST(node)->nd_head;
if (setup_args_dup_rest_p(value_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
}
}
if (!dup_rest) {
// require allocation for keyword key/value/splat that may modify splatted argument
NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head;
while (node) {
NODE *key_node = RNODE_LIST(node)->nd_head;
if (key_node && setup_args_dup_rest_p(key_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
NODE *value_node = RNODE_LIST(node)->nd_head;
if (setup_args_dup_rest_p(value_node)) {
dup_rest = 1;
break;
}
node = RNODE_LIST(node)->nd_next;
}
}
if (!dup_rest && (check_arg != argn) &&
setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
// require allocation for block pass that may modify splatted argument
dup_rest = 1;
}
if (!dup_rest && (check_arg != argn) &&
setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
// require allocation for block pass that may modify splatted argument
dup_rest = 1;
}
if (!dup_rest && (check_arg != argn) &&
setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
// require allocation for block pass that may modify splatted argument
dup_rest = 1;
}
if (!dup_rest && (check_arg != argn) &&
setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
// require allocation for block pass that may modify splatted argument
dup_rest = 1;
}
if (!dup_rest && (check_arg != argn) &&
setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
// require allocation for block pass that may modify splatted argument
dup_rest = 1;
}
# No Array Allocated
a(1, *ary)
a(1, *ary, &block)
a(*ary, **kw)
a(*ary, **kw, &block)
a(*ary, kw: 1)
a(*ary, kw: 1, &block)
# No Array Allocated
a(*ary, **kw, **kw)
a(*ary, **kw, **kw, &block)
a(*ary, kw: 1, **kw)
a(*ary, kw: 1, **kw, &block)
a(*ary, kw: lvar)
a(*ary, kw: lvar, &block)
a(*ary, kw: @ivar)
a(*ary, kw: @ivar, &block)
a(1, *ary, **kw, **kw)
a(1, *ary, **kw, **kw, &block)
a(1, *ary, kw: 1, **kw)
a(1, *ary, kw: 1, **kw, &block)
a(**h, &h.delete(key))
a(**h, &h.delete(key))
a(**h, &h.delete(key))
if (!dup_rest && (check_arg != argn) &&
setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
// require allocation for block pass that may modify splatted argument
dup_rest = 1;
}
if (!dup_rest && (check_arg != argn) &&
setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
// require allocation for block pass that may modify splatted argument
dup_rest = 1;
}
if (!dup_rest && (check_arg != argn) &&
setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
// require allocation for block pass that may modify splatted argument
dup_rest = SPLATARRAY_TRUE | DUP_SINGLE_KW_SPLAT;
}
if (!dup_rest && (check_arg != argn) &&
setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
// require allocation for block pass that may modify splatted argument
dup_rest = SPLATARRAY_TRUE | DUP_SINGLE_KW_SPLAT;
}
if (!dup_rest && (check_arg != argn) &&
setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
// require allocation for block pass that may modify splatted argument
dup_rest = SPLATARRAY_TRUE | DUP_SINGLE_KW_SPLAT;
}
if (!dup_rest && (check_arg != argn) &&
setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
// require allocation for block pass that may modify splatted argument
dup_rest = SPLATARRAY_TRUE | DUP_SINGLE_KW_SPLAT;
}
if ((check_arg != argn) &&
setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) {
// require allocation for block pass that may modify splatted argument
dup_rest = SPLATARRAY_TRUE | DUP_SINGLE_KW_SPLAT;
}
if (!keyword_node_single_splat_p(kwnode)) {
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
}
compile_hash(iseq, args, kwnode, TRUE, FALSE);
argc += 1;
if (!keyword_node_single_splat_p(kwnode)) {
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
}
compile_hash(iseq, args, kwnode, TRUE, FALSE);
argc += 1;
if (!keyword_node_single_splat_p(kwnode)) {
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
}
compile_hash(iseq, args, kwnode, TRUE, FALSE);
argc += 1;
if (!keyword_node_single_splat_p(kwnode)) {
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
}
compile_hash(iseq, args, kwnode, TRUE, FALSE);
argc += 1;
if (!keyword_node_single_splat_p(kwnode)) {
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
compile_hash(iseq, args, kwnode, TRUE, FALSE);
}
else if (*dup_rest & DUP_SINGLE_KW_SPLAT) {
compile_single_keyword_splat_mutable(iseq, args, argn,
kwnode, flag_ptr);
}
else {
compile_hash(iseq, args, kwnode, TRUE, FALSE);
}
argc += 1;
if (!keyword_node_single_splat_p(kwnode)) {
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
compile_hash(iseq, args, kwnode, TRUE, FALSE);
}
else if (*dup_rest & DUP_SINGLE_KW_SPLAT) {
compile_single_keyword_splat_mutable(iseq, args, argn,
kwnode, flag_ptr);
}
else {
compile_hash(iseq, args, kwnode, TRUE, FALSE);
}
argc += 1;
if (!keyword_node_single_splat_p(kwnode)) {
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
compile_hash(iseq, args, kwnode, TRUE, FALSE);
}
else if (*dup_rest & DUP_SINGLE_KW_SPLAT) {
compile_single_keyword_splat_mutable(iseq, args, argn,
kwnode, flag_ptr);
}
else {
compile_hash(iseq, args, kwnode, TRUE, FALSE);
}
argc += 1;
if (!keyword_node_single_splat_p(kwnode)) {
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
compile_hash(iseq, args, kwnode, TRUE, FALSE);
}
else if (*dup_rest & DUP_SINGLE_KW_SPLAT) {
compile_single_keyword_splat_mutable(iseq, args, argn,
kwnode, flag_ptr);
}
else {
compile_hash(iseq, args, kwnode, TRUE, FALSE);
}
argc += 1;
if (!keyword_node_single_splat_p(kwnode)) {
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
compile_hash(iseq, args, kwnode, TRUE, FALSE);
}
else if (*dup_rest & DUP_SINGLE_KW_SPLAT) {
compile_single_keyword_splat_mutable(iseq, args, argn,
kwnode, flag_ptr);
}
else {
compile_hash(iseq, args, kwnode, TRUE, FALSE);
}
argc += 1;
static void
compile_single_keyword_splat_mutable(rb_iseq_t *iseq, LINK_ANCHOR *const args,
const NODE *argn, NODE *kwnode,
unsigned int *flag_ptr)
{
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
ADD_INSN1(args, argn, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_INSN1(args, argn, newhash, INT2FIX(0));
compile_hash(iseq, args, kwnode, TRUE, FALSE);
ADD_SEND(args, argn, id_core_hash_merge_kwd, INT2FIX(2));
}
static void
compile_single_keyword_splat_mutable(rb_iseq_t *iseq, LINK_ANCHOR *const args,
const NODE *argn, NODE *kwnode,
unsigned int *flag_ptr)
{
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
ADD_INSN1(args, argn, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_INSN1(args, argn, newhash, INT2FIX(0));
compile_hash(iseq, args, kwnode, TRUE, FALSE);
ADD_SEND(args, argn, id_core_hash_merge_kwd, INT2FIX(2));
}
static void
compile_single_keyword_splat_mutable(rb_iseq_t *iseq, LINK_ANCHOR *const args,
const NODE *argn, NODE *kwnode,
unsigned int *flag_ptr)
{
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
ADD_INSN1(args, argn, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_INSN1(args, argn, newhash, INT2FIX(0));
compile_hash(iseq, args, kwnode, TRUE, FALSE);
ADD_SEND(args, argn, id_core_hash_merge_kwd, INT2FIX(2));
}
static void
compile_single_keyword_splat_mutable(rb_iseq_t *iseq, LINK_ANCHOR *const args,
const NODE *argn, NODE *kwnode,
unsigned int *flag_ptr)
{
*flag_ptr |= VM_CALL_KW_SPLAT_MUT;
ADD_INSN1(args, argn, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE));
ADD_INSN1(args, argn, newhash, INT2FIX(0));
compile_hash(iseq, args, kwnode, TRUE, FALSE);
ADD_SEND(args, argn, id_core_hash_merge_kwd, INT2FIX(2));
}
a(**h, &h.delete(key))
a(*ary, arg)
a(*ary1, *ary2)
a(kw: 1, **hash)
a(**hash1, **hash2)
a(*ary1, kw: lvar)
def a(*args)
# ...
end
def a(**kwargs)
# ...
end
def a(arg)
# ...
end
a(k: 1)
a(**hash)