mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 15:37:52 +01:00
first steps to compile loops
This commit is contained in:
parent
652d6c3d6a
commit
c8ef4fd3c7
@ -19,6 +19,8 @@ package de.inetsoftware.jwebassembly.module;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.inetsoftware.classparser.CodeInputStream;
|
import de.inetsoftware.classparser.CodeInputStream;
|
||||||
@ -36,12 +38,15 @@ class BranchManger {
|
|||||||
|
|
||||||
private final BranchNode root = new BranchNode( 0, Integer.MAX_VALUE, null, null );
|
private final BranchNode root = new BranchNode( 0, Integer.MAX_VALUE, null, null );
|
||||||
|
|
||||||
|
private final HashMap<Integer, ParsedBlock> loops = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all branch information for reusing the manager.
|
* Remove all branch information for reusing the manager.
|
||||||
*/
|
*/
|
||||||
void reset() {
|
void reset() {
|
||||||
allParsedOperations.clear();
|
allParsedOperations.clear();
|
||||||
root.clear();
|
root.clear();
|
||||||
|
loops.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,9 +89,40 @@ class BranchManger {
|
|||||||
* Calculate all block operators from the parsed information.
|
* Calculate all block operators from the parsed information.
|
||||||
*/
|
*/
|
||||||
void calculate() {
|
void calculate() {
|
||||||
|
addLoops();
|
||||||
|
Collections.sort( allParsedOperations, (a,b) -> Integer.compare( a.startPosition, b.startPosition ) );
|
||||||
calculate( root, allParsedOperations );
|
calculate( root, allParsedOperations );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
private void addLoops() {
|
||||||
|
for( ParsedBlock parsedBlock : allParsedOperations ) {
|
||||||
|
if( parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition > parsedBlock.endPosition ) {
|
||||||
|
int start = parsedBlock.endPosition;
|
||||||
|
ParsedBlock loop = loops.get( start );
|
||||||
|
if( loop == null ) {
|
||||||
|
loop = new ParsedBlock( JavaBlockOperator.LOOP, start, 0, parsedBlock.lineNumber );
|
||||||
|
loops.put( start, loop );
|
||||||
|
}
|
||||||
|
loop.endPosition = parsedBlock.startPosition + 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( ParsedBlock loop : loops.values() ) {
|
||||||
|
for( int i = 0; i < allParsedOperations.size(); i++ ) {
|
||||||
|
ParsedBlock parsedBlock = allParsedOperations.get( i );
|
||||||
|
if( loop.startPosition < parsedBlock.startPosition && loop.endPosition < parsedBlock.endPosition ) {
|
||||||
|
// fix overlapping from structures
|
||||||
|
loop.endPosition = parsedBlock.endPosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allParsedOperations.addAll( loops.values() );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the branch tree for the given branch and parsed sub operations.
|
* Calculate the branch tree for the given branch and parsed sub operations.
|
||||||
*
|
*
|
||||||
@ -103,6 +139,12 @@ class BranchManger {
|
|||||||
case SWITCH:
|
case SWITCH:
|
||||||
caculateSwitch( parent, (SwitchParsedBlock)parsedBlock, parsedOperations );
|
caculateSwitch( parent, (SwitchParsedBlock)parsedBlock, parsedOperations );
|
||||||
break;
|
break;
|
||||||
|
case GOTO:
|
||||||
|
caculateGoto( parent, parsedBlock, parsedOperations );
|
||||||
|
break;
|
||||||
|
case LOOP:
|
||||||
|
caculateLoop( parent, parsedBlock, parsedOperations );
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new WasmException( "Unimplemented block code operation: " + parsedBlock.op, null, parsedBlock.lineNumber );
|
throw new WasmException( "Unimplemented block code operation: " + parsedBlock.op, null, parsedBlock.lineNumber );
|
||||||
}
|
}
|
||||||
@ -126,7 +168,7 @@ class BranchManger {
|
|||||||
BranchNode branch = null;
|
BranchNode branch = null;
|
||||||
for( ; i < parsedOperations.size(); i++ ) {
|
for( ; i < parsedOperations.size(); i++ ) {
|
||||||
ParsedBlock parsedBlock = parsedOperations.get( i );
|
ParsedBlock parsedBlock = parsedOperations.get( i );
|
||||||
if( parsedBlock.startPosition == gotoPos && parsedBlock.op == JavaBlockOperator.GOTO ) {
|
if( parsedBlock.startPosition == gotoPos && parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition < parsedBlock.endPosition) {
|
||||||
parsedOperations.remove( i );
|
parsedOperations.remove( i );
|
||||||
branch = new BranchNode( startBlock.startPosition, startBlock.endPosition, WasmBlockOperator.IF, null );
|
branch = new BranchNode( startBlock.startPosition, startBlock.endPosition, WasmBlockOperator.IF, null );
|
||||||
parent.add( branch );
|
parent.add( branch );
|
||||||
@ -323,6 +365,59 @@ class BranchManger {
|
|||||||
int block;
|
int block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The not consumed GOTO operators of IF THEN ELSE must be break or continue in a loop.
|
||||||
|
*
|
||||||
|
* @param parent
|
||||||
|
* the parent branch
|
||||||
|
* @param gotoBlock
|
||||||
|
* the GOTO operation
|
||||||
|
* @param parsedOperations
|
||||||
|
* the not consumed operations in the parent branch
|
||||||
|
*/
|
||||||
|
private void caculateGoto ( BranchNode parent, ParsedBlock gotoBlock, List<ParsedBlock> parsedOperations ) {
|
||||||
|
int start = gotoBlock.endPosition;
|
||||||
|
int end = gotoBlock.startPosition;
|
||||||
|
if( end > start ) {
|
||||||
|
int deep = 0;
|
||||||
|
while( parent != null ) {
|
||||||
|
if( parent.startOp == WasmBlockOperator.LOOP && parent.startPos == start ) {
|
||||||
|
parent.add( new BranchNode( end, end, WasmBlockOperator.BR, null, deep ) ); // continue to the start of the loop
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parent = parent.parent;
|
||||||
|
deep++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new WasmException( "GOTO code without target loop/block", null, gotoBlock.lineNumber );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the needed nodes for a loop.
|
||||||
|
* @param parent
|
||||||
|
* the parent branch
|
||||||
|
* @param loopBlock
|
||||||
|
* the virtual LOOP operation
|
||||||
|
* @param parsedOperations
|
||||||
|
* the not consumed operations in the parent branch
|
||||||
|
*/
|
||||||
|
private void caculateLoop ( BranchNode parent, ParsedBlock loopBlock, List<ParsedBlock> parsedOperations ) {
|
||||||
|
BranchNode loopNode = new BranchNode( loopBlock.startPosition, loopBlock.endPosition, WasmBlockOperator.LOOP, WasmBlockOperator.END );
|
||||||
|
parent.add( loopNode );
|
||||||
|
|
||||||
|
int idx = 0;
|
||||||
|
for( ; idx < parsedOperations.size(); idx++ ) {
|
||||||
|
ParsedBlock parsedBlock = parsedOperations.get( idx );
|
||||||
|
if( parsedBlock.startPosition >= loopBlock.endPosition ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
calculate( loopNode, parsedOperations.subList( 0, idx ) );
|
||||||
|
// add the "br 0" as last child to receive the right order
|
||||||
|
loopNode.add( new BranchNode( loopBlock.endPosition, loopBlock.endPosition, WasmBlockOperator.BR, null, 0 ) ); // continue to the start of the loop
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check on every instruction position if there any branch is ending
|
* Check on every instruction position if there any branch is ending
|
||||||
*
|
*
|
||||||
@ -390,6 +485,8 @@ class BranchManger {
|
|||||||
|
|
||||||
private Object data;
|
private Object data;
|
||||||
|
|
||||||
|
private BranchNode parent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new description.
|
* Create a new description.
|
||||||
*
|
*
|
||||||
@ -428,6 +525,15 @@ class BranchManger {
|
|||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean add( BranchNode e ) {
|
||||||
|
e.parent = this;
|
||||||
|
return super.add( e );
|
||||||
|
}
|
||||||
|
|
||||||
void handle( int codePositions, ModuleWriter writer ) throws IOException {
|
void handle( int codePositions, ModuleWriter writer ) throws IOException {
|
||||||
if( codePositions < startPos || codePositions > endPos ) {
|
if( codePositions < startPos || codePositions > endPos ) {
|
||||||
return;
|
return;
|
||||||
|
@ -26,4 +26,5 @@ public enum JavaBlockOperator {
|
|||||||
IF,
|
IF,
|
||||||
GOTO,
|
GOTO,
|
||||||
SWITCH,
|
SWITCH,
|
||||||
|
LOOP,
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user