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

ruby-changes:68895

From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:15:06 +0900 (JST)
Subject: [ruby-changes:68895] cbbae12a96 (master): Keep track of local types in the context

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

From cbbae12a96e1857c414b4592376886fc8bb5da1a Mon Sep 17 00:00:00 2001
From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...>
Date: Tue, 6 Apr 2021 14:44:28 -0400
Subject: Keep track of local types in the context

---
 yjit_codegen.c | 28 +++++++++++++++++++++-------
 yjit_core.c    | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++----
 yjit_core.h    |  2 ++
 3 files changed, 74 insertions(+), 11 deletions(-)

diff --git a/yjit_codegen.c b/yjit_codegen.c
index 18c8f7c4e9..af0522a493 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -486,11 +486,12 @@ gen_getlocal_wc0(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L486
     int32_t local_idx = (int32_t)jit_get_arg(jit, 0);
     const int32_t offs = -(SIZEOF_VALUE * local_idx);
 
-    // Load the local from the block
+    // Load the local from the EP
     mov(cb, REG0, mem_opnd(64, REG0, offs));
 
     // Write the local at SP
-    x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_UNKNOWN);
+    x86opnd_t stack_top = ctx_stack_push_local(ctx, local_idx);
+    //x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_UNKNOWN);
     mov(cb, stack_top, REG0);
 
     return YJIT_KEEP_COMPILING;
@@ -539,6 +540,8 @@ gen_setlocal_wc0(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L540
     }
     */
 
+    int32_t local_idx = (int32_t)jit_get_arg(jit, 0);
+
     // Load environment pointer EP from CFP
     mov(cb, REG0, member_opnd(REG_CFP, rb_control_frame_t, ep));
 
@@ -552,12 +555,15 @@ gen_setlocal_wc0(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L555
     // if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
     jnz_ptr(cb, side_exit);
 
+    // Set the type of the local variable in the context
+    val_type_t temp_type = ctx_get_temp_type(ctx, 0);
+    ctx_set_local_type(ctx, local_idx, temp_type);
+
     // Pop the value to write from the stack
     x86opnd_t stack_top = ctx_stack_pop(ctx, 1);
     mov(cb, REG1, stack_top);
 
     // Write the value at the environment pointer
-    int32_t local_idx = (int32_t)jit_get_arg(jit, 0);
     const int32_t offs = -8 * local_idx;
     mov(cb, mem_opnd(64, REG0, offs), REG1);
 
@@ -1326,9 +1332,12 @@ gen_jump(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1332
     return YJIT_END_BLOCK;
 }
 
-// Guard that recv_opnd has the same class as known_klass. Recompile as contingency if possible, or take side exit a last resort.
+/*
+Guard that a stack operand has the same class as known_klass.
+Recompile as contingency if possible, or take side exit a last resort.
+*/
 static bool
-jit_guard_known_klass(jitstate_t *jit, const ctx_t *recompile_context, VALUE known_klass, x86opnd_t recv_opnd, const int max_chain_depth, uint8_t *side_exit)
+jit_guard_known_klass(jitstate_t *jit, ctx_t* ctx, VALUE known_klass, uint32_t stack_idx, const int max_chain_depth, uint8_t *side_exit)
 {
     // Can't guard for for these classes because some of they are sometimes immediate (special const).
     // Can remove this by adding appropriate dynamic checks.
@@ -1341,7 +1350,10 @@ jit_guard_known_klass(jitstate_t *jit, const ctx_t *recompile_context, VALUE kno https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1350
         return false;
     }
 
+    val_type_t temp_type = ctx_get_temp_type(ctx, stack_idx);
+
     // Check that the receiver is a heap object
+    if (!temp_type.is_heap)
     {
         test(cb, REG0, imm_opnd(RUBY_IMMEDIATE_MASK));
         jnz_ptr(cb, side_exit);
@@ -1349,6 +1361,8 @@ jit_guard_known_klass(jitstate_t *jit, const ctx_t *recompile_context, VALUE kno https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1361
         je_ptr(cb, side_exit);
         cmp(cb, REG0, imm_opnd(Qnil));
         je_ptr(cb, side_exit);
+
+        ctx_set_temp_type(ctx, stack_idx, TYPE_HEAP);
     }
 
     // Pointer to the klass field of the receiver &(recv->klass)
@@ -1357,7 +1371,7 @@ jit_guard_known_klass(jitstate_t *jit, const ctx_t *recompile_context, VALUE kno https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1371
     // Bail if receiver class is different from compile-time call cache class
     jit_mov_gc_ptr(jit, cb, REG1, known_klass);
     cmp(cb, klass_opnd, REG1);
-    jit_chain_guard(JCC_JNE, jit, recompile_context, max_chain_depth, side_exit);
+    jit_chain_guard(JCC_JNE, jit, ctx, max_chain_depth, side_exit);
     return true;
 }
 
@@ -1759,7 +1773,7 @@ gen_opt_send_without_block(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1773
     // Points to the receiver operand on the stack
     x86opnd_t recv = ctx_stack_opnd(ctx, argc);
     mov(cb, REG0, recv);
-    if (!jit_guard_known_klass(jit, ctx, comptime_recv_klass, REG0, OSWB_MAX_DEPTH, side_exit)) {
+    if (!jit_guard_known_klass(jit, ctx, comptime_recv_klass, argc, OSWB_MAX_DEPTH, side_exit)) {
         return YJIT_CANT_COMPILE;
     }
 
diff --git a/yjit_core.c b/yjit_core.c
index 4d95fc1312..0a7e2c6442 100644
--- a/yjit_core.c
+++ b/yjit_core.c
@@ -145,13 +145,60 @@ ctx_get_temp_type(const ctx_t* ctx, size_t idx) https://github.com/ruby/ruby/blob/trunk/yjit_core.c#L145
 
     temp_mapping_t mapping = ctx->temp_mapping[ctx->stack_size - 1 - idx];
 
-    if (mapping.kind == TEMP_SELF)
+    switch (mapping.kind)
+    {
+        case TEMP_SELF:
         return ctx->self_type;
-    else if (mapping.kind == TEMP_STACK)
+
+        case TEMP_STACK:
         return ctx->temp_types[ctx->stack_size - 1 - idx];
 
-    RUBY_ASSERT(false);
-    return TYPE_UNKNOWN;
+        case TEMP_LOCAL:
+        RUBY_ASSERT(mapping.idx < MAX_LOCAL_TYPES);
+        return ctx->local_types[mapping.idx];
+    }
+
+    rb_bug("unreachable");
+}
+
+/**
+Set the type of a value in the temporary stack
+*/
+void ctx_set_temp_type(ctx_t* ctx, size_t idx, val_type_t type)
+{
+    RUBY_ASSERT(idx < ctx->stack_size);
+
+    if (ctx->stack_size > MAX_TEMP_TYPES)
+        return;
+
+    temp_mapping_t mapping = ctx->temp_mapping[ctx->stack_size - 1 - idx];
+
+    switch (mapping.kind)
+    {
+        case TEMP_SELF:
+        ctx->self_type = type;
+        break;
+
+        case TEMP_STACK:
+        ctx->temp_types[ctx->stack_size - 1 - idx] = type;
+        break;
+
+        case TEMP_LOCAL:
+        RUBY_ASSERT(mapping.idx < MAX_LOCAL_TYPES);
+        ctx->local_types[mapping.idx] = type;
+        break;
+    }
+}
+
+/**
+Set the type of a local variable
+*/
+void ctx_set_local_type(ctx_t* ctx, size_t idx, val_type_t type)
+{
+    if (ctx->stack_size > MAX_LOCAL_TYPES)
+        return;
+
+    ctx->local_types[idx] = type;
 }
 
 /*
diff --git a/yjit_core.h b/yjit_core.h
index cb47d013a9..7d7803566c 100644
--- a/yjit_core.h
+++ b/yjit_core.h
@@ -222,6 +222,8 @@ x86opnd_t ctx_stack_push_local(ctx_t* ctx, size_t local_idx); https://github.com/ruby/ruby/blob/trunk/yjit_core.h#L222
 x86opnd_t ctx_stack_pop(ctx_t* ctx, size_t n);
 x86opnd_t ctx_stack_opnd(ctx_t* ctx, int32_t idx);
 val_type_t ctx_get_temp_type(const ctx_t* ctx, size_t idx);
+void ctx_set_temp_type(ctx_t* ctx, size_t idx, val_type_t type);
+void ctx_set_local_type(ctx_t* ctx, size_t idx, val_type_t type);
 int ctx_diff(const ctx_t* src, const ctx_t* dst);
 
 block_t* find_block_version(blockid_t blockid, const ctx_t* ctx);
-- 
cgit v1.2.1


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

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