@@ -1361,7 +1361,7 @@ fn gen_newarray(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
1361
1361
// Save the PC and SP because we are allocating
1362
1362
jit_prepare_routine_call(jit, ctx, REG0);
1363
1363
1364
- x86opnd_t values_ptr = ctx_sp_opnd(ctx, -(sizeof(VALUE) * (uint32_t)n));
1364
+ x86opnd_t values_ptr = ctx_sp_opnd(ctx, -(SIZEOF_VALUE * (uint32_t)n));
1365
1365
1366
1366
// call rb_ec_ary_new_from_values(struct rb_execution_context_struct *ec, long n, const VALUE *elts);
1367
1367
mov(cb, C_ARG_REGS[0], REG_EC);
@@ -1650,6 +1650,91 @@ fn gen_getlocal_wc1(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, o
1650
1650
gen_getlocal_generic ( ctx, cb, idx. as_u32 ( ) , 1 )
1651
1651
}
1652
1652
1653
+ fn gen_setlocal_wc0 ( jit : & mut JITState , ctx : & mut Context , cb : & mut CodeBlock , ocb : & mut OutlinedCb ) -> CodegenStatus
1654
+ {
1655
+ /*
1656
+ vm_env_write(const VALUE *ep, int index, VALUE v)
1657
+ {
1658
+ VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
1659
+ if (LIKELY((flags & VM_ENV_FLAG_WB_REQUIRED) == 0)) {
1660
+ VM_STACK_ENV_WRITE(ep, index, v);
1661
+ }
1662
+ else {
1663
+ vm_env_write_slowpath(ep, index, v);
1664
+ }
1665
+ }
1666
+ */
1667
+
1668
+ let slot_idx = jit_get_arg ( jit, 0 ) . as_i32 ( ) ;
1669
+ let local_idx = slot_to_local_idx ( jit. get_iseq ( ) , slot_idx) as usize ;
1670
+
1671
+ // Load environment pointer EP (level 0) from CFP
1672
+ gen_get_ep ( cb, REG0 , 0 ) ;
1673
+
1674
+ // flags & VM_ENV_FLAG_WB_REQUIRED
1675
+ let flags_opnd = mem_opnd ( 64 , REG0 , SIZEOF_VALUE as i32 * VM_ENV_DATA_INDEX_FLAGS as i32 ) ;
1676
+ test ( cb, flags_opnd, imm_opnd ( VM_ENV_FLAG_WB_REQUIRED as i64 ) ) ;
1677
+
1678
+ // Create a side-exit to fall back to the interpreter
1679
+ let side_exit = get_side_exit ( jit, ocb, ctx) ;
1680
+
1681
+ // if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
1682
+ jnz_ptr ( cb, side_exit) ;
1683
+
1684
+ // Set the type of the local variable in the context
1685
+ let temp_type = ctx. get_opnd_type ( InsnOpnd :: StackOpnd ( 0 ) ) ;
1686
+ ctx. set_local_type ( local_idx, temp_type) ;
1687
+
1688
+ // Pop the value to write from the stack
1689
+ let stack_top = ctx. stack_pop ( 1 ) ;
1690
+ mov ( cb, REG1 , stack_top) ;
1691
+
1692
+ // Write the value at the environment pointer
1693
+ let offs: i32 = -8 * slot_idx;
1694
+ mov ( cb, mem_opnd ( 64 , REG0 , offs) , REG1 ) ;
1695
+
1696
+ KeepCompiling
1697
+ }
1698
+
1699
+ fn gen_setlocal_generic ( jit : & mut JITState , ctx : & mut Context , cb : & mut CodeBlock , ocb : & mut OutlinedCb , local_idx : i32 , level : u32 ) -> CodegenStatus
1700
+ {
1701
+ // Load environment pointer EP at level
1702
+ gen_get_ep ( cb, REG0 , level) ;
1703
+
1704
+ // flags & VM_ENV_FLAG_WB_REQUIRED
1705
+ let flags_opnd = mem_opnd ( 64 , REG0 , SIZEOF_VALUE as i32 * VM_ENV_DATA_INDEX_FLAGS as i32 ) ;
1706
+ test ( cb, flags_opnd, imm_opnd ( VM_ENV_FLAG_WB_REQUIRED as i64 ) ) ;
1707
+
1708
+ // Create a side-exit to fall back to the interpreter
1709
+ let side_exit = get_side_exit ( jit, ocb, ctx) ;
1710
+
1711
+ // if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
1712
+ jnz_ptr ( cb, side_exit) ;
1713
+
1714
+ // Pop the value to write from the stack
1715
+ let stack_top = ctx. stack_pop ( 1 ) ;
1716
+ mov ( cb, REG1 , stack_top) ;
1717
+
1718
+ // Write the value at the environment pointer
1719
+ let offs = -( SIZEOF_VALUE as i32 * local_idx) ;
1720
+ mov ( cb, mem_opnd ( 64 , REG0 , offs) , REG1 ) ;
1721
+
1722
+ KeepCompiling
1723
+ }
1724
+
1725
+ fn gen_setlocal ( jit : & mut JITState , ctx : & mut Context , cb : & mut CodeBlock , ocb : & mut OutlinedCb ) -> CodegenStatus
1726
+ {
1727
+ let idx = jit_get_arg ( jit, 0 ) . as_i32 ( ) ;
1728
+ let level = jit_get_arg ( jit, 1 ) . as_u32 ( ) ;
1729
+ gen_setlocal_generic ( jit, ctx, cb, ocb, idx, level)
1730
+ }
1731
+
1732
+ fn gen_setlocal_wc1 ( jit : & mut JITState , ctx : & mut Context , cb : & mut CodeBlock , ocb : & mut OutlinedCb ) -> CodegenStatus
1733
+ {
1734
+ let idx = jit_get_arg ( jit, 0 ) . as_i32 ( ) ;
1735
+ gen_setlocal_generic ( jit, ctx, cb, ocb, idx, 1 )
1736
+ }
1737
+
1653
1738
/*
1654
1739
// new hash initialized from top N values
1655
1740
fn gen_newhash(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb: &mut OutlinedCb) -> CodegenStatus
@@ -1709,68 +1794,6 @@ fn gen_putstring(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
1709
1794
return YJIT_KEEP_COMPILING;
1710
1795
}
1711
1796
1712
- // Get EP at level from CFP
1713
- static void
1714
- gen_get_ep(codeblock_t *cb, x86opnd_t reg, uint32_t level)
1715
- {
1716
- // Load environment pointer EP from CFP
1717
- mov(cb, reg, member_opnd(REG_CFP, rb_control_frame_t, ep));
1718
-
1719
- while (level--) {
1720
- // Get the previous EP from the current EP
1721
- // See GET_PREV_EP(ep) macro
1722
- // VALUE *prev_ep = ((VALUE *)((ep)[VM_ENV_DATA_INDEX_SPECVAL] & ~0x03))
1723
- mov(cb, reg, mem_opnd(64, REG0, SIZEOF_VALUE * VM_ENV_DATA_INDEX_SPECVAL));
1724
- and(cb, reg, imm_opnd(~0x03));
1725
- }
1726
- }
1727
-
1728
- fn gen_setlocal_wc0(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb: &mut OutlinedCb) -> CodegenStatus
1729
- {
1730
- /*
1731
- vm_env_write(const VALUE *ep, int index, VALUE v)
1732
- {
1733
- VALUE flags = ep[VM_ENV_DATA_INDEX_FLAGS];
1734
- if (LIKELY((flags & VM_ENV_FLAG_WB_REQUIRED) == 0)) {
1735
- VM_STACK_ENV_WRITE(ep, index, v);
1736
- }
1737
- else {
1738
- vm_env_write_slowpath(ep, index, v);
1739
- }
1740
- }
1741
- */
1742
-
1743
- int32_t slot_idx = (int32_t)jit_get_arg(jit, 0);
1744
- uint32_t local_idx = slot_to_local_idx(jit->iseq, slot_idx);
1745
-
1746
- // Load environment pointer EP (level 0) from CFP
1747
- gen_get_ep(cb, REG0, 0);
1748
-
1749
- // flags & VM_ENV_FLAG_WB_REQUIRED
1750
- x86opnd_t flags_opnd = mem_opnd(64, REG0, sizeof(VALUE) * VM_ENV_DATA_INDEX_FLAGS);
1751
- test(cb, flags_opnd, imm_opnd(VM_ENV_FLAG_WB_REQUIRED));
1752
-
1753
- // Create a side-exit to fall back to the interpreter
1754
- uint8_t *side_exit = get_side_exit(jit, ocb, ctx);
1755
-
1756
- // if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
1757
- jnz_ptr(cb, side_exit);
1758
-
1759
- // Set the type of the local variable in the context
1760
- val_type_t temp_type = ctx_get_opnd_type(ctx, OPND_STACK(0));
1761
- ctx_set_local_type(ctx, local_idx, temp_type);
1762
-
1763
- // Pop the value to write from the stack
1764
- x86opnd_t stack_top = ctx_stack_pop(ctx, 1);
1765
- mov(cb, REG1, stack_top);
1766
-
1767
- // Write the value at the environment pointer
1768
- const int32_t offs = -8 * slot_idx;
1769
- mov(cb, mem_opnd(64, REG0, offs), REG1);
1770
-
1771
- return YJIT_KEEP_COMPILING;
1772
- }
1773
-
1774
1797
// Push Qtrue or Qfalse depending on whether the given keyword was supplied by
1775
1798
// the caller
1776
1799
fn gen_checkkeyword(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb: &mut OutlinedCb) -> CodegenStatus
@@ -1791,7 +1814,7 @@ fn gen_checkkeyword(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, o
1791
1814
gen_get_ep(cb, REG0, 0);
1792
1815
1793
1816
// VALUE kw_bits = *(ep - bits);
1794
- x86opnd_t bits_opnd = mem_opnd(64, REG0, sizeof(VALUE) * -bits_offset);
1817
+ x86opnd_t bits_opnd = mem_opnd(64, REG0, SIZEOF_VALUE * -bits_offset);
1795
1818
1796
1819
// unsigned int b = (unsigned int)FIX2ULONG(kw_bits);
1797
1820
// if ((b & (0x01 << idx))) {
@@ -1809,45 +1832,6 @@ fn gen_checkkeyword(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, o
1809
1832
return YJIT_KEEP_COMPILING;
1810
1833
}
1811
1834
1812
- fn gen_setlocal_generic(jitstate_t *jit, ctx_t *ctx, uint32_t local_idx, uint32_t level)
1813
- {
1814
- // Load environment pointer EP at level
1815
- gen_get_ep(cb, REG0, level);
1816
-
1817
- // flags & VM_ENV_FLAG_WB_REQUIRED
1818
- x86opnd_t flags_opnd = mem_opnd(64, REG0, sizeof(VALUE) * VM_ENV_DATA_INDEX_FLAGS);
1819
- test(cb, flags_opnd, imm_opnd(VM_ENV_FLAG_WB_REQUIRED));
1820
-
1821
- // Create a side-exit to fall back to the interpreter
1822
- uint8_t *side_exit = get_side_exit(jit, ocb, ctx);
1823
-
1824
- // if (flags & VM_ENV_FLAG_WB_REQUIRED) != 0
1825
- jnz_ptr(cb, side_exit);
1826
-
1827
- // Pop the value to write from the stack
1828
- x86opnd_t stack_top = ctx_stack_pop(ctx, 1);
1829
- mov(cb, REG1, stack_top);
1830
-
1831
- // Write the value at the environment pointer
1832
- const int32_t offs = -(SIZEOF_VALUE * local_idx);
1833
- mov(cb, mem_opnd(64, REG0, offs), REG1);
1834
-
1835
- return YJIT_KEEP_COMPILING;
1836
- }
1837
-
1838
- fn gen_setlocal(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb: &mut OutlinedCb) -> CodegenStatus
1839
- {
1840
- int32_t idx = (int32_t)jit_get_arg(jit, 0);
1841
- int32_t level = (int32_t)jit_get_arg(jit, 1);
1842
- return gen_setlocal_generic(jit, ctx, idx, level);
1843
- }
1844
-
1845
- fn gen_setlocal_wc1(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb: &mut OutlinedCb) -> CodegenStatus
1846
- {
1847
- int32_t idx = (int32_t)jit_get_arg(jit, 0);
1848
- return gen_setlocal_generic(jit, ctx, idx, 1);
1849
- }
1850
-
1851
1835
static void
1852
1836
gen_jnz_to_target0(codeblock_t *cb, uint8_t *target0, uint8_t *target1, uint8_t shape)
1853
1837
{
@@ -2098,7 +2082,7 @@ fn gen_get_ivar(jitstate_t *jit, ctx_t *ctx, const int max_chain_depth, VALUE co
2098
2082
mov(cb, REG0, tbl_opnd);
2099
2083
2100
2084
// Read the ivar from the extended table
2101
- x86opnd_t ivar_opnd = mem_opnd(64, REG0, sizeof(VALUE) * ivar_index);
2085
+ x86opnd_t ivar_opnd = mem_opnd(64, REG0, SIZEOF_VALUE * ivar_index);
2102
2086
mov(cb, REG0, ivar_opnd);
2103
2087
2104
2088
// Check that the ivar is not Qundef
@@ -2271,7 +2255,7 @@ fn gen_concatstrings(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock,
2271
2255
// Save the PC and SP because we are allocating
2272
2256
jit_prepare_routine_call(jit, ctx, REG0);
2273
2257
2274
- x86opnd_t values_ptr = ctx_sp_opnd(ctx, -(sizeof(VALUE) * (uint32_t)n));
2258
+ x86opnd_t values_ptr = ctx_sp_opnd(ctx, SIZEOF_VALUE * (uint32_t)n));
2275
2259
2276
2260
// call rb_str_concat_literals(long n, const VALUE *strings);
2277
2261
mov(cb, C_ARG_REGS[0], imm_opnd(n));
@@ -3586,8 +3570,8 @@ fn gen_send_cfunc(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, con
3586
3570
3587
3571
// Stack overflow check
3588
3572
// #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin)
3589
- // REG_CFP <= REG_SP + 4 * sizeof(VALUE) + sizeof(rb_control_frame_t)
3590
- lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * 4 + 2 * sizeof(rb_control_frame_t)));
3573
+ // REG_CFP <= REG_SP + 4 * SIZEOF_VALUE + sizeof(rb_control_frame_t)
3574
+ lea(cb, REG0, ctx_sp_opnd(ctx, SIZEOF_VALUE * 4 + 2 * sizeof(rb_control_frame_t)));
3591
3575
cmp(cb, REG_CFP, REG0);
3592
3576
jle_ptr(cb, counted_exit!(ocb, side_exit, send_se_cf_overflow));
3593
3577
@@ -3607,7 +3591,7 @@ fn gen_send_cfunc(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, con
3607
3591
3608
3592
// Increment the stack pointer by 3 (in the callee)
3609
3593
// sp += 3
3610
- lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * 3));
3594
+ lea(cb, REG0, ctx_sp_opnd(ctx, SIZEOF_VALUE * 3));
3611
3595
3612
3596
// Write method entry at sp[-3]
3613
3597
// sp[-3] = me;
@@ -3656,7 +3640,7 @@ fn gen_send_cfunc(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, con
3656
3640
mov(cb, member_opnd(REG1, rb_control_frame_t, iseq), imm_opnd(0));
3657
3641
mov(cb, member_opnd(REG1, rb_control_frame_t, block_code), imm_opnd(0));
3658
3642
mov(cb, member_opnd(REG1, rb_control_frame_t, __bp__), REG0);
3659
- sub(cb, REG0, imm_opnd(sizeof(VALUE) ));
3643
+ sub(cb, REG0, imm_opnd(SIZEOF_VALUE ));
3660
3644
mov(cb, member_opnd(REG1, rb_control_frame_t, ep), REG0);
3661
3645
mov(cb, REG0, recv);
3662
3646
mov(cb, member_opnd(REG1, rb_control_frame_t, self), REG0);
@@ -3986,7 +3970,7 @@ fn gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, cons
3986
3970
// Note that vm_push_frame checks it against a decremented cfp, hence the multiply by 2.
3987
3971
// #define CHECK_VM_STACK_OVERFLOW0(cfp, sp, margin)
3988
3972
add_comment(cb, "stack overflow check");
3989
- lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * (num_locals + iseq->body->stack_max) + 2 * sizeof(rb_control_frame_t)));
3973
+ lea(cb, REG0, ctx_sp_opnd(ctx, SIZEOF_VALUE * (num_locals + iseq->body->stack_max) + 2 * sizeof(rb_control_frame_t)));
3990
3974
cmp(cb, REG_CFP, REG0);
3991
3975
jle_ptr(cb, counted_exit!(ocb, side_exit, send_se_cf_overflow));
3992
3976
@@ -4106,7 +4090,7 @@ fn gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, cons
4106
4090
4107
4091
// Store the updated SP on the current frame (pop arguments and receiver)
4108
4092
add_comment(cb, "store caller sp");
4109
- lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * -(argc + 1)));
4093
+ lea(cb, REG0, ctx_sp_opnd(ctx, SIZEOF_VALUE * -(argc + 1)));
4110
4094
mov(cb, member_opnd(REG_CFP, rb_control_frame_t, sp), REG0);
4111
4095
4112
4096
// Store the next PC in the current frame
@@ -4121,11 +4105,11 @@ fn gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, cons
4121
4105
}
4122
4106
4123
4107
// Adjust the callee's stack pointer
4124
- lea(cb, REG0, ctx_sp_opnd(ctx, sizeof(VALUE) * (3 + num_locals + doing_kw_call)));
4108
+ lea(cb, REG0, ctx_sp_opnd(ctx, SIZEOF_VALUE * (3 + num_locals + doing_kw_call)));
4125
4109
4126
4110
// Initialize local variables to Qnil
4127
4111
for (int i = 0; i < num_locals; i++) {
4128
- mov(cb, mem_opnd(64, REG0, sizeof(VALUE) * (i - num_locals - 3)), imm_opnd(Qnil));
4112
+ mov(cb, mem_opnd(64, REG0, SIZEOF_VALUE * (i - num_locals - 3)), imm_opnd(Qnil));
4129
4113
}
4130
4114
4131
4115
add_comment(cb, "push env");
@@ -4173,7 +4157,7 @@ fn gen_send_iseq(jitstate_t *jit, ctx_t *ctx, const struct rb_callinfo *ci, cons
4173
4157
mov(cb, REG_SP, REG0); // Switch to the callee's REG_SP
4174
4158
mov(cb, member_opnd(REG_CFP, rb_control_frame_t, sp), REG0);
4175
4159
mov(cb, member_opnd(REG_CFP, rb_control_frame_t, __bp__), REG0);
4176
- sub(cb, REG0, imm_opnd(sizeof(VALUE) ));
4160
+ sub(cb, REG0, imm_opnd(SIZEOF_VALUE ));
4177
4161
mov(cb, member_opnd(REG_CFP, rb_control_frame_t, ep), REG0);
4178
4162
jit_mov_gc_ptr(jit, cb, REG0, (VALUE)iseq);
4179
4163
mov(cb, member_opnd(REG_CFP, rb_control_frame_t, iseq), REG0);
@@ -4778,7 +4762,7 @@ fn gen_toregexp(jit: &mut JITState, ctx: &mut Context, cb: &mut CodeBlock, ocb:
4778
4762
// raise an exception.
4779
4763
jit_prepare_routine_call(jit, ctx, REG0);
4780
4764
4781
- x86opnd_t values_ptr = ctx_sp_opnd(ctx, -(sizeof(VALUE) * (uint32_t)cnt));
4765
+ x86opnd_t values_ptr = ctx_sp_opnd(ctx, -(SIZEOF_VALUE * (uint32_t)cnt));
4782
4766
ctx_stack_pop(ctx, cnt);
4783
4767
4784
4768
mov(cb, C_ARG_REGS[0], imm_opnd(0));
@@ -5238,6 +5222,9 @@ fn get_gen_fn(opcode: VALUE) -> Option<CodeGenFn>
5238
5222
OP_GETLOCAL => Some ( gen_getlocal) ,
5239
5223
OP_GETLOCAL_WC_0 => Some ( gen_getlocal_wc0) ,
5240
5224
OP_GETLOCAL_WC_1 => Some ( gen_getlocal_wc1) ,
5225
+ OP_SETLOCAL => Some ( gen_setlocal) ,
5226
+ OP_SETLOCAL_WC_0 => Some ( gen_setlocal_wc0) ,
5227
+ OP_SETLOCAL_WC_1 => Some ( gen_setlocal_wc1) ,
5241
5228
5242
5229
/*
5243
5230
yjit_reg_op(BIN(newarray), gen_newarray);
@@ -5249,9 +5236,6 @@ fn get_gen_fn(opcode: VALUE) -> Option<CodeGenFn>
5249
5236
yjit_reg_op(BIN(newrange), gen_newrange);
5250
5237
yjit_reg_op(BIN(concatstrings), gen_concatstrings);
5251
5238
yjit_reg_op(BIN(putstring), gen_putstring);
5252
- yjit_reg_op(BIN(setlocal), gen_setlocal);
5253
- yjit_reg_op(BIN(setlocal_WC_0), gen_setlocal_wc0);
5254
- yjit_reg_op(BIN(setlocal_WC_1), gen_setlocal_wc1);
5255
5239
yjit_reg_op(BIN(getinstancevariable), gen_getinstancevariable);
5256
5240
yjit_reg_op(BIN(setinstancevariable), gen_setinstancevariable);
5257
5241
yjit_reg_op(BIN(defined), gen_defined);
0 commit comments