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

Unified Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 13947004: dart2js: Allow 'throw' when inlining (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Nicolas' Code review feedback Created 7 years, 8 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
Index: sdk/lib/_internal/compiler/implementation/ssa/builder.dart
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 48dd75987ec7b1cb9ee4089227b4d814277a7a11..eaadbd80879d7e73cf26e3f8be83c25cab35af29 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -36,14 +36,14 @@ class SsaBuilderTask extends CompilerTask {
SsaBuilder builder = new SsaBuilder(constantSystem, this, work);
HGraph graph;
ElementKind kind = element.kind;
- if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR)) {
+ if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
graph = compileConstructor(builder, work);
- } else if (identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR_BODY) ||
- identical(kind, ElementKind.FUNCTION) ||
- identical(kind, ElementKind.GETTER) ||
- identical(kind, ElementKind.SETTER)) {
+ } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY ||
+ kind == ElementKind.FUNCTION ||
+ kind == ElementKind.GETTER ||
+ kind == ElementKind.SETTER) {
graph = builder.buildMethod(element);
- } else if (identical(kind, ElementKind.FIELD)) {
+ } else if (kind == ElementKind.FIELD) {
graph = builder.buildLazyInitializer(element);
} else {
compiler.internalErrorOnElement(element,
@@ -110,6 +110,7 @@ class SsaBuilderTask extends CompilerTask {
}
}
+
/**
* Keeps track of locals (including parameters and phis) when building. The
* 'this' reference is treated as parameter and hence handled by this class,
@@ -440,8 +441,9 @@ class LocalsHandler {
}
/**
- * This function must be called before visiting any children of the loop. In
- * particular it needs to be called before executing the initializers.
+ * This function, startLoop, must be called before visiting any children of
+ * the loop. In particular it needs to be called before executing the
+ * initializers.
*
* The [LocalsHandler] will make the boxes and updates at the right moment.
* The builder just needs to call [enterLoopBody] and [enterLoopUpdates] (for
@@ -794,14 +796,28 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
// We build the Ssa graph by simulating a stack machine.
List<HInstruction> stack;
- // The current block to add instructions to. Might be null, if we are
- // visiting dead code.
- HBasicBlock current;
- // The most recently opened block. Has the same value as [current] while
- // the block is open, but unlike [current], it isn't cleared when the current
- // block is closed.
+ /**
+ * The current block to add instructions to. Might be null, if we are
+ * visiting dead code, but see [isReachable].
+ */
+ HBasicBlock _current;
+
+ /**
+ * The most recently opened block. Has the same value as [_current] while
+ * the block is open, but unlike [_current], it isn't cleared when the
+ * current block is closed.
+ */
HBasicBlock lastOpenedBlock;
+ /**
+ * Indicates whether the current block is dead (because it has a throw or a
+ * return further up). If this is false, then [_current] may be null. If the
+ * block is dead then it may also be aborted, but for simplicity we only
+ * abort on statement boundaries, not in the middle of expressions. See
+ * isAborted.
+ */
+ bool isReachable = true;
+
final List<Element> sourceElementStack;
Element get currentElement => sourceElementStack.last.declaration;
@@ -831,6 +847,12 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
DartType returnType;
bool inTryStatement = false;
+ HBasicBlock get current => _current;
+ void set current(c) {
+ isReachable = c != null;
+ _current = c;
+ }
+
/**
* Compiles compile-time constants. Never returns [:null:]. If the
* initial value is not a compile-time constants, it reports an
@@ -1663,7 +1685,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
bool isAborted() {
- return current == null;
+ return _current == null;
}
/**
@@ -1750,11 +1772,12 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
visitBlock(Block node) {
+ if (!isReachable) return; // This can happen when inlining.
ngeoffray 2013/04/11 09:31:08 // This only happens when inlining Can you add: a
for (Link<Node> link = node.statements.nodes;
!link.isEmpty;
link = link.tail) {
visit(link.head);
- if (isAborted()) {
+ if (!isReachable) {
// The block has been aborted by a return or a throw.
if (!stack.isEmpty) compiler.cancel('non-empty instruction stack');
return;
@@ -1769,6 +1792,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
visitExpressionStatement(ExpressionStatement node) {
+ assert(isReachable);
visit(node.expression);
pop();
}
@@ -2047,6 +2071,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
visitFor(For node) {
+ assert(isReachable);
assert(node.body != null);
void buildInitializer() {
if (node.initializer == null) return;
@@ -2081,6 +2106,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
visitWhile(While node) {
+ assert(isReachable);
HInstruction buildCondition() {
visit(node.condition);
return popBoolified();
@@ -2093,6 +2119,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
visitDoWhile(DoWhile node) {
+ assert(isReachable);
LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
localsHandler.startLoop(node);
JumpHandler jumpHandler = beginLoopHeader(node);
@@ -2255,6 +2282,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
visitFunctionDeclaration(FunctionDeclaration node) {
+ assert(isReachable);
visit(node.function);
localsHandler.updateLocal(elements[node], pop());
}
@@ -2269,6 +2297,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
visitIf(If node) {
+ assert(isReachable);
handleIf(node,
() => visit(node.condition),
() => visit(node.thenPart),
@@ -3874,7 +3903,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
assert(invariant(node, !node.isRedirectingFactoryBody));
HInstruction value;
- if (node.expression == null) {
+ if (node.expression == null || !isReachable) {
ngeoffray 2013/04/11 09:31:08 I think you can remove the isReachable check.
value = graph.addConstantNull(constantSystem);
} else {
visit(node.expression);
@@ -3901,8 +3930,17 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
close(new HThrow(exception, isRethrow: true));
} else {
- visit(node.expression);
- close(new HThrow(pop()));
+ if (inliningStack.isEmpty) {
+ visit(node.expression);
+ close(new HThrow(pop()));
+ } else if (isReachable) {
+ // We don't close the block when we are inlining, because we could be
+ // inside an expression, and it is rather complicated to close the
+ // block at an arbitrary place in an expression.
+ visit(node.expression);
+ add(new HThrowExpression(pop()));
+ isReachable = false;
+ }
}
}
@@ -3912,6 +3950,7 @@ class SsaBuilder extends ResolvedVisitor implements Visitor {
}
visitVariableDefinitions(VariableDefinitions node) {
+ assert(isReachable);
for (Link<Node> link = node.definitions.nodes;
!link.isEmpty;
link = link.tail) {
@@ -4905,9 +4944,11 @@ class InlineWeeder extends Visitor {
tooDifficult = true;
}
- void visitThrow(Node node) {
+ void visitThrow(Throw node) {
if (!registerNode()) return;
- tooDifficult = true;
+ // We can't inline rethrows and we don't want to handle throw after a return
+ // even if it is in an "if".
+ if (seenReturn || node.expression == null) tooDifficult = true;
}
}

Powered by Google App Engine
This is Rietveld 408576698