mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-15 02:44:47 +01:00
implements support for static class constructors
This commit is contained in:
parent
645996ceb0
commit
65a1f3ff76
@ -35,7 +35,7 @@ The project is currently not production ready but you can run already some tests
|
||||
* [x] invoke default method calls
|
||||
* [x] String support
|
||||
* [x] Simple Class object support
|
||||
* [ ] static constructors
|
||||
* [x] static constructors
|
||||
* [x] Optimizer - Optimize the WASM output of a single method after transpiling before writing to output
|
||||
* [x] Hello World sample [(live)](https://i-net-software.github.io/JWebAssembly/samples/HelloWorld/HelloWorld.html), [(source code)](https://github.com/i-net-software/JWebAssembly/blob/master/docs/samples/HelloWorld/HelloWorld.java)
|
||||
|
||||
|
@ -91,6 +91,8 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
||||
|
||||
private boolean callIndirect;
|
||||
|
||||
private FunctionName startFunction;
|
||||
|
||||
/**
|
||||
* Create new instance.
|
||||
*
|
||||
@ -133,6 +135,7 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
||||
writeEventSection();
|
||||
writeSection( SectionType.Global, globals.values() );
|
||||
writeSection( SectionType.Export, exports );
|
||||
writeStartSection();
|
||||
writeElementSection();
|
||||
writeCodeSection();
|
||||
writeDataSection();
|
||||
@ -253,6 +256,22 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a start section. The id of the function that should be automatically executed.
|
||||
*
|
||||
* @throws IOException
|
||||
* if any I/O error occur
|
||||
*/
|
||||
private void writeStartSection() throws IOException {
|
||||
if( startFunction == null ) {
|
||||
return;
|
||||
}
|
||||
int id = getFunction( startFunction ).id;
|
||||
WasmOutputStream stream = new WasmOutputStream();
|
||||
stream.writeVaruint32( id );
|
||||
wasm.writeSection( SectionType.Start, stream );
|
||||
}
|
||||
|
||||
/**
|
||||
* Write element section. This section create a matching between direct and indirect function call IDs.
|
||||
*
|
||||
@ -518,10 +537,15 @@ public class BinaryModuleWriter extends ModuleWriter implements InstructionOpcod
|
||||
*/
|
||||
@Override
|
||||
protected void writeMethodParamStart( FunctionName name, FunctionType funcType ) throws IOException {
|
||||
if( funcType == FunctionType.Abstract ) {
|
||||
abstracts.put( name.signatureName, function = new Function() );
|
||||
} else {
|
||||
function = getFunction( name );
|
||||
switch( funcType ) {
|
||||
case Abstract:
|
||||
abstracts.put( name.signatureName, function = new Function() );
|
||||
break;
|
||||
case Start:
|
||||
startFunction = name;
|
||||
//$FALL-THROUGH$
|
||||
default:
|
||||
function = getFunction( name );
|
||||
}
|
||||
functionType = new FunctionTypeEntry();
|
||||
locals.clear();
|
||||
|
@ -37,9 +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 final Map<String, FunctionName> classesWithClinit = new HashMap<>();
|
||||
|
||||
private boolean isFinish;
|
||||
|
||||
@ -90,10 +90,10 @@ class FunctionManager {
|
||||
* Mark that a class has static initializer.
|
||||
*
|
||||
* @param name
|
||||
* the function name
|
||||
* the "<clinit>" function name
|
||||
*/
|
||||
void markClassWithCInit( FunctionName name ) {
|
||||
classesWithCInit.put( name.className, name );
|
||||
void markClassWithClinit( FunctionName name ) {
|
||||
classesWithClinit.put( name.className, name );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -152,7 +152,7 @@ class FunctionManager {
|
||||
}
|
||||
state.state = State.Needed;
|
||||
JWebAssembly.LOGGER.fine( "\t\tcall: " + name.signatureName );
|
||||
FunctionName cInit = classesWithCInit.get( name.className );
|
||||
FunctionName cInit = classesWithClinit.get( name.className );
|
||||
if( cInit != null ) {
|
||||
markAsNeeded( cInit );
|
||||
}
|
||||
@ -243,10 +243,23 @@ class FunctionManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all static constructor FunctionName of used classes.
|
||||
*
|
||||
* @return an iterator
|
||||
*/
|
||||
@Nullable
|
||||
Iterator<FunctionName> getWriteLaterClinit() {
|
||||
return classesWithClinit.values().stream().filter( ( name ) -> {
|
||||
FunctionState state = states.get( name );
|
||||
return state != null && (state.state == State.Needed || state.state == State.Scanned);
|
||||
} ).iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all FunctionName that is required but was not written.
|
||||
*
|
||||
* @return the FunctionName or null
|
||||
* @return an iterator
|
||||
*/
|
||||
@Nullable
|
||||
Iterator<FunctionName> getWriteLater() {
|
||||
|
@ -299,6 +299,9 @@ public class ModuleGenerator {
|
||||
javaScript.addImport( importModule, importName, importAnannotation );
|
||||
}
|
||||
|
||||
// add a start method for the static class constructors
|
||||
prepareStartFunction();
|
||||
|
||||
// init/write the function types
|
||||
for( Iterator<FunctionName> iterator = functions.getWriteLater(); iterator.hasNext(); ) {
|
||||
FunctionName name = iterator.next();
|
||||
@ -318,6 +321,39 @@ public class ModuleGenerator {
|
||||
writer.prepareFinish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a start method for the static class constructors
|
||||
*
|
||||
* @throws IOException
|
||||
* if any I/O error occur
|
||||
*/
|
||||
private void prepareStartFunction() throws IOException {
|
||||
// add the start function/section only if there are static code
|
||||
Iterator<FunctionName> iterator = functions.getWriteLaterClinit();
|
||||
if( iterator.hasNext() ) {
|
||||
FunctionName cinit = new SyntheticFunctionName( "", "<clinit>", "()V" ) {
|
||||
@Override
|
||||
protected boolean hasWasmCode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WasmCodeBuilder getCodeBuilder( WatParser watParser ) {
|
||||
watParser.reset( null, null, getSignature( null ) );
|
||||
|
||||
while( iterator.hasNext() ) {
|
||||
FunctionName name = iterator.next();
|
||||
//TODO if not in the debug mode then inlining would produce smaller output and should be faster
|
||||
watParser.addCallInstruction( name, 0, -1 );
|
||||
}
|
||||
return watParser;
|
||||
}
|
||||
};
|
||||
functions.markAsNeeded( cinit );
|
||||
writeMethodSignature( cinit, FunctionType.Start, null );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the code generation.
|
||||
*
|
||||
@ -405,7 +441,7 @@ public class ModuleGenerator {
|
||||
try {
|
||||
FunctionName name = new FunctionName( method );
|
||||
if( "<clinit>".equals( name.methodName ) ) {
|
||||
functions.markClassWithCInit( name );
|
||||
functions.markClassWithClinit( name );
|
||||
}
|
||||
if( functions.isKnown( name ) ) {
|
||||
return;
|
||||
|
@ -329,8 +329,14 @@ public class TextModuleWriter extends ModuleWriter {
|
||||
*/
|
||||
@Override
|
||||
protected void writeMethodParamStart( @Nonnull FunctionName name, FunctionType funcType ) throws IOException {
|
||||
if( funcType == FunctionType.Abstract ) {
|
||||
abstracts.put( name.signatureName, new Function() );
|
||||
switch( funcType ) {
|
||||
case Abstract:
|
||||
abstracts.put( name.signatureName, new Function() );
|
||||
break;
|
||||
case Start:
|
||||
newline( imports );
|
||||
imports.append( "(start $" ).append( normalizeName( name ) ).append( ")" );
|
||||
break;
|
||||
}
|
||||
typeOutput.setLength( 0 );
|
||||
methodParamNames.clear();
|
||||
|
@ -26,5 +26,7 @@ public enum FunctionType {
|
||||
/** has real code */
|
||||
Code,
|
||||
/** abstract or interface, only used for indirrect call */
|
||||
Abstract;
|
||||
Abstract,
|
||||
/** the function of start section, should occur only once */
|
||||
Start,
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user