mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +01:00
improve the compiling of exceptions
This commit is contained in:
parent
b9bbb1c56d
commit
cd2f07733d
@ -847,7 +847,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
break;
|
break;
|
||||||
case BLOCK:
|
case BLOCK:
|
||||||
codeStream.writeOpCode( BLOCK );
|
codeStream.writeOpCode( BLOCK );
|
||||||
codeStream.writeValueType( ValueType.empty ); // void; the return type of the block. currently we does not use it
|
codeStream.writeValueType( data == null ? ValueType.empty : (ValueType)data ); // void; the return type of the block.
|
||||||
break;
|
break;
|
||||||
case BR:
|
case BR:
|
||||||
codeStream.writeOpCode( BR );
|
codeStream.writeOpCode( BR );
|
||||||
@ -879,6 +879,18 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
|||||||
case CATCH:
|
case CATCH:
|
||||||
codeStream.writeOpCode( CATCH );
|
codeStream.writeOpCode( CATCH );
|
||||||
break;
|
break;
|
||||||
|
case THROW:
|
||||||
|
codeStream.writeOpCode( THROW );
|
||||||
|
codeStream.writeVaruint32( 0 ); // event/exception ever 0 because currently there is only one with signature anyref
|
||||||
|
break;
|
||||||
|
case RETHROW:
|
||||||
|
codeStream.writeOpCode( RETHROW );
|
||||||
|
break;
|
||||||
|
case BR_ON_EXN:
|
||||||
|
codeStream.writeOpCode( BR_ON_EXN );
|
||||||
|
codeStream.writeVaruint32( (Integer)data ); // break depth
|
||||||
|
codeStream.writeVaruint32( 0 ); // event/exception ever 0 because currently there is only one with signature anyref
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error( "Unknown block: " + op );
|
throw new Error( "Unknown block: " + op );
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,9 @@ class BranchManger {
|
|||||||
|
|
||||||
private final HashMap<Integer, ParsedBlock> loops = new HashMap<>();
|
private final HashMap<Integer, ParsedBlock> loops = new HashMap<>();
|
||||||
|
|
||||||
private final List<WasmInstruction> instructions;
|
private final List<WasmInstruction> instructions;
|
||||||
|
|
||||||
|
private TryCatchFinally[] exceptionTable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a branch manager.
|
* Create a branch manager.
|
||||||
@ -71,7 +73,7 @@ class BranchManger {
|
|||||||
root.clear();
|
root.clear();
|
||||||
loops.clear();
|
loops.clear();
|
||||||
root.endPos = code.getCodeSize();
|
root.endPos = code.getCodeSize();
|
||||||
TryCatchFinally[] exceptionTable = code.getExceptionTable();
|
exceptionTable = code.getExceptionTable();
|
||||||
for( TryCatchFinally ex : exceptionTable ) {
|
for( TryCatchFinally ex : exceptionTable ) {
|
||||||
allParsedOperations.add( new TryCatchParsedBlock( ex ) );
|
allParsedOperations.add( new TryCatchParsedBlock( ex ) );
|
||||||
}
|
}
|
||||||
@ -588,6 +590,36 @@ class BranchManger {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the needed nodes for try/catch
|
* Calculate the needed nodes for try/catch
|
||||||
|
* Sample: The follow Java code:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* try {
|
||||||
|
* code1
|
||||||
|
* catch(Exception ex)
|
||||||
|
* code2
|
||||||
|
* }
|
||||||
|
* code3
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* Should be converted to the follow Wasm code for tableswitch:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* block
|
||||||
|
* block (result anyref)
|
||||||
|
* try
|
||||||
|
* code1
|
||||||
|
* catch
|
||||||
|
* br_on_exn 1 0
|
||||||
|
* rethrow
|
||||||
|
* end
|
||||||
|
* br 1
|
||||||
|
* end
|
||||||
|
* local.set x
|
||||||
|
* code2
|
||||||
|
* end
|
||||||
|
* code3
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
* @param parent
|
* @param parent
|
||||||
* the parent branch
|
* the parent branch
|
||||||
* @param tryBlock
|
* @param tryBlock
|
||||||
@ -595,14 +627,14 @@ class BranchManger {
|
|||||||
* @param parsedOperations
|
* @param parsedOperations
|
||||||
* the not consumed operations in the parent branch
|
* the not consumed operations in the parent branch
|
||||||
*/
|
*/
|
||||||
private void calculateTry ( BranchNode parent, TryCatchParsedBlock tryBlock, List<ParsedBlock> parsedOperations ) {
|
private void calculateTry( BranchNode parent, TryCatchParsedBlock tryBlock, List<ParsedBlock> parsedOperations ) {
|
||||||
TryCatchFinally tryCatch = tryBlock.tryCatch;
|
TryCatchFinally tryCatch = tryBlock.tryCatch;
|
||||||
|
|
||||||
int gotoPos = tryCatch.getEnd(); // alternativ we can use tryCatch.getHandler()-3
|
int gotoPos = tryCatch.getEnd(); // alternativ we can use tryCatch.getHandler()-3
|
||||||
int endPos = parent.endPos;
|
int endPos = parent.endPos;
|
||||||
for( int i = 0; i < parsedOperations.size(); i++ ) {
|
for( int i = 0; i < parsedOperations.size(); i++ ) {
|
||||||
ParsedBlock parsedBlock = parsedOperations.get( i );
|
ParsedBlock parsedBlock = parsedOperations.get( i );
|
||||||
if( parsedBlock.startPosition == gotoPos && parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition < parsedBlock.endPosition) {
|
if( parsedBlock.startPosition == gotoPos && parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition < parsedBlock.endPosition ) {
|
||||||
parsedOperations.remove( i );
|
parsedOperations.remove( i );
|
||||||
endPos = parsedBlock.endPosition;
|
endPos = parsedBlock.endPosition;
|
||||||
break;
|
break;
|
||||||
@ -611,8 +643,40 @@ class BranchManger {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parent.add( new BranchNode( tryBlock.startPosition, tryCatch.getHandler(), WasmBlockOperator.TRY, null ) );
|
int startPos = tryBlock.startPosition;
|
||||||
parent.add( new BranchNode( tryCatch.getHandler(), endPos, WasmBlockOperator.CATCH, WasmBlockOperator.END ) );
|
int catchPos = tryCatch.getHandler();
|
||||||
|
BranchNode node = new BranchNode( startPos, endPos, WasmBlockOperator.BLOCK, WasmBlockOperator.END );
|
||||||
|
parent.add( node );
|
||||||
|
parent = node;
|
||||||
|
|
||||||
|
node = new BranchNode( startPos, catchPos, WasmBlockOperator.BLOCK, WasmBlockOperator.END, ValueType.anyref );
|
||||||
|
parent.add( node );
|
||||||
|
parent = node;
|
||||||
|
|
||||||
|
parent.add( new BranchNode( startPos, catchPos, WasmBlockOperator.TRY, null ) );
|
||||||
|
BranchNode catchNode = new BranchNode( catchPos, catchPos, WasmBlockOperator.CATCH, WasmBlockOperator.END );
|
||||||
|
parent.add( catchNode );
|
||||||
|
|
||||||
|
catchNode.add( new BranchNode( catchPos, catchPos, WasmBlockOperator.BR_ON_EXN, null, 1 ) );
|
||||||
|
catchNode.add( new BranchNode( catchPos, catchPos, WasmBlockOperator.RETHROW, null ) );
|
||||||
|
|
||||||
|
parent.add( new BranchNode( catchPos, catchPos, WasmBlockOperator.BR, null, 1 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if there are a start of a catch block on the code position.
|
||||||
|
*
|
||||||
|
* @param codePosition
|
||||||
|
* the code position
|
||||||
|
* @return true, if there is a catch block
|
||||||
|
*/
|
||||||
|
boolean isCatch( int codePosition ) {
|
||||||
|
for( TryCatchFinally tryCatch : exceptionTable ) {
|
||||||
|
if( tryCatch.getHandler() == codePosition ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -241,7 +241,11 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
|
|||||||
case 76: // astore_1
|
case 76: // astore_1
|
||||||
case 77: // astore_2
|
case 77: // astore_2
|
||||||
case 78: // astore_3
|
case 78: // astore_3
|
||||||
storeType = findPreviousPushInstructionPushValueType();
|
if( branchManager.isCatch( codePos ) ) {
|
||||||
|
storeType = ValueType.anyref; // for the catch there are no previous instructions
|
||||||
|
} else {
|
||||||
|
storeType = findPreviousPushInstructionPushValueType();
|
||||||
|
}
|
||||||
addLoadStoreInstruction( storeType, false, op - 75, codePos );
|
addLoadStoreInstruction( storeType, false, op - 75, codePos );
|
||||||
break;
|
break;
|
||||||
case 79: // iastore
|
case 79: // iastore
|
||||||
@ -556,7 +560,7 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
|
|||||||
ref = (ConstantRef)constantPool.get( byteCode.readUnsignedShort() );
|
ref = (ConstantRef)constantPool.get( byteCode.readUnsignedShort() );
|
||||||
addStructInstruction( StructOperator.SET, ref.getClassName(), ref.getName(), codePos );
|
addStructInstruction( StructOperator.SET, ref.getClassName(), ref.getName(), codePos );
|
||||||
break;
|
break;
|
||||||
//TODO case 182: // invokevirtual
|
case 182: // invokevirtual
|
||||||
case 183: // invokespecial, invoke a constructor
|
case 183: // invokespecial, invoke a constructor
|
||||||
case 184: // invokestatic
|
case 184: // invokestatic
|
||||||
idx = byteCode.readUnsignedShort();
|
idx = byteCode.readUnsignedShort();
|
||||||
@ -603,7 +607,9 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
|
|||||||
case 190: // arraylength
|
case 190: // arraylength
|
||||||
addArrayInstruction( ArrayOperator.LENGTH, ValueType.i32, codePos );
|
addArrayInstruction( ArrayOperator.LENGTH, ValueType.i32, codePos );
|
||||||
break;
|
break;
|
||||||
//TODO case 191: // athrow
|
case 191: // athrow
|
||||||
|
addBlockInstruction( WasmBlockOperator.THROW, null, codePos );
|
||||||
|
break;
|
||||||
//TODO case 192: // checkcast
|
//TODO case 192: // checkcast
|
||||||
//TODO case 193: // instanceof
|
//TODO case 193: // instanceof
|
||||||
//TODO case 194: // monitorenter
|
//TODO case 194: // monitorenter
|
||||||
|
@ -389,6 +389,9 @@ public class TextModuleWriter extends ModuleWriter {
|
|||||||
break;
|
break;
|
||||||
case BLOCK:
|
case BLOCK:
|
||||||
name = "block";
|
name = "block";
|
||||||
|
if( data != null ) {
|
||||||
|
name += " (result " + data + ")";
|
||||||
|
}
|
||||||
insetAfter++;
|
insetAfter++;
|
||||||
break;
|
break;
|
||||||
case BR:
|
case BR:
|
||||||
@ -420,6 +423,15 @@ public class TextModuleWriter extends ModuleWriter {
|
|||||||
name = "catch";
|
name = "catch";
|
||||||
insetAfter++;
|
insetAfter++;
|
||||||
break;
|
break;
|
||||||
|
case THROW:
|
||||||
|
name = "throw 0"; // currently there is only one event/exception with anyref
|
||||||
|
break;
|
||||||
|
case RETHROW:
|
||||||
|
name = "rethrow";
|
||||||
|
break;
|
||||||
|
case BR_ON_EXN:
|
||||||
|
name = "br_on_exn " + data + " 0"; // br_on_exn, break depth, event; // currently there is only one event/exception with anyref
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error( "Unknown block: " + op );
|
throw new Error( "Unknown block: " + op );
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2018 Volker Berlin (i-net software)
|
Copyright 2018 - 2019 Volker Berlin (i-net software)
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@ -36,4 +36,7 @@ public enum WasmBlockOperator {
|
|||||||
UNREACHABLE,
|
UNREACHABLE,
|
||||||
TRY,
|
TRY,
|
||||||
CATCH,
|
CATCH,
|
||||||
|
THROW,
|
||||||
|
RETHROW,
|
||||||
|
BR_ON_EXN,
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user