diff options
author | Alan Wu <XrXr@users.noreply.github.com> | 2021-05-06 12:24:50 -0400 |
---|---|---|
committer | Alan Wu <XrXr@users.noreply.github.com> | 2021-10-20 18:19:34 -0400 |
commit | 0d64f5e8a89a0ca5caba5289249ba9ee34fa4303 (patch) | |
tree | e197d107c1e629b62c69b1553726728923a8827f | |
parent | ad601cef8af4bc93a53c8437be4fe8749191f621 (diff) |
Check for easy-to-handle cases of block param (#24)
In some cases, methods taking block parameters don't require extra
paramter setup. They are fairly popular in railsbench.
-rw-r--r-- | bootstraptest/test_yjit.rb | 24 | ||||
-rw-r--r-- | yjit_codegen.c | 21 |
2 files changed, 43 insertions, 2 deletions
diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 0b469ff5fa..663977f0ca 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -869,3 +869,27 @@ end use([], 0) [use([2, 2], 38), use([14, 14, 14], 0)] } + +# test calling method taking block param +assert_equal '[Proc, 1, 2, 3, Proc]', %q{ + def three(a, b, c, &block) + [a, b, c, block.class] + end + + def zero(&block) + block.class + end + + def use_three + three(1, 2, 3) {} + end + + def use_zero + zero {} + end + + use_three + use_zero + + [use_zero] + use_three +} diff --git a/yjit_codegen.c b/yjit_codegen.c index ba332687b4..0b1c7745da 100644 --- a/yjit_codegen.c +++ b/yjit_codegen.c @@ -1892,7 +1892,22 @@ gen_return_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t s } } -bool rb_simple_iseq_p(const rb_iseq_t *iseq); +// Returns whether the iseq only needs positional (lead) argument setup. +static bool +iseq_lead_only_arg_setup_p(const rb_iseq_t *iseq) +{ + // When iseq->body->local_iseq == iseq, setup_parameters_complex() + // doesn't do anything to setup the block parameter. + bool takes_block = iseq->body->param.flags.has_block; + return (!takes_block || iseq->body->local_iseq == iseq) && + iseq->body->param.flags.has_opt == false && + iseq->body->param.flags.has_rest == false && + iseq->body->param.flags.has_post == false && + iseq->body->param.flags.has_kw == false && + iseq->body->param.flags.has_kwrest == false && + iseq->body->param.flags.accepts_no_kwarg == false; +} + bool rb_iseq_only_optparam_p(const rb_iseq_t *iseq); bool rb_iseq_only_kwparam_p(const rb_iseq_t *iseq); @@ -1910,7 +1925,9 @@ gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, const r // Arity handling and optional parameter setup int num_params = iseq->body->param.size; uint32_t start_pc_offset = 0; - if (rb_simple_iseq_p(iseq)) { + if (iseq_lead_only_arg_setup_p(iseq)) { + num_params = iseq->body->param.lead_num; + if (num_params != argc) { GEN_COUNTER_INC(cb, send_iseq_arity_error); return YJIT_CANT_COMPILE; |