diff --git a/src/de/inetsoftware/jwebassembly/javascript/NonGC.java b/src/de/inetsoftware/jwebassembly/javascript/NonGC.java index 134de29..034f85c 100644 --- a/src/de/inetsoftware/jwebassembly/javascript/NonGC.java +++ b/src/de/inetsoftware/jwebassembly/javascript/NonGC.java @@ -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 ); } diff --git a/src/de/inetsoftware/jwebassembly/module/JavaMethodWasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/JavaMethodWasmCodeBuilder.java index 3cf742c..38f17ce 100644 --- a/src/de/inetsoftware/jwebassembly/module/JavaMethodWasmCodeBuilder.java +++ b/src/de/inetsoftware/jwebassembly/module/JavaMethodWasmCodeBuilder.java @@ -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 ); } /** diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java index 38d4a38..85f1773 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCodeBuilder.java @@ -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 ); } }