pub struct VarTable {
pub vars: Vec<VarInfo>,
pub by_slot: Vec<Vec<(u16, u16, u32)>>,
pub has_lvt: bool,
pub stack_vars: Vec<u32>,
pub wide_stack_vars: HashSet<u32>,
pub force_concrete_vars: HashSet<u32>,
pub handler_starts: Vec<u16>,
}Fields§
§vars: Vec<VarInfo>§by_slot: Vec<Vec<(u16, u16, u32)>>Per slot: (range_start, range_end, var_id), sorted by range_start.
has_lvt: bool§stack_vars: Vec<u32>Synthetic stack-merge variables (need declaration hoisting).
wide_stack_vars: HashSet<u32>Merge variables whose branches disagreed on type (or carried a generic/plain-Object value); they must stay Object so every branch assignment type-checks. Evidence inference may not narrow them.
force_concrete_vars: HashSet<u32>Variables whose declared type must render as the CONCRETE class
(via shorten_concrete), NOT the anonymous-class → SAM-interface
fallback. A $<digits> desugared/suspend-lambda local that owns a
non-static FIELD access (v.L$0 = obj, the Kotlin coroutine
capture fields) needs its concrete type: interfaces carry no
instance fields, so Function2 v; v.L$0 is “找不到符号 变量 L$0”.
Set by the front-end for single-concrete-typed field owners; the
phi case is excluded because a disagreed merge stays Object (in
wide_stack_vars), never a specific concrete class.
handler_starts: Vec<u16>Exception-table handler start pcs: an LVT range beginning at one
(or at its astore + 1/2) is a catch parameter binding. Such
ranges never receive forward store attribution — a store just
BEFORE a handler initializes the try-body variable, not the
catch param (jdk11 HostnameChecker.matchDNS: sni = new SNIHostName(..) at pc 8 landed on iae whose handler range
starts at 14, within the 8-byte lead-in — SNIHostName无法转换为
IllegalArgumentException).
Implementations§
Source§impl VarTable
impl VarTable
pub fn add_stack_var(&mut self, slot: u16, name: String, ty: TypeRef) -> u32
Sourcepub fn add_split(&mut self, slot: u16, name: String, ty: TypeRef) -> u32
pub fn add_split(&mut self, slot: u16, name: String, ty: TypeRef) -> u32
Allocate a synthetic variable that is NOT a stack-merge temp (e.g. a catch parameter); it must not be hoisted by the stack-var pass. Add a new variable identity for slot-reuse splitting (post-build; not registered in pc-range lookups).
pub fn add_catch_var(&mut self, slot: u16, name: String, ty: TypeRef) -> u32
Sourcepub fn at(&self, slot: u16, pc: u16) -> Option<u32>
pub fn at(&self, slot: u16, pc: u16) -> Option<u32>
Resolve the variable live at (pc, slot). Falls back to the nearest preceding range, then to any var on the slot.
Sourcepub fn sole_on_slot(&self, slot: u16) -> Option<u32>
pub fn sole_on_slot(&self, slot: u16) -> Option<u32>
The single variable covering a slot (when the slot is not reused).