diff --git a/classlib/src/main/java/org/teavm/classlib/impl/PlatformMarkerSupport.java b/classlib/src/main/java/org/teavm/classlib/impl/PlatformMarkerSupport.java index 84a53333b..91f56c1a9 100644 --- a/classlib/src/main/java/org/teavm/classlib/impl/PlatformMarkerSupport.java +++ b/classlib/src/main/java/org/teavm/classlib/impl/PlatformMarkerSupport.java @@ -65,12 +65,18 @@ public class PlatformMarkerSupport implements ClassHolderTransformer { for (BasicBlock block : program.getBasicBlocks()) { for (Instruction instruction : block) { Variable receiver; + MarkerKind kind; if (instruction instanceof InvokeInstruction) { MethodReference methodRef = ((InvokeInstruction) instruction).getMethod(); MethodReader method = innerSource.resolve(methodRef); - if (method == null || !isMarker(method)) { + if (method == null) { continue; } + kind = isMarker(method); + if (kind == null) { + continue; + } + if (!method.hasModifier(ElementModifier.STATIC)) { diagnostics.error(new CallLocation(containingMethod, instruction.getLocation()), "Method '{{m0}}' is marked with '{{c1}}' and should be static", @@ -87,9 +93,14 @@ public class PlatformMarkerSupport implements ClassHolderTransformer { } else if (instruction instanceof GetFieldInstruction) { FieldReference fieldRef = ((GetFieldInstruction) instruction).getField(); FieldReader field = innerSource.resolve(fieldRef); - if (field == null || !isMarker(field)) { + if (field == null) { continue; } + kind = isMarker(field); + if (kind == null) { + continue; + } + if (!field.hasModifier(ElementModifier.STATIC)) { diagnostics.error(new CallLocation(containingMethod, instruction.getLocation()), "Field '{{f0}}' is marked with '{{c1}}' and should be static", @@ -113,7 +124,7 @@ public class PlatformMarkerSupport implements ClassHolderTransformer { } else { IntegerConstantInstruction trueResult = new IntegerConstantInstruction(); trueResult.setReceiver(receiver); - trueResult.setConstant(1); + trueResult.setConstant(kind == MarkerKind.TRUE ? 1 : 0); trueResult.setLocation(instruction.getLocation()); instruction.replace(trueResult); } @@ -130,21 +141,26 @@ public class PlatformMarkerSupport implements ClassHolderTransformer { } } - private boolean isMarker(MemberReader member) { + private MarkerKind isMarker(MemberReader member) { AnnotationReader annot = member.getAnnotations().get(PlatformMarker.class.getName()); if (annot == null) { - return false; + return null; } AnnotationValue value = annot.getValue("value"); if (value == null) { - return true; + return MarkerKind.TRUE; } String tagToMatch = value.getString(); for (String tag : tags) { if (tag.equals(tagToMatch)) { - return true; + return MarkerKind.TRUE; } } - return false; + return MarkerKind.FALSE; + } + + enum MarkerKind { + TRUE, + FALSE } } diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TCharacter.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TCharacter.java index 122689df5..488e1c541 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TCharacter.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TCharacter.java @@ -242,7 +242,7 @@ public class TCharacter extends TObject implements TComparable { return toLowerCaseSystem(codePoint); } - @Import(module = "runtime", name = "tolower") + @Import(module = "runtime", name = "towlower") private static native int toLowerCaseSystem(int codePoint); public static char toUpperCase(char ch) { @@ -258,7 +258,7 @@ public class TCharacter extends TObject implements TComparable { return toUpperCaseSystem(codePoint); } - @Import(module = "runtime", name = "toupper") + @Import(module = "runtime", name = "towupper") private static native int toUpperCaseSystem(int codePoint); public static int digit(char ch, int radix) { diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java index d99f7795b..7d90276a3 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TClass.java @@ -512,7 +512,11 @@ public class TClass extends TObject implements TAnnotatedElement { @SuppressWarnings("unchecked") public T[] getEnumConstants() { - return isEnum() ? (T[]) Platform.getEnumConstants(platformClass).clone() : null; + if (!isEnum()) { + return null; + } + Platform.initClass(platformClass); + return (T[]) Platform.getEnumConstants(platformClass).clone(); } @SuppressWarnings("unchecked") diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TConsoleOutputStreamStderr.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TConsoleOutputStreamStderr.java index 5eb0a919c..530d7d2f5 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TConsoleOutputStreamStderr.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TConsoleOutputStreamStderr.java @@ -32,6 +32,6 @@ class TConsoleOutputStreamStderr extends TOutputStream { writeImpl(b); } - @Import(name = "putchar", module = "runtime") + @Import(name = "putwchar", module = "runtime") static native void writeImpl(int b); } diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java index f046473b2..90e32736d 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TDouble.java @@ -222,15 +222,15 @@ public class TDouble extends TNumber implements TComparable { } @JSBody(params = "v", script = "return isNaN(v);") - @Import(module = "runtime", name = "isNaN") + @Import(module = "runtime", name = "isnan") public static native boolean isNaN(double v); @JSBody(script = "return NaN;") - @Import(module = "runtime", name = "getNaN") + @Import(module = "runtime", name = "TeaVM_getNaN") private static native double getNaN(); @JSBody(params = "v", script = "return !isFinite(v);") - @Import(module = "runtime", name = "isInfinite") + @Import(module = "runtime", name = "isinf") public static native boolean isInfinite(double v); public static long doubleToRawLongBits(double value) { diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java index ee9d6329d..feb1b993b 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TFloat.java @@ -90,7 +90,7 @@ public class TFloat extends TNumber implements TComparable { } @JSBody(params = "v", script = "return isNaN(v);") - @Import(module = "runtime", name = "isNaN") + @Import(module = "runtime", name = "isnan") public static native boolean isNaN(float v); public static boolean isInfinite(float v) { @@ -98,11 +98,11 @@ public class TFloat extends TNumber implements TComparable { } @JSBody(params = "v", script = "return isFinite(v);") - @Import(module = "runtime", name = "isFinite") + @Import(module = "runtime", name = "isfinite") private static native boolean isFinite(float v); @JSBody(script = "return NaN;") - @Import(module = "runtime", name = "getNaN") + @Import(module = "runtime", name = "TeaVM_getNaN") private static native float getNaN(); public static float parseFloat(TString string) throws TNumberFormatException { diff --git a/classlib/src/main/java/org/teavm/classlib/java/util/TRandom.java b/classlib/src/main/java/org/teavm/classlib/java/util/TRandom.java index efcc92736..46530bafa 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/util/TRandom.java +++ b/classlib/src/main/java/org/teavm/classlib/java/util/TRandom.java @@ -15,6 +15,7 @@ */ package org.teavm.classlib.java.util; +import org.teavm.classlib.PlatformDetector; import org.teavm.classlib.java.io.TSerializable; import org.teavm.classlib.java.lang.TMath; import org.teavm.classlib.java.lang.TObject; @@ -39,7 +40,7 @@ public class TRandom extends TObject implements TSerializable { } protected int next(int bits) { - return (int) (random() * (1L << TMath.min(32, bits))); + return (int) (nextDouble() * (1L << TMath.min(32, bits))); } public void nextBytes(byte[] bytes) { @@ -53,7 +54,7 @@ public class TRandom extends TObject implements TSerializable { } public int nextInt(int n) { - return (int) (random() * n); + return (int) (nextDouble() * n); } public long nextLong() { @@ -65,13 +66,20 @@ public class TRandom extends TObject implements TSerializable { } public float nextFloat() { - return (float) random(); + return (float) nextDouble(); } public double nextDouble() { - return random(); + if (PlatformDetector.isC()) { + return crand(); + } else { + return random(); + } } - + + @Import(name = "TeaVM_rand") + private static native double crand(); + /** * Generate a random number with Gaussian distribution: * centered around 0 with a standard deviation of 1.0. diff --git a/core/src/main/java/org/teavm/backend/c/CTarget.java b/core/src/main/java/org/teavm/backend/c/CTarget.java index 12a2b7f4a..10e65b349 100644 --- a/core/src/main/java/org/teavm/backend/c/CTarget.java +++ b/core/src/main/java/org/teavm/backend/c/CTarget.java @@ -352,6 +352,7 @@ public class CTarget implements TeaVMTarget { Set types) { writer.println("int main(int argc, char** argv) {").indent(); + writer.println("TeaVM_beforeInit();"); writer.println("initHeap(" + minHeapSize + ");"); generateVirtualTableHeaders(context, writer, types); generateStringPoolHeaders(context, writer); @@ -417,6 +418,6 @@ public class CTarget implements TeaVMTarget { @Override public String[] getPlatformTags() { - return new String[] { PlatformMarkers.C, PlatformMarkers.WEBASSEMBLY }; + return new String[] { PlatformMarkers.C, PlatformMarkers.LOW_LEVEL }; } } diff --git a/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java b/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java index 45f9bbc98..328ab6443 100644 --- a/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java +++ b/core/src/main/java/org/teavm/backend/c/generate/ClassGenerator.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import org.teavm.ast.RegularMethodNode; import org.teavm.ast.decompilation.Decompiler; import org.teavm.backend.c.generators.Generator; @@ -36,6 +37,7 @@ import org.teavm.model.ClassReader; import org.teavm.model.ClassReaderSource; import org.teavm.model.ElementModifier; import org.teavm.model.FieldHolder; +import org.teavm.model.FieldReader; import org.teavm.model.FieldReference; import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodHolder; @@ -276,11 +278,20 @@ public class ClassGenerator { String name = context.getNames().forClassInstance(type); vtableForwardWriter.print("static ").print(structName).print(" ").print(name).println(";"); + + ClassReader cls = className != null ? context.getClassSource().get(className) : null; + String enumConstants; + if (cls != null && cls.hasModifier(ElementModifier.ENUM)) { + enumConstants = writeEnumConstants(cls, name); + } else { + enumConstants = "NULL"; + } + vtableWriter.print("static alignas(8) ").print(structName).print(" ").print(name).println(" = {").indent(); if (className != null) { vtableWriter.println(".parent = {").indent(); - generateRuntimeClassInitializer(type); + generateRuntimeClassInitializer(type, enumConstants); vtableWriter.outdent().println("},"); VirtualTable virtualTable = context.getVirtualTableProvider().lookup(className); @@ -301,19 +312,34 @@ public class ClassGenerator { } } } else { - generateRuntimeClassInitializer(type); + generateRuntimeClassInitializer(type, enumConstants); } vtableWriter.outdent().println("};"); } - private void generateRuntimeClassInitializer(ValueType type) { + private String writeEnumConstants(ClassReader cls, String baseName) { + List fields = cls.getFields().stream() + .filter(f -> f.hasModifier(ElementModifier.ENUM)) + .collect(Collectors.toList()); + String name = baseName + "_enumConstants"; + vtableWriter.print("static void* " + name + "[" + (fields.size() + 1) + "] = { "); + vtableWriter.print("(void*) (intptr_t) " + fields.size()); + for (FieldReader field : fields) { + vtableWriter.print(", ").print("&" + context.getNames().forStaticField(field.getReference())); + } + vtableWriter.println(" };"); + return name; + } + + private void generateRuntimeClassInitializer(ValueType type, String enumConstants) { String sizeExpr; int tag; String parent; String itemTypeExpr; int flags = 0; String layout = "NULL"; + String initFunction = "NULL"; if (type instanceof ValueType.Object) { String className = ((ValueType.Object) type).getClassName(); @@ -323,13 +349,17 @@ public class ClassGenerator { className = RuntimeObject.class.getName(); } - if (needsData(cls)) { + if (cls != null && needsData(cls)) { String structName = context.getNames().forClass(className); sizeExpr = "(int32_t) (intptr_t) ALIGN(sizeof(" + structName + "), sizeof(void*))"; } else { sizeExpr = "0"; } - tag = tagRegistry.getRanges(className).get(0).lower; + if (cls != null && cls.hasModifier(ElementModifier.ENUM)) { + flags |= RuntimeClass.ENUM; + } + List ranges = tagRegistry.getRanges(className); + tag = ranges != null && !ranges.isEmpty() ? ranges.get(0).lower : 0; parent = cls != null && cls.getParent() != null && types.contains(ValueType.object(cls.getParent())) ? "&" + context.getNames().forClassInstance(ValueType.object(cls.getParent())) @@ -337,6 +367,10 @@ public class ClassGenerator { itemTypeExpr = "NULL"; int layoutOffset = classLayoutOffsets.getOrDefault(className, -1); layout = layoutOffset >= 0 ? "classLayouts + " + layoutOffset : "NULL"; + + if (cls != null && needsInitializer(cls)) { + initFunction = context.getNames().forClassInitializer(className); + } } else if (type instanceof ValueType.Array) { parent = "&" + context.getNames().forClassInstance(ValueType.object("java.lang.Object")); tag = tagRegistry.getRanges("java.lang.Object").get(0).lower; @@ -382,7 +416,9 @@ public class ClassGenerator { vtableWriter.print(".").print(classFieldName("isSupertypeOf")).println(" = &" + superTypeFunction + ","); vtableWriter.print(".").print(classFieldName("parent")).println(" = " + parent + ","); vtableWriter.print(".").print(classFieldName("enumValues")).println(" = NULL,"); - vtableWriter.print(".").print(classFieldName("layout")).println(" = " + layout); + vtableWriter.print(".").print(classFieldName("layout")).println(" = " + layout + ","); + vtableWriter.print(".").print(classFieldName("enumValues")).println(" = " + enumConstants + ","); + vtableWriter.print(".").print(classFieldName("init")).println(" = " + initFunction); } private void generateVirtualTableStructure(ClassReader cls) { @@ -392,13 +428,15 @@ public class ClassGenerator { vtableStructuresWriter.println("JavaClass parent;"); VirtualTable virtualTable = context.getVirtualTableProvider().lookup(cls.getName()); - for (VirtualTableEntry entry : virtualTable.getEntries().values()) { - String methodName = context.getNames().forVirtualMethod( - new MethodReference(cls.getName(), entry.getMethod())); - vtableStructuresWriter.printType(entry.getMethod().getResultType()) - .print(" (*").print(methodName).print(")("); - codeGenerator.generateMethodParameters(vtableStructuresWriter, entry.getMethod(), false, false); - vtableStructuresWriter.println(");"); + if (virtualTable != null) { + for (VirtualTableEntry entry : virtualTable.getEntries().values()) { + String methodName = context.getNames().forVirtualMethod( + new MethodReference(cls.getName(), entry.getMethod())); + vtableStructuresWriter.printType(entry.getMethod().getResultType()) + .print(" (*").print(methodName).print(")("); + codeGenerator.generateMethodParameters(vtableStructuresWriter, entry.getMethod(), false, false); + vtableStructuresWriter.println(");"); + } } vtableStructuresWriter.outdent().print("} ").print(name).println(";"); @@ -517,7 +555,7 @@ public class ClassGenerator { } } - private boolean needsInitializer(ClassHolder cls) { + private boolean needsInitializer(ClassReader cls) { return !context.getCharacteristics().isStaticInit(cls.getName()) && !context.getCharacteristics().isStructure(cls.getName()) && cls.getMethod(new MethodDescriptor("", ValueType.VOID)) != null; diff --git a/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java b/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java index cd3d1eb65..f730e5cd5 100644 --- a/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java @@ -266,13 +266,48 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { int index = context.getStringPool().getStringIndex((String) value); writer.print("(stringPool + " + index + ")"); } else if (value instanceof Integer) { - writer.print("INT32_C(" + value + ")"); + int i = (Integer) value; + long v = i; + if (i < 0) { + writer.print("-"); + v = -i; + } + writer.print("INT32_C("); + writeLongConstant(v); + writer.print(")"); } else if (value instanceof Long) { - writer.print("INT64_C(" + value + ")"); + long v = (Long) value; + if (v < 0) { + writer.print("-"); + v = -v; + } + writer.print("INT64_C("); + writeLongConstant(v); + writer.print(")"); } else if (value instanceof Float) { - writer.print(value + "f"); + float f = (Float) value; + if (Float.isInfinite(f)) { + if (f < 0) { + writer.print("-"); + } + writer.print("INFINITY"); + } else if (Float.isNaN(f)) { + writer.print("NAN"); + } else { + writer.print(f + "f"); + } } else if (value instanceof Double) { - writer.print(value.toString()); + double d = (Double) value; + if (Double.isInfinite(d)) { + if (d < 0) { + writer.print("-"); + } + writer.print("INFINITY"); + } else if (Double.isNaN(d)) { + writer.print("NAN"); + } else { + writer.print(value.toString()); + } } else if (value instanceof Boolean) { writer.print((Boolean) value ? "1" : "0"); } else if (value instanceof ValueType) { @@ -280,6 +315,14 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { } } + private void writeLongConstant(long v) { + if (v == Long.MIN_VALUE) { + writer.print("0x8000000000000000"); + return; + } + writer.print(String.valueOf(v)); + } + @Override public void visit(VariableExpr expr) { if (expr.getIndex() == 0) { diff --git a/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformClassMetadataIntrinsic.java b/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformClassMetadataIntrinsic.java index 7dfdff876..b65b81140 100644 --- a/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformClassMetadataIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformClassMetadataIntrinsic.java @@ -24,26 +24,40 @@ public class PlatformClassMetadataIntrinsic implements Intrinsic { private static final String PLATFORM_CLASS_METADATA = "org.teavm.platform.PlatformClassMetadata"; private static final FieldReference ARRAY_TYPE_FIELD = new FieldReference( RuntimeClass.class.getName(), "arrayType"); + private static final FieldReference SUPERCLASS_FIELD = new FieldReference( + RuntimeClass.class.getName(), "parent"); @Override public boolean canHandle(MethodReference method) { if (!method.getClassName().equals(PLATFORM_CLASS_METADATA)) { return false; } - return method.getName().equals("getArrayItem"); + switch (method.getName()) { + case "getArrayItem": + case "getSuperclass": + return true; + } + return false; } @Override public void apply(IntrinsicContext context, InvocationExpr invocation) { switch (invocation.getMethod().getName()) { case "getArrayItem": - context.writer().print("FIELD("); - context.emit(invocation.getArguments().get(0)); - context.writer().print(","); - context.writer().print(context.names().forClass(ARRAY_TYPE_FIELD.getClassName())).print(", "); - context.writer().print(context.names().forMemberField(ARRAY_TYPE_FIELD)); - context.writer().print(")"); + printFieldAccess(context, invocation, ARRAY_TYPE_FIELD); + break; + case "getSuperclass": + printFieldAccess(context, invocation, SUPERCLASS_FIELD); break; } } + + private void printFieldAccess(IntrinsicContext context, InvocationExpr invocation, FieldReference field) { + context.writer().print("FIELD("); + context.emit(invocation.getArguments().get(0)); + context.writer().print(","); + context.writer().print(context.names().forClass(field.getClassName())).print(", "); + context.writer().print(context.names().forMemberField(field)); + context.writer().print(")"); + } } diff --git a/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformIntrinsic.java b/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformIntrinsic.java index b248e242c..460d35676 100644 --- a/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/c/intrinsic/PlatformIntrinsic.java @@ -42,8 +42,6 @@ public class PlatformIntrinsic implements Intrinsic { case "asJavaClass": context.emit(invocation.getArguments().get(0)); break; - case "getName": - } } } diff --git a/core/src/main/java/org/teavm/runtime/InitFunction.java b/core/src/main/java/org/teavm/runtime/InitFunction.java new file mode 100644 index 000000000..2c8d28c0c --- /dev/null +++ b/core/src/main/java/org/teavm/runtime/InitFunction.java @@ -0,0 +1,24 @@ +/* + * Copyright 2018 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; +import org.teavm.interop.Unmanaged; + +public abstract class InitFunction extends Function { + @Unmanaged + public abstract void run(); +} diff --git a/core/src/main/java/org/teavm/runtime/RuntimeClass.java b/core/src/main/java/org/teavm/runtime/RuntimeClass.java index f804eca84..ec139ad9f 100644 --- a/core/src/main/java/org/teavm/runtime/RuntimeClass.java +++ b/core/src/main/java/org/teavm/runtime/RuntimeClass.java @@ -43,6 +43,7 @@ public class RuntimeClass extends RuntimeObject { public RuntimeClass itemType; public RuntimeClass arrayType; public IsSupertypeFunction isSupertypeOf; + public InitFunction init; public RuntimeClass parent; public Address enumValues; public Address layout; diff --git a/core/src/main/resources/org/teavm/backend/c/runtime.c b/core/src/main/resources/org/teavm/backend/c/runtime.c index e73cfaf24..712126a6a 100644 --- a/core/src/main/resources/org/teavm/backend/c/runtime.c +++ b/core/src/main/resources/org/teavm/backend/c/runtime.c @@ -2,7 +2,9 @@ #include #include #include +#include #include +#include #include #include @@ -87,6 +89,18 @@ static int32_t gc_regionSize = INT32_C(32768); static int32_t gc_regionMaxCount = INT32_C(0); static int64_t gc_availableBytes = INT64_C(0); +static double TeaVM_rand() { + return rand() / ((double) RAND_MAX + 1); +} + +static inline float TeaVM_getNaN() { + return NAN; +} + +static void TeaVM_beforeInit() { + srand(time(NULL)); +} + #ifdef __GNUC__ static void initHeap(int64_t heapSize) { long workSize = heapSize / 16; diff --git a/platform/src/main/java/org/teavm/platform/Platform.java b/platform/src/main/java/org/teavm/platform/Platform.java index f8955a524..0eea8a94a 100644 --- a/platform/src/main/java/org/teavm/platform/Platform.java +++ b/platform/src/main/java/org/teavm/platform/Platform.java @@ -112,8 +112,16 @@ public final class Platform { @PluggableDependency(PlatformGenerator.class) @InjectedBy(PlatformGenerator.class) + @DelegateTo("initClassLowLevel") public static native void initClass(PlatformClass cls); + @Unmanaged + private static void initClassLowLevel(RuntimeClass cls) { + if (cls.init != null) { + cls.init.run(); + } + } + @InjectedBy(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class) public static native PlatformClass classFromResource(ClassResource resource); diff --git a/platform/src/main/java/org/teavm/platform/PlatformClassMetadata.java b/platform/src/main/java/org/teavm/platform/PlatformClassMetadata.java index bbca2938d..de7c1d193 100644 --- a/platform/src/main/java/org/teavm/platform/PlatformClassMetadata.java +++ b/platform/src/main/java/org/teavm/platform/PlatformClassMetadata.java @@ -15,17 +15,20 @@ */ package org.teavm.platform; +import org.teavm.interop.Unmanaged; import org.teavm.jso.JSObject; import org.teavm.jso.JSProperty; public interface PlatformClassMetadata extends JSObject { @JSProperty("item") + @Unmanaged PlatformClass getArrayItem(); @JSProperty PlatformSequence getSupertypes(); @JSProperty + @Unmanaged PlatformClass getSuperclass(); @JSProperty