diff --git a/vm.c b/vm.c index 32cdd484250355..18f8d264fe82bf 100644 --- a/vm.c +++ b/vm.c @@ -2299,68 +2299,73 @@ hook_before_rewind(rb_execution_context_t *ec, const rb_control_frame_t *cfp, static inline VALUE vm_exec_handle_exception(rb_execution_context_t *ec, enum ruby_tag_type state, VALUE errinfo); -// for non-Emscripten Wasm build, use vm_exec with optimized setjmp for runtime performance -#if defined(__wasm__) && !defined(__EMSCRIPTEN__) - -struct rb_vm_exec_context { - rb_execution_context_t *ec; - struct rb_vm_tag *tag; - VALUE result; - enum ruby_tag_type state; -}; - -static void -vm_exec_enter_vm_loop(rb_execution_context_t *ec, struct rb_vm_exec_context *ctx, - struct rb_vm_tag *_tag, bool skip_first_ex_handle) +static VALUE +vm_exec_loop(rb_execution_context_t *ec, enum ruby_tag_type state, + struct rb_vm_tag *_tag, VALUE result) { - if (skip_first_ex_handle) { + if (state == TAG_NONE) { /* no jumps, result is discarded */ goto vm_loop_start; } - ctx->result = ec->errinfo; rb_ec_raised_reset(ec, RAISED_STACKOVERFLOW | RAISED_NOMEMORY); - while (UNDEF_P(ctx->result = vm_exec_handle_exception(ec, ctx->state, ctx->result))) { + while (UNDEF_P(result = vm_exec_handle_exception(ec, state, result))) { /* caught a jump, exec the handler */ - ctx->result = vm_exec_core(ec); - vm_loop_start: + vm_loop_start: + result = vm_exec_core(ec); VM_ASSERT(ec->tag == _tag); /* when caught `throw`, `tag.state` is set. */ - if ((ctx->state = _tag->state) == TAG_NONE) break; + if ((state = _tag->state) == TAG_NONE) break; _tag->state = TAG_NONE; } + + return result; } +struct rb_vm_exec_context { + rb_execution_context_t *const ec; + struct rb_vm_tag *const tag; + + VALUE result; +}; + +// for non-Emscripten Wasm build, use vm_exec with optimized setjmp for runtime performance +#if defined(__wasm__) && !defined(__EMSCRIPTEN__) + static void vm_exec_bottom_main(void *context) { - struct rb_vm_exec_context *ctx = (struct rb_vm_exec_context *)context; + struct rb_vm_exec_context *ctx = context; + rb_execution_context_t *ec = ctx->ec; - ctx->state = TAG_NONE; - ctx->result = vm_exec_core(ctx->ec); - vm_exec_enter_vm_loop(ctx->ec, ctx, ctx->tag, true); + ctx->result = vm_exec_loop(ec, TAG_NONE, ctx->tag, Qundef); } static void vm_exec_bottom_rescue(void *context) { - struct rb_vm_exec_context *ctx = (struct rb_vm_exec_context *)context; - ctx->state = rb_ec_tag_state(ctx->ec); - vm_exec_enter_vm_loop(ctx->ec, ctx, ctx->tag, false); + struct rb_vm_exec_context *ctx = context; + rb_execution_context_t *ec = ctx->ec; + + ctx->result = vm_exec_loop(ec, rb_ec_tag_state(ec), ctx->tag, ec->errinfo); } +#endif VALUE vm_exec(rb_execution_context_t *ec) { + VALUE result = Qundef; + + EC_PUSH_TAG(ec); + struct rb_vm_exec_context ctx = { .ec = ec, - .result = Qundef, + .tag = &_tag, }; - struct rb_wasm_try_catch try_catch; - - EC_PUSH_TAG(ec); _tag.retval = Qnil; - ctx.tag = &_tag; + +#if defined(__wasm__) && !defined(__EMSCRIPTEN__) + struct rb_wasm_try_catch try_catch; EC_REPUSH_TAG(); @@ -2368,44 +2373,23 @@ vm_exec(rb_execution_context_t *ec) rb_wasm_try_catch_loop_run(&try_catch, &_tag.buf); - EC_POP_TAG(); - return ctx.result; -} - + result = ctx.result; #else - -VALUE -vm_exec(rb_execution_context_t *ec) -{ enum ruby_tag_type state; - VALUE result = Qundef; - - EC_PUSH_TAG(ec); - - _tag.retval = Qnil; if ((state = EC_EXEC_TAG()) == TAG_NONE) { - if (UNDEF_P(result = jit_exec(ec))) { - result = vm_exec_core(ec); + if (UNDEF_P(result = jit_exec(ctx.ec))) { + /* fallback to the VM */ + result = vm_exec_loop(ctx.ec, TAG_NONE, ctx.tag, Qundef); } - goto vm_loop_start; /* fallback to the VM */ } else { - result = ec->errinfo; - rb_ec_raised_reset(ec, RAISED_STACKOVERFLOW | RAISED_NOMEMORY); - while (UNDEF_P(result = vm_exec_handle_exception(ec, state, result))) { - /* caught a jump, exec the handler */ - result = vm_exec_core(ec); - vm_loop_start: - VM_ASSERT(ec->tag == &_tag); - /* when caught `throw`, `tag.state` is set. */ - if ((state = _tag.state) == TAG_NONE) break; - _tag.state = TAG_NONE; - } + result = vm_exec_loop(ctx.ec, state, ctx.tag, ctx.ec->errinfo); } +#endif + EC_POP_TAG(); return result; } -#endif static inline VALUE vm_exec_handle_exception(rb_execution_context_t *ec, enum ruby_tag_type state, VALUE errinfo)