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.java.lang.annotation.TAnnotation;
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.PlatformClass;
import org.teavm.platform.metadata.ClassResource;
import org.teavm.platform.metadata.ClassScopedMetadataProvider;
import org.teavm.runtime.RuntimeClass;
import org.teavm.runtime.RuntimeObject;
public class TClass<T> extends TObject implements TAnnotatedElement {
TString name;
@ -93,11 +97,11 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
}
public boolean isPrimitive() {
return platformClass.getMetadata().isPrimitive();
return Platform.isPrimitive(platformClass);
}
public boolean isArray() {
return platformClass.getMetadata().getArrayItem() != null;
return Platform.getArrayItem(platformClass) != null;
}
public boolean isEnum() {
@ -105,7 +109,7 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
}
public TClass<?> getComponentType() {
return getClass(platformClass.getMetadata().getArrayItem());
return getClass(Platform.getArrayItem(platformClass));
}
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);
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;
if ((type.itemType.flags & RuntimeClass.PRIMITIVE) == 0) {
itemSize = Address.sizeOf();

View File

@ -21,14 +21,26 @@ import org.teavm.interop.DelegateTo;
import org.teavm.backend.javascript.spi.GeneratedBy;
import org.teavm.platform.PlatformClass;
import org.teavm.runtime.Allocator;
import org.teavm.runtime.RuntimeArray;
import org.teavm.runtime.RuntimeClass;
import org.teavm.runtime.RuntimeObject;
public final class TArray extends TObject {
@GeneratedBy(ArrayNativeGenerator.class)
@PluggableDependency(ArrayNativeGenerator.class)
@DelegateTo("getLengthLowLevel")
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 {
if (componentType == null) {
throw new TNullPointerException();

View File

@ -32,7 +32,7 @@ public final class Example {
testLazyInitialization();
testHashCode();
testArrayList();
//testArrayCopy();
testArrayCopy();
}
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.AllocatorIntrinsic;
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.PlatformClassMetadataIntrinsic;
import org.teavm.backend.wasm.intrinsics.PlatformIntrinsic;
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.WasmStructureIntrinsic;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmMemorySegment;
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.classes.TagRegistry;
import org.teavm.model.classes.VirtualTableProvider;
import org.teavm.model.instructions.CloneArrayInstruction;
import org.teavm.model.instructions.InvocationType;
import org.teavm.model.instructions.InvokeInstruction;
import org.teavm.runtime.Allocator;
@ -125,6 +126,7 @@ public class WasmTarget implements TeaVMTarget {
List<ClassHolderTransformer> transformers = new ArrayList<>();
transformers.add(new ObjectPatch());
transformers.add(new ClassPatch());
transformers.add(new WasmDependencyListener());
return transformers;
}
@ -158,6 +160,8 @@ public class WasmTarget implements TeaVMTarget {
Address.class, void.class), null).use();
dependencyChecker.linkMethod(new MethodReference(WasmRuntime.class, "fillZero", Address.class, int.class,
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",
RuntimeClass.class, Address.class), null).use();
@ -188,7 +192,8 @@ public class WasmTarget implements TeaVMTarget {
VirtualTableProvider vtableProvider = createVirtualTableProvider(classes);
TagRegistry tagRegistry = new TagRegistry(classes);
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<>(),
new HashSet<>());
@ -197,12 +202,12 @@ public class WasmTarget implements TeaVMTarget {
vtableProvider, tagRegistry, stringPool);
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 AllocatorIntrinsic());
context.addIntrinsic(new PlatformIntrinsic());
context.addIntrinsic(new PlatformClassIntrinsic());
context.addIntrinsic(new PlatformClassMetadataIntrinsic());
context.addIntrinsic(new PlatformObjectIntrinsic(classGenerator));
context.addIntrinsic(new ClassIntrinsic());
@ -393,6 +398,8 @@ public class WasmTarget implements TeaVMTarget {
if (invoke.getType() == InvocationType.VIRTUAL) {
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.DataValue;
import org.teavm.interop.Address;
import org.teavm.interop.Function;
import org.teavm.interop.Structure;
import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource;
@ -63,7 +64,8 @@ public class WasmClassGenerator {
DataPrimitives.INT, /* tag */
DataPrimitives.INT, /* canary */
DataPrimitives.ADDRESS, /* item type */
DataPrimitives.ADDRESS /* array type */);
DataPrimitives.ADDRESS, /* array type */
DataPrimitives.INT /* isInstance function */);
public WasmClassGenerator(ClassReaderSource classSource, VirtualTableProvider vtableProvider,
TagRegistry tagRegistry, BinaryWriter binaryWriter) {
@ -216,10 +218,22 @@ public class WasmClassGenerator {
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) {
if (cls.getName().equals(Structure.class.getName()) || cls.getName().equals(Address.class.getName())) {
data.size = 0;
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())) {
addClass(ValueType.object(cls.getParent()));
ClassBinaryData parentData = binaryDataMap.get(ValueType.object(cls.getParent()));
@ -228,6 +242,10 @@ public class WasmClassGenerator {
if (parentData.start == -1) {
data.start = -1;
}
if (parentData.function) {
data.function = true;
return;
}
} else {
data.size = 4;
data.alignment = 4;
@ -328,5 +346,6 @@ public class WasmClassGenerator {
int start;
ObjectIntMap<String> fieldLayout = new ObjectIntOpenHashMap<>();
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.DependencyAgent;
import org.teavm.dependency.MethodDependency;
import org.teavm.diagnostics.Diagnostics;
import org.teavm.interop.DelegateTo;
import org.teavm.model.AnnotationReader;
import org.teavm.model.CallLocation;
import org.teavm.model.ClassHolder;
import org.teavm.model.ClassHolderTransformer;
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;
public class WasmDependencyListener extends AbstractDependencyListener {
public class WasmDependencyListener extends AbstractDependencyListener implements ClassHolderTransformer {
@Override
public void methodReached(DependencyAgent agent, MethodDependency method, CallLocation location) {
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) {
String str = (String) expr.getValue();
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 {
throw new IllegalArgumentException("Constant unsupported: " + expr.getValue());
}

View File

@ -109,13 +109,16 @@ public class WasmGenerator {
public WasmFunction generateNative(MethodReference methodReference) {
WasmFunction function = new WasmFunction(WasmMangling.mangleMethod(methodReference));
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);
if (importedMethod != null) {
function.setImportName(importedMethod.name);
function.setImportModule(importedMethod.module);
} else {
function.setImportName("<unknown>");
}
return function;

View File

@ -27,8 +27,16 @@ import org.teavm.runtime.Allocator;
public class AllocatorIntrinsic implements WasmIntrinsic {
@Override
public boolean isApplicable(MethodReference methodReference) {
return methodReference.getClassName().equals(Allocator.class.getName())
&& methodReference.getName().equals("fillZero");
if (!methodReference.getClassName().equals(Allocator.class.getName())) {
return false;
}
switch (methodReference.getName()) {
case "fillZero":
case "moveMemoryBlock":
return true;
default:
return false;
}
}
@Override
@ -39,7 +47,8 @@ public class AllocatorIntrinsic implements WasmIntrinsic {
MethodReference delegateMetod = new MethodReference(WasmRuntime.class.getName(),
invocation.getMethod().getDescriptor());
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()));
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.backend.wasm.model.expression.WasmExpression;
import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodReference;
public class PlatformIntrinsic implements WasmIntrinsic {
@ -24,7 +25,18 @@ public class PlatformIntrinsic implements WasmIntrinsic {
@Override
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

View File

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

View File

@ -15,6 +15,8 @@
*/
package org.teavm.runtime;
import org.teavm.interop.Address;
public class RuntimeClass extends RuntimeJavaObject {
public static final int INITIALIZED = 1;
public static final int PRIMITIVE = 2;
@ -25,6 +27,7 @@ public class RuntimeClass extends RuntimeJavaObject {
public int canary;
public RuntimeClass itemType;
public RuntimeClass arrayType;
public IsSupertypeFunction isSupertypeOf;
public static int computeCanary(int size, int tag) {
return size ^ (tag << 8) ^ (tag >>> 24) ^ 0xAAAAAAAA;
@ -33,4 +36,8 @@ public class RuntimeClass extends RuntimeJavaObject {
public int computeCanary() {
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.InjectedBy;
import org.teavm.dependency.PluggableDependency;
import org.teavm.interop.DelegateTo;
import org.teavm.jso.JSBody;
import org.teavm.jso.JSObject;
import org.teavm.jso.browser.Window;
import org.teavm.platform.metadata.ClassResource;
import org.teavm.platform.metadata.StaticFieldResource;
import org.teavm.platform.plugin.PlatformGenerator;
import org.teavm.runtime.RuntimeClass;
import org.teavm.runtime.RuntimeObject;
public final class Platform {
private Platform() {
@ -37,14 +40,21 @@ public final class Platform {
@PluggableDependency(PlatformGenerator.class)
public static native Object clone(Object obj);
@DelegateTo("isInstanceLowLevel")
public static boolean isInstance(PlatformObject obj, PlatformClass cls) {
return obj != null && !isUndefined(obj.getPlatformClass().getMetadata())
&& 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';")
private static native boolean isUndefined(JSObject object);
@DelegateTo("isAssignableLowLevel")
public static boolean isAssignable(PlatformClass from, PlatformClass to) {
if (from == to) {
return true;
@ -58,6 +68,11 @@ public final class Platform {
return false;
}
@SuppressWarnings("unused")
private static boolean isAssignableLowLevel(RuntimeClass from, RuntimeClass to) {
return to.isSupertypeOf.apply(from);
}
@InjectedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class)
public static native Class<?> asJavaClass(PlatformObject obj);
@ -131,4 +146,24 @@ public final class Platform {
public static PlatformString stringFromCharCode(int 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.JSProperty;
/**
*
* @author Alexey Andreev
*/
public interface PlatformClassMetadata extends JSObject {
@JSProperty("item")
PlatformClass getArrayItem();