mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
C/Wasm: fix bugs in GC
This commit is contained in:
parent
70cb67c8f0
commit
f7620704fc
|
@ -1077,10 +1077,7 @@ public class ClassGenerator {
|
|||
public static boolean needsVirtualTable(Characteristics characteristics, ValueType type) {
|
||||
if (type instanceof ValueType.Object) {
|
||||
String className = ((ValueType.Object) type).getClassName();
|
||||
if (className.equals(Address.class.getName())) {
|
||||
return false;
|
||||
}
|
||||
return !characteristics.isStructure(className);
|
||||
return characteristics.isManaged(className);
|
||||
} else if (type instanceof ValueType.Array) {
|
||||
return needsVirtualTable(characteristics, ((ValueType.Array) type).getItemType());
|
||||
} else {
|
||||
|
|
|
@ -95,8 +95,14 @@ public final class CodeGeneratorUtil {
|
|||
} else if (value instanceof Character) {
|
||||
writeIntValue(writer, (char) value);
|
||||
} else if (value instanceof ValueType) {
|
||||
includes.includeType((ValueType) value);
|
||||
writer.print("&").print(context.getNames().forClassInstance((ValueType) value));
|
||||
ValueType type = (ValueType) value;
|
||||
if (type instanceof ValueType.Object
|
||||
&& !context.getCharacteristics().isManaged(((ValueType.Object) type).getClassName())) {
|
||||
writer.print("NULL");
|
||||
} else {
|
||||
includes.includeType(type);
|
||||
writer.print("&").print(context.getNames().forClassInstance(type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ public class MutatorIntrinsic implements Intrinsic {
|
|||
|
||||
switch (method.getName()) {
|
||||
case "getStaticGCRoots":
|
||||
case "getClasses":
|
||||
case "getClassCount":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -40,6 +42,12 @@ public class MutatorIntrinsic implements Intrinsic {
|
|||
case "getStaticGCRoots":
|
||||
context.writer().print("teavm_gc_staticRoots");
|
||||
break;
|
||||
case "getClasses":
|
||||
context.writer().print("teavm_classReferences");
|
||||
break;
|
||||
case "getClassCount":
|
||||
context.writer().print("teavm_classReferencesCount");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -403,6 +403,8 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
|
|||
generateIsSupertypeFunctions(tagRegistry, module, classGenerator);
|
||||
classGenerator.postProcess();
|
||||
mutatorIntrinsic.setStaticGcRootsAddress(classGenerator.getStaticGcRootsAddress());
|
||||
mutatorIntrinsic.setClassesAddress(classGenerator.getClassesAddress());
|
||||
mutatorIntrinsic.setClassCount(classGenerator.getClassCount());
|
||||
|
||||
WasmMemorySegment dataSegment = new WasmMemorySegment();
|
||||
dataSegment.setData(binaryWriter.getData());
|
||||
|
|
|
@ -88,6 +88,8 @@ public class WasmClassGenerator {
|
|||
DataPrimitives.ADDRESS /* canonical name cache */);
|
||||
private IntegerArray staticGcRoots = new IntegerArray(1);
|
||||
private int staticGcRootsAddress;
|
||||
private int classesAddress;
|
||||
private int classCount;
|
||||
|
||||
private static final int CLASS_SIZE = 1;
|
||||
private static final int CLASS_FLAGS = 2;
|
||||
|
@ -618,12 +620,21 @@ public class WasmClassGenerator {
|
|||
}
|
||||
}
|
||||
writeStaticGcRoots();
|
||||
writeClasses();
|
||||
}
|
||||
|
||||
public int getStaticGcRootsAddress() {
|
||||
return staticGcRootsAddress;
|
||||
}
|
||||
|
||||
public int getClassesAddress() {
|
||||
return classesAddress;
|
||||
}
|
||||
|
||||
public int getClassCount() {
|
||||
return classCount;
|
||||
}
|
||||
|
||||
private void writeStaticGcRoots() {
|
||||
DataValue sizeValue = DataPrimitives.LONG.createValue();
|
||||
sizeValue.setLong(0, staticGcRoots.size());
|
||||
|
@ -635,6 +646,21 @@ public class WasmClassGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
private void writeClasses() {
|
||||
for (ClassBinaryData cls : binaryDataMap.values()) {
|
||||
if (cls.start < 0) {
|
||||
continue;
|
||||
}
|
||||
DataValue value = DataPrimitives.ADDRESS.createValue();
|
||||
value.setAddress(0, cls.start);
|
||||
int address = binaryWriter.append(value);
|
||||
if (classesAddress == 0) {
|
||||
classesAddress = address;
|
||||
}
|
||||
++classCount;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasClinit(String className) {
|
||||
if (isStructure(className) || className.equals(Address.class.getName())) {
|
||||
return false;
|
||||
|
|
|
@ -25,6 +25,8 @@ import org.teavm.runtime.Mutator;
|
|||
|
||||
public class MutatorIntrinsic implements WasmIntrinsic {
|
||||
private List<WasmInt32Constant> staticGcRootsExpressions = new ArrayList<>();
|
||||
private List<WasmInt32Constant> classesExpressions = new ArrayList<>();
|
||||
private List<WasmInt32Constant> classCountExpressions = new ArrayList<>();
|
||||
|
||||
public void setStaticGcRootsAddress(int address) {
|
||||
for (WasmInt32Constant constant : staticGcRootsExpressions) {
|
||||
|
@ -32,6 +34,18 @@ public class MutatorIntrinsic implements WasmIntrinsic {
|
|||
}
|
||||
}
|
||||
|
||||
public void setClassesAddress(int address) {
|
||||
for (WasmInt32Constant constant : classesExpressions) {
|
||||
constant.setValue(address);
|
||||
}
|
||||
}
|
||||
|
||||
public void setClassCount(int count) {
|
||||
for (WasmInt32Constant constant : classCountExpressions) {
|
||||
constant.setValue(count);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApplicable(MethodReference methodReference) {
|
||||
if (!methodReference.getClassName().equals(Mutator.class.getName())) {
|
||||
|
@ -39,6 +53,8 @@ public class MutatorIntrinsic implements WasmIntrinsic {
|
|||
}
|
||||
switch (methodReference.getName()) {
|
||||
case "getStaticGCRoots":
|
||||
case "getClasses":
|
||||
case "getClassCount":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -53,6 +69,16 @@ public class MutatorIntrinsic implements WasmIntrinsic {
|
|||
staticGcRootsExpressions.add(constant);
|
||||
return constant;
|
||||
}
|
||||
case "getClasses": {
|
||||
WasmInt32Constant constant = new WasmInt32Constant(0);
|
||||
classesExpressions.add(constant);
|
||||
return constant;
|
||||
}
|
||||
case "getClassCount": {
|
||||
WasmInt32Constant constant = new WasmInt32Constant(0);
|
||||
classCountExpressions.add(constant);
|
||||
return constant;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException(invocation.getMethod().toString());
|
||||
}
|
||||
|
|
|
@ -40,18 +40,14 @@ import org.teavm.model.MethodReference;
|
|||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.instructions.CloneArrayInstruction;
|
||||
import org.teavm.model.instructions.ConstructArrayInstruction;
|
||||
import org.teavm.model.instructions.ConstructInstruction;
|
||||
import org.teavm.model.instructions.ConstructMultiArrayInstruction;
|
||||
import org.teavm.model.instructions.InitClassInstruction;
|
||||
import org.teavm.model.instructions.AssignInstruction;
|
||||
import org.teavm.model.instructions.ClassConstantInstruction;
|
||||
import org.teavm.model.instructions.IntegerConstantInstruction;
|
||||
import org.teavm.model.instructions.InvocationType;
|
||||
import org.teavm.model.instructions.InvokeInstruction;
|
||||
import org.teavm.model.instructions.MonitorEnterInstruction;
|
||||
import org.teavm.model.instructions.MonitorExitInstruction;
|
||||
import org.teavm.model.instructions.NullCheckInstruction;
|
||||
import org.teavm.model.instructions.RaiseInstruction;
|
||||
import org.teavm.model.instructions.NullConstantInstruction;
|
||||
import org.teavm.model.instructions.StringConstantInstruction;
|
||||
import org.teavm.model.util.DefinitionExtractor;
|
||||
import org.teavm.model.util.GraphColorer;
|
||||
import org.teavm.model.util.LivenessAnalyzer;
|
||||
|
@ -128,6 +124,7 @@ public class GCShadowStackContributor {
|
|||
|
||||
private List<Map<Instruction, BitSet>> findCallSiteLiveIns(Program program, MethodReader method) {
|
||||
boolean[] nativePointers = nativePointerFinder.findNativePointers(method.getReference(), program);
|
||||
BitSet constants = findConstantRefVariables(program);
|
||||
|
||||
TypeInferer typeInferer = new TypeInferer();
|
||||
typeInferer.inferTypes(program, method.getReference());
|
||||
|
@ -153,20 +150,10 @@ public class GCShadowStackContributor {
|
|||
for (Variable definedVar : defExtractor.getDefinedVariables()) {
|
||||
currentLiveOut.clear(definedVar.getIndex());
|
||||
}
|
||||
if (insn instanceof InvokeInstruction || insn instanceof InitClassInstruction
|
||||
|| insn instanceof ConstructInstruction || insn instanceof ConstructArrayInstruction
|
||||
|| insn instanceof ConstructMultiArrayInstruction
|
||||
|| insn instanceof CloneArrayInstruction || insn instanceof RaiseInstruction
|
||||
|| insn instanceof NullCheckInstruction
|
||||
|| insn instanceof MonitorEnterInstruction || insn instanceof MonitorExitInstruction) {
|
||||
if (insn instanceof InvokeInstruction
|
||||
&& !characteristics.isManaged(((InvokeInstruction) insn).getMethod())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ExceptionHandlingShadowStackContributor.isCallInstruction(characteristics, insn)) {
|
||||
BitSet csLiveIn = (BitSet) currentLiveOut.clone();
|
||||
for (int v = csLiveIn.nextSetBit(0); v >= 0; v = csLiveIn.nextSetBit(v + 1)) {
|
||||
if (!isReference(typeInferer, v) || nativePointers[v]) {
|
||||
if (!isReference(typeInferer, v) || nativePointers[v] || constants.get(v)) {
|
||||
csLiveIn.clear(v);
|
||||
}
|
||||
}
|
||||
|
@ -410,4 +397,46 @@ public class GCShadowStackContributor {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private BitSet findConstantRefVariables(Program program) {
|
||||
BitSet constantClasses = new BitSet();
|
||||
DisjointSet classes = new DisjointSet();
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
classes.create();
|
||||
}
|
||||
|
||||
for (BasicBlock block : program.getBasicBlocks()) {
|
||||
for (Instruction instruction : block) {
|
||||
Variable variable;
|
||||
if (instruction instanceof ClassConstantInstruction) {
|
||||
variable = ((ClassConstantInstruction) instruction).getReceiver();
|
||||
} else if (instruction instanceof StringConstantInstruction) {
|
||||
variable = ((StringConstantInstruction) instruction).getReceiver();
|
||||
} else if (instruction instanceof NullConstantInstruction) {
|
||||
variable = ((NullConstantInstruction) instruction).getReceiver();
|
||||
} else if (instruction instanceof AssignInstruction) {
|
||||
AssignInstruction assign = (AssignInstruction) instruction;
|
||||
boolean wasConstant = constantClasses.get(classes.find(assign.getAssignee().getIndex()));
|
||||
int newClass = classes.union(assign.getAssignee().getIndex(), assign.getReceiver().getIndex());
|
||||
if (wasConstant) {
|
||||
constantClasses.set(newClass);
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
constantClasses.set(classes.find(variable.getIndex()));
|
||||
}
|
||||
}
|
||||
|
||||
BitSet result = new BitSet();
|
||||
for (int i = 0; i < program.variableCount(); ++i) {
|
||||
if (constantClasses.get(classes.find(i))) {
|
||||
result.set(i);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -198,6 +198,19 @@ public final class GC {
|
|||
staticRoots = staticRoots.add(Address.sizeOf());
|
||||
}
|
||||
|
||||
int classCount = Mutator.getClassCount();
|
||||
Address classPtr = Mutator.getClasses();
|
||||
for (int i = 0; i < classCount; ++i) {
|
||||
RuntimeClass cls = classPtr.getAddress().toStructure();
|
||||
if (cls.simpleNameCache != null) {
|
||||
mark(cls.simpleNameCache);
|
||||
}
|
||||
if (cls.canonicalName != null) {
|
||||
mark(cls.canonicalName);
|
||||
}
|
||||
classPtr = classPtr.add(Address.sizeOf());
|
||||
}
|
||||
|
||||
for (Address stackRoots = ShadowStack.getStackTop(); stackRoots != null;
|
||||
stackRoots = ShadowStack.getNextStackFrame(stackRoots)) {
|
||||
int count = ShadowStack.getStackRootCount(stackRoots);
|
||||
|
@ -414,6 +427,7 @@ public final class GC {
|
|||
markStackRoots();
|
||||
calculateRelocationTargets();
|
||||
updatePointersFromStaticRoots();
|
||||
updatePointersFromClasses();
|
||||
updatePointersFromObjects();
|
||||
restoreObjectHeaders();
|
||||
relocateObjects();
|
||||
|
@ -557,6 +571,21 @@ public final class GC {
|
|||
}
|
||||
}
|
||||
|
||||
private static void updatePointersFromClasses() {
|
||||
int classCount = Mutator.getClassCount();
|
||||
Address classPtr = Mutator.getClasses();
|
||||
for (int i = 0; i < classCount; ++i) {
|
||||
RuntimeClass cls = classPtr.getAddress().toStructure();
|
||||
if (cls.simpleNameCache != null) {
|
||||
cls.simpleNameCache = updatePointer(cls.simpleNameCache.toAddress()).toStructure();
|
||||
}
|
||||
if (cls.canonicalName != null) {
|
||||
cls.canonicalName = updatePointer(cls.canonicalName.toAddress()).toStructure();
|
||||
}
|
||||
classPtr = classPtr.add(Address.sizeOf());
|
||||
}
|
||||
}
|
||||
|
||||
private static void updatePointersFromObjects() {
|
||||
Address start = heapAddress();
|
||||
long heapSize = availableBytes();
|
||||
|
|
|
@ -26,4 +26,8 @@ public final class Mutator {
|
|||
}
|
||||
|
||||
public static native Address getStaticGCRoots();
|
||||
|
||||
public static native Address getClasses();
|
||||
|
||||
public static native int getClassCount();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user