experimental exception handling

This commit is contained in:
Volker Berlin 2018-11-03 18:01:42 +01:00
parent ce3e2d7546
commit f15e9c8341
8 changed files with 79 additions and 9 deletions

View File

@ -749,6 +749,13 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
case UNREACHABLE: case UNREACHABLE:
codeStream.writeOpCode( UNREACHABLE ); codeStream.writeOpCode( UNREACHABLE );
break; break;
case TRY:
codeStream.writeOpCode( TRY );
codeStream.write( ValueType.empty.getCode() ); // void; the return type of the try. currently we does not use it
break;
case CATCH:
codeStream.writeOpCode( CATCH );
break;
default: default:
throw new Error( "Unknown block: " + op ); throw new Error( "Unknown block: " + op );
} }

View File

@ -26,6 +26,7 @@ import java.util.List;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import de.inetsoftware.classparser.CodeInputStream; import de.inetsoftware.classparser.CodeInputStream;
import de.inetsoftware.classparser.TryCatchFinally;
import de.inetsoftware.jwebassembly.WasmException; import de.inetsoftware.jwebassembly.WasmException;
/** /**
@ -57,10 +58,13 @@ class BranchManger {
/** /**
* Remove all branch information for reusing the manager. * Remove all branch information for reusing the manager.
*/ */
void reset() { void reset( TryCatchFinally[] exceptionTable ) {
allParsedOperations.clear(); allParsedOperations.clear();
root.clear(); root.clear();
loops.clear(); loops.clear();
for( TryCatchFinally ex : exceptionTable ) {
allParsedOperations.add( new TryCatchParsedBlock( ex ) );
}
} }
/** /**
@ -224,6 +228,9 @@ class BranchManger {
case LOOP: case LOOP:
calculateLoop( parent, parsedBlock, parsedOperations ); calculateLoop( parent, parsedBlock, parsedOperations );
break; break;
case TRY:
calculateTry( parent, (TryCatchParsedBlock)parsedBlock, parsedOperations );
break;
default: default:
throw new WasmException( "Unimplemented block code operation: " + parsedBlock.op, null, null, parsedBlock.lineNumber ); throw new WasmException( "Unimplemented block code operation: " + parsedBlock.op, null, null, parsedBlock.lineNumber );
} }
@ -569,6 +576,35 @@ class BranchManger {
// loopNode.add( new BranchNode( loopBlock.endPosition, loopBlock.endPosition, WasmBlockOperator.BR, null, 0 ) ); // continue to the start of the loop // loopNode.add( new BranchNode( loopBlock.endPosition, loopBlock.endPosition, WasmBlockOperator.BR, null, 0 ) ); // continue to the start of the loop
} }
/**
* Calculate the needed nodes for try/catch
* @param parent
* the parent branch
* @param tryBlock
* the virtual TRY operation
* @param parsedOperations
* the not consumed operations in the parent branch
*/
private void calculateTry ( BranchNode parent, TryCatchParsedBlock tryBlock, List<ParsedBlock> parsedOperations ) {
TryCatchFinally tryCatch = tryBlock.tryCatch;
int gotoPos = tryCatch.getEnd(); // alternativ we can use tryCatch.getHandler()-3
int endPos = parent.endPos;
for( int i = 0; i < parsedOperations.size(); i++ ) {
ParsedBlock parsedBlock = parsedOperations.get( i );
if( parsedBlock.startPosition == gotoPos && parsedBlock.op == JavaBlockOperator.GOTO && parsedBlock.startPosition < parsedBlock.endPosition) {
parsedOperations.remove( i );
endPos = parsedBlock.endPosition;
break;
}
if( parsedBlock.startPosition > gotoPos ) {
break;
}
}
parent.add( new BranchNode( tryBlock.startPosition, tryCatch.getHandler(), WasmBlockOperator.TRY, null ) );
parent.add( new BranchNode( tryCatch.getHandler(), endPos, WasmBlockOperator.CATCH, WasmBlockOperator.END ) );
}
/** /**
* Check on every instruction position if there any branch is ending * Check on every instruction position if there any branch is ending
* *
@ -682,6 +718,18 @@ class BranchManger {
} }
} }
/**
* Description of a parsed try-Catch structure.
*/
private static class TryCatchParsedBlock extends ParsedBlock {
private final TryCatchFinally tryCatch;
TryCatchParsedBlock( TryCatchFinally tryCatch ) {
super( JavaBlockOperator.TRY, tryCatch.getStart(), 0, -1 );
this.tryCatch = tryCatch;
}
}
/** /**
* Described a code branch/block node in a tree structure. * Described a code branch/block node in a tree structure.
*/ */

View File

@ -27,4 +27,5 @@ public enum JavaBlockOperator {
GOTO, GOTO,
SWITCH, SWITCH,
LOOP, LOOP,
TRY,
} }

View File

@ -159,7 +159,7 @@ public class ModuleGenerator {
writer.writeMethodStart( name ); writer.writeMethodStart( name );
localVariables.reset(); localVariables.reset();
branchManager.reset(); branchManager.reset( code.getExceptionTable() );
byteCode = code.getByteCode(); byteCode = code.getByteCode();
writeCode( byteCode, method.getConstantPool() ); writeCode( byteCode, method.getConstantPool() );
@ -388,10 +388,12 @@ public class ModuleGenerator {
case 74: // dstore_3 case 74: // dstore_3
instr = loadStore( ValueType.f64, false, op - 71, codePos ); instr = loadStore( ValueType.f64, false, op - 71, codePos );
break; break;
//TODO case 75: // astore_0 case 75: // astore_0
//TODO case 76: // astore_1 case 76: // astore_1
//TODO case 77: // astore_2 case 77: // astore_2
//TODO case 78: // astore_3 case 78: // astore_3
instr = loadStore( ValueType.anyref, false, op - 75, codePos );
break;
//TODO case 79: // iastore //TODO case 79: // iastore
//TODO case 80: // lastore //TODO case 80: // lastore
//TODO case 81: // fastore //TODO case 81: // fastore

View File

@ -34,4 +34,6 @@ public enum WasmBlockOperator {
BR_TABLE, BR_TABLE,
LOOP, LOOP,
UNREACHABLE, UNREACHABLE,
TRY,
CATCH,
} }

View File

@ -345,6 +345,15 @@ public class TextModuleWriter extends ModuleWriter {
case UNREACHABLE: case UNREACHABLE:
name = "unreachable"; name = "unreachable";
break; break;
case TRY:
name = "try";
insetAfter++;
break;
case CATCH:
inset--;
name = "catch";
insetAfter++;
break;
default: default:
throw new Error( "Unknown block: " + op ); throw new Error( "Unknown block: " + op );
} }

View File

@ -291,7 +291,7 @@ public class WasmRule extends TemporaryFolder {
* if the download failed * if the download failed
*/ */
private ProcessBuilder spiderMonkeyCommand() throws IOException { private ProcessBuilder spiderMonkeyCommand() throws IOException {
return new ProcessBuilder( spiderMonkey.getCommand(), spiderMonkeyScript.getAbsolutePath() ); return new ProcessBuilder( spiderMonkey.getCommand(), "--wasm-gc", spiderMonkeyScript.getAbsolutePath() );
} }
/** /**
@ -312,7 +312,8 @@ public class WasmRule extends TemporaryFolder {
command += "/bin/node"; command += "/bin/node";
} }
} }
return new ProcessBuilder( command, "--experimental-wasm-se", "--experimental-wasm-sat-f2i-conversions", script.getAbsolutePath() ); // details see with command: node --v8-options
return new ProcessBuilder( command, "--experimental-wasm-se", "--experimental-wasm-sat-f2i-conversions", "--experimental-wasm-eh", "--experimental-wasm-anyref", script.getAbsolutePath() );
} }
/** /**

View File

@ -6,7 +6,7 @@ var wabt = require("wabt")();
var filename = '{test.wat}'; var filename = '{test.wat}';
var text = nodeFS['readFileSync'](filename, "utf8"); var text = nodeFS['readFileSync'](filename, "utf8");
var features = {'sat_float_to_int':true, 'sign_extension':true}; var features = {'sat_float_to_int':true, 'sign_extension':true, 'exceptions':true};
var ret = wabt.parseWat(filename, text, features); var ret = wabt.parseWat(filename, text, features);
ret = ret.toBinary({}).buffer; ret = ret.toBinary({}).buffer;