diff --git a/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java b/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java index b7d7a1a2b..8b76c9c8c 100644 --- a/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/c/generate/CodeGenerationVisitor.java @@ -340,11 +340,20 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor { expr.getOperand().acceptVisitor(this); writer.print(")"); break; - case NULL_CHECK: + case NULL_CHECK: { + boolean needParenthesis = false; + if (needsCallSiteId()) { + needParenthesis = true; + withCallSite(); + } writer.print("teavm_nullCheck("); expr.getOperand().acceptVisitor(this); writer.print(")"); + if (needParenthesis) { + writer.print(")"); + } break; + } case INT_TO_BYTE: writer.print("TEAVM_TO_BYTE("); expr.getOperand().acceptVisitor(this); diff --git a/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingShadowStackContributor.java b/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingShadowStackContributor.java index feaa2f216..fd2850da1 100644 --- a/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingShadowStackContributor.java +++ b/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingShadowStackContributor.java @@ -55,6 +55,7 @@ import org.teavm.model.instructions.JumpInstruction; import org.teavm.model.instructions.LongConstantInstruction; import org.teavm.model.instructions.MonitorEnterInstruction; import org.teavm.model.instructions.MonitorExitInstruction; +import org.teavm.model.instructions.NullCheckInstruction; import org.teavm.model.instructions.NullConstantInstruction; import org.teavm.model.instructions.RaiseInstruction; import org.teavm.model.instructions.SwitchInstruction; @@ -279,7 +280,8 @@ public class ExceptionHandlingShadowStackContributor { if (insn instanceof InitClassInstruction || insn instanceof ConstructInstruction || insn instanceof ConstructArrayInstruction || insn instanceof ConstructMultiArrayInstruction || insn instanceof CloneArrayInstruction || insn instanceof RaiseInstruction - || insn instanceof MonitorEnterInstruction || insn instanceof MonitorExitInstruction) { + || insn instanceof MonitorEnterInstruction || insn instanceof MonitorExitInstruction + || insn instanceof NullCheckInstruction) { return true; } else if (insn instanceof InvokeInstruction) { return isManagedMethodCall(characteristics, ((InvokeInstruction) insn).getMethod()); diff --git a/core/src/main/java/org/teavm/model/lowlevel/GCShadowStackContributor.java b/core/src/main/java/org/teavm/model/lowlevel/GCShadowStackContributor.java index 134ae28f8..020fea5e3 100644 --- a/core/src/main/java/org/teavm/model/lowlevel/GCShadowStackContributor.java +++ b/core/src/main/java/org/teavm/model/lowlevel/GCShadowStackContributor.java @@ -50,6 +50,7 @@ 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.util.DefinitionExtractor; import org.teavm.model.util.GraphColorer; @@ -156,6 +157,7 @@ public class GCShadowStackContributor { || 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())) { @@ -239,6 +241,7 @@ public class GCShadowStackContributor { Step start = new Step(0); Arrays.fill(start.slotStates, program.variableCount()); stack[head++] = start; + int[] definitionClasses = getDefinitionClasses(program); while (head > 0) { Step step = stack[--head]; @@ -260,7 +263,8 @@ public class GCShadowStackContributor { } } - updatesByCallSite.put(callSiteLocation, compareStates(previousStates, states, autoSpilled)); + int[] updates = compareStates(previousStates, states, autoSpilled, definitionClasses); + updatesByCallSite.put(callSiteLocation, updates); previousStates = states; states = states.clone(); } @@ -275,6 +279,22 @@ public class GCShadowStackContributor { return slotsToUpdate; } + private int[] getDefinitionClasses(Program program) { + DisjointSet disjointSet = new DisjointSet(); + for (int i = 0; i < program.variableCount(); ++i) { + disjointSet.create(); + } + for (BasicBlock block : program.getBasicBlocks()) { + for (Instruction instruction : block) { + if (instruction instanceof NullCheckInstruction) { + NullCheckInstruction nullCheck = (NullCheckInstruction) instruction; + disjointSet.union(nullCheck.getValue().getIndex(), nullCheck.getReceiver().getIndex()); + } + } + } + return disjointSet.pack(program.variableCount()); + } + private List sortInstructions(Collection instructions, BasicBlock block) { ObjectIntMap indexes = new ObjectIntHashMap<>(); int index = 0; @@ -286,12 +306,21 @@ public class GCShadowStackContributor { return sortedInstructions; } - private static int[] compareStates(int[] oldStates, int[] newStates, boolean[] autoSpilled) { + private static int[] compareStates(int[] oldStates, int[] newStates, boolean[] autoSpilled, + int[] definitionClasses) { int[] comparison = new int[oldStates.length]; Arrays.fill(comparison, -2); for (int i = 0; i < oldStates.length; ++i) { - if (oldStates[i] != newStates[i]) { + int oldState = oldStates[i]; + int newState = newStates[i]; + if (oldState >= 0 && oldState < definitionClasses.length) { + oldState = definitionClasses[oldState]; + } + if (newState >= 0 && newState < definitionClasses.length) { + newState = definitionClasses[newState]; + } + if (oldState != newState) { comparison[i] = newStates[i]; } }