@@ -1193,6 +1193,22 @@ gen_putspecialobject(jitstate_t* jit, ctx_t* ctx)
11931193 }
11941194}
11951195
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+
11961212// Compute the index of a local variable from its slot index
11971213static uint32_t
11981214slot_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)
12131229 const int32_t offs = - (SIZEOF_VALUE * slot_idx );
12141230 uint32_t local_idx = slot_to_local_idx (jit -> iseq , slot_idx );
12151231
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 );
12181234
12191235 // Load the local from the EP
12201236 mov (cb , REG0 , mem_opnd (64 , REG0 , offs ));
@@ -1229,16 +1245,7 @@ gen_getlocal_wc0(jitstate_t* jit, ctx_t* ctx)
12291245static codegen_status_t
12301246gen_getlocal_generic (ctx_t * ctx , uint32_t local_idx , uint32_t level )
12311247{
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 );
12421249
12431250 // Load the local from the block
12441251 // val = *(vm_get_ep(GET_EP(), level) - idx);
@@ -1286,8 +1293,8 @@ gen_setlocal_wc0(jitstate_t* jit, ctx_t* ctx)
12861293 int32_t slot_idx = (int32_t )jit_get_arg (jit , 0 );
12871294 uint32_t local_idx = slot_to_local_idx (jit -> iseq , slot_idx );
12881295
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 );
12911298
12921299 // flags & VM_ENV_FLAG_WB_REQUIRED
12931300 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)
13141321 return YJIT_KEEP_COMPILING ;
13151322}
13161323
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+
13171366// Check that `self` is a pointer to an object on the GC heap
13181367static void
13191368guard_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)
43054354 yjit_reg_op (BIN (getlocal ), gen_getlocal );
43064355 yjit_reg_op (BIN (getlocal_WC_0 ), gen_getlocal_wc0 );
43074356 yjit_reg_op (BIN (getlocal_WC_1 ), gen_getlocal_wc1 );
4357+ yjit_reg_op (BIN (setlocal ), gen_setlocal );
43084358 yjit_reg_op (BIN (setlocal_WC_0 ), gen_setlocal_wc0 );
4359+ yjit_reg_op (BIN (setlocal_WC_1 ), gen_setlocal_wc1 );
43094360 yjit_reg_op (BIN (getinstancevariable ), gen_getinstancevariable );
43104361 yjit_reg_op (BIN (setinstancevariable ), gen_setinstancevariable );
43114362 yjit_reg_op (BIN (defined ), gen_defined );
0 commit comments