Mark override methods as needed if the super methods are needed.

This commit is contained in:
Volker Berlin 2019-06-10 11:39:19 +02:00
parent 3d5e3af432
commit 0a4d03e974
4 changed files with 90 additions and 21 deletions

View File

@ -144,13 +144,12 @@ public class ModuleGenerator {
} }
/** /**
* Finish the prepare after all classes/methods are prepare. This must be call before we can start with write the * Prepare all needed methods/functions and scan the content for more needed stuff.
* first method. *
* @throws IOException * @throws IOException
* if any I/O error occur * if any I/O error occur
*/ */
public void prepareFinish() throws IOException { private void prepareFunctions() throws IOException {
// scan all methods that should be write to build optimize structures
FunctionName next; FunctionName next;
NEXT: NEXT:
while( (next = functions.nextScannLater()) != null ) { while( (next = functions.nextScannLater()) != null ) {
@ -193,9 +192,19 @@ public class ModuleGenerator {
throw new WasmException( "Missing function: " + next.signatureName, -1 ); throw new WasmException( "Missing function: " + next.signatureName, -1 );
} }
} }
functions.prepareFinish(); }
/**
* Finish the prepare after all classes/methods are prepare. This must be call before we can start with write the
* first method.
* @throws IOException
* if any I/O error occur
*/
public void prepareFinish() throws IOException {
prepareFunctions();
types.prepareFinish( writer, functions, libraries ); types.prepareFinish( writer, functions, libraries );
prepareFunctions(); // prepare of types can add some override methods as needed
functions.prepareFinish();
writer.prepareFinish(); writer.prepareFinish();
} }

View File

@ -197,24 +197,24 @@ public class TypeManager {
continue; continue;
} }
FunctionName funcName = new FunctionName( method ); FunctionName funcName = new FunctionName( method );
if( functions.needToWrite( funcName ) ) {
int idx = 0; int idx = 0;
// search if the method is already in our list // search if the method is already in our list
for( ; idx < methods.size(); idx++ ) { for( ; idx < methods.size(); idx++ ) {
FunctionName func = methods.get( idx ); FunctionName func = methods.get( idx );
if( func.methodName.equals( funcName.methodName ) && func.signature.equals( funcName.signature ) ) { if( func.methodName.equals( funcName.methodName ) && func.signature.equals( funcName.signature ) ) {
methods.set( idx, funcName ); // use the override method methods.set( idx, funcName ); // use the override method
functions.markAsNeeded( funcName ); // mark all overridden methods also as needed if the super method is used
break; break;
} }
} }
if( idx == methods.size() ) { if( idx == methods.size() && functions.needToWrite( funcName ) ) {
// if a new method // if a new needed method then add it
methods.add( funcName ); methods.add( funcName );
} }
functions.setFunctionIndex( funcName, idx ); functions.setFunctionIndex( funcName, idx );
} }
} }
}
/** /**
* {@inheritDoc} * {@inheritDoc}

View File

@ -157,7 +157,7 @@ public class TextModuleWriter extends ModuleWriter {
protected int writeStructType( StructType type ) throws IOException { protected int writeStructType( StructType type ) throws IOException {
type.setVTable( dataStream.size() ); type.setVTable( dataStream.size() );
for( FunctionName funcName : type.getMethods() ) { for( FunctionName funcName : type.getMethods() ) {
int functIdx = functions.get( funcName.signatureName ).id; int functIdx = getFunction( funcName ).id;
// little-endian byte order // little-endian byte order
dataStream.write( functIdx >>> 0 ); dataStream.write( functIdx >>> 0 );
dataStream.write( functIdx >>> 8 ); dataStream.write( functIdx >>> 8 );

View File

@ -47,6 +47,10 @@ public class Structs extends AbstractBaseTest {
addParam( list, script, "isSame" ); addParam( list, script, "isSame" );
addParam( list, script, "isNotSame" ); addParam( list, script, "isNotSame" );
addParam( list, script, "simple" ); addParam( list, script, "simple" );
addParam( list, script, "callSuperMethod" );
//TODO addParam( list, script, "callVirtualMethod" );
addParam( list, script, "useGlobalObject" );
addParam( list, script, "multipleAssign" );
} }
return list; return list;
} }
@ -92,15 +96,71 @@ public class Structs extends AbstractBaseTest {
return val.a; return val.a;
} }
/**
* Call a method that is declared in the super class of the instance
*/
@Export
static int callSuperMethod() {
Abc2 val = new Abc2();
val.foo();
return val.a;
}
/**
* Call an overridden method
*/
@Export
static int callVirtualMethod() {
Abc val = new Abc2();
val.bar();
return val.a;
}
/**
* Access a object in a global/static variable.
*/
static Abc2 valGlobal;
@Export
static int useGlobalObject() {
valGlobal = new Abc2();
valGlobal.foo();
return valGlobal.a;
}
/**
* Assign multiple with a field. There are complex stack operation
*/
@Export
static int multipleAssign() {
Abc2 val = new Abc2();
for( int i = 0; i < 1_000; i++ ) {
val.a = 42;
// TODO
//val = val.abc = new Abc2();
}
return val.a;
}
} }
static class Abc { static class Abc {
int a; int a;
long b; long b;
final void foo() {
a = 1;
}
void bar() {
a = 2;
}
} }
static class Abc2 extends Abc { static class Abc2 extends Abc {
Abc abc; Abc2 abc;
void bar() {
a = 3;
}
} }
} }