ruby-changes:69144
From: John <ko1@a...>
Date: Thu, 21 Oct 2021 08:20:59 +0900 (JST)
Subject: [ruby-changes:69144] cb9bc13fcb (master): Check for comptime integers in opt_plus and opt_minus
https://git.ruby-lang.org/ruby.git/commit/?id=cb9bc13fcb From cb9bc13fcb2f78513338aa463aaf7544ebbfbfba Mon Sep 17 00:00:00 2001 From: John Hawthorn <john@h...> Date: Mon, 13 Sep 2021 19:21:26 -0700 Subject: Check for comptime integers in opt_plus and opt_minus --- yjit_codegen.c | 108 ++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 40 deletions(-) diff --git a/yjit_codegen.c b/yjit_codegen.c index 6bcf5c3fb5..b2cd49f69c 100644 --- a/yjit_codegen.c +++ b/yjit_codegen.c @@ -2264,63 +2264,91 @@ gen_opt_or(jitstate_t* jit, ctx_t* ctx) https://github.com/ruby/ruby/blob/trunk/yjit_codegen.c#L2264 static codegen_status_t gen_opt_minus(jitstate_t* jit, ctx_t* ctx) { - // Create a size-exit to fall back to the interpreter - // Note: we generate the side-exit before popping operands from the stack - uint8_t* side_exit = yjit_side_exit(jit, ctx); - - if (!assume_bop_not_redefined(jit->block, INTEGER_REDEFINED_OP_FLAG, BOP_MINUS)) { - return YJIT_CANT_COMPILE; + // Defer compilation so we can specialize on a runtime `self` + if (!jit_at_current_insn(jit)) { + defer_compilation(jit->block, jit->insn_idx, ctx); + return YJIT_END_BLOCK; } - // Check that both operands are fixnums - guard_two_fixnums(ctx, side_exit); + VALUE comptime_a = jit_peek_at_stack(jit, ctx, 1); + VALUE comptime_b = jit_peek_at_stack(jit, ctx, 0); - // Get the operands and destination from the stack - x86opnd_t arg1 = ctx_stack_pop(ctx, 1); - x86opnd_t arg0 = ctx_stack_pop(ctx, 1); + if (FIXNUM_P(comptime_a) && FIXNUM_P(comptime_b)) { + // Create a size-exit to fall back to the interpreter + // Note: we generate the side-exit before popping operands from the stack + uint8_t* side_exit = yjit_side_exit(jit, ctx); - // Subtract arg0 - arg1 and test for overflow - mov(cb, REG0, arg0); - sub(cb, REG0, arg1); - jo_ptr(cb, side_exit); - add(cb, REG0, imm_opnd(1)); + if (!assume_bop_not_redefined(jit->block, INTEGER_REDEFINED_OP_FLAG, BOP_MINUS)) { + return YJIT_CANT_COMPILE; + } - // Push the output on the stack - x86opnd_t dst = ctx_stack_push(ctx, TYPE_FIXNUM); - mov(cb, dst, REG0); + // Check that both operands are fixnums + guard_two_fixnums(ctx, side_exit); - return YJIT_KEEP_COMPILING; + // Get the operands and destination from the stack + x86opnd_t arg1 = ctx_stack_pop(ctx, 1); + x86opnd_t arg0 = ctx_stack_pop(ctx, 1); + + // Subtract arg0 - arg1 and test for overflow + mov(cb, REG0, arg0); + sub(cb, REG0, arg1); + jo_ptr(cb, side_exit); + add(cb, REG0, imm_opnd(1)); + + // Push the output on the stack + x86opnd_t dst = ctx_stack_push(ctx, TYPE_FIXNUM); + mov(cb, dst, REG0); + + return YJIT_KEEP_COMPILING; + } else { + // Delegate to send, call the method on the recv + return gen_opt_send_without_block(jit, ctx); + } } static codegen_status_t gen_opt_plus(jitstate_t* jit, ctx_t* ctx) { - // Create a size-exit to fall back to the interpreter - // Note: we generate the side-exit before popping operands from the stack - uint8_t* side_exit = yjit_side_exit(jit, ctx); - - if (!assume_bop_not_redefined(jit->block, INTEGER_REDEFINED_OP_FLAG, BOP_PLUS)) { - return YJIT_CANT_COMPILE; + // Defer compilation so we can specialize on a runtime `self` + if (!jit_at_current_insn(jit)) { + defer_compilation(jit->block, jit->insn_idx, ctx); + return YJIT_END_BLOCK; } - // Check that both operands are fixnums - guard_two_fixnums(ctx, side_exit); + VALUE comptime_a = jit_peek_at_stack(jit, ctx, 1); + VALUE comptime_b = jit_peek_at_stack(jit, ctx, 0); - // Get the operands and destination from the stack - x86opnd_t arg1 = ctx_stack_pop(ctx, 1); - x86opnd_t arg0 = ctx_stack_pop(ctx, 1); + if (FIXNUM_P(comptime_a) && FIXNUM_P(comptime_b)) { + // Create a size-exit to fall back to the interpreter + // Note: we generate the side-exit before popping operands from the stack + uint8_t* side_exit = yjit_side_exit(jit, ctx); - // Add arg0 + arg1 and test for overflow - mov(cb, REG0, arg0); - sub(cb, REG0, imm_opnd(1)); - add(cb, REG0, arg1); - jo_ptr(cb, side_exit); + if (!assume_bop_not_redefined(jit->block, INTEGER_REDEFINED_OP_FLAG, BOP_PLUS)) { + return YJIT_CANT_COMPILE; + } - // Push the output on the stack - x86opnd_t dst = ctx_stack_push(ctx, TYPE_FIXNUM); - mov(cb, dst, REG0); + // Check that both operands are fixnums + guard_two_fixnums(ctx, side_exit); - return YJIT_KEEP_COMPILING; + // Get the operands and destination from the stack + x86opnd_t arg1 = ctx_stack_pop(ctx, 1); + x86opnd_t arg0 = ctx_stack_pop(ctx, 1); + + // Add arg0 + arg1 and test for overflow + mov(cb, REG0, arg0); + sub(cb, REG0, imm_opnd(1)); + add(cb, REG0, arg1); + jo_ptr(cb, side_exit); + + // Push the output on the stack + x86opnd_t dst = ctx_stack_push(ctx, TYPE_FIXNUM); + mov(cb, dst, REG0); + + return YJIT_KEEP_COMPILING; + } else { + // Delegate to send, call the method on the recv + return gen_opt_send_without_block(jit, ctx); + } } static codegen_status_t -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/