Index: pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart |
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart |
index d1353979d145a3d1fa3a0142e9467c7efd29c125..36f569f6a86a4669fe8fb8e13b8722c195ada637 100644 |
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart |
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart |
@@ -159,6 +159,13 @@ abstract class JumpCollector { |
if (hasExtraArgument) _continuationEnvironment.extend(null, null); |
} |
+ /// Construct a collector for collecting only return jumps. |
+ /// |
+ /// There is no jump target, it is implicitly the exit from the function. |
+ /// There is no environment at the destination. |
+ JumpCollector.retrn(this._continuation) |
+ : _continuationEnvironment = null, target = null; |
+ |
/// True if the collector has not recorded any jumps to its continuation. |
bool get isEmpty; |
@@ -175,7 +182,8 @@ abstract class JumpCollector { |
/// values to finally blocks for returns inside try/finally and to pass |
/// values of expressions that have internal control flow to their join-point |
/// continuations. |
- void addJump(IrBuilder builder, [ir.Primitive value]); |
+ void addJump(IrBuilder builder, |
+ [ir.Primitive value, SourceInformation sourceInformation]); |
/// Add a set of variables that were boxed on entry to a try block. |
/// |
@@ -259,7 +267,8 @@ class ForwardJumpCollector extends JumpCollector { |
return _continuationEnvironment; |
} |
- void addJump(IrBuilder builder, [ir.Primitive value]) { |
+ void addJump(IrBuilder builder, |
+ [ir.Primitive value, SourceInformation sourceInformation]) { |
assert(_continuation == null); |
_buildTryExit(builder); |
ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized( |
@@ -368,7 +377,8 @@ class BackwardJumpCollector extends JumpCollector { |
ir.Continuation get continuation => _continuation; |
Environment get environment => _continuationEnvironment; |
- void addJump(IrBuilder builder, [ir.Primitive value]) { |
+ void addJump(IrBuilder builder, |
+ [ir.Primitive value, SourceInformation sourceInformation]) { |
assert(_continuation.parameters.length <= builder.environment.length); |
isEmpty = false; |
_buildTryExit(builder); |
@@ -388,6 +398,29 @@ class BackwardJumpCollector extends JumpCollector { |
} |
} |
+/// Collect 'return' jumps. |
+/// |
+/// A return jump is one that targets the return continuation of a function. |
+/// Thus, returns from inside try/finally are not return jumps because they are |
+/// intercepted by a block that contains the finally handler code. |
+class ReturnJumpCollector extends JumpCollector { |
+ bool isEmpty = true; |
+ ir.Continuation get continuation => _continuation; |
+ Environment environment = null; |
+ |
+ /// Construct a return jump collector for a given return continuation. |
+ ReturnJumpCollector(ir.Continuation continuation) : super.retrn(continuation); |
+ |
+ void addJump(IrBuilder builder, |
+ [ir.Primitive value, SourceInformation sourceInformation]) { |
+ isEmpty = false; |
+ builder.add(new ir.InvokeContinuation(continuation, <ir.Primitive>[value], |
+ isEscapingTry: isEscapingTry, |
+ sourceInformation: sourceInformation)); |
+ builder._current = null; |
+ } |
+} |
+ |
/// Function for building a node in the context of the current builder. |
typedef ir.Node BuildFunction(node); |
@@ -466,7 +499,7 @@ class IrBuilderSharedState { |
/// A null value indicates that the target is the function's return |
/// continuation. Otherwise, when inside the try block of try/finally |
/// a return is intercepted to give a place to generate the finally code. |
- JumpCollector returnCollector = null; |
+ JumpCollector returnCollector; |
/// Parameter holding the internal value of 'this' passed to the function. |
/// |
@@ -483,7 +516,9 @@ class IrBuilderSharedState { |
/// the environment. |
final Map<Local, ClosureLocation> boxedVariables = {}; |
- IrBuilderSharedState(this.program, this.constants, this.currentElement); |
+ IrBuilderSharedState(this.program, this.constants, this.currentElement) { |
+ returnCollector = new ReturnJumpCollector(returnContinuation); |
+ } |
} |
class ThisParameterLocal implements Local { |
@@ -1160,8 +1195,9 @@ class IrBuilder { |
} |
} |
- void jumpTo(JumpCollector collector, [ir.Primitive value]) { |
- collector.addJump(this, value); |
+ void jumpTo(JumpCollector collector, |
+ [ir.Primitive value, SourceInformation sourceInformation]) { |
+ collector.addJump(this, value, sourceInformation); |
} |
void addRecursiveContinuation(BackwardJumpCollector collector) { |
@@ -1811,6 +1847,7 @@ class IrBuilder { |
} |
builder.state.breakCollectors.forEach(interceptJump); |
builder.state.continueCollectors.forEach(interceptJump); |
+ interceptJump(builder.state.returnCollector); |
} |
void leaveTry(IrBuilder builder) { |
@@ -1821,6 +1858,7 @@ class IrBuilder { |
} |
builder.state.breakCollectors.forEach(restoreJump); |
builder.state.continueCollectors.forEach(restoreJump); |
+ restoreJump(builder.state.returnCollector); |
} |
List<ir.Parameter> buildCatch(IrBuilder builder, |
@@ -2029,16 +2067,7 @@ class IrBuilder { |
if (value == null) { |
value = buildNullConstant(); |
} |
- if (state.returnCollector == null) { |
- add(new ir.InvokeContinuation(state.returnContinuation, [value], |
- sourceInformation: sourceInformation)); |
- _current = null; |
- } else { |
- // Inside the try block of try/finally, all returns go to a join-point |
- // continuation that contains the finally code. The return value is |
- // passed as an extra argument. |
- jumpTo(state.returnCollector, value); |
- } |
+ jumpTo(state.returnCollector, value, sourceInformation); |
} |
/// Build a call to the closure conversion helper for the [Function] typed |