Class ControlFlowContext


  • public class ControlFlowContext
    extends Object
    Shared context for control flow recovery operations.
    • Constructor Detail

      • ControlFlowContext

        public ControlFlowContext​(IRMethod irMethod,
                                  DominatorTree dominatorTree,
                                  LoopAnalysis loopAnalysis,
                                  RecoveryContext expressionContext)
        Creates a recovery context over one method's analyses.
        Parameters:
        irMethod - the method being recovered
        dominatorTree - its dominator tree
        loopAnalysis - its loop analysis
        expressionContext - the expression-level recovery context
    • Method Detail

      • getIrMethod

        public IRMethod getIrMethod()
        Returns:
        the ir method
      • getDominatorTree

        public DominatorTree getDominatorTree()
        Returns:
        the dominator tree
      • getLoopAnalysis

        public LoopAnalysis getLoopAnalysis()
        Returns:
        the loop analysis
      • getExpressionContext

        public RecoveryContext getExpressionContext()
        Returns:
        the expression context
      • getProcessedBlocks

        public Set<IRBlock> getProcessedBlocks()
        Returns:
        the live set of blocks recovery has already consumed
      • getBlockStatements

        public Map<IRBlock,​List<Statement>> getBlockStatements()
        Returns:
        the recovered statements keyed by the block they came from
      • getBlockLabels

        public Map<IRBlock,​String> getBlockLabels()
        Returns:
        the labels generated for blocks that are break or continue targets
      • getLoopStack

        public Deque<ControlFlowContext.LoopFrame> getLoopStack()
        Returns:
        the enclosing loop frames, innermost first, which resolve break and continue targets and decide when a label is needed
      • getPendingStatements

        public List<Statement> getPendingStatements()
        Returns:
        the live queue of statements to emit before the next structured statement
      • getStopBlocksStack

        public Deque<Set<IRBlock>> getStopBlocksStack()
        Returns:
        the scoped stack of blocks that bound each enclosing control structure
      • getKnownFalseValuesStack

        public Deque<Set<SSAValue>> getKnownFalseValuesStack()
        Returns:
        the scoped stack of SSA values proven false or zero
      • getKnownFalseFieldsStack

        public Deque<Set<ControlFlowContext.FieldKey>> getKnownFalseFieldsStack()
        Returns:
        the scoped stack of fields, keyed by owner and name, proven false or zero
      • getSkipInstructionsStack

        public Deque<Set<IRInstruction>> getSkipInstructionsStack()
        Returns:
        the scoped stack of instruction sets recovery must not emit, such as a lifted for-loop increment
      • getForLoopInitInstructions

        public Set<IRInstruction> getForLoopInitInstructions()
        Returns:
        the instructions permanently skipped because a for-loop claimed them as initializers
      • getForLoopInductionLocalIndices

        public Set<Integer> getForLoopInductionLocalIndices()
        Returns:
        the local slots holding for-loop induction variables, whose PHI declarations are skipped
      • getForLoopInductionPhis

        public Set<SSAValue> getForLoopInductionPhis()
        Returns:
        the PHI results carrying for-loop induction variables, which must not be declared early
      • getForLoopHeaderBlocks

        public Set<IRBlock> getForLoopHeaderBlocks()
        Returns:
        the for-loop header blocks, which scope the induction local index checks
      • getLabelCounter

        public int getLabelCounter()
        Returns:
        the label counter
      • markProcessed

        public void markProcessed​(IRBlock block)
        Marks a block as emitted so it is not recovered a second time.
        Parameters:
        block - the block to mark
        Throws:
        NumberFormatException - if "yabr.debug.mark" is not an integer
      • isProcessed

        public boolean isProcessed​(IRBlock block)
        Parameters:
        block - the block to test
        Returns:
        true if the block has already been emitted
      • resetProcessedBlocks

        public void resetProcessedBlocks()
        Clears the emitted-block marks and their cached statements so a fresh recovery pass over the same method starts clean.
      • setStatements

        public void setStatements​(IRBlock block,
                                  List<Statement> stmts)
        Records the statements recovered for a block, replacing any earlier set.
        Parameters:
        block - the block
        stmts - its statements
      • getStatements

        public List<Statement> getStatements​(IRBlock block)
        Parameters:
        block - the block to look up
        Returns:
        its recovered statements, empty if none were recorded
      • setRegion

        public void setRegion​(IRBlock block,
                              ControlFlowContext.StructuredRegion region)
        Records the structured shape a block was recovered as.
        Parameters:
        block - the block
        region - the region shape
      • getOrCreateLabel

        public String getOrCreateLabel​(IRBlock block)
        Returns a block's break/continue label, minting "labelN" on first use.
        Parameters:
        block - the block to label
        Returns:
        the label name
      • hasLabel

        public boolean hasLabel​(IRBlock block)
        Parameters:
        block - the block to test
        Returns:
        true if a label has already been created for it
      • getLabel

        public String getLabel​(IRBlock block)
        Parameters:
        block - the block to look up
        Returns:
        its label, or null if none was created
      • pushLoop

        public void pushLoop​(IRBlock header,
                             IRBlock continueTarget,
                             IRBlock exit)
        Enters a loop scope so edges to its exit or continue-target classify as break or continue, recording the current scope depth for labeling.
        Parameters:
        header - the loop header, used as the label anchor
        continueTarget - where a continue jumps to
        exit - where a break jumps to
      • pushLoop

        public void pushLoop​(IRBlock header,
                             IRBlock continueTarget,
                             IRBlock exit,
                             IRBlock latch)
        As pushLoop(IRBlock, IRBlock, IRBlock) but records the loop's for-update latch.
        Parameters:
        header - the loop header, used as the label anchor
        continueTarget - where a continue jumps to
        exit - where a break jumps to
        latch - the update block that back-edges to the header
      • popLoop

        public void popLoop()
        Pops the innermost loop frame, if any.
      • pushSwitch

        public void pushSwitch​(IRBlock header,
                               IRBlock merge,
                               Set<IRBlock> caseHeaders)
        Enters a switch scope so edges to its merge or sibling cases classify as break or fall-through.
        Parameters:
        header - the switch header block
        merge - where control leaves the switch
        caseHeaders - the case entry blocks
      • popSwitch

        public void popSwitch()
        Pops the innermost switch frame, if any.
      • innermostLoopExit

        public IRBlock innermostLoopExit()
        Returns:
        the exit, that is the break target, of the innermost enclosing loop, or null when no loop encloses
      • innermostLoopHeader

        public IRBlock innermostLoopHeader()
        Returns:
        the header of the innermost enclosing loop, or null when no loop encloses
      • innermostLoopLatch

        public IRBlock innermostLoopLatch()
        Returns:
        the for-update latch of the innermost enclosing loop, or null when none encloses or it is not a counted loop
      • innermostSwitchMerge

        public IRBlock innermostSwitchMerge()
        Returns:
        the merge of the innermost enclosing switch, or null when no switch encloses
      • switchBoundaries

        public Set<IRBlock> switchBoundaries()
        The boundaries - case headers and merge - of every currently enclosing switch.
        Returns:
        the case headers and merges of every enclosing switch
      • inInnermostSwitchCase

        public boolean inInnermostSwitchCase​(IRBlock block)
        True when block lies in a case body of the innermost enclosing switch (is dominated by one of its case headers).
        Parameters:
        block - the block to locate
        Returns:
        true if a case header of the innermost switch dominates it
      • classifyLoopJump

        public ControlFlowContext.LoopJump classifyLoopJump​(IRBlock target)
        Classifies a control-flow edge into target.
        Parameters:
        target - the edge destination
        Returns:
        the loop jump and its label anchor, or null when the target is not a loop boundary
      • classifySwitchJump

        public ControlFlowContext.SwitchJump classifySwitchJump​(IRBlock target)
        Classifies an edge into target relative to the innermost switch.
        Parameters:
        target - the edge destination
        Returns:
        the switch jump, or null when the target is not an innermost-switch boundary
      • addPendingStatements

        public void addPendingStatements​(List<Statement> stmts)
        Queues statements to be emitted before the next structured statement, as header block instructions of an if or while need.
        Parameters:
        stmts - the statements to queue
      • collectPendingStatements

        public List<Statement> collectPendingStatements()
        Collects and clears any pending statements.
        Returns:
        the pending statements, now cleared from context
      • pushStopBlocks

        public void pushStopBlocks​(Set<IRBlock> stopBlocks)
        Enters a control structure whose recovery must stop at the given blocks.
        Parameters:
        stopBlocks - the blocks that bound this structure
      • popStopBlocks

        public void popStopBlocks()
        Pops the current stop blocks from the stack.
      • getAllStopBlocks

        public Set<IRBlock> getAllStopBlocks()
        Flattens the stop blocks of every enclosing scope so an inner structure honours the outer exit points too.
        Returns:
        the union of all pushed stop block sets
      • pushSkipInstructions

        public void pushSkipInstructions​(Set<IRInstruction> instructions)
        Enters a scope that suppresses instructions, as a for-loop does with the increment it lifted into its update clause.
        Parameters:
        instructions - the instructions recovery must not emit inside this scope
      • popSkipInstructions

        public void popSkipInstructions()
        Pops the current skip instructions from the stack.
      • shouldSkipInstruction

        public boolean shouldSkipInstruction​(IRInstruction instruction)
        Tests an instruction against the permanent for-loop init claims and every pushed skip set.
        Parameters:
        instruction - the instruction to test
        Returns:
        true if recovery should not emit it
      • markAsForLoopInit

        public void markAsForLoopInit​(IRInstruction instruction)
        Claims an instruction as a for-loop initializer, permanently skipping it in predecessor blocks because the loop inlines it into its init clause.
        Parameters:
        instruction - the initializing instruction
      • isForLoopInit

        public boolean isForLoopInit​(IRInstruction instruction)
        Parameters:
        instruction - the instruction to test
        Returns:
        true if a for-loop has claimed it as an initializer
      • markAsForLoopInductionLocal

        public void markAsForLoopInductionLocal​(int localIndex)
        Records a local slot as a for-loop induction variable so its PHI declaration is skipped - the variable is declared in the loop's init instead.
        Parameters:
        localIndex - the local slot
      • isForLoopInductionLocal

        public boolean isForLoopInductionLocal​(int localIndex)
        Parameters:
        localIndex - the local slot to test
        Returns:
        true if the slot holds a for-loop induction variable
      • markAsForLoopInductionPhi

        public void markAsForLoopInductionPhi​(SSAValue phiResult)
        Records a PHI as carrying a for-loop induction variable so its declaration is not emitted early.
        Parameters:
        phiResult - the PHI result value
      • isForLoopInductionPhi

        public boolean isForLoopInductionPhi​(SSAValue phiResult)
        Parameters:
        phiResult - the PHI result to test
        Returns:
        true if the PHI carries a for-loop induction variable
      • markAsForLoopHeader

        public void markAsForLoopHeader​(IRBlock block)
        Records a block as a for-loop header, which scopes the induction local checks.
        Parameters:
        block - the header block
      • isForLoopHeader

        public boolean isForLoopHeader​(IRBlock block)
        Parameters:
        block - the block to test
        Returns:
        true if the block was marked as a for-loop header
      • pushKnownFalseValues

        public void pushKnownFalseValues​(Set<SSAValue> values)
        Enters a scope in which the given values are proven false or zero, as the then-branch of an inverted condition is.
        Parameters:
        values - the SSA values pinned to false or zero
      • popKnownFalseValues

        public void popKnownFalseValues()
        Pops the current known false values from the stack.
      • isKnownFalse

        public boolean isKnownFalse​(SSAValue value)
        Searches every enclosing scope for a value pinned to false or zero.
        Parameters:
        value - the SSA value to test
        Returns:
        true if some enclosing scope proved it false or zero
      • popKnownFalseFields

        public void popKnownFalseFields()
        Pops the current known false fields from the stack.
      • isFieldKnownFalse

        public boolean isFieldKnownFalse​(String owner,
                                         String fieldName)
        Searches every enclosing scope for a field pinned to false or zero.
        Parameters:
        owner - the internal name of the class declaring the field
        fieldName - the field name
        Returns:
        true if some enclosing scope proved the field false or zero