Fixed register windows of OP_SENDs generated by NODE_{SCALL,CASE,YIELD,UNDEF}; ref
MODIFY
mrbgems/mruby-compiler/core/codegen.c
mrbgems/mruby-compiler/core/codegen.c
@@ -870,7 +870,7 @@ gen_call(codegen_scope *s, node *tree, mrb_sym name, int sp, int val, int safe)
genop(s, MKOP_A(OP_LOADNIL, cursp()));
push();
genop(s, MKOP_AB(OP_MOVE, cursp(), recv));
- push(); pop(); /* space for a block */
+ push_n(2); pop_n(2); /* space for one arg and a block */
pop();
idx = new_msym(s, mrb_intern_lit(s->mrb, "=="));
genop(s, MKOP_ABC(OP_EQ, cursp(), idx, 1));
@@ -1542,6 +1542,7 @@ codegen(codegen_scope *s, node *tree, int val)
codegen(s, n->car, VAL);
if (head) {
genop(s, MKOP_AB(OP_MOVE, cursp(), head));
+ push_n(2); pop_n(2); /* space for one arg and a block */
pop();
if (nint(n->car->car) == NODE_SPLAT) {
genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
@@ -2049,6 +2050,7 @@ codegen(codegen_scope *s, node *tree, int val)
push();
}
}
+ push();pop(); /* space for a block */
pop_n(n+1);
genop(s, MKOP_ABx(OP_BLKPUSH, cursp(), (ainfo<<4)|(lv & 0xf)));
if (sendv) n = CALL_MAXARGS;
@@ -2644,6 +2646,7 @@ codegen(codegen_scope *s, node *tree, int val)
t = t->cdr;
num++;
}
+ push();pop(); /* space for a block */
pop();
if (num < CALL_MAXARGS) {
pop_n(num);

MODIFY
test/t/codegen.rb
test/t/codegen.rb
@@ -73,3 +73,39 @@ assert('negate literal register alignment') do
assert_equal [2], a
end
+
+assert('register window of calls (#3783)') do
+ # NODE_SCALL
+ assert_nothing_raised do
+ Object.new&.__id__
+ end
+
+ # NODE_CASE
+ assert_nothing_raised do
+ case 1
+ when nil
+ end
+ end
+
+ # NODE_CASE with splat
+ assert_nothing_raised do
+ case 1
+ when *nil
+ end
+ end
+
+ # NODE_YIELD
+ def check_node_yield
+ yield
+ end
+ assert_nothing_raised do
+ check_node_yield{}
+ end
+
+ # NODE_UNDEF
+ assert_nothing_raised do
+ class << Object.new
+ undef send
+ end
+ end
+end
\ No newline at end of file

Fixed register windows of OP_SENDs generated by NODE_{SCALL,CASE,YIELD,UNDEF}; ref #3783