Move the analyzing and writing of types in the TypeManager

This commit is contained in:
Volker Berlin 2019-05-19 15:17:30 +02:00
parent 8f09d4d04a
commit fd43aca97b
4 changed files with 129 additions and 86 deletions

View File

@ -19,7 +19,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -120,6 +119,7 @@ public class FunctionManager {
case Needed:
case Scanned:
return entry.getKey();
default:
}
}
return null;
@ -200,27 +200,40 @@ public class FunctionManager {
return newMethod != null ? newMethod : method;
}
/**
* Set the index of a virtual function in a a type
*
* @param name
* the name
* @param functionIdx
* the index
*/
void setFunctionIndex( FunctionName name, int functionIdx ) {
getOrCreate( name ).functionIdx = functionIdx;
}
/**
* Get all function names for the class.
* Get the index of a virtual function in a a type
*
* @param className
* the className
* @return a stream with the names
* @param name
* the name
* @return the index
*/
Stream<FunctionName> getNamesOfClass( String className ) {
return states.keySet().stream().filter( ( name ) -> name.className.equals( className ) );
int getFunctionIndex( FunctionName name ) {
return getOrCreate( name ).functionIdx;
}
/**
* State of a function/method
*/
private static class FunctionState {
private State state = State.None;
private State state = State.None;
private MethodInfo method;
private MethodInfo method;
private FunctionName alias;
private int functionIdx = -1;
}
private static enum State {

View File

@ -22,8 +22,6 @@ import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -37,7 +35,6 @@ import javax.annotation.Nullable;
import de.inetsoftware.classparser.ClassFile;
import de.inetsoftware.classparser.Code;
import de.inetsoftware.classparser.ConstantClass;
import de.inetsoftware.classparser.FieldInfo;
import de.inetsoftware.classparser.MethodInfo;
import de.inetsoftware.jwebassembly.JWebAssembly;
import de.inetsoftware.jwebassembly.WasmException;
@ -198,7 +195,7 @@ public class ModuleGenerator {
}
functions.prepareFinish();
types.prepareFinish();
types.prepareFinish( writer, functions, libraries );
}
/**
@ -271,75 +268,6 @@ public class ModuleGenerator {
}
}
/**
* Write the struct type if not already write.
*
* @param type
* the type
* @throws IOException
* if any I/O error occur
*/
private void writeStructType( StructType type ) throws IOException {
if( type == null || type.getCode() != Integer.MAX_VALUE ) {
return;
}
String className = type.getName();
List<NamedStorageType> list = new ArrayList<>();
listStructFields( className, list );
int id = writer.writeStruct( className, list );
types.useType( type, id, list );
for( NamedStorageType namedType : list ) {
AnyType fieldType = namedType.getType();
if( fieldType.getCode() == Integer.MAX_VALUE ) {
writeStructType( (StructType)fieldType );
}
}
}
/**
* List the non static fields of the class and its super classes.
*
* @param className
* the className
* @param list
* the container for the fields
* @throws IOException
* if any I/O error occur
*/
private void listStructFields( String className, List<NamedStorageType> list ) throws IOException {
ClassFile classFile = ClassFile.get( className, libraries );
if( classFile == null ) {
throw new WasmException( "Missing class: " + className, -1 );
}
ConstantClass superClass = classFile.getSuperClass();
if( superClass != null ) {
String superClassName = superClass.getName();
listStructFields( superClassName, list );
} else {
list.add( new NamedStorageType( ValueType.i32, className, ".vtable" ) );
}
for( FieldInfo field : classFile.getFields() ) {
if( field.isStatic() ) {
continue;
}
list.add( new NamedStorageType( className, field, types ) );
}
HashMap<String,Boolean> virtualFunctions = new HashMap<>();
functions.getNamesOfClass( className ).forEach( (name) -> {
String methodName = name.methodName;
Boolean virtual = virtualFunctions.get( methodName );
if( virtual == null ) {
virtualFunctions.put( methodName, Boolean.FALSE );
} else {
virtualFunctions.put( methodName, Boolean.TRUE );
}
} );
}
/**
* Iterate over all methods of the classFile and run the handler.
*
@ -513,7 +441,6 @@ public class ModuleGenerator {
break;
case Struct:
WasmStructInstruction instr = (WasmStructInstruction)instruction;
writeStructType( instr.getStructType() );
if( instr.getOperator() == StructOperator.NEW_DEFAULT ) {
List<NamedStorageType> list = instr.getStructType().getFields();
for( NamedStorageType storageType : list ) {
@ -572,7 +499,6 @@ public class ModuleGenerator {
int paramCount = 0;
if( !isStatic ) {
StructType instanceType = types.valueOf( name.className );
writeStructType( instanceType );
writer.writeMethodParam( "param", instanceType, "this" );
}
Iterator<AnyType> parser = name.getSignature();

View File

@ -16,6 +16,8 @@
*/
package de.inetsoftware.jwebassembly.module;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
@ -24,8 +26,14 @@ import java.util.Map;
import javax.annotation.Nonnull;
import de.inetsoftware.classparser.ClassFile;
import de.inetsoftware.classparser.ConstantClass;
import de.inetsoftware.classparser.FieldInfo;
import de.inetsoftware.classparser.MethodInfo;
import de.inetsoftware.jwebassembly.WasmException;
import de.inetsoftware.jwebassembly.wasm.AnyType;
import de.inetsoftware.jwebassembly.wasm.NamedStorageType;
import de.inetsoftware.jwebassembly.wasm.ValueType;
/**
* Manage the written and to write types (classes)
@ -38,10 +46,22 @@ public class TypeManager {
/**
* Finish the prepare. Now no new function should be added.
* Finish the prepare and write the types. Now no new types and functions should be added.
*
* @param writer
* the targets for the types
* @param functions
* the used functions for the vtables of the types
* @param libraries
* for loading the class files if not in the cache
* @throws IOException
* if any I/O error occur on loading or writing
*/
public void prepareFinish() {
void prepareFinish( ModuleWriter writer, FunctionManager functions, ClassLoader libraries ) throws IOException {
map = Collections.unmodifiableMap( map );
for( StructType type : map.values() ) {
type.writeStructType( writer, functions, this, libraries );
}
}
/**
@ -98,6 +118,8 @@ public class TypeManager {
private List<NamedStorageType> fields;
private List<String> methods;
/**
* Create a reference to type
*
@ -108,6 +130,79 @@ public class TypeManager {
this.name = name;
}
/**
* Write this struct type and initialize internal structures
*
* @param writer
* the targets for the types
* @param functions
* the used functions for the vtables of the types
* @param types
* for types of fields
* @param libraries
* for loading the class files if not in the cache
* @throws IOException
* if any I/O error occur on loading or writing
*/
private void writeStructType( ModuleWriter writer, FunctionManager functions, TypeManager types, ClassLoader libraries ) throws IOException {
fields = new ArrayList<>();
methods = new ArrayList<>();
listStructFields( name, functions, types, libraries );
code = writer.writeStruct( name, fields );
}
/**
* List the non static fields of the class and its super classes.
*
* @param className
* the className to list. because the recursion this must not the name of this class
* @param functions
* the used functions for the vtables of the types
* @param types
* for types of fields
* @param libraries
* for loading the class files if not in the cache
* @throws IOException
* if any I/O error occur on loading or writing
*/
private void listStructFields( String className, FunctionManager functions, TypeManager types, ClassLoader libraries ) throws IOException {
ClassFile classFile = ClassFile.get( className, libraries );
if( classFile == null ) {
throw new WasmException( "Missing class: " + className, -1 );
}
ConstantClass superClass = classFile.getSuperClass();
if( superClass != null ) {
String superClassName = superClass.getName();
listStructFields( superClassName, functions, types, libraries );
} else {
fields.add( new NamedStorageType( ValueType.i32, className, ".vtable" ) );
}
for( FieldInfo field : classFile.getFields() ) {
if( field.isStatic() ) {
continue;
}
fields.add( new NamedStorageType( className, field, types ) );
}
for( MethodInfo method : classFile.getMethods() ) {
if( method.isStatic() ) {
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 );
}
functions.setFunctionIndex( funcName, idx );
}
}
}
/**
* {@inheritDoc}
*/

View File

@ -52,6 +52,15 @@ class WasmCallIndirectInstruction extends WasmCallInstruction {
return Type.CallIndirect;
}
/**
* {@inheritDoc}
*/
@Override
void markAsNeeded( FunctionManager functions ) {
super.markAsNeeded( functions );
virtualFunctionIdx = functions.getFunctionIndex( getFunctionName() );
}
/**
* {@inheritDoc}
*/