mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-03 05:44:10 -08:00
Add class field layout for GC
This commit is contained in:
parent
476086af47
commit
f79716d53d
|
@ -23,6 +23,7 @@ import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import org.teavm.backend.wasm.binary.BinaryWriter;
|
import org.teavm.backend.wasm.binary.BinaryWriter;
|
||||||
import org.teavm.backend.wasm.binary.DataArray;
|
import org.teavm.backend.wasm.binary.DataArray;
|
||||||
import org.teavm.backend.wasm.binary.DataPrimitives;
|
import org.teavm.backend.wasm.binary.DataPrimitives;
|
||||||
|
@ -54,7 +55,6 @@ public class WasmClassGenerator {
|
||||||
private List<String> functionTable = new ArrayList<>();
|
private List<String> functionTable = new ArrayList<>();
|
||||||
private VirtualTableProvider vtableProvider;
|
private VirtualTableProvider vtableProvider;
|
||||||
private TagRegistry tagRegistry;
|
private TagRegistry tagRegistry;
|
||||||
private boolean isSubtypeGenerated;
|
|
||||||
private DataStructure objectStructure = new DataStructure((byte) 0,
|
private DataStructure objectStructure = new DataStructure((byte) 0,
|
||||||
DataPrimitives.INT, /* class */
|
DataPrimitives.INT, /* class */
|
||||||
DataPrimitives.ADDRESS /* monitor/hash code */);
|
DataPrimitives.ADDRESS /* monitor/hash code */);
|
||||||
|
@ -67,7 +67,19 @@ public class WasmClassGenerator {
|
||||||
DataPrimitives.INT, /* canary */
|
DataPrimitives.INT, /* canary */
|
||||||
DataPrimitives.ADDRESS, /* item type */
|
DataPrimitives.ADDRESS, /* item type */
|
||||||
DataPrimitives.ADDRESS, /* array type */
|
DataPrimitives.ADDRESS, /* array type */
|
||||||
DataPrimitives.INT /* isInstance function */);
|
DataPrimitives.INT, /* isInstance function */
|
||||||
|
DataPrimitives.ADDRESS, /* parent */
|
||||||
|
DataPrimitives.ADDRESS /* layout */);
|
||||||
|
|
||||||
|
private static final int CLASS_SIZE = 1;
|
||||||
|
private static final int CLASS_FLAGS = 2;
|
||||||
|
private static final int CLASS_TAG = 3;
|
||||||
|
private static final int CLASS_CANARY = 4;
|
||||||
|
private static final int CLASS_ITEM_TYPE = 5;
|
||||||
|
private static final int CLASS_ARRAY_TYPE = 6;
|
||||||
|
private static final int CLASS_IS_INSTANCE = 7;
|
||||||
|
private static final int CLASS_PARENT = 8;
|
||||||
|
private static final int CLASS_LAYOUT = 9;
|
||||||
|
|
||||||
public WasmClassGenerator(ClassReaderSource classSource, VirtualTableProvider vtableProvider,
|
public WasmClassGenerator(ClassReaderSource classSource, VirtualTableProvider vtableProvider,
|
||||||
TagRegistry tagRegistry, BinaryWriter binaryWriter) {
|
TagRegistry tagRegistry, BinaryWriter binaryWriter) {
|
||||||
|
@ -136,21 +148,21 @@ public class WasmClassGenerator {
|
||||||
|
|
||||||
binaryData.size = 4;
|
binaryData.size = 4;
|
||||||
binaryData.data = wrapper.getValue(0);
|
binaryData.data = wrapper.getValue(0);
|
||||||
binaryData.data.setInt(1, 4);
|
binaryData.data.setInt(CLASS_SIZE, 4);
|
||||||
binaryData.data.setAddress(5, itemBinaryData.start);
|
binaryData.data.setAddress(CLASS_ITEM_TYPE, itemBinaryData.start);
|
||||||
binaryData.data.setInt(7, functionTable.size());
|
binaryData.data.setInt(CLASS_IS_INSTANCE, functionTable.size());
|
||||||
functionTable.add(WasmMangling.mangeIsSupertype(type));
|
functionTable.add(WasmMangling.mangeIsSupertype(type));
|
||||||
binaryData.start = binaryWriter.append(vtableSize > 0 ? wrapper : binaryData.data);
|
binaryData.start = binaryWriter.append(vtableSize > 0 ? wrapper : binaryData.data);
|
||||||
|
|
||||||
itemBinaryData.data.setAddress(6, binaryData.start);
|
itemBinaryData.data.setAddress(CLASS_ARRAY_TYPE, binaryData.start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataValue createPrimitiveClassData(int size, ValueType type) {
|
private DataValue createPrimitiveClassData(int size, ValueType type) {
|
||||||
DataValue value = classStructure.createValue();
|
DataValue value = classStructure.createValue();
|
||||||
value.setInt(1, size);
|
value.setInt(CLASS_SIZE, size);
|
||||||
value.setInt(2, RuntimeClass.PRIMITIVE);
|
value.setInt(CLASS_FLAGS, RuntimeClass.PRIMITIVE);
|
||||||
value.setInt(7, functionTable.size());
|
value.setInt(CLASS_IS_INSTANCE, functionTable.size());
|
||||||
functionTable.add(WasmMangling.mangeIsSupertype(type));
|
functionTable.add(WasmMangling.mangeIsSupertype(type));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -160,6 +172,11 @@ public class WasmClassGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private DataValue createStructure(ClassBinaryData binaryData) {
|
private DataValue createStructure(ClassBinaryData binaryData) {
|
||||||
|
String parent = binaryData.cls.getParent();
|
||||||
|
int parentPtr = !binaryData.isInferface && parent != null
|
||||||
|
? getClassPointer(ValueType.object(binaryData.cls.getParent()))
|
||||||
|
: 0;
|
||||||
|
|
||||||
String name = ((ValueType.Object) binaryData.type).getClassName();
|
String name = ((ValueType.Object) binaryData.type).getClassName();
|
||||||
|
|
||||||
VirtualTable vtable = vtableProvider.lookup(name);
|
VirtualTable vtable = vtableProvider.lookup(name);
|
||||||
|
@ -171,21 +188,43 @@ public class WasmClassGenerator {
|
||||||
DataValue header = wrapper.getValue(0);
|
DataValue header = wrapper.getValue(0);
|
||||||
binaryData.data = header;
|
binaryData.data = header;
|
||||||
|
|
||||||
header.setInt(1, binaryData.size);
|
header.setInt(CLASS_SIZE, binaryData.size);
|
||||||
List<TagRegistry.Range> ranges = tagRegistry.getRanges(name);
|
List<TagRegistry.Range> ranges = tagRegistry.getRanges(name);
|
||||||
int tag = ranges.stream().mapToInt(range -> range.lower).min().orElse(0);
|
int tag = ranges.stream().mapToInt(range -> range.lower).min().orElse(0);
|
||||||
header.setInt(3, tag);
|
header.setInt(CLASS_TAG, tag);
|
||||||
header.setInt(4, RuntimeClass.computeCanary(binaryData.size, tag));
|
header.setInt(CLASS_CANARY, RuntimeClass.computeCanary(binaryData.size, tag));
|
||||||
header.setInt(7, functionTable.size());
|
header.setInt(CLASS_IS_INSTANCE, functionTable.size());
|
||||||
functionTable.add(WasmMangling.mangeIsSupertype(ValueType.object(name)));
|
functionTable.add(WasmMangling.mangeIsSupertype(ValueType.object(name)));
|
||||||
|
header.setAddress(CLASS_PARENT, parentPtr);
|
||||||
|
|
||||||
if (vtable != null) {
|
if (vtable != null) {
|
||||||
fillVirtualTable(vtable, array);
|
fillVirtualTable(vtable, array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<FieldReference> 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);
|
||||||
|
for (FieldReference field : fields) {
|
||||||
|
DataValue layoutElement = DataPrimitives.SHORT.createValue();
|
||||||
|
layoutElement.setShort(0, (short) binaryData.fieldLayout.get(field.getFieldName()));
|
||||||
|
binaryWriter.append(layoutElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return vtable != null ? wrapper : header;
|
return vtable != null ? wrapper : header;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<FieldReference> getReferenceFields(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) {
|
private void fillVirtualTable(VirtualTable vtable, DataValue array) {
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (VirtualTableEntry vtableEntry : vtable.getEntries().values()) {
|
for (VirtualTableEntry vtableEntry : vtable.getEntries().values()) {
|
||||||
|
@ -275,6 +314,9 @@ public class WasmClassGenerator {
|
||||||
data.alignment = 4;
|
data.alignment = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.isInferface = cls.hasModifier(ElementModifier.INTERFACE);
|
||||||
|
data.cls = cls;
|
||||||
|
|
||||||
for (FieldReader field : cls.getFields()) {
|
for (FieldReader field : cls.getFields()) {
|
||||||
int desiredAlignment = getDesiredAlignment(field.getType());
|
int desiredAlignment = getDesiredAlignment(field.getType());
|
||||||
if (field.hasModifier(ElementModifier.STATIC)) {
|
if (field.hasModifier(ElementModifier.STATIC)) {
|
||||||
|
@ -368,8 +410,10 @@ public class WasmClassGenerator {
|
||||||
int size;
|
int size;
|
||||||
int alignment;
|
int alignment;
|
||||||
int start;
|
int start;
|
||||||
|
boolean isInferface;
|
||||||
ObjectIntMap<String> fieldLayout = new ObjectIntOpenHashMap<>();
|
ObjectIntMap<String> fieldLayout = new ObjectIntOpenHashMap<>();
|
||||||
DataValue data;
|
DataValue data;
|
||||||
|
ClassReader cls;
|
||||||
boolean function;
|
boolean function;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,8 @@ public class RuntimeClass extends RuntimeJavaObject {
|
||||||
public RuntimeClass itemType;
|
public RuntimeClass itemType;
|
||||||
public RuntimeClass arrayType;
|
public RuntimeClass arrayType;
|
||||||
public IsSupertypeFunction isSupertypeOf;
|
public IsSupertypeFunction isSupertypeOf;
|
||||||
|
public RuntimeClass parent;
|
||||||
|
public Address layout;
|
||||||
|
|
||||||
@NoGC
|
@NoGC
|
||||||
public static int computeCanary(int size, int tag) {
|
public static int computeCanary(int size, int tag) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user