From 43140453c93728366a9e15e8282bf5ccb1e3921d Mon Sep 17 00:00:00 2001 From: Volker Berlin Date: Wed, 13 May 2020 21:20:19 +0200 Subject: [PATCH] fix interface calls for redefinied defaults with new defaults --- .../jwebassembly/module/TypeManager.java | 55 ++++++++++++++----- .../runtime/InterfaceOperations.java | 13 +++++ 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/de/inetsoftware/jwebassembly/module/TypeManager.java b/src/de/inetsoftware/jwebassembly/module/TypeManager.java index b2a2593..44bb99a 100644 --- a/src/de/inetsoftware/jwebassembly/module/TypeManager.java +++ b/src/de/inetsoftware/jwebassembly/module/TypeManager.java @@ -575,7 +575,7 @@ public class TypeManager { for( ; idx < vtable.size(); idx++ ) { FunctionName func = vtable.get( idx ); if( func.methodName.equals( funcName.methodName ) && func.signature.equals( funcName.signature ) ) { - if( !isDefault ) { + if( !isDefault || functions.getITableIndex( func ) >= 0 ) { vtable.set( idx, funcName ); // use the override method functions.markAsNeeded( funcName ); // mark all overridden methods also as needed if the super method is used } @@ -616,18 +616,11 @@ public class TypeManager { // all classes in the hierarchy ArrayList classFiles = new ArrayList<>(); + // list classes of the hierarchy and its interfaces + Set interfaceNames = new LinkedHashSet<>(); for( ClassFile classFile = classFileLoader.get( name );; ) { classFiles.add( classFile ); - for( ConstantClass interClass : classFile.getInterfaces() ) { - String interName = interClass.getName(); - StructType type = types.structTypes.get( interName ); - if( type == null ) { - continue; - } - interfaceTypes.add( type ); - // add all used interfaces to the instanceof set - instanceOFs.add( type ); - } + listInterfaceTypes( classFile, types, classFileLoader, interfaceTypes, interfaceNames ); ConstantClass superClass = classFile.getSuperClass(); if( superClass == null ) { @@ -660,8 +653,8 @@ public class TypeManager { if( method == null ) { // search if there is a default implementation in an interface - for( StructType iType : interfaceTypes ) { - ClassFile iClassFile = classFileLoader.get( iType.name ); + for( String iClassName : interfaceNames ) { + ClassFile iClassFile = classFileLoader.get( iClassName ); method = iClassFile.getMethod( iName.methodName, iName.signature ); if( method != null ) { break; @@ -685,6 +678,40 @@ public class TypeManager { } } + /** + * List all interface StrucTypes recursively. + * + * @param classFile + * The class from which the interfaces should listed + * @param types + * the type manager with references to the types + * @param classFileLoader + * for loading the class files + * @param interfaceTypes + * the target + * @param interfaceNames + * already listed interfaces to prevent a endless loop + * @throws IOException + * if any I/O error occur on loading or writing + */ + private void listInterfaceTypes( ClassFile classFile, TypeManager types, ClassFileLoader classFileLoader, Set interfaceTypes, Set interfaceNames ) throws IOException { + for( ConstantClass interClass : classFile.getInterfaces() ) { + String interName = interClass.getName(); + if( interfaceNames.add( interName ) ) { + StructType type = types.structTypes.get( interName ); + if( type != null ) { + interfaceTypes.add( type ); + // add all used interfaces to the instanceof set + instanceOFs.add( type ); + } + ClassFile interClassFile = classFileLoader.get( interName ); + if( interClassFile != null ) { + listInterfaceTypes( interClassFile, types, classFileLoader, interfaceTypes, interfaceNames ); + } + } + } + } + /** * {@inheritDoc} */ @@ -786,7 +813,7 @@ public class TypeManager { for( Entry> entry : interfaceMethods.entrySet() ) { data.writeInt32( entry.getKey().getClassIndex() ); List iMethods = entry.getValue(); - int nextClassPosition = data.size() + 4 * (1 + iMethods.size()); + int nextClassPosition = 4 * (2 + iMethods.size()); data.writeInt32( nextClassPosition ); for( FunctionName funcName : iMethods ) { int functIdx = getFunctionsID.applyAsInt( funcName ); diff --git a/test/de/inetsoftware/jwebassembly/runtime/InterfaceOperations.java b/test/de/inetsoftware/jwebassembly/runtime/InterfaceOperations.java index 470730c..7b41295 100644 --- a/test/de/inetsoftware/jwebassembly/runtime/InterfaceOperations.java +++ b/test/de/inetsoftware/jwebassembly/runtime/InterfaceOperations.java @@ -45,6 +45,7 @@ public class InterfaceOperations extends AbstractBaseTest { addParam( list, script, "getDefaultOverride2" ); addParam( list, script, "getDefaultExtends" ); addParam( list, script, "getDefaultReimplement" ); + addParam( list, script, "getDefaultRedefinied" ); addParam( list, script, "abstractParent" ); } rule.setTestParameters( list ); @@ -89,6 +90,12 @@ public class InterfaceOperations extends AbstractBaseTest { return bar.getDefaultValue(); } + @Export + static int getDefaultRedefinied() { + Bar bar = new Bar2() {}; + return bar.getDefaultValue(); + } + interface Bar { default int getDefaultValue() { return 7; @@ -114,6 +121,12 @@ public class InterfaceOperations extends AbstractBaseTest { static class BarReimplement extends BarExtends implements Bar { } + interface Bar2 extends Bar { + default int getDefaultValue() { + return 99; + } + } + @Export static int abstractParent() { Foo foo = new FooAdder() {