Fix bugs in C backend to make more tests pass

This commit is contained in:
Alexey Andreev 2018-04-21 00:55:43 +03:00
parent 4990dbe8e4
commit 8f0320e217
17 changed files with 223 additions and 51 deletions

View File

@ -65,12 +65,18 @@ public class PlatformMarkerSupport implements ClassHolderTransformer {
for (BasicBlock block : program.getBasicBlocks()) { for (BasicBlock block : program.getBasicBlocks()) {
for (Instruction instruction : block) { for (Instruction instruction : block) {
Variable receiver; Variable receiver;
MarkerKind kind;
if (instruction instanceof InvokeInstruction) { if (instruction instanceof InvokeInstruction) {
MethodReference methodRef = ((InvokeInstruction) instruction).getMethod(); MethodReference methodRef = ((InvokeInstruction) instruction).getMethod();
MethodReader method = innerSource.resolve(methodRef); MethodReader method = innerSource.resolve(methodRef);
if (method == null || !isMarker(method)) { if (method == null) {
continue; continue;
} }
kind = isMarker(method);
if (kind == null) {
continue;
}
if (!method.hasModifier(ElementModifier.STATIC)) { if (!method.hasModifier(ElementModifier.STATIC)) {
diagnostics.error(new CallLocation(containingMethod, instruction.getLocation()), diagnostics.error(new CallLocation(containingMethod, instruction.getLocation()),
"Method '{{m0}}' is marked with '{{c1}}' and should be static", "Method '{{m0}}' is marked with '{{c1}}' and should be static",
@ -87,9 +93,14 @@ public class PlatformMarkerSupport implements ClassHolderTransformer {
} else if (instruction instanceof GetFieldInstruction) { } else if (instruction instanceof GetFieldInstruction) {
FieldReference fieldRef = ((GetFieldInstruction) instruction).getField(); FieldReference fieldRef = ((GetFieldInstruction) instruction).getField();
FieldReader field = innerSource.resolve(fieldRef); FieldReader field = innerSource.resolve(fieldRef);
if (field == null || !isMarker(field)) { if (field == null) {
continue; continue;
} }
kind = isMarker(field);
if (kind == null) {
continue;
}
if (!field.hasModifier(ElementModifier.STATIC)) { if (!field.hasModifier(ElementModifier.STATIC)) {
diagnostics.error(new CallLocation(containingMethod, instruction.getLocation()), diagnostics.error(new CallLocation(containingMethod, instruction.getLocation()),
"Field '{{f0}}' is marked with '{{c1}}' and should be static", "Field '{{f0}}' is marked with '{{c1}}' and should be static",
@ -113,7 +124,7 @@ public class PlatformMarkerSupport implements ClassHolderTransformer {
} else { } else {
IntegerConstantInstruction trueResult = new IntegerConstantInstruction(); IntegerConstantInstruction trueResult = new IntegerConstantInstruction();
trueResult.setReceiver(receiver); trueResult.setReceiver(receiver);
trueResult.setConstant(1); trueResult.setConstant(kind == MarkerKind.TRUE ? 1 : 0);
trueResult.setLocation(instruction.getLocation()); trueResult.setLocation(instruction.getLocation());
instruction.replace(trueResult); 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()); AnnotationReader annot = member.getAnnotations().get(PlatformMarker.class.getName());
if (annot == null) { if (annot == null) {
return false; return null;
} }
AnnotationValue value = annot.getValue("value"); AnnotationValue value = annot.getValue("value");
if (value == null) { if (value == null) {
return true; return MarkerKind.TRUE;
} }
String tagToMatch = value.getString(); String tagToMatch = value.getString();
for (String tag : tags) { for (String tag : tags) {
if (tag.equals(tagToMatch)) { if (tag.equals(tagToMatch)) {
return true; return MarkerKind.TRUE;
} }
} }
return false; return MarkerKind.FALSE;
}
enum MarkerKind {
TRUE,
FALSE
} }
} }

View File

@ -242,7 +242,7 @@ public class TCharacter extends TObject implements TComparable<TCharacter> {
return toLowerCaseSystem(codePoint); return toLowerCaseSystem(codePoint);
} }
@Import(module = "runtime", name = "tolower") @Import(module = "runtime", name = "towlower")
private static native int toLowerCaseSystem(int codePoint); private static native int toLowerCaseSystem(int codePoint);
public static char toUpperCase(char ch) { public static char toUpperCase(char ch) {
@ -258,7 +258,7 @@ public class TCharacter extends TObject implements TComparable<TCharacter> {
return toUpperCaseSystem(codePoint); return toUpperCaseSystem(codePoint);
} }
@Import(module = "runtime", name = "toupper") @Import(module = "runtime", name = "towupper")
private static native int toUpperCaseSystem(int codePoint); private static native int toUpperCaseSystem(int codePoint);
public static int digit(char ch, int radix) { public static int digit(char ch, int radix) {

View File

@ -512,7 +512,11 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public T[] getEnumConstants() { 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") @SuppressWarnings("unchecked")

View File

@ -32,6 +32,6 @@ class TConsoleOutputStreamStderr extends TOutputStream {
writeImpl(b); writeImpl(b);
} }
@Import(name = "putchar", module = "runtime") @Import(name = "putwchar", module = "runtime")
static native void writeImpl(int b); static native void writeImpl(int b);
} }

View File

@ -222,15 +222,15 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
} }
@JSBody(params = "v", script = "return isNaN(v);") @JSBody(params = "v", script = "return isNaN(v);")
@Import(module = "runtime", name = "isNaN") @Import(module = "runtime", name = "isnan")
public static native boolean isNaN(double v); public static native boolean isNaN(double v);
@JSBody(script = "return NaN;") @JSBody(script = "return NaN;")
@Import(module = "runtime", name = "getNaN") @Import(module = "runtime", name = "TeaVM_getNaN")
private static native double getNaN(); private static native double getNaN();
@JSBody(params = "v", script = "return !isFinite(v);") @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 native boolean isInfinite(double v);
public static long doubleToRawLongBits(double value) { public static long doubleToRawLongBits(double value) {

View File

@ -90,7 +90,7 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
} }
@JSBody(params = "v", script = "return isNaN(v);") @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 native boolean isNaN(float v);
public static boolean isInfinite(float v) { public static boolean isInfinite(float v) {
@ -98,11 +98,11 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
} }
@JSBody(params = "v", script = "return isFinite(v);") @JSBody(params = "v", script = "return isFinite(v);")
@Import(module = "runtime", name = "isFinite") @Import(module = "runtime", name = "isfinite")
private static native boolean isFinite(float v); private static native boolean isFinite(float v);
@JSBody(script = "return NaN;") @JSBody(script = "return NaN;")
@Import(module = "runtime", name = "getNaN") @Import(module = "runtime", name = "TeaVM_getNaN")
private static native float getNaN(); private static native float getNaN();
public static float parseFloat(TString string) throws TNumberFormatException { public static float parseFloat(TString string) throws TNumberFormatException {

View File

@ -15,6 +15,7 @@
*/ */
package org.teavm.classlib.java.util; package org.teavm.classlib.java.util;
import org.teavm.classlib.PlatformDetector;
import org.teavm.classlib.java.io.TSerializable; import org.teavm.classlib.java.io.TSerializable;
import org.teavm.classlib.java.lang.TMath; import org.teavm.classlib.java.lang.TMath;
import org.teavm.classlib.java.lang.TObject; import org.teavm.classlib.java.lang.TObject;
@ -39,7 +40,7 @@ public class TRandom extends TObject implements TSerializable {
} }
protected int next(int bits) { 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) { public void nextBytes(byte[] bytes) {
@ -53,7 +54,7 @@ public class TRandom extends TObject implements TSerializable {
} }
public int nextInt(int n) { public int nextInt(int n) {
return (int) (random() * n); return (int) (nextDouble() * n);
} }
public long nextLong() { public long nextLong() {
@ -65,13 +66,20 @@ public class TRandom extends TObject implements TSerializable {
} }
public float nextFloat() { public float nextFloat() {
return (float) random(); return (float) nextDouble();
} }
public double 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: * Generate a random number with Gaussian distribution:
* centered around 0 with a standard deviation of 1.0. * centered around 0 with a standard deviation of 1.0.

View File

@ -352,6 +352,7 @@ public class CTarget implements TeaVMTarget {
Set<? extends ValueType> types) { Set<? extends ValueType> types) {
writer.println("int main(int argc, char** argv) {").indent(); writer.println("int main(int argc, char** argv) {").indent();
writer.println("TeaVM_beforeInit();");
writer.println("initHeap(" + minHeapSize + ");"); writer.println("initHeap(" + minHeapSize + ");");
generateVirtualTableHeaders(context, writer, types); generateVirtualTableHeaders(context, writer, types);
generateStringPoolHeaders(context, writer); generateStringPoolHeaders(context, writer);
@ -417,6 +418,6 @@ public class CTarget implements TeaVMTarget {
@Override @Override
public String[] getPlatformTags() { public String[] getPlatformTags() {
return new String[] { PlatformMarkers.C, PlatformMarkers.WEBASSEMBLY }; return new String[] { PlatformMarkers.C, PlatformMarkers.LOW_LEVEL };
} }
} }

View File

@ -22,6 +22,7 @@ import java.util.Arrays;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
import org.teavm.ast.RegularMethodNode; import org.teavm.ast.RegularMethodNode;
import org.teavm.ast.decompilation.Decompiler; import org.teavm.ast.decompilation.Decompiler;
import org.teavm.backend.c.generators.Generator; 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.ClassReaderSource;
import org.teavm.model.ElementModifier; import org.teavm.model.ElementModifier;
import org.teavm.model.FieldHolder; import org.teavm.model.FieldHolder;
import org.teavm.model.FieldReader;
import org.teavm.model.FieldReference; import org.teavm.model.FieldReference;
import org.teavm.model.MethodDescriptor; import org.teavm.model.MethodDescriptor;
import org.teavm.model.MethodHolder; import org.teavm.model.MethodHolder;
@ -276,11 +278,20 @@ public class ClassGenerator {
String name = context.getNames().forClassInstance(type); String name = context.getNames().forClassInstance(type);
vtableForwardWriter.print("static ").print(structName).print(" ").print(name).println(";"); 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(); vtableWriter.print("static alignas(8) ").print(structName).print(" ").print(name).println(" = {").indent();
if (className != null) { if (className != null) {
vtableWriter.println(".parent = {").indent(); vtableWriter.println(".parent = {").indent();
generateRuntimeClassInitializer(type); generateRuntimeClassInitializer(type, enumConstants);
vtableWriter.outdent().println("},"); vtableWriter.outdent().println("},");
VirtualTable virtualTable = context.getVirtualTableProvider().lookup(className); VirtualTable virtualTable = context.getVirtualTableProvider().lookup(className);
@ -301,19 +312,34 @@ public class ClassGenerator {
} }
} }
} else { } else {
generateRuntimeClassInitializer(type); generateRuntimeClassInitializer(type, enumConstants);
} }
vtableWriter.outdent().println("};"); vtableWriter.outdent().println("};");
} }
private void generateRuntimeClassInitializer(ValueType type) { private String writeEnumConstants(ClassReader cls, String baseName) {
List<FieldReader> 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; String sizeExpr;
int tag; int tag;
String parent; String parent;
String itemTypeExpr; String itemTypeExpr;
int flags = 0; int flags = 0;
String layout = "NULL"; String layout = "NULL";
String initFunction = "NULL";
if (type instanceof ValueType.Object) { if (type instanceof ValueType.Object) {
String className = ((ValueType.Object) type).getClassName(); String className = ((ValueType.Object) type).getClassName();
@ -323,13 +349,17 @@ public class ClassGenerator {
className = RuntimeObject.class.getName(); className = RuntimeObject.class.getName();
} }
if (needsData(cls)) { if (cls != null && needsData(cls)) {
String structName = context.getNames().forClass(className); String structName = context.getNames().forClass(className);
sizeExpr = "(int32_t) (intptr_t) ALIGN(sizeof(" + structName + "), sizeof(void*))"; sizeExpr = "(int32_t) (intptr_t) ALIGN(sizeof(" + structName + "), sizeof(void*))";
} else { } else {
sizeExpr = "0"; sizeExpr = "0";
} }
tag = tagRegistry.getRanges(className).get(0).lower; if (cls != null && cls.hasModifier(ElementModifier.ENUM)) {
flags |= RuntimeClass.ENUM;
}
List<TagRegistry.Range> 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())) parent = cls != null && cls.getParent() != null && types.contains(ValueType.object(cls.getParent()))
? "&" + context.getNames().forClassInstance(ValueType.object(cls.getParent())) ? "&" + context.getNames().forClassInstance(ValueType.object(cls.getParent()))
@ -337,6 +367,10 @@ public class ClassGenerator {
itemTypeExpr = "NULL"; itemTypeExpr = "NULL";
int layoutOffset = classLayoutOffsets.getOrDefault(className, -1); int layoutOffset = classLayoutOffsets.getOrDefault(className, -1);
layout = layoutOffset >= 0 ? "classLayouts + " + layoutOffset : "NULL"; layout = layoutOffset >= 0 ? "classLayouts + " + layoutOffset : "NULL";
if (cls != null && needsInitializer(cls)) {
initFunction = context.getNames().forClassInitializer(className);
}
} else if (type instanceof ValueType.Array) { } else if (type instanceof ValueType.Array) {
parent = "&" + context.getNames().forClassInstance(ValueType.object("java.lang.Object")); parent = "&" + context.getNames().forClassInstance(ValueType.object("java.lang.Object"));
tag = tagRegistry.getRanges("java.lang.Object").get(0).lower; 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("isSupertypeOf")).println(" = &" + superTypeFunction + ",");
vtableWriter.print(".").print(classFieldName("parent")).println(" = " + parent + ","); vtableWriter.print(".").print(classFieldName("parent")).println(" = " + parent + ",");
vtableWriter.print(".").print(classFieldName("enumValues")).println(" = NULL,"); 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) { private void generateVirtualTableStructure(ClassReader cls) {
@ -392,13 +428,15 @@ public class ClassGenerator {
vtableStructuresWriter.println("JavaClass parent;"); vtableStructuresWriter.println("JavaClass parent;");
VirtualTable virtualTable = context.getVirtualTableProvider().lookup(cls.getName()); VirtualTable virtualTable = context.getVirtualTableProvider().lookup(cls.getName());
for (VirtualTableEntry entry : virtualTable.getEntries().values()) { if (virtualTable != null) {
String methodName = context.getNames().forVirtualMethod( for (VirtualTableEntry entry : virtualTable.getEntries().values()) {
new MethodReference(cls.getName(), entry.getMethod())); String methodName = context.getNames().forVirtualMethod(
vtableStructuresWriter.printType(entry.getMethod().getResultType()) new MethodReference(cls.getName(), entry.getMethod()));
.print(" (*").print(methodName).print(")("); vtableStructuresWriter.printType(entry.getMethod().getResultType())
codeGenerator.generateMethodParameters(vtableStructuresWriter, entry.getMethod(), false, false); .print(" (*").print(methodName).print(")(");
vtableStructuresWriter.println(");"); codeGenerator.generateMethodParameters(vtableStructuresWriter, entry.getMethod(), false, false);
vtableStructuresWriter.println(");");
}
} }
vtableStructuresWriter.outdent().print("} ").print(name).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()) return !context.getCharacteristics().isStaticInit(cls.getName())
&& !context.getCharacteristics().isStructure(cls.getName()) && !context.getCharacteristics().isStructure(cls.getName())
&& cls.getMethod(new MethodDescriptor("<clinit>", ValueType.VOID)) != null; && cls.getMethod(new MethodDescriptor("<clinit>", ValueType.VOID)) != null;

View File

@ -266,13 +266,48 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
int index = context.getStringPool().getStringIndex((String) value); int index = context.getStringPool().getStringIndex((String) value);
writer.print("(stringPool + " + index + ")"); writer.print("(stringPool + " + index + ")");
} else if (value instanceof Integer) { } 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) { } 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) { } 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) { } 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) { } else if (value instanceof Boolean) {
writer.print((Boolean) value ? "1" : "0"); writer.print((Boolean) value ? "1" : "0");
} else if (value instanceof ValueType) { } 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 @Override
public void visit(VariableExpr expr) { public void visit(VariableExpr expr) {
if (expr.getIndex() == 0) { if (expr.getIndex() == 0) {

View File

@ -24,26 +24,40 @@ public class PlatformClassMetadataIntrinsic implements Intrinsic {
private static final String PLATFORM_CLASS_METADATA = "org.teavm.platform.PlatformClassMetadata"; private static final String PLATFORM_CLASS_METADATA = "org.teavm.platform.PlatformClassMetadata";
private static final FieldReference ARRAY_TYPE_FIELD = new FieldReference( private static final FieldReference ARRAY_TYPE_FIELD = new FieldReference(
RuntimeClass.class.getName(), "arrayType"); RuntimeClass.class.getName(), "arrayType");
private static final FieldReference SUPERCLASS_FIELD = new FieldReference(
RuntimeClass.class.getName(), "parent");
@Override @Override
public boolean canHandle(MethodReference method) { public boolean canHandle(MethodReference method) {
if (!method.getClassName().equals(PLATFORM_CLASS_METADATA)) { if (!method.getClassName().equals(PLATFORM_CLASS_METADATA)) {
return false; return false;
} }
return method.getName().equals("getArrayItem"); switch (method.getName()) {
case "getArrayItem":
case "getSuperclass":
return true;
}
return false;
} }
@Override @Override
public void apply(IntrinsicContext context, InvocationExpr invocation) { public void apply(IntrinsicContext context, InvocationExpr invocation) {
switch (invocation.getMethod().getName()) { switch (invocation.getMethod().getName()) {
case "getArrayItem": case "getArrayItem":
context.writer().print("FIELD("); printFieldAccess(context, invocation, ARRAY_TYPE_FIELD);
context.emit(invocation.getArguments().get(0)); break;
context.writer().print(","); case "getSuperclass":
context.writer().print(context.names().forClass(ARRAY_TYPE_FIELD.getClassName())).print(", "); printFieldAccess(context, invocation, SUPERCLASS_FIELD);
context.writer().print(context.names().forMemberField(ARRAY_TYPE_FIELD));
context.writer().print(")");
break; 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(")");
}
} }

View File

@ -42,8 +42,6 @@ public class PlatformIntrinsic implements Intrinsic {
case "asJavaClass": case "asJavaClass":
context.emit(invocation.getArguments().get(0)); context.emit(invocation.getArguments().get(0));
break; break;
case "getName":
} }
} }
} }

View File

@ -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();
}

View File

@ -43,6 +43,7 @@ public class RuntimeClass extends RuntimeObject {
public RuntimeClass itemType; public RuntimeClass itemType;
public RuntimeClass arrayType; public RuntimeClass arrayType;
public IsSupertypeFunction isSupertypeOf; public IsSupertypeFunction isSupertypeOf;
public InitFunction init;
public RuntimeClass parent; public RuntimeClass parent;
public Address enumValues; public Address enumValues;
public Address layout; public Address layout;

View File

@ -2,7 +2,9 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <uchar.h> #include <uchar.h>
#include <wchar.h>
#include <time.h> #include <time.h>
#include <math.h> #include <math.h>
@ -87,6 +89,18 @@ static int32_t gc_regionSize = INT32_C(32768);
static int32_t gc_regionMaxCount = INT32_C(0); static int32_t gc_regionMaxCount = INT32_C(0);
static int64_t gc_availableBytes = INT64_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__ #ifdef __GNUC__
static void initHeap(int64_t heapSize) { static void initHeap(int64_t heapSize) {
long workSize = heapSize / 16; long workSize = heapSize / 16;

View File

@ -112,8 +112,16 @@ public final class Platform {
@PluggableDependency(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class)
@InjectedBy(PlatformGenerator.class) @InjectedBy(PlatformGenerator.class)
@DelegateTo("initClassLowLevel")
public static native void initClass(PlatformClass cls); public static native void initClass(PlatformClass cls);
@Unmanaged
private static void initClassLowLevel(RuntimeClass cls) {
if (cls.init != null) {
cls.init.run();
}
}
@InjectedBy(PlatformGenerator.class) @InjectedBy(PlatformGenerator.class)
@PluggableDependency(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class)
public static native PlatformClass classFromResource(ClassResource resource); public static native PlatformClass classFromResource(ClassResource resource);

View File

@ -15,17 +15,20 @@
*/ */
package org.teavm.platform; package org.teavm.platform;
import org.teavm.interop.Unmanaged;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
import org.teavm.jso.JSProperty; import org.teavm.jso.JSProperty;
public interface PlatformClassMetadata extends JSObject { public interface PlatformClassMetadata extends JSObject {
@JSProperty("item") @JSProperty("item")
@Unmanaged
PlatformClass getArrayItem(); PlatformClass getArrayItem();
@JSProperty @JSProperty
PlatformSequence<PlatformClass> getSupertypes(); PlatformSequence<PlatformClass> getSupertypes();
@JSProperty @JSProperty
@Unmanaged
PlatformClass getSuperclass(); PlatformClass getSuperclass();
@JSProperty @JSProperty