@@ -1193,6 +1193,22 @@ gen_putspecialobject(jitstate_t* jit, ctx_t* ctx)
1193
1193
}
1194
1194
}
1195
1195
1196
+ // Get EP at level from CFP
1197
+ static void
1198
+ gen_get_ep (codeblock_t * cb , x86opnd_t reg , uint32_t level )
1199
+ {
1200
+ // Load environment pointer EP from CFP
1201
+ mov (cb , reg , member_opnd (REG_CFP , rb_control_frame_t , ep ));
1202
+
1203
+ while (level -- ) {
1204
+ // Get the previous EP from the current EP
1205
+ // See GET_PREV_EP(ep) macro
1206
+ // VALUE* prev_ep = ((VALUE *)((ep)[VM_ENV_DATA_INDEX_SPECVAL] & ~0x03))
1207
+ mov (cb , reg , mem_opnd (64 , REG0 , SIZEOF_VALUE * VM_ENV_DATA_INDEX_SPECVAL ));
1208
+ and (cb , reg , imm_opnd (~0x03 ));
1209
+ }
1210
+ }
1211
+
1196
1212
// Compute the index of a local variable from its slot index
1197
1213
static uint32_t
1198
1214
slot_to_local_idx (const rb_iseq_t * iseq , int32_t slot_idx )
@@ -1213,8 +1229,8 @@ gen_getlocal_wc0(jitstate_t* jit, ctx_t* ctx)
1213
1229
const int32_t offs = - (SIZEOF_VALUE * slot_idx );
1214
1230
uint32_t local_idx = slot_to_local_idx (jit -> iseq , slot_idx );
1215
1231
1216
- // Load environment pointer EP from CFP
1217
- mov (cb , REG0 , member_opnd ( REG_CFP , rb_control_frame_t , ep ) );
1232
+ // Load environment pointer EP (level 0) from CFP
1233
+ gen_get_ep (cb , REG0 , 0 );
1218
1234
1219
1235
// Load the local from the EP
1220
1236
mov (cb , REG0 , mem_opnd (64 , REG0 , offs ));
@@ -1229,16 +1245,7 @@ gen_getlocal_wc0(jitstate_t* jit, ctx_t* ctx)
1229
1245
static codegen_status_t
1230
1246
gen_getlocal_generic (ctx_t * ctx , uint32_t local_idx , uint32_t level )
1231
1247
{
1232
- // Load environment pointer EP from CFP
1233
- mov (cb , REG0 , member_opnd (REG_CFP , rb_control_frame_t , ep ));
1234
-
1235
- while (level -- ) {
1236
- // Get the previous EP from the current EP
1237
- // See GET_PREV_EP(ep) macro
1238
- // VALUE* prev_ep = ((VALUE *)((ep)[VM_ENV_DATA_INDEX_SPECVAL] & ~0x03))
1239
- mov (cb , REG0 , mem_opnd (64 , REG0 , SIZEOF_VALUE * VM_ENV_DATA_INDEX_SPECVAL ));
1240
- and (cb , REG0 , imm_opnd (~0x03 ));
1241
- }
1248
+ gen_get_ep (cb , REG0 , level );
1242
1249
1243
1250
// Load the local from the block
1244
1251
// val = *(vm_get_ep(GET_EP(), level) - idx);
@@ -1286,8 +1293,8 @@ gen_setlocal_wc0(jitstate_t* jit, ctx_t* ctx)
1286
1293
int32_t slot_idx = (int32_t )jit_get_arg (jit , 0 );
1287
1294
uint32_t local_idx = slot_to_local_idx (jit -> iseq , slot_idx );
1288
1295
1289
- // Load environment pointer EP from CFP
1290
- mov (cb , REG0 , member_opnd ( REG_CFP , rb_control_frame_t , ep ) );
1296
+ // Load environment pointer EP (level 0) from CFP
1297
+ gen_get_ep (cb , REG0 , 0 );
1291
1298
1292
1299
// flags & VM_ENV_FLAG_WB_REQUIRED
1293
1300
x86opnd_t flags_opnd = mem_opnd (64 , REG0 , sizeof (VALUE ) * VM_ENV_DATA_INDEX_FLAGS );
@@ -1314,6 +1321,48 @@ gen_setlocal_wc0(jitstate_t* jit, ctx_t* ctx)
1314
1321
return YJIT_KEEP_COMPILING ;
1315
1322
}
1316
1323
1324
+ static codegen_status_t
1325
+ gen_setlocal_generic (jitstate_t * jit , ctx_t * ctx , uint32_t local_idx , uint32_t level )
1326
+ {
1327
+ // Load environment pointer EP at level
1328
+ gen_get_ep (cb , REG0 , level );
1329
+
1330
+ // flags & VM_ENV_FLAG_WB_REQUIRED
1331
+ x86opnd_t flags_opnd = mem_opnd (64 , REG0 , sizeof (VALUE ) * VM_ENV_DATA_INDEX_FLAGS );
1332
+ test (cb , flags_opnd , imm_opnd (VM_ENV_FLAG_WB_REQUIRED ));
1333
+
1334
+ // Create a size-exit to fall back to the interpreter
1335
+ uint8_t * side_exit = yjit_side_exit (jit , ctx );
1336
+
1337
+ // if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
1338
+ jnz_ptr (cb , side_exit );
1339
+
1340
+ // Pop the value to write from the stack
1341
+ x86opnd_t stack_top = ctx_stack_pop (ctx , 1 );
1342
+ mov (cb , REG1 , stack_top );
1343
+
1344
+ // Write the value at the environment pointer
1345
+ const int32_t offs = - (SIZEOF_VALUE * local_idx );
1346
+ mov (cb , mem_opnd (64 , REG0 , offs ), REG1 );
1347
+
1348
+ return YJIT_KEEP_COMPILING ;
1349
+ }
1350
+
1351
+ static codegen_status_t
1352
+ gen_setlocal (jitstate_t * jit , ctx_t * ctx )
1353
+ {
1354
+ int32_t idx = (int32_t )jit_get_arg (jit , 0 );
1355
+ int32_t level = (int32_t )jit_get_arg (jit , 1 );
1356
+ return gen_setlocal_generic (jit , ctx , idx , level );
1357
+ }
1358
+
1359
+ static codegen_status_t
1360
+ gen_setlocal_wc1 (jitstate_t * jit , ctx_t * ctx )
1361
+ {
1362
+ int32_t idx = (int32_t )jit_get_arg (jit , 0 );
1363
+ return gen_setlocal_generic (jit , ctx , idx , 1 );
1364
+ }
1365
+
1317
1366
// Check that `self` is a pointer to an object on the GC heap
1318
1367
static void
1319
1368
guard_self_is_heap (codeblock_t * cb , x86opnd_t self_opnd , uint8_t * side_exit , ctx_t * ctx )
@@ -4305,7 +4354,9 @@ yjit_init_codegen(void)
4305
4354
yjit_reg_op (BIN (getlocal ), gen_getlocal );
4306
4355
yjit_reg_op (BIN (getlocal_WC_0 ), gen_getlocal_wc0 );
4307
4356
yjit_reg_op (BIN (getlocal_WC_1 ), gen_getlocal_wc1 );
4357
+ yjit_reg_op (BIN (setlocal ), gen_setlocal );
4308
4358
yjit_reg_op (BIN (setlocal_WC_0 ), gen_setlocal_wc0 );
4359
+ yjit_reg_op (BIN (setlocal_WC_1 ), gen_setlocal_wc1 );
4309
4360
yjit_reg_op (BIN (getinstancevariable ), gen_getinstancevariable );
4310
4361
yjit_reg_op (BIN (setinstancevariable ), gen_setinstancevariable );
4311
4362
yjit_reg_op (BIN (defined ), gen_defined );
0 commit comments