System.arrayCopy works

This commit is contained in:
Alexey Andreev 2016-08-31 23:00:59 +03:00
parent ca3258417b
commit 1ae683ead3
20 changed files with 246 additions and 74 deletions

View File

@ -21,10 +21,14 @@ import java.util.Map;
import org.teavm.classlib.impl.DeclaringClassMetadataGenerator; import org.teavm.classlib.impl.DeclaringClassMetadataGenerator;
import org.teavm.classlib.java.lang.annotation.TAnnotation; import org.teavm.classlib.java.lang.annotation.TAnnotation;
import org.teavm.classlib.java.lang.reflect.TAnnotatedElement; import org.teavm.classlib.java.lang.reflect.TAnnotatedElement;
import org.teavm.interop.Address;
import org.teavm.interop.DelegateTo;
import org.teavm.platform.Platform; import org.teavm.platform.Platform;
import org.teavm.platform.PlatformClass; import org.teavm.platform.PlatformClass;
import org.teavm.platform.metadata.ClassResource; import org.teavm.platform.metadata.ClassResource;
import org.teavm.platform.metadata.ClassScopedMetadataProvider; import org.teavm.platform.metadata.ClassScopedMetadataProvider;
import org.teavm.runtime.RuntimeClass;
import org.teavm.runtime.RuntimeObject;
public class TClass<T> extends TObject implements TAnnotatedElement { public class TClass<T> extends TObject implements TAnnotatedElement {
TString name; TString name;
@ -93,11 +97,11 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
} }
public boolean isPrimitive() { public boolean isPrimitive() {
return platformClass.getMetadata().isPrimitive(); return Platform.isPrimitive(platformClass);
} }
public boolean isArray() { public boolean isArray() {
return platformClass.getMetadata().getArrayItem() != null; return Platform.getArrayItem(platformClass) != null;
} }
public boolean isEnum() { public boolean isEnum() {
@ -105,7 +109,7 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
} }
public TClass<?> getComponentType() { public TClass<?> getComponentType() {
return getClass(platformClass.getMetadata().getArrayItem()); return getClass(Platform.getArrayItem(platformClass));
} }
public boolean desiredAssertionStatus() { public boolean desiredAssertionStatus() {

View File

@ -80,7 +80,7 @@ public final class TSystem extends TObject {
private static native void doArrayCopy(Object src, int srcPos, Object dest, int destPos, int length); private static native void doArrayCopy(Object src, int srcPos, Object dest, int destPos, int length);
static void doArrayCopyLowLevel(RuntimeArray src, int srcPos, RuntimeArray dest, int destPos, int length) { static void doArrayCopyLowLevel(RuntimeArray src, int srcPos, RuntimeArray dest, int destPos, int length) {
RuntimeClass type = Address.fromInt(src.classReference << 3).toStructure(); RuntimeClass type = RuntimeClass.getClass(src);
int itemSize = type.itemType.size; int itemSize = type.itemType.size;
if ((type.itemType.flags & RuntimeClass.PRIMITIVE) == 0) { if ((type.itemType.flags & RuntimeClass.PRIMITIVE) == 0) {
itemSize = Address.sizeOf(); itemSize = Address.sizeOf();

View File

@ -21,14 +21,26 @@ import org.teavm.interop.DelegateTo;
import org.teavm.backend.javascript.spi.GeneratedBy; import org.teavm.backend.javascript.spi.GeneratedBy;
import org.teavm.platform.PlatformClass; import org.teavm.platform.PlatformClass;
import org.teavm.runtime.Allocator; import org.teavm.runtime.Allocator;
import org.teavm.runtime.RuntimeArray;
import org.teavm.runtime.RuntimeClass; import org.teavm.runtime.RuntimeClass;
import org.teavm.runtime.RuntimeObject; import org.teavm.runtime.RuntimeObject;
public final class TArray extends TObject { public final class TArray extends TObject {
@GeneratedBy(ArrayNativeGenerator.class) @GeneratedBy(ArrayNativeGenerator.class)
@PluggableDependency(ArrayNativeGenerator.class) @PluggableDependency(ArrayNativeGenerator.class)
@DelegateTo("getLengthLowLevel")
public static native int getLength(TObject array) throws TIllegalArgumentException; public static native int getLength(TObject array) throws TIllegalArgumentException;
@SuppressWarnings("unused")
private static int getLengthLowLevel(RuntimeObject obj) {
RuntimeClass cls = RuntimeClass.getClass(obj);
if (cls.itemType == null) {
throw new TIllegalArgumentException();
}
RuntimeArray array = (RuntimeArray) obj;
return array.size;
}
public static TObject newInstance(TClass<?> componentType, int length) throws TNegativeArraySizeException { public static TObject newInstance(TClass<?> componentType, int length) throws TNegativeArraySizeException {
if (componentType == null) { if (componentType == null) {
throw new TNullPointerException(); throw new TNullPointerException();

View File

@ -32,7 +32,7 @@ public final class Example {
testLazyInitialization(); testLazyInitialization();
testHashCode(); testHashCode();
testArrayList(); testArrayList();
//testArrayCopy(); testArrayCopy();
} }
private static void testFibonacci() { private static void testFibonacci() {

View File

@ -36,12 +36,12 @@ import org.teavm.backend.wasm.generate.WasmStringPool;
import org.teavm.backend.wasm.intrinsics.AddressIntrinsic; import org.teavm.backend.wasm.intrinsics.AddressIntrinsic;
import org.teavm.backend.wasm.intrinsics.AllocatorIntrinsic; import org.teavm.backend.wasm.intrinsics.AllocatorIntrinsic;
import org.teavm.backend.wasm.intrinsics.ClassIntrinsic; import org.teavm.backend.wasm.intrinsics.ClassIntrinsic;
import org.teavm.backend.wasm.intrinsics.FunctionIntrinsic;
import org.teavm.backend.wasm.intrinsics.PlatformClassIntrinsic; import org.teavm.backend.wasm.intrinsics.PlatformClassIntrinsic;
import org.teavm.backend.wasm.intrinsics.PlatformClassMetadataIntrinsic;
import org.teavm.backend.wasm.intrinsics.PlatformIntrinsic; import org.teavm.backend.wasm.intrinsics.PlatformIntrinsic;
import org.teavm.backend.wasm.intrinsics.PlatformObjectIntrinsic; import org.teavm.backend.wasm.intrinsics.PlatformObjectIntrinsic;
import org.teavm.backend.wasm.intrinsics.StructureIntrinsic;
import org.teavm.backend.wasm.intrinsics.WasmRuntimeIntrinsic; import org.teavm.backend.wasm.intrinsics.WasmRuntimeIntrinsic;
import org.teavm.backend.wasm.intrinsics.WasmStructureIntrinsic;
import org.teavm.backend.wasm.model.WasmFunction; import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmMemorySegment; import org.teavm.backend.wasm.model.WasmMemorySegment;
import org.teavm.backend.wasm.model.WasmModule; import org.teavm.backend.wasm.model.WasmModule;
@ -88,6 +88,7 @@ import org.teavm.model.Program;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
import org.teavm.model.classes.TagRegistry; import org.teavm.model.classes.TagRegistry;
import org.teavm.model.classes.VirtualTableProvider; import org.teavm.model.classes.VirtualTableProvider;
import org.teavm.model.instructions.CloneArrayInstruction;
import org.teavm.model.instructions.InvocationType; import org.teavm.model.instructions.InvocationType;
import org.teavm.model.instructions.InvokeInstruction; import org.teavm.model.instructions.InvokeInstruction;
import org.teavm.runtime.Allocator; import org.teavm.runtime.Allocator;
@ -125,6 +126,7 @@ public class WasmTarget implements TeaVMTarget {
List<ClassHolderTransformer> transformers = new ArrayList<>(); List<ClassHolderTransformer> transformers = new ArrayList<>();
transformers.add(new ObjectPatch()); transformers.add(new ObjectPatch());
transformers.add(new ClassPatch()); transformers.add(new ClassPatch());
transformers.add(new WasmDependencyListener());
return transformers; return transformers;
} }
@ -158,6 +160,8 @@ public class WasmTarget implements TeaVMTarget {
Address.class, void.class), null).use(); Address.class, void.class), null).use();
dependencyChecker.linkMethod(new MethodReference(WasmRuntime.class, "fillZero", Address.class, int.class, dependencyChecker.linkMethod(new MethodReference(WasmRuntime.class, "fillZero", Address.class, int.class,
void.class), null).use(); void.class), null).use();
dependencyChecker.linkMethod(new MethodReference(WasmRuntime.class, "moveMemoryBlock", Address.class,
Address.class, int.class, void.class), null).use();
dependencyChecker.linkMethod(new MethodReference(Allocator.class, "allocate", dependencyChecker.linkMethod(new MethodReference(Allocator.class, "allocate",
RuntimeClass.class, Address.class), null).use(); RuntimeClass.class, Address.class), null).use();
@ -188,7 +192,8 @@ public class WasmTarget implements TeaVMTarget {
VirtualTableProvider vtableProvider = createVirtualTableProvider(classes); VirtualTableProvider vtableProvider = createVirtualTableProvider(classes);
TagRegistry tagRegistry = new TagRegistry(classes); TagRegistry tagRegistry = new TagRegistry(classes);
BinaryWriter binaryWriter = new BinaryWriter(256); BinaryWriter binaryWriter = new BinaryWriter(256);
WasmClassGenerator classGenerator = new WasmClassGenerator(classes, vtableProvider, tagRegistry, binaryWriter); WasmClassGenerator classGenerator = new WasmClassGenerator(
classes, vtableProvider, tagRegistry, binaryWriter);
Decompiler decompiler = new Decompiler(classes, controller.getClassLoader(), new HashSet<>(), Decompiler decompiler = new Decompiler(classes, controller.getClassLoader(), new HashSet<>(),
new HashSet<>()); new HashSet<>());
@ -197,12 +202,12 @@ public class WasmTarget implements TeaVMTarget {
vtableProvider, tagRegistry, stringPool); vtableProvider, tagRegistry, stringPool);
context.addIntrinsic(new AddressIntrinsic(classGenerator)); context.addIntrinsic(new AddressIntrinsic(classGenerator));
context.addIntrinsic(new WasmStructureIntrinsic(classGenerator)); context.addIntrinsic(new StructureIntrinsic(classGenerator));
context.addIntrinsic(new FunctionIntrinsic(classGenerator));
context.addIntrinsic(new WasmRuntimeIntrinsic()); context.addIntrinsic(new WasmRuntimeIntrinsic());
context.addIntrinsic(new AllocatorIntrinsic()); context.addIntrinsic(new AllocatorIntrinsic());
context.addIntrinsic(new PlatformIntrinsic()); context.addIntrinsic(new PlatformIntrinsic());
context.addIntrinsic(new PlatformClassIntrinsic()); context.addIntrinsic(new PlatformClassIntrinsic());
context.addIntrinsic(new PlatformClassMetadataIntrinsic());
context.addIntrinsic(new PlatformObjectIntrinsic(classGenerator)); context.addIntrinsic(new PlatformObjectIntrinsic(classGenerator));
context.addIntrinsic(new ClassIntrinsic()); context.addIntrinsic(new ClassIntrinsic());
@ -393,6 +398,8 @@ public class WasmTarget implements TeaVMTarget {
if (invoke.getType() == InvocationType.VIRTUAL) { if (invoke.getType() == InvocationType.VIRTUAL) {
virtualMethods.add(invoke.getMethod()); virtualMethods.add(invoke.getMethod());
} }
} else if (insn instanceof CloneArrayInstruction) {
virtualMethods.add(new MethodReference(Object.class, "clone", Object.class));
} }
} }
} }

View File

@ -29,6 +29,7 @@ import org.teavm.backend.wasm.binary.DataStructure;
import org.teavm.backend.wasm.binary.DataType; import org.teavm.backend.wasm.binary.DataType;
import org.teavm.backend.wasm.binary.DataValue; import org.teavm.backend.wasm.binary.DataValue;
import org.teavm.interop.Address; import org.teavm.interop.Address;
import org.teavm.interop.Function;
import org.teavm.interop.Structure; import org.teavm.interop.Structure;
import org.teavm.model.ClassReader; import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource; import org.teavm.model.ClassReaderSource;
@ -63,7 +64,8 @@ public class WasmClassGenerator {
DataPrimitives.INT, /* tag */ DataPrimitives.INT, /* tag */
DataPrimitives.INT, /* canary */ DataPrimitives.INT, /* canary */
DataPrimitives.ADDRESS, /* item type */ DataPrimitives.ADDRESS, /* item type */
DataPrimitives.ADDRESS /* array type */); DataPrimitives.ADDRESS, /* array type */
DataPrimitives.INT /* isInstance function */);
public WasmClassGenerator(ClassReaderSource classSource, VirtualTableProvider vtableProvider, public WasmClassGenerator(ClassReaderSource classSource, VirtualTableProvider vtableProvider,
TagRegistry tagRegistry, BinaryWriter binaryWriter) { TagRegistry tagRegistry, BinaryWriter binaryWriter) {
@ -216,10 +218,22 @@ public class WasmClassGenerator {
return data.start < 0; return data.start < 0;
} }
public boolean isFunctionClass(String className) {
ValueType type = ValueType.object(className);
addClass(type);
return binaryDataMap.get(type).function;
}
private void calculateLayout(ClassReader cls, ClassBinaryData data) { private void calculateLayout(ClassReader cls, ClassBinaryData data) {
if (cls.getName().equals(Structure.class.getName()) || cls.getName().equals(Address.class.getName())) { if (cls.getName().equals(Structure.class.getName()) || cls.getName().equals(Address.class.getName())) {
data.size = 0; data.size = 0;
data.start = -1; data.start = -1;
return;
} else if (cls.getName().equals(Function.class.getName())) {
data.size = 0;
data.start = -1;
data.function = true;
return;
} else if (cls.getParent() != null && !cls.getParent().equals(cls.getName())) { } else if (cls.getParent() != null && !cls.getParent().equals(cls.getName())) {
addClass(ValueType.object(cls.getParent())); addClass(ValueType.object(cls.getParent()));
ClassBinaryData parentData = binaryDataMap.get(ValueType.object(cls.getParent())); ClassBinaryData parentData = binaryDataMap.get(ValueType.object(cls.getParent()));
@ -228,6 +242,10 @@ public class WasmClassGenerator {
if (parentData.start == -1) { if (parentData.start == -1) {
data.start = -1; data.start = -1;
} }
if (parentData.function) {
data.function = true;
return;
}
} else { } else {
data.size = 4; data.size = 4;
data.alignment = 4; data.alignment = 4;
@ -328,5 +346,6 @@ public class WasmClassGenerator {
int start; int start;
ObjectIntMap<String> fieldLayout = new ObjectIntOpenHashMap<>(); ObjectIntMap<String> fieldLayout = new ObjectIntOpenHashMap<>();
DataValue data; DataValue data;
boolean function;
} }
} }

View File

@ -18,13 +18,19 @@ package org.teavm.backend.wasm.generate;
import org.teavm.dependency.AbstractDependencyListener; import org.teavm.dependency.AbstractDependencyListener;
import org.teavm.dependency.DependencyAgent; import org.teavm.dependency.DependencyAgent;
import org.teavm.dependency.MethodDependency; import org.teavm.dependency.MethodDependency;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.interop.DelegateTo; import org.teavm.interop.DelegateTo;
import org.teavm.model.AnnotationReader; import org.teavm.model.AnnotationReader;
import org.teavm.model.CallLocation; import org.teavm.model.CallLocation;
import org.teavm.model.ClassHolder;
import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.ClassReader; import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource;
import org.teavm.model.ElementModifier;
import org.teavm.model.MethodHolder;
import org.teavm.model.MethodReader; import org.teavm.model.MethodReader;
public class WasmDependencyListener extends AbstractDependencyListener { public class WasmDependencyListener extends AbstractDependencyListener implements ClassHolderTransformer {
@Override @Override
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) { public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
AnnotationReader delegateAnnot = method.getMethod().getAnnotations().get(DelegateTo.class.getName()); AnnotationReader delegateAnnot = method.getMethod().getAnnotations().get(DelegateTo.class.getName());
@ -40,4 +46,15 @@ public class WasmDependencyListener extends AbstractDependencyListener {
} }
} }
} }
@Override
public void transformClass(ClassHolder cls, ClassReaderSource innerSource, Diagnostics diagnostics) {
for (MethodHolder method : cls.getMethods()) {
AnnotationReader delegateAnnot = method.getAnnotations().get(DelegateTo.class.getName());
if (delegateAnnot != null) {
method.setProgram(null);
method.getModifiers().add(ElementModifier.NATIVE);
}
}
}
} }

View File

@ -572,6 +572,9 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor {
} else if (expr.getValue() instanceof String) { } else if (expr.getValue() instanceof String) {
String str = (String) expr.getValue(); String str = (String) expr.getValue();
result = new WasmInt32Constant(context.getStringPool().getStringPointer(str)); result = new WasmInt32Constant(context.getStringPool().getStringPointer(str));
} else if (expr.getValue() instanceof ValueType) {
int pointer = classGenerator.getClassPointer((ValueType) expr.getValue());
result = new WasmInt32Constant(pointer);
} else { } else {
throw new IllegalArgumentException("Constant unsupported: " + expr.getValue()); throw new IllegalArgumentException("Constant unsupported: " + expr.getValue());
} }

View File

@ -109,13 +109,16 @@ public class WasmGenerator {
public WasmFunction generateNative(MethodReference methodReference) { public WasmFunction generateNative(MethodReference methodReference) {
WasmFunction function = new WasmFunction(WasmMangling.mangleMethod(methodReference)); WasmFunction function = new WasmFunction(WasmMangling.mangleMethod(methodReference));
for (int i = 0; i < methodReference.parameterCount(); ++i) { for (int i = 0; i < methodReference.parameterCount(); ++i) {
function.getParameters().add(WasmGeneratorUtil.mapType(methodReference.parameterType(i))); WasmType paramType = WasmGeneratorUtil.mapType(methodReference.parameterType(i));
function.getParameters().add(paramType);
} }
WasmGenerationContext.ImportedMethod importedMethod = context.getImportedMethod(methodReference); WasmGenerationContext.ImportedMethod importedMethod = context.getImportedMethod(methodReference);
if (importedMethod != null) { if (importedMethod != null) {
function.setImportName(importedMethod.name); function.setImportName(importedMethod.name);
function.setImportModule(importedMethod.module); function.setImportModule(importedMethod.module);
} else {
function.setImportName("<unknown>");
} }
return function; return function;

View File

@ -27,8 +27,16 @@ import org.teavm.runtime.Allocator;
public class AllocatorIntrinsic implements WasmIntrinsic { public class AllocatorIntrinsic implements WasmIntrinsic {
@Override @Override
public boolean isApplicable(MethodReference methodReference) { public boolean isApplicable(MethodReference methodReference) {
return methodReference.getClassName().equals(Allocator.class.getName()) if (!methodReference.getClassName().equals(Allocator.class.getName())) {
&& methodReference.getName().equals("fillZero"); return false;
}
switch (methodReference.getName()) {
case "fillZero":
case "moveMemoryBlock":
return true;
default:
return false;
}
} }
@Override @Override
@ -39,7 +47,8 @@ public class AllocatorIntrinsic implements WasmIntrinsic {
MethodReference delegateMetod = new MethodReference(WasmRuntime.class.getName(), MethodReference delegateMetod = new MethodReference(WasmRuntime.class.getName(),
invocation.getMethod().getDescriptor()); invocation.getMethod().getDescriptor());
WasmCall call = new WasmCall(WasmMangling.mangleMethod(delegateMetod)); WasmCall call = new WasmCall(WasmMangling.mangleMethod(delegateMetod));
call.getArguments().addAll(invocation.getArguments().stream().map(manager::generate) call.getArguments().addAll(invocation.getArguments().stream()
.map(manager::generate)
.collect(Collectors.toList())); .collect(Collectors.toList()));
return call; return call;
} }

View File

@ -0,0 +1,55 @@
/*
* 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.backend.wasm.intrinsics;
import org.teavm.ast.InvocationExpr;
import org.teavm.backend.wasm.generate.WasmClassGenerator;
import org.teavm.backend.wasm.generate.WasmGeneratorUtil;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.backend.wasm.model.expression.WasmIndirectCall;
import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;
public class FunctionIntrinsic implements WasmIntrinsic {
private WasmClassGenerator classGenerator;
public FunctionIntrinsic(WasmClassGenerator classGenerator) {
this.classGenerator = classGenerator;
}
@Override
public boolean isApplicable(MethodReference methodReference) {
return classGenerator.isFunctionClass(methodReference.getClassName());
}
@Override
public WasmExpression apply(InvocationExpr invocation, WasmIntrinsicManager manager) {
WasmExpression selector = manager.generate(invocation.getArguments().get(0));
WasmIndirectCall call = new WasmIndirectCall(selector);
for (ValueType type : invocation.getMethod().getParameterTypes()) {
call.getParameterTypes().add(WasmGeneratorUtil.mapType(type));
}
if (invocation.getMethod().getReturnType() != ValueType.VOID) {
call.setReturnType(WasmGeneratorUtil.mapType(invocation.getMethod().getReturnType()));
}
for (int i = 1; i < invocation.getArguments().size(); ++i) {
call.getArguments().add(manager.generate(invocation.getArguments().get(i)));
}
return call;
}
}

View File

@ -1,47 +0,0 @@
/*
* 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.backend.wasm.intrinsics;
import org.teavm.ast.InvocationExpr;
import org.teavm.ast.QualificationExpr;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.model.FieldReference;
import org.teavm.model.MethodReference;
import org.teavm.runtime.RuntimeClass;
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());
}
}
}

View File

@ -17,6 +17,7 @@ package org.teavm.backend.wasm.intrinsics;
import org.teavm.ast.InvocationExpr; import org.teavm.ast.InvocationExpr;
import org.teavm.backend.wasm.model.expression.WasmExpression; import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
public class PlatformIntrinsic implements WasmIntrinsic { public class PlatformIntrinsic implements WasmIntrinsic {
@ -24,7 +25,18 @@ public class PlatformIntrinsic implements WasmIntrinsic {
@Override @Override
public boolean isApplicable(MethodReference methodReference) { public boolean isApplicable(MethodReference methodReference) {
return methodReference.getClassName().equals(PLATFORM); return methodReference.getClassName().equals(PLATFORM)
&& isApplicableToMethod(methodReference.getDescriptor());
}
private boolean isApplicableToMethod(MethodDescriptor methodDescriptor) {
switch (methodDescriptor.getName()) {
case "getPlatformObject":
case "asJavaClass":
return true;
default:
return false;
}
} }
@Override @Override

View File

@ -20,21 +20,20 @@ import org.teavm.ast.InvocationExpr;
import org.teavm.backend.wasm.generate.WasmClassGenerator; import org.teavm.backend.wasm.generate.WasmClassGenerator;
import org.teavm.backend.wasm.model.expression.WasmExpression; import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.backend.wasm.model.expression.WasmInt32Constant; import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
import org.teavm.interop.Address; import org.teavm.interop.Structure;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.model.ValueType; import org.teavm.model.ValueType;
public class WasmStructureIntrinsic implements WasmIntrinsic { public class StructureIntrinsic implements WasmIntrinsic {
private WasmClassGenerator classGenerator; private WasmClassGenerator classGenerator;
public WasmStructureIntrinsic(WasmClassGenerator classGenerator) { public StructureIntrinsic(WasmClassGenerator classGenerator) {
this.classGenerator = classGenerator; this.classGenerator = classGenerator;
} }
@Override @Override
public boolean isApplicable(MethodReference methodReference) { public boolean isApplicable(MethodReference methodReference) {
return !methodReference.getClassName().equals(Address.class.getName()) return methodReference.getClassName().equals(Structure.class.getName());
&& classGenerator.getClassPointer(ValueType.object(methodReference.getClassName())) < 0;
} }
@Override @Override

View File

@ -0,0 +1,22 @@
/*
* 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;
import org.teavm.interop.Function;
public abstract class IsSupertypeFunction extends Function {
public abstract boolean apply(RuntimeClass superType);
}

View File

@ -16,5 +16,5 @@
package org.teavm.runtime; package org.teavm.runtime;
public class RuntimeArray extends RuntimeJavaObject { public class RuntimeArray extends RuntimeJavaObject {
int size; public int size;
} }

View File

@ -15,6 +15,8 @@
*/ */
package org.teavm.runtime; package org.teavm.runtime;
import org.teavm.interop.Address;
public class RuntimeClass extends RuntimeJavaObject { public class RuntimeClass extends RuntimeJavaObject {
public static final int INITIALIZED = 1; public static final int INITIALIZED = 1;
public static final int PRIMITIVE = 2; public static final int PRIMITIVE = 2;
@ -25,6 +27,7 @@ public class RuntimeClass extends RuntimeJavaObject {
public int canary; public int canary;
public RuntimeClass itemType; public RuntimeClass itemType;
public RuntimeClass arrayType; public RuntimeClass arrayType;
public IsSupertypeFunction isSupertypeOf;
public static int computeCanary(int size, int tag) { public static int computeCanary(int size, int tag) {
return size ^ (tag << 8) ^ (tag >>> 24) ^ 0xAAAAAAAA; return size ^ (tag << 8) ^ (tag >>> 24) ^ 0xAAAAAAAA;
@ -33,4 +36,8 @@ public class RuntimeClass extends RuntimeJavaObject {
public int computeCanary() { public int computeCanary() {
return computeCanary(size, tag); return computeCanary(size, tag);
} }
public static RuntimeClass getClass(RuntimeObject object) {
return Address.fromInt(object.classReference << 3).toStructure();
}
} }

View File

@ -0,0 +1,19 @@
/*
* 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.interop;
public abstract class Function {
}

View File

@ -19,12 +19,15 @@ import java.lang.annotation.Annotation;
import org.teavm.backend.javascript.spi.GeneratedBy; import org.teavm.backend.javascript.spi.GeneratedBy;
import org.teavm.backend.javascript.spi.InjectedBy; import org.teavm.backend.javascript.spi.InjectedBy;
import org.teavm.dependency.PluggableDependency; import org.teavm.dependency.PluggableDependency;
import org.teavm.interop.DelegateTo;
import org.teavm.jso.JSBody; import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
import org.teavm.jso.browser.Window; import org.teavm.jso.browser.Window;
import org.teavm.platform.metadata.ClassResource; import org.teavm.platform.metadata.ClassResource;
import org.teavm.platform.metadata.StaticFieldResource; import org.teavm.platform.metadata.StaticFieldResource;
import org.teavm.platform.plugin.PlatformGenerator; import org.teavm.platform.plugin.PlatformGenerator;
import org.teavm.runtime.RuntimeClass;
import org.teavm.runtime.RuntimeObject;
public final class Platform { public final class Platform {
private Platform() { private Platform() {
@ -37,14 +40,21 @@ public final class Platform {
@PluggableDependency(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class)
public static native Object clone(Object obj); public static native Object clone(Object obj);
@DelegateTo("isInstanceLowLevel")
public static boolean isInstance(PlatformObject obj, PlatformClass cls) { public static boolean isInstance(PlatformObject obj, PlatformClass cls) {
return obj != null && !isUndefined(obj.getPlatformClass().getMetadata()) return obj != null && !isUndefined(obj.getPlatformClass().getMetadata())
&& isAssignable(obj.getPlatformClass(), cls); && isAssignable(obj.getPlatformClass(), cls);
} }
@SuppressWarnings("unused")
private static boolean isInstanceLowLevel(RuntimeClass self, RuntimeObject object) {
return isAssignableLowLevel(RuntimeClass.getClass(object), self);
}
@JSBody(params = "object", script = "return typeof object === 'undefined';") @JSBody(params = "object", script = "return typeof object === 'undefined';")
private static native boolean isUndefined(JSObject object); private static native boolean isUndefined(JSObject object);
@DelegateTo("isAssignableLowLevel")
public static boolean isAssignable(PlatformClass from, PlatformClass to) { public static boolean isAssignable(PlatformClass from, PlatformClass to) {
if (from == to) { if (from == to) {
return true; return true;
@ -58,6 +68,11 @@ public final class Platform {
return false; return false;
} }
@SuppressWarnings("unused")
private static boolean isAssignableLowLevel(RuntimeClass from, RuntimeClass to) {
return to.isSupertypeOf.apply(from);
}
@InjectedBy(PlatformGenerator.class) @InjectedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class)
public static native Class<?> asJavaClass(PlatformObject obj); public static native Class<?> asJavaClass(PlatformObject obj);
@ -131,4 +146,24 @@ public final class Platform {
public static PlatformString stringFromCharCode(int charCode) { public static PlatformString stringFromCharCode(int charCode) {
return ((PlatformHelper) Window.current()).getStringClass().fromCharCode(charCode); return ((PlatformHelper) Window.current()).getStringClass().fromCharCode(charCode);
} }
@DelegateTo("isPrimitiveLowLevel")
public static boolean isPrimitive(PlatformClass cls) {
return cls.getMetadata().isPrimitive();
}
@SuppressWarnings("unused")
private static boolean isPrimitiveLowLevel(RuntimeClass cls) {
return (cls.flags & RuntimeClass.PRIMITIVE) != 0;
}
@DelegateTo("getArrayItemLowLevel")
public static PlatformClass getArrayItem(PlatformClass cls) {
return cls.getMetadata().getArrayItem();
}
@SuppressWarnings("unused")
private static RuntimeClass getArrayItemLowLevel(RuntimeClass cls) {
return cls.itemType;
}
} }

View File

@ -18,10 +18,6 @@ package org.teavm.platform;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty; import org.teavm.jso.JSProperty;
/**
*
* @author Alexey Andreev
*/
public interface PlatformClassMetadata extends JSObject { public interface PlatformClassMetadata extends JSObject {
@JSProperty("item") @JSProperty("item")
PlatformClass getArrayItem(); PlatformClass getArrayItem();