add "ref_eq" polyfill function

This commit is contained in:
Volker Berlin 2019-09-08 21:45:28 +02:00
parent c5d514de73
commit 713020ef60
3 changed files with 38 additions and 21 deletions

View File

@ -18,7 +18,7 @@ package de.inetsoftware.jwebassembly.javascript;
import de.inetsoftware.jwebassembly.api.annotation.Import;
/**
* Workaround for the missing GC feature of WebAssembly. This call add import functions to allocate the objects in the JavaScript host.
* Workaround/polyfill for the missing GC feature of WebAssembly. This call add import functions to allocate the objects in the JavaScript host.
*
* @author Volker Berlin
*
@ -108,4 +108,7 @@ public abstract class NonGC {
@Import( js = "(a,i,v) => a[i]" )
native static Object array_get_anyref( Object[] array, int idx );
@Import( js = "(a,b) => a === b" )
native static Object ref_eq( Object a, Object b );
}

View File

@ -875,9 +875,8 @@ class JavaMethodWasmCodeBuilder extends WasmCodeBuilder {
*/
private void opIfCompareCondition( NumericOperator compareOp, CodeInputStream byteCode, int codePos, int lineNumber ) throws IOException {
int offset = byteCode.readShort();
WasmNumericInstruction compare = new WasmNumericInstruction( compareOp, ValueType.i32, codePos, lineNumber );
WasmNumericInstruction compare = addNumericInstruction( compareOp, ValueType.i32, codePos, lineNumber );
branchManager.addIfOperator( codePos, offset, byteCode.getLineNumber(), compare );
getInstructions().add( compare );
}
/**

View File

@ -257,9 +257,15 @@ public abstract class WasmCodeBuilder {
* the code position/offset in the Java method
* @param lineNumber
* the line number in the Java source code
* @return the added instruction
*/
protected void addNumericInstruction( @Nullable NumericOperator numOp, @Nullable ValueType valueType, int javaCodePos, int lineNumber ) {
instructions.add( new WasmNumericInstruction( numOp, valueType, javaCodePos, lineNumber ) );
protected WasmNumericInstruction addNumericInstruction( @Nullable NumericOperator numOp, @Nullable ValueType valueType, int javaCodePos, int lineNumber ) {
WasmNumericInstruction numeric = new WasmNumericInstruction( numOp, valueType, javaCodePos, lineNumber );
instructions.add( numeric );
if( !useGC && numOp == NumericOperator.ref_eq ) {
functions.markAsNeeded( getNonGC( "ref_eq", lineNumber ), true );
}
return numeric;
}
/**
@ -333,6 +339,26 @@ public abstract class WasmCodeBuilder {
instructions.add( new WasmNopInstruction( javaCodePos, lineNumber ) );
}
/**
* Get a non GC polyfill function.
* @param name the function name
* @param lineNumber the line number for a possible error
* @return the function name
*/
private FunctionName getNonGC( String name, int lineNumber ) {
try {
ClassFile classFile = ClassFile.get( NonGC.class.getName().replace( '.', '/' ), getClass().getClassLoader() );
for( MethodInfo method : classFile.getMethods() ) {
if( name.equals( method.getName() ) ) {
return new FunctionName( method );
}
}
} catch( IOException ex ) {
throw WasmException.create( ex, lineNumber );
}
throw new WasmException( "Not implemented NonGC polyfill function: " + name, lineNumber );
}
/**
* Add an array operation to the instruction list as marker on the code position.
*
@ -349,23 +375,12 @@ public abstract class WasmCodeBuilder {
if( useGC ) {
instructions.add( new WasmArrayInstruction( op, type, types, javaCodePos, lineNumber ) );
} else {
try {
if( type.getCode() >= 0 ) {
type = ValueType.anyref;
}
String api = "array_" + op.toString().toLowerCase() + "_" + type;
ClassFile classFile = ClassFile.get( NonGC.class.getName().replace( '.', '/' ), getClass().getClassLoader() );
for( MethodInfo method : classFile.getMethods() ) {
if( api.equals( method.getName() ) ) {
FunctionName name = new FunctionName( method );
addCallInstruction( name, javaCodePos, lineNumber );
return;
}
}
} catch( IOException ex ) {
throw WasmException.create( ex, lineNumber );
if( type.getCode() >= 0 ) {
type = ValueType.anyref;
}
throw new WasmException( "Not implemented array op " + op + " for type " + type, lineNumber );
String api = "array_" + op.toString().toLowerCase() + "_" + type;
FunctionName name = getNonGC( api, lineNumber );
addCallInstruction( name, javaCodePos, lineNumber );
}
}