diff --git a/zjit.rb b/zjit.rb index eb47a704708cae..b85b5629a72654 100644 --- a/zjit.rb +++ b/zjit.rb @@ -43,6 +43,7 @@ def stats_string print_counters_with_prefix(prefix: 'dynamic_send_type_', prompt: 'dynamic send types', buf:, stats:, limit: 20) print_counters_with_prefix(prefix: 'unspecialized_def_type_', prompt: 'send fallback unspecialized def_types', buf:, stats:, limit: 20) print_counters_with_prefix(prefix: 'send_fallback_', prompt: 'dynamic send types', buf:, stats:, limit: 20) + print_counters_with_prefix(prefix: 'not_optimized_cfuncs_', prompt: 'unoptimized sends to C functions', buf:, stats:, limit: 20) # Show exit counters, ordered by the typical amount of exits for the prefix at the time print_counters_with_prefix(prefix: 'unhandled_yarv_insn_', prompt: 'unhandled YARV insns', buf:, stats:, limit: 20) diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index 8230d39522504f..e8f1d968298860 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -16,7 +16,7 @@ use crate::stats::{exit_counter_for_compile_error, incr_counter, incr_counter_by use crate::stats::{counter_ptr, with_time_stat, Counter, send_fallback_counter, Counter::{compile_time_ns, exit_compile_error}}; use crate::{asm::CodeBlock, cruby::*, options::debug, virtualmem::CodePtr}; use crate::backend::lir::{self, asm_comment, asm_ccall, Assembler, Opnd, Target, CFP, C_ARG_OPNDS, C_RET_OPND, EC, NATIVE_STACK_PTR, NATIVE_BASE_PTR, SCRATCH_OPND, SP}; -use crate::hir::{iseq_to_hir, Block, BlockId, BranchEdge, Invariant, MethodType, RangeType, SideExitReason::{self, *}, SpecialBackrefSymbol, SpecialObjectType, SELF_PARAM_IDX}; +use crate::hir::{iseq_to_hir, BlockId, BranchEdge, Invariant, MethodType, RangeType, SideExitReason::{self, *}, SpecialBackrefSymbol, SpecialObjectType}; use crate::hir::{Const, FrameState, Function, Insn, InsnId}; use crate::hir_type::{types, Type}; use crate::options::get_option; @@ -37,7 +37,7 @@ struct JITState { jit_entries: Vec>>, /// ISEQ calls that need to be compiled later - iseq_calls: Vec>>, + iseq_calls: Vec, /// The number of bytes allocated for basic block arguments spilled onto the C stack c_stack_slots: usize, @@ -126,23 +126,23 @@ fn gen_iseq_entry_point(cb: &mut CodeBlock, iseq: IseqPtr, jit_exception: bool) })?; // Compile an entry point to the JIT code - gen_entry(cb, iseq, &function, start_ptr).inspect_err(|err| { + gen_entry(cb, iseq, start_ptr).inspect_err(|err| { debug!("{err:?}: gen_entry failed: {}", iseq_get_location(iseq, 0)); }) } /// Stub a branch for a JIT-to-JIT call -fn gen_iseq_call(cb: &mut CodeBlock, caller_iseq: IseqPtr, iseq_call: &Rc>) -> Result<(), CompileError> { +fn gen_iseq_call(cb: &mut CodeBlock, caller_iseq: IseqPtr, iseq_call: &IseqCallRef) -> Result<(), CompileError> { // Compile a function stub let stub_ptr = gen_function_stub(cb, iseq_call.clone()).inspect_err(|err| { debug!("{err:?}: gen_function_stub failed: {} -> {}", - iseq_get_location(caller_iseq, 0), iseq_get_location(iseq_call.borrow().iseq, 0)); + iseq_get_location(caller_iseq, 0), iseq_get_location(iseq_call.iseq.get(), 0)); })?; // Update the JIT-to-JIT call to call the stub let stub_addr = stub_ptr.raw_ptr(cb); - let iseq = iseq_call.borrow().iseq; - iseq_call.borrow_mut().regenerate(cb, |asm| { + let iseq = iseq_call.iseq.get(); + iseq_call.regenerate(cb, |asm| { asm_comment!(asm, "call function stub: {}", iseq_get_location(iseq, 0)); asm.ccall(stub_addr, vec![]); }); @@ -164,11 +164,10 @@ fn register_with_perf(iseq_name: String, start_ptr: usize, code_size: usize) { } /// Compile a JIT entry -fn gen_entry(cb: &mut CodeBlock, iseq: IseqPtr, function: &Function, function_ptr: CodePtr) -> Result { +fn gen_entry(cb: &mut CodeBlock, iseq: IseqPtr, function_ptr: CodePtr) -> Result { // Set up registers for CFP, EC, SP, and basic block arguments let mut asm = Assembler::new(); gen_entry_prologue(&mut asm, iseq); - gen_entry_params(&mut asm, iseq, function.entry_block()); // Jump to the first block using a call instruction asm.ccall(function_ptr.raw_ptr(cb), vec![]); @@ -236,7 +235,7 @@ fn gen_iseq_body(cb: &mut CodeBlock, iseq: IseqPtr, function: Option<&Function>, } // Prepare for GC - payload.iseq_calls.extend(iseq_calls.clone()); + payload.iseq_calls.extend(iseq_calls); append_gc_offsets(iseq, &gc_offsets); Ok(iseq_code_ptrs) } @@ -409,8 +408,8 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio Insn::GetIvar { self_val, id, state: _ } => gen_getivar(asm, opnd!(self_val), *id), Insn::SetGlobal { id, val, state } => no_output!(gen_setglobal(jit, asm, *id, opnd!(val), &function.frame_state(*state))), Insn::GetGlobal { id, state } => gen_getglobal(jit, asm, *id, &function.frame_state(*state)), - &Insn::GetLocal { ep_offset, level } => gen_getlocal_with_ep(asm, ep_offset, level), - &Insn::SetLocal { val, ep_offset, level } => no_output!(gen_setlocal_with_ep(asm, opnd!(val), function.type_of(val), ep_offset, level)), + &Insn::GetLocal { ep_offset, level, use_sp, .. } => gen_getlocal(asm, ep_offset, level, use_sp), + &Insn::SetLocal { val, ep_offset, level } => no_output!(gen_setlocal(asm, opnd!(val), function.type_of(val), ep_offset, level)), Insn::GetConstantPath { ic, state } => gen_get_constant_path(jit, asm, *ic, &function.frame_state(*state)), Insn::SetIvar { self_val, id, val, state: _ } => no_output!(gen_setivar(asm, opnd!(self_val), *id, opnd!(val))), Insn::SideExit { state, reason } => no_output!(gen_side_exit(jit, asm, reason, &function.frame_state(*state))), @@ -420,6 +419,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio Insn::GetSpecialSymbol { symbol_type, state: _ } => gen_getspecial_symbol(asm, *symbol_type), Insn::GetSpecialNumber { nth, state } => gen_getspecial_number(asm, *nth, &function.frame_state(*state)), &Insn::IncrCounter(counter) => no_output!(gen_incr_counter(asm, counter)), + Insn::IncrCounterPtr { counter_ptr } => no_output!(gen_incr_counter_ptr(asm, *counter_ptr)), Insn::ObjToString { val, cd, state, .. } => gen_objtostring(jit, asm, opnd!(val), *cd, &function.frame_state(*state)), &Insn::CheckInterrupts { state } => no_output!(gen_check_interrupts(jit, asm, &function.frame_state(state))), &Insn::HashDup { val, state } => { gen_hash_dup(asm, opnd!(val), &function.frame_state(state)) }, @@ -430,6 +430,7 @@ fn gen_insn(cb: &mut CodeBlock, jit: &mut JITState, asm: &mut Assembler, functio &Insn::ArrayExtend { left, right, state } => { no_output!(gen_array_extend(jit, asm, opnd!(left), opnd!(right), &function.frame_state(state))) }, &Insn::GuardShape { val, shape, state } => gen_guard_shape(jit, asm, opnd!(val), shape, &function.frame_state(state)), Insn::LoadPC => gen_load_pc(asm), + Insn::LoadSelf => gen_load_self(), &Insn::LoadIvarEmbedded { self_val, id, index } => gen_load_ivar_embedded(asm, opnd!(self_val), id, index), &Insn::LoadIvarExtended { self_val, id, index } => gen_load_ivar_extended(asm, opnd!(self_val), id, index), &Insn::ArrayMax { state, .. } @@ -537,19 +538,28 @@ fn gen_defined(jit: &JITState, asm: &mut Assembler, op_type: usize, obj: VALUE, /// Get a local variable from a higher scope or the heap. `local_ep_offset` is in number of VALUEs. /// We generate this instruction with level=0 only when the local variable is on the heap, so we /// can't optimize the level=0 case using the SP register. -fn gen_getlocal_with_ep(asm: &mut Assembler, local_ep_offset: u32, level: u32) -> lir::Opnd { +fn gen_getlocal(asm: &mut Assembler, local_ep_offset: u32, level: u32, use_sp: bool) -> lir::Opnd { + let local_ep_offset = i32::try_from(local_ep_offset).unwrap_or_else(|_| panic!("Could not convert local_ep_offset {local_ep_offset} to i32")); if level > 0 { gen_incr_counter(asm, Counter::vm_read_from_parent_iseq_local_count); } - let ep = gen_get_ep(asm, level); - let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).unwrap_or_else(|_| panic!("Could not convert local_ep_offset {local_ep_offset} to i32"))); - asm.load(Opnd::mem(64, ep, offset)) + let local = if use_sp { + assert_eq!(level, 0, "use_sp optimization should be used only for level=0 locals"); + let offset = -(SIZEOF_VALUE_I32 * (local_ep_offset + 1)); + Opnd::mem(64, SP, offset) + } else { + let ep = gen_get_ep(asm, level); + let offset = -(SIZEOF_VALUE_I32 * local_ep_offset); + Opnd::mem(64, ep, offset) + }; + asm.load(local) } /// Set a local variable from a higher scope or the heap. `local_ep_offset` is in number of VALUEs. /// We generate this instruction with level=0 only when the local variable is on the heap, so we /// can't optimize the level=0 case using the SP register. -fn gen_setlocal_with_ep(asm: &mut Assembler, val: Opnd, val_type: Type, local_ep_offset: u32, level: u32) { +fn gen_setlocal(asm: &mut Assembler, val: Opnd, val_type: Type, local_ep_offset: u32, level: u32) { + let local_ep_offset = c_int::try_from(local_ep_offset).unwrap_or_else(|_| panic!("Could not convert local_ep_offset {local_ep_offset} to i32")); if level > 0 { gen_incr_counter(asm, Counter::vm_write_to_parent_iseq_local_count); } @@ -558,12 +568,12 @@ fn gen_setlocal_with_ep(asm: &mut Assembler, val: Opnd, val_type: Type, local_ep // When we've proved that we're writing an immediate, // we can skip the write barrier. if val_type.is_immediate() { - let offset = -(SIZEOF_VALUE_I32 * i32::try_from(local_ep_offset).unwrap_or_else(|_| panic!("Could not convert local_ep_offset {local_ep_offset} to i32"))); + let offset = -(SIZEOF_VALUE_I32 * local_ep_offset); asm.mov(Opnd::mem(64, ep, offset), val); } else { // We're potentially writing a reference to an IMEMO/env object, // so take care of the write barrier with a function. - let local_index = c_int::try_from(local_ep_offset).ok().and_then(|idx| idx.checked_mul(-1)).unwrap_or_else(|| panic!("Could not turn {local_ep_offset} into a negative c_int")); + let local_index = local_ep_offset * -1; asm_ccall!(asm, rb_vm_env_write, ep, local_index.into(), val); } } @@ -834,6 +844,10 @@ fn gen_load_pc(asm: &mut Assembler) -> Opnd { asm.load(Opnd::mem(64, CFP, RUBY_OFFSET_CFP_PC)) } +fn gen_load_self() -> Opnd { + Opnd::mem(64, CFP, RUBY_OFFSET_CFP_SELF) +} + fn gen_load_ivar_embedded(asm: &mut Assembler, self_val: Opnd, id: ID, index: u16) -> Opnd { // See ROBJECT_FIELDS() from include/ruby/internal/core/robject.h @@ -871,53 +885,6 @@ fn gen_entry_prologue(asm: &mut Assembler, iseq: IseqPtr) { asm.mov(SP, Opnd::mem(64, CFP, RUBY_OFFSET_CFP_SP)); } -/// Assign method arguments to basic block arguments at JIT entry -fn gen_entry_params(asm: &mut Assembler, iseq: IseqPtr, entry_block: &Block) { - let num_params = entry_block.params().len() - 1; // -1 to exclude self - if num_params > 0 { - asm_comment!(asm, "set method params: {num_params}"); - - // Fill basic block parameters. - // Doing it in reverse is load-bearing. High index params have memory slots that might - // require using a register to fill. Filling them first avoids clobbering. - for idx in (0..num_params).rev() { - let param = param_opnd(idx + 1); // +1 for self - let local = gen_entry_param(asm, iseq, idx); - - // Funky offset adjustment to write into the native stack frame of the - // HIR function we'll be calling into. This only makes sense in context - // of the schedule of instructions in gen_entry() for the JIT entry point. - // - // The entry point needs to load VALUEs into native stack slots _before_ the - // frame containing the slots exists. So, we anticipate the stack frame size - // of the Function and subtract offsets based on that. - // - // native SP at entry point ─────►┌────────────┐ Native SP grows downwards - // │ │ ↓ on all arches we support. - // SP-0x8 ├────────────┤ - // │ │ - // where native SP SP-0x10├────────────┤ - // would be while │ │ - // the HIR function ────────────► └────────────┘ - // is running - match param { - Opnd::Mem(lir::Mem { base: _, disp, num_bits }) => { - let param_slot = Opnd::mem(num_bits, NATIVE_STACK_PTR, disp - Assembler::frame_size()); - asm.mov(param_slot, local); - } - // Prepare for parallel move for locals in registers - reg @ Opnd::Reg(_) => { - asm.load_into(reg, local); - } - _ => unreachable!("on entry, params are either in memory or in reg. Got {param:?}") - } - - // Assign local variables to the basic block arguments - } - } - asm.load_into(param_opnd(SELF_PARAM_IDX), Opnd::mem(VALUE_BITS, CFP, RUBY_OFFSET_CFP_SELF)); -} - /// Set branch params to basic block arguments fn gen_branch_params(jit: &mut JITState, asm: &mut Assembler, branch: &BranchEdge) { if branch.args.is_empty() { @@ -941,28 +908,6 @@ fn gen_branch_params(jit: &mut JITState, asm: &mut Assembler, branch: &BranchEdg asm.parallel_mov(moves); } -/// Get a method parameter on JIT entry. As of entry, whether EP is escaped or not solely -/// depends on the ISEQ type. -fn gen_entry_param(asm: &mut Assembler, iseq: IseqPtr, local_idx: usize) -> lir::Opnd { - let ep_offset = local_idx_to_ep_offset(iseq, local_idx); - - // If the ISEQ does not escape EP, we can optimize the local variable access using the SP register. - if !iseq_entry_escapes_ep(iseq) { - // Create a reference to the local variable using the SP register. We assume EP == BP. - // TODO: Implement the invalidation in rb_zjit_invalidate_no_ep_escape() - let offs = -(SIZEOF_VALUE_I32 * (ep_offset + 1)); - Opnd::mem(64, SP, offs) - } else { - // Get the EP of the current CFP - let ep_opnd = Opnd::mem(64, CFP, RUBY_OFFSET_CFP_EP); - let ep_reg = asm.load(ep_opnd); - - // Create a reference to the local variable using cfp->ep - let offs = -(SIZEOF_VALUE_I32 * ep_offset); - Opnd::mem(64, ep_reg, offs) - } -} - /// Compile a constant fn gen_const_value(val: VALUE) -> lir::Opnd { // Just propagate the constant value and generate nothing @@ -1584,15 +1529,20 @@ fn gen_guard_bit_equals(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, val } +/// Generate code that records unoptimized C functions if --zjit-stats is enabled +fn gen_incr_counter_ptr(asm: &mut Assembler, counter_ptr: *mut u64) { + if get_option!(stats) { + let ptr_reg = asm.load(Opnd::const_ptr(counter_ptr as *const u8)); + let counter_opnd = Opnd::mem(64, ptr_reg, 0); + asm.incr_counter(counter_opnd, Opnd::UImm(1)); + } +} + /// Generate code that increments a counter if --zjit-stats fn gen_incr_counter(asm: &mut Assembler, counter: Counter) { if get_option!(stats) { let ptr = counter_ptr(counter); - let ptr_reg = asm.load(Opnd::const_ptr(ptr as *const u8)); - let counter_opnd = Opnd::mem(64, ptr_reg, 0); - - // Increment and store the updated value - asm.incr_counter(counter_opnd, Opnd::UImm(1)); + gen_incr_counter_ptr(asm, ptr); } } @@ -1817,20 +1767,6 @@ fn build_side_exit(jit: &JITState, state: &FrameState, reason: SideExitReason, l } } -/// Return true if a given ISEQ is known to escape EP to the heap on entry. -/// -/// As of vm_push_frame(), EP is always equal to BP. However, after pushing -/// a frame, some ISEQ setups call vm_bind_update_env(), which redirects EP. -fn iseq_entry_escapes_ep(iseq: IseqPtr) -> bool { - match unsafe { get_iseq_body_type(iseq) } { - //
frame is always associated to TOPLEVEL_BINDING. - ISEQ_TYPE_MAIN | - // Kernel#eval uses a heap EP when a Binding argument is not nil. - ISEQ_TYPE_EVAL => true, - _ => false, - } -} - /// Returne the maximum number of arguments for a block in a given function fn max_num_params(function: &Function) -> usize { let reverse_post_order = function.rpo(); @@ -1867,8 +1803,8 @@ c_callable! { with_vm_lock(src_loc!(), || { // gen_push_frame() doesn't set PC, so we need to set them before exit. // function_stub_hit_body() may allocate and call gc_validate_pc(), so we always set PC. - let iseq_call = unsafe { Rc::from_raw(iseq_call_ptr as *const RefCell) }; - let iseq = iseq_call.borrow().iseq; + let iseq_call = unsafe { Rc::from_raw(iseq_call_ptr as *const IseqCall) }; + let iseq = iseq_call.iseq.get(); let pc = unsafe { rb_iseq_pc_at_idx(iseq, 0) }; // TODO: handle opt_pc once supported unsafe { rb_set_cfp_pc(cfp, pc) }; @@ -1904,7 +1840,7 @@ c_callable! { }; if let Some(compile_error) = compile_error { // We'll use this Rc again, so increment the ref count decremented by from_raw. - unsafe { Rc::increment_strong_count(iseq_call_ptr as *const RefCell); } + unsafe { Rc::increment_strong_count(iseq_call_ptr as *const IseqCall); } prepare_for_exit(iseq, cfp, sp, compile_error); return ZJITState::get_exit_trampoline_with_counter().raw_ptr(cb); @@ -1923,10 +1859,10 @@ c_callable! { } /// Compile an ISEQ for a function stub -fn function_stub_hit_body(cb: &mut CodeBlock, iseq_call: &Rc>) -> Result { +fn function_stub_hit_body(cb: &mut CodeBlock, iseq_call: &IseqCallRef) -> Result { // Compile the stubbed ISEQ - let IseqCodePtrs { jit_entry_ptrs, .. } = gen_iseq(cb, iseq_call.borrow().iseq, None).inspect_err(|err| { - debug!("{err:?}: gen_iseq failed: {}", iseq_get_location(iseq_call.borrow().iseq, 0)); + let IseqCodePtrs { jit_entry_ptrs, .. } = gen_iseq(cb, iseq_call.iseq.get(), None).inspect_err(|err| { + debug!("{err:?}: gen_iseq failed: {}", iseq_get_location(iseq_call.iseq.get(), 0)); })?; // We currently don't support JIT-to-JIT calls for ISEQs with optional arguments. @@ -1936,8 +1872,8 @@ fn function_stub_hit_body(cb: &mut CodeBlock, iseq_call: &Rc>) // Update the stub to call the code pointer let code_addr = jit_entry_ptr.raw_ptr(cb); - let iseq = iseq_call.borrow().iseq; - iseq_call.borrow_mut().regenerate(cb, |asm| { + let iseq = iseq_call.iseq.get(); + iseq_call.regenerate(cb, |asm| { asm_comment!(asm, "call compiled function: {}", iseq_get_location(iseq, 0)); asm.ccall(code_addr, vec![]); }); @@ -1946,9 +1882,9 @@ fn function_stub_hit_body(cb: &mut CodeBlock, iseq_call: &Rc>) } /// Compile a stub for an ISEQ called by SendWithoutBlockDirect -fn gen_function_stub(cb: &mut CodeBlock, iseq_call: Rc>) -> Result { +fn gen_function_stub(cb: &mut CodeBlock, iseq_call: IseqCallRef) -> Result { let mut asm = Assembler::new(); - asm_comment!(asm, "Stub: {}", iseq_get_location(iseq_call.borrow().iseq, 0)); + asm_comment!(asm, "Stub: {}", iseq_get_location(iseq_call.iseq.get(), 0)); // Call function_stub_hit using the shared trampoline. See `gen_function_stub_hit_trampoline`. // Use load_into instead of mov, which is split on arm64, to avoid clobbering ALLOC_REGS. @@ -2113,7 +2049,7 @@ fn aligned_stack_bytes(num_slots: usize) -> usize { impl Assembler { /// Make a C call while marking the start and end positions for IseqCall - fn ccall_with_iseq_call(&mut self, fptr: *const u8, opnds: Vec, iseq_call: &Rc>) -> Opnd { + fn ccall_with_iseq_call(&mut self, fptr: *const u8, opnds: Vec, iseq_call: &IseqCallRef) -> Opnd { // We need to create our own branch rc objects so that we can move the closure below let start_iseq_call = iseq_call.clone(); let end_iseq_call = iseq_call.clone(); @@ -2122,10 +2058,10 @@ impl Assembler { fptr, opnds, move |code_ptr, _| { - start_iseq_call.borrow_mut().start_addr.set(Some(code_ptr)); + start_iseq_call.start_addr.set(Some(code_ptr)); }, move |code_ptr, _| { - end_iseq_call.borrow_mut().end_addr.set(Some(code_ptr)); + end_iseq_call.end_addr.set(Some(code_ptr)); }, ) } @@ -2154,7 +2090,7 @@ impl JITEntry { #[derive(Debug)] pub struct IseqCall { /// Callee ISEQ that start_addr jumps to - pub iseq: IseqPtr, + pub iseq: Cell, /// Position where the call instruction starts start_addr: Cell>, @@ -2163,17 +2099,17 @@ pub struct IseqCall { end_addr: Cell>, } -type IseqCallRef = Rc>; +pub type IseqCallRef = Rc; impl IseqCall { /// Allocate a new IseqCall - fn new(iseq: IseqPtr) -> Rc> { + fn new(iseq: IseqPtr) -> IseqCallRef { let iseq_call = IseqCall { - iseq, + iseq: Cell::new(iseq), start_addr: Cell::new(None), end_addr: Cell::new(None), }; - Rc::new(RefCell::new(iseq_call)) + Rc::new(iseq_call) } /// Regenerate a IseqCall with a given callback diff --git a/zjit/src/cruby.rs b/zjit/src/cruby.rs index 9575c3d1993393..baba0992ccaef9 100644 --- a/zjit/src/cruby.rs +++ b/zjit/src/cruby.rs @@ -294,7 +294,10 @@ pub fn iseq_opcode_at_idx(iseq: IseqPtr, insn_idx: u32) -> u32 { unsafe { rb_iseq_opcode_at_pc(iseq, pc) as u32 } } -/// Return true if the ISEQ always uses a frame with escaped EP. +/// Return true if a given ISEQ is known to escape EP to the heap on entry. +/// +/// As of vm_push_frame(), EP is always equal to BP. However, after pushing +/// a frame, some ISEQ setups call vm_bind_update_env(), which redirects EP. pub fn iseq_escapes_ep(iseq: IseqPtr) -> bool { match unsafe { get_iseq_body_type(iseq) } { // The EP of the
frame points to TOPLEVEL_BINDING @@ -305,6 +308,17 @@ pub fn iseq_escapes_ep(iseq: IseqPtr) -> bool { } } +/// Index of the local variable that has a rest parameter if any +pub fn iseq_rest_param_idx(iseq: IseqPtr) -> Option { + if !iseq.is_null() && unsafe { get_iseq_flags_has_rest(iseq) } { + let opt_num = unsafe { get_iseq_body_param_opt_num(iseq) }; + let lead_num = unsafe { get_iseq_body_param_lead_num(iseq) }; + Some(opt_num + lead_num) + } else { + None + } +} + /// Iterate over all existing ISEQs pub fn for_each_iseq(mut callback: F) { unsafe extern "C" fn callback_wrapper(iseq: IseqPtr, data: *mut c_void) { diff --git a/zjit/src/gc.rs b/zjit/src/gc.rs index eed202ac77a378..cc08b8fc9ebb07 100644 --- a/zjit/src/gc.rs +++ b/zjit/src/gc.rs @@ -1,9 +1,7 @@ //! This module is responsible for marking/moving objects on GC. -use std::cell::RefCell; -use std::rc::Rc; use std::{ffi::c_void, ops::Range}; -use crate::codegen::IseqCall; +use crate::codegen::IseqCallRef; use crate::stats::CompileError; use crate::{cruby::*, profile::IseqProfile, state::ZJITState, stats::with_time_stat, virtualmem::CodePtr}; use crate::stats::Counter::gc_time_ns; @@ -21,7 +19,7 @@ pub struct IseqPayload { pub gc_offsets: Vec, /// JIT-to-JIT calls in the ISEQ. The IseqPayload's ISEQ is the caller of it. - pub iseq_calls: Vec>>, + pub iseq_calls: Vec, } impl IseqPayload { @@ -191,10 +189,10 @@ fn iseq_update_references(payload: &mut IseqPayload) { // Move ISEQ references in IseqCall for iseq_call in payload.iseq_calls.iter_mut() { - let old_iseq = iseq_call.borrow().iseq; + let old_iseq = iseq_call.iseq.get(); let new_iseq = unsafe { rb_gc_location(VALUE(old_iseq as usize)) }.0 as IseqPtr; if old_iseq != new_iseq { - iseq_call.borrow_mut().iseq = new_iseq; + iseq_call.iseq.set(new_iseq); } } diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index 598bcb00c4e082..d81231e2820b88 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -589,13 +589,17 @@ pub enum Insn { /// Load cfp->pc LoadPC, + /// Load cfp->self + LoadSelf, /// Read an instance variable at the given index, embedded in the object LoadIvarEmbedded { self_val: InsnId, id: ID, index: u16 }, /// Read an instance variable at the given index, from the extended table LoadIvarExtended { self_val: InsnId, id: ID, index: u16 }, - /// Get a local variable from a higher scope or the heap - GetLocal { level: u32, ep_offset: u32 }, + /// Get a local variable from a higher scope or the heap. + /// If `use_sp` is true, it uses the SP register to optimize the read. + /// `rest_param` is used by infer_types to infer the ArrayExact type. + GetLocal { level: u32, ep_offset: u32, use_sp: bool, rest_param: bool }, /// Set a local variable in a higher scope or the heap SetLocal { level: u32, ep_offset: u32, val: InsnId }, GetSpecialSymbol { symbol_type: SpecialBackrefSymbol, state: InsnId }, @@ -707,6 +711,9 @@ pub enum Insn { /// Increment a counter in ZJIT stats IncrCounter(Counter), + /// Increment a counter in ZJIT stats for the given counter pointer + IncrCounterPtr { counter_ptr: *mut u64 }, + /// Equivalent of RUBY_VM_CHECK_INTS. Automatically inserted by the compiler before jumps and /// return instructions. CheckInterrupts { state: InsnId }, @@ -720,7 +727,7 @@ impl Insn { | Insn::IfTrue { .. } | Insn::IfFalse { .. } | Insn::EntryPoint { .. } | Insn::Return { .. } | Insn::PatchPoint { .. } | Insn::SetIvar { .. } | Insn::ArrayExtend { .. } | Insn::ArrayPush { .. } | Insn::SideExit { .. } | Insn::SetGlobal { .. } - | Insn::SetLocal { .. } | Insn::Throw { .. } | Insn::IncrCounter(_) + | Insn::SetLocal { .. } | Insn::Throw { .. } | Insn::IncrCounter(_) | Insn::IncrCounterPtr { .. } | Insn::CheckInterrupts { .. } | Insn::GuardBlockParamProxy { .. } => false, _ => true, } @@ -769,6 +776,8 @@ impl Insn { Insn::FixnumOr { .. } => false, Insn::GetLocal { .. } => false, Insn::IsNil { .. } => false, + Insn::LoadPC => false, + Insn::LoadSelf => false, Insn::LoadIvarEmbedded { .. } => false, Insn::LoadIvarExtended { .. } => false, Insn::CCall { elidable, .. } => !elidable, @@ -972,6 +981,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> { } Ok(()) }, + Insn::IncrCounterPtr { .. } => write!(f, "IncrCounterPtr"), Insn::Snapshot { state } => write!(f, "Snapshot {}", state.print(self.ptr_map)), Insn::Defined { op_type, v, .. } => { // op_type (enum defined_type) printing logic from iseq.c. @@ -992,12 +1002,14 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> { Insn::DefinedIvar { self_val, id, .. } => write!(f, "DefinedIvar {self_val}, :{}", id.contents_lossy()), Insn::GetIvar { self_val, id, .. } => write!(f, "GetIvar {self_val}, :{}", id.contents_lossy()), Insn::LoadPC => write!(f, "LoadPC"), + Insn::LoadSelf => write!(f, "LoadSelf"), &Insn::LoadIvarEmbedded { self_val, id, index } => write!(f, "LoadIvarEmbedded {self_val}, :{}@{:p}", id.contents_lossy(), self.ptr_map.map_index(index as u64)), &Insn::LoadIvarExtended { self_val, id, index } => write!(f, "LoadIvarExtended {self_val}, :{}@{:p}", id.contents_lossy(), self.ptr_map.map_index(index as u64)), Insn::SetIvar { self_val, id, val, .. } => write!(f, "SetIvar {self_val}, :{}, {val}", id.contents_lossy()), Insn::GetGlobal { id, .. } => write!(f, "GetGlobal :{}", id.contents_lossy()), Insn::SetGlobal { id, val, .. } => write!(f, "SetGlobal :{}, {val}", id.contents_lossy()), - Insn::GetLocal { level, ep_offset } => write!(f, "GetLocal l{level}, EP@{ep_offset}"), + &Insn::GetLocal { level, ep_offset, use_sp: true, rest_param } => write!(f, "GetLocal l{level}, SP@{}{}", ep_offset + 1, if rest_param { ", *" } else { "" }), + &Insn::GetLocal { level, ep_offset, use_sp: false, rest_param } => write!(f, "GetLocal l{level}, EP@{ep_offset}{}", if rest_param { ", *" } else { "" }), Insn::SetLocal { val, level, ep_offset } => write!(f, "SetLocal l{level}, EP@{ep_offset}, {val}"), Insn::GetSpecialSymbol { symbol_type, .. } => write!(f, "GetSpecialSymbol {symbol_type:?}"), Insn::GetSpecialNumber { nth, .. } => write!(f, "GetSpecialNumber {nth}"), @@ -1376,6 +1388,8 @@ impl Function { | SideExit {..} | EntryPoint {..} | LoadPC + | LoadSelf + | IncrCounterPtr {..} | IncrCounter(_)) => result.clone(), &Snapshot { state: FrameState { iseq, insn_idx, pc, ref stack, ref locals } } => Snapshot { @@ -1525,7 +1539,7 @@ impl Function { | Insn::IfTrue { .. } | Insn::IfFalse { .. } | Insn::Return { .. } | Insn::Throw { .. } | Insn::PatchPoint { .. } | Insn::SetIvar { .. } | Insn::ArrayExtend { .. } | Insn::ArrayPush { .. } | Insn::SideExit { .. } | Insn::SetLocal { .. } | Insn::IncrCounter(_) - | Insn::CheckInterrupts { .. } | Insn::GuardBlockParamProxy { .. } => + | Insn::CheckInterrupts { .. } | Insn::GuardBlockParamProxy { .. } | Insn::IncrCounterPtr { .. } => panic!("Cannot infer type of instruction with no output: {}", self.insns[insn.0]), Insn::Const { val: Const::Value(val) } => Type::from_value(*val), Insn::Const { val: Const::CBool(val) } => Type::from_cbool(*val), @@ -1593,6 +1607,7 @@ impl Function { Insn::GetGlobal { .. } => types::BasicObject, Insn::GetIvar { .. } => types::BasicObject, Insn::LoadPC => types::CPtr, + Insn::LoadSelf => types::BasicObject, Insn::LoadIvarEmbedded { .. } => types::BasicObject, Insn::LoadIvarExtended { .. } => types::BasicObject, Insn::GetSpecialSymbol { .. } => types::BasicObject, @@ -1601,6 +1616,7 @@ impl Function { Insn::ToArray { .. } => types::ArrayExact, Insn::ObjToString { .. } => types::BasicObject, Insn::AnyToString { .. } => types::String, + Insn::GetLocal { rest_param: true, .. } => types::ArrayExact, Insn::GetLocal { .. } => types::BasicObject, // The type of Snapshot doesn't really matter; it's never materialized. It's used only // as a reference for FrameState, which we use to generate side-exit code. @@ -1608,17 +1624,11 @@ impl Function { } } - /// Set self.param_types. They are copied to the param types of entry blocks. + /// Set self.param_types. They are copied to the param types of jit_entry_blocks. fn set_param_types(&mut self) { let iseq = self.iseq; let param_size = unsafe { get_iseq_body_param_size(iseq) }.as_usize(); - let rest_param_idx = if !iseq.is_null() && unsafe { get_iseq_flags_has_rest(iseq) } { - let opt_num = unsafe { get_iseq_body_param_opt_num(iseq) }; - let lead_num = unsafe { get_iseq_body_param_lead_num(iseq) }; - Some(opt_num + lead_num) - } else { - None - }; + let rest_param_idx = iseq_rest_param_idx(iseq); self.param_types.push(types::BasicObject); // self for local_idx in 0..param_size { @@ -1631,10 +1641,10 @@ impl Function { } } - /// Copy self.param_types to the param types of entry blocks. + /// Copy self.param_types to the param types of jit_entry_blocks. fn copy_param_types(&mut self) { - for entry_block in self.entry_blocks() { - let entry_params = self.blocks[entry_block.0].params.iter(); + for jit_entry_block in self.jit_entry_blocks.iter() { + let entry_params = self.blocks[jit_entry_block.0].params.iter(); let param_types = self.param_types.iter(); assert_eq!( entry_params.len(), @@ -2149,9 +2159,9 @@ impl Function { self_type: Type, send: Insn, send_insn_id: InsnId, - ) -> Result<(), ()> { + ) -> Result<(), Option<*const rb_callable_method_entry_struct>> { let Insn::SendWithoutBlock { mut recv, cd, mut args, state, .. } = send else { - return Err(()); + return Err(None); }; let call_info = unsafe { (*cd).ci }; @@ -2163,20 +2173,20 @@ impl Function { (class, None) } else { let iseq_insn_idx = fun.frame_state(state).insn_idx; - let Some(recv_type) = fun.profiled_type_of_at(recv, iseq_insn_idx) else { return Err(()) }; + let Some(recv_type) = fun.profiled_type_of_at(recv, iseq_insn_idx) else { return Err(None) }; (recv_type.class(), Some(recv_type)) }; // Do method lookup - let method = unsafe { rb_callable_method_entry(recv_class, method_id) }; + let method: *const rb_callable_method_entry_struct = unsafe { rb_callable_method_entry(recv_class, method_id) }; if method.is_null() { - return Err(()); + return Err(None); } // Filter for C methods let def_type = unsafe { get_cme_def_type(method) }; if def_type != VM_METHOD_TYPE_CFUNC { - return Err(()); + return Err(None); } // Find the `argc` (arity) of the C method, which describes the parameters it expects @@ -2188,7 +2198,7 @@ impl Function { // // Bail on argc mismatch if argc != cfunc_argc as u32 { - return Err(()); + return Err(Some(method)); } // Filter for a leaf and GC free function @@ -2196,7 +2206,7 @@ impl Function { let Some(FnProperties { leaf: true, no_gc: true, return_type, elidable }) = ZJITState::get_method_annotations().get_cfunc_properties(method) else { - return Err(()); + return Err(Some(method)); }; let ci_flags = unsafe { vm_ci_flag(call_info) }; @@ -2213,13 +2223,13 @@ impl Function { cfunc_args.append(&mut args); let ccall = fun.push_insn(block, Insn::CCall { cfun, args: cfunc_args, name: method_id, return_type, elidable }); fun.make_equal_to(send_insn_id, ccall); - return Ok(()); + return Ok(()) } } // Variadic method -1 => { if unsafe { rb_zjit_method_tracing_currently_enabled() } { - return Err(()); + return Err(None); } // The method gets a pointer to the first argument // func(int argc, VALUE *argv, VALUE recv) @@ -2251,8 +2261,9 @@ impl Function { }); fun.make_equal_to(send_insn_id, ccall); - return Ok(()); + return Ok(()) } + // Fall through for complex cases (splat, kwargs, etc.) } -2 => { @@ -2262,7 +2273,7 @@ impl Function { _ => unreachable!("unknown cfunc kind: argc={argc}") } - Err(()) + Err(Some(method)) } for block in self.rpo() { @@ -2271,8 +2282,23 @@ impl Function { for insn_id in old_insns { if let send @ Insn::SendWithoutBlock { recv, .. } = self.find(insn_id) { let recv_type = self.type_of(recv); - if reduce_to_ccall(self, block, recv_type, send, insn_id).is_ok() { - continue; + match reduce_to_ccall(self, block, recv_type, send, insn_id) { + Ok(()) => continue, + Err(Some(cme)) => { + if get_option!(stats) { + let owner = unsafe { (*cme).owner }; + let called_id = unsafe { (*cme).called_id }; + let class_name = get_class_name(owner); + let method_name = called_id.contents_lossy(); + let qualified_method_name = format!("{}#{}", class_name, method_name); + let unoptimized_cfunc_counter_pointers = ZJITState::get_unoptimized_cfunc_counter_pointers(); + let counter_ptr = unoptimized_cfunc_counter_pointers.entry(qualified_method_name.clone()).or_insert_with(|| Box::new(0)); + let counter_ptr = &mut **counter_ptr as *mut u64; + + self.push_insn(block, Insn::IncrCounterPtr { counter_ptr }); + } + } + _ => {} } } self.push_insn_id(block, insn_id); @@ -2414,10 +2440,12 @@ impl Function { &Insn::Const { .. } | &Insn::Param { .. } | &Insn::EntryPoint { .. } - | &Insn::LoadPC { .. } + | &Insn::LoadPC + | &Insn::LoadSelf | &Insn::GetLocal { .. } | &Insn::PutSpecialObject { .. } - | &Insn::IncrCounter(_) => + | &Insn::IncrCounter(_) + | &Insn::IncrCounterPtr { .. } => {} &Insn::PatchPoint { state, .. } | &Insn::CheckInterrupts { state } @@ -3653,7 +3681,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result { let ep_offset = get_arg(pc, 0).as_u32(); if ep_escaped || has_blockiseq { // TODO: figure out how to drop has_blockiseq here // Read the local using EP - let val = fun.push_insn(block, Insn::GetLocal { ep_offset, level: 0 }); + let val = fun.push_insn(block, Insn::GetLocal { ep_offset, level: 0, use_sp: false, rest_param: false }); state.setlocal(ep_offset, val); // remember the result to spill on side-exits state.stack_push(val); } else { @@ -3687,7 +3715,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result { } YARVINSN_getlocal_WC_1 => { let ep_offset = get_arg(pc, 0).as_u32(); - state.stack_push(fun.push_insn(block, Insn::GetLocal { ep_offset, level: 1 })); + state.stack_push(fun.push_insn(block, Insn::GetLocal { ep_offset, level: 1, use_sp: false, rest_param: false })); } YARVINSN_setlocal_WC_1 => { let ep_offset = get_arg(pc, 0).as_u32(); @@ -3696,7 +3724,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result { YARVINSN_getlocal => { let ep_offset = get_arg(pc, 0).as_u32(); let level = get_arg(pc, 1).as_u32(); - state.stack_push(fun.push_insn(block, Insn::GetLocal { ep_offset, level })); + state.stack_push(fun.push_insn(block, Insn::GetLocal { ep_offset, level, use_sp: false, rest_param: false })); } YARVINSN_setlocal => { let ep_offset = get_arg(pc, 0).as_u32(); @@ -3896,7 +3924,8 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result { // or not used after this. Max thinks we could eventually DCE them. for local_idx in 0..state.locals.len() { let ep_offset = local_idx_to_ep_offset(iseq, local_idx) as u32; - let val = fun.push_insn(block, Insn::GetLocal { ep_offset, level: 0 }); + // TODO: We could use `use_sp: true` with PatchPoint + let val = fun.push_insn(block, Insn::GetLocal { ep_offset, level: 0, use_sp: false, rest_param: false }); state.setlocal(ep_offset, val); } } @@ -3925,7 +3954,8 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result { // Reload locals that may have been modified by the blockiseq. for local_idx in 0..state.locals.len() { let ep_offset = local_idx_to_ep_offset(iseq, local_idx) as u32; - let val = fun.push_insn(block, Insn::GetLocal { ep_offset, level: 0 }); + // TODO: We could use `use_sp: true` with PatchPoint + let val = fun.push_insn(block, Insn::GetLocal { ep_offset, level: 0, use_sp: false, rest_param: false }); state.setlocal(ep_offset, val); } } @@ -3955,7 +3985,8 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result { // or not used after this. Max thinks we could eventually DCE them. for local_idx in 0..state.locals.len() { let ep_offset = local_idx_to_ep_offset(iseq, local_idx) as u32; - let val = fun.push_insn(block, Insn::GetLocal { ep_offset, level: 0 }); + // TODO: We could use `use_sp: true` with PatchPoint + let val = fun.push_insn(block, Insn::GetLocal { ep_offset, level: 0, use_sp: false, rest_param: false }); state.setlocal(ep_offset, val); } } @@ -4199,30 +4230,51 @@ fn compile_entry_block(fun: &mut Function, jit_entry_insns: &Vec) { } } +/// Compile initial locals for an entry_block for the interpreter +fn compile_entry_state(fun: &mut Function, entry_block: BlockId) -> (InsnId, FrameState) { + let iseq = fun.iseq; + let param_size = unsafe { get_iseq_body_param_size(iseq) }.as_usize(); + let rest_param_idx = iseq_rest_param_idx(iseq); + + let self_param = fun.push_insn(entry_block, Insn::LoadSelf); + let mut entry_state = FrameState::new(iseq); + for local_idx in 0..num_locals(iseq) { + if local_idx < param_size { + let ep_offset = local_idx_to_ep_offset(iseq, local_idx) as u32; + let use_sp = !iseq_escapes_ep(iseq); // If the ISEQ does not escape EP, we can assume EP + 1 == SP + let rest_param = Some(local_idx as i32) == rest_param_idx; + entry_state.locals.push(fun.push_insn(entry_block, Insn::GetLocal { level: 0, ep_offset, use_sp, rest_param })); + } else { + entry_state.locals.push(fun.push_insn(entry_block, Insn::Const { val: Const::Value(Qnil) })); + } + } + (self_param, entry_state) +} + /// Compile a jit_entry_block fn compile_jit_entry_block(fun: &mut Function, jit_entry_idx: usize, target_block: BlockId) { let jit_entry_block = fun.jit_entry_blocks[jit_entry_idx]; fun.push_insn(jit_entry_block, Insn::EntryPoint { jit_entry_idx: Some(jit_entry_idx) }); // Prepare entry_state with basic block params - let (self_param, entry_state) = compile_entry_state(fun, jit_entry_block); + let (self_param, entry_state) = compile_jit_entry_state(fun, jit_entry_block); // Jump to target_block fun.push_insn(jit_entry_block, Insn::Jump(BranchEdge { target: target_block, args: entry_state.as_args(self_param) })); } -/// Compile params and initial locals for an entry block -fn compile_entry_state(fun: &mut Function, entry_block: BlockId) -> (InsnId, FrameState) { +/// Compile params and initial locals for a jit_entry_block +fn compile_jit_entry_state(fun: &mut Function, jit_entry_block: BlockId) -> (InsnId, FrameState) { let iseq = fun.iseq; let param_size = unsafe { get_iseq_body_param_size(iseq) }.as_usize(); - let self_param = fun.push_insn(entry_block, Insn::Param { idx: SELF_PARAM_IDX }); + let self_param = fun.push_insn(jit_entry_block, Insn::Param { idx: SELF_PARAM_IDX }); let mut entry_state = FrameState::new(iseq); for local_idx in 0..num_locals(iseq) { if local_idx < param_size { - entry_state.locals.push(fun.push_insn(entry_block, Insn::Param { idx: local_idx + 1 })); // +1 for self + entry_state.locals.push(fun.push_insn(jit_entry_block, Insn::Param { idx: local_idx + 1 })); // +1 for self } else { - entry_state.locals.push(fun.push_insn(entry_block, Insn::Const { val: Const::Value(Qnil) })); + entry_state.locals.push(fun.push_insn(jit_entry_block, Insn::Const { val: Const::Value(Qnil) })); } } (self_param, entry_state) @@ -4541,18 +4593,6 @@ mod infer_tests { }); } - #[test] - fn test_unknown() { - crate::cruby::with_rubyvm(|| { - let mut function = Function::new(std::ptr::null()); - let param = function.push_insn(function.entry_block, Insn::Param { idx: SELF_PARAM_IDX }); - function.param_types.push(types::BasicObject); // self - let val = function.push_insn(function.entry_block, Insn::Test { val: param }); - function.infer_types(); - assert_bit_equal(function.type_of(val), types::CBool); - }); - } - #[test] fn newarray() { let mut function = Function::new(std::ptr::null()); @@ -4627,8 +4667,11 @@ mod snapshot_tests { eval("def test(a, b) = [a, b]"); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -4729,8 +4772,10 @@ mod tests { eval("def test(x=1) = 123"); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 v3:CPtr = LoadPC v4:CPtr[CPtr(0x1000)] = Const CPtr(0x1008) v5:CBool = IsBitEqual v3, v4 @@ -4758,8 +4803,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_putobject); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -4777,8 +4823,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_newarray); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -4796,8 +4843,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_newarray); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -4815,8 +4864,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_newarray); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -4834,8 +4886,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_newrange); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -4854,8 +4908,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_newrange); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -4873,8 +4930,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_newrange); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -4893,8 +4952,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_newrange); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -4912,8 +4974,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_duparray); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -4932,8 +4995,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_duphash); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -4952,8 +5016,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_newhash); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -4971,8 +5036,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_newhash); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -4992,8 +5060,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_putchilledstring); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5012,8 +5081,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_putobject); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5031,8 +5101,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_putobject); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5050,8 +5121,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_putobject); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5069,8 +5141,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_putobject); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5088,8 +5161,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_plus); assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5111,8 +5185,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_hash_freeze); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5136,8 +5211,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_hash_freeze); assert_snapshot!(hir_string("test"), @r" fn test@:5: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5155,8 +5231,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_ary_freeze); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5180,8 +5257,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_ary_freeze); assert_snapshot!(hir_string("test"), @r" fn test@:5: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5199,8 +5277,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_str_freeze); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5224,8 +5303,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_str_freeze); assert_snapshot!(hir_string("test"), @r" fn test@:5: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5243,8 +5323,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_str_uminus); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5268,8 +5349,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_str_uminus); assert_snapshot!(hir_string("test"), @r" fn test@:5: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5290,8 +5372,9 @@ mod tests { assert_contains_opcodes("test", &[YARVINSN_getlocal_WC_0, YARVINSN_setlocal_WC_0]); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -5329,8 +5412,9 @@ mod tests { YARVINSN_getlocal, YARVINSN_setlocal]); assert_snapshot!(hir_string("test"), @r" fn block (3 levels) in @:10: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5360,8 +5444,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_setlocal_WC_0); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 v3:NilClass = Const Value(nil) v4:CPtr = LoadPC v5:CPtr[CPtr(0x1000)] = Const CPtr(0x1008) @@ -5411,8 +5497,10 @@ mod tests { "); assert_snapshot!(hir_string_proc("test"), @r" fn block in test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -5431,8 +5519,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_definedivar); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5458,8 +5547,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_definedivar); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5487,8 +5577,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_defined); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5519,8 +5610,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_leave); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -5553,8 +5646,10 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 v3:NilClass = Const Value(nil) Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject): @@ -5589,8 +5684,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_plus); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -5611,8 +5709,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_minus); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -5633,8 +5734,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_mult); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -5655,8 +5759,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_div); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -5677,8 +5784,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_mod); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -5699,8 +5809,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_eq); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -5721,8 +5834,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_neq); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -5743,8 +5859,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_lt); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -5765,8 +5884,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_le); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -5787,8 +5909,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_gt); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -5816,8 +5941,9 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) v3:NilClass = Const Value(nil) Jump bb2(v1, v2, v3) @@ -5861,8 +5987,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_ge); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -5888,8 +6017,9 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -5924,8 +6054,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_send_without_block); assert_snapshot!(hir_string("test"), @r" fn test@:6: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -5952,8 +6083,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_send); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -5977,8 +6110,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_intern); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -6002,8 +6136,9 @@ mod tests { // The 2 string literals have the same address because they're deduped. assert_snapshot!(hir_string("test"), @r" fn test@:1: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -6030,8 +6165,10 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6049,8 +6186,10 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6069,8 +6208,10 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6088,8 +6229,10 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6110,8 +6253,9 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -6130,8 +6274,9 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -6150,8 +6295,9 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -6171,8 +6317,10 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6187,8 +6335,10 @@ mod tests { eval("def forwardable(...) = nil"); assert_snapshot!(hir_string("forwardable"), @r" fn forwardable@:1: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6209,8 +6359,10 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6237,8 +6389,10 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:ArrayExact): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:ArrayExact = GetLocal l0, SP@4, * Jump bb2(v1, v2) bb1(v5:BasicObject, v6:ArrayExact): EntryPoint JIT(0) @@ -6258,8 +6412,10 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6278,8 +6434,13 @@ mod tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:ArrayExact, v4:BasicObject, v5:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@8 + v3:ArrayExact = GetLocal l0, SP@7, * + v4:BasicObject = GetLocal l0, SP@6 + v5:BasicObject = GetLocal l0, SP@5 v6:NilClass = Const Value(nil) Jump bb2(v1, v2, v3, v4, v5, v6) bb1(v9:BasicObject, v10:BasicObject, v11:ArrayExact, v12:BasicObject, v13:BasicObject): @@ -6304,8 +6465,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_new); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -6337,8 +6499,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_newarray_send); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -6359,8 +6522,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_newarray_send); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -6386,8 +6552,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_newarray_send); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@7 + v3:BasicObject = GetLocal l0, SP@6 v4:NilClass = Const Value(nil) v5:NilClass = Const Value(nil) Jump bb2(v1, v2, v3, v4, v5) @@ -6415,8 +6584,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_newarray_send); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@7 + v3:BasicObject = GetLocal l0, SP@6 v4:NilClass = Const Value(nil) v5:NilClass = Const Value(nil) Jump bb2(v1, v2, v3, v4, v5) @@ -6444,8 +6616,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_newarray_send); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@7 + v3:BasicObject = GetLocal l0, SP@6 v4:NilClass = Const Value(nil) v5:NilClass = Const Value(nil) Jump bb2(v1, v2, v3, v4, v5) @@ -6477,8 +6652,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_newarray_send); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@7 + v3:BasicObject = GetLocal l0, SP@6 v4:NilClass = Const Value(nil) v5:NilClass = Const Value(nil) Jump bb2(v1, v2, v3, v4, v5) @@ -6501,8 +6679,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_length); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -6523,8 +6704,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_size); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -6546,8 +6730,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_getinstancevariable); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -6569,8 +6754,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_setinstancevariable); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -6593,8 +6779,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_setglobal); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -6616,8 +6803,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_getglobal); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -6637,8 +6825,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_splatarray); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6658,8 +6848,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_concattoarray); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6682,8 +6874,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_pushtoarray); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6705,8 +6899,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_pushtoarray); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6732,8 +6928,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_aset); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -6755,8 +6954,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_aref); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -6776,8 +6978,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_empty_p); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6797,8 +7001,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_succ); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6818,8 +7024,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_and); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -6839,8 +7048,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_or); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -6860,8 +7072,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_not); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -6881,8 +7095,11 @@ mod tests { assert_contains_opcode("test", YARVINSN_opt_regexpmatch2); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -6906,8 +7123,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_putspecialobject); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -6940,8 +7158,9 @@ mod tests { assert_contains_opcode("reverse_even", YARVINSN_opt_reverse); assert_snapshot!(hir_strings!("reverse_odd", "reverse_even"), @r" fn reverse_odd@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) v3:NilClass = Const Value(nil) v4:NilClass = Const Value(nil) @@ -6965,8 +7184,9 @@ mod tests { Return v33 fn reverse_even@:8: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) v3:NilClass = Const Value(nil) v4:NilClass = Const Value(nil) @@ -7003,8 +7223,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_branchnil); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -7026,8 +7248,12 @@ mod tests { assert_contains_opcode("Float", YARVINSN_opt_invokebuiltin_delegate_leave); assert_snapshot!(hir_string("Float"), @r" fn Float@: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject, v4:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@6 + v3:BasicObject = GetLocal l0, SP@5 + v4:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3, v4) bb1(v7:BasicObject, v8:BasicObject, v9:BasicObject, v10:BasicObject): EntryPoint JIT(0) @@ -7046,8 +7272,9 @@ mod tests { assert_contains_opcode("class", YARVINSN_opt_invokebuiltin_delegate_leave); assert_snapshot!(hir_string("class"), @r" fn class@: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7069,8 +7296,13 @@ mod tests { let function = iseq_to_hir(iseq).unwrap(); assert_snapshot!(hir_string_function(&function), @r" fn open@: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject, v4:BasicObject, v5:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@8 + v3:BasicObject = GetLocal l0, SP@7 + v4:BasicObject = GetLocal l0, SP@6 + v5:BasicObject = GetLocal l0, SP@5 v6:NilClass = Const Value(nil) Jump bb2(v1, v2, v3, v4, v5, v6) bb1(v9:BasicObject, v10:BasicObject, v11:BasicObject, v12:BasicObject, v13:BasicObject): @@ -7104,8 +7336,9 @@ mod tests { let function = iseq_to_hir(iseq).unwrap(); assert_snapshot!(hir_string_function(&function), @r" fn enable@: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7126,8 +7359,13 @@ mod tests { let function = iseq_to_hir(iseq).unwrap(); assert_snapshot!(hir_string_function(&function), @r" fn start@: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject, v4:BasicObject, v5:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@7 + v3:BasicObject = GetLocal l0, SP@6 + v4:BasicObject = GetLocal l0, SP@5 + v5:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3, v4, v5) bb1(v8:BasicObject, v9:BasicObject, v10:BasicObject, v11:BasicObject, v12:BasicObject): EntryPoint JIT(0) @@ -7148,8 +7386,10 @@ mod tests { assert_contains_opcode("test", YARVINSN_dupn); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -7180,8 +7420,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_objtostring); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7205,8 +7446,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_concatstrings); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7235,8 +7477,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_concatstrings); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7260,8 +7503,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_toregexp); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7290,8 +7534,9 @@ mod tests { assert_contains_opcode("test", YARVINSN_toregexp); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7319,8 +7564,9 @@ mod tests { assert_contains_opcode("throw_break", YARVINSN_throw); assert_snapshot!(hir_strings!("throw_return", "throw_break"), @r" fn block in @:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7330,8 +7576,9 @@ mod tests { Throw TAG_RETURN, v12 fn block in @:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7351,8 +7598,9 @@ mod tests { "#); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7373,8 +7621,11 @@ mod tests { "#); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -7414,8 +7665,11 @@ mod graphviz_tests { node [shape=plaintext]; mode=hier; overlap=false; splines=true; bb0 [label=< - + + + +
bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject) 
bb0() 
EntryPoint interpreter 
v1:BasicObject = LoadSelf 
v2:BasicObject = GetLocal l0, SP@5 
v3:BasicObject = GetLocal l0, SP@4 
Jump bb2(v1, v2, v3) 
>]; bb0:v4 -> bb2:params:n; @@ -7460,8 +7714,10 @@ mod graphviz_tests { node [shape=plaintext]; mode=hier; overlap=false; splines=true; bb0 [label=< - + + +
bb0(v1:BasicObject, v2:BasicObject) 
bb0() 
EntryPoint interpreter 
v1:BasicObject = LoadSelf 
v2:BasicObject = GetLocal l0, SP@4 
Jump bb2(v1, v2) 
>]; bb0:v3 -> bb2:params:n; @@ -7527,8 +7783,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -7558,8 +7815,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -7584,8 +7842,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7612,8 +7871,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7640,8 +7900,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7665,8 +7926,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7691,8 +7953,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -7726,8 +7990,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7757,8 +8022,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7793,8 +8059,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7824,8 +8091,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7860,8 +8128,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7891,8 +8160,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7922,8 +8192,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7954,8 +8225,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -7983,8 +8255,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -8010,8 +8284,10 @@ mod opt_tests { "); assert_snapshot!(hir_strings!("rest", "kw", "kw_rest", "block", "post"), @r" fn rest@:2: - bb0(v1:BasicObject, v2:ArrayExact): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:ArrayExact = GetLocal l0, SP@4, * Jump bb2(v1, v2) bb1(v5:BasicObject, v6:ArrayExact): EntryPoint JIT(0) @@ -8021,8 +8297,11 @@ mod opt_tests { Return v9 fn kw@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -8032,8 +8311,10 @@ mod opt_tests { Return v11 fn kw_rest@:4: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -8043,8 +8324,10 @@ mod opt_tests { Return v9 fn block@:6: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -8055,8 +8338,11 @@ mod opt_tests { Return v13 fn post@:5: - bb0(v1:BasicObject, v2:ArrayExact, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:ArrayExact = GetLocal l0, SP@5, * + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:ArrayExact, v8:BasicObject): EntryPoint JIT(0) @@ -8079,8 +8365,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:5: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -8107,8 +8394,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:5: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -8133,8 +8421,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:6: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -8158,8 +8447,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -8186,8 +8476,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:5: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -8218,8 +8509,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:7: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -8246,8 +8538,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -8276,8 +8569,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:7: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -8297,8 +8593,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -8321,8 +8620,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -8345,8 +8646,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -8369,8 +8672,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -8393,8 +8699,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -8417,8 +8725,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -8444,8 +8754,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -8473,8 +8784,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -8500,8 +8812,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -8525,8 +8839,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -8550,8 +8866,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -8575,8 +8893,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -8601,8 +8921,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -8628,8 +8949,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -8655,8 +8977,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -8687,8 +9010,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 v3:NilClass = Const Value(nil) Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject): @@ -8713,8 +9038,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -8740,8 +9066,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@6 + v3:BasicObject = GetLocal l0, SP@5 v4:NilClass = Const Value(nil) Jump bb2(v1, v2, v3, v4) bb1(v7:BasicObject, v8:BasicObject, v9:BasicObject): @@ -8770,8 +9099,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -8797,8 +9127,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -8825,8 +9156,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -8851,8 +9183,9 @@ mod opt_tests { "#); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -8879,8 +9212,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -8906,8 +9242,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -8933,8 +9272,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -8960,8 +9302,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -8988,8 +9333,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -9016,8 +9364,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -9043,8 +9394,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -9070,8 +9424,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -9097,8 +9454,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -9124,8 +9484,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -9151,8 +9514,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -9178,8 +9544,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9201,8 +9568,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -9223,8 +9592,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9248,8 +9618,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -9279,8 +9650,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:4: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -9310,8 +9682,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -9337,8 +9710,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9360,8 +9734,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9393,8 +9768,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9422,8 +9798,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:4: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9447,8 +9824,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -9475,8 +9853,9 @@ mod opt_tests { // Not specialized assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9497,8 +9876,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -9522,8 +9903,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 v3:NilClass = Const Value(nil) Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject): @@ -9550,8 +9933,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9584,8 +9968,10 @@ mod opt_tests { assert_snapshot!(hir_string("test"), @r" fn test@:8: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -9609,8 +9995,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9633,8 +10020,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9660,8 +10048,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:4: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -9689,8 +10078,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9713,8 +10103,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9735,8 +10126,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9756,8 +10148,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9779,8 +10172,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9801,8 +10195,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9822,8 +10217,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9851,8 +10247,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:8: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9875,8 +10272,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9909,8 +10307,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:7: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9939,8 +10338,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9968,8 +10368,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -9997,8 +10398,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10026,8 +10428,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10054,8 +10457,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10084,8 +10488,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10111,8 +10516,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10141,8 +10547,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -10163,8 +10572,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -10185,8 +10597,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -10207,8 +10621,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10228,8 +10643,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10250,8 +10666,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10274,8 +10691,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:5: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10292,8 +10710,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10314,8 +10733,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10336,8 +10756,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10358,8 +10779,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10379,8 +10801,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10401,8 +10824,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10423,8 +10847,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10445,8 +10870,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10466,8 +10892,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10488,8 +10915,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10511,8 +10939,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10534,8 +10963,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10555,8 +10985,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10577,8 +11008,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10600,8 +11032,9 @@ mod opt_tests { "##); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10623,8 +11056,9 @@ mod opt_tests { "##); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10651,8 +11085,10 @@ mod opt_tests { assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -10680,8 +11116,10 @@ mod opt_tests { assert_snapshot!(hir_string("test"), @r" fn test@:5: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -10706,8 +11144,10 @@ mod opt_tests { assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -10734,8 +11174,9 @@ mod opt_tests { assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -10761,8 +11202,9 @@ mod opt_tests { assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf v2:NilClass = Const Value(nil) Jump bb2(v1, v2) bb1(v5:BasicObject): @@ -10786,8 +11228,9 @@ mod opt_tests { "##); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10810,8 +11253,9 @@ mod opt_tests { "##); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10834,8 +11278,9 @@ mod opt_tests { "##); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10858,8 +11303,9 @@ mod opt_tests { "##); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10885,8 +11331,9 @@ mod opt_tests { "##); assert_snapshot!(hir_string("test"), @r" fn test@:5: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10911,8 +11358,9 @@ mod opt_tests { "##); assert_snapshot!(hir_string("test"), @r" fn test@:5: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10939,8 +11387,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:4: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10961,8 +11410,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -10981,8 +11431,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -11006,8 +11457,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -11028,8 +11480,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -11053,8 +11506,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -11077,8 +11531,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11101,8 +11557,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11125,8 +11583,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11149,8 +11609,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11173,8 +11635,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11197,8 +11661,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11221,8 +11687,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11245,8 +11713,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11269,8 +11739,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11293,8 +11765,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11318,8 +11792,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -11342,8 +11819,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -11367,8 +11847,11 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:2: - bb0(v1:BasicObject, v2:BasicObject, v3:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@5 + v3:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2, v3) bb1(v6:BasicObject, v7:BasicObject, v8:BasicObject): EntryPoint JIT(0) @@ -11394,8 +11877,9 @@ mod opt_tests { assert_snapshot!(hir_string("test"), @r" fn test@:3: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -11426,8 +11910,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:10: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11459,8 +11945,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:10: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11503,8 +11991,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:20: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11530,8 +12020,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:7: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -11562,8 +12053,9 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:7: - bb0(v1:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf Jump bb2(v1) bb1(v4:BasicObject): EntryPoint JIT(0) @@ -11593,8 +12085,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:6: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) @@ -11622,8 +12116,10 @@ mod opt_tests { "); assert_snapshot!(hir_string("test"), @r" fn test@:6: - bb0(v1:BasicObject, v2:BasicObject): + bb0(): EntryPoint interpreter + v1:BasicObject = LoadSelf + v2:BasicObject = GetLocal l0, SP@4 Jump bb2(v1, v2) bb1(v5:BasicObject, v6:BasicObject): EntryPoint JIT(0) diff --git a/zjit/src/state.rs b/zjit/src/state.rs index c0f81e1e856dec..fa5d3bc83f506c 100644 --- a/zjit/src/state.rs +++ b/zjit/src/state.rs @@ -8,6 +8,7 @@ use crate::asm::CodeBlock; use crate::options::get_option; use crate::stats::{Counters, ExitCounters}; use crate::virtualmem::CodePtr; +use std::collections::HashMap; #[allow(non_upper_case_globals)] #[unsafe(no_mangle)] @@ -46,6 +47,9 @@ pub struct ZJITState { /// Trampoline to call function_stub_hit function_stub_hit_trampoline: CodePtr, + + /// Counter pointers for unoptimized C functions + unoptimized_cfunc_counter_pointers: HashMap>, } /// Private singleton instance of the codegen globals @@ -80,6 +84,7 @@ impl ZJITState { exit_trampoline, function_stub_hit_trampoline, exit_trampoline_with_counter: exit_trampoline, + unoptimized_cfunc_counter_pointers: HashMap::new(), }; unsafe { ZJIT_STATE = Some(zjit_state); } @@ -138,6 +143,11 @@ impl ZJITState { &mut ZJITState::get_instance().exit_counters } + /// Get a mutable reference to unoptimized cfunc counter pointers + pub fn get_unoptimized_cfunc_counter_pointers() -> &'static mut HashMap> { + &mut ZJITState::get_instance().unoptimized_cfunc_counter_pointers + } + /// Was --zjit-save-compiled-iseqs specified? pub fn should_log_compiled_iseqs() -> bool { get_option!(log_compiled_iseqs).is_some() diff --git a/zjit/src/stats.rs b/zjit/src/stats.rs index 6d4525084ef849..42dc44538ada0a 100644 --- a/zjit/src/stats.rs +++ b/zjit/src/stats.rs @@ -384,6 +384,13 @@ pub extern "C" fn rb_zjit_stats(_ec: EcPtr, _self: VALUE, target_key: VALUE) -> set_stat_f64!(hash, "ratio_in_zjit", 100.0 * zjit_insn_count as f64 / total_insn_count as f64); } + // Set unoptimized cfunc counters + let unoptimized_cfuncs = ZJITState::get_unoptimized_cfunc_counter_pointers(); + for (signature, counter) in unoptimized_cfuncs.iter() { + let key_string = format!("not_optimized_cfuncs_{}", signature); + set_stat_usize!(hash, &key_string, **counter); + } + hash }