@@ -896,6 +896,34 @@ gen_setinstancevariable(jitstate_t* jit, ctx_t* ctx)
896
896
return YJIT_KEEP_COMPILING ;
897
897
}
898
898
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
+
899
927
// Conditional move operation used by comparison operators
900
928
typedef void (* cmov_fn )(codeblock_t * cb , x86opnd_t opnd0 , x86opnd_t opnd1 );
901
929
@@ -910,22 +938,13 @@ gen_fixnum_cmp(jitstate_t* jit, ctx_t* ctx, cmov_fn cmov_op)
910
938
return YJIT_CANT_COMPILE ;
911
939
}
912
940
941
+ // Check that both operands are fixnums
942
+ guard_two_fixnums (ctx , side_exit );
943
+
913
944
// Get the operands and destination from the stack
914
- val_type_t arg1_type = ctx_get_opnd_type (ctx , OPND_STACK (0 ));
915
945
x86opnd_t arg1 = ctx_stack_pop (ctx , 1 );
916
- val_type_t arg0_type = ctx_get_opnd_type (ctx , OPND_STACK (0 ));
917
946
x86opnd_t arg0 = ctx_stack_pop (ctx , 1 );
918
947
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
-
929
948
// Compare the arguments
930
949
xor (cb , REG0_32 , REG0_32 ); // REG0 = Qfalse
931
950
mov (cb , REG1 , arg0 );
@@ -1120,22 +1139,13 @@ gen_opt_and(jitstate_t* jit, ctx_t* ctx)
1120
1139
return YJIT_CANT_COMPILE ;
1121
1140
}
1122
1141
1142
+ // Check that both operands are fixnums
1143
+ guard_two_fixnums (ctx , side_exit );
1144
+
1123
1145
// Get the operands and destination from the stack
1124
- val_type_t arg1_type = ctx_get_opnd_type (ctx , OPND_STACK (0 ));
1125
1146
x86opnd_t arg1 = ctx_stack_pop (ctx , 1 );
1126
- val_type_t arg0_type = ctx_get_opnd_type (ctx , OPND_STACK (0 ));
1127
1147
x86opnd_t arg0 = ctx_stack_pop (ctx , 1 );
1128
1148
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
-
1139
1149
// Do the bitwise and arg0 & arg1
1140
1150
mov (cb , REG0 , arg0 );
1141
1151
and (cb , REG0 , arg1 );
@@ -1148,32 +1158,52 @@ gen_opt_and(jitstate_t* jit, ctx_t* ctx)
1148
1158
}
1149
1159
1150
1160
static codegen_status_t
1151
- gen_opt_minus (jitstate_t * jit , ctx_t * ctx )
1161
+ gen_opt_or (jitstate_t * jit , ctx_t * ctx )
1152
1162
{
1153
1163
// Create a size-exit to fall back to the interpreter
1154
1164
// Note: we generate the side-exit before popping operands from the stack
1155
1165
uint8_t * side_exit = yjit_side_exit (jit , ctx );
1156
1166
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 )) {
1158
1168
return YJIT_CANT_COMPILE ;
1159
1169
}
1160
1170
1171
+ // Check that both operands are fixnums
1172
+ guard_two_fixnums (ctx , side_exit );
1173
+
1161
1174
// Get the operands and destination from the stack
1162
- val_type_t arg1_type = ctx_get_opnd_type (ctx , OPND_STACK (0 ));
1163
1175
x86opnd_t arg1 = ctx_stack_pop (ctx , 1 );
1164
- val_type_t arg0_type = ctx_get_opnd_type (ctx , OPND_STACK (0 ));
1165
1176
x86opnd_t arg0 = ctx_stack_pop (ctx , 1 );
1166
1177
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 ;
1175
1198
}
1176
1199
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
+
1177
1207
// Subtract arg0 - arg1 and test for overflow
1178
1208
mov (cb , REG0 , arg0 );
1179
1209
sub (cb , REG0 , arg1 );
@@ -1198,22 +1228,13 @@ gen_opt_plus(jitstate_t* jit, ctx_t* ctx)
1198
1228
return YJIT_CANT_COMPILE ;
1199
1229
}
1200
1230
1231
+ // Check that both operands are fixnums
1232
+ guard_two_fixnums (ctx , side_exit );
1233
+
1201
1234
// Get the operands and destination from the stack
1202
- val_type_t arg1_type = ctx_get_opnd_type (ctx , OPND_STACK (0 ));
1203
1235
x86opnd_t arg1 = ctx_stack_pop (ctx , 1 );
1204
- val_type_t arg0_type = ctx_get_opnd_type (ctx , OPND_STACK (0 ));
1205
1236
x86opnd_t arg0 = ctx_stack_pop (ctx , 1 );
1206
1237
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
-
1217
1238
// Add arg0 + arg1 and test for overflow
1218
1239
mov (cb , REG0 , arg0 );
1219
1240
sub (cb , REG0 , imm_opnd (1 ));
@@ -2006,6 +2027,7 @@ yjit_init_codegen(void)
2006
2027
yjit_reg_op (BIN (opt_gt ), gen_opt_gt );
2007
2028
yjit_reg_op (BIN (opt_aref ), gen_opt_aref );
2008
2029
yjit_reg_op (BIN (opt_and ), gen_opt_and );
2030
+ yjit_reg_op (BIN (opt_or ), gen_opt_or );
2009
2031
yjit_reg_op (BIN (opt_minus ), gen_opt_minus );
2010
2032
yjit_reg_op (BIN (opt_plus ), gen_opt_plus );
2011
2033
yjit_reg_op (BIN (opt_getinlinecache ), gen_opt_getinlinecache );
0 commit comments