mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-25 23:47:51 +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;
|
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 ) {
|
for( MethodInfo method : methods ) {
|
||||||
if( name.equals( method.getName() ) ) {
|
if( name.equals( method.getName() ) && signature.equals( method.getType() ) ) {
|
||||||
count++;
|
return method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return count;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FieldInfo getField( String name ) {
|
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
|
* @param name
|
||||||
* the function name
|
* the function name
|
||||||
|
* @return the real function name
|
||||||
*/
|
*/
|
||||||
void markAsNeeded( FunctionName name ) {
|
FunctionName markAsNeeded( FunctionName name ) {
|
||||||
FunctionState state = getOrCreate( name );
|
FunctionState state = getOrCreate( name );
|
||||||
if( state.state == State.None ) {
|
if( state.state == State.None ) {
|
||||||
state.state = State.Needed;
|
state.state = State.Needed;
|
||||||
}
|
}
|
||||||
|
return state.alias == null ? name : state.alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -167,6 +169,21 @@ public class FunctionManager {
|
|||||||
getOrCreate( name ).method = method;
|
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
|
* Check if there is a replacement method
|
||||||
*
|
*
|
||||||
@ -189,6 +206,8 @@ public class FunctionManager {
|
|||||||
private State state = State.None;
|
private State state = State.None;
|
||||||
|
|
||||||
private MethodInfo method;
|
private MethodInfo method;
|
||||||
|
|
||||||
|
private FunctionName alias;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static enum State {
|
private static enum State {
|
||||||
|
@ -38,6 +38,12 @@ public class FunctionName {
|
|||||||
@Nonnull
|
@Nonnull
|
||||||
public final String className;
|
public final String className;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The method name.
|
||||||
|
*/
|
||||||
|
@Nonnull
|
||||||
|
public final String methodName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The name in the WebAssembly.
|
* The name in the WebAssembly.
|
||||||
*/
|
*/
|
||||||
@ -54,7 +60,7 @@ public class FunctionName {
|
|||||||
* The signature
|
* The signature
|
||||||
*/
|
*/
|
||||||
@Nonnull
|
@Nonnull
|
||||||
private final String signature;
|
public final String signature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance from the given reference in the ConstantPool or parsed method.
|
* 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 ) {
|
FunctionName( String className, String methodName, String signature ) {
|
||||||
this.className = className;
|
this.className = className;
|
||||||
|
this.methodName = methodName;
|
||||||
this.fullName = className + '.' + methodName;
|
this.fullName = className + '.' + methodName;
|
||||||
this.signatureName = fullName + signature;
|
this.signatureName = fullName + signature;
|
||||||
this.signature = signature;
|
this.signature = signature;
|
||||||
@ -102,11 +109,13 @@ public class FunctionName {
|
|||||||
* the full Java method signature like "com/foo/Bar.method()V"
|
* the full Java method signature like "com/foo/Bar.method()V"
|
||||||
*/
|
*/
|
||||||
FunctionName( String signatureName ) {
|
FunctionName( String signatureName ) {
|
||||||
this.className = signatureName.substring( 0, signatureName.indexOf( '.' ) );
|
int idx1 = signatureName.indexOf( '.' );
|
||||||
int idx = signatureName.indexOf( '(' );
|
this.className = signatureName.substring( 0, idx1 );
|
||||||
this.fullName = signatureName.substring( 0, idx );
|
int idx2 = signatureName.indexOf( '(', idx1 );
|
||||||
|
this.methodName = signatureName.substring( idx1 + 1, idx2 );
|
||||||
|
this.fullName = signatureName.substring( 0, idx2 );
|
||||||
this.signatureName = signatureName;
|
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
|
// scan all methods that should be write to build optimize structures
|
||||||
FunctionName next;
|
FunctionName next;
|
||||||
|
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 ) {
|
||||||
@ -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 );
|
throw new WasmException( "Missing function: " + next.signatureName, -1 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,7 +213,7 @@ public class ModuleGenerator {
|
|||||||
for( WasmInstruction instruction : instructions ) {
|
for( WasmInstruction instruction : instructions ) {
|
||||||
switch( instruction.getType() ) {
|
switch( instruction.getType() ) {
|
||||||
case Call:
|
case Call:
|
||||||
functions.markAsNeeded( ((WasmCallInstruction)instruction).getFunctionName() );
|
((WasmCallInstruction)instruction).markAsNeeded( functions );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
@ -477,7 +491,7 @@ public class ModuleGenerator {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Call:
|
case Call:
|
||||||
functions.markAsNeeded( ((WasmCallInstruction)instruction).getFunctionName() );
|
((WasmCallInstruction)instruction).markAsNeeded( functions );
|
||||||
break;
|
break;
|
||||||
case Struct:
|
case Struct:
|
||||||
WasmStructInstruction instr = (WasmStructInstruction)instruction;
|
WasmStructInstruction instr = (WasmStructInstruction)instruction;
|
||||||
|
@ -31,11 +31,11 @@ import de.inetsoftware.jwebassembly.wasm.AnyType;
|
|||||||
*/
|
*/
|
||||||
class WasmCallInstruction extends WasmInstruction {
|
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
|
* 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
|
void markAsNeeded( @Nonnull FunctionManager functions ) {
|
||||||
FunctionName getFunctionName() {
|
name = functions.markAsNeeded( name );
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
x
Reference in New Issue
Block a user