use a synthetic function call to calculate the function id of a virtual call.

This commit is contained in:
Volker Berlin 2020-02-25 18:05:12 +01:00
parent db002f8d96
commit 02696a6488
15 changed files with 79 additions and 34 deletions

View File

@ -40,9 +40,9 @@ import de.inetsoftware.classparser.ClassFile;
import de.inetsoftware.jwebassembly.binary.BinaryModuleWriter;
import de.inetsoftware.jwebassembly.module.ModuleGenerator;
import de.inetsoftware.jwebassembly.module.ModuleWriter;
import de.inetsoftware.jwebassembly.module.WasmOptions;
import de.inetsoftware.jwebassembly.module.WasmTarget;
import de.inetsoftware.jwebassembly.text.TextModuleWriter;
import de.inetsoftware.jwebassembly.wasm.WasmOptions;
/**
* The main class of the compiler.

View File

@ -32,6 +32,7 @@ import de.inetsoftware.jwebassembly.module.FunctionName;
import de.inetsoftware.jwebassembly.module.ModuleWriter;
import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
import de.inetsoftware.jwebassembly.module.ValueTypeConvertion;
import de.inetsoftware.jwebassembly.module.WasmOptions;
import de.inetsoftware.jwebassembly.module.WasmTarget;
import de.inetsoftware.jwebassembly.sourcemap.SourceMapWriter;
import de.inetsoftware.jwebassembly.sourcemap.SourceMapping;
@ -44,7 +45,6 @@ import de.inetsoftware.jwebassembly.wasm.StructOperator;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.VariableOperator;
import de.inetsoftware.jwebassembly.wasm.WasmBlockOperator;
import de.inetsoftware.jwebassembly.wasm.WasmOptions;
/**
* Module Writer for binary format. http://webassembly.org/docs/binary-encoding/

View File

@ -25,7 +25,7 @@ import de.inetsoftware.jwebassembly.wasm.VariableOperator;
*
* @author Volker Berlin
*/
public class CodeOptimizer {
class CodeOptimizer {
/**
* Optimize the code before writing.

View File

@ -34,7 +34,7 @@ import de.inetsoftware.jwebassembly.WasmException;
*
* @author Volker Berlin
*/
public class FunctionManager {
class FunctionManager {
private final Map<FunctionName, FunctionState> states = new LinkedHashMap<>();

View File

@ -46,7 +46,6 @@ import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.StructOperator;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.WasmOptions;
import de.inetsoftware.jwebassembly.watparser.WatParser;
/**

View File

@ -33,7 +33,6 @@ import de.inetsoftware.jwebassembly.wasm.StructOperator;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.VariableOperator;
import de.inetsoftware.jwebassembly.wasm.WasmBlockOperator;
import de.inetsoftware.jwebassembly.wasm.WasmOptions;
/**
* Module Writer base class.

View File

@ -27,14 +27,13 @@ import javax.annotation.Nonnull;
import de.inetsoftware.jwebassembly.api.annotation.WasmTextCode;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.WasmOptions;
/**
* Handle all the constant strings. The constant strings will be write into the data section.
*
* @author Volker Berlin
*/
public class StringManager extends LinkedHashMap<String, Integer> {
class StringManager extends LinkedHashMap<String, Integer> {
/**
* Signature of method stringConstant.
@ -54,7 +53,7 @@ public class StringManager extends LinkedHashMap<String, Integer> {
* @param options
* compiler properties and shared managers
*/
public StringManager( WasmOptions options ) {
StringManager( WasmOptions options ) {
this.functions = options.functions;
}

View File

@ -23,6 +23,8 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
import de.inetsoftware.classparser.ClassFile;
import de.inetsoftware.classparser.ClassFile.Type;
import de.inetsoftware.classparser.ConstantClass;
@ -34,7 +36,6 @@ import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ArrayType;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.WasmOptions;
/**
* Manage the written and to write types (classes)
@ -60,7 +61,7 @@ public class TypeManager {
* @param options
* compiler properties
*/
public TypeManager( WasmOptions options ) {
TypeManager( WasmOptions options ) {
this.options = options;
}
@ -87,7 +88,7 @@ public class TypeManager {
* Get the StructType. If needed an instance is created.
*
* @param name
* the type name
* the type name like java/lang/Object
* @return the struct type
*/
public StructType valueOf( String name ) {
@ -123,6 +124,24 @@ public class TypeManager {
return type;
}
/**
* Get the FunctionName for a virtual call and mark it as used. The function has 2 parameters (THIS,
* virtualfunctionIndex) and returns the index of the function.
*
* @return the name
*/
@Nonnull
WatCodeSyntheticFunctionName getCallVirtualGC() {
return new WatCodeSyntheticFunctionName( //
"callVirtual", "local.get 0 " // THIS
+ "struct.get java/lang/Object .vtable " // vtable is on index 0
+ "local.get 1 " // virtualFunctionIndex
+ "i32.add " //
+ "i32.load offset=0 align=4 " //
+ "return " //
, valueOf( "java/lang/Object" ), ValueType.i32, null, ValueType.i32 ); //
}
/**
* A reference to a type.
*

View File

@ -22,12 +22,7 @@ import javax.annotation.Nonnull;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
import de.inetsoftware.jwebassembly.wasm.MemoryOperator;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.StructOperator;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.VariableOperator;
import de.inetsoftware.jwebassembly.wasm.WasmOptions;
/**
* WasmInstruction for a function call.

View File

@ -26,7 +26,6 @@ import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.StructOperator;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.VariableOperator;
import de.inetsoftware.jwebassembly.wasm.WasmOptions;
/**
* WasmInstruction for a function call.
@ -96,14 +95,9 @@ class WasmCallVirtualInstruction extends WasmCallIndirectInstruction {
// duplicate this on the stack
writer.writeLocal( VariableOperator.get, getVariableIndexOfThis() );
writer.writeConst( virtualFunctionIdx * 4, ValueType.i32 );
writer.writeFunctionCall( options.getCallVirtual() );
StructType type = getThisType();
if( options.useGC() ) {
writer.writeStructOperator( StructOperator.GET, type, new NamedStorageType( type, "", "vtable" ), 0 ); // vtable is ever on position 0
} else {
writer.writeConst( 0, ValueType.i32 ); // vtable is ever on position 0
writer.writeFunctionCall( WasmCodeBuilder.GET_I32 );
}
writer.writeMemoryOperator( MemoryOperator.load, ValueType.i32, virtualFunctionIdx * 4, 2 );
writer.writeVirtualFunctionCall( getFunctionName(), type );
}
}

View File

@ -44,7 +44,6 @@ import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.ValueTypeParser;
import de.inetsoftware.jwebassembly.wasm.VariableOperator;
import de.inetsoftware.jwebassembly.wasm.WasmBlockOperator;
import de.inetsoftware.jwebassembly.wasm.WasmOptions;
/**
* Base class for Code Building.
@ -517,6 +516,7 @@ public abstract class WasmCodeBuilder {
*/
protected void addCallVirtualInstruction( FunctionName name, int javaCodePos, int lineNumber ) {
addCallIndirectInstruction( new WasmCallVirtualInstruction( name, javaCodePos, lineNumber, types, options ) );
options.getCallVirtual(); // mark the function as needed
}
/**
@ -629,7 +629,7 @@ public abstract class WasmCodeBuilder {
}
/**
* Add an array operation to the instruction list as marker on the code position.
* Add a struct/object operation to the instruction list.
*
* @param op
* the operation

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.inetsoftware.jwebassembly.wasm;
package de.inetsoftware.jwebassembly.module;
import java.util.HashMap;
@ -33,13 +33,13 @@ import de.inetsoftware.jwebassembly.module.TypeManager;
*/
public class WasmOptions {
public final FunctionManager functions = new FunctionManager();
final FunctionManager functions = new FunctionManager();
public final TypeManager types = new TypeManager( this );
final TypeManager types = new TypeManager( this );
public final StringManager strings = new StringManager( this );
final StringManager strings = new StringManager( this );
public final CodeOptimizer optimizer = new CodeOptimizer();
final CodeOptimizer optimizer = new CodeOptimizer();
private final boolean debugNames;
@ -55,6 +55,9 @@ public class WasmOptions {
*/
public FunctionName ref_eq;
private FunctionName callVirtual;
/**
* Create a new instance of options
*
@ -108,4 +111,20 @@ public class WasmOptions {
public String getSourceMapBase() {
return sourceMapBase;
}
/**
* Get the FunctionName for a virtual call and mark it as used. The function has 2 parameters (THIS,
* virtualfunctionIndex) and returns the index of the function.
*
* @return the name
*/
@Nonnull
FunctionName getCallVirtual() {
FunctionName name = callVirtual;
if( name == null ) {
callVirtual = name = types.getCallVirtualGC();
functions.markAsNeeded( name );
}
return name;
}
}

View File

@ -33,6 +33,7 @@ import de.inetsoftware.jwebassembly.module.FunctionName;
import de.inetsoftware.jwebassembly.module.ModuleWriter;
import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
import de.inetsoftware.jwebassembly.module.ValueTypeConvertion;
import de.inetsoftware.jwebassembly.module.WasmOptions;
import de.inetsoftware.jwebassembly.module.WasmTarget;
import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
@ -43,7 +44,6 @@ import de.inetsoftware.jwebassembly.wasm.StructOperator;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.VariableOperator;
import de.inetsoftware.jwebassembly.wasm.WasmBlockOperator;
import de.inetsoftware.jwebassembly.wasm.WasmOptions;
/**
* Module Writer for text format with S-expressions.

View File

@ -28,8 +28,12 @@ import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.module.FunctionName;
import de.inetsoftware.jwebassembly.module.ValueTypeConvertion;
import de.inetsoftware.jwebassembly.module.WasmCodeBuilder;
import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.MemoryOperator;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.NumericOperator;
import de.inetsoftware.jwebassembly.wasm.StructOperator;
import de.inetsoftware.jwebassembly.wasm.ValueType;
import de.inetsoftware.jwebassembly.wasm.VariableOperator;
import de.inetsoftware.jwebassembly.wasm.WasmBlockOperator;
@ -246,6 +250,24 @@ public class WatParser extends WasmCodeBuilder {
case "i32.load8_u":
i = addMemoryInstruction( MemoryOperator.load8_u, ValueType.i32, tokens, i, lineNumber );
break;
case "struct.get":
String typeName = get( tokens, ++i );
String fieldName = get( tokens, ++i );
NamedStorageType fieldNameType = null;
List<NamedStorageType> fields = getTypeManager().valueOf( typeName ).getFields();
if( fields != null ) { // field is null on prepare
for( NamedStorageType namedStorageType : fields ) {
if( namedStorageType.getName().equals( fieldName ) ) {
fieldNameType = namedStorageType;
break;
}
}
}
if( fieldNameType == null ) {
fieldNameType = new NamedStorageType( ValueType.anyref, "", fieldName );
}
addStructInstruction( StructOperator.GET, typeName, fieldNameType, javaCodePos, lineNumber );
break;
default:
throw new WasmException( "Unknown WASM token: " + tok, lineNumber );
}

View File

@ -28,7 +28,6 @@ import org.junit.Test;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.binary.BinaryModuleWriter;
import de.inetsoftware.jwebassembly.text.TextModuleWriter;
import de.inetsoftware.jwebassembly.wasm.WasmOptions;
import de.inetsoftware.jwebassembly.watparser.WatParser;
/**