Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(471)

Unified Diff: lib/compiler/implementation/ssa/bailout.dart

Issue 10533128: Reapply "Simplify generated code for trivial bailout methods". (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/builder.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/compiler/implementation/ssa/bailout.dart
===================================================================
--- lib/compiler/implementation/ssa/bailout.dart (revision 8641)
+++ lib/compiler/implementation/ssa/bailout.dart (working copy)
@@ -26,7 +26,18 @@
}
void add(HInstruction instruction) {
- if (!instruction.isCodeMotionInvariant()) {
+ // If the instruction is a type guard, we add its checked input
+ // instead. This allows sharing the same environment between
+ // different type guards.
+ //
+ // Also, we don't need to add code motion invariant instructions
+ // in the live set (because we generate them at use-site), except
+ // for parameters that are not 'this', which is always passed as
+ // the receiver.
+ if (instruction is HTypeGuard) {
+ add(instruction.checkedInput);
+ } else if (!instruction.isCodeMotionInvariant()
+ || (instruction is HParameterValue && instruction is !HThis)) {
lives.add(instruction);
} else {
for (int i = 0, len = instruction.inputs.length; i < len; i++) {
@@ -48,27 +59,6 @@
loopMarkers.addAll(other.loopMarkers);
}
- /**
- * Stores all live variables in the guard. The guarded instruction will be the
- * last input in the guard's input list.
- */
- void storeInGuard(HTypeGuard guard) {
- HInstruction guarded = guard.guarded;
- List<HInstruction> inputs = guard.inputs;
- assert(inputs.length == 1);
- inputs.clear();
- // Remove the guarded from the environment, so that we are sure it is last
- // when we add it again.
- remove(guarded);
- inputs.addAll(lives);
- inputs.addLast(guarded);
- add(guarded);
- for (int i = 0; i < inputs.length - 1; i++) {
- HInstruction input = inputs[i];
- input.usedBy.add(guard);
- }
- }
-
bool isEmpty() => lives.isEmpty() && loopMarkers.isEmpty();
}
@@ -184,13 +174,33 @@
HType speculativeType = instruction.propagatedType;
if (shouldInsertTypeGuard(instruction)) {
List<HInstruction> inputs = <HInstruction>[instruction];
- HTypeGuard guard = new HTypeGuard(speculativeType, stateId++, inputs);
+ HInstruction insertionPoint;
+ if (instruction is HPhi) {
+ insertionPoint = instruction.block.first;
+ } else if (instruction is HParameterValue) {
+ // We insert the type guard at the end of the entry block
+ // because if a parameter is live, it must be kept in the live
+ // environment. Not doing so would mean we could visit a
+ // parameter and remove it from the environment before
+ // visiting a type guard.
+ insertionPoint = instruction.block.last;
+ } else {
+ insertionPoint = instruction.next;
+ }
+ // If the previous instruction is also a type guard, then both
+ // guards have the same environment, and can therefore share the
+ // same state id.
+ int state;
+ if (insertionPoint.previous is HTypeGuard) {
+ HTypeGuard other = insertionPoint.previous;
+ state = other.state;
+ } else {
+ state = stateId++;
+ }
+ HTypeGuard guard = new HTypeGuard(speculativeType, state, inputs);
guard.propagatedType = speculativeType;
work.guards.add(guard);
instruction.block.rewrite(instruction, guard);
- HInstruction insertionPoint = (instruction is HPhi)
- ? instruction.block.first
- : instruction.next;
insertionPoint.block.addBefore(insertionPoint, guard);
}
}
@@ -310,10 +320,44 @@
}
void insertCapturedEnvironments() {
+ Map<int, HTypeGuard> seenGuardStates = new Map<int, HTypeGuard>();
capturedEnvironments.forEach((HTypeGuard guard, Environment env) {
- env.storeInGuard(guard);
+ storeInGuard(guard, env.lives, seenGuardStates);
});
}
+
+ /**
+ * Stores all live variables in the guard.
+ */
+ void storeInGuard(HTypeGuard guard,
+ Set<HInstruction> lives,
+ Map<int, HTypeGuard> seenGuardStates) {
+ HInstruction guarded = guard.guarded;
+ List<HInstruction> inputs = guard.inputs;
+ assert(inputs.length == 1);
+ inputs.clear();
+ HTypeGuard other = seenGuardStates[guard.state];
+ if (other !== null) {
+ // The guards are sharing the same state. Also share the same
+ // environment, in the same order.
+ inputs.addAll(other.inputs);
+ assert(inputs.length == lives.length);
+ } else {
+ seenGuardStates[guard.state] = guard;
+ inputs.addAll(lives);
+ }
+
+ for (int i = 0; i < inputs.length; i++) {
+ HInstruction input = inputs[i];
+ if (input == guarded) {
+ guard.checkedInputIndex = i;
+ // No need to update [input.usedBy], the guard is already
+ // there.
+ } else {
+ input.usedBy.add(guard);
+ }
+ }
+ }
}
/**
@@ -325,17 +369,34 @@
final Compiler compiler;
final List<HBasicBlock> blocks;
final List<HLabeledBlockInformation> labeledBlockInformations;
+ final Set<HInstruction> generateAtUseSite;
SubGraph subGraph;
- SsaBailoutPropagator(Compiler this.compiler)
+ /**
+ * If set to true, the graph has either multiple bailouts in
+ * different places, or a bailout inside an if or a loop. For such a
+ * graph, the code generator will emit a generic switch.
+ */
+ bool hasComplexTypeGuards = false;
+
+ /**
+ * The first type guard in the graph.
+ */
+ HTypeGuard firstTypeGuard;
+
+ /**
+ * If set, it is the first block in the graph where we generate
+ * code. Blocks before this one are dead code in the bailout
+ * version.
+ */
+
+ SsaBailoutPropagator(this.compiler, this.generateAtUseSite)
: blocks = <HBasicBlock>[],
labeledBlockInformations = <HLabeledBlockInformation>[];
void visitGraph(HGraph graph) {
subGraph = new SubGraph(graph.entry, graph.exit);
- blocks.addLast(graph.entry);
visitBasicBlock(graph.entry);
- blocks.removeLast();
if (!blocks.isEmpty()) {
compiler.internalError('Bailout propagation',
node: compiler.currentElement.parseNode(compiler));
@@ -348,7 +409,8 @@
if (block.isLoopHeader()) {
blocks.addLast(block);
- } else if (block.isLabeledBlock() && blocks.last() !== block) {
+ } else if (block.isLabeledBlock()
+ && (blocks.isEmpty() || blocks.last() !== block)) {
HLabeledBlockInformation info = block.blockFlow.body;
visitStatements(info.body);
return;
@@ -446,8 +508,17 @@
}
visitTypeGuard(HTypeGuard guard) {
- blocks.forEach((HBasicBlock block) {
- block.guards.add(guard);
- });
+ if (blocks.isEmpty()) {
+ if (firstTypeGuard === null || firstTypeGuard.state === guard.state) {
+ firstTypeGuard = guard;
+ } else {
+ hasComplexTypeGuards = true;
+ }
+ } else {
+ hasComplexTypeGuards = true;
+ blocks.forEach((HBasicBlock block) {
+ block.guards.add(guard);
+ });
+ }
}
}
« no previous file with comments | « no previous file | lib/compiler/implementation/ssa/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698