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
* first method.
* Prepare all needed methods/functions and scan the content for more needed stuff.
*
* @throws IOException
* if any I/O error occur
*/
public void prepareFinish() throws IOException {
// scan all methods that should be write to build optimize structures
private void prepareFunctions() throws IOException {
FunctionName next;
NEXT:
while( (next = functions.nextScannLater()) != null ) {
@ -193,9 +192,19 @@ public class ModuleGenerator {
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 );
prepareFunctions(); // prepare of types can add some override methods as needed
functions.prepareFinish();
writer.prepareFinish();
}

View File

@ -197,22 +197,22 @@ public class TypeManager {
continue;
}
FunctionName funcName = new FunctionName( method );
if( functions.needToWrite( funcName ) ) {
int idx = 0;
// search if the method is already in our list
for( ; idx < methods.size(); idx++ ) {
FunctionName func = methods.get( idx );
if( func.methodName.equals( funcName.methodName ) && func.signature.equals( funcName.signature ) ) {
methods.set( idx, funcName ); // use the override method
break;
}
int idx = 0;
// search if the method is already in our list
for( ; idx < methods.size(); idx++ ) {
FunctionName func = methods.get( idx );
if( func.methodName.equals( funcName.methodName ) && func.signature.equals( funcName.signature ) ) {
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;
}
if( idx == methods.size() ) {
// if a new method
methods.add( funcName );
}
functions.setFunctionIndex( funcName, idx );
}
if( idx == methods.size() && functions.needToWrite( funcName ) ) {
// if a new needed method then add it
methods.add( funcName );
}
functions.setFunctionIndex( funcName, idx );
}
}

View File

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

View File

@ -47,6 +47,10 @@ public class Structs extends AbstractBaseTest {
addParam( list, script, "isSame" );
addParam( list, script, "isNotSame" );
addParam( list, script, "simple" );
addParam( list, script, "callSuperMethod" );
//TODO addParam( list, script, "callVirtualMethod" );
addParam( list, script, "useGlobalObject" );
addParam( list, script, "multipleAssign" );
}
return list;
}
@ -92,15 +96,71 @@ public class Structs extends AbstractBaseTest {
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 {
int a;
long b;
final void foo() {
a = 1;
}
void bar() {
a = 2;
}
}
static class Abc2 extends Abc {
Abc abc;
Abc2 abc;
void bar() {
a = 3;
}
}
}