diff --git a/core/src/main/java/org/teavm/backend/c/intrinsic/GCIntrinsic.java b/core/src/main/java/org/teavm/backend/c/intrinsic/GCIntrinsic.java index 19057b495..aa378d228 100644 --- a/core/src/main/java/org/teavm/backend/c/intrinsic/GCIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/c/intrinsic/GCIntrinsic.java @@ -39,6 +39,7 @@ public class GCIntrinsic implements Intrinsic { case "resizeHeap": case "cardTable": case "writeBarrier": + case "canShrinkHeap": return true; default: return false; @@ -60,6 +61,10 @@ public class GCIntrinsic implements Intrinsic { context.writer().print(")"); break; + case "canShrinkHeap": + context.writer().print("1"); + break; + default: context.includes().includePath("heaptrace.h"); context.writer().print("teavm_gc_").print(invocation.getMethod().getName()); diff --git a/core/src/main/java/org/teavm/backend/wasm/intrinsics/GCIntrinsic.java b/core/src/main/java/org/teavm/backend/wasm/intrinsics/GCIntrinsic.java index 43c3e6d65..c510ab536 100644 --- a/core/src/main/java/org/teavm/backend/wasm/intrinsics/GCIntrinsic.java +++ b/core/src/main/java/org/teavm/backend/wasm/intrinsics/GCIntrinsic.java @@ -72,6 +72,7 @@ public class GCIntrinsic implements WasmIntrinsic { case "maxAvailableBytes": case "resizeHeap": case "writeBarrier": + case "canShrinkHeap": return true; default: return false; @@ -131,6 +132,12 @@ public class GCIntrinsic implements WasmIntrinsic { cardIndex); return new WasmStoreInt32(1, card, new WasmInt32Constant(0), WasmInt32Subtype.INT8); } + case "canShrinkHeap": { + var expr = new WasmInt32Constant(0); + expr.setLocation(invocation.getLocation()); + return expr; + } + default: throw new IllegalArgumentException(invocation.getMethod().toString()); } diff --git a/core/src/main/java/org/teavm/runtime/GC.java b/core/src/main/java/org/teavm/runtime/GC.java index c5a58d542..5cf7027f7 100644 --- a/core/src/main/java/org/teavm/runtime/GC.java +++ b/core/src/main/java/org/teavm/runtime/GC.java @@ -67,6 +67,8 @@ public final class GC { public static native void resizeHeap(long size); + public static native boolean canShrinkHeap(); + private static native int regionSize(); public static native void writeBarrier(RuntimeObject object); @@ -183,7 +185,8 @@ public final class GC { } if (!isFullGC) { - if (++youngGCCount >= 8 && isAboutToExpand(minRequestedSize)) { + var youngGCLimit = canShrinkHeap() ? 2 : 8; + if (++youngGCCount >= youngGCLimit && isAboutToExpand(minRequestedSize)) { triggerFullGC(); doCollectGarbage(); youngGCCount = 0; @@ -1387,7 +1390,7 @@ public final class GC { freeChunks++; totalChunks++; } - } else { + } else if (canShrinkHeap()) { long minimumSize = lastChunk.toAddress().toLong() - heapAddress().toLong(); if (lastChunk.classReference != 0) { minimumSize += objectSize(lastChunk);