From b6f543d4aea38333521b8b2333c8ec675a3ebe8f Mon Sep 17 00:00:00 2001 From: John Hawthorn 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 --- yjit_codegen.c | 71 ++++++++++++++++++++++++++-------------------------------- 1 file changed, 32 insertions(+), 39 deletions(-) (limited to 'yjit_codegen.c') diff --git a/yjit_codegen.c b/yjit_codegen.c index 1076b48e8b..26362a7064 100644 --- a/yjit_codegen.c +++ b/yjit_codegen.c @@ -1139,56 +1139,55 @@ gen_newhash(jitstate_t *jit, ctx_t *ctx, codeblock_t *cb) 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) 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) // 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.3