Use also RETURN in the BranchManager to calculate the IF THEN ELSE blocks.

This commit is contained in:
Volker Berlin 2022-02-19 22:15:56 +01:00
parent 7f9353833e
commit 9f0f82bb06
4 changed files with 123 additions and 32 deletions

View File

@ -100,7 +100,7 @@ class BranchManager {
}
/**
* Add a new Java block operator to handle from this manager.
* Add a new GOTO operator to handle from this manager.
*
* @param startPosition
* the byte position of the start position
@ -115,6 +115,20 @@ class BranchManager {
allParsedOperations.add( new ParsedBlock( JavaBlockOperator.GOTO, startPosition, offset, nextPosition, lineNumber ) );
}
/**
* Add a new RETURN to help analyze structures.
*
* @param startPosition
* the byte position of the start position
* @param nextPosition
* the position of the next instruction
* @param lineNumber
* the current line number
*/
void addReturnOperator( int startPosition, int nextPosition, int lineNumber ) {
allParsedOperations.add( new ParsedBlock( JavaBlockOperator.RETURN, startPosition, 0, nextPosition, lineNumber ) );
}
/**
* Add a new IF operator.
*
@ -375,6 +389,9 @@ class BranchManager {
case TRY:
calculateTry( parent, (TryCatchParsedBlock)parsedBlock, parsedOperations );
break;
case RETURN:
// noting, only use as alternative GOTO
break;
default:
throw new WasmException( "Unimplemented block code operation: " + parsedBlock.op, parsedBlock.lineNumber );
}
@ -462,35 +479,50 @@ class BranchManager {
BranchNode branch = null;
for( ; i < parsedOperations.size(); i++ ) {
ParsedBlock parsedBlock = parsedOperations.get( i );
if( parsedBlock.nextPosition == positions.elsePos && parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition < parsedBlock.endPosition ) {
parsedOperations.remove( i );
// end position can not be outside of the parent
endPos = Math.min( parsedBlock.endPosition, parent.endPos );
branch = new BranchNode( startPos, positions.elsePos, WasmBlockOperator.IF, null );
parent.add( branch );
if( i > 0 ) {
calculate( branch, parsedOperations.subList( 0, i ) );
i = 0;
if( parsedBlock.nextPosition == positions.elsePos ) {
boolean endPosFound = false;
if( parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition < parsedBlock.endPosition ) {
parsedOperations.remove( i );
endPos = parsedBlock.endPosition;
endPosFound = true;
} else if( parsedBlock.op == JavaBlockOperator.RETURN ) {
for( int k = 0; k < i; k++ ) {
ParsedBlock block = parsedOperations.get( k );
if( block.op == JavaBlockOperator.IF ) {
endPos = Math.max( endPos, block.endPosition );
}
}
endPosFound = true;
}
if( endPosFound ) {
// end position can not be outside of the parent
endPos = Math.min( endPos, parent.endPos );
if( addBreakIfLoopContinue( branch, parsedBlock ) ) {
branch.endOp = WasmBlockOperator.END;
endPos = branch.endPos;
branch = new BranchNode( startPos, positions.elsePos, WasmBlockOperator.IF, null );
parent.add( branch );
if( i > 0 ) {
calculate( branch, parsedOperations.subList( 0, i ) );
i = 0;
}
if( addBreakIfLoopContinue( branch, parsedBlock ) ) {
branch.endOp = WasmBlockOperator.END;
endPos = branch.endPos;
break;
}
// if with block type signature must have an else block
int breakDeep = calculateBreakDeep( parent, endPos );
if( breakDeep > 0 ) {
branch.endOp = WasmBlockOperator.END;
branch.add( new BranchNode( positions.elsePos, endPos, WasmBlockOperator.BR, null, breakDeep + 1 ) );
endPos = branch.endPos;
} else {
branch.elseEndPos = endPos;
branch = new BranchNode( positions.elsePos, endPos, WasmBlockOperator.ELSE, WasmBlockOperator.END );
parent.add( branch );
}
break;
}
// if with block type signature must have an else block
int breakDeep = calculateBreakDeep( parent, endPos );
if( breakDeep > 0 ) {
branch.endOp = WasmBlockOperator.END;
branch.add( new BranchNode( positions.elsePos, endPos, WasmBlockOperator.BR, null, breakDeep + 1 ) );
endPos = branch.endPos;
} else {
branch.elseEndPos = endPos;
branch = new BranchNode( positions.elsePos, endPos, WasmBlockOperator.ELSE, WasmBlockOperator.END );
parent.add( branch );
}
break;
}
if( parsedBlock.nextPosition >= positions.elsePos ) {
break;
@ -562,10 +594,18 @@ class BranchManager {
newElsePositionFound = false;
for( int j = i; j < parsedOpCount; j++ ) {
parsedBlock = parsedOperations.get( j );
if( parsedBlock.op == JavaBlockOperator.GOTO ) {
if( parsedBlock.nextPosition == endElse ) {
break LOOP;
}
switch( parsedBlock.op ) {
case IF:
break;
case GOTO:
if( parsedBlock.nextPosition == endElse ) {
break LOOP;
}
break;
default:
if( parsedBlock.nextPosition < endElse ) {
break LOOP;
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
Copyright 2018 Volker Berlin (i-net software)
Copyright 2018 - 2022 Volker Berlin (i-net software)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -28,4 +28,5 @@ public enum JavaBlockOperator {
SWITCH,
LOOP,
TRY,
RETURN,
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2018 - 2021 Volker Berlin (i-net software)
* Copyright 2018 - 2022 Volker Berlin (i-net software)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -593,6 +593,7 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
type = null;
}
addBlockInstruction( WasmBlockOperator.RETURN, type, codePos, lineNumber );
branchManager.addReturnOperator( codePos, byteCode.getCodePosition(), lineNumber );
break;
case 178: // getstatic
ConstantRef ref = (ConstantRef)constantPool.get( byteCode.readUnsignedShort() );

View File

@ -85,6 +85,11 @@ public class ControlFlowOperators extends AbstractBaseTest {
addParam( list, script, "conditionalInsideIf_2" );
addParam( list, script, "conditionalInsideIf_3" );
addParam( list, script, "conditionalInsideIf_4" );
addParam( list, script, "ifWithReturn8" );
addParam( list, script, "ifWithReturn17" );
addParam( list, script, "ifWithReturn21" );
addParam( list, script, "ifWithReturn27" );
addParam( list, script, "ifWithReturn28" );
addParam( list, script, "stringSwitchNormalFoo" );
addParam( list, script, "stringSwitchNormalBar" );
addParam( list, script, "stringSwitchNormalDefault" );
@ -684,6 +689,50 @@ public class ControlFlowOperators extends AbstractBaseTest {
}
}
@Export
static int ifWithReturn8() {
return ifWithReturn( 8, 0 );
}
@Export
static int ifWithReturn17() {
return ifWithReturn( 8, 13 );
}
@Export
static int ifWithReturn21() {
return ifWithReturn( 8, 5 );
}
@Export
static int ifWithReturn27() {
return ifWithReturn( 0, 0 );
}
@Export
static int ifWithReturn28() {
return ifWithReturn( 0, 1 );
}
private static int ifWithReturn( int a, int b ) {
if( a > 7 ) {
if( b > 1 ) {
if( b == 13 ) {
return 17;
} else {
return 21;
}
}
} else {
if( a == b ) {
return 27;
} else {
return 28;
}
}
return a;
}
@Export
static int stringSwitchNormalFoo() {
return stringSwitchNormal( "foo" );