summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Wu <XrXr@users.noreply.github.com>2021-05-06 12:24:50 -0400
committerAlan Wu <XrXr@users.noreply.github.com>2021-10-20 18:19:34 -0400
commit0d64f5e8a89a0ca5caba5289249ba9ee34fa4303 (patch)
treee197d107c1e629b62c69b1553726728923a8827f
parentad601cef8af4bc93a53c8437be4fe8749191f621 (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.rb24
-rw-r--r--yjit_codegen.c21
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;