YJIT: Move stack_opnd from Context to Assembler (#7700)
This commit is contained in:
parent
847813ab13
commit
2fcd3ea6d8
Notes:
git
2023-04-13 16:20:54 +00:00
Merged-By: maximecb <maximecb@ruby-lang.org>
@ -1093,7 +1093,7 @@ impl Assembler
|
|||||||
for stack_idx in 0..u8::min(MAX_REG_TEMPS, self.ctx.get_stack_size()) {
|
for stack_idx in 0..u8::min(MAX_REG_TEMPS, self.ctx.get_stack_size()) {
|
||||||
if self.get_reg_temps().get(stack_idx) {
|
if self.get_reg_temps().get(stack_idx) {
|
||||||
let idx = self.ctx.get_stack_size() - 1 - stack_idx;
|
let idx = self.ctx.get_stack_size() - 1 - stack_idx;
|
||||||
self.spill_temp(self.ctx.stack_opnd(idx.into()));
|
self.spill_temp(self.stack_opnd(idx.into()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1019,7 +1019,7 @@ fn gen_dup(
|
|||||||
asm: &mut Assembler,
|
asm: &mut Assembler,
|
||||||
_ocb: &mut OutlinedCb,
|
_ocb: &mut OutlinedCb,
|
||||||
) -> CodegenStatus {
|
) -> CodegenStatus {
|
||||||
let dup_val = asm.ctx.stack_opnd(0);
|
let dup_val = asm.stack_opnd(0);
|
||||||
let (mapping, tmp_type) = asm.ctx.get_opnd_mapping(dup_val.into());
|
let (mapping, tmp_type) = asm.ctx.get_opnd_mapping(dup_val.into());
|
||||||
|
|
||||||
let loc0 = asm.stack_push_mapping((mapping, tmp_type));
|
let loc0 = asm.stack_push_mapping((mapping, tmp_type));
|
||||||
@ -1041,8 +1041,8 @@ fn gen_dupn(
|
|||||||
return CantCompile;
|
return CantCompile;
|
||||||
}
|
}
|
||||||
|
|
||||||
let opnd1: Opnd = asm.ctx.stack_opnd(1);
|
let opnd1: Opnd = asm.stack_opnd(1);
|
||||||
let opnd0: Opnd = asm.ctx.stack_opnd(0);
|
let opnd0: Opnd = asm.stack_opnd(0);
|
||||||
|
|
||||||
let mapping1 = asm.ctx.get_opnd_mapping(opnd1.into());
|
let mapping1 = asm.ctx.get_opnd_mapping(opnd1.into());
|
||||||
let mapping0 = asm.ctx.get_opnd_mapping(opnd0.into());
|
let mapping0 = asm.ctx.get_opnd_mapping(opnd0.into());
|
||||||
@ -1071,8 +1071,8 @@ fn stack_swap(
|
|||||||
offset0: u16,
|
offset0: u16,
|
||||||
offset1: u16,
|
offset1: u16,
|
||||||
) {
|
) {
|
||||||
let stack0_mem = asm.ctx.stack_opnd(offset0 as i32);
|
let stack0_mem = asm.stack_opnd(offset0 as i32);
|
||||||
let stack1_mem = asm.ctx.stack_opnd(offset1 as i32);
|
let stack1_mem = asm.stack_opnd(offset1 as i32);
|
||||||
|
|
||||||
let mapping0 = asm.ctx.get_opnd_mapping(stack0_mem.into());
|
let mapping0 = asm.ctx.get_opnd_mapping(stack0_mem.into());
|
||||||
let mapping1 = asm.ctx.get_opnd_mapping(stack1_mem.into());
|
let mapping1 = asm.ctx.get_opnd_mapping(stack1_mem.into());
|
||||||
@ -1171,8 +1171,8 @@ fn gen_setn(
|
|||||||
) -> CodegenStatus {
|
) -> CodegenStatus {
|
||||||
let n = jit.get_arg(0).as_usize();
|
let n = jit.get_arg(0).as_usize();
|
||||||
|
|
||||||
let top_val = asm.ctx.stack_opnd(0);
|
let top_val = asm.stack_opnd(0);
|
||||||
let dst_opnd = asm.ctx.stack_opnd(n.try_into().unwrap());
|
let dst_opnd = asm.stack_opnd(n.try_into().unwrap());
|
||||||
asm.mov(
|
asm.mov(
|
||||||
dst_opnd,
|
dst_opnd,
|
||||||
top_val
|
top_val
|
||||||
@ -1192,7 +1192,7 @@ fn gen_topn(
|
|||||||
) -> CodegenStatus {
|
) -> CodegenStatus {
|
||||||
let n = jit.get_arg(0).as_usize();
|
let n = jit.get_arg(0).as_usize();
|
||||||
|
|
||||||
let top_n_val = asm.ctx.stack_opnd(n.try_into().unwrap());
|
let top_n_val = asm.stack_opnd(n.try_into().unwrap());
|
||||||
let mapping = asm.ctx.get_opnd_mapping(top_n_val.into());
|
let mapping = asm.ctx.get_opnd_mapping(top_n_val.into());
|
||||||
let loc0 = asm.stack_push_mapping(mapping);
|
let loc0 = asm.stack_push_mapping(mapping);
|
||||||
asm.mov(loc0, top_n_val);
|
asm.mov(loc0, top_n_val);
|
||||||
@ -1394,8 +1394,8 @@ fn gen_newrange(
|
|||||||
let range_opnd = asm.ccall(
|
let range_opnd = asm.ccall(
|
||||||
rb_range_new as *const u8,
|
rb_range_new as *const u8,
|
||||||
vec![
|
vec![
|
||||||
asm.ctx.stack_opnd(1),
|
asm.stack_opnd(1),
|
||||||
asm.ctx.stack_opnd(0),
|
asm.stack_opnd(0),
|
||||||
flag.into()
|
flag.into()
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
@ -1559,7 +1559,7 @@ fn gen_expandarray(
|
|||||||
return CantCompile;
|
return CantCompile;
|
||||||
}
|
}
|
||||||
|
|
||||||
let array_opnd = asm.ctx.stack_opnd(0);
|
let array_opnd = asm.stack_opnd(0);
|
||||||
|
|
||||||
// num is the number of requested values. If there aren't enough in the
|
// num is the number of requested values. If there aren't enough in the
|
||||||
// array then we're going to push on nils.
|
// array then we're going to push on nils.
|
||||||
@ -1833,7 +1833,7 @@ fn gen_newhash(
|
|||||||
asm.cpush(new_hash); // x86 alignment
|
asm.cpush(new_hash); // x86 alignment
|
||||||
|
|
||||||
// Get a pointer to the values to insert into the hash
|
// Get a pointer to the values to insert into the hash
|
||||||
let stack_addr_from_top = asm.lea(asm.ctx.stack_opnd((num - 1) as i32));
|
let stack_addr_from_top = asm.lea(asm.stack_opnd((num - 1) as i32));
|
||||||
|
|
||||||
// rb_hash_bulk_insert(num, STACK_ADDR_FROM_TOP(num), val);
|
// rb_hash_bulk_insert(num, STACK_ADDR_FROM_TOP(num), val);
|
||||||
asm.ccall(
|
asm.ccall(
|
||||||
@ -2629,8 +2629,8 @@ fn guard_two_fixnums(
|
|||||||
ocb: &mut OutlinedCb,
|
ocb: &mut OutlinedCb,
|
||||||
) {
|
) {
|
||||||
// Get stack operands without popping them
|
// Get stack operands without popping them
|
||||||
let arg1 = asm.ctx.stack_opnd(0);
|
let arg1 = asm.stack_opnd(0);
|
||||||
let arg0 = asm.ctx.stack_opnd(1);
|
let arg0 = asm.stack_opnd(1);
|
||||||
|
|
||||||
// Get the stack operand types
|
// Get the stack operand types
|
||||||
let arg1_type = asm.ctx.get_opnd_type(arg1.into());
|
let arg1_type = asm.ctx.get_opnd_type(arg1.into());
|
||||||
@ -2778,8 +2778,8 @@ fn gen_equality_specialized(
|
|||||||
ocb: &mut OutlinedCb,
|
ocb: &mut OutlinedCb,
|
||||||
gen_eq: bool,
|
gen_eq: bool,
|
||||||
) -> Option<bool> {
|
) -> Option<bool> {
|
||||||
let a_opnd = asm.ctx.stack_opnd(1);
|
let a_opnd = asm.stack_opnd(1);
|
||||||
let b_opnd = asm.ctx.stack_opnd(0);
|
let b_opnd = asm.stack_opnd(0);
|
||||||
|
|
||||||
let two_fixnums = match asm.ctx.two_fixnums_on_stack(jit) {
|
let two_fixnums = match asm.ctx.two_fixnums_on_stack(jit) {
|
||||||
Some(two_fixnums) => two_fixnums,
|
Some(two_fixnums) => two_fixnums,
|
||||||
@ -2948,8 +2948,8 @@ fn gen_opt_aref(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the stack operands
|
// Get the stack operands
|
||||||
let idx_opnd = asm.ctx.stack_opnd(0);
|
let idx_opnd = asm.stack_opnd(0);
|
||||||
let recv_opnd = asm.ctx.stack_opnd(1);
|
let recv_opnd = asm.stack_opnd(1);
|
||||||
|
|
||||||
// Guard that the receiver is an ::Array
|
// Guard that the receiver is an ::Array
|
||||||
// BOP_AREF check above is only good for ::Array.
|
// BOP_AREF check above is only good for ::Array.
|
||||||
@ -2993,7 +2993,7 @@ fn gen_opt_aref(
|
|||||||
return CantCompile;
|
return CantCompile;
|
||||||
}
|
}
|
||||||
|
|
||||||
let recv_opnd = asm.ctx.stack_opnd(1);
|
let recv_opnd = asm.stack_opnd(1);
|
||||||
|
|
||||||
// Guard that the receiver is a hash
|
// Guard that the receiver is a hash
|
||||||
jit_guard_known_klass(
|
jit_guard_known_klass(
|
||||||
@ -3012,8 +3012,8 @@ fn gen_opt_aref(
|
|||||||
jit_prepare_routine_call(jit, asm);
|
jit_prepare_routine_call(jit, asm);
|
||||||
|
|
||||||
// Call rb_hash_aref
|
// Call rb_hash_aref
|
||||||
let key_opnd = asm.ctx.stack_opnd(0);
|
let key_opnd = asm.stack_opnd(0);
|
||||||
let recv_opnd = asm.ctx.stack_opnd(1);
|
let recv_opnd = asm.stack_opnd(1);
|
||||||
let val = asm.ccall(rb_hash_aref as *const u8, vec![recv_opnd, key_opnd]);
|
let val = asm.ccall(rb_hash_aref as *const u8, vec![recv_opnd, key_opnd]);
|
||||||
|
|
||||||
// Pop the key and the receiver
|
// Pop the key and the receiver
|
||||||
@ -3047,9 +3047,9 @@ fn gen_opt_aset(
|
|||||||
let comptime_key = jit.peek_at_stack(&asm.ctx, 1);
|
let comptime_key = jit.peek_at_stack(&asm.ctx, 1);
|
||||||
|
|
||||||
// Get the operands from the stack
|
// Get the operands from the stack
|
||||||
let recv = asm.ctx.stack_opnd(2);
|
let recv = asm.stack_opnd(2);
|
||||||
let key = asm.ctx.stack_opnd(1);
|
let key = asm.stack_opnd(1);
|
||||||
let _val = asm.ctx.stack_opnd(0);
|
let _val = asm.stack_opnd(0);
|
||||||
|
|
||||||
if comptime_recv.class_of() == unsafe { rb_cArray } && comptime_key.fixnum_p() {
|
if comptime_recv.class_of() == unsafe { rb_cArray } && comptime_key.fixnum_p() {
|
||||||
// Guard receiver is an Array
|
// Guard receiver is an Array
|
||||||
@ -3082,15 +3082,15 @@ fn gen_opt_aset(
|
|||||||
jit_prepare_routine_call(jit, asm);
|
jit_prepare_routine_call(jit, asm);
|
||||||
|
|
||||||
// Call rb_ary_store
|
// Call rb_ary_store
|
||||||
let recv = asm.ctx.stack_opnd(2);
|
let recv = asm.stack_opnd(2);
|
||||||
let key = asm.load(asm.ctx.stack_opnd(1));
|
let key = asm.load(asm.stack_opnd(1));
|
||||||
let key = asm.rshift(key, Opnd::UImm(1)); // FIX2LONG(key)
|
let key = asm.rshift(key, Opnd::UImm(1)); // FIX2LONG(key)
|
||||||
let val = asm.ctx.stack_opnd(0);
|
let val = asm.stack_opnd(0);
|
||||||
asm.ccall(rb_ary_store as *const u8, vec![recv, key, val]);
|
asm.ccall(rb_ary_store as *const u8, vec![recv, key, val]);
|
||||||
|
|
||||||
// rb_ary_store returns void
|
// rb_ary_store returns void
|
||||||
// stored value should still be on stack
|
// stored value should still be on stack
|
||||||
let val = asm.load(asm.ctx.stack_opnd(0));
|
let val = asm.load(asm.stack_opnd(0));
|
||||||
|
|
||||||
// Push the return value onto the stack
|
// Push the return value onto the stack
|
||||||
asm.stack_pop(3);
|
asm.stack_pop(3);
|
||||||
@ -3117,9 +3117,9 @@ fn gen_opt_aset(
|
|||||||
jit_prepare_routine_call(jit, asm);
|
jit_prepare_routine_call(jit, asm);
|
||||||
|
|
||||||
// Call rb_hash_aset
|
// Call rb_hash_aset
|
||||||
let recv = asm.ctx.stack_opnd(2);
|
let recv = asm.stack_opnd(2);
|
||||||
let key = asm.ctx.stack_opnd(1);
|
let key = asm.stack_opnd(1);
|
||||||
let val = asm.ctx.stack_opnd(0);
|
let val = asm.stack_opnd(0);
|
||||||
let ret = asm.ccall(rb_hash_aset as *const u8, vec![recv, key, val]);
|
let ret = asm.ccall(rb_hash_aset as *const u8, vec![recv, key, val]);
|
||||||
|
|
||||||
// Push the return value onto the stack
|
// Push the return value onto the stack
|
||||||
@ -3515,7 +3515,7 @@ fn gen_opt_case_dispatch(
|
|||||||
|
|
||||||
// Try to reorder case/else branches so that ones that are actually used come first.
|
// Try to reorder case/else branches so that ones that are actually used come first.
|
||||||
// Supporting only Fixnum for now so that the implementation can be an equality check.
|
// Supporting only Fixnum for now so that the implementation can be an equality check.
|
||||||
let key_opnd = asm.ctx.stack_opnd(0);
|
let key_opnd = asm.stack_opnd(0);
|
||||||
let comptime_key = jit.peek_at_stack(&asm.ctx, 0);
|
let comptime_key = jit.peek_at_stack(&asm.ctx, 0);
|
||||||
|
|
||||||
// Check that all cases are fixnums to avoid having to register BOP assumptions on
|
// Check that all cases are fixnums to avoid having to register BOP assumptions on
|
||||||
@ -4078,7 +4078,7 @@ fn jit_rb_kernel_is_a(
|
|||||||
let sample_is_a = unsafe { rb_obj_is_kind_of(sample_lhs, sample_rhs) == Qtrue };
|
let sample_is_a = unsafe { rb_obj_is_kind_of(sample_lhs, sample_rhs) == Qtrue };
|
||||||
|
|
||||||
asm.comment("Kernel#is_a?");
|
asm.comment("Kernel#is_a?");
|
||||||
asm.cmp(asm.ctx.stack_opnd(0), sample_rhs.into());
|
asm.cmp(asm.stack_opnd(0), sample_rhs.into());
|
||||||
asm.jne(counted_exit!(jit, &asm.ctx, ocb, send_is_a_class_mismatch));
|
asm.jne(counted_exit!(jit, &asm.ctx, ocb, send_is_a_class_mismatch));
|
||||||
|
|
||||||
asm.stack_pop(2);
|
asm.stack_pop(2);
|
||||||
@ -4137,7 +4137,7 @@ fn jit_rb_kernel_instance_of(
|
|||||||
let sample_instance_of = sample_lhs_real_class == sample_rhs;
|
let sample_instance_of = sample_lhs_real_class == sample_rhs;
|
||||||
|
|
||||||
asm.comment("Kernel#instance_of?");
|
asm.comment("Kernel#instance_of?");
|
||||||
asm.cmp(asm.ctx.stack_opnd(0), sample_rhs.into());
|
asm.cmp(asm.stack_opnd(0), sample_rhs.into());
|
||||||
asm.jne(counted_exit!(jit, &asm.ctx, ocb, send_instance_of_class_mismatch));
|
asm.jne(counted_exit!(jit, &asm.ctx, ocb, send_instance_of_class_mismatch));
|
||||||
|
|
||||||
asm.stack_pop(2);
|
asm.stack_pop(2);
|
||||||
@ -4174,8 +4174,8 @@ fn jit_rb_mod_eqq(
|
|||||||
// Ruby methods with these inputs.
|
// Ruby methods with these inputs.
|
||||||
// Note the difference in approach from Kernel#is_a? because we don't get a free guard for the
|
// Note the difference in approach from Kernel#is_a? because we don't get a free guard for the
|
||||||
// right hand side.
|
// right hand side.
|
||||||
let lhs = asm.ctx.stack_opnd(1); // the module
|
let lhs = asm.stack_opnd(1); // the module
|
||||||
let rhs = asm.ctx.stack_opnd(0);
|
let rhs = asm.stack_opnd(0);
|
||||||
let ret = asm.ccall(rb_obj_is_kind_of as *const u8, vec![rhs, lhs]);
|
let ret = asm.ccall(rb_obj_is_kind_of as *const u8, vec![rhs, lhs]);
|
||||||
|
|
||||||
// Return the result
|
// Return the result
|
||||||
@ -4485,7 +4485,7 @@ fn jit_rb_str_concat(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Guard that the concat argument is a string
|
// Guard that the concat argument is a string
|
||||||
guard_object_is_string(jit, asm, ocb, asm.ctx.stack_opnd(0), StackOpnd(0), None);
|
guard_object_is_string(jit, asm, ocb, asm.stack_opnd(0), StackOpnd(0), None);
|
||||||
|
|
||||||
// Guard buffers from GC since rb_str_buf_append may allocate. During the VM lock on GC,
|
// Guard buffers from GC since rb_str_buf_append may allocate. During the VM lock on GC,
|
||||||
// other Ractors may trigger global invalidation, so we need ctx.clear_local_types().
|
// other Ractors may trigger global invalidation, so we need ctx.clear_local_types().
|
||||||
@ -5096,7 +5096,7 @@ fn gen_send_cfunc(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Points to the receiver operand on the stack
|
// Points to the receiver operand on the stack
|
||||||
let recv = asm.ctx.stack_opnd(argc);
|
let recv = asm.stack_opnd(argc);
|
||||||
|
|
||||||
// Store incremented PC into current control frame in case callee raises.
|
// Store incremented PC into current control frame in case callee raises.
|
||||||
jit_save_pc(jit, asm);
|
jit_save_pc(jit, asm);
|
||||||
@ -5144,7 +5144,7 @@ fn gen_send_cfunc(
|
|||||||
let kwargs = asm.ccall(build_kwhash as *const u8, vec![imemo_ci.into(), sp]);
|
let kwargs = asm.ccall(build_kwhash as *const u8, vec![imemo_ci.into(), sp]);
|
||||||
|
|
||||||
// Replace the stack location at the start of kwargs with the new hash
|
// Replace the stack location at the start of kwargs with the new hash
|
||||||
let stack_opnd = asm.ctx.stack_opnd(argc - passed_argc);
|
let stack_opnd = asm.stack_opnd(argc - passed_argc);
|
||||||
asm.mov(stack_opnd, kwargs);
|
asm.mov(stack_opnd, kwargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5309,7 +5309,7 @@ fn move_rest_args_to_stack(array: Opnd, num_args: u32, jit: &mut JITState, asm:
|
|||||||
fn push_splat_args(required_args: u32, jit: &mut JITState, asm: &mut Assembler, ocb: &mut OutlinedCb) {
|
fn push_splat_args(required_args: u32, jit: &mut JITState, asm: &mut Assembler, ocb: &mut OutlinedCb) {
|
||||||
asm.comment("push_splat_args");
|
asm.comment("push_splat_args");
|
||||||
|
|
||||||
let array_opnd = asm.ctx.stack_opnd(0);
|
let array_opnd = asm.stack_opnd(0);
|
||||||
let array_reg = asm.load(array_opnd);
|
let array_reg = asm.load(array_opnd);
|
||||||
|
|
||||||
guard_object_is_array(
|
guard_object_is_array(
|
||||||
@ -5335,7 +5335,7 @@ fn push_splat_args(required_args: u32, jit: &mut JITState, asm: &mut Assembler,
|
|||||||
asm.test(flags_opnd, (RARRAY_EMBED_FLAG as u64).into());
|
asm.test(flags_opnd, (RARRAY_EMBED_FLAG as u64).into());
|
||||||
|
|
||||||
// Need to repeat this here to deal with register allocation
|
// Need to repeat this here to deal with register allocation
|
||||||
let array_opnd = asm.ctx.stack_opnd(0);
|
let array_opnd = asm.stack_opnd(0);
|
||||||
let array_reg = asm.load(array_opnd);
|
let array_reg = asm.load(array_opnd);
|
||||||
|
|
||||||
let array_len_opnd = Opnd::mem(
|
let array_len_opnd = Opnd::mem(
|
||||||
@ -5352,7 +5352,7 @@ fn push_splat_args(required_args: u32, jit: &mut JITState, asm: &mut Assembler,
|
|||||||
asm.comment("Check last argument is not ruby2keyword hash");
|
asm.comment("Check last argument is not ruby2keyword hash");
|
||||||
|
|
||||||
// Need to repeat this here to deal with register allocation
|
// Need to repeat this here to deal with register allocation
|
||||||
let array_reg = asm.load(asm.ctx.stack_opnd(0));
|
let array_reg = asm.load(asm.stack_opnd(0));
|
||||||
|
|
||||||
let ary_opnd = get_array_ptr(asm, array_reg);
|
let ary_opnd = get_array_ptr(asm, array_reg);
|
||||||
|
|
||||||
@ -5772,7 +5772,7 @@ fn gen_send_iseq(
|
|||||||
|
|
||||||
// Copy self and arguments
|
// Copy self and arguments
|
||||||
for i in 0..=builtin_argc {
|
for i in 0..=builtin_argc {
|
||||||
let stack_opnd = asm.ctx.stack_opnd(builtin_argc - i);
|
let stack_opnd = asm.stack_opnd(builtin_argc - i);
|
||||||
args.push(stack_opnd);
|
args.push(stack_opnd);
|
||||||
}
|
}
|
||||||
asm.stack_pop((builtin_argc + 1).try_into().unwrap());
|
asm.stack_pop((builtin_argc + 1).try_into().unwrap());
|
||||||
@ -6056,7 +6056,7 @@ fn gen_send_iseq(
|
|||||||
// explicitly given a value and have a non-constant default.
|
// explicitly given a value and have a non-constant default.
|
||||||
let unspec_opnd = VALUE::fixnum_from_usize(unspecified_bits).as_u64();
|
let unspec_opnd = VALUE::fixnum_from_usize(unspecified_bits).as_u64();
|
||||||
asm.spill_temps(); // avoid using a register for unspecified_bits
|
asm.spill_temps(); // avoid using a register for unspecified_bits
|
||||||
asm.mov(asm.ctx.stack_opnd(-1), unspec_opnd.into());
|
asm.mov(asm.stack_opnd(-1), unspec_opnd.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Same as vm_callee_setup_block_arg_arg0_check and vm_callee_setup_block_arg_arg0_splat
|
// Same as vm_callee_setup_block_arg_arg0_check and vm_callee_setup_block_arg_arg0_splat
|
||||||
@ -6065,7 +6065,7 @@ fn gen_send_iseq(
|
|||||||
// side exits, so you still need to allow side exits here if block_arg0_splat is true.
|
// side exits, so you still need to allow side exits here if block_arg0_splat is true.
|
||||||
// Note that you can't have side exits after this arg0 splat.
|
// Note that you can't have side exits after this arg0 splat.
|
||||||
if block_arg0_splat {
|
if block_arg0_splat {
|
||||||
let arg0_opnd = asm.ctx.stack_opnd(0);
|
let arg0_opnd = asm.stack_opnd(0);
|
||||||
|
|
||||||
// Only handle the case that you don't need to_ary conversion
|
// Only handle the case that you don't need to_ary conversion
|
||||||
let not_array_counter = exit_counter!(invokeblock_iseq_arg0_not_array);
|
let not_array_counter = exit_counter!(invokeblock_iseq_arg0_not_array);
|
||||||
@ -6094,7 +6094,7 @@ fn gen_send_iseq(
|
|||||||
// Points to the receiver operand on the stack unless a captured environment is used
|
// Points to the receiver operand on the stack unless a captured environment is used
|
||||||
let recv = match captured_opnd {
|
let recv = match captured_opnd {
|
||||||
Some(captured_opnd) => asm.load(Opnd::mem(64, captured_opnd, 0)), // captured->self
|
Some(captured_opnd) => asm.load(Opnd::mem(64, captured_opnd, 0)), // captured->self
|
||||||
_ => asm.ctx.stack_opnd(argc),
|
_ => asm.stack_opnd(argc),
|
||||||
};
|
};
|
||||||
let captured_self = captured_opnd.is_some();
|
let captured_self = captured_opnd.is_some();
|
||||||
let sp_offset = (argc as isize) + if captured_self { 0 } else { 1 };
|
let sp_offset = (argc as isize) + if captured_self { 0 } else { 1 };
|
||||||
@ -6353,7 +6353,7 @@ fn gen_send_general(
|
|||||||
let comptime_recv_klass = comptime_recv.class_of();
|
let comptime_recv_klass = comptime_recv.class_of();
|
||||||
|
|
||||||
// Points to the receiver operand on the stack
|
// Points to the receiver operand on the stack
|
||||||
let recv = asm.ctx.stack_opnd(recv_idx);
|
let recv = asm.stack_opnd(recv_idx);
|
||||||
let recv_opnd: YARVOpnd = recv.into();
|
let recv_opnd: YARVOpnd = recv.into();
|
||||||
|
|
||||||
// Log the name of the method we're calling to
|
// Log the name of the method we're calling to
|
||||||
@ -6606,7 +6606,7 @@ fn gen_send_general(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let name_opnd = asm.ctx.stack_opnd(argc);
|
let name_opnd = asm.stack_opnd(argc);
|
||||||
jit_guard_known_klass(
|
jit_guard_known_klass(
|
||||||
jit,
|
jit,
|
||||||
asm,
|
asm,
|
||||||
@ -6785,11 +6785,11 @@ fn gen_send_general(
|
|||||||
fn handle_opt_send_shift_stack(asm: &mut Assembler, argc: i32) {
|
fn handle_opt_send_shift_stack(asm: &mut Assembler, argc: i32) {
|
||||||
asm.comment("shift_stack");
|
asm.comment("shift_stack");
|
||||||
for j in (0..argc).rev() {
|
for j in (0..argc).rev() {
|
||||||
let opnd = asm.ctx.stack_opnd(j);
|
let opnd = asm.stack_opnd(j);
|
||||||
let opnd2 = asm.ctx.stack_opnd(j + 1);
|
let opnd2 = asm.stack_opnd(j + 1);
|
||||||
asm.mov(opnd2, opnd);
|
asm.mov(opnd2, opnd);
|
||||||
}
|
}
|
||||||
asm.ctx.shift_stack(argc as usize);
|
asm.shift_stack(argc as usize);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gen_opt_send_without_block(
|
fn gen_opt_send_without_block(
|
||||||
@ -7197,7 +7197,7 @@ fn gen_objtostring(
|
|||||||
return EndBlock;
|
return EndBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
let recv = asm.ctx.stack_opnd(0);
|
let recv = asm.stack_opnd(0);
|
||||||
let comptime_recv = jit.peek_at_stack(&asm.ctx, 0);
|
let comptime_recv = jit.peek_at_stack(&asm.ctx, 0);
|
||||||
|
|
||||||
if unsafe { RB_TYPE_P(comptime_recv, RUBY_T_STRING) } {
|
if unsafe { RB_TYPE_P(comptime_recv, RUBY_T_STRING) } {
|
||||||
@ -7710,7 +7710,7 @@ fn gen_invokebuiltin(
|
|||||||
|
|
||||||
// Copy arguments from locals
|
// Copy arguments from locals
|
||||||
for i in 0..bf_argc {
|
for i in 0..bf_argc {
|
||||||
let stack_opnd = asm.ctx.stack_opnd((bf_argc - i - 1) as i32);
|
let stack_opnd = asm.stack_opnd((bf_argc - i - 1) as i32);
|
||||||
args.push(stack_opnd);
|
args.push(stack_opnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1622,49 +1622,6 @@ impl Context {
|
|||||||
self.set_reg_temps(reg_temps);
|
self.set_reg_temps(reg_temps);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pop N values off the stack
|
|
||||||
// Return a pointer to the stack top before the pop operation
|
|
||||||
fn stack_pop(&mut self, n: usize) -> Opnd {
|
|
||||||
assert!(n <= self.stack_size.into());
|
|
||||||
|
|
||||||
let top = self.stack_opnd(0);
|
|
||||||
|
|
||||||
// Clear the types of the popped values
|
|
||||||
for i in 0..n {
|
|
||||||
let idx: usize = (self.stack_size as usize) - i - 1;
|
|
||||||
|
|
||||||
if idx < MAX_TEMP_TYPES {
|
|
||||||
self.temp_types[idx] = Type::Unknown;
|
|
||||||
self.temp_mapping[idx] = MapToStack;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.stack_size -= n as u8;
|
|
||||||
self.sp_offset -= n as i8;
|
|
||||||
|
|
||||||
return top;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn shift_stack(&mut self, argc: usize) {
|
|
||||||
assert!(argc < self.stack_size.into());
|
|
||||||
|
|
||||||
let method_name_index = (self.stack_size as usize) - (argc as usize) - 1;
|
|
||||||
|
|
||||||
for i in method_name_index..(self.stack_size - 1) as usize {
|
|
||||||
|
|
||||||
if i + 1 < MAX_TEMP_TYPES {
|
|
||||||
self.temp_types[i] = self.temp_types[i + 1];
|
|
||||||
self.temp_mapping[i] = self.temp_mapping[i + 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.stack_pop(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get an operand pointing to a slot on the temp stack
|
|
||||||
pub fn stack_opnd(&self, idx: i32) -> Opnd {
|
|
||||||
Opnd::Stack { idx, stack_size: self.stack_size, sp_offset: self.sp_offset, num_bits: 64 }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the type of an instruction operand
|
/// Get the type of an instruction operand
|
||||||
pub fn get_opnd_type(&self, opnd: YARVOpnd) -> Type {
|
pub fn get_opnd_type(&self, opnd: YARVOpnd) -> Type {
|
||||||
match opnd {
|
match opnd {
|
||||||
@ -1956,7 +1913,7 @@ impl Assembler {
|
|||||||
self.ctx.stack_size += 1;
|
self.ctx.stack_size += 1;
|
||||||
self.ctx.sp_offset += 1;
|
self.ctx.sp_offset += 1;
|
||||||
|
|
||||||
return self.ctx.stack_opnd(0);
|
return self.stack_opnd(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Push one new value on the temp stack
|
/// Push one new value on the temp stack
|
||||||
@ -1982,7 +1939,44 @@ impl Assembler {
|
|||||||
// Pop N values off the stack
|
// Pop N values off the stack
|
||||||
// Return a pointer to the stack top before the pop operation
|
// Return a pointer to the stack top before the pop operation
|
||||||
pub fn stack_pop(&mut self, n: usize) -> Opnd {
|
pub fn stack_pop(&mut self, n: usize) -> Opnd {
|
||||||
self.ctx.stack_pop(n)
|
assert!(n <= self.ctx.stack_size.into());
|
||||||
|
|
||||||
|
let top = self.stack_opnd(0);
|
||||||
|
|
||||||
|
// Clear the types of the popped values
|
||||||
|
for i in 0..n {
|
||||||
|
let idx: usize = (self.ctx.stack_size as usize) - i - 1;
|
||||||
|
|
||||||
|
if idx < MAX_TEMP_TYPES {
|
||||||
|
self.ctx.temp_types[idx] = Type::Unknown;
|
||||||
|
self.ctx.temp_mapping[idx] = MapToStack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ctx.stack_size -= n as u8;
|
||||||
|
self.ctx.sp_offset -= n as i8;
|
||||||
|
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Shift stack temps to remove a Symbol for #send.
|
||||||
|
pub fn shift_stack(&mut self, argc: usize) {
|
||||||
|
assert!(argc < self.ctx.stack_size.into());
|
||||||
|
|
||||||
|
let method_name_index = (self.ctx.stack_size as usize) - (argc as usize) - 1;
|
||||||
|
|
||||||
|
for i in method_name_index..(self.ctx.stack_size - 1) as usize {
|
||||||
|
if i + 1 < MAX_TEMP_TYPES {
|
||||||
|
self.ctx.temp_types[i] = self.ctx.temp_types[i + 1];
|
||||||
|
self.ctx.temp_mapping[i] = self.ctx.temp_mapping[i + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.stack_pop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get an operand pointing to a slot on the temp stack
|
||||||
|
pub fn stack_opnd(&self, idx: i32) -> Opnd {
|
||||||
|
Opnd::Stack { idx, stack_size: self.ctx.stack_size, sp_offset: self.ctx.sp_offset, num_bits: 64 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user