From 67098a60efa56eb3f5e1da3688816f499b5b9292 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 15 Sep 2016 16:34:06 +0300 Subject: [PATCH] Fix bugs in GC and runtime --- .../org/teavm/classlib/java/lang/TSystem.java | 9 +++++++ .../java/org/teavm/backend/wasm/Example.java | 25 +++++++++++++++++++ .../backend/wasm/binary/BinaryWriter.java | 14 +++++------ .../backend/wasm/generate/WasmGenerator.java | 1 + core/src/main/java/org/teavm/runtime/GC.java | 22 +++++++++++----- 5 files changed, 58 insertions(+), 13 deletions(-) diff --git a/classlib/src/main/java/org/teavm/classlib/java/lang/TSystem.java b/classlib/src/main/java/org/teavm/classlib/java/lang/TSystem.java index cbe3d6f94..a60402038 100644 --- a/classlib/src/main/java/org/teavm/classlib/java/lang/TSystem.java +++ b/classlib/src/main/java/org/teavm/classlib/java/lang/TSystem.java @@ -23,6 +23,7 @@ import org.teavm.dependency.PluggableDependency; import org.teavm.backend.javascript.spi.GeneratedBy; import org.teavm.interop.Address; import org.teavm.interop.DelegateTo; +import org.teavm.interop.Import; import org.teavm.interop.NoGC; import org.teavm.interop.Structure; import org.teavm.runtime.Allocator; @@ -98,8 +99,16 @@ public final class TSystem extends TObject { } @GeneratedBy(SystemNativeGenerator.class) + @DelegateTo(("currentTimeMillisLowLevel")) public static native long currentTimeMillis(); + private static long currentTimeMillisLowLevel() { + return (long) currentTimeMillisImpl(); + } + + @Import(name = "currentTimeMillis", module = "runtime") + private static native double currentTimeMillisImpl(); + public static TString getProperty(@SuppressWarnings("unused") TString key) { // TODO: make implementation return null; diff --git a/core/src/main/java/org/teavm/backend/wasm/Example.java b/core/src/main/java/org/teavm/backend/wasm/Example.java index dd83958a2..b77823956 100644 --- a/core/src/main/java/org/teavm/backend/wasm/Example.java +++ b/core/src/main/java/org/teavm/backend/wasm/Example.java @@ -15,6 +15,7 @@ */ package org.teavm.backend.wasm; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -36,9 +37,33 @@ public final class Example { testArrayCopy(); testArrayIsObject(); testIsAssignableFrom(); + testBigInteger(); testGC(); } + private static void testBigInteger() { + BigInteger result = BigInteger.ONE; + for (int j = 0; j < 100; ++j) { + long start = System.currentTimeMillis(); + + for (int k = 0; k < 5000; ++k) { + BigInteger a = BigInteger.ZERO; + BigInteger b = BigInteger.ONE; + for (int i = 0; i < 1000; ++i) { + BigInteger c = a.add(b); + a = b; + b = c; + } + result = a; + } + + long end = System.currentTimeMillis(); + + println("Operation took " + (end - start) + " milliseconds"); + } + println(result.toString()); + } + private static void testFibonacci() { int a = 0; int b = 1; diff --git a/core/src/main/java/org/teavm/backend/wasm/binary/BinaryWriter.java b/core/src/main/java/org/teavm/backend/wasm/binary/BinaryWriter.java index 47a8a5055..79a089a03 100644 --- a/core/src/main/java/org/teavm/backend/wasm/binary/BinaryWriter.java +++ b/core/src/main/java/org/teavm/backend/wasm/binary/BinaryWriter.java @@ -163,14 +163,14 @@ public class BinaryWriter { private int writeLong(int offset, byte[] result, long v) { offset = align(offset, 8); - result[offset++] = (byte) (v >> 56); - result[offset++] = (byte) (v >> 48); - result[offset++] = (byte) (v >> 40); - result[offset++] = (byte) (v >> 32); - result[offset++] = (byte) (v >> 24); - result[offset++] = (byte) (v >> 16); - result[offset++] = (byte) (v >> 8); result[offset++] = (byte) v; + result[offset++] = (byte) (v >> 8); + result[offset++] = (byte) (v >> 16); + result[offset++] = (byte) (v >> 24); + result[offset++] = (byte) (v >> 32); + result[offset++] = (byte) (v >> 40); + result[offset++] = (byte) (v >> 48); + result[offset++] = (byte) (v >> 56); return offset; } } diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerator.java index 0aac90820..04bbd88d0 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerator.java @@ -78,6 +78,7 @@ public class WasmGenerator { WasmType paramType = WasmGeneratorUtil.mapType(methodReference.parameterType(i)); function.getParameters().add(paramType); } + function.setResult(WasmGeneratorUtil.mapType(methodReference.getReturnType())); WasmGenerationContext.ImportedMethod importedMethod = context.getImportedMethod(methodReference); if (importedMethod != null) { diff --git a/core/src/main/java/org/teavm/runtime/GC.java b/core/src/main/java/org/teavm/runtime/GC.java index 2f866ff20..2e671c449 100644 --- a/core/src/main/java/org/teavm/runtime/GC.java +++ b/core/src/main/java/org/teavm/runtime/GC.java @@ -59,15 +59,18 @@ public final class GC { public static RuntimeObject alloc(int size) { FreeChunk current = currentChunk; Address next = currentChunk.toAddress().add(size); - if (!next.add(Structure.sizeOf(FreeChunk.class) + 1).isLessThan(currentChunkLimit)) { + if (!next.add(Structure.sizeOf(FreeChunk.class)).isLessThan(currentChunkLimit)) { getAvailableChunk(size); current = currentChunk; next = currentChunk.toAddress().add(size); } - int oldSize = current.size; + int freeSize = current.size; currentChunk = next.toStructure(); - currentChunk.classReference = 0; - currentChunk.size = oldSize - size; + freeSize -= size; + if (freeSize > 0) { + currentChunk.classReference = 0; + currentChunk.size = freeSize; + } return current; } @@ -80,7 +83,13 @@ public final class GC { } private static boolean getAvailableChunkIfPossible(int size) { - while (!currentChunk.toAddress().add(size).isLessThan(currentChunkLimit)) { + while (true) { + if (currentChunk.toAddress().add(size) == currentChunkLimit) { + break; + } + if (currentChunk.toAddress().add(size + Structure.sizeOf(FreeChunk.class)).isLessThan(currentChunkLimit)) { + break; + } if (--freeChunks == 0) { return false; } @@ -104,10 +113,11 @@ public final class GC { int staticCount = staticRoots.getInt(); staticRoots.add(8); while (staticCount-- > 0) { - RuntimeObject object = staticRoots.getAddress().toStructure(); + RuntimeObject object = staticRoots.getAddress().getAddress().toStructure(); if (object != null) { mark(object); } + staticRoots = staticRoots.add(Address.sizeOf()); } for (Address stackRoots = Mutator.getStackGcRoots(); stackRoots != null;