mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Further development of WASM backend
This commit is contained in:
parent
b83c33bcc6
commit
3f02cad9e7
|
@ -26,16 +26,9 @@ import org.teavm.platform.PlatformClass;
|
|||
import org.teavm.platform.metadata.ClassResource;
|
||||
import org.teavm.platform.metadata.ClassScopedMetadataProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
* @param <T> class type.
|
||||
*/
|
||||
public class TClass<T> extends TObject implements TAnnotatedElement {
|
||||
TString name;
|
||||
TString simpleName;
|
||||
private TClass<?> componentType;
|
||||
private boolean componentTypeDirty = true;
|
||||
private PlatformClass platformClass;
|
||||
private TAnnotation[] annotationsCache;
|
||||
private Map<TClass<?>, TAnnotation> annotationsByType;
|
||||
|
@ -112,17 +105,7 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
|
|||
}
|
||||
|
||||
public TClass<?> getComponentType() {
|
||||
if (componentTypeDirty) {
|
||||
PlatformClass arrayItem = platformClass.getMetadata().getArrayItem();
|
||||
componentType = arrayItem != null ? getClass(arrayItem) : null;
|
||||
componentTypeDirty = false;
|
||||
}
|
||||
return componentType;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static TClass<TVoid> voidClass() {
|
||||
return (TClass<TVoid>) getClass(Platform.getPrimitives().getVoidClass());
|
||||
return getClass(platformClass.getMetadata().getArrayItem());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
@ -145,11 +128,6 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
|
|||
return (TClass<TShort>) getClass(Platform.getPrimitives().getShortClass());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static TClass<TInteger> intClass() {
|
||||
return (TClass<TInteger>) getClass(Platform.getPrimitives().getIntClass());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static TClass<TLong> longClass() {
|
||||
return (TClass<TLong>) getClass(Platform.getPrimitives().getLongClass());
|
||||
|
|
|
@ -15,15 +15,11 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class TInteger extends TNumber implements TComparable<TInteger> {
|
||||
public static final int SIZE = 32;
|
||||
public static final int MIN_VALUE = 0x80000000;
|
||||
public static final int MAX_VALUE = 0x7FFFFFFF;
|
||||
public static final TClass<TInteger> TYPE = TClass.intClass();
|
||||
public static final Class<Integer> TYPE = int.class;
|
||||
private static TInteger[] integerCache;
|
||||
private int value;
|
||||
|
||||
|
|
|
@ -15,10 +15,6 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.lang;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public final class TVoid extends TObject {
|
||||
public static final TClass<TVoid> TYPE = TClass.voidClass();
|
||||
public static final Class<Void> TYPE = void.class;
|
||||
}
|
||||
|
|
|
@ -15,11 +15,9 @@
|
|||
*/
|
||||
package org.teavm.runtime;
|
||||
|
||||
import org.teavm.interop.Structure;
|
||||
|
||||
public class RuntimeClass extends Structure {
|
||||
public class RuntimeClass extends RuntimeJavaObject {
|
||||
public static int INITIALIZED = 1;
|
||||
public static int PRIMITIVE = 1;
|
||||
public static int PRIMITIVE = 2;
|
||||
|
||||
public int size;
|
||||
public int flags;
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
*/
|
||||
package org.teavm.wasm;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public final class Example {
|
||||
private Example() {
|
||||
}
|
||||
|
@ -66,6 +70,14 @@ public final class Example {
|
|||
WasmRuntime.print(o.hashCode());
|
||||
WasmRuntime.print(new Object().hashCode());
|
||||
WasmRuntime.print(new Object().hashCode());
|
||||
|
||||
/*List<Integer> list = new ArrayList<>(Arrays.asList(333, 444, 555));
|
||||
list.add(1234);
|
||||
list.remove(444);
|
||||
|
||||
for (int item : list) {
|
||||
WasmRuntime.print(item);
|
||||
}*/
|
||||
}
|
||||
|
||||
private static Base instance(int index) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.teavm.ast.decompilation.Decompiler;
|
||||
import org.teavm.dependency.ClassDependency;
|
||||
import org.teavm.dependency.DependencyChecker;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.interop.Import;
|
||||
|
@ -37,6 +38,7 @@ import org.teavm.model.ClassHolder;
|
|||
import org.teavm.model.ClassHolderTransformer;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.ElementModifier;
|
||||
import org.teavm.model.FieldReader;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.ListableClassHolderSource;
|
||||
|
@ -52,7 +54,10 @@ import org.teavm.model.classes.VirtualTableProvider;
|
|||
import org.teavm.model.instructions.InvocationType;
|
||||
import org.teavm.model.instructions.InvokeInstruction;
|
||||
import org.teavm.runtime.Allocator;
|
||||
import org.teavm.runtime.RuntimeArray;
|
||||
import org.teavm.runtime.RuntimeClass;
|
||||
import org.teavm.runtime.RuntimeJavaObject;
|
||||
import org.teavm.runtime.RuntimeObject;
|
||||
import org.teavm.vm.BuildTarget;
|
||||
import org.teavm.vm.TeaVM;
|
||||
import org.teavm.vm.TeaVMBuilder;
|
||||
|
@ -67,6 +72,11 @@ import org.teavm.wasm.generate.WasmGenerator;
|
|||
import org.teavm.wasm.generate.WasmMangling;
|
||||
import org.teavm.wasm.generate.WasmStringPool;
|
||||
import org.teavm.wasm.intrinsics.AllocatorIntrinsic;
|
||||
import org.teavm.wasm.intrinsics.ClassIntrinsic;
|
||||
import org.teavm.wasm.intrinsics.PlatformClassIntrinsic;
|
||||
import org.teavm.wasm.intrinsics.PlatformClassMetadataIntrinsic;
|
||||
import org.teavm.wasm.intrinsics.PlatformIntrinsic;
|
||||
import org.teavm.wasm.intrinsics.PlatformObjectIntrinsic;
|
||||
import org.teavm.wasm.intrinsics.WasmAddressIntrinsic;
|
||||
import org.teavm.wasm.intrinsics.WasmRuntimeIntrinsic;
|
||||
import org.teavm.wasm.intrinsics.WasmStructureIntrinsic;
|
||||
|
@ -86,6 +96,7 @@ import org.teavm.wasm.model.expression.WasmIntType;
|
|||
import org.teavm.wasm.model.expression.WasmLoadInt32;
|
||||
import org.teavm.wasm.model.expression.WasmReturn;
|
||||
import org.teavm.wasm.model.expression.WasmStoreInt32;
|
||||
import org.teavm.wasm.patches.ClassPatch;
|
||||
import org.teavm.wasm.patches.ObjectPatch;
|
||||
import org.teavm.wasm.render.WasmRenderer;
|
||||
|
||||
|
@ -111,6 +122,7 @@ public class WasmTarget implements TeaVMTarget {
|
|||
public List<ClassHolderTransformer> getTransformers() {
|
||||
List<ClassHolderTransformer> transformers = new ArrayList<>();
|
||||
transformers.add(new ObjectPatch());
|
||||
transformers.add(new ClassPatch());
|
||||
return transformers;
|
||||
}
|
||||
|
||||
|
@ -138,6 +150,17 @@ public class WasmTarget implements TeaVMTarget {
|
|||
dependencyChecker.linkMethod(new MethodReference(Allocator.class, "<clinit>", void.class), null).use();
|
||||
|
||||
dependencyChecker.linkField(new FieldReference("java.lang.Object", "monitor"), null);
|
||||
|
||||
ClassDependency runtimeClassDep = dependencyChecker.linkClass(RuntimeClass.class.getName(), null);
|
||||
ClassDependency runtimeObjectDep = dependencyChecker.linkClass(RuntimeObject.class.getName(), null);
|
||||
ClassDependency runtimeJavaObjectDep = dependencyChecker.linkClass(RuntimeJavaObject.class.getName(), null);
|
||||
ClassDependency runtimeArrayDep = dependencyChecker.linkClass(RuntimeArray.class.getName(), null);
|
||||
for (ClassDependency classDep : Arrays.asList(runtimeClassDep, runtimeObjectDep, runtimeJavaObjectDep,
|
||||
runtimeArrayDep)) {
|
||||
for (FieldReader field : classDep.getClassReader().getFields()) {
|
||||
dependencyChecker.linkField(field.getReference(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -154,12 +177,18 @@ public class WasmTarget implements TeaVMTarget {
|
|||
Decompiler decompiler = new Decompiler(classes, controller.getClassLoader(), new HashSet<>(),
|
||||
new HashSet<>());
|
||||
WasmStringPool stringPool = new WasmStringPool(classGenerator, binaryWriter);
|
||||
WasmGenerationContext context = new WasmGenerationContext(classes, vtableProvider, tagRegistry, stringPool);
|
||||
WasmGenerationContext context = new WasmGenerationContext(classes, controller.getDiagnostics(),
|
||||
vtableProvider, tagRegistry, stringPool);
|
||||
|
||||
context.addIntrinsic(new WasmAddressIntrinsic());
|
||||
context.addIntrinsic(new WasmStructureIntrinsic(classGenerator));
|
||||
context.addIntrinsic(new WasmRuntimeIntrinsic());
|
||||
context.addIntrinsic(new AllocatorIntrinsic());
|
||||
context.addIntrinsic(new PlatformIntrinsic());
|
||||
context.addIntrinsic(new PlatformClassIntrinsic());
|
||||
context.addIntrinsic(new PlatformClassMetadataIntrinsic());
|
||||
context.addIntrinsic(new PlatformObjectIntrinsic(classGenerator));
|
||||
context.addIntrinsic(new ClassIntrinsic());
|
||||
|
||||
WasmGenerator generator = new WasmGenerator(decompiler, classes, context, classGenerator);
|
||||
|
||||
|
@ -180,7 +209,7 @@ public class WasmTarget implements TeaVMTarget {
|
|||
if (context.getImportedMethod(method.getReference()) == null) {
|
||||
CallLocation location = new CallLocation(method.getReference());
|
||||
controller.getDiagnostics().error(location, "Method {{m0}} is native but "
|
||||
+ "has no {{c1}} annotation on it", method.getReference(), Import.class);
|
||||
+ "has no {{c1}} annotation on it", method.getReference(), Import.class.getName());
|
||||
}
|
||||
module.add(generator.generateNative(method.getReference()));
|
||||
continue;
|
||||
|
@ -195,6 +224,8 @@ public class WasmTarget implements TeaVMTarget {
|
|||
}
|
||||
}
|
||||
|
||||
classGenerator.postProcess();
|
||||
|
||||
WasmMemorySegment dataSegment = new WasmMemorySegment();
|
||||
dataSegment.setData(binaryWriter.getData());
|
||||
dataSegment.setOffset(256);
|
||||
|
|
|
@ -52,8 +52,12 @@ public class WasmClassGenerator {
|
|||
private List<String> functionTable = new ArrayList<>();
|
||||
private VirtualTableProvider vtableProvider;
|
||||
private TagRegistry tagRegistry;
|
||||
private DataStructure objectStructure = new DataStructure((byte) 0,
|
||||
DataPrimitives.INT, /* class */
|
||||
DataPrimitives.ADDRESS /* monitor/hash code */);
|
||||
private DataStructure classStructure = new DataStructure(
|
||||
(byte) 8,
|
||||
objectStructure,
|
||||
DataPrimitives.INT, /* size */
|
||||
DataPrimitives.INT, /* flags */
|
||||
DataPrimitives.INT, /* tag */
|
||||
|
@ -119,18 +123,18 @@ public class WasmClassGenerator {
|
|||
|
||||
binaryData.size = 4;
|
||||
binaryData.data = classStructure.createValue();
|
||||
binaryData.data.setInt(0, 4);
|
||||
binaryData.data.setAddress(4, itemBinaryData.start);
|
||||
binaryData.data.setInt(1, 4);
|
||||
binaryData.data.setAddress(5, itemBinaryData.start);
|
||||
binaryData.start = binaryWriter.append(binaryData.data);
|
||||
|
||||
itemBinaryData.data.setAddress(5, binaryData.start);
|
||||
itemBinaryData.data.setAddress(6, binaryData.start);
|
||||
}
|
||||
}
|
||||
|
||||
private DataValue createPrimitiveClassData(int size) {
|
||||
DataValue value = classStructure.createValue();
|
||||
value.setInt(0, size);
|
||||
value.setInt(1, RuntimeClass.PRIMITIVE);
|
||||
value.setInt(1, size);
|
||||
value.setInt(2, RuntimeClass.PRIMITIVE);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -150,11 +154,11 @@ public class WasmClassGenerator {
|
|||
DataValue header = wrapper.getValue(0);
|
||||
binaryData.data = header;
|
||||
|
||||
header.setInt(0, binaryData.size);
|
||||
header.setInt(1, binaryData.size);
|
||||
List<TagRegistry.Range> ranges = tagRegistry.getRanges(name);
|
||||
int tag = ranges.stream().mapToInt(range -> range.lower).min().orElse(0);
|
||||
header.setInt(2, tag);
|
||||
header.setInt(3, RuntimeClass.computeCanary(binaryData.size, tag));
|
||||
header.setInt(3, tag);
|
||||
header.setInt(4, RuntimeClass.computeCanary(binaryData.size, tag));
|
||||
if (vtable == null) {
|
||||
return header;
|
||||
}
|
||||
|
@ -282,6 +286,18 @@ public class WasmClassGenerator {
|
|||
return 4;
|
||||
}
|
||||
|
||||
public void postProcess() {
|
||||
ClassBinaryData classClassData = binaryDataMap.get(ValueType.object("java.lang.Class"));
|
||||
if (classClassData != null) {
|
||||
int tag = classClassData.start >> 3;
|
||||
for (ClassBinaryData classData : binaryDataMap.values()) {
|
||||
if (classData.data != null) {
|
||||
classData.data.getValue(0).setInt(0, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasClinit(String className) {
|
||||
if (isStructure(className)) {
|
||||
return false;
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.util.ArrayList;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.interop.Import;
|
||||
import org.teavm.model.AnnotationReader;
|
||||
import org.teavm.model.AnnotationValue;
|
||||
|
@ -31,12 +32,11 @@ 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.binary.BinaryWriter;
|
||||
import org.teavm.wasm.intrinsics.WasmIntrinsic;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
|
||||
public class WasmGenerationContext {
|
||||
private ClassReaderSource classSource;
|
||||
private Diagnostics diagnostics;
|
||||
private VirtualTableProvider vtableProvider;
|
||||
private TagRegistry tagRegistry;
|
||||
private WasmStringPool stringPool;
|
||||
|
@ -44,9 +44,10 @@ public class WasmGenerationContext {
|
|||
private List<WasmIntrinsic> intrinsics = new ArrayList<>();
|
||||
private Map<MethodReference, WasmIntrinsic> intrinsicCache = new HashMap<>();
|
||||
|
||||
public WasmGenerationContext(ClassReaderSource classSource, VirtualTableProvider vtableProvider,
|
||||
TagRegistry tagRegistry, WasmStringPool stringPool) {
|
||||
public WasmGenerationContext(ClassReaderSource classSource, Diagnostics diagnostics,
|
||||
VirtualTableProvider vtableProvider, TagRegistry tagRegistry, WasmStringPool stringPool) {
|
||||
this.classSource = classSource;
|
||||
this.diagnostics = diagnostics;
|
||||
this.vtableProvider = vtableProvider;
|
||||
this.tagRegistry = tagRegistry;
|
||||
this.stringPool = stringPool;
|
||||
|
@ -109,6 +110,10 @@ public class WasmGenerationContext {
|
|||
return stringPool;
|
||||
}
|
||||
|
||||
public Diagnostics getDiagnostics() {
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
public class ImportedMethod {
|
||||
public final String name;
|
||||
public final String module;
|
||||
|
|
|
@ -62,7 +62,9 @@ import org.teavm.ast.UnwrapArrayExpr;
|
|||
import org.teavm.ast.VariableExpr;
|
||||
import org.teavm.ast.WhileStatement;
|
||||
import org.teavm.interop.Address;
|
||||
import org.teavm.model.CallLocation;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.InstructionLocation;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.classes.TagRegistry;
|
||||
|
@ -115,6 +117,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
private WasmGenerationContext context;
|
||||
private WasmClassGenerator classGenerator;
|
||||
private WasmFunction function;
|
||||
private MethodReference method;
|
||||
private int firstVariable;
|
||||
private IdentifiedStatement currentContinueTarget;
|
||||
private IdentifiedStatement currentBreakTarget;
|
||||
|
@ -125,10 +128,11 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
WasmExpression result;
|
||||
|
||||
WasmGenerationVisitor(WasmGenerationContext context, WasmClassGenerator classGenerator,
|
||||
WasmFunction function, int firstVariable) {
|
||||
WasmFunction function, MethodReference method, int firstVariable) {
|
||||
this.context = context;
|
||||
this.classGenerator = classGenerator;
|
||||
this.function = function;
|
||||
this.method = method;
|
||||
this.firstVariable = firstVariable;
|
||||
}
|
||||
|
||||
|
@ -759,9 +763,22 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
|
|||
block.getBody().add(new WasmSetLocal(instanceVar, instance));
|
||||
instance = new WasmGetLocal(instanceVar);
|
||||
|
||||
int vtableOffset = classGenerator.getClassSize(RuntimeClass.class.getName());
|
||||
VirtualTableEntry vtableEntry = context.getVirtualTableProvider().lookup(expr.getMethod());
|
||||
if (vtableEntry == null) {
|
||||
result = new WasmInt32Constant(0);
|
||||
InstructionLocation insnLocation = null;
|
||||
if (expr.getLocation() != null) {
|
||||
insnLocation = new InstructionLocation(expr.getLocation().getFileName(),
|
||||
expr.getLocation().getLine());
|
||||
}
|
||||
CallLocation location = new CallLocation(method, insnLocation);
|
||||
context.getDiagnostics().error(location, "Can't generate WebAssembly to call {{m0}} method",
|
||||
expr.getMethod());
|
||||
return;
|
||||
}
|
||||
WasmExpression methodIndex = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD,
|
||||
getReferenceToClass(instance), new WasmInt32Constant(vtableEntry.getIndex() * 4 + 24));
|
||||
getReferenceToClass(instance), new WasmInt32Constant(vtableEntry.getIndex() * 4 + vtableOffset));
|
||||
methodIndex = new WasmLoadInt32(4, methodIndex, WasmInt32Subtype.INT32);
|
||||
|
||||
WasmIndirectCall call = new WasmIndirectCall(methodIndex);
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.teavm.model.ValueType;
|
|||
import org.teavm.runtime.RuntimeClass;
|
||||
import org.teavm.wasm.model.WasmFunction;
|
||||
import org.teavm.wasm.model.WasmLocal;
|
||||
import org.teavm.wasm.model.WasmType;
|
||||
import org.teavm.wasm.model.expression.WasmCall;
|
||||
import org.teavm.wasm.model.expression.WasmConditional;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
|
@ -61,7 +62,10 @@ public class WasmGenerator {
|
|||
int firstVariable = method.hasModifier(ElementModifier.STATIC) ? 1 : 0;
|
||||
for (int i = firstVariable; i < methodAst.getVariables().size(); ++i) {
|
||||
VariableNode variable = methodAst.getVariables().get(i);
|
||||
function.add(new WasmLocal(WasmGeneratorUtil.mapType(variable.getType())));
|
||||
WasmType type = variable.getType() != null
|
||||
? WasmGeneratorUtil.mapType(variable.getType())
|
||||
: WasmType.INT32;
|
||||
function.add(new WasmLocal(type));
|
||||
}
|
||||
|
||||
for (int i = firstVariable; i <= methodReference.parameterCount(); ++i) {
|
||||
|
@ -85,7 +89,8 @@ public class WasmGenerator {
|
|||
function.getBody().add(conditional);
|
||||
}
|
||||
|
||||
WasmGenerationVisitor visitor = new WasmGenerationVisitor(context, classGenerator, function, firstVariable);
|
||||
WasmGenerationVisitor visitor = new WasmGenerationVisitor(context, classGenerator, function, methodReference,
|
||||
firstVariable);
|
||||
methodAst.getBody().acceptVisitor(visitor);
|
||||
function.getBody().add(visitor.result);
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.wasm.intrinsics;
|
||||
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
|
||||
public class ClassIntrinsic implements WasmIntrinsic {
|
||||
@Override
|
||||
public boolean isApplicable(MethodReference methodReference) {
|
||||
return methodReference.getClassName().equals("java.lang.Class")
|
||||
&& isApplicableToMethod(methodReference.getDescriptor());
|
||||
}
|
||||
|
||||
private boolean isApplicableToMethod(MethodDescriptor method) {
|
||||
return method.getName().equals("getClass") && method.parameterCount() == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "getClass":
|
||||
return manager.generate(invocation.getArguments().get(0));
|
||||
default:
|
||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.wasm.intrinsics;
|
||||
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.wasm.model.expression.WasmBlock;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
|
||||
public class PlatformClassIntrinsic implements WasmIntrinsic {
|
||||
private static final String PLATFORM_CLASS_NAME = "org.teavm.platform.PlatformClass";
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(MethodReference methodReference) {
|
||||
return methodReference.getClassName().equals(PLATFORM_CLASS_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "getMetadata":
|
||||
case "getJavaClass":
|
||||
return manager.generate(invocation.getArguments().get(0));
|
||||
case "setJavaClass":
|
||||
return new WasmBlock(false);
|
||||
default:
|
||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.wasm.intrinsics;
|
||||
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.ast.QualificationExpr;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.runtime.RuntimeClass;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
|
||||
public class PlatformClassMetadataIntrinsic implements WasmIntrinsic {
|
||||
private static final String PLATFORM_CLASS_METADATA_NAME = "org.teavm.platform.PlatformClassMetadata";
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(MethodReference methodReference) {
|
||||
return methodReference.getClassName().equals(PLATFORM_CLASS_METADATA_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "getArrayItem": {
|
||||
QualificationExpr expr = new QualificationExpr();
|
||||
expr.setQualified(invocation.getArguments().get(0));
|
||||
expr.setField(new FieldReference(RuntimeClass.class.getName(), "itemType"));
|
||||
expr.setLocation(invocation.getLocation());
|
||||
return manager.generate(expr);
|
||||
}
|
||||
default:
|
||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.wasm.intrinsics;
|
||||
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
|
||||
public class PlatformIntrinsic implements WasmIntrinsic {
|
||||
private static final String PLATFORM = "org.teavm.platform.Platform";
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(MethodReference methodReference) {
|
||||
return methodReference.getClassName().equals(PLATFORM);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "getPlatformObject":
|
||||
case "asJavaClass":
|
||||
return manager.generate(invocation.getArguments().get(0));
|
||||
default:
|
||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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.wasm.intrinsics;
|
||||
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.runtime.RuntimeObject;
|
||||
import org.teavm.wasm.generate.WasmClassGenerator;
|
||||
import org.teavm.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.wasm.model.expression.WasmInt32Constant;
|
||||
import org.teavm.wasm.model.expression.WasmInt32Subtype;
|
||||
import org.teavm.wasm.model.expression.WasmIntBinary;
|
||||
import org.teavm.wasm.model.expression.WasmIntBinaryOperation;
|
||||
import org.teavm.wasm.model.expression.WasmIntType;
|
||||
import org.teavm.wasm.model.expression.WasmLoadInt32;
|
||||
|
||||
public class PlatformObjectIntrinsic implements WasmIntrinsic {
|
||||
private static final String PLATFORM_OBJECT = "org.teavm.platform.PlatformObject";
|
||||
private static final FieldReference classField = new FieldReference(RuntimeObject.class.getName(),
|
||||
"classReference");
|
||||
private WasmClassGenerator classGenerator;
|
||||
|
||||
public PlatformObjectIntrinsic(WasmClassGenerator classGenerator) {
|
||||
this.classGenerator = classGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(MethodReference methodReference) {
|
||||
return methodReference.getClassName().equals(PLATFORM_OBJECT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
|
||||
switch (invocation.getMethod().getName()) {
|
||||
case "getPlatformClass": {
|
||||
int offset = classGenerator.getFieldOffset(classField);
|
||||
WasmExpression object = manager.generate(invocation.getArguments().get(0));
|
||||
if (offset > 0) {
|
||||
object = new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.ADD, object,
|
||||
new WasmInt32Constant(offset));
|
||||
}
|
||||
WasmExpression classPtr = new WasmLoadInt32(4, object, WasmInt32Subtype.INT32);
|
||||
return new WasmIntBinary(WasmIntType.INT32, WasmIntBinaryOperation.SHL,
|
||||
classPtr, new WasmInt32Constant(3));
|
||||
}
|
||||
default:
|
||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||
}
|
||||
}
|
||||
}
|
71
core/src/main/java/org/teavm/wasm/patches/ClassPatch.java
Normal file
71
core/src/main/java/org/teavm/wasm/patches/ClassPatch.java
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.wasm.patches;
|
||||
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ClassHolderTransformer;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.MethodHolder;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.EmptyInstruction;
|
||||
import org.teavm.model.instructions.GetFieldInstruction;
|
||||
import org.teavm.model.instructions.PutFieldInstruction;
|
||||
|
||||
public class ClassPatch implements ClassHolderTransformer {
|
||||
private FieldReference platformClassField = new FieldReference("java.lang.Class", "platformClass");
|
||||
|
||||
@Override
|
||||
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
|
||||
if (!cls.getName().equals("java.lang.Class")) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (MethodHolder method : cls.getMethods()) {
|
||||
patchProgram(method.getProgram());
|
||||
}
|
||||
}
|
||||
|
||||
private void patchProgram(Program program) {
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
BasicBlock block = program.basicBlockAt(i);
|
||||
for (int j = 0; j < block.getInstructions().size(); ++j) {
|
||||
Instruction instruction = block.getInstructions().get(j);
|
||||
if (instruction instanceof GetFieldInstruction) {
|
||||
GetFieldInstruction getField = (GetFieldInstruction) instruction;
|
||||
if (getField.getField().equals(platformClassField)) {
|
||||
AssignInstruction replacement = new AssignInstruction();
|
||||
replacement.setReceiver(getField.getReceiver());
|
||||
replacement.setAssignee(getField.getInstance());
|
||||
replacement.setLocation(instruction.getLocation());
|
||||
block.getInstructions().set(j, replacement);
|
||||
}
|
||||
} else if (instruction instanceof PutFieldInstruction) {
|
||||
PutFieldInstruction putField = (PutFieldInstruction) instruction;
|
||||
if (putField.getField().equals(platformClassField)) {
|
||||
EmptyInstruction replacement = new EmptyInstruction();
|
||||
replacement.setLocation(instruction.getLocation());
|
||||
block.getInstructions().set(j, replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,10 +18,6 @@ package org.teavm.platform;
|
|||
import org.teavm.jso.JSObject;
|
||||
import org.teavm.jso.JSProperty;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface PlatformClass extends JSObject {
|
||||
@JSProperty("$meta")
|
||||
PlatformClassMetadata getMetadata();
|
||||
|
|
|
@ -18,14 +18,7 @@ package org.teavm.platform;
|
|||
import org.teavm.jso.JSMethod;
|
||||
import org.teavm.jso.JSObject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface PlatformPrimitives extends JSObject {
|
||||
@JSMethod("$rt_voidcls")
|
||||
PlatformClass getVoidClass();
|
||||
|
||||
@JSMethod("$rt_booleancls")
|
||||
PlatformClass getBooleanClass();
|
||||
|
||||
|
@ -38,9 +31,6 @@ public interface PlatformPrimitives extends JSObject {
|
|||
@JSMethod("$rt_charcls")
|
||||
PlatformClass getCharClass();
|
||||
|
||||
@JSMethod("$rt_intcls")
|
||||
PlatformClass getIntClass();
|
||||
|
||||
@JSMethod("$rt_longcls")
|
||||
PlatformClass getLongClass();
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user