aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreileencodes <eileencodes@gmail.com>2023-12-15 11:32:10 -0500
committerKevin Newton <kddnewton@gmail.com>2023-12-15 16:23:06 -0500
commitb8074c2f043d99f6f30ab75ad21cc2c998f49dcf (patch)
tree5a16af98ae44d5f8f51378565b6e5e54c9dcc643
parent161787f9beef96c9fa1057b6378fe7e048ac2ecd (diff)
downloadruby-b8074c2f043d99f6f30ab75ad21cc2c998f49dcf.tar.gz
[PRISM] Fix incorrect instructions for `default_proc=`
This is kind of specific and was found via debugging ruby/prism#2061 but does not actually fix that issue. The change here checks for `!popped` for the additional instructions that are normally added for nodes with the `attribute_write` flag. I also removed the extra catch table by deleting the `ISEQ_COMPILE_DATA(iseq)->catch_except_p = true;` line. I'm...not entirely sure why it was added but it doesn't match the upstream compiler [code](https://github.com/ruby/ruby/blob/92b10f5be7453aceb5863e46ac775a4ddbf83b97/compile.c#L887-L892). The changes here unfortunately don't improve the test failures mentioned in the linked issue so we still have other issues with instructions for hashes. Instructions before: ``` "********* Ruby *************" == disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(34,8)> local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] h@0 0000 putnil ( 32)[Li] 0001 putobject true 0003 getconstant :Hash 0005 send <calldata!mid:new, argc:0, ARGS_SIMPLE>, nil 0008 setlocal h@0, 0 0011 getlocal h@0, 0 ( 33)[Li] 0014 putspecialobject 1 0016 send <calldata!mid:lambda, argc:0, FCALL>, block in <compiled> 0019 send <calldata!mid:default_proc=, argc:1, ARGS_SIMPLE>, nil 0022 pop 0023 getlocal h@0, 0 ( 34)[Li] 0026 putobject :nope 0028 send <calldata!mid:[], argc:1, ARGS_SIMPLE>, nil 0031 leave == disasm: #<ISeq:block in <compiled>@<compiled>:33 (33,19)-(33,32)> local table (size: 2, argc: 2 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 2] _@0<Arg> [ 1] _@1<Arg> 0000 putobject true ( 33)[LiBc] 0002 leave [Br] true "********* PRISM *************" == disasm: #<ISeq:<compiled>@<compiled>:31 (31,0)-(33,8)> local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] h@0 0000 putnil ( 31)[Li] 0001 putobject true 0003 getconstant :Hash 0005 send <calldata!mid:new, argc:0, ARGS_SIMPLE>, nil 0008 setlocal h@0, 0 0011 putnil ( 32)[Li] 0012 getlocal h@0, 0 0015 putspecialobject 1 0017 send <calldata!mid:lambda, argc:0, FCALL>, block in <compiled> 0020 setn 2 0022 send <calldata!mid:default_proc=, argc:1, ARGS_SIMPLE>, nil 0025 pop 0026 pop 0027 getlocal h@0, 0 ( 33)[Li] 0030 putobject :nope 0032 send <calldata!mid:[], argc:1, ARGS_SIMPLE>, nil 0035 leave ( 31) == disasm: #<ISeq:block in <compiled>@<compiled>:32 (32,17)-(32,32)> == catch table | catch type: redo st: 0000 ed: 0002 sp: 0000 cont: 0000 | catch type: next st: 0000 ed: 0002 sp: 0000 cont: 0002 |------------------------------------------------------------------------ local table (size: 2, argc: 2 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 2] _@0<Arg> [ 1] _@1<Arg> 0000 putobject true ( 32)[LiBc] 0002 leave [Br] ``` Instructions after: ``` "********* Ruby *************" == disasm: #<ISeq:<compiled>@<compiled>:1 (1,0)-(34,8)> local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] h@0 0000 putnil ( 32)[Li] 0001 putobject true 0003 getconstant :Hash 0005 send <calldata!mid:new, argc:0, ARGS_SIMPLE>, nil 0008 setlocal h@0, 0 0011 getlocal h@0, 0 ( 33)[Li] 0014 putspecialobject 1 0016 send <calldata!mid:lambda, argc:0, FCALL>, block in <compiled> 0019 send <calldata!mid:default_proc=, argc:1, ARGS_SIMPLE>, nil 0022 pop 0023 getlocal h@0, 0 ( 34)[Li] 0026 putobject :nope 0028 send <calldata!mid:[], argc:1, ARGS_SIMPLE>, nil 0031 leave == disasm: #<ISeq:block in <compiled>@<compiled>:33 (33,19)-(33,32)> local table (size: 2, argc: 2 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 2] _@0<Arg> [ 1] _@1<Arg> 0000 putobject true ( 33)[LiBc] 0002 leave [Br] "********* PRISM *************" == disasm: #<ISeq:<compiled>@<compiled>:31 (31,0)-(33,8)> local table (size: 1, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 1] h@0 0000 putnil ( 31)[Li] 0001 putobject true 0003 getconstant :Hash 0005 send <calldata!mid:new, argc:0, ARGS_SIMPLE>, nil 0008 setlocal h@0, 0 0011 getlocal h@0, 0 ( 32)[Li] 0014 putspecialobject 1 0016 send <calldata!mid:lambda, argc:0, FCALL>, block in <compiled> 0019 send <calldata!mid:default_proc=, argc:1, ARGS_SIMPLE>, nil 0022 pop 0023 getlocal h@0, 0 ( 33)[Li] 0026 putobject :nope 0028 send <calldata!mid:[], argc:1, ARGS_SIMPLE>, nil 0031 leave ( 31) == disasm: #<ISeq:block in <compiled>@<compiled>:32 (32,17)-(32,32)> local table (size: 2, argc: 2 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 2] _@0<Arg> [ 1] _@1<Arg> 0000 putobject true ( 32)[LiBc] 0002 leave [Br] ```
-rw-r--r--prism_compile.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/prism_compile.c b/prism_compile.c
index 30918344c0..096b9e7903 100644
--- a/prism_compile.c
+++ b/prism_compile.c
@@ -2641,9 +2641,11 @@ pm_compile_call(rb_iseq_t *iseq, const pm_call_node_t *call_node, LINK_ANCHOR *c
}
if (pm_node->flags & PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) {
- ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(orig_argc + 1));
+ if (!popped) {
+ ADD_INSN1(ret, &dummy_line_node, setn, INT2FIX(orig_argc + 1));
+ }
ADD_SEND_R(ret, &dummy_line_node, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg);
- PM_POP;
+ PM_POP_UNLESS_POPPED;
}
else {
ADD_SEND_R(ret, &dummy_line_node, method_id, INT2FIX(orig_argc), block_iseq, INT2FIX(flags), kw_arg);
@@ -3156,7 +3158,9 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
ID method_id = pm_constant_id_lookup(scope_node, call_node->name);
if (node->flags & PM_CALL_NODE_FLAGS_ATTRIBUTE_WRITE) {
- PM_PUTNIL;
+ if (!popped) {
+ PM_PUTNIL;
+ }
}
if (call_node->receiver == NULL) {
@@ -6182,7 +6186,6 @@ pm_compile_node(rb_iseq_t *iseq, const pm_node_t *node, LINK_ANCHOR *const ret,
ISEQ_COMPILE_DATA(iseq)->last_line = body->location.code_location.end_pos.lineno;
/* wide range catch handler must put at last */
- ISEQ_COMPILE_DATA(iseq)->catch_except_p = true;
ADD_CATCH_ENTRY(CATCH_TYPE_REDO, start, end, NULL, start);
ADD_CATCH_ENTRY(CATCH_TYPE_NEXT, start, end, NULL, end);
break;