add support for static constructors, WIP

This commit is contained in:
Volker Berlin 2020-03-30 22:27:30 +02:00
parent 41c795eaee
commit 645996ceb0
2 changed files with 55 additions and 35 deletions

View File

@ -15,6 +15,7 @@
*/
package de.inetsoftware.jwebassembly.module;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
@ -36,7 +37,9 @@ import de.inetsoftware.jwebassembly.WasmException;
*/
class FunctionManager {
private final Map<FunctionName, FunctionState> states = new LinkedHashMap<>();
private final Map<FunctionName, FunctionState> states = new LinkedHashMap<>();
private final Map<String, FunctionName> classesWithCInit = new HashMap<>();
private boolean isFinish;
@ -83,6 +86,16 @@ class FunctionManager {
return states.get( name ) != null;
}
/**
* Mark that a class has static initializer.
*
* @param name
* the function name
*/
void markClassWithCInit( FunctionName name ) {
classesWithCInit.put( name.className, name );
}
/**
* Mark the a function as a import function. Only if the function is also needed then it will imported from
* compiler.
@ -109,6 +122,44 @@ class FunctionManager {
getOrCreate( name ).importAnannotation = importAnannotation;
}
/**
* Same like markAsNeeded but it will replace the function name if already registered.
*
* @param name
* the function name
*/
void markAsNeededAndReplaceIfExists( @Nonnull SyntheticFunctionName name ) {
FunctionState state = states.get( name );
if( state != null ) {
states.remove( name );
states.put( name, state );
}
markAsNeeded( name );
}
/**
* Mark a function as used/called and return the real name if there is an alias.
*
* @param name
* the function name
* @return the real function name
*/
FunctionName markAsNeeded( @Nonnull FunctionName name ) {
FunctionState state = getOrCreate( name );
if( state.state == State.None ) {
if( isFinish ) {
throw new WasmException( "Prepare was already finish: " + name.signatureName, -1 );
}
state.state = State.Needed;
JWebAssembly.LOGGER.fine( "\t\tcall: " + name.signatureName );
FunctionName cInit = classesWithCInit.get( name.className );
if( cInit != null ) {
markAsNeeded( cInit );
}
}
return state.alias == null ? name : state.alias;
}
/**
* Mark the a function as scanned in the prepare phase. This should only occur with needed functions.
*
@ -148,40 +199,6 @@ class FunctionManager {
getOrCreate( name ).state = State.Abstract;
}
/**
* Same like markAsNeeded but it will replace the function name if already registered.
*
* @param name
* the function name
*/
void markAsNeededAndReplaceIfExists( @Nonnull SyntheticFunctionName name ) {
FunctionState state = states.get( name );
if( state != null ) {
states.remove( name );
states.put( name, state );
}
markAsNeeded( name );
}
/**
* Mark a function as used/called and return the real name if there is an alias.
*
* @param name
* the function name
* @return the real function name
*/
FunctionName markAsNeeded( @Nonnull FunctionName name ) {
FunctionState state = getOrCreate( name );
if( state.state == State.None ) {
if( isFinish ) {
throw new WasmException( "Prepare was already finish: " + name.signatureName, -1 );
}
state.state = State.Needed;
JWebAssembly.LOGGER.fine( "\t\tcall: " + name.signatureName );
}
return state.alias == null ? name : state.alias;
}
/**
* Get all FunctionNames that need imported
*

View File

@ -404,6 +404,9 @@ public class ModuleGenerator {
private void prepareMethod( MethodInfo method ) throws WasmException {
try {
FunctionName name = new FunctionName( method );
if( "<clinit>".equals( name.methodName ) ) {
functions.markClassWithCInit( name );
}
if( functions.isKnown( name ) ) {
return;
}