From f7296e038981fac81f0c9932b2dc27fe385c7054 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 8 Sep 2016 14:47:48 +0300 Subject: [PATCH] Add static GC roots --- .../wasm/generate/WasmClassGenerator.java | 34 +++++++++++++++++-- .../java/org/teavm/runtime/Allocator.java | 4 ++- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/WasmClassGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/WasmClassGenerator.java index 0893ccc6d..91dfcc077 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/WasmClassGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/WasmClassGenerator.java @@ -30,6 +30,7 @@ import org.teavm.backend.wasm.binary.DataPrimitives; import org.teavm.backend.wasm.binary.DataStructure; import org.teavm.backend.wasm.binary.DataType; import org.teavm.backend.wasm.binary.DataValue; +import org.teavm.common.IntegerArray; import org.teavm.interop.Address; import org.teavm.interop.Function; import org.teavm.interop.Structure; @@ -70,6 +71,8 @@ public class WasmClassGenerator { DataPrimitives.INT, /* isInstance function */ DataPrimitives.ADDRESS, /* parent */ DataPrimitives.ADDRESS /* layout */); + private IntegerArray staticGcRoots = new IntegerArray(1); + private int staticGcRootsAddress; private static final int CLASS_SIZE = 1; private static final int CLASS_FLAGS = 2; @@ -203,10 +206,9 @@ public class WasmClassGenerator { List fields = getReferenceFields(binaryData.cls); if (!fields.isEmpty()) { - header.setAddress(CLASS_LAYOUT, binaryWriter.getAddress()); DataValue layoutSize = DataPrimitives.SHORT.createValue(); layoutSize.setShort(0, (short) fields.size()); - binaryWriter.append(layoutSize); + header.setAddress(CLASS_LAYOUT, binaryWriter.append(layoutSize)); for (FieldReference field : fields) { DataValue layoutElement = DataPrimitives.SHORT.createValue(); layoutElement.setShort(0, (short) binaryData.fieldLayout.get(field.getFieldName())); @@ -214,6 +216,10 @@ public class WasmClassGenerator { } } + for (FieldReference field : getStaticReferenceFields(binaryData.cls)) { + staticGcRoots.add(binaryData.fieldLayout.get(field.getFieldName())); + } + return vtable != null ? wrapper : header; } @@ -225,6 +231,14 @@ public class WasmClassGenerator { .collect(Collectors.toList()); } + private List getStaticReferenceFields(ClassReader cls) { + return cls.getFields().stream() + .filter(field -> field.hasModifier(ElementModifier.STATIC)) + .filter(field -> !(field.getType() instanceof ValueType.Primitive)) + .map(field -> field.getReference()) + .collect(Collectors.toList()); + } + private void fillVirtualTable(VirtualTable vtable, DataValue array) { int index = 0; for (VirtualTableEntry vtableEntry : vtable.getEntries().values()) { @@ -392,6 +406,22 @@ public class WasmClassGenerator { } } } + writeStaticGcRoots(); + } + + public int getStaticGcRootsAddress() { + return staticGcRootsAddress; + } + + private void writeStaticGcRoots() { + DataValue sizeValue = DataPrimitives.LONG.createValue(); + sizeValue.setLong(0, staticGcRoots.size()); + staticGcRootsAddress = binaryWriter.append(sizeValue); + for (int gcRoot : staticGcRoots.getAll()) { + DataValue value = DataPrimitives.ADDRESS.createValue(); + value.setAddress(0, gcRoot); + binaryWriter.append(value); + } } public boolean hasClinit(String className) { diff --git a/core/src/main/java/org/teavm/runtime/Allocator.java b/core/src/main/java/org/teavm/runtime/Allocator.java index 19d485328..924b71b53 100644 --- a/core/src/main/java/org/teavm/runtime/Allocator.java +++ b/core/src/main/java/org/teavm/runtime/Allocator.java @@ -24,7 +24,7 @@ public final class Allocator { private Allocator() { } - private static Address address = initialize(); + static Address address = initialize(); private static native Address initialize(); @@ -64,4 +64,6 @@ public final class Allocator { public static native void removeGcRoot(int index); public static native void releaseStack(int size); + + public static native Address getStaticGcRoots(); }