ruby-changes:68711
From: Maxime <ko1@a...>
Date: Thu, 21 Oct 2021 08:12:31 +0900 (JST)
Subject: [ruby-changes:68711] 0a6e824ad2 (master): Prototype type-specialization for temp values
https://git.ruby-lang.org/ruby.git/commit/?id=0a6e824ad2 From 0a6e824ad2cc22315b32d1a11dc094c528b32acb Mon Sep 17 00:00:00 2001 From: Maxime Chevalier-Boisvert <maxime.chevalierboisvert@s...> Date: Wed, 20 Jan 2021 16:58:09 -0500 Subject: Prototype type-specialization for temp values --- ujit_codegen.c | 38 ++++++++++++++++++++++---------------- ujit_core.c | 39 ++++++++++++++++++++++++++++++++++++--- ujit_core.h | 6 ++---- 3 files changed, 60 insertions(+), 23 deletions(-) diff --git a/ujit_codegen.c b/ujit_codegen.c index 4e02e1f43f..488e4ca770 100644 --- a/ujit_codegen.c +++ b/ujit_codegen.c @@ -230,8 +230,8 @@ static bool https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L230 gen_dup(jitstate_t* jit, ctx_t* ctx) { x86opnd_t dup_val = ctx_stack_pop(ctx, 1); - x86opnd_t loc0 = ctx_stack_push(ctx, 1); - x86opnd_t loc1 = ctx_stack_push(ctx, 1); + x86opnd_t loc0 = ctx_stack_push(ctx, T_NONE); + x86opnd_t loc1 = ctx_stack_push(ctx, T_NONE); mov(cb, RAX, dup_val); mov(cb, loc0, RAX); mov(cb, loc1, RAX); @@ -257,7 +257,7 @@ static bool https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L257 gen_putnil(jitstate_t* jit, ctx_t* ctx) { // Write constant at SP - x86opnd_t stack_top = ctx_stack_push(ctx, 1); + x86opnd_t stack_top = ctx_stack_push(ctx, T_NIL); mov(cb, stack_top, imm_opnd(Qnil)); return true; } @@ -272,7 +272,7 @@ gen_putobject(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L272 mov(cb, RAX, mem_opnd(64, RAX, 8)); // One after the opcode // Write argument at SP - x86opnd_t stack_top = ctx_stack_push(ctx, 1); + x86opnd_t stack_top = ctx_stack_push(ctx, T_NONE); mov(cb, stack_top, RAX); return true; @@ -285,7 +285,7 @@ gen_putobject_int2fix(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L285 int cst_val = (opcode == BIN(putobject_INT2FIX_0_))? 0:1; // Write constant at SP - x86opnd_t stack_top = ctx_stack_push(ctx, 1); + x86opnd_t stack_top = ctx_stack_push(ctx, T_FIXNUM); mov(cb, stack_top, imm_opnd(INT2FIX(cst_val))); return true; @@ -298,7 +298,7 @@ gen_putself(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L298 mov(cb, RAX, member_opnd(REG_CFP, rb_control_frame_t, self)); // Write it on the stack - x86opnd_t stack_top = ctx_stack_push(ctx, 1); + x86opnd_t stack_top = ctx_stack_push(ctx, T_NONE); mov(cb, stack_top, RAX); return true; @@ -318,7 +318,7 @@ gen_getlocal_wc0(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L318 mov(cb, REG0, mem_opnd(64, REG0, offs)); // Write the local at SP - x86opnd_t stack_top = ctx_stack_push(ctx, 1); + x86opnd_t stack_top = ctx_stack_push(ctx, T_NONE); mov(cb, stack_top, REG0); return true; @@ -437,7 +437,7 @@ gen_getinstancevariable(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L437 je_ptr(cb, side_exit); // Push the ivar on the stack - x86opnd_t out_opnd = ctx_stack_push(ctx, 1); + x86opnd_t out_opnd = ctx_stack_push(ctx, T_NONE); mov(cb, out_opnd, REG0); return true; @@ -549,7 +549,7 @@ gen_opt_lt(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L549 cmovl(cb, REG0, REG1); // Push the output on the stack - x86opnd_t dst = ctx_stack_push(ctx, 1); + x86opnd_t dst = ctx_stack_push(ctx, T_NONE); mov(cb, dst, REG0); return true; @@ -589,7 +589,7 @@ gen_opt_minus(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L589 add(cb, REG0, imm_opnd(1)); // Push the output on the stack - x86opnd_t dst = ctx_stack_push(ctx, 1); + x86opnd_t dst = ctx_stack_push(ctx, T_NONE); mov(cb, dst, REG0); return true; @@ -613,14 +613,20 @@ gen_opt_plus(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L613 jnz_ptr(cb, side_exit); // Get the operands and destination from the stack + int arg1_type = ctx_get_top_type(ctx); x86opnd_t arg1 = ctx_stack_pop(ctx, 1); + int arg0_type = ctx_get_top_type(ctx); x86opnd_t arg0 = ctx_stack_pop(ctx, 1); // If not fixnums, fall back - test(cb, arg0, imm_opnd(RUBY_FIXNUM_FLAG)); - jz_ptr(cb, side_exit); - test(cb, arg1, imm_opnd(RUBY_FIXNUM_FLAG)); - jz_ptr(cb, side_exit); + if (arg0_type != T_FIXNUM) { + test(cb, arg0, imm_opnd(RUBY_FIXNUM_FLAG)); + jz_ptr(cb, side_exit); + } + if (arg1_type != T_FIXNUM) { + test(cb, arg1, imm_opnd(RUBY_FIXNUM_FLAG)); + jz_ptr(cb, side_exit); + } // Add arg0 + arg1 and test for overflow mov(cb, REG0, arg0); @@ -629,7 +635,7 @@ gen_opt_plus(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L635 jo_ptr(cb, side_exit); // Push the output on the stack - x86opnd_t dst = ctx_stack_push(ctx, 1); + x86opnd_t dst = ctx_stack_push(ctx, T_NONE); mov(cb, dst, REG0); return true; @@ -938,7 +944,7 @@ gen_opt_send_without_block(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/ujit_codegen.c#L944 pop(cb, REG_CFP); // Push the return value on the Ruby stack - x86opnd_t stack_ret = ctx_stack_push(ctx, 1); + x86opnd_t stack_ret = ctx_stack_push(ctx, T_NONE); mov(cb, stack_ret, RAX); // If this function needs a Ruby stack frame diff --git a/ujit_core.c b/ujit_core.c index 2ca4550a71..aaaf56d3b3 100644 --- a/ujit_core.c +++ b/ujit_core.c @@ -31,13 +31,18 @@ ctx_sp_opnd(ctx_t* ctx, int32_t offset_bytes) https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L31 } /* -Make space on the stack for N values +Push one new value on the temp stack Return a pointer to the new stack top */ x86opnd_t -ctx_stack_push(ctx_t* ctx, size_t n) +ctx_stack_push(ctx_t* ctx, int type) { - ctx->stack_size += n; + // Keep track of the type of the value + RUBY_ASSERT(type <= RUBY_T_MASK); + if (ctx->stack_size < MAX_TEMP_TYPES) + ctx->temp_types[ctx->stack_size] = type; + + ctx->stack_size += 1; // SP points just above the topmost value int32_t offset = (ctx->stack_size - 1) * 8; @@ -51,15 +56,28 @@ Return a pointer to the stack top before the pop operation https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L56 x86opnd_t ctx_stack_pop(ctx_t* ctx, size_t n) { + RUBY_ASSERT(n <= ctx->stack_size); + // SP points just above the topmost value int32_t offset = (ctx->stack_size - 1) * 8; x86opnd_t top = mem_opnd(64, REG_SP, offset); + // Clear the types of the popped values + for (size_t i = 0; i < n; ++i) + { + size_t idx = ctx->stack_size - i - 1; + if (idx < MAX_TEMP_TYPES) + ctx->temp_types[idx] = T_NONE; + } + ctx->stack_size -= n; return top; } +/** +Get an operand pointing to a slot on the temp stack +*/ x86opnd_t ctx_stack_opnd(ctx_t* ctx, int32_t idx) { @@ -70,6 +88,21 @@ ctx_stack_opnd(ctx_t* ctx, int32_t idx) https://github.com/ruby/ruby/blob/trunk/ujit_core.c#L88 return opnd; } +/** +Get the type of the topmost value on the temp stack +Returns T_NONE if unknown +*/ +int +ctx_get_top_type(ctx_t* ctx) +{ + RUBY_ASSERT(n <= ctx->stack_size); + + if (ctx->stack_size > MAX_TEMP_TYPES) + return T_NONE; + + return ctx->temp_types[ctx->stack_size - 1]; +} + // Add an incoming branch for a given block version static void add_incoming(block_t* p_block, uint32_t branch_idx) { diff --git a/ujit_core.h b/ujit_core.h index dc94cd2873..5438cd850e 100644 --- a/ujit_core.h +++ b/ujit_core.h @@ -112,13 +112,11 @@ typedef struct BlockVersion https://github.com/ruby/ruby/blob/trunk/ujit_core.h#L112 } block_t; // Context object methods -int ctx_get_opcode(ctx_t *ctx); -uint32_t ctx_next_idx(ctx_t* ctx); -VALUE ctx_get_arg(ctx_t* ctx, size_t arg_idx); x86opnd_t ctx_sp_opnd(ctx_t* ctx, int32_t offset_bytes); -x86opnd_t ctx_stack_push(ctx_t* ctx, size_t n); +x86opnd_t ctx_stack_push(ctx_t* ctx, int type); x86opnd_t ctx_stack_pop(ctx_t* ctx, size_t n); x86opnd_t ctx_stack_opnd(ctx_t* ctx, int32_t idx); +int ctx_get_top_type(ctx_t* ctx); block_t* find_block_version(blockid_t blockid, const ctx_t* ctx); block_t* gen_block_version(blockid_t blockid, const ctx_t* ctx); -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/