From 0b7fa505200490b9dd50b1120af09ea7b0dcf3f5 Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Thu, 9 May 2019 22:13:02 +0200 Subject: [PATCH] next step for scanning on prepare --- .../jwebassembly/module/FunctionManager.java | 65 ++++++++++++++++--- .../jwebassembly/module/ModuleGenerator.java | 32 ++++++--- 2 files changed, 81 insertions(+), 16 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/module/FunctionManager.java b/src/de/inetsoftware/jwebassembly/module/FunctionManager.java index a817cf5..9a15c27 100644 --- a/src/de/inetsoftware/jwebassembly/module/FunctionManager.java +++ b/src/de/inetsoftware/jwebassembly/module/FunctionManager.java @@ -48,13 +48,23 @@ public class FunctionManager { return state; } + /** + * Mark the a function as scanned in the prepare phase. This should only occur with needed functions. + * + * @param name + * the function name + */ + void markAsScanned( FunctionName name ) { + getOrCreate( name ).state = State.Scanned; + } + /** * Mark the a function as written to the wasm file. * * @param name * the function name */ - void writeFunction( FunctionName name ) { + void markAsWritten( FunctionName name ) { getOrCreate( name ).state = State.Written; } @@ -64,13 +74,28 @@ public class FunctionManager { * @param name * the function name */ - void functionCall( FunctionName name ) { + void markAsNeeded( FunctionName name ) { FunctionState state = getOrCreate( name ); if( state.state == State.None ) { - state.state = State.Need; + state.state = State.Needed; } } + /** + * Get the first FunctionName that is required but was not scanned. + * + * @return the FunctionName or null + */ + @Nullable + FunctionName nextScannLater() { + for( Entry entry : states.entrySet() ) { + if( entry.getValue().state == State.Needed ) { + return entry.getKey(); + } + } + return null; + } + /** * Get the first FunctionName that is required but was not written. * @@ -79,13 +104,31 @@ public class FunctionManager { @Nullable FunctionName nextWriteLater() { for( Entry entry : states.entrySet() ) { - if( entry.getValue().state == State.Need ) { - return entry.getKey(); + switch( entry.getValue().state ) { + case Needed: + case Scanned: + return entry.getKey(); } } return null; } + /** + * if the given function is required but was not scanned. + * + * @param name + * the function name + * @return true, if the function on the to do list + */ + boolean needToScan( FunctionName name ) { + switch( getOrCreate( name ).state ) { + case Needed: + return true; + default: + return false; + } + } + /** * if the given function is required but was not written. * @@ -93,8 +136,14 @@ public class FunctionManager { * the function name * @return true, if the function on the to do list */ - boolean isToWrite( FunctionName name ) { - return getOrCreate( name ).state == State.Need; + boolean needToWrite( FunctionName name ) { + switch( getOrCreate( name ).state ) { + case Needed: + case Scanned: + return true; + default: + return false; + } } /** @@ -134,6 +183,6 @@ public class FunctionManager { } private static enum State { - None, Need, Written; + None, Needed, Scanned, Written; } } diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java index 7429ef1..c43f706 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java @@ -18,7 +18,6 @@ package de.inetsoftware.jwebassembly.module; import java.io.BufferedInputStream; import java.io.File; import java.io.IOException; -import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Files; @@ -148,9 +147,26 @@ public class ModuleGenerator { /** * Finish the prepare after all classes/methods are prepare. This must be call before we can start with write the * first method. + * @throws IOException + * if any I/O error occur */ - public void prepareFinish() { + public void prepareFinish() throws IOException { writer.prepareFinish(); + + FunctionName next; + while( (next = functions.nextScannLater()) != null ) { + ClassFile classFile = ClassFile.get( next.className, libraries ); + if( classFile == null ) { + } else { + iterateMethods( classFile, method -> { + FunctionName name = new FunctionName( method ); + if( functions.needToScan( name ) ) { + //TODO + } + } ); + } + functions.markAsScanned( next ); + } } /** @@ -184,7 +200,7 @@ public class ModuleGenerator { name = new FunctionName( method ); method = functions.replace( name, method ); } - if( functions.isToWrite( name ) ) { + if( functions.needToWrite( name ) ) { writeMethod( name, method ); } } catch (IOException ioex){ @@ -193,7 +209,7 @@ public class ModuleGenerator { } ); } - if( functions.isToWrite( next ) ) { + if( functions.needToWrite( next ) ) { throw new WasmException( "Missing function: " + next.signatureName, -1 ); } } @@ -310,7 +326,7 @@ public class ModuleGenerator { if( !method.isStatic() ) { throw new WasmException( "Import method must be static: " + name.fullName, -1 ); } - functions.writeFunction( name ); + functions.markAsWritten( name ); String impoarModule = (String)annotationValues.get( "module" ); String importName = (String)annotationValues.get( "name" ); writer.prepareImport( name, impoarModule, importName ); @@ -321,7 +337,7 @@ public class ModuleGenerator { if( !method.isStatic() ) { throw new WasmException( "Export method must be static: " + name.fullName, -1 ); } - functions.functionCall( name ); + functions.markAsNeeded( name ); return; } if( (annotationValues = method.getAnnotation( JWebAssembly.REPLACE_ANNOTATION )) != null ) { @@ -378,7 +394,7 @@ public class ModuleGenerator { private void writeMethodImpl( FunctionName name, boolean isStatic, WasmCodeBuilder codeBuilder ) throws WasmException, IOException { writer.writeMethodStart( name, sourceFile ); - functions.writeFunction( name ); + functions.markAsWritten( name ); writeMethodSignature( name, isStatic, codeBuilder ); List instructions = codeBuilder.getInstructions(); @@ -405,7 +421,7 @@ public class ModuleGenerator { } break; case Call: - functions.functionCall( ((WasmCallInstruction)instruction).getFunctionName() ); + functions.markAsNeeded( ((WasmCallInstruction)instruction).getFunctionName() ); break; case Struct: WasmStructInstruction instr = (WasmStructInstruction)instruction;