pub struct Structurer<'a> {Show 15 fields
pub cfg: &'a Cfg,
pub results: &'a Vec<BlockResult>,
pub diamond_merges: HashSet<usize>,
pub fold_regions: HashMap<usize, (usize, HashSet<usize>)>,
pub fold_root_to_merge: HashMap<usize, usize>,
pub copied_tails: HashSet<usize>,
pub loops_stack: Vec<usize>,
pub switch_depth: usize,
pub case_arm_ctx: Vec<(usize, Option<usize>, bool)>,
pub sese_loop_headers: HashSet<usize>,
pub sese_exc_retry_headers: HashSet<usize>,
pub groups: Vec<TryGroup>,
pub body_group: HashMap<usize, usize>,
pub handler_group: HashMap<usize, usize>,
pub final_fields: HashSet<String>,
/* private fields */
}Fields§
§cfg: &'a Cfg§results: &'a Vec<BlockResult>§diamond_merges: HashSet<usize>Blocks whose operand stack was folded from a pure value diamond.
fold_regions: HashMap<usize, (usize, HashSet<usize>)>Folded diamond regions: merge block -> (root header, absorbed blocks). When the walk reaches a root header, the whole region collapses: the absorbed blocks are claimed and the walk continues at the merge.
fold_root_to_merge: HashMap<usize, usize>Reverse index: root header -> merge block.
copied_tails: HashSet<usize>Heads of shared-tail regions that were copy-walked into a scope (a RawGoto targeting one is natural fallthrough at conversion).
loops_stack: Vec<usize>Headers of loops currently being structured (nesting barriers).
switch_depth: usizeNesting depth of structure_switch case walks: >0 while walking
inside another switch’s case regions. A stop-confluence follow of
a NESTED switch crosses construct boundaries (it is typically the
ENCLOSING switch’s own follow) — passing it as this switch’s
follow makes conversion resolve the case-tail goto to a bare
break that binds to the WRONG (inner) switch.
case_arm_ctx: Vec<(usize, Option<usize>, bool)>Innermost switch case-arm walk context: (case head block, that
switch’s region follow, selector is a Java 21+ typeSwitch pattern
switch). A nested switch whose stop-confluence equals the ENCLOSING
pattern switch’s follow may keep the plain-break binding when it is
the LAST construct of the case arm AND the arm walk is the case-arm
walk itself: the pattern-switch restoration appends the case’s
terminal break;, which lands on the outer follow == the
confluence, so both bindings are equivalent and the plain one keeps
the appended outer break reachable (ClassPrinterImpl.toYaml/toXml).
Classic switches get NO appended break (case fall-through) — the
crossing nulling must stay for them (bkeyword’s inner default
return '?' must not degrade to break + fall-through).
sese_loop_headers: HashSet<usize>Loop headers detected at the SESE method level (including
exception-edge back edges from no-normal-pred retry handlers).
Walk-based sub-builders consult this so a retry goto header
keeps loop precedence and resolves to continue (jdk26
Future.exceptionNow).
sese_exc_retry_headers: HashSet<usize>Subset of sese_loop_headers discovered via EXCEPTION-mediated back edges (handler-flow retry gotos). The walk loop branch trusts only this subset: normal back edges must keep failing the scoped dominance check (the loop belongs to an enclosing scope then — structuring it from the inner scope degraded ThreadPoolExecutor / the blocking-queue family: int-boolean conditions, catch-less tries x6 per tree).
groups: Vec<TryGroup>§body_group: HashMap<usize, usize>Outermost group index owning each body block.
handler_group: HashMap<usize, usize>Group index owning each handler head block.
final_fields: HashSet<String>Final fields of the emitting class: SESE must not duplicate a
shared terminator block that assigns one (a final accepts exactly
one assignment per path — jdk17 Long$LongCache clinit tail
cache = archivedCache; return; copied into a branch =
“variable cache might already have been assigned”).
Implementations§
Source§impl<'a> Structurer<'a>
impl<'a> Structurer<'a>
pub fn structure_method_sese(&mut self) -> Region
Sourcepub fn stmt_splice_pathology(s: &Stmt) -> bool
pub fn stmt_splice_pathology(s: &Stmt) -> bool
Scan a converted Stmt tree for splice pathologies (see materialize_content_exits). Conservative: any hit rolls the exit back to the bare-break shape.
Source§impl<'a> Structurer<'a>
impl<'a> Structurer<'a>
pub fn new(cfg: &'a Cfg, results: &'a Vec<BlockResult>) -> Structurer<'a>
pub fn with_diamonds( cfg: &'a Cfg, results: &'a Vec<BlockResult>, diamond_merges: HashSet<usize>, fold_regions: HashMap<usize, (usize, HashSet<usize>)>, ) -> Structurer<'a>
Sourcepub fn with_precomputed_groups(
cfg: &'a Cfg,
results: &'a Vec<BlockResult>,
groups: Vec<TryGroup>,
diamond_merges: HashSet<usize>,
fold_regions: HashMap<usize, (usize, HashSet<usize>)>,
) -> Structurer<'a>
pub fn with_precomputed_groups( cfg: &'a Cfg, results: &'a Vec<BlockResult>, groups: Vec<TryGroup>, diamond_merges: HashSet<usize>, fold_regions: HashMap<usize, (usize, HashSet<usize>)>, ) -> Structurer<'a>
Constructor for callers that already computed the exception groups
(e.g. to share them with the Converter): skips the internal
group_exceptions_with recompute. The body/handler maps derive
from the passed groups exactly as with_diamonds derives them.
Sourcepub fn structure_method(&mut self) -> Region
pub fn structure_method(&mut self) -> Region
Structure the whole method.
Sourcepub fn structure_method_walk(&mut self) -> Region
pub fn structure_method_walk(&mut self) -> Region
The verified walk baseline, ungated: the SESE hybrid fallback in method.rs runs it on a fresh Structurer to compare emission counts.