C: improve null check implementation

This commit is contained in:
Alexey Andreev 2019-07-23 16:33:13 +03:00
parent a260067fde
commit ca3b565210
3 changed files with 45 additions and 5 deletions

View File

@ -340,11 +340,20 @@ public class CodeGenerationVisitor implements ExprVisitor, StatementVisitor {
expr.getOperand().acceptVisitor(this); expr.getOperand().acceptVisitor(this);
writer.print(")"); writer.print(")");
break; break;
case NULL_CHECK: case NULL_CHECK: {
boolean needParenthesis = false;
if (needsCallSiteId()) {
needParenthesis = true;
withCallSite();
}
writer.print("teavm_nullCheck("); writer.print("teavm_nullCheck(");
expr.getOperand().acceptVisitor(this); expr.getOperand().acceptVisitor(this);
writer.print(")"); writer.print(")");
if (needParenthesis) {
writer.print(")");
}
break; break;
}
case INT_TO_BYTE: case INT_TO_BYTE:
writer.print("TEAVM_TO_BYTE("); writer.print("TEAVM_TO_BYTE(");
expr.getOperand().acceptVisitor(this); expr.getOperand().acceptVisitor(this);

View File

@ -55,6 +55,7 @@ import org.teavm.model.instructions.JumpInstruction;
import org.teavm.model.instructions.LongConstantInstruction; import org.teavm.model.instructions.LongConstantInstruction;
import org.teavm.model.instructions.MonitorEnterInstruction; import org.teavm.model.instructions.MonitorEnterInstruction;
import org.teavm.model.instructions.MonitorExitInstruction; import org.teavm.model.instructions.MonitorExitInstruction;
import org.teavm.model.instructions.NullCheckInstruction;
import org.teavm.model.instructions.NullConstantInstruction; import org.teavm.model.instructions.NullConstantInstruction;
import org.teavm.model.instructions.RaiseInstruction; import org.teavm.model.instructions.RaiseInstruction;
import org.teavm.model.instructions.SwitchInstruction; import org.teavm.model.instructions.SwitchInstruction;
@ -279,7 +280,8 @@ public class ExceptionHandlingShadowStackContributor {
if (insn instanceof InitClassInstruction || insn instanceof ConstructInstruction if (insn instanceof InitClassInstruction || insn instanceof ConstructInstruction
|| insn instanceof ConstructArrayInstruction || insn instanceof ConstructMultiArrayInstruction || insn instanceof ConstructArrayInstruction || insn instanceof ConstructMultiArrayInstruction
|| insn instanceof CloneArrayInstruction || insn instanceof RaiseInstruction || insn instanceof CloneArrayInstruction || insn instanceof RaiseInstruction
|| insn instanceof MonitorEnterInstruction || insn instanceof MonitorExitInstruction) { || insn instanceof MonitorEnterInstruction || insn instanceof MonitorExitInstruction
|| insn instanceof NullCheckInstruction) {
return true; return true;
} else if (insn instanceof InvokeInstruction) { } else if (insn instanceof InvokeInstruction) {
return isManagedMethodCall(characteristics, ((InvokeInstruction) insn).getMethod()); return isManagedMethodCall(characteristics, ((InvokeInstruction) insn).getMethod());

View File

@ -50,6 +50,7 @@ import org.teavm.model.instructions.InvocationType;
import org.teavm.model.instructions.InvokeInstruction; import org.teavm.model.instructions.InvokeInstruction;
import org.teavm.model.instructions.MonitorEnterInstruction; import org.teavm.model.instructions.MonitorEnterInstruction;
import org.teavm.model.instructions.MonitorExitInstruction; import org.teavm.model.instructions.MonitorExitInstruction;
import org.teavm.model.instructions.NullCheckInstruction;
import org.teavm.model.instructions.RaiseInstruction; import org.teavm.model.instructions.RaiseInstruction;
import org.teavm.model.util.DefinitionExtractor; import org.teavm.model.util.DefinitionExtractor;
import org.teavm.model.util.GraphColorer; import org.teavm.model.util.GraphColorer;
@ -156,6 +157,7 @@ public class GCShadowStackContributor {
|| insn instanceof ConstructInstruction || insn instanceof ConstructArrayInstruction || insn instanceof ConstructInstruction || insn instanceof ConstructArrayInstruction
|| insn instanceof ConstructMultiArrayInstruction || insn instanceof ConstructMultiArrayInstruction
|| insn instanceof CloneArrayInstruction || insn instanceof RaiseInstruction || insn instanceof CloneArrayInstruction || insn instanceof RaiseInstruction
|| insn instanceof NullCheckInstruction
|| insn instanceof MonitorEnterInstruction || insn instanceof MonitorExitInstruction) { || insn instanceof MonitorEnterInstruction || insn instanceof MonitorExitInstruction) {
if (insn instanceof InvokeInstruction if (insn instanceof InvokeInstruction
&& !characteristics.isManaged(((InvokeInstruction) insn).getMethod())) { && !characteristics.isManaged(((InvokeInstruction) insn).getMethod())) {
@ -239,6 +241,7 @@ public class GCShadowStackContributor {
Step start = new Step(0); Step start = new Step(0);
Arrays.fill(start.slotStates, program.variableCount()); Arrays.fill(start.slotStates, program.variableCount());
stack[head++] = start; stack[head++] = start;
int[] definitionClasses = getDefinitionClasses(program);
while (head > 0) { while (head > 0) {
Step step = stack[--head]; 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; previousStates = states;
states = states.clone(); states = states.clone();
} }
@ -275,6 +279,22 @@ public class GCShadowStackContributor {
return slotsToUpdate; 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<Instruction> sortInstructions(Collection<Instruction> instructions, BasicBlock block) { private List<Instruction> sortInstructions(Collection<Instruction> instructions, BasicBlock block) {
ObjectIntMap<Instruction> indexes = new ObjectIntHashMap<>(); ObjectIntMap<Instruction> indexes = new ObjectIntHashMap<>();
int index = 0; int index = 0;
@ -286,12 +306,21 @@ public class GCShadowStackContributor {
return sortedInstructions; 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]; int[] comparison = new int[oldStates.length];
Arrays.fill(comparison, -2); Arrays.fill(comparison, -2);
for (int i = 0; i < oldStates.length; ++i) { 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]; comparison[i] = newStates[i];
} }
} }