Class BranchManager
java.lang.Object
de.inetsoftware.jwebassembly.module.BranchManager
This calculate the goto offsets from Java back to block operations
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static class
Described a code branch/block node in a tree structure.private static class
Described a break to a block that will be added later.private static class
Description of a parsed IF operation.private static class
Positions inside a IF control structure.private static class
Description of single block/branch from the parsed Java byte code.private static class
Helper structure for caculateSwitchprivate static class
Description of a parsed switch structure.private static class
Description of a parsed try-Catch structure. -
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final ArrayList
<BranchManager.ParsedBlock> private final ArrayList
<BranchManager.BreakBlock> private TryCatchFinally[]
private final List
<WasmInstruction> private final LocaleVariableManager
private final HashMap
<Integer, BranchManager.ParsedBlock> private final WasmOptions
private final BranchManager.BranchNode
-
Constructor Summary
ConstructorsConstructorDescriptionBranchManager
(WasmOptions options, List<WasmInstruction> instructions, LocaleVariableManager localVariables) Create a branch manager. -
Method Summary
Modifier and TypeMethodDescriptionprivate boolean
addBreakIfLoopContinue
(BranchManager.BranchNode parent, BranchManager.ParsedBlock startBlock) Add a break to the node if the block jump to the continue position of an outer loop.(package private) void
addGotoOperator
(int startPosition, int offset, int nextPosition, int lineNumber) Add a new GOTO operator to handle from this manager.(package private) void
addIfOperator
(int startPosition, int offset, int lineNumber, WasmNumericInstruction instr) Add a new IF operator.private void
addLoops
(List<BranchManager.ParsedBlock> parsedOperations) In the compiled Java byte code there is no marker for the start of loop.(package private) void
addReturnOperator
(int startPosition, int nextPosition, int lineNumber) Add a new RETURN to help analyze structures.(package private) void
addSwitchOperator
(int startPosition, int offset, int lineNumber, int[] keys, int[] positions, int defaultPosition) Add a new switch block.private void
addUnboxExnref
(BranchManager.BranchNode catchNode, TryCatchFinally tryCatch) Add an unboxing of the WASm exnref on the stack(package private) void
Calculate all block operators from the parsed information.private void
calculate
(BranchManager.BranchNode parent, List<BranchManager.ParsedBlock> parsedOperations) Calculate the branch tree for the given branch and parsed sub operations.private void
calculateBreak
(BranchManager.BreakBlock breakBlock) Add the break to the block hierarchy.private int
calculateBreakDeep
(BranchManager.BranchNode parent, int endPos) Calculate the deep of a break.private int
calculateContinueDeep
(BranchManager.BranchNode parent, int startPos) Calculate the break deep for a continue in a do while(condition) loop.private void
calculateGoto
(BranchManager.BranchNode parent, BranchManager.ParsedBlock gotoBlock, List<BranchManager.ParsedBlock> parsedOperations) The not consumed GOTO operators of IF THEN ELSE must be break or continue in a loop.private void
calculateIf
(BranchManager.BranchNode parent, BranchManager.IfParsedBlock startBlock, List<BranchManager.ParsedBlock> parsedOperations) Calculate the ELSE and END position of an IF control structure.private void
calculateLoop
(BranchManager.BranchNode parent, BranchManager.ParsedBlock loopBlock, List<BranchManager.ParsedBlock> parsedOperations) Calculate the needed nodes for a loop.private void
calculateSwitch
(BranchManager.BranchNode parent, BranchManager.SwitchParsedBlock switchBlock, List<BranchManager.ParsedBlock> parsedOperations) Calculate the blocks of a switch.private void
calculateTry
(BranchManager.BranchNode parent, BranchManager.TryCatchParsedBlock tryBlock, List<BranchManager.ParsedBlock> parsedOperations) Calculate the needed nodes for try/catch Sample: The follow Java code:private void
calculateTrySubOperations
(BranchManager.BranchNode catchNode, BranchManager.BranchNode node, List<BranchManager.ParsedBlock> parsedOperations) Calculate branch operations inside the CATCH/FINALLY blocks.private void
convertToLoop
(BranchManager.ParsedBlock gotoBlock, int conditionStart, int conditionEnd) Convert the GOTO block with condition at the end into a loop block and move the condition from the end to the start like wasm it required.private int
findIdxOfCodePos
(int codePosition) Find the index of the instruction with the given code position.(package private) AnyType
getCatchType
(int codePosition) Get the catch type if there are a start of a catch block on the code position.private AnyType
getCatchType
(TryCatchFinally tryCatch) (package private) void
handle
(CodeInputStream byteCode) Check on every instruction position if there any branch is endingprivate void
insertConstBeforePosition
(int constant, int pos, int lineNumber) Insert a constant i32 operation before the given code positionprivate static void
normalizeEmptyThenBlocks
(List<BranchManager.ParsedBlock> parsedOperations) Normalize all empty THEN blocks like:private void
patchBrDeep
(BranchManager.BranchNode newNode) Patch the existing BR instructions after a new BLOCK node was injected in the hierarchy.private void
patchBrDeepInTree
(BranchManager.BranchNode newNode, int deep) Patch the existing BR instructions in the tree after a new BLOCK node was injected in the hierarchy.(package private) void
Remove all branch information for reusing the manager.private BranchManager.IfPositions
searchElsePosition
(BranchManager.IfParsedBlock startBlock, List<BranchManager.ParsedBlock> parsedOperations) Search the start positions of the THEN and ELSE branch from an IF control structure.
-
Field Details
-
allParsedOperations
-
root
-
loops
-
options
-
instructions
-
localVariables
-
exceptionTable
-
breakOperations
-
-
Constructor Details
-
BranchManager
public BranchManager(WasmOptions options, List<WasmInstruction> instructions, LocaleVariableManager localVariables) Create a branch manager.- Parameters:
options
- compiler option/propertiesinstructions
- the target for instructionslocalVariables
- the local variables
-
-
Method Details
-
reset
Remove all branch information for reusing the manager.- Parameters:
code
- the Java method code
-
addGotoOperator
void addGotoOperator(int startPosition, int offset, int nextPosition, int lineNumber) Add a new GOTO operator to handle from this manager.- Parameters:
startPosition
- the byte position of the start positionoffset
- the relative jump positionnextPosition
- the position of the next instructionlineNumber
- the current line number
-
addReturnOperator
void addReturnOperator(int startPosition, int nextPosition, int lineNumber) Add a new RETURN to help analyze structures.- Parameters:
startPosition
- the byte position of the start positionnextPosition
- the position of the next instructionlineNumber
- the current line number
-
addIfOperator
Add a new IF operator.- Parameters:
startPosition
- the byte position of the start positionoffset
- the relative jump positionlineNumber
- the current line numberinstr
- the compare instruction
-
addSwitchOperator
void addSwitchOperator(int startPosition, int offset, int lineNumber, int[] keys, int[] positions, int defaultPosition) Add a new switch block.- Parameters:
startPosition
- the byte position of the start positionoffset
- the relative jump positionlineNumber
- the current line numberkeys
- the values of the cases or null if a tableswitchpositions
- the code positionsdefaultPosition
- the code position of the default block
-
calculate
void calculate()Calculate all block operators from the parsed information. -
addLoops
In the compiled Java byte code there is no marker for the start of loop. But we need this marker. That we add a virtual loop operator on the target position of GOTO operators with a negative offset.- Parameters:
parsedOperations
- the parsed operations
-
convertToLoop
private void convertToLoop(BranchManager.ParsedBlock gotoBlock, int conditionStart, int conditionEnd) Convert the GOTO block with condition at the end into a loop block and move the condition from the end to the start like wasm it required.- Parameters:
gotoBlock
- the goto blockconditionStart
- the code position where condition code startconditionEnd
- the end position
-
normalizeEmptyThenBlocks
Normalize all empty THEN blocks like:if (condition) { } else { .... }
are changed to: if (!condition) { .... } The THEN block contains only a single GOTO operation. This operation is removed and the IF condition is negate. The removing of the GOTO operation make it easer to convert it to a valid WebAssembly structure without GOTO.- Parameters:
parsedOperations
- the parsed operations
-
calculate
private void calculate(BranchManager.BranchNode parent, List<BranchManager.ParsedBlock> parsedOperations) Calculate the branch tree for the given branch and parsed sub operations.- Parameters:
parent
- the parent branch/block in the hierarchy.parsedOperations
- the not consumed parsed operations of the parent block.
-
addBreakIfLoopContinue
private boolean addBreakIfLoopContinue(BranchManager.BranchNode parent, BranchManager.ParsedBlock startBlock) Add a break to the node if the block jump to the continue position of an outer loop.- Parameters:
parent
- the container for adding the breakstartBlock
- an IF or GOTO block.- Returns:
- true, if the break was added
-
calculateIf
private void calculateIf(BranchManager.BranchNode parent, BranchManager.IfParsedBlock startBlock, List<BranchManager.ParsedBlock> parsedOperations) Calculate the ELSE and END position of an IF control structure.- Parameters:
parent
- the parent branchstartBlock
- the start block of the if control structureparsedOperations
- the not consumed operations in the parent branch
-
searchElsePosition
private BranchManager.IfPositions searchElsePosition(BranchManager.IfParsedBlock startBlock, List<BranchManager.ParsedBlock> parsedOperations) Search the start positions of the THEN and ELSE branch from an IF control structure.- Parameters:
startBlock
- the start block of the IF control structureparsedOperations
- the not consumed operations in the parent branch- Returns:
- the calculated positions
-
insertConstBeforePosition
private void insertConstBeforePosition(int constant, int pos, int lineNumber) Insert a constant i32 operation before the given code position- Parameters:
constant
- the i32 valuepos
- the code positionlineNumber
- the line number for possible error messages
-
findIdxOfCodePos
private int findIdxOfCodePos(int codePosition) Find the index of the instruction with the given code position.- Parameters:
codePosition
- the java position- Returns:
- the index
-
calculateContinueDeep
Calculate the break deep for a continue in a do while(condition) loop.- Parameters:
parent
- current branchstartPos
- the start position of the loop- Returns:
- the deep count
-
calculateBreakDeep
Calculate the deep of a break. A GOTO or IF in Java can jump out multiple loops. We need to calculate how many levels we need to jump.- Parameters:
parent
- the current parent node.endPos
- the end position of the jump- Returns:
- the deep level for "br" or -1 if there is no parent node with this end position
-
calculateSwitch
private void calculateSwitch(BranchManager.BranchNode parent, BranchManager.SwitchParsedBlock switchBlock, List<BranchManager.ParsedBlock> parsedOperations) Calculate the blocks of a switch. Sample: The follow Java code:int b; switch( a ) { case 8: b = 1; break; default: b = 9; } return b;
Should be converted to the follow Wasm code for tableswitch:block block block get_local 0 i32.const 8 i32.sub br_table 0 1 end i32.const 1 set_local 1 br 1 end i32.const 9 set_local 1 end get_local 1 return
and for lookupswitchblock block block get_local 0 tee_local $switch i32.const 8 i32.eq br_if 0 br 1 end i32.const 1 set_local 1 br 1 end i32.const 9 set_local 1 end get_local 1 return
- Parameters:
parent
- the parent branchswitchBlock
- the start block of the if control structureparsedOperations
- the not consumed operations in the parent branch
-
patchBrDeep
Patch the existing BR instructions after a new BLOCK node was injected in the hierarchy. The break position must only increment if the old break position is outside of the new BLOCK.- Parameters:
newNode
- the new node
-
patchBrDeepInTree
Patch the existing BR instructions in the tree after a new BLOCK node was injected in the hierarchy. The break position must only increment if the old break position is outside of the new BLOCK.- Parameters:
newNode
- the new nodedeep
- the deep of recursion
-
calculateGoto
private void calculateGoto(@Nonnull BranchManager.BranchNode parent, @Nonnull BranchManager.ParsedBlock gotoBlock, List<BranchManager.ParsedBlock> parsedOperations) The not consumed GOTO operators of IF THEN ELSE must be break or continue in a loop.- Parameters:
parent
- the parent branchgotoBlock
- the GOTO operationparsedOperations
- the not consumed operations in the parent branch
-
calculateLoop
private void calculateLoop(BranchManager.BranchNode parent, BranchManager.ParsedBlock loopBlock, List<BranchManager.ParsedBlock> parsedOperations) Calculate the needed nodes for a loop.- Parameters:
parent
- the parent branchloopBlock
- the virtual LOOP operationparsedOperations
- the not consumed operations in the parent branch
-
calculateTry
private void calculateTry(BranchManager.BranchNode parent, BranchManager.TryCatchParsedBlock tryBlock, List<BranchManager.ParsedBlock> parsedOperations) Calculate the needed nodes for try/catch Sample: The follow Java code:try { code1 catch(Exception ex) code2 } code3
Should be converted to the follow Wasm code for try/catch:try code1 catch block (param exnref)(result anyref) br_on_exn 0 0 rethrow end local.tee $ex i32.const classIndex(Exception) call $.instanceof i32.eqz if local.get $ex throw 0 end code2 end code3
- Parameters:
parent
- the parent branchtryBlock
- the virtual TRY operationparsedOperations
- the not consumed operations in the parent branch
-
calculateTrySubOperations
private void calculateTrySubOperations(BranchManager.BranchNode catchNode, BranchManager.BranchNode node, List<BranchManager.ParsedBlock> parsedOperations) Calculate branch operations inside the CATCH/FINALLY blocks.- Parameters:
catchNode
- the parent nodenode
- the most inner nodeparsedOperations
- the not consumed operations in the parent branch
-
addUnboxExnref
Add an unboxing of the WASm exnref on the stack- Parameters:
catchNode
- the catch nodetryCatch
- the catch or finally block
-
getCatchType
-
getCatchType
Get the catch type if there are a start of a catch block on the code position.- Parameters:
codePosition
- the code position- Returns:
- the type or null
-
calculateBreak
Add the break to the block hierarchy. Add an extra block if needed and correct the break deep of other instructions.- Parameters:
breakBlock
- the description of the break.
-
handle
Check on every instruction position if there any branch is ending- Parameters:
byteCode
- the byte code stream
-