mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-15 18:44:47 +01:00
Replace a function name in call with its supper method if real target name does not exists.
This commit is contained in:
parent
aa1ed68b3f
commit
f0d3027553
@ -171,14 +171,22 @@ public class ClassFile {
|
||||
return methods;
|
||||
}
|
||||
|
||||
public int getMethodCount( String name ) {
|
||||
int count = 0;
|
||||
/**
|
||||
* Find a method via name and signature.
|
||||
*
|
||||
* @param name
|
||||
* the name
|
||||
* @param signature
|
||||
* the signature
|
||||
* @return the method or null if not found
|
||||
*/
|
||||
public MethodInfo getMethod( String name, String signature ) {
|
||||
for( MethodInfo method : methods ) {
|
||||
if( name.equals( method.getName() ) ) {
|
||||
count++;
|
||||
if( name.equals( method.getName() ) && signature.equals( method.getType() ) ) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
return null;
|
||||
}
|
||||
|
||||
public FieldInfo getField( String name ) {
|
||||
|
@ -78,16 +78,18 @@ public class FunctionManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a function as used/called.
|
||||
* 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
|
||||
*/
|
||||
void markAsNeeded( FunctionName name ) {
|
||||
FunctionName markAsNeeded( FunctionName name ) {
|
||||
FunctionState state = getOrCreate( name );
|
||||
if( state.state == State.None ) {
|
||||
state.state = State.Needed;
|
||||
}
|
||||
return state.alias == null ? name : state.alias;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,6 +169,21 @@ public class FunctionManager {
|
||||
getOrCreate( name ).method = method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an alias for the method. If this method should be called then the alias method should be really called. This
|
||||
* is typical a virtual super method.
|
||||
*
|
||||
* @param name
|
||||
* the original name
|
||||
* @param alias
|
||||
* the new name.
|
||||
*/
|
||||
void setAlias( FunctionName name, FunctionName alias ) {
|
||||
FunctionState state = getOrCreate( name );
|
||||
state.alias = alias;
|
||||
state.state = State.Written;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there is a replacement method
|
||||
*
|
||||
@ -189,6 +206,8 @@ public class FunctionManager {
|
||||
private State state = State.None;
|
||||
|
||||
private MethodInfo method;
|
||||
|
||||
private FunctionName alias;
|
||||
}
|
||||
|
||||
private static enum State {
|
||||
|
@ -38,6 +38,12 @@ public class FunctionName {
|
||||
@Nonnull
|
||||
public final String className;
|
||||
|
||||
/**
|
||||
* The method name.
|
||||
*/
|
||||
@Nonnull
|
||||
public final String methodName;
|
||||
|
||||
/**
|
||||
* The name in the WebAssembly.
|
||||
*/
|
||||
@ -54,7 +60,7 @@ public class FunctionName {
|
||||
* The signature
|
||||
*/
|
||||
@Nonnull
|
||||
private final String signature;
|
||||
public final String signature;
|
||||
|
||||
/**
|
||||
* Create a new instance from the given reference in the ConstantPool or parsed method.
|
||||
@ -90,6 +96,7 @@ public class FunctionName {
|
||||
*/
|
||||
FunctionName( String className, String methodName, String signature ) {
|
||||
this.className = className;
|
||||
this.methodName = methodName;
|
||||
this.fullName = className + '.' + methodName;
|
||||
this.signatureName = fullName + signature;
|
||||
this.signature = signature;
|
||||
@ -102,11 +109,13 @@ public class FunctionName {
|
||||
* the full Java method signature like "com/foo/Bar.method()V"
|
||||
*/
|
||||
FunctionName( String signatureName ) {
|
||||
this.className = signatureName.substring( 0, signatureName.indexOf( '.' ) );
|
||||
int idx = signatureName.indexOf( '(' );
|
||||
this.fullName = signatureName.substring( 0, idx );
|
||||
int idx1 = signatureName.indexOf( '.' );
|
||||
this.className = signatureName.substring( 0, idx1 );
|
||||
int idx2 = signatureName.indexOf( '(', idx1 );
|
||||
this.methodName = signatureName.substring( idx1 + 1, idx2 );
|
||||
this.fullName = signatureName.substring( 0, idx2 );
|
||||
this.signatureName = signatureName;
|
||||
this.signature = signatureName.substring( idx );
|
||||
this.signature = signatureName.substring( idx2 );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -156,6 +156,7 @@ public class ModuleGenerator {
|
||||
|
||||
// scan all methods that should be write to build optimize structures
|
||||
FunctionName next;
|
||||
NEXT:
|
||||
while( (next = functions.nextScannLater()) != null ) {
|
||||
ClassFile classFile = ClassFile.get( next.className, libraries );
|
||||
if( classFile == null ) {
|
||||
@ -176,7 +177,20 @@ public class ModuleGenerator {
|
||||
}
|
||||
} );
|
||||
}
|
||||
if( functions.needToScan( next ) ) {
|
||||
|
||||
if( functions.needToScan( next ) ) { // function was not found
|
||||
ClassFile superClassFile = classFile;
|
||||
while( superClassFile != null ) {
|
||||
MethodInfo method = superClassFile.getMethod( next.methodName, next.signature );
|
||||
if( method != null ) {
|
||||
FunctionName name = new FunctionName( method );
|
||||
functions.markAsNeeded( name );
|
||||
functions.setAlias( next, name );
|
||||
continue NEXT;
|
||||
}
|
||||
ConstantClass superClass = superClassFile.getSuperClass();
|
||||
superClassFile = superClass == null ? null : ClassFile.get( superClass.getName(), libraries );
|
||||
}
|
||||
throw new WasmException( "Missing function: " + next.signatureName, -1 );
|
||||
}
|
||||
}
|
||||
@ -199,7 +213,7 @@ public class ModuleGenerator {
|
||||
for( WasmInstruction instruction : instructions ) {
|
||||
switch( instruction.getType() ) {
|
||||
case Call:
|
||||
functions.markAsNeeded( ((WasmCallInstruction)instruction).getFunctionName() );
|
||||
((WasmCallInstruction)instruction).markAsNeeded( functions );
|
||||
break;
|
||||
default:
|
||||
}
|
||||
@ -477,7 +491,7 @@ public class ModuleGenerator {
|
||||
}
|
||||
break;
|
||||
case Call:
|
||||
functions.markAsNeeded( ((WasmCallInstruction)instruction).getFunctionName() );
|
||||
((WasmCallInstruction)instruction).markAsNeeded( functions );
|
||||
break;
|
||||
case Struct:
|
||||
WasmStructInstruction instr = (WasmStructInstruction)instruction;
|
||||
|
@ -31,11 +31,11 @@ import de.inetsoftware.jwebassembly.wasm.AnyType;
|
||||
*/
|
||||
class WasmCallInstruction extends WasmInstruction {
|
||||
|
||||
private AnyType valueType;
|
||||
private AnyType valueType;
|
||||
|
||||
private final FunctionName name;
|
||||
private FunctionName name;
|
||||
|
||||
private int paramCount = -1;
|
||||
private int paramCount = -1;
|
||||
|
||||
/**
|
||||
* Create an instance of a function call instruction
|
||||
@ -61,13 +61,13 @@ class WasmCallInstruction extends WasmInstruction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the function name that should be called
|
||||
* Mark the function as needed in the functions manager and replace the function name with a possible super name.
|
||||
*
|
||||
* @return the name
|
||||
* @param functions
|
||||
* the function manager
|
||||
*/
|
||||
@Nonnull
|
||||
FunctionName getFunctionName() {
|
||||
return name;
|
||||
void markAsNeeded( @Nonnull FunctionManager functions ) {
|
||||
name = functions.markAsNeeded( name );
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user