|
1 | | -use crate::{ |
2 | | - asm::CodeBlock, backend::lir, backend::lir::{asm_comment, Assembler, Opnd, Target, CFP, C_ARG_OPNDS, EC, SP}, cruby::*, debug, hir::{Const, FrameState, Function, Insn, InsnId}, hir_type::{types::Fixnum, Type}, virtualmem::CodePtr |
3 | | -}; |
| 1 | +use crate::{asm::CodeBlock, cruby::*, debug, virtualmem::CodePtr}; |
| 2 | +use crate::invariants::{iseq_escapes_ep, track_no_ep_escape_assumption}; |
| 3 | +use crate::backend::lir::{self, asm_comment, Assembler, Opnd, Target, CFP, C_ARG_OPNDS, EC, SP}; |
| 4 | +use crate::hir::{Const, FrameState, Function, Insn, InsnId}; |
| 5 | +use crate::hir_type::{types::Fixnum, Type}; |
4 | 6 |
|
5 | 7 | /// Ephemeral code generation state |
6 | 8 | struct JITState { |
@@ -28,6 +30,15 @@ impl JITState { |
28 | 30 | } |
29 | 31 | opnd |
30 | 32 | } |
| 33 | + |
| 34 | + /// Assume that this ISEQ doesn't escape EP. Return false if it's known to escape EP. |
| 35 | + fn assume_no_ep_escape(&mut self) -> bool { |
| 36 | + if iseq_escapes_ep(self.iseq) { |
| 37 | + return false; |
| 38 | + } |
| 39 | + track_no_ep_escape_assumption(self.iseq); |
| 40 | + true |
| 41 | + } |
31 | 42 | } |
32 | 43 |
|
33 | 44 | /// Compile High-level IR into machine code |
@@ -104,17 +115,23 @@ fn gen_const(val: VALUE) -> Opnd { |
104 | 115 | } |
105 | 116 |
|
106 | 117 | /// Compile a method/block paramter read. For now, it only supports method parameters. |
107 | | -fn gen_param(jit: &JITState, asm: &mut Assembler, local_idx: usize) -> Option<lir::Opnd> { |
108 | | - // Get the EP of the current CFP |
109 | | - // TODO: Use the SP register and invalidate on EP escape |
110 | | - let ep_opnd = Opnd::mem(64, CFP, RUBY_OFFSET_CFP_EP); |
111 | | - let ep_reg = asm.load(ep_opnd); |
112 | | - |
113 | | - // Load the local variable |
114 | | - // val = *(vm_get_ep(GET_EP(), level) - idx); |
| 118 | +fn gen_param(jit: &mut JITState, asm: &mut Assembler, local_idx: usize) -> Option<lir::Opnd> { |
115 | 119 | let ep_offset = local_idx_to_ep_offset(jit.iseq, local_idx); |
116 | | - let offs = -(SIZEOF_VALUE_I32 * ep_offset); |
117 | | - let local_opnd = Opnd::mem(64, ep_reg, offs); |
| 120 | + |
| 121 | + let local_opnd = if jit.assume_no_ep_escape() { |
| 122 | + // Create a reference to the local variable using the SP register. We assume EP == BP. |
| 123 | + // TODO: Implement the invalidation in rb_zjit_invalidate_ep_is_bp() |
| 124 | + let offs = -(SIZEOF_VALUE_I32 * (ep_offset + 1)); |
| 125 | + Opnd::mem(64, SP, offs) |
| 126 | + } else { |
| 127 | + // Get the EP of the current CFP |
| 128 | + let ep_opnd = Opnd::mem(64, CFP, RUBY_OFFSET_CFP_EP); |
| 129 | + let ep_reg = asm.load(ep_opnd); |
| 130 | + |
| 131 | + // Create a reference to the local variable using cfp->ep |
| 132 | + let offs = -(SIZEOF_VALUE_I32 * ep_offset); |
| 133 | + Opnd::mem(64, ep_reg, offs) |
| 134 | + }; |
118 | 135 |
|
119 | 136 | Some(local_opnd) |
120 | 137 | } |
|
0 commit comments