@@ -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
900928typedef 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
11501160static 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 );
0 commit comments