@@ -2175,37 +2175,84 @@ gen_opt_aref(jitstate_t *jit, ctx_t *ctx)
21752175 }
21762176}
21772177
2178- VALUE rb_vm_opt_aset (VALUE recv , VALUE obj , VALUE set );
2179-
21802178static codegen_status_t
21812179gen_opt_aset (jitstate_t * jit , ctx_t * ctx )
21822180{
2183- // Save the PC and SP because the callee may allocate
2184- // Note that this modifies REG_SP, which is why we do it first
2185- jit_prepare_routine_call (jit , ctx , REG0 );
2181+ // Defer compilation so we can specialize on a runtime `self`
2182+ if (!jit_at_current_insn (jit )) {
2183+ defer_compilation (jit -> block , jit -> insn_idx , ctx );
2184+ return YJIT_END_BLOCK ;
2185+ }
21862186
2187- uint8_t * side_exit = yjit_side_exit (jit , ctx );
2187+ VALUE comptime_recv = jit_peek_at_stack (jit , ctx , 2 );
2188+ VALUE comptime_key = jit_peek_at_stack (jit , ctx , 1 );
2189+ VALUE comptime_val = jit_peek_at_stack (jit , ctx , 0 );
21882190
21892191 // Get the operands from the stack
2190- x86opnd_t arg2 = ctx_stack_pop (ctx , 1 );
2191- x86opnd_t arg1 = ctx_stack_pop (ctx , 1 );
2192- x86opnd_t arg0 = ctx_stack_pop (ctx , 1 );
2192+ x86opnd_t recv = ctx_stack_opnd (ctx , 2 );
2193+ x86opnd_t key = ctx_stack_opnd (ctx , 1 );
2194+ x86opnd_t val = ctx_stack_opnd (ctx , 0 );
21932195
2194- // Call rb_vm_opt_aset(VALUE recv, VALUE obj)
2195- mov (cb , C_ARG_REGS [0 ], arg0 );
2196- mov (cb , C_ARG_REGS [1 ], arg1 );
2197- mov (cb , C_ARG_REGS [2 ], arg2 );
2198- call_ptr (cb , REG0 , (void * )rb_vm_opt_aset );
2196+ if (CLASS_OF (comptime_recv ) == rb_cArray && FIXNUM_P (comptime_val )) {
2197+ uint8_t * side_exit = yjit_side_exit (jit , ctx );
21992198
2200- // If val == Qundef, bail to do a method call
2201- cmp (cb , RAX , imm_opnd ( Qundef ) );
2202- je_ptr ( cb , side_exit );
2199+ // Guard receiver is an Array
2200+ mov (cb , REG0 , recv );
2201+ jit_guard_known_klass ( jit , ctx , rb_cArray , OPND_STACK ( 2 ), comptime_recv , SEND_MAX_DEPTH , side_exit );
22032202
2204- // Push the return value onto the stack
2205- x86opnd_t stack_ret = ctx_stack_push ( ctx , TYPE_UNKNOWN );
2206- mov ( cb , stack_ret , RAX );
2203+ // Guard key is a fixnum
2204+ mov ( cb , REG0 , key );
2205+ jit_guard_known_klass ( jit , ctx , rb_cInteger , OPND_STACK ( 1 ), comptime_key , SEND_MAX_DEPTH , side_exit );
22072206
2208- return YJIT_KEEP_COMPILING ;
2207+ // Call rb_ary_store
2208+ mov (cb , C_ARG_REGS [0 ], recv );
2209+ mov (cb , C_ARG_REGS [1 ], key );
2210+ sar (cb , C_ARG_REGS [1 ], imm_opnd (1 )); // FIX2LONG(key)
2211+ mov (cb , C_ARG_REGS [2 ], val );
2212+
2213+ // We might allocate or raise
2214+ jit_prepare_routine_call (jit , ctx , REG0 );
2215+
2216+ call_ptr (cb , REG0 , (void * )rb_ary_store );
2217+
2218+ // rb_ary_store returns void
2219+ // stored value should still be on stack
2220+ mov (cb , REG0 , ctx_stack_opnd (ctx , 0 ));
2221+
2222+ // Push the return value onto the stack
2223+ ctx_stack_pop (ctx , 3 );
2224+ x86opnd_t stack_ret = ctx_stack_push (ctx , TYPE_UNKNOWN );
2225+ mov (cb , stack_ret , REG0 );
2226+
2227+ jit_jump_to_next_insn (jit , ctx );
2228+ return YJIT_END_BLOCK ;
2229+ } else if (CLASS_OF (comptime_recv ) == rb_cHash ) {
2230+ uint8_t * side_exit = yjit_side_exit (jit , ctx );
2231+
2232+ // Guard receiver is a Hash
2233+ mov (cb , REG0 , recv );
2234+ jit_guard_known_klass (jit , ctx , rb_cHash , OPND_STACK (2 ), comptime_recv , SEND_MAX_DEPTH , side_exit );
2235+
2236+ // Call rb_hash_aset
2237+ mov (cb , C_ARG_REGS [0 ], recv );
2238+ mov (cb , C_ARG_REGS [1 ], key );
2239+ mov (cb , C_ARG_REGS [2 ], val );
2240+
2241+ // We might allocate or raise
2242+ jit_prepare_routine_call (jit , ctx , REG0 );
2243+
2244+ call_ptr (cb , REG0 , (void * )rb_hash_aset );
2245+
2246+ // Push the return value onto the stack
2247+ ctx_stack_pop (ctx , 3 );
2248+ x86opnd_t stack_ret = ctx_stack_push (ctx , TYPE_UNKNOWN );
2249+ mov (cb , stack_ret , RAX );
2250+
2251+ jit_jump_to_next_insn (jit , ctx );
2252+ return YJIT_END_BLOCK ;
2253+ } else {
2254+ return gen_opt_send_without_block (jit , ctx );
2255+ }
22092256}
22102257
22112258static codegen_status_t
0 commit comments