next step for scanning on prepare

This commit is contained in:
Volker Berlin 2019-05-09 22:13:02 +02:00
parent cd4f1cf307
commit 0b7fa50520
2 changed files with 81 additions and 16 deletions

View File

@ -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<FunctionName, FunctionState> 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<FunctionName, FunctionState> 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;
}
}

View File

@ -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<WasmInstruction> 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;