implements StructType.isSubTypeOf(x)

This commit is contained in:
Volker Berlin 2021-03-28 15:16:45 +02:00
parent f4fd312d31
commit 1f167d99b9
3 changed files with 162 additions and 13 deletions

View File

@ -102,6 +102,8 @@ public class ModuleGenerator {
optimizer = options.optimizer;
javaCodeBuilder.init( options, classFileLoader );
((WasmCodeBuilder)watParser).init( options, classFileLoader );
types.init( classFileLoader );
scanLibraries( libraries );
}
@ -279,7 +281,7 @@ public class ModuleGenerator {
scanFunctions();
functCount = functions.size(); // scan the functions can find new needed types or only new needed fields in the known types
scanForClinit();
types.scanTypeHierarchy( classFileLoader ); // scan the type hierarchy can find new functions
types.scanTypeHierarchy(); // scan the type hierarchy can find new functions
} while( functCount < functions.size() );
// write only the needed imports to the output
@ -319,10 +321,10 @@ public class ModuleGenerator {
}
// scan again if there are new types or new needed fields
types.scanTypeHierarchy( classFileLoader );
types.scanTypeHierarchy();
JWebAssembly.LOGGER.fine( "scan finish" );
types.prepareFinish( writer, classFileLoader );
types.prepareFinish( writer );
functions.prepareFinish();
strings.prepareFinish( writer );
writer.prepareFinish();

View File

@ -18,6 +18,7 @@ package de.inetsoftware.jwebassembly.module;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
@ -159,6 +160,8 @@ public class TypeManager {
private int typeTableOffset;
private ClassFileLoader classFileLoader;
/**
* Initialize the type manager.
*
@ -169,6 +172,14 @@ public class TypeManager {
this.options = options;
}
/**
* Initialize the type manager
* @param classFileLoader for loading the class files
*/
void init( ClassFileLoader classFileLoader ) {
this.classFileLoader = classFileLoader;
}
/**
* Count of used types
*
@ -190,12 +201,10 @@ public class TypeManager {
/**
* Scan the hierarchy of the types.
*
* @param classFileLoader
* for loading the class files
* @throws IOException
* if any I/O error occur on loading or writing
*/
void scanTypeHierarchy( ClassFileLoader classFileLoader ) throws IOException {
void scanTypeHierarchy() throws IOException {
for( StructType type : structTypes.values() ) {
type.scanTypeHierarchy( options.functions, this, classFileLoader );
}
@ -206,12 +215,10 @@ public class TypeManager {
*
* @param writer
* the targets for the types
* @param classFileLoader
* for loading the class files
* @throws IOException
* if any I/O error occur on loading or writing
*/
void prepareFinish( ModuleWriter writer, ClassFileLoader classFileLoader ) throws IOException {
void prepareFinish( ModuleWriter writer ) throws IOException {
isFinish = true;
for( StructType type : structTypes.values() ) {
type.writeStructType( writer );
@ -570,7 +577,9 @@ public class TypeManager {
private final String name;
private final StructTypeKind kind;
private final StructTypeKind kind;
private final TypeManager manager;
private final int classIndex;
@ -595,7 +604,7 @@ public class TypeManager {
* Create a reference to type
*
* @param name
* the Java class name
* the Java class name like "java/lang/String"
* @param kind
* the type kind
* @param manager
@ -604,6 +613,7 @@ public class TypeManager {
protected StructType( @Nonnull String name, @Nonnull StructTypeKind kind, @Nonnull TypeManager manager ) {
this.name = name;
this.kind = kind;
this.manager = manager;
switch( kind ) {
case array_native:
this.classIndex = -1;
@ -943,8 +953,43 @@ public class TypeManager {
*/
@Override
public boolean isSubTypeOf( AnyType type ) {
//TODO if type is StructType (class or interface)
return type == this || type == ValueType.externref || type == ValueType.anyref || type == ValueType.eqref;
if( type == this || type == ValueType.externref || type == ValueType.anyref || type == ValueType.eqref ) {
return true;
}
if( !(type instanceof StructType) ) {
return false;
}
StructType structType = (StructType)type;
if( kind != structType.kind ) {
return false;
}
try {
ClassFile classFile = manager.classFileLoader.get( name );
if( classFile != null ) {
for( ConstantClass interClass : classFile.getInterfaces() ) {
if( interClass.getName().equals( structType.name ) ) {
return true;
}
}
while( classFile != null ) {
ConstantClass superClass = classFile.getSuperClass();
if( superClass == null ) {
break;
}
String superName = superClass.getName();
if( superName.equals( structType.name ) ) {
return true;
}
classFile = manager.classFileLoader.get( superName );
}
}
} catch( IOException ex ) {
throw new UncheckedIOException( ex );
}
return false;
}
/**

View File

@ -0,0 +1,102 @@
/*
* Copyright 2021 Volker Berlin (i-net software)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.inetsoftware.jwebassembly.module;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.util.HashMap;
import org.junit.Before;
import org.junit.Test;
import de.inetsoftware.jwebassembly.JWebAssembly;
import de.inetsoftware.jwebassembly.module.TypeManager.StructType;
import de.inetsoftware.jwebassembly.module.TypeManager.StructTypeKind;
/**
* @author Volker Berlin
*/
public class StructTypeTest {
private TypeManager manager;
@Before
public void before() {
HashMap<String, String> properties = new HashMap<>();
properties.put( JWebAssembly.WASM_USE_GC, "true" );
WasmOptions options = new WasmOptions( properties );
manager = options.types;
manager.init( new ClassFileLoader( getClass().getClassLoader() ) );
}
@Test
public void isSubTypeOf_SuperClass() throws Throwable {
StructType typeInteger = manager.valueOf( "java/lang/Integer" );
StructType typeNumber = manager.valueOf( "java/lang/Number" );
StructType typeObject = manager.valueOf( "java/lang/Object" );
assertTrue( typeInteger.isSubTypeOf( typeInteger ) );
assertTrue( typeInteger.isSubTypeOf( typeNumber ) );
assertTrue( typeInteger.isSubTypeOf( typeObject ) );
assertFalse( typeNumber.isSubTypeOf( typeInteger ) );
assertFalse( typeObject.isSubTypeOf( typeInteger ) );
assertFalse( typeObject.isSubTypeOf( typeNumber ) );
}
@Test
public void isSubTypeOf_Primitives() throws Throwable {
StructType typeObject = manager.valueOf( "java/lang/Object" );
StructType typeBoolean = manager.valueOf( "boolean" );
StructType typeInt = manager.valueOf( "int" );
assertEquals( StructTypeKind.primitive, typeBoolean.getKind() );
assertEquals( StructTypeKind.primitive, typeInt.getKind() );
assertEquals( StructTypeKind.normal, typeObject.getKind() );
assertFalse( typeBoolean.isSubTypeOf( typeInt ) );
assertFalse( typeInt.isSubTypeOf( typeBoolean ) );
assertFalse( typeBoolean.isSubTypeOf( typeObject ) );
assertFalse( typeObject.isSubTypeOf( typeBoolean ) );
}
@Test
public void isSubTypeOf_Interfaces() throws Throwable {
StructType typeInteger = manager.valueOf( "java/lang/Integer" );
StructType typeComparable = manager.valueOf( "java/lang/Comparable" );
assertTrue( typeInteger.isSubTypeOf( typeComparable ) );
assertFalse( typeComparable.isSubTypeOf( typeInteger ) );
}
@Test
public void isSubTypeOf_Arrays() throws Throwable {
StructType typeObject = manager.valueOf( "java/lang/Object" );
StructType typeInteger = manager.valueOf( "java/lang/Integer" );
StructType typeObjArray = manager.arrayType( typeObject );
StructType typeIntArray = manager.arrayType( typeInteger );
assertTrue( typeObjArray.isSubTypeOf( typeObject ) );
assertFalse( typeObjArray.isSubTypeOf( typeInteger ) );
assertTrue( typeIntArray.isSubTypeOf( typeObjArray ) );
assertFalse( typeObjArray.isSubTypeOf( typeIntArray ) );
}
}