mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 07:27:52 +01:00
scanning the Java methods on prepare
This commit is contained in:
parent
0b7fa50520
commit
aa1ed68b3f
@ -15,7 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package de.inetsoftware.jwebassembly.module;
|
package de.inetsoftware.jwebassembly.module;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
@ -30,7 +32,14 @@ import de.inetsoftware.classparser.MethodInfo;
|
|||||||
*/
|
*/
|
||||||
public class FunctionManager {
|
public class FunctionManager {
|
||||||
|
|
||||||
private HashMap<FunctionName, FunctionState> states = new HashMap<>();
|
private Map<FunctionName, FunctionState> states = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finish the prepare. Now no new function should be added.
|
||||||
|
*/
|
||||||
|
void prepareFinish() {
|
||||||
|
states = Collections.unmodifiableMap( states );
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an existing state or create one.
|
* Get an existing state or create one.
|
||||||
|
@ -31,6 +31,7 @@ import java.util.zip.ZipEntry;
|
|||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
import de.inetsoftware.classparser.ClassFile;
|
import de.inetsoftware.classparser.ClassFile;
|
||||||
import de.inetsoftware.classparser.Code;
|
import de.inetsoftware.classparser.Code;
|
||||||
@ -153,19 +154,55 @@ public class ModuleGenerator {
|
|||||||
public void prepareFinish() throws IOException {
|
public void prepareFinish() throws IOException {
|
||||||
writer.prepareFinish();
|
writer.prepareFinish();
|
||||||
|
|
||||||
|
// scan all methods that should be write to build optimize structures
|
||||||
FunctionName next;
|
FunctionName next;
|
||||||
while( (next = functions.nextScannLater()) != null ) {
|
while( (next = functions.nextScannLater()) != null ) {
|
||||||
ClassFile classFile = ClassFile.get( next.className, libraries );
|
ClassFile classFile = ClassFile.get( next.className, libraries );
|
||||||
if( classFile == null ) {
|
if( classFile == null ) {
|
||||||
|
if( next instanceof SyntheticFunctionName ) {
|
||||||
|
scanMethod( ((SyntheticFunctionName)next).getCodeBuilder( watParser ) );
|
||||||
|
functions.markAsScanned( next );
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
iterateMethods( classFile, method -> {
|
iterateMethods( classFile, method -> {
|
||||||
FunctionName name = new FunctionName( method );
|
try {
|
||||||
if( functions.needToScan( name ) ) {
|
FunctionName name = new FunctionName( method );
|
||||||
//TODO
|
if( functions.needToScan( name ) ) {
|
||||||
|
scanMethod( createInstructions( method ) );
|
||||||
|
functions.markAsScanned( name );
|
||||||
|
}
|
||||||
|
} catch (IOException ioex){
|
||||||
|
throw WasmException.create( ioex, sourceFile, className, -1 );
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
functions.markAsScanned( next );
|
if( functions.needToScan( next ) ) {
|
||||||
|
throw new WasmException( "Missing function: " + next.signatureName, -1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
functions.prepareFinish();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scan the method and list all needed methods.
|
||||||
|
*
|
||||||
|
* @param codeBuilder
|
||||||
|
* the codeBuilder with instructions of the method
|
||||||
|
* @throws IOException
|
||||||
|
* if any I/O error occur
|
||||||
|
*/
|
||||||
|
private void scanMethod( WasmCodeBuilder codeBuilder ) throws IOException {
|
||||||
|
if( codeBuilder == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<WasmInstruction> instructions = codeBuilder.getInstructions();
|
||||||
|
for( WasmInstruction instruction : instructions ) {
|
||||||
|
switch( instruction.getType() ) {
|
||||||
|
case Call:
|
||||||
|
functions.markAsNeeded( ((WasmCallInstruction)instruction).getFunctionName() );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -216,20 +253,7 @@ public class ModuleGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the StructType into the instruction and write the types/structs if needed.
|
* Write the struct type if not already write.
|
||||||
*
|
|
||||||
* @param instruction
|
|
||||||
* the struct instruction
|
|
||||||
* @throws IOException
|
|
||||||
* if any I/O error occur
|
|
||||||
*/
|
|
||||||
private void setStructType( WasmStructInstruction instruction ) throws IOException {
|
|
||||||
StructType type = instruction.getStructType();
|
|
||||||
writeStructType( type );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Write the struct type
|
|
||||||
*
|
*
|
||||||
* @param type
|
* @param type
|
||||||
* the type
|
* the type
|
||||||
@ -360,38 +384,70 @@ public class ModuleGenerator {
|
|||||||
* the method
|
* the method
|
||||||
* @throws WasmException
|
* @throws WasmException
|
||||||
* if some Java code can't converted
|
* if some Java code can't converted
|
||||||
|
* @throws IOException
|
||||||
|
* if any I/O error occur
|
||||||
*/
|
*/
|
||||||
private void writeMethod( FunctionName name, MethodInfo method ) throws WasmException, IOException {
|
private void writeMethod( FunctionName name, MethodInfo method ) throws WasmException, IOException {
|
||||||
|
WasmCodeBuilder codeBuilder = createInstructions( method );
|
||||||
|
if( codeBuilder == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
writeExport( name, method );
|
||||||
|
writeMethodImpl( name, method.isStatic(), codeBuilder );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the instructions in a code builder
|
||||||
|
*
|
||||||
|
* @param method
|
||||||
|
* the method to parse
|
||||||
|
* @return the CodeBuilder or null if it is an import function
|
||||||
|
* @throws IOException
|
||||||
|
* if any I/O error occur
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private WasmCodeBuilder createInstructions( MethodInfo method ) throws IOException {
|
||||||
Code code = null;
|
Code code = null;
|
||||||
try {
|
try {
|
||||||
if( method.getAnnotation( JWebAssembly.IMPORT_ANNOTATION ) != null ) {
|
if( method.getAnnotation( JWebAssembly.IMPORT_ANNOTATION ) != null ) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
WasmCodeBuilder codeBuilder;
|
|
||||||
code = method.getCode();
|
code = method.getCode();
|
||||||
if( method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION ) != null ) {
|
if( method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION ) != null ) {
|
||||||
Map<String, Object> wat = method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION );
|
Map<String, Object> wat = method.getAnnotation( JWebAssembly.TEXTCODE_ANNOTATION );
|
||||||
String watCode = (String)wat.get( "value" );
|
String watCode = (String)wat.get( "value" );
|
||||||
String signature = (String)wat.get( "signature" );
|
String signature = (String)wat.get( "signature" );
|
||||||
if( signature == null ) {
|
if( signature == null ) {
|
||||||
signature = method.getType();
|
signature = method.getType();
|
||||||
}
|
}
|
||||||
watParser.parse( watCode, code == null ? -1 : code.getFirstLineNr() );
|
watParser.parse( watCode, code == null ? -1 : code.getFirstLineNr() );
|
||||||
codeBuilder = watParser;
|
return watParser;
|
||||||
} else if( code != null ) { // abstract methods and interface methods does not have code
|
} else if( code != null ) { // abstract methods and interface methods does not have code
|
||||||
javaCodeBuilder.buildCode( code, !method.getType().endsWith( ")V" ) );
|
javaCodeBuilder.buildCode( code, !method.getType().endsWith( ")V" ) );
|
||||||
codeBuilder = javaCodeBuilder;
|
return javaCodeBuilder;
|
||||||
} else {
|
} else {
|
||||||
throw new WasmException( "Abstract or native method can not be used: " + name.fullName, -1 );
|
throw new WasmException( "Abstract or native method can not be used: " + new FunctionName( method ).fullName, -1 );
|
||||||
}
|
}
|
||||||
writeExport( name, method );
|
|
||||||
writeMethodImpl( name, method.isStatic(), codeBuilder );
|
|
||||||
} catch( Exception ioex ) {
|
} catch( Exception ioex ) {
|
||||||
int lineNumber = code == null ? -1 : code.getFirstLineNr();
|
int lineNumber = code == null ? -1 : code.getFirstLineNr();
|
||||||
throw WasmException.create( ioex, sourceFile, className, lineNumber );
|
throw WasmException.create( ioex, sourceFile, className, lineNumber );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write the method instruction to the Wasm writer.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* the name of the function
|
||||||
|
* @param isStatic
|
||||||
|
* if it is static
|
||||||
|
* @param codeBuilder
|
||||||
|
* the code builder with instructions
|
||||||
|
* @throws WasmException
|
||||||
|
* if some Java code can't converted
|
||||||
|
* @throws IOException
|
||||||
|
* if an i/O error occur
|
||||||
|
*/
|
||||||
private void writeMethodImpl( FunctionName name, boolean isStatic, WasmCodeBuilder codeBuilder ) throws WasmException, IOException {
|
private void writeMethodImpl( FunctionName name, boolean isStatic, WasmCodeBuilder codeBuilder ) throws WasmException, IOException {
|
||||||
writer.writeMethodStart( name, sourceFile );
|
writer.writeMethodStart( name, sourceFile );
|
||||||
functions.markAsWritten( name );
|
functions.markAsWritten( name );
|
||||||
@ -425,7 +481,7 @@ public class ModuleGenerator {
|
|||||||
break;
|
break;
|
||||||
case Struct:
|
case Struct:
|
||||||
WasmStructInstruction instr = (WasmStructInstruction)instruction;
|
WasmStructInstruction instr = (WasmStructInstruction)instruction;
|
||||||
setStructType( instr );
|
writeStructType( instr.getStructType() );
|
||||||
if( instr.getOperator() == StructOperator.NEW_DEFAULT ) {
|
if( instr.getOperator() == StructOperator.NEW_DEFAULT ) {
|
||||||
List<NamedStorageType> list = instr.getStructType().getFields();
|
List<NamedStorageType> list = instr.getStructType().getFields();
|
||||||
for( NamedStorageType storageType : list ) {
|
for( NamedStorageType storageType : list ) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user