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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy