From fd43aca97b409c5650366126049e72f26f596711 Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Sun, 19 May 2019 15:17:30 +0200 Subject: [PATCH] Move the analyzing and writing of types in the TypeManager --- .../jwebassembly/module/FunctionManager.java | 31 ++++-- .../jwebassembly/module/ModuleGenerator.java | 76 +------------- .../jwebassembly/module/TypeManager.java | 99 ++++++++++++++++++- .../module/WasmCallIndirectInstruction.java | 9 ++ 4 files changed, 129 insertions(+), 86 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/module/FunctionManager.java b/src/de/inetsoftware/jwebassembly/module/FunctionManager.java index 77d6997..590cab8 100644 --- a/src/de/inetsoftware/jwebassembly/module/FunctionManager.java +++ b/src/de/inetsoftware/jwebassembly/module/FunctionManager.java @@ -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 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 { diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java index 0126deb..c31ff91 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java @@ -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 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 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 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 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 parser = name.getSignature(); diff --git a/src/de/inetsoftware/jwebassembly/module/TypeManager.java b/src/de/inetsoftware/jwebassembly/module/TypeManager.java index 35d08da..4553502 100644 --- a/src/de/inetsoftware/jwebassembly/module/TypeManager.java +++ b/src/de/inetsoftware/jwebassembly/module/TypeManager.java @@ -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 fields; + private List 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} */ diff --git a/src/de/inetsoftware/jwebassembly/module/WasmCallIndirectInstruction.java b/src/de/inetsoftware/jwebassembly/module/WasmCallIndirectInstruction.java index 03c1fd3..54e0e9b 100644 --- a/src/de/inetsoftware/jwebassembly/module/WasmCallIndirectInstruction.java +++ b/src/de/inetsoftware/jwebassembly/module/WasmCallIndirectInstruction.java @@ -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} */