From 0a4d03e97492a7f1d60ef884a2397f2e5ca5f939 Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Mon, 10 Jun 2019 11:39:19 +0200 Subject: [PATCH] Mark override methods as needed if the super methods are needed. --- .../jwebassembly/module/ModuleGenerator.java | 19 ++++-- .../jwebassembly/module/TypeManager.java | 28 ++++----- .../jwebassembly/text/TextModuleWriter.java | 2 +- .../jwebassembly/runtime/Structs.java | 62 ++++++++++++++++++- 4 files changed, 90 insertions(+), 21 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java index 8bddf45..841fae0 100644 --- a/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java +++ b/src/de/inetsoftware/jwebassembly/module/ModuleGenerator.java @@ -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(); } diff --git a/src/de/inetsoftware/jwebassembly/module/TypeManager.java b/src/de/inetsoftware/jwebassembly/module/TypeManager.java index af39216..8f11501 100644 --- a/src/de/inetsoftware/jwebassembly/module/TypeManager.java +++ b/src/de/inetsoftware/jwebassembly/module/TypeManager.java @@ -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 ); } } diff --git a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java index 34b4e31..92ecefb 100644 --- a/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java +++ b/src/de/inetsoftware/jwebassembly/text/TextModuleWriter.java @@ -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 ); diff --git a/test/de/inetsoftware/jwebassembly/runtime/Structs.java b/test/de/inetsoftware/jwebassembly/runtime/Structs.java index 01e9339..6d071f5 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/Structs.java +++ b/test/de/inetsoftware/jwebassembly/runtime/Structs.java @@ -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; + } } }