mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-15 02:44:47 +01:00
prepare the polyfill of struct/Object instruction
This commit is contained in:
parent
c029ef2a88
commit
4e3c11553f
@ -0,0 +1,74 @@
|
||||
/*
|
||||
Copyright 2019 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.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
*/
|
||||
package de.inetsoftware.jwebassembly.javascript;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import de.inetsoftware.jwebassembly.module.SyntheticFunctionName;
|
||||
import de.inetsoftware.jwebassembly.wasm.AnyType;
|
||||
|
||||
/**
|
||||
* Synthetic JavaScript import function.
|
||||
*
|
||||
* @author Volker Berlin
|
||||
*
|
||||
*/
|
||||
public class JavaScriptSyntheticFunctionName extends SyntheticFunctionName {
|
||||
|
||||
private final Supplier<String> js;
|
||||
|
||||
/**
|
||||
* Create a synthetic function which based on imported, dynamic generated JavaScript.
|
||||
*
|
||||
* @param module
|
||||
* the module name
|
||||
* @param functionName
|
||||
* the name of the function
|
||||
* @param js
|
||||
* the dynamic JavaScript as a lambda expression
|
||||
* @param signature
|
||||
* the types of the signature
|
||||
*/
|
||||
public JavaScriptSyntheticFunctionName( String module, String functionName, Supplier<String> js, AnyType... signature ) {
|
||||
super( module, functionName, signature );
|
||||
this.js = js;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected boolean hasWasmCode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected Function<String, Object> getAnnotation() {
|
||||
return ( key ) -> {
|
||||
switch( key ) {
|
||||
case JavaScriptWriter.JAVA_SCRIPT_CONTENT:
|
||||
return js.get();
|
||||
default:
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
}
|
@ -94,8 +94,8 @@ public class ModuleGenerator {
|
||||
this.javaScript = new JavaScriptWriter( target );
|
||||
this.libraries = new URLClassLoader( libraries.toArray( new URL[libraries.size()] ) );
|
||||
types.init( properties );
|
||||
javaCodeBuilder.init( types, properties );
|
||||
((WasmCodeBuilder)watParser).init( types, properties );
|
||||
javaCodeBuilder.init( types, functions, properties );
|
||||
((WasmCodeBuilder)watParser).init( types, functions, properties );
|
||||
scanLibraries( libraries );
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ import de.inetsoftware.jwebassembly.watparser.WatParser;
|
||||
*
|
||||
* @author Volker Berlin
|
||||
*/
|
||||
abstract class SyntheticFunctionName extends FunctionName {
|
||||
public abstract class SyntheticFunctionName extends FunctionName {
|
||||
|
||||
private final AnyType[] signature;
|
||||
|
||||
@ -60,7 +60,7 @@ abstract class SyntheticFunctionName extends FunctionName {
|
||||
*
|
||||
* @return true, if WASM code
|
||||
*/
|
||||
abstract boolean hasWasmCode();
|
||||
protected abstract boolean hasWasmCode();
|
||||
|
||||
/**
|
||||
* Get the WasmCodeBuilder for the synthetic WASM code.
|
||||
@ -69,7 +69,7 @@ abstract class SyntheticFunctionName extends FunctionName {
|
||||
* a helping WatParser
|
||||
* @return the code
|
||||
*/
|
||||
WasmCodeBuilder getCodeBuilder( WatParser watParser ) {
|
||||
protected WasmCodeBuilder getCodeBuilder( WatParser watParser ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ abstract class SyntheticFunctionName extends FunctionName {
|
||||
*
|
||||
* @return the annotation
|
||||
*/
|
||||
Function<String, Object> getAnnotation() {
|
||||
protected Function<String, Object> getAnnotation() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -206,7 +206,7 @@ public class TypeManager {
|
||||
methods = new ArrayList<>();
|
||||
HashSet<String> allNeededFields = new HashSet<>();
|
||||
listStructFields( name, functions, types, libraries, allNeededFields );
|
||||
code = writer.writeStructType( this );
|
||||
code = types.useGC ? writer.writeStructType( this ) : ValueType.anyref.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,7 +31,6 @@ import de.inetsoftware.classparser.MethodInfo;
|
||||
import de.inetsoftware.jwebassembly.JWebAssembly;
|
||||
import de.inetsoftware.jwebassembly.WasmException;
|
||||
import de.inetsoftware.jwebassembly.javascript.NonGC;
|
||||
import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
|
||||
import de.inetsoftware.jwebassembly.module.WasmInstruction.Type;
|
||||
import de.inetsoftware.jwebassembly.wasm.AnyType;
|
||||
import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
|
||||
@ -55,6 +54,8 @@ public abstract class WasmCodeBuilder {
|
||||
|
||||
private TypeManager types;
|
||||
|
||||
private FunctionManager functions;
|
||||
|
||||
private boolean useGC;
|
||||
|
||||
/**
|
||||
@ -84,12 +85,15 @@ public abstract class WasmCodeBuilder {
|
||||
*
|
||||
* @param types
|
||||
* the type manager
|
||||
* @param functions
|
||||
* the function manager
|
||||
* @param properties
|
||||
* compiler properties
|
||||
*/
|
||||
void init( TypeManager types, HashMap<String, String> properties ) {
|
||||
void init( TypeManager types, FunctionManager functions, HashMap<String, String> properties ) {
|
||||
this.localVariables.init( types );
|
||||
this.types = types;
|
||||
this.functions = functions;
|
||||
this.useGC = Boolean.parseBoolean( properties.getOrDefault( JWebAssembly.WASM_USE_GC, "false" ) );
|
||||
}
|
||||
|
||||
@ -380,6 +384,14 @@ public abstract class WasmCodeBuilder {
|
||||
* the line number in the Java source code
|
||||
*/
|
||||
protected void addStructInstruction( StructOperator op, @Nonnull String typeName, @Nullable NamedStorageType fieldName, int javaCodePos, int lineNumber ) {
|
||||
instructions.add( new WasmStructInstruction( op, typeName, fieldName, javaCodePos, lineNumber, types ) );
|
||||
WasmStructInstruction structInst = new WasmStructInstruction( op, typeName, fieldName, javaCodePos, lineNumber, types );
|
||||
instructions.add( structInst );
|
||||
if( !useGC ) {
|
||||
SyntheticFunctionName name = structInst.createNonGcFunction();
|
||||
if( name != null ) {
|
||||
functions.markAsNeeded( name, true );
|
||||
functions.markAsImport( name, name.getAnnotation() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import de.inetsoftware.jwebassembly.WasmException;
|
||||
import de.inetsoftware.jwebassembly.javascript.JavaScriptSyntheticFunctionName;
|
||||
import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
|
||||
import de.inetsoftware.jwebassembly.wasm.AnyType;
|
||||
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
|
||||
@ -43,6 +44,8 @@ class WasmStructInstruction extends WasmInstruction {
|
||||
|
||||
private final NamedStorageType fieldName;
|
||||
|
||||
private SyntheticFunctionName functionName;
|
||||
|
||||
/**
|
||||
* Create an instance of numeric operation.
|
||||
*
|
||||
@ -56,6 +59,8 @@ class WasmStructInstruction extends WasmInstruction {
|
||||
* the code position/offset in the Java method
|
||||
* @param lineNumber
|
||||
* the line number in the Java source code
|
||||
* @param types
|
||||
* the type manager
|
||||
*/
|
||||
WasmStructInstruction( @Nullable StructOperator op, @Nullable String typeName, @Nullable NamedStorageType fieldName, int javaCodePos, int lineNumber, TypeManager types ) {
|
||||
super( javaCodePos, lineNumber );
|
||||
@ -67,6 +72,34 @@ class WasmStructInstruction extends WasmInstruction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the synthetic polyfill function of this instruction for nonGC mode.
|
||||
*
|
||||
* @return the function or null if not needed
|
||||
*/
|
||||
SyntheticFunctionName createNonGcFunction() {
|
||||
switch( op ) {
|
||||
case NEW:
|
||||
case NEW_DEFAULT:
|
||||
functionName = new JavaScriptSyntheticFunctionName( "NonGC", "new_" + getSciptTypeName(), () -> "{}", null, type );
|
||||
break;
|
||||
case SET:
|
||||
AnyType type = fieldName.getType();
|
||||
functionName = new JavaScriptSyntheticFunctionName( "NonGC", "set_" + getSciptTypeName(), () -> "(a,i,v) => a[i]=v", type, null, null );
|
||||
break;
|
||||
case GET:
|
||||
type = fieldName.getType();
|
||||
functionName = new JavaScriptSyntheticFunctionName( "NonGC", "get_" + getSciptTypeName(), () -> "(a,i) => a[i]", type, null, type );
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return functionName;
|
||||
}
|
||||
|
||||
private String getSciptTypeName() {
|
||||
return type.getName().replace( '/', '_' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the StructOperator
|
||||
*
|
||||
@ -123,7 +156,12 @@ class WasmStructInstruction extends WasmInstruction {
|
||||
}
|
||||
}
|
||||
}
|
||||
writer.writeStructOperator( op, type, fieldName, idx );
|
||||
if( functionName != null ) { // nonGC
|
||||
//TODO idx
|
||||
writer.writeFunctionCall( functionName );
|
||||
} else {
|
||||
writer.writeStructOperator( op, type, fieldName, idx );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,7 +47,7 @@ class WatCodeSyntheticFunctionName extends SyntheticFunctionName {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
boolean hasWasmCode() {
|
||||
protected boolean hasWasmCode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ class WatCodeSyntheticFunctionName extends SyntheticFunctionName {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public WasmCodeBuilder getCodeBuilder( WatParser watParser ) {
|
||||
protected WasmCodeBuilder getCodeBuilder( WatParser watParser ) {
|
||||
watParser.parse( code, -1 );
|
||||
return watParser;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@ -79,12 +80,14 @@ public class TextModuleWriter extends ModuleWriter {
|
||||
|
||||
private boolean isPrepared;
|
||||
|
||||
private HashSet<String> globals = new HashSet<>();
|
||||
private HashMap<String,AnyType> globals = new HashMap<>();
|
||||
|
||||
private boolean useExceptions;
|
||||
|
||||
private boolean callIndirect;
|
||||
|
||||
private boolean useGC;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
@ -100,7 +103,8 @@ public class TextModuleWriter extends ModuleWriter {
|
||||
debugNames = Boolean.parseBoolean( properties.get( JWebAssembly.DEBUG_NAMES ) );
|
||||
output.append( "(module" );
|
||||
inset++;
|
||||
if( spiderMonkey ) {
|
||||
useGC = Boolean.parseBoolean( properties.getOrDefault( JWebAssembly.WASM_USE_GC, "false" ) );
|
||||
if( spiderMonkey && useGC ) {
|
||||
output.append( " (gc_feature_opt_in 3)" ); // enable GcFeatureOptIn for SpiderMonkey https://github.com/lars-t-hansen/moz-gc-experiments/blob/master/version2.md
|
||||
}
|
||||
}
|
||||
@ -117,6 +121,15 @@ public class TextModuleWriter extends ModuleWriter {
|
||||
|
||||
output.append( imports );
|
||||
|
||||
for( Entry<String, AnyType> entry : globals.entrySet() ) {
|
||||
output.append( "\n " );
|
||||
output.append( "(global $" ).append( entry.getKey() ).append( " (mut " );
|
||||
writeTypeName( output, entry.getValue() );
|
||||
output.append( ')' );
|
||||
writeDefaultValue( output, entry.getValue() );
|
||||
output.append( ')' );
|
||||
}
|
||||
|
||||
for( Function func : functions.values() ) {
|
||||
output.append( func.output );
|
||||
}
|
||||
@ -285,10 +298,12 @@ public class TextModuleWriter extends ModuleWriter {
|
||||
* if any I/O error occur
|
||||
*/
|
||||
private void writeTypeName( Appendable output, AnyType type ) throws IOException {
|
||||
if( type.getCode() < 0 ) {
|
||||
if( type instanceof ValueType ) {
|
||||
output.append( type.toString() );
|
||||
} else {
|
||||
} else if( useGC ) {
|
||||
output.append( "(ref " ).append( normalizeName( type.toString() ) ).append( ')' );
|
||||
} else {
|
||||
output.append( ValueType.anyref.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
@ -445,15 +460,9 @@ public class TextModuleWriter extends ModuleWriter {
|
||||
@Override
|
||||
protected void writeGlobalAccess( boolean load, FunctionName name, AnyType type ) throws IOException {
|
||||
String fullName = normalizeName( name.fullName );
|
||||
if( !globals.contains( fullName ) ) {
|
||||
if( !globals.containsKey( fullName ) ) {
|
||||
// declare global variable if not already declared.
|
||||
output.append( "\n " );
|
||||
output.append( "(global $" ).append( fullName ).append( " (mut " );
|
||||
writeTypeName( output, type );
|
||||
output.append( ')' );
|
||||
writeDefaultValue( output, type );
|
||||
output.append( ')' );
|
||||
globals.add( fullName );
|
||||
globals.put( fullName, type );
|
||||
}
|
||||
newline( methodOutput );
|
||||
methodOutput.append( load ? "global.get $" : "global.set $" ).append( fullName );
|
||||
|
@ -18,6 +18,7 @@ package de.inetsoftware.jwebassembly.runtime;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
@ -40,7 +41,10 @@ public class Structs extends AbstractBaseTest {
|
||||
@Parameters( name = "{0}-{1}" )
|
||||
public static Collection<Object[]> data() {
|
||||
ArrayList<Object[]> list = new ArrayList<>();
|
||||
for( ScriptEngine script : ScriptEngine.testEngines() ) {
|
||||
ScriptEngine[] engines = ScriptEngine.testEngines();
|
||||
engines = Arrays.copyOf( engines, engines.length + 1 );
|
||||
engines[engines.length - 1] = ScriptEngine.SpiderMonkeyGC;
|
||||
for( ScriptEngine script : engines ) {
|
||||
addParam( list, script, "isNull" );
|
||||
addParam( list, script, "isNotNull" );
|
||||
addParam( list, script, "isSame" );
|
||||
@ -57,7 +61,7 @@ public class Structs extends AbstractBaseTest {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
assumeTrue( getScriptEngine() == ScriptEngine.SpiderMonkey || getScriptEngine() == ScriptEngine.SpiderMonkeyWat );
|
||||
assumeTrue( getScriptEngine() == ScriptEngine.SpiderMonkeyGC );
|
||||
super.test();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user