write the vtable of objects to the data section. Use the vtable offset into the data section in the new operation of objects.

This commit is contained in:
Volker Berlin 2019-06-09 17:17:47 +02:00
parent 6da4a93918
commit 1ee77584d9
5 changed files with 90 additions and 25 deletions

View File

@ -31,6 +31,7 @@ import javax.annotation.Nullable;
import de.inetsoftware.jwebassembly.JWebAssembly;
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.WasmTarget;
import de.inetsoftware.jwebassembly.sourcemap.SourceMapWriter;
@ -442,9 +443,19 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
* {@inheritDoc}
*/
@Override
protected int writeStruct( String typeName, List<NamedStorageType> fields ) throws IOException {
protected int writeStructType( StructType type ) throws IOException {
type.setVTable( dataStream.size() );
for( FunctionName funcName : type.getMethods() ) {
int functIdx = getFunction( funcName ).id;
// little-endian byte order
dataStream.write( functIdx >>> 0 );
dataStream.write( functIdx >>> 8 );
dataStream.write( functIdx >>> 16 );
dataStream.write( functIdx >>> 24 );
}
int typeId = functionTypes.size();
functionTypes.add( new StructTypeEntry( fields ) );
functionTypes.add( new StructTypeEntry( type.getFields() ) );
return typeId;
}

View File

@ -443,9 +443,14 @@ public class ModuleGenerator {
case Struct:
WasmStructInstruction instr = (WasmStructInstruction)instruction;
if( instr.getOperator() == StructOperator.NEW_DEFAULT ) {
List<NamedStorageType> list = instr.getStructType().getFields();
StructType structType = instr.getStructType();
List<NamedStorageType> list = structType.getFields();
for( NamedStorageType storageType : list ) {
writer.writeDefaultValue( storageType.getType() );
if( TypeManager.VTABLE == storageType.getName() ) {
writer.writeConst( structType.getVTable(), ValueType.i32 );
} else {
writer.writeDefaultValue( storageType.getType() );
}
}
}
break;

View File

@ -17,11 +17,11 @@ package de.inetsoftware.jwebassembly.module;
import java.io.Closeable;
import java.io.IOException;
import java.util.List;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
@ -47,15 +47,13 @@ public abstract class ModuleWriter implements Closeable {
/**
* Write a type/struct.
*
* @param typeName
* the name
* @param fields
* the fields
* @param type
* the type to declare/write
* @return type ID
* @throws IOException
* if any I/O error occur
*/
protected abstract int writeStruct( String typeName, List<NamedStorageType> fields ) throws IOException;
protected abstract int writeStructType( StructType type ) throws IOException;
/**
* Mark to write exceptions

View File

@ -42,8 +42,9 @@ import de.inetsoftware.jwebassembly.wasm.ValueType;
*/
public class TypeManager {
private Map<String, StructType> map = new LinkedHashMap<>();
static final String VTABLE = ".vtable";
private Map<String, StructType> map = new LinkedHashMap<>();
/**
* Finish the prepare and write the types. Now no new types and functions should be added.
@ -110,7 +111,7 @@ public class TypeManager {
*
* @author Volker Berlin
*/
static class StructType implements AnyType {
public static class StructType implements AnyType {
private final String name;
@ -118,7 +119,12 @@ public class TypeManager {
private List<NamedStorageType> fields;
private List<String> methods;
private List<FunctionName> methods;
/**
* The offset to the vtable in the data section.
*/
private int vtableOffset;
/**
* Create a reference to type
@ -148,7 +154,7 @@ public class TypeManager {
fields = new ArrayList<>();
methods = new ArrayList<>();
listStructFields( name, functions, types, libraries );
code = writer.writeStruct( name, fields );
code = writer.writeStructType( this );
}
/**
@ -176,7 +182,7 @@ public class TypeManager {
String superClassName = superClass.getName();
listStructFields( superClassName, functions, types, libraries );
} else {
fields.add( new NamedStorageType( ValueType.i32, className, ".vtable" ) );
fields.add( new NamedStorageType( ValueType.i32, className, VTABLE ) );
}
for( FieldInfo field : classFile.getFields() ) {
@ -187,16 +193,23 @@ public class TypeManager {
}
for( MethodInfo method : classFile.getMethods() ) {
if( method.isStatic() ) {
if( method.isStatic() || "<init>".equals( method.getName() ) ) {
continue;
}
FunctionName funcName = new FunctionName( method );
if( functions.needToWrite( funcName ) ) {
String signature = funcName.methodName + funcName.signature;
int idx = methods.indexOf( signature );
if( idx < 0 ) {
idx = methods.size();
methods.add( signature );
int idx = 0;
// search if the method is already in our list
for( ; idx < methods.size(); idx++ ) {
FunctionName func = methods.get( idx );
if( func.methodName.equals( funcName.methodName ) && func.signature.equals( funcName.signature ) ) {
methods.set( idx, funcName ); // use the override method
break;
}
}
if( idx == methods.size() ) {
// if a new method
methods.add( funcName );
}
functions.setFunctionIndex( funcName, idx );
}
@ -227,6 +240,34 @@ public class TypeManager {
return fields;
}
/**
* Get the virtual function/methods
*
* @return the methods
*/
public List<FunctionName> getMethods() {
return methods;
}
/**
* Set the offset of the vtable in the data section
*
* @param vtableOffset
* the offset
*/
public void setVTable( int vtableOffset ) {
this.vtableOffset = vtableOffset;
}
/**
* Get the vtable offset.
*
* @return the offset
*/
public int getVTable() {
return this.vtableOffset;
}
/**
* {@inheritDoc}
*/

View File

@ -21,7 +21,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nonnull;
@ -31,6 +30,7 @@ import de.inetsoftware.jwebassembly.JWebAssembly;
import de.inetsoftware.jwebassembly.WasmException;
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.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.ArrayOperator;
@ -148,14 +148,24 @@ public class TextModuleWriter extends ModuleWriter {
* {@inheritDoc}
*/
@Override
protected int writeStruct( String typeName, List<NamedStorageType> fields ) throws IOException {
protected int writeStructType( StructType type ) throws IOException {
type.setVTable( dataStream.size() );
for( FunctionName funcName : type.getMethods() ) {
int functIdx = functions.get( funcName.signatureName );
// little-endian byte order
dataStream.write( functIdx >>> 0 );
dataStream.write( functIdx >>> 8 );
dataStream.write( functIdx >>> 16 );
dataStream.write( functIdx >>> 24 );
}
int oldInset = inset;
inset = 1;
newline( output );
typeName = normalizeName( typeName );
String typeName = normalizeName( type.getName() );
output.append( "(type $" ).append( typeName ).append( " (struct" );
inset++;
for( NamedStorageType field : fields ) {
for( NamedStorageType field : type.getFields() ) {
newline( output );
output.append( "(field" );
if( debugNames && field.getName() != null ) {