Skip to content

Commit 68d8f61

Browse files
authored
Merge pull request ruby#107 from Shopify/yjit-guard-fixnums
YJIT: Factor our guard_two_fixnums(). Implement opt_or.
2 parents 742a8c0 + 5d45358 commit 68d8f61

File tree

2 files changed

+73
-51
lines changed

2 files changed

+73
-51
lines changed

yjit_codegen.c

Lines changed: 70 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,34 @@ gen_setinstancevariable(jitstate_t* jit, ctx_t* ctx)
896896
return YJIT_KEEP_COMPILING;
897897
}
898898

899+
static void
900+
guard_two_fixnums(ctx_t* ctx, uint8_t* side_exit)
901+
{
902+
// Get the stack operand types
903+
val_type_t arg1_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
904+
val_type_t arg0_type = ctx_get_opnd_type(ctx, OPND_STACK(1));
905+
906+
// Get stack operands without popping them
907+
x86opnd_t arg1 = ctx_stack_opnd(ctx, 0);
908+
x86opnd_t arg0 = ctx_stack_opnd(ctx, 1);
909+
910+
// If not fixnums, fall back
911+
if (arg0_type.type != ETYPE_FIXNUM) {
912+
ADD_COMMENT(cb, "guard arg0 fixnum");
913+
test(cb, arg0, imm_opnd(RUBY_FIXNUM_FLAG));
914+
jz_ptr(cb, side_exit);
915+
}
916+
if (arg1_type.type != ETYPE_FIXNUM) {
917+
ADD_COMMENT(cb, "guard arg1 fixnum");
918+
test(cb, arg1, imm_opnd(RUBY_FIXNUM_FLAG));
919+
jz_ptr(cb, side_exit);
920+
}
921+
922+
// Set stack types in context
923+
ctx_set_opnd_type(ctx, OPND_STACK(0), TYPE_FIXNUM);
924+
ctx_set_opnd_type(ctx, OPND_STACK(1), TYPE_FIXNUM);
925+
}
926+
899927
// Conditional move operation used by comparison operators
900928
typedef void (*cmov_fn)(codeblock_t* cb, x86opnd_t opnd0, x86opnd_t opnd1);
901929

@@ -910,22 +938,13 @@ gen_fixnum_cmp(jitstate_t* jit, ctx_t* ctx, cmov_fn cmov_op)
910938
return YJIT_CANT_COMPILE;
911939
}
912940

941+
// Check that both operands are fixnums
942+
guard_two_fixnums(ctx, side_exit);
943+
913944
// Get the operands and destination from the stack
914-
val_type_t arg1_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
915945
x86opnd_t arg1 = ctx_stack_pop(ctx, 1);
916-
val_type_t arg0_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
917946
x86opnd_t arg0 = ctx_stack_pop(ctx, 1);
918947

919-
// If not fixnums, fall back
920-
if (arg0_type.type != ETYPE_FIXNUM) {
921-
test(cb, arg0, imm_opnd(RUBY_FIXNUM_FLAG));
922-
jz_ptr(cb, side_exit);
923-
}
924-
if (arg1_type.type != ETYPE_FIXNUM) {
925-
test(cb, arg1, imm_opnd(RUBY_FIXNUM_FLAG));
926-
jz_ptr(cb, side_exit);
927-
}
928-
929948
// Compare the arguments
930949
xor(cb, REG0_32, REG0_32); // REG0 = Qfalse
931950
mov(cb, REG1, arg0);
@@ -1120,22 +1139,13 @@ gen_opt_and(jitstate_t* jit, ctx_t* ctx)
11201139
return YJIT_CANT_COMPILE;
11211140
}
11221141

1142+
// Check that both operands are fixnums
1143+
guard_two_fixnums(ctx, side_exit);
1144+
11231145
// Get the operands and destination from the stack
1124-
val_type_t arg1_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
11251146
x86opnd_t arg1 = ctx_stack_pop(ctx, 1);
1126-
val_type_t arg0_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
11271147
x86opnd_t arg0 = ctx_stack_pop(ctx, 1);
11281148

1129-
// If not fixnums, fall back
1130-
if (arg0_type.type != ETYPE_FIXNUM) {
1131-
test(cb, arg0, imm_opnd(RUBY_FIXNUM_FLAG));
1132-
jz_ptr(cb, side_exit);
1133-
}
1134-
if (arg1_type.type != ETYPE_FIXNUM) {
1135-
test(cb, arg1, imm_opnd(RUBY_FIXNUM_FLAG));
1136-
jz_ptr(cb, side_exit);
1137-
}
1138-
11391149
// Do the bitwise and arg0 & arg1
11401150
mov(cb, REG0, arg0);
11411151
and(cb, REG0, arg1);
@@ -1148,32 +1158,52 @@ gen_opt_and(jitstate_t* jit, ctx_t* ctx)
11481158
}
11491159

11501160
static codegen_status_t
1151-
gen_opt_minus(jitstate_t* jit, ctx_t* ctx)
1161+
gen_opt_or(jitstate_t* jit, ctx_t* ctx)
11521162
{
11531163
// Create a size-exit to fall back to the interpreter
11541164
// Note: we generate the side-exit before popping operands from the stack
11551165
uint8_t* side_exit = yjit_side_exit(jit, ctx);
11561166

1157-
if (!assume_bop_not_redefined(jit->block, INTEGER_REDEFINED_OP_FLAG, BOP_MINUS)) {
1167+
if (!assume_bop_not_redefined(jit->block, INTEGER_REDEFINED_OP_FLAG, BOP_OR)) {
11581168
return YJIT_CANT_COMPILE;
11591169
}
11601170

1171+
// Check that both operands are fixnums
1172+
guard_two_fixnums(ctx, side_exit);
1173+
11611174
// Get the operands and destination from the stack
1162-
val_type_t arg1_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
11631175
x86opnd_t arg1 = ctx_stack_pop(ctx, 1);
1164-
val_type_t arg0_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
11651176
x86opnd_t arg0 = ctx_stack_pop(ctx, 1);
11661177

1167-
// If not fixnums, fall back
1168-
if (arg0_type.type != ETYPE_FIXNUM) {
1169-
test(cb, arg0, imm_opnd(RUBY_FIXNUM_FLAG));
1170-
jz_ptr(cb, side_exit);
1171-
}
1172-
if (arg1_type.type != ETYPE_FIXNUM) {
1173-
test(cb, arg1, imm_opnd(RUBY_FIXNUM_FLAG));
1174-
jz_ptr(cb, side_exit);
1178+
// Do the bitwise or arg0 | arg1
1179+
mov(cb, REG0, arg0);
1180+
or(cb, REG0, arg1);
1181+
1182+
// Push the output on the stack
1183+
x86opnd_t dst = ctx_stack_push(ctx, TYPE_FIXNUM);
1184+
mov(cb, dst, REG0);
1185+
1186+
return YJIT_KEEP_COMPILING;
1187+
}
1188+
1189+
static codegen_status_t
1190+
gen_opt_minus(jitstate_t* jit, ctx_t* ctx)
1191+
{
1192+
// Create a size-exit to fall back to the interpreter
1193+
// Note: we generate the side-exit before popping operands from the stack
1194+
uint8_t* side_exit = yjit_side_exit(jit, ctx);
1195+
1196+
if (!assume_bop_not_redefined(jit->block, INTEGER_REDEFINED_OP_FLAG, BOP_MINUS)) {
1197+
return YJIT_CANT_COMPILE;
11751198
}
11761199

1200+
// Check that both operands are fixnums
1201+
guard_two_fixnums(ctx, side_exit);
1202+
1203+
// Get the operands and destination from the stack
1204+
x86opnd_t arg1 = ctx_stack_pop(ctx, 1);
1205+
x86opnd_t arg0 = ctx_stack_pop(ctx, 1);
1206+
11771207
// Subtract arg0 - arg1 and test for overflow
11781208
mov(cb, REG0, arg0);
11791209
sub(cb, REG0, arg1);
@@ -1198,22 +1228,13 @@ gen_opt_plus(jitstate_t* jit, ctx_t* ctx)
11981228
return YJIT_CANT_COMPILE;
11991229
}
12001230

1231+
// Check that both operands are fixnums
1232+
guard_two_fixnums(ctx, side_exit);
1233+
12011234
// Get the operands and destination from the stack
1202-
val_type_t arg1_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
12031235
x86opnd_t arg1 = ctx_stack_pop(ctx, 1);
1204-
val_type_t arg0_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
12051236
x86opnd_t arg0 = ctx_stack_pop(ctx, 1);
12061237

1207-
// If not fixnums, fall back
1208-
if (arg0_type.type != ETYPE_FIXNUM) {
1209-
test(cb, arg0, imm_opnd(RUBY_FIXNUM_FLAG));
1210-
jz_ptr(cb, side_exit);
1211-
}
1212-
if (arg1_type.type != ETYPE_FIXNUM) {
1213-
test(cb, arg1, imm_opnd(RUBY_FIXNUM_FLAG));
1214-
jz_ptr(cb, side_exit);
1215-
}
1216-
12171238
// Add arg0 + arg1 and test for overflow
12181239
mov(cb, REG0, arg0);
12191240
sub(cb, REG0, imm_opnd(1));
@@ -2006,6 +2027,7 @@ yjit_init_codegen(void)
20062027
yjit_reg_op(BIN(opt_gt), gen_opt_gt);
20072028
yjit_reg_op(BIN(opt_aref), gen_opt_aref);
20082029
yjit_reg_op(BIN(opt_and), gen_opt_and);
2030+
yjit_reg_op(BIN(opt_or), gen_opt_or);
20092031
yjit_reg_op(BIN(opt_minus), gen_opt_minus);
20102032
yjit_reg_op(BIN(opt_plus), gen_opt_plus);
20112033
yjit_reg_op(BIN(opt_getinlinecache), gen_opt_getinlinecache);

yjit_core.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -653,7 +653,7 @@ void gen_branch(
653653
{
654654
RUBY_ASSERT(target0.iseq != NULL);
655655
//RUBY_ASSERT(target1.iseq != NULL);
656-
RUBY_ASSERT(num_branches < MAX_BRANCHES);
656+
RUBY_ASSERT_ALWAYS(num_branches < MAX_BRANCHES);
657657
uint32_t branch_idx = num_branches++;
658658

659659
// Get the branch targets or stubs
@@ -704,7 +704,7 @@ void gen_direct_jump(
704704
)
705705
{
706706
RUBY_ASSERT(target0.iseq != NULL);
707-
RUBY_ASSERT(num_branches < MAX_BRANCHES);
707+
RUBY_ASSERT_ALWAYS(num_branches < MAX_BRANCHES);
708708
ctx_t generic_ctx;
709709
uint32_t branch_idx = num_branches++;
710710

@@ -788,7 +788,7 @@ void defer_compilation(
788788

789789
next_ctx.chain_depth += 1;
790790

791-
RUBY_ASSERT(num_branches < MAX_BRANCHES);
791+
RUBY_ASSERT_ALWAYS(num_branches < MAX_BRANCHES);
792792
uint32_t branch_idx = num_branches++;
793793

794794
// Get the branch targets or stubs

0 commit comments

Comments
 (0)