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

ruby-changes:69943

From: John <ko1@a...>
Date: Fri, 26 Nov 2021 08:10:57 +0900 (JST)
Subject: [ruby-changes:69943] b6f543d4ae (master): YJIT: Introduce jit_putobject (#5179)

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

From b6f543d4aea38333521b8b2333c8ec675a3ebe8f Mon Sep 17 00:00:00 2001
From: John Hawthorn <john@h...>
Date: Thu, 25 Nov 2021 15:10:42 -0800
Subject: YJIT: Introduce jit_putobject (#5179)

* YJIT: Introduce jit_putobject

This extracts the logic previously inside gen_putobject to a more
reusable helper method jit_putobject.

The motivation for this is that it both simplifies the implementation of
other instructions, and other instructions can reuse the optimized
behaviour for 32-bit special constants (most importantly
opt_getinlinecache).

This commit also expands the optimization to use a mov directly to
memory when we encounter a 32-bit immediate constant. Previously it
covered fixnums and Qtrue/Qfalse, now it will cover any SPECIAL_CONST_P
value which can be represented as a 32-bit immediate. Notably, this
includes static symbols, and Qnil.

* Style touchups and a comment

* delete empty line

Co-authored-by: Alan Wu <XrXr@u...>
---
 yjit_codegen.c | 71 ++++++++++++++++++++++++++--------------------------------
 1 file changed, 32 insertions(+), 39 deletions(-)

diff --git a/yjit_codegen.c b/yjit_codegen.c
index 1076b48e8bf..26362a7064f 100644
--- a/yjit_codegen.c
+++ b/yjit_codegen.c
@@ -1139,56 +1139,55 @@ gen_newhash(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1139
     return YJIT_KEEP_COMPILING;
 }
 
-static codegen_status_t
-gen_putnil(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
+// Push a constant value to the stack, including type information.
+// The constant may be a heap object or a special constant.
+static void
+jit_putobject(jitstate_t *jit, ctx_t *ctx, VALUE arg)
 {
-    // Write constant at SP
-    x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_NIL);
-    mov(cb, stack_top, imm_opnd(Qnil));
-    return YJIT_KEEP_COMPILING;
-}
+    val_type_t val_type = yjit_type_of_value(arg);
+    x86opnd_t stack_top = ctx_stack_push(ctx, val_type);
 
-static codegen_status_t
-gen_putobject(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
-{
-    VALUE arg = jit_get_arg(jit, 0);
+    if (SPECIAL_CONST_P(arg)) {
+        // Immediates will not move and do not need to be tracked for GC
+        // Thanks to this we can mov directly to memory when possible.
 
-    if (FIXNUM_P(arg))
-    {
-        // Keep track of the fixnum type tag
-        x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_FIXNUM);
+        // NOTE: VALUE -> int64_t cast below is implementation defined.
+        // Hopefully it preserves the the bit pattern or raise a signal.
+        // See N1256 section 6.3.1.3.
         x86opnd_t imm = imm_opnd((int64_t)arg);
 
         // 64-bit immediates can't be directly written to memory
-        if (imm.num_bits <= 32)
-        {
+        if (imm.num_bits <= 32) {
             mov(cb, stack_top, imm);
         }
-        else
-        {
+        else {
             mov(cb, REG0, imm);
             mov(cb, stack_top, REG0);
         }
     }
-    else if (arg == Qtrue || arg == Qfalse)
-    {
-        x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_IMM);
-        mov(cb, stack_top, imm_opnd((int64_t)arg));
-    }
-    else
-    {
+    else {
         // Load the value to push into REG0
         // Note that this value may get moved by the GC
-        VALUE put_val = jit_get_arg(jit, 0);
-        jit_mov_gc_ptr(jit, cb, REG0, put_val);
-
-        val_type_t val_type = yjit_type_of_value(put_val);
+        jit_mov_gc_ptr(jit, cb, REG0, arg);
 
         // Write argument at SP
-        x86opnd_t stack_top = ctx_stack_push(ctx, val_type);
         mov(cb, stack_top, REG0);
     }
+}
+
+static codegen_status_t
+gen_putnil(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
+{
+    jit_putobject(jit, ctx, Qnil);
+    return YJIT_KEEP_COMPILING;
+}
+
+static codegen_status_t
+gen_putobject(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb)
+{
+    VALUE arg = jit_get_arg(jit, 0);
 
+    jit_putobject(jit, ctx, arg);
     return YJIT_KEEP_COMPILING;
 }
 
@@ -1216,10 +1215,7 @@ gen_putobject_int2fix(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L1215
     int opcode = jit_get_opcode(jit);
     int cst_val = (opcode == BIN(putobject_INT2FIX_0_))? 0:1;
 
-    // Write constant at SP
-    x86opnd_t stack_top = ctx_stack_push(ctx, TYPE_FIXNUM);
-    mov(cb, stack_top, imm_opnd(INT2FIX(cst_val)));
-
+    jit_putobject(jit, ctx, INT2FIX(cst_val));
     return YJIT_KEEP_COMPILING;
 }
 
@@ -4653,10 +4649,7 @@ gen_opt_getinlinecache(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L4649
         // FIXME: This leaks when st_insert raises NoMemoryError
         assume_stable_global_constant_state(jit);
 
-        val_type_t type = yjit_type_of_value(ice->value);
-        x86opnd_t stack_top = ctx_stack_push(ctx, type);
-        jit_mov_gc_ptr(jit, cb, REG0, ice->value);
-        mov(cb, stack_top, REG0);
+        jit_putobject(jit, ctx, ice->value);
     }
 
     // Jump over the code for filling the cache
-- 
cgit v1.2.1


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

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