mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Fix bugs in C backend to make more tests pass
This commit is contained in:
parent
4990dbe8e4
commit
8f0320e217
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,7 +242,7 @@ public class TCharacter extends TObject implements TComparable<TCharacter> {
|
|||
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<TCharacter> {
|
|||
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) {
|
||||
|
|
|
@ -512,7 +512,11 @@ public class TClass<T> 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")
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -222,15 +222,15 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
|||
}
|
||||
|
||||
@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) {
|
||||
|
|
|
@ -90,7 +90,7 @@ public class TFloat extends TNumber implements TComparable<TFloat> {
|
|||
}
|
||||
|
||||
@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<TFloat> {
|
|||
}
|
||||
|
||||
@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 {
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -352,6 +352,7 @@ public class CTarget implements TeaVMTarget {
|
|||
Set<? extends ValueType> 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 };
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<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;
|
||||
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<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()))
|
||||
? "&" + 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("<clinit>", ValueType.VOID)) != null;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(")");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,8 +42,6 @@ public class PlatformIntrinsic implements Intrinsic {
|
|||
case "asJavaClass":
|
||||
context.emit(invocation.getArguments().get(0));
|
||||
break;
|
||||
case "getName":
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
24
core/src/main/java/org/teavm/runtime/InitFunction.java
Normal file
24
core/src/main/java/org/teavm/runtime/InitFunction.java
Normal 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();
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <uchar.h>
|
||||
#include <wchar.h>
|
||||
#include <time.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 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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<PlatformClass> getSupertypes();
|
||||
|
||||
@JSProperty
|
||||
@Unmanaged
|
||||
PlatformClass getSuperclass();
|
||||
|
||||
@JSProperty
|
||||
|
|
Loading…
Reference in New Issue
Block a user