C: reduce number of synthesized null checks

This commit is contained in:
Alexey Andreev 2019-07-12 14:07:57 +03:00
parent 9ad0ddd891
commit a240537e36
5 changed files with 72 additions and 22 deletions

View File

@ -191,6 +191,17 @@ public class ExceptionHandlingShadowStackContributor {
BasicBlock initialBlock = block;
for (Instruction insn : block) {
insn.acceptVisitor(defExtractor);
for (Variable definedVar : defExtractor.getDefinedVariables()) {
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
int jointReceiver = jointReceiverMaps.get(tryCatch.getHandler().getIndex())[definedVar.getIndex()];
if (jointReceiver >= 0) {
currentJointSources[jointReceiver] = definedVar.getIndex();
}
}
variablesDefinedHere.add(definedVar.getIndex());
}
if (isCallInstruction(insn)) {
BasicBlock next;
boolean last = false;
@ -250,17 +261,6 @@ public class ExceptionHandlingShadowStackContributor {
block = next;
variablesDefinedHere.clear();
}
insn.acceptVisitor(defExtractor);
for (Variable definedVar : defExtractor.getDefinedVariables()) {
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
int jointReceiver = jointReceiverMaps.get(tryCatch.getHandler().getIndex())[definedVar.getIndex()];
if (jointReceiver >= 0) {
currentJointSources[jointReceiver] = definedVar.getIndex();
}
}
variablesDefinedHere.add(definedVar.getIndex());
}
}
fixOutgoingPhis(initialBlock, block, currentJointSources, variablesDefinedHere);

View File

@ -15,6 +15,8 @@
*/
package org.teavm.model.lowlevel;
import com.carrotsearch.hppc.IntHashSet;
import com.carrotsearch.hppc.IntSet;
import java.util.function.BiConsumer;
import java.util.function.Function;
import org.teavm.model.BasicBlock;
@ -32,6 +34,8 @@ import org.teavm.model.instructions.NullCheckInstruction;
import org.teavm.model.instructions.PutFieldInstruction;
import org.teavm.model.instructions.RaiseInstruction;
import org.teavm.model.instructions.UnwrapArrayInstruction;
import org.teavm.model.util.DominatorWalker;
import org.teavm.model.util.DominatorWalkerCallback;
import org.teavm.model.util.PhiUpdater;
public class NullCheckInsertion {
@ -42,23 +46,51 @@ public class NullCheckInsertion {
}
public void transformProgram(Program program, MethodReference methodReference) {
if (!characteristics.isManaged(methodReference)) {
if (!characteristics.isManaged(methodReference) || program.basicBlockCount() == 0) {
return;
}
InsertionVisitor visitor = new InsertionVisitor();
for (BasicBlock block : program.getBasicBlocks()) {
for (Instruction instruction : block) {
instruction.acceptVisitor(visitor);
}
}
InsertionVisitor visitor = new InsertionVisitor(program.variableCount());
new DominatorWalker(program).walk(visitor);
if (visitor.changed) {
new PhiUpdater().updatePhis(program, methodReference.parameterCount() + 1);
}
}
class InsertionVisitor extends AbstractInstructionVisitor {
class InsertionVisitor extends AbstractInstructionVisitor implements DominatorWalkerCallback<BlockNullness> {
boolean changed;
boolean[] notNullVariables;
BlockNullness blockNullness;
InsertionVisitor(int variableCount) {
notNullVariables = new boolean[variableCount];
if (variableCount > 0) {
notNullVariables[0] = true;
}
}
@Override
public BlockNullness visit(BasicBlock block) {
blockNullness = new BlockNullness();
if (block.getExceptionVariable() != null) {
notNullVariables[block.getExceptionVariable().getIndex()] = true;
blockNullness.notNullVariables.add(block.getExceptionVariable().getIndex());
}
for (Instruction instruction : block) {
instruction.acceptVisitor(this);
}
return blockNullness;
}
@Override
public void endVisit(BasicBlock block, BlockNullness state) {
for (int variable : state.notNullVariables.toArray()) {
notNullVariables[variable] = false;
}
}
@Override
public void visit(RaiseInstruction insn) {
@ -114,6 +146,13 @@ public class NullCheckInsertion {
return;
}
if (notNullVariables[value.getIndex()]) {
return;
}
notNullVariables[value.getIndex()] = true;
blockNullness.notNullVariables.add(value.getIndex());
NullCheckInstruction nullCheck = new NullCheckInstruction();
nullCheck.setValue(value);
nullCheck.setReceiver(value);
@ -123,4 +162,8 @@ public class NullCheckInsertion {
changed = true;
}
}
static class BlockNullness {
IntSet notNullVariables = new IntHashSet();
}
}

View File

@ -48,8 +48,8 @@ public class LivenessAnalyzer {
public void analyze(Program program) {
Graph cfg = ProgramUtils.buildControlFlowGraph(program);
DominatorTree dominatorTree = GraphUtils.buildDominatorTree(cfg);
liveVars = new BitSet[cfg.size()];
liveOutVars = new BitSet[cfg.size()];
liveVars = new BitSet[program.basicBlockCount()];
liveOutVars = new BitSet[program.basicBlockCount()];
for (int i = 0; i < liveVars.length; ++i) {
liveVars[i] = new BitSet(program.basicBlockCount());
liveOutVars[i] = new BitSet(program.basicBlockCount());

View File

@ -760,8 +760,8 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
optimizations.add(new LoopInvariantMotion());
}
optimizations.add(new GlobalValueNumbering(optimizationLevel == TeaVMOptimizationLevel.SIMPLE));
optimizations.add(new RedundantNullCheckElimination());
if (optimizationLevel.ordinal() >= TeaVMOptimizationLevel.ADVANCED.ordinal()) {
optimizations.add(new RedundantNullCheckElimination());
optimizations.add(new ConstantConditionElimination());
optimizations.add(new RedundantJumpElimination());
optimizations.add(new UnusedVariableElimination());

View File

@ -39,6 +39,7 @@ import org.teavm.model.instructions.ConstructInstruction;
import org.teavm.model.instructions.ExitInstruction;
import org.teavm.model.instructions.InvocationType;
import org.teavm.model.instructions.InvokeInstruction;
import org.teavm.model.instructions.JumpInstruction;
import org.teavm.runtime.Fiber;
public class AsyncMethodProcessor implements ClassHolderTransformer {
@ -89,8 +90,14 @@ public class AsyncMethodProcessor implements ClassHolderTransformer {
Program program = new Program();
method.setProgram(program);
BasicBlock startBlock = program.createBasicBlock();
BasicBlock block = program.createBasicBlock();
JumpInstruction jumpToBlock = new JumpInstruction();
jumpToBlock.setTarget(block);
startBlock.add(jumpToBlock);
InvokeInstruction constructorInvocation = new InvokeInstruction();
constructorInvocation.setType(InvocationType.SPECIAL);
List<ValueType> signature = new ArrayList<>();