From a240537e3647c624e8a2f53b5983ff0b702b0702 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 12 Jul 2019 14:07:57 +0300 Subject: [PATCH] C: reduce number of synthesized null checks --- ...ceptionHandlingShadowStackContributor.java | 22 +++---- .../model/lowlevel/NullCheckInsertion.java | 59 ++++++++++++++++--- .../teavm/model/util/LivenessAnalyzer.java | 4 +- core/src/main/java/org/teavm/vm/TeaVM.java | 2 +- .../platform/plugin/AsyncMethodProcessor.java | 7 +++ 5 files changed, 72 insertions(+), 22 deletions(-) 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 ac2ab29de..4ebe03a3c 100644 --- a/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingShadowStackContributor.java +++ b/core/src/main/java/org/teavm/model/lowlevel/ExceptionHandlingShadowStackContributor.java @@ -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); diff --git a/core/src/main/java/org/teavm/model/lowlevel/NullCheckInsertion.java b/core/src/main/java/org/teavm/model/lowlevel/NullCheckInsertion.java index 920247f62..4c8d1d5a0 100644 --- a/core/src/main/java/org/teavm/model/lowlevel/NullCheckInsertion.java +++ b/core/src/main/java/org/teavm/model/lowlevel/NullCheckInsertion.java @@ -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 { 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(); + } } diff --git a/core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java b/core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java index ec86ceaea..7089161e9 100644 --- a/core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java +++ b/core/src/main/java/org/teavm/model/util/LivenessAnalyzer.java @@ -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()); diff --git a/core/src/main/java/org/teavm/vm/TeaVM.java b/core/src/main/java/org/teavm/vm/TeaVM.java index afad5a10a..c15692533 100644 --- a/core/src/main/java/org/teavm/vm/TeaVM.java +++ b/core/src/main/java/org/teavm/vm/TeaVM.java @@ -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()); diff --git a/platform/src/main/java/org/teavm/platform/plugin/AsyncMethodProcessor.java b/platform/src/main/java/org/teavm/platform/plugin/AsyncMethodProcessor.java index fbf906e28..71eb68fa8 100644 --- a/platform/src/main/java/org/teavm/platform/plugin/AsyncMethodProcessor.java +++ b/platform/src/main/java/org/teavm/platform/plugin/AsyncMethodProcessor.java @@ -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 signature = new ArrayList<>();