mirror of
https://github.com/i-net-software/JWebAssembly.git
synced 2025-03-15 02:44:47 +01:00
implements INSTANCEOF operation
This commit is contained in:
parent
0138eb5dc0
commit
6c820ba5e6
@ -52,6 +52,11 @@ public class TypeManager {
|
||||
/** name of virtual function table, start with a point for an invalid Java identifier */
|
||||
static final String VTABLE = ".vtable";
|
||||
|
||||
/**
|
||||
* The reserved position on start of the vtable:
|
||||
* <li>offset of interface call table (itable)
|
||||
* <li>offset of instanceof list
|
||||
*/
|
||||
private static final int VTABLE_FIRST_FUNCTION_INDEX = 2;
|
||||
|
||||
private Map<String, StructType> structTypes = new LinkedHashMap<>();
|
||||
@ -132,13 +137,13 @@ public class TypeManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the FunctionName for a virtual call and mark it as used. The function has 2 parameters (THIS,
|
||||
* Create the FunctionName for a virtual call and mark it as used. The function has 2 parameters (THIS,
|
||||
* virtualfunctionIndex) and returns the index of the function.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
@Nonnull
|
||||
WatCodeSyntheticFunctionName getCallVirtualGC() {
|
||||
WatCodeSyntheticFunctionName createCallVirtualGC() {
|
||||
return new WatCodeSyntheticFunctionName( //
|
||||
"callVirtual", "local.get 0 " // THIS
|
||||
+ "struct.get java/lang/Object .vtable " // vtable is on index 0
|
||||
@ -149,6 +154,49 @@ public class TypeManager {
|
||||
, valueOf( "java/lang/Object" ), ValueType.i32, null, ValueType.i32 ); //
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the FunctionName for the INSTANCEOF operation and mark it as used. The function has 2 parameters (THIS,
|
||||
* classIndex) and returns true if there is a match.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
WatCodeSyntheticFunctionName createInstanceOf() {
|
||||
return new WatCodeSyntheticFunctionName( //
|
||||
"instanceof", "local.get 0 " // THIS
|
||||
+ "struct.get java/lang/Object .vtable " // vtable is on index 0
|
||||
+ "local.tee 2 " // save the vtable location
|
||||
+ "i32.load offset=4 align=4 " // get offset of instanceof inside vtable (int position 1, byte position 4)
|
||||
+ "local.get 2 " // get the vtable location
|
||||
+ "i32.add " //
|
||||
+ "local.tee 2 " // save the instanceof location
|
||||
+ "i32.load offset=0 align=4 " // count of instanceof entries
|
||||
+ "i32.const 4 " //
|
||||
+ "i32.mul " //
|
||||
+ "local.get 2 " // get the instanceof location
|
||||
+ "i32.add " //
|
||||
+ "local.set 3 " // save end position
|
||||
+ "loop" //
|
||||
+ " local.get 2 " // get the instanceof location pointer
|
||||
+ " local.get 3 " // get the end location
|
||||
+ " i32.eq" //
|
||||
+ " if" // current offset == end offset
|
||||
+ " i32.const 0" // not found
|
||||
+ " return" //
|
||||
+ " end" //
|
||||
+ " local.get 2" // get the instanceof location pointer
|
||||
+ " i32.const 4" //
|
||||
+ " i32.add" // increment offset
|
||||
+ " local.tee 2" // save the instanceof location pointer
|
||||
+ " i32.load offset=0 align=4" //
|
||||
+ " local.get 1" // the class index that we search
|
||||
+ " i32.ne" //
|
||||
+ " br_if 0 " //
|
||||
+ "end " //
|
||||
+ "i32.const 1 " // class/interface found
|
||||
+ "return " //
|
||||
, valueOf( "java/lang/Object" ), ValueType.i32, null, ValueType.i32 ); //
|
||||
}
|
||||
|
||||
/**
|
||||
* A reference to a type.
|
||||
*
|
||||
@ -259,9 +307,9 @@ public class TypeManager {
|
||||
}
|
||||
}
|
||||
|
||||
// add all interfaces to the instanceof
|
||||
// add all interfaces to the instanceof set
|
||||
for(ConstantClass interClass : classFile.getInterfaces() ) {
|
||||
StructType type = types.structTypes.get( className );
|
||||
StructType type = types.structTypes.get( interClass.getName() );
|
||||
if( type != null ) {
|
||||
instanceOFs.add( type );
|
||||
}
|
||||
|
@ -52,11 +52,6 @@ import de.inetsoftware.jwebassembly.wasm.WasmBlockOperator;
|
||||
*/
|
||||
public abstract class WasmCodeBuilder {
|
||||
|
||||
/**
|
||||
* declare for frequently use of virtual call with non GC mode.
|
||||
*/
|
||||
static final SyntheticFunctionName GET_I32 = new JavaScriptSyntheticFunctionName( "NonGC", "get_i32", () -> "(a,i) => a[i]", ValueType.anyref, ValueType.i32, null, ValueType.i32 );
|
||||
|
||||
private final LocaleVariableManager localVariables = new LocaleVariableManager();
|
||||
|
||||
private final List<WasmInstruction> instructions = new ArrayList<>();
|
||||
@ -497,11 +492,7 @@ public abstract class WasmCodeBuilder {
|
||||
}
|
||||
indirectCall.setVariableIndexOfThis( varIndex );
|
||||
instructions.add( indirectCall );
|
||||
if( !options.useGC() ) {
|
||||
// for later access of the vtable
|
||||
functions.markAsNeeded( GET_I32 );
|
||||
functions.markAsImport( GET_I32, GET_I32.getAnnotation() );
|
||||
}
|
||||
options.registerGet_i32(); // for later access of the vtable
|
||||
}
|
||||
|
||||
/**
|
||||
@ -643,6 +634,12 @@ public abstract class WasmCodeBuilder {
|
||||
* the line number in the Java source code
|
||||
*/
|
||||
protected void addStructInstruction( StructOperator op, @Nonnull String typeName, @Nullable NamedStorageType fieldName, int javaCodePos, int lineNumber ) {
|
||||
if( op == StructOperator.INSTANCEOF ) {
|
||||
instructions.add( new WasmConstInstruction( types.valueOf( typeName ).getClassIndex(), javaCodePos, lineNumber ) );
|
||||
FunctionName name = options.getInstanceOf();
|
||||
instructions.add( new WasmCallInstruction( name, javaCodePos, lineNumber, types, false ) );
|
||||
return;
|
||||
}
|
||||
WasmStructInstruction structInst = new WasmStructInstruction( op, typeName, fieldName, javaCodePos, lineNumber, types );
|
||||
instructions.add( structInst );
|
||||
if( !options.useGC() ) {
|
||||
|
@ -20,11 +20,13 @@ import java.util.HashMap;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import de.inetsoftware.jwebassembly.JWebAssembly;
|
||||
import de.inetsoftware.jwebassembly.javascript.JavaScriptSyntheticFunctionName;
|
||||
import de.inetsoftware.jwebassembly.module.CodeOptimizer;
|
||||
import de.inetsoftware.jwebassembly.module.FunctionManager;
|
||||
import de.inetsoftware.jwebassembly.module.FunctionName;
|
||||
import de.inetsoftware.jwebassembly.module.StringManager;
|
||||
import de.inetsoftware.jwebassembly.module.TypeManager;
|
||||
import de.inetsoftware.jwebassembly.wasm.ValueType;
|
||||
|
||||
/**
|
||||
* The option/properties for the behavior of the compiler.
|
||||
@ -55,9 +57,12 @@ public class WasmOptions {
|
||||
*/
|
||||
public FunctionName ref_eq;
|
||||
|
||||
private FunctionName get_i32;
|
||||
|
||||
private FunctionName callVirtual;
|
||||
|
||||
private FunctionName instanceOf;
|
||||
|
||||
/**
|
||||
* Create a new instance of options
|
||||
*
|
||||
@ -112,6 +117,21 @@ public class WasmOptions {
|
||||
return sourceMapBase;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register FunctionName "NonGC.get_i32" for frequently access to vtable with non GC mode.
|
||||
*/
|
||||
void registerGet_i32() {
|
||||
if( useGC ) {
|
||||
return;
|
||||
}
|
||||
if( get_i32 == null ) {
|
||||
SyntheticFunctionName name;
|
||||
get_i32 = name = new JavaScriptSyntheticFunctionName( "NonGC", "get_i32", () -> "(a,i) => a[i]", ValueType.anyref, ValueType.i32, null, ValueType.i32 );
|
||||
functions.markAsNeeded( name );
|
||||
functions.markAsImport( name, name.getAnnotation() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the FunctionName for a virtual call and mark it as used. The function has 2 parameters (THIS,
|
||||
* virtualfunctionIndex) and returns the index of the function.
|
||||
@ -122,8 +142,26 @@ public class WasmOptions {
|
||||
FunctionName getCallVirtual() {
|
||||
FunctionName name = callVirtual;
|
||||
if( name == null ) {
|
||||
callVirtual = name = types.getCallVirtualGC();
|
||||
callVirtual = name = types.createCallVirtualGC();
|
||||
functions.markAsNeeded( name );
|
||||
registerGet_i32();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the FunctionName for an INSTANCEOF check and mark it as used. The function has 2 parameters (THIS,
|
||||
* classIndex) and returns true or false.
|
||||
*
|
||||
* @return the name
|
||||
*/
|
||||
@Nonnull
|
||||
FunctionName getInstanceOf() {
|
||||
FunctionName name = instanceOf;
|
||||
if( name == null ) {
|
||||
instanceOf = name = types.createInstanceOf();
|
||||
functions.markAsNeeded( name );
|
||||
registerGet_i32();
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
@ -126,19 +126,6 @@ public class RuntimeErrors {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void instanceofCall() throws IOException {
|
||||
compileErrorTest( "Unknown operator: INSTANCEOF", InstanceofMethod.class );
|
||||
}
|
||||
|
||||
static class InstanceofMethod {
|
||||
@Export
|
||||
static boolean runnable() {
|
||||
Object obj = new Object();
|
||||
return obj instanceof Integer;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkcast() throws IOException {
|
||||
compileErrorTest( "Unknown operator: CAST", CheckcastMethod.class );
|
||||
|
@ -17,6 +17,8 @@ package de.inetsoftware.jwebassembly.runtime;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
@ -50,6 +52,9 @@ public class StructsNonGC extends AbstractBaseTest {
|
||||
addParam( list, script, "useGlobalObject" );
|
||||
addParam( list, script, "multipleAssign" );
|
||||
addParam( list, script, "getDefaultValue" );
|
||||
addParam( list, script, "instanceof1" );
|
||||
addParam( list, script, "instanceof2" );
|
||||
addParam( list, script, "instanceof3" );
|
||||
}
|
||||
rule.setTestParameters( list );
|
||||
return list;
|
||||
@ -143,6 +148,24 @@ public class StructsNonGC extends AbstractBaseTest {
|
||||
Abc2 val = new Abc2();
|
||||
return val.getDefault();
|
||||
}
|
||||
|
||||
@Export
|
||||
static boolean instanceof1() {
|
||||
Object obj = new Object();
|
||||
return obj instanceof Integer;
|
||||
}
|
||||
|
||||
@Export
|
||||
static boolean instanceof2() {
|
||||
Object obj = new Object();
|
||||
return obj instanceof Object;
|
||||
}
|
||||
|
||||
@Export
|
||||
static boolean instanceof3() {
|
||||
Object obj = new LinkedList();
|
||||
return obj instanceof List;
|
||||
}
|
||||
}
|
||||
|
||||
interface TestDefault {
|
||||
|
Loading…
x
Reference in New Issue
Block a user