summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mjit_compile.c2
-rw-r--r--test/ruby/test_jit.rb10
-rw-r--r--tool/ruby_vm/views/_mjit_compile_send.erb3
3 files changed, 15 insertions, 0 deletions
diff --git a/mjit_compile.c b/mjit_compile.c
index 4f87550e78..e01f6b3cda 100644
--- a/mjit_compile.c
+++ b/mjit_compile.c
@@ -27,6 +27,7 @@ struct compile_status {
/* If TRUE, JIT-ed code will use local variables to store pushed values instead of
using VM's stack and moving stack pointer. */
int local_stack_p;
+ const char *funcname; /* the method name which is being compiled */
};
/* Storage to keep data which is consistent in each conditional branch.
@@ -193,6 +194,7 @@ mjit_compile(FILE *f, const struct rb_iseq_constant_body *body, const char *func
status.success = TRUE;
status.local_stack_p = !body->catch_except_p;
status.stack_size_for_pos = ALLOC_N(int, body->iseq_size);
+ status.funcname = funcname;
memset(status.stack_size_for_pos, NOT_COMPILED_STACK_SIZE, sizeof(int) * body->iseq_size);
/* For performance, we verify stack size only on compilation time (mjit_compile.inc.erb) without --jit-debug */
diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb
index 891b7f496f..844f36a98f 100644
--- a/test/ruby/test_jit.rb
+++ b/test/ruby/test_jit.rb
@@ -322,6 +322,16 @@ class TestJIT < Test::Unit::TestCase
def test_compile_insn_opt_send_without_block
assert_compile_once('print', result_inspect: 'nil', insns: %i[opt_send_without_block])
+
+ # recursive inline
+ assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '120', success_count: 1, min_calls: 2)
+ begin;
+ def fact(i)
+ return i if i <= 1
+ i * fact(i - 1)
+ end
+ print fact(5)
+ end;
end
def test_compile_insn_invokesuper
diff --git a/tool/ruby_vm/views/_mjit_compile_send.erb b/tool/ruby_vm/views/_mjit_compile_send.erb
index cb7c1f40f8..b1dc0e72c8 100644
--- a/tool/ruby_vm/views/_mjit_compile_send.erb
+++ b/tool/ruby_vm/views/_mjit_compile_send.erb
@@ -58,6 +58,9 @@
fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n");
fprintf(f, " v = vm_exec(ec, TRUE);\n");
}
+ else if (body == iseq->body) { /* inline recursive call */
+ fprintf(f, " v = %s(ec, ec->cfp);\n", status->funcname);
+ }
else {
fprintf(f, " if ((v = mjit_exec(ec)) == Qundef) {\n");
fprintf(f, " VM_ENV_FLAGS_SET(ec->cfp->ep, VM_FRAME_FLAG_FINISH);\n"); /* This is vm_call0_body's code after vm_call_iseq_setup */