[前][次][番号順一覧][スレッド一覧]

ruby-changes:68706

From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:12:30 +0900 (JST)
Subject: [ruby-changes:68706] 02a9700475 (master): End current block after opt_send_without_block

https://git.ruby-lang.org/ruby.git/commit/?id=02a9700475

From 02a97004751eae471e00b2b6c3ce86c9dd6ae259 Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...>
Date: Fri, 15 Jan 2021 17:10:52 -0500
Subject: End current block after opt_send_without_block

---
 ujit_codegen.c | 209 +++++++++++++++++++++++++--------------------------------
 ujit_iface.c   |  36 ++++++++++
 ujit_iface.h   |   4 ++
 3 files changed, 133 insertions(+), 116 deletions(-)

diff --git a/ujit_codegen.c b/ujit_codegen.c
index 24b0dab4b3..006d64fe0f 100644
--- a/ujit_codegen.c
+++ b/ujit_codegen.c
@@ -640,40 +640,103 @@ gen_opt_plus(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L640
     return true;
 }
 
-// Verify that calling with cd on receiver goes to callee
-static void
-check_cfunc_dispatch(VALUE receiver, struct rb_call_data *cd, void *callee, rb_callable_method_entry_t *compile_time_cme)
+void 
+gen_branchunless_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t shape)
 {
-    if (METHOD_ENTRY_INVALIDATED(compile_time_cme)) {
-        rb_bug("ujit: output code uses invalidated cme %p", (void *)compile_time_cme);
-    }
+    switch (shape)
+    {
+        case SHAPE_NEXT0:
+        jnz_ptr(cb, target1);
+        break;
 
-    bool callee_correct = false;
-    const rb_callable_method_entry_t *cme = rb_callable_method_entry(CLASS_OF(receiver), vm_ci_mid(cd->ci));
-    if (cme->def->type == VM_METHOD_TYPE_CFUNC) {
-        const rb_method_cfunc_t *cfunc = UNALIGNED_MEMBER_PTR(cme->def, body.cfunc);
-        if ((void *)cfunc->func == callee) {
-            callee_correct = true;
-        }
-    }
-    if (!callee_correct) {
-        rb_bug("ujit: output code calls wrong method cd->cc->klass: %p", (void *)cd->cc->klass);
+        case SHAPE_NEXT1:
+        jz_ptr(cb, target0);
+        break;
+
+        case SHAPE_DEFAULT:
+        jz_ptr(cb, target0);
+        jmp_ptr(cb, target1);
+        break;
     }
 }
 
-MJIT_FUNC_EXPORTED VALUE rb_hash_has_key(VALUE hash, VALUE key);
+static bool
+gen_branchunless(jitstate_t* jit, ctx_t* ctx)
+{
+    // TODO: we need to eventually do an interrupt check when jumping/branching
+    // How can we do this while keeping the check logic out of line?
+    // Maybe we can push the check int into the next block or the stub?
+    //
+	// RUBY_VM_CHECK_INTS(ec);
+
+    // Test if any bit (outside of the Qnil bit) is on
+    // RUBY_Qfalse  /* ...0000 0000 */
+    // RUBY_Qnil    /* ...0000 1000 */
+    x86opnd_t val_opnd = ctx_stack_pop(ctx, 1);
+    test(cb, val_opnd, imm_opnd(~Qnil));
+
+    // Get the branch target instruction offsets
+    uint32_t next_idx = jit_next_idx(jit);
+    uint32_t jump_idx = next_idx + (uint32_t)jit_get_arg(jit, 0);
+    blockid_t next_block = { jit->iseq, next_idx };
+    blockid_t jump_block = { jit->iseq, jump_idx };
+
+    // Generate the branch instructions
+    gen_branch(
+        jit->block,
+        ctx,
+        jump_block,
+        ctx,
+        next_block,
+        ctx,
+        gen_branchunless_branch
+    );
+
+    return true;
+}
+
+void
+gen_jump_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t shape)
+{
+    switch (shape)
+    {
+        case SHAPE_NEXT0:
+        break;
+
+        case SHAPE_NEXT1:
+        assert (false);
+        break;
+
+        case SHAPE_DEFAULT:
+        jmp_ptr(cb, target0);
+        break;
+    }
+}
 
 static bool
-cfunc_needs_frame(const rb_method_cfunc_t *cfunc)
+gen_jump(jitstate_t* jit, ctx_t* ctx)
 {
-    void* fptr = (void*)cfunc->func;
+    // Get the branch target instruction offsets
+    uint32_t jump_idx = jit_next_idx(jit) + (int32_t)jit_get_arg(jit, 0);
+    blockid_t jump_block = { jit->iseq, jump_idx };
+
+    //
+    // TODO:
+	// RUBY_VM_CHECK_INTS(ec);
+    //
 
-    // Leaf C functions do not need a stack frame
-    // or a stack overflow check
-    return !(
-        // Hash#key?
-        fptr == (void*)rb_hash_has_key
+    // Generate the jump instruction
+    gen_branch(
+        jit->block,
+        ctx,
+        jump_block,
+        ctx,
+        BLOCKID_NULL,
+        ctx,
+        gen_jump_branch
     );
+
+    return true;
 }
 
 static bool
@@ -750,7 +813,7 @@ gen_opt_send_without_block(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L813
     mov(cb, REG0, recv);
 
     // Callee method ID
-    ID mid = vm_ci_mid(cd->ci);
+    //ID mid = vm_ci_mid(cd->ci);
     //printf("JITting call to C function \"%s\", argc: %lu\n", rb_id2name(mid), argc);
     //print_str(cb, "");
     //print_str(cb, "calling CFUNC:");
@@ -919,99 +982,13 @@ gen_opt_send_without_block(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L982
         );
     }
 
-    return true;
-}
-
-void 
-gen_branchunless_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t shape)
-{
-    switch (shape)
-    {
-        case SHAPE_NEXT0:
-        jnz_ptr(cb, target1);
-        break;
-
-        case SHAPE_NEXT1:
-        jz_ptr(cb, target0);
-        break;
-
-        case SHAPE_DEFAULT:
-        jz_ptr(cb, target0);
-        jmp_ptr(cb, target1);
-        break;
-    }
-}
-
-static bool
-gen_branchunless(jitstate_t* jit, ctx_t* ctx)
-{
-    // TODO: we need to eventually do an interrupt check when jumping/branching
-    // How can we do this while keeping the check logic out of line?
-    // Maybe we can push the check int into the next block or the stub?
-    //
-	// RUBY_VM_CHECK_INTS(ec);
-
-    // Test if any bit (outside of the Qnil bit) is on
-    // RUBY_Qfalse  /* ...0000 0000 */
-    // RUBY_Qnil    /* ...0000 1000 */
-    x86opnd_t val_opnd = ctx_stack_pop(ctx, 1);
-    test(cb, val_opnd, imm_opnd(~Qnil));
-
-    // Get the branch target instruction offsets
-    uint32_t next_idx = jit_next_idx(jit);
-    uint32_t jump_idx = next_idx + (uint32_t)jit_get_arg(jit, 0);
-    blockid_t next_block = { jit->iseq, next_idx };
-    blockid_t jump_block = { jit->iseq, jump_idx };
-
-    // Generate the branch instructions
+    // Jump (fall through) to the call continuation block
+    // We do this to end the current block after the call
+    blockid_t cont_block = { jit->iseq, jit_next_idx(jit) };
     gen_branch(
         jit->block,
         ctx,
-        jump_block,
-        ctx,
-        next_block,
-        ctx,
-        gen_branchunless_branch
-    );
-
-    return true;
-}
-
-void
-gen_jump_branch(codeblock_t* cb, uint8_t* target0, uint8_t* target1, uint8_t shape)
-{
-    switch (shape)
-    {
-        case SHAPE_NEXT0:
-        break;
-
-        case SHAPE_NEXT1:
-        assert (false);
-        break;
-
-        case SHAPE_DEFAULT:
-        jmp_ptr(cb, target0);
-        break;
-    }
-}
-
-static bool
-gen_jump(jitstate_t* jit, ctx_t* ctx)
-{
-    // Get the branch target instruction offsets
-    uint32_t jump_idx = jit_next_idx(jit) + (int32_t)jit_get_arg(jit, 0);
-    blockid_t jump_block = { jit->iseq, jump_idx };
-
-    //
-    // TODO:
-	// RUBY_VM_CHECK_INTS(ec);
-    //
-
-    // Generate the jump instruction
-    gen_branch(
-        jit->block,
-        ctx,
-        jump_block,
+        cont_block,
         ctx,
         BLOCKID_NULL,
         ctx,
@@ -1066,7 +1043,7 @@ ujit_init_codegen(void) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L1043
     ujit_reg_op(BIN(opt_lt), gen_opt_lt, false);
     ujit_reg_op(BIN(opt_minus), gen_opt_minus, false);
     ujit_reg_op(BIN(opt_plus), gen_opt_plus, false);
-    ujit_reg_op(BIN(opt_send_without_block), gen_opt_send_without_block, false);
     ujit_reg_op(BIN(branchunless), gen_branchunless, true);
     ujit_reg_op(BIN(jump), gen_jump, true);
+    ujit_reg_op(BIN(opt_send_without_block), gen_opt_send_without_block, true);
 }
diff --git a/ujit_iface.c b/ujit_iface.c
index 583326ce42..d759560cb6 100644
--- a/ujit_iface.c
+++ b/ujit_iface.c
@@ -63,6 +63,42 @@ opcode_at_pc(const rb_iseq_t *iseq, const VALUE *pc) https://github.com/ruby/ruby/blob/trunk/ujit_iface.c#L63
     }
 }
 
+// Verify that calling with cd on receiver goes to callee
+void
+check_cfunc_dispatch(VALUE receiver, struct rb_call_data *cd, void *callee, rb_callable_method_entry_t *compile_time_cme)
+{
+    if (METHOD_ENTRY_INVALIDATED(compile_time_cme)) {
+        rb_bug("ujit: output code uses invalidated cme %p", (void *)compile_time_cme);
+    }
+
+    bool callee_correct = false;
+    const rb_callable_method_entry_t *cme = rb_callable_method_entry(CLASS_OF(receiver), vm_ci_mid(cd->ci));
+    if (cme->def->type == VM_METHOD_TYPE_CFUNC) {
+        const rb_method_cfunc_t *cfunc = UNALIGNED_MEMBER_PTR(cme->def, body.cfunc);
+        if ((void *)cfunc->func == callee) {
+            callee_correct = true;
+        }
+    }
+    if (!callee_correct) {
+        rb_bug("ujit: output code calls wrong method cd->cc->klass: %p", (void *)cd->cc->klass);
+    }
+}
+
+MJIT_FUNC_EXPORTED VALUE rb_hash_has_key(VALUE hash, VALUE key);
+
+bool
+cfunc_needs_frame(const rb_method_cfunc_t *cfunc)
+{
+    void* fptr = (void*)cfunc->func;
+
+    // Leaf C functions do not need a stack frame
+    // or a stack overflow check
+    return !(
+        // Hash#key?
+        fptr == (void*)rb_hash_has_key
+    );
+}
+
 // GC root for interacting with the GC
 struct ujit_root_struct {};
 
diff --git a/ujit_iface.h b/ujit_iface.h
index 0c6bf2456c..aa335dbf19 100644
--- a/ujit_iface.h
+++ b/ujit_iface.h
@@ -22,8 +22,12 @@ struct rb_callcache; https://github.com/ruby/ruby/blob/trunk/ujit_iface.h#L22
 
 void cb_write_pre_call_bytes(codeblock_t* cb);
 void cb_write_post_call_bytes(codeblock_t* cb);
+
 void map_addr2insn(void *code_ptr, int insn);
 int opcode_at_pc(const rb_iseq_t *iseq, const VALUE *pc);
+
+void check_cfunc_dispatch(VALUE receiver, struct rb_call_data *cd, void *callee, rb_callable_method_entry_t *compile_time_cme);
+bool cfunc_needs_frame(const rb_method_cfunc_t *cfunc);
 void assume_method_lookup_stable(const struct rb_callcache *cc, const rb_callable_method_entry_t *cme, block_t* bl (... truncated)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]