mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-03 05:44:10 -08:00
Add support for instanceof expressions
This commit is contained in:
parent
1aacbea4d0
commit
38aca08993
21
core/src/main/java/org/teavm/runtime/RuntimeArray.java
Normal file
21
core/src/main/java/org/teavm/runtime/RuntimeArray.java
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* 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 org.teavm.runtime;
|
||||||
|
|
||||||
|
public class RuntimeArray extends RuntimeObject {
|
||||||
|
public int componentClassReference;
|
||||||
|
public byte depth;
|
||||||
|
}
|
|
@ -29,15 +29,14 @@ public class RuntimeClass extends Structure {
|
||||||
public static int CANARY_OFFSET = 24;
|
public static int CANARY_OFFSET = 24;
|
||||||
public static int VIRTUAL_TABLE_OFFSET = 28;
|
public static int VIRTUAL_TABLE_OFFSET = 28;
|
||||||
|
|
||||||
public static int ARRAY_CLASS = -1;
|
public static int BOOLEAN_CLASS = -1;
|
||||||
public static int BOOLEAN_CLASS = -2;
|
public static int BYTE_CLASS = -2;
|
||||||
public static int BYTE_CLASS = -3;
|
public static int SHORT_CLASS = -3;
|
||||||
public static int SHORT_CLASS = -4;
|
public static int CHAR_CLASS = -4;
|
||||||
public static int CHAR_CLASS = -5;
|
public static int INT_CLASS = -5;
|
||||||
public static int INT_CLASS = -6;
|
public static int LONG_CLASS = -6;
|
||||||
public static int LONG_CLASS = -7;
|
public static int FLOAT_CLASS = -7;
|
||||||
public static int FLOAT_CLASS = -8;
|
public static int DOUBLE_CLASS = -8;
|
||||||
public static int DOUBLE_CLASS = -9;
|
|
||||||
|
|
||||||
public int size;
|
public int size;
|
||||||
public int flags;
|
public int flags;
|
||||||
|
@ -53,4 +52,6 @@ public class RuntimeClass extends Structure {
|
||||||
public int computeCanary() {
|
public int computeCanary() {
|
||||||
return computeCanary(size, lowerTag, upperTag);
|
return computeCanary(size, lowerTag, upperTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static native RuntimeClass getArrayClass();
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,12 @@ public final class Example {
|
||||||
for (int i = 0; i < 4; ++i) {
|
for (int i = 0; i < 4; ++i) {
|
||||||
WasmRuntime.print(instance(i).foo());
|
WasmRuntime.print(instance(i).foo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WasmRuntime.print(new Derived2() instanceof Base ? 1 : 0);
|
||||||
|
WasmRuntime.print(new Derived3() instanceof Base ? 1 : 0);
|
||||||
|
WasmRuntime.print((Object) new Derived2() instanceof Derived1 ? 1 : 0);
|
||||||
|
WasmRuntime.print((Object) new Derived2() instanceof A ? 1 : 0);
|
||||||
|
WasmRuntime.print(new A(23) instanceof Base ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Base instance(int index) {
|
private static Base instance(int index) {
|
||||||
|
|
|
@ -134,7 +134,7 @@ public class WasmTarget implements TeaVMTarget {
|
||||||
|
|
||||||
Decompiler decompiler = new Decompiler(classes, controller.getClassLoader(), new HashSet<>(),
|
Decompiler decompiler = new Decompiler(classes, controller.getClassLoader(), new HashSet<>(),
|
||||||
new HashSet<>());
|
new HashSet<>());
|
||||||
WasmGenerationContext context = new WasmGenerationContext(classes, vtableProvider);
|
WasmGenerationContext context = new WasmGenerationContext(classes, vtableProvider, tagRegistry);
|
||||||
context.addIntrinsic(new WasmRuntimeIntrinsic());
|
context.addIntrinsic(new WasmRuntimeIntrinsic());
|
||||||
WasmGenerator generator = new WasmGenerator(decompiler, classes, context, classGenerator);
|
WasmGenerator generator = new WasmGenerator(decompiler, classes, context, classGenerator);
|
||||||
|
|
||||||
|
|
|
@ -29,19 +29,23 @@ import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
import org.teavm.model.classes.TagRegistry;
|
||||||
import org.teavm.model.classes.VirtualTableProvider;
|
import org.teavm.model.classes.VirtualTableProvider;
|
||||||
import org.teavm.wasm.intrinsics.WasmIntrinsic;
|
import org.teavm.wasm.intrinsics.WasmIntrinsic;
|
||||||
|
|
||||||
public class WasmGenerationContext {
|
public class WasmGenerationContext {
|
||||||
private ClassReaderSource classSource;
|
private ClassReaderSource classSource;
|
||||||
private VirtualTableProvider vtableProvider;
|
private VirtualTableProvider vtableProvider;
|
||||||
|
private TagRegistry tagRegistry;
|
||||||
private Map<MethodReference, ImportedMethod> importedMethods = new HashMap<>();
|
private Map<MethodReference, ImportedMethod> importedMethods = new HashMap<>();
|
||||||
private List<WasmIntrinsic> intrinsics = new ArrayList<>();
|
private List<WasmIntrinsic> intrinsics = new ArrayList<>();
|
||||||
private Map<MethodReference, WasmIntrinsic> intrinsicCache = new HashMap<>();
|
private Map<MethodReference, WasmIntrinsic> intrinsicCache = new HashMap<>();
|
||||||
|
|
||||||
public WasmGenerationContext(ClassReaderSource classSource, VirtualTableProvider vtableProvider) {
|
public WasmGenerationContext(ClassReaderSource classSource, VirtualTableProvider vtableProvider,
|
||||||
|
TagRegistry tagRegistry) {
|
||||||
this.classSource = classSource;
|
this.classSource = classSource;
|
||||||
this.vtableProvider = vtableProvider;
|
this.vtableProvider = vtableProvider;
|
||||||
|
this.tagRegistry = tagRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addIntrinsic(WasmIntrinsic intrinsic) {
|
public void addIntrinsic(WasmIntrinsic intrinsic) {
|
||||||
|
@ -93,6 +97,10 @@ public class WasmGenerationContext {
|
||||||
return vtableProvider;
|
return vtableProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TagRegistry getTagRegistry() {
|
||||||
|
return tagRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
public class ImportedMethod {
|
public class ImportedMethod {
|
||||||
public final String name;
|
public final String name;
|
||||||
public final String module;
|
public final String module;
|
||||||
|
|
|
@ -16,8 +16,11 @@
|
||||||
package org.teavm.wasm.generate;
|
package org.teavm.wasm.generate;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.teavm.ast.AssignmentStatement;
|
import org.teavm.ast.AssignmentStatement;
|
||||||
|
@ -65,6 +68,7 @@ import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
import org.teavm.model.classes.TagRegistry;
|
||||||
import org.teavm.model.classes.VirtualTableEntry;
|
import org.teavm.model.classes.VirtualTableEntry;
|
||||||
import org.teavm.runtime.Allocator;
|
import org.teavm.runtime.Allocator;
|
||||||
import org.teavm.runtime.RuntimeClass;
|
import org.teavm.runtime.RuntimeClass;
|
||||||
|
@ -631,13 +635,9 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
block.getBody().add(new WasmSetLocal(instanceVar, instance));
|
block.getBody().add(new WasmSetLocal(instanceVar, instance));
|
||||||
instance = new WasmGetLocal(instanceVar);
|
instance = new WasmGetLocal(instanceVar);
|
||||||
|
|
||||||
WasmExpression classIndex = new WasmLoadInt32(4, instance, WasmInt32Subtype.INT32);
|
|
||||||
classIndex = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHL, classIndex,
|
|
||||||
new WasmInt32Constant(3));
|
|
||||||
|
|
||||||
VirtualTableEntry vtableEntry = context.getVirtualTableProvider().lookup(expr.getMethod());
|
VirtualTableEntry vtableEntry = context.getVirtualTableProvider().lookup(expr.getMethod());
|
||||||
WasmExpression methodIndex = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD,
|
WasmExpression methodIndex = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD,
|
||||||
classIndex, new WasmInt32Constant(vtableEntry.getIndex() * 4
|
getReferenceToClass(instance), new WasmInt32Constant(vtableEntry.getIndex() * 4
|
||||||
+ RuntimeClass.VIRTUAL_TABLE_OFFSET));
|
+ RuntimeClass.VIRTUAL_TABLE_OFFSET));
|
||||||
methodIndex = new WasmLoadInt32(4, methodIndex, WasmInt32Subtype.INT32);
|
methodIndex = new WasmLoadInt32(4, methodIndex, WasmInt32Subtype.INT32);
|
||||||
|
|
||||||
|
@ -897,7 +897,55 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visit(InstanceOfExpr expr) {
|
public void visit(InstanceOfExpr expr) {
|
||||||
|
expr.getExpr().acceptVisitor(this);
|
||||||
|
|
||||||
|
if (expr.getType() instanceof ValueType.Object) {
|
||||||
|
ValueType.Object cls = (ValueType.Object) expr.getType();
|
||||||
|
List<TagRegistry.Range> ranges = context.getTagRegistry().getRanges(cls.getClassName());
|
||||||
|
Collections.sort(ranges, Comparator.comparingInt(range -> range.lower));
|
||||||
|
|
||||||
|
WasmBlock block = new WasmBlock(false);
|
||||||
|
WasmLocal tagVar = function.getLocalVariables().get(getTemporaryInt32());
|
||||||
|
WasmExpression tagPtr = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD,
|
||||||
|
getReferenceToClass(result), new WasmInt32Constant(RuntimeClass.LOWER_TAG_OFFSET));
|
||||||
|
block.getBody().add(new WasmSetLocal(tagVar, new WasmLoadInt32(4, tagPtr, WasmInt32Subtype.INT32)));
|
||||||
|
|
||||||
|
WasmExpression lowerThanMinCond = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.LT_SIGNED,
|
||||||
|
new WasmGetLocal(tagVar), new WasmInt32Constant(ranges.get(0).lower));
|
||||||
|
WasmBranch lowerThanMin = new WasmBranch(lowerThanMinCond, block);
|
||||||
|
lowerThanMin.setResult(new WasmInt32Constant(0));
|
||||||
|
block.getBody().add(lowerThanMin);
|
||||||
|
|
||||||
|
WasmExpression upperThanMaxCond = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.GT_SIGNED,
|
||||||
|
new WasmGetLocal(tagVar), new WasmInt32Constant(ranges.get(ranges.size() - 1).upper));
|
||||||
|
WasmBranch upperThanMax = new WasmBranch(upperThanMaxCond, block);
|
||||||
|
upperThanMax.setResult(new WasmInt32Constant(0));
|
||||||
|
block.getBody().add(upperThanMax);
|
||||||
|
|
||||||
|
for (int i = 1; i < ranges.size(); ++i) {
|
||||||
|
WasmExpression upperThanExcluded = new WasmIntBinary(WasmIntType.INT32,
|
||||||
|
WasmIntBinaryOperation.GT_SIGNED, new WasmGetLocal(tagVar),
|
||||||
|
new WasmInt32Constant(ranges.get(i - 1).upper));
|
||||||
|
WasmConditional conditional = new WasmConditional(upperThanExcluded);
|
||||||
|
WasmExpression lowerThanExluded = new WasmIntBinary(WasmIntType.INT32,
|
||||||
|
WasmIntBinaryOperation.LT_SIGNED, new WasmGetLocal(tagVar),
|
||||||
|
new WasmInt32Constant(ranges.get(i).lower));
|
||||||
|
|
||||||
|
WasmBranch branch = new WasmBranch(lowerThanExluded, block);
|
||||||
|
branch.setResult(new WasmInt32Constant(0));
|
||||||
|
conditional.getThenBlock().getBody().add(branch);
|
||||||
|
|
||||||
|
block.getBody().add(conditional);
|
||||||
|
}
|
||||||
|
|
||||||
|
block.getBody().add(new WasmInt32Constant(1));
|
||||||
|
|
||||||
|
result = block;
|
||||||
|
} else if (expr.getType() instanceof ValueType.Array) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1075,4 +1123,10 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
||||||
}
|
}
|
||||||
return temporaryInt32;
|
return temporaryInt32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private WasmExpression getReferenceToClass(WasmExpression instance) {
|
||||||
|
WasmExpression classIndex = new WasmLoadInt32(4, instance, WasmInt32Subtype.INT32);
|
||||||
|
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHL, classIndex,
|
||||||
|
new WasmInt32Constant(3));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user