summaryrefslogtreecommitdiff
path: root/tool/ruby_vm/views/_mjit_compile_send.erb
diff options
context:
space:
mode:
authorTakashi Kokubun <takashikkbn@gmail.com>2019-07-02 23:32:09 +0900
committerTakashi Kokubun <takashikkbn@gmail.com>2019-07-02 23:35:52 +0900
commitea30dd702512ff9df34fe8c71c825f8f901bf5b1 (patch)
treefefa0f795f3c8eaa06b00de7c6693f89da27d9c0 /tool/ruby_vm/views/_mjit_compile_send.erb
parent181b966e7553ac53d034266a7cdc18664d080814 (diff)
Avoid corrupting VM stack on inlined setlocal
setlocal relies on cfp->ep, and frame-omitted method inlining introduced in Ruby 2.7 kept it wrong. This change might slow down frame-omitted method inlining for cfp->ep manipulation, and it obviously complicates the implementaion more. By introducing an optimization that changes Ruby's local variable to C local variable, we could optimize it and simplify the cfp->ep manipulation later. [Bug #15971]
Diffstat (limited to 'tool/ruby_vm/views/_mjit_compile_send.erb')
-rw-r--r--tool/ruby_vm/views/_mjit_compile_send.erb5
1 files changed, 5 insertions, 0 deletions
diff --git a/tool/ruby_vm/views/_mjit_compile_send.erb b/tool/ruby_vm/views/_mjit_compile_send.erb
index da7e96581b..3db1386aca 100644
--- a/tool/ruby_vm/views/_mjit_compile_send.erb
+++ b/tool/ruby_vm/views/_mjit_compile_send.erb
@@ -46,10 +46,15 @@
% # JIT: If ISeq is inlinable, call the inlined method without pushing a frame.
if (status->inlined_iseqs != NULL && status->inlined_iseqs[pos] == iseq->body) {
+ // TODO: consider using C variables for Ruby variables to simplify cfp->ep manipulation
fprintf(f, " {\n");
fprintf(f, " VALUE orig_self = reg_cfp->self;\n");
+ fprintf(f, " VALUE orig_ep = reg_cfp->ep;\n");
fprintf(f, " reg_cfp->self = stack[%d];\n", b->stack_size - argc - 1);
+ fprintf(f, " reg_cfp->ep = reg_cfp->sp + %d + 2;\n", iseq->body->local_table_size - iseq->body->param.size); // simulate `vm_push_frame`'s local_size and 2 increments
+ fprintf(f, " ((VALUE *)reg_cfp->ep)[VM_ENV_DATA_INDEX_ENV] = ((VALUE *)orig_ep)[VM_ENV_DATA_INDEX_ENV];\n"); // `vm_env_write_slowpath` checks this value
fprintf(f, " stack[%d] = _mjit_inlined_%d(ec, reg_cfp, orig_self, original_iseq);\n", b->stack_size - argc - 1, pos);
+ fprintf(f, " reg_cfp->ep = orig_ep;\n");
fprintf(f, " reg_cfp->self = orig_self;\n");
fprintf(f, " }\n");
}