mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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 VIRTUAL_TABLE_OFFSET = 28;
|
||||
|
||||
public static int ARRAY_CLASS = -1;
|
||||
public static int BOOLEAN_CLASS = -2;
|
||||
public static int BYTE_CLASS = -3;
|
||||
public static int SHORT_CLASS = -4;
|
||||
public static int CHAR_CLASS = -5;
|
||||
public static int INT_CLASS = -6;
|
||||
public static int LONG_CLASS = -7;
|
||||
public static int FLOAT_CLASS = -8;
|
||||
public static int DOUBLE_CLASS = -9;
|
||||
public static int BOOLEAN_CLASS = -1;
|
||||
public static int BYTE_CLASS = -2;
|
||||
public static int SHORT_CLASS = -3;
|
||||
public static int CHAR_CLASS = -4;
|
||||
public static int INT_CLASS = -5;
|
||||
public static int LONG_CLASS = -6;
|
||||
public static int FLOAT_CLASS = -7;
|
||||
public static int DOUBLE_CLASS = -8;
|
||||
|
||||
public int size;
|
||||
public int flags;
|
||||
|
@ -53,4 +52,6 @@ public class RuntimeClass extends Structure {
|
|||
public int computeCanary() {
|
||||
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) {
|
||||
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) {
|
||||
|
|
|
@ -134,7 +134,7 @@ public class WasmTarget implements TeaVMTarget {
|
|||
|
||||
Decompiler decompiler = new Decompiler(classes, controller.getClassLoader(), new HashSet<>(),
|
||||
new HashSet<>());
|
||||
WasmGenerationContext context = new WasmGenerationContext(classes, vtableProvider);
|
||||
WasmGenerationContext context = new WasmGenerationContext(classes, vtableProvider, tagRegistry);
|
||||
context.addIntrinsic(new WasmRuntimeIntrinsic());
|
||||
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.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.classes.TagRegistry;
|
||||
import org.teavm.model.classes.VirtualTableProvider;
|
||||
import org.teavm.wasm.intrinsics.WasmIntrinsic;
|
||||
|
||||
public class WasmGenerationContext {
|
||||
private ClassReaderSource classSource;
|
||||
private VirtualTableProvider vtableProvider;
|
||||
private TagRegistry tagRegistry;
|
||||
private Map<MethodReference, ImportedMethod> importedMethods = new HashMap<>();
|
||||
private List<WasmIntrinsic> intrinsics = new ArrayList<>();
|
||||
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.vtableProvider = vtableProvider;
|
||||
this.tagRegistry = tagRegistry;
|
||||
}
|
||||
|
||||
public void addIntrinsic(WasmIntrinsic intrinsic) {
|
||||
|
@ -93,6 +97,10 @@ public class WasmGenerationContext {
|
|||
return vtableProvider;
|
||||
}
|
||||
|
||||
public TagRegistry getTagRegistry() {
|
||||
return tagRegistry;
|
||||
}
|
||||
|
||||
public class ImportedMethod {
|
||||
public final String name;
|
||||
public final String module;
|
||||
|
|
|
@ -16,8 +16,11 @@
|
|||
package org.teavm.wasm.generate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.teavm.ast.AssignmentStatement;
|
||||
|
@ -65,6 +68,7 @@ import org.teavm.model.FieldReference;
|
|||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.classes.TagRegistry;
|
||||
import org.teavm.model.classes.VirtualTableEntry;
|
||||
import org.teavm.runtime.Allocator;
|
||||
import org.teavm.runtime.RuntimeClass;
|
||||
|
@ -631,13 +635,9 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
block.getBody().add(new WasmSetLocal(instanceVar, instance));
|
||||
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());
|
||||
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));
|
||||
methodIndex = new WasmLoadInt32(4, methodIndex, WasmInt32Subtype.INT32);
|
||||
|
||||
|
@ -897,7 +897,55 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
|
||||
@Override
|
||||
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
|
||||
|
@ -1075,4 +1123,10 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
}
|
||||
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