Refactor the try statement analysis results.

In the dart2js CPS backend, move the frontend-specific try statement
analysis results out of the frontend-independent IrBuilder and into the
frontend-specific IrBuilderVisitor.

BUG=
R=johnniwinther@google.com

Review URL: https://codereview.chromium.org//1075923002

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@45009 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
kmillikin@google.com
2015-04-09 14:17:36 +00:00
parent 16b03eb41e
commit 34fc9fb911
3 changed files with 55 additions and 53 deletions
+6 -10
View File
@@ -95,8 +95,8 @@ class CpsGeneratingVisitor extends SemanticVisitor<ir.Node>
return withBuilder(
new DartIrBuilder(DART_CONSTANT_SYSTEM,
element,
// TODO(johnniwinther): Supported closure variables.
new NullCapturedVariables()),
// TODO(johnniwinther): Support closure variables.
new Set<dart2js.Local>()),
() {
irBuilder.buildFunctionHeader(
constructor.parameters.map(converter.convertElement));
@@ -114,8 +114,8 @@ class CpsGeneratingVisitor extends SemanticVisitor<ir.Node>
return withBuilder(
new DartIrBuilder(DART_CONSTANT_SYSTEM,
element,
// TODO(johnniwinther): Supported closure variables.
new NullCapturedVariables()),
// TODO(johnniwinther): Support closure variables.
new Set<dart2js.Local>()),
() {
irBuilder.buildFieldInitializerHeader();
ir.Primitive initializer = build(node.initializer);
@@ -129,8 +129,8 @@ class CpsGeneratingVisitor extends SemanticVisitor<ir.Node>
return withBuilder(
new DartIrBuilder(DART_CONSTANT_SYSTEM,
element,
// TODO(johnniwinther): Supported closure variables.
new NullCapturedVariables()),
// TODO(johnniwinther): Support closure variables.
new Set<dart2js.Local>()),
() {
irBuilder.buildFunctionHeader(
function.parameters.map(converter.convertElement));
@@ -585,7 +585,3 @@ class CpsGeneratingVisitor extends SemanticVisitor<ir.Node>
catchClauseInfos: catchClauseInfos);
}
}
class NullCapturedVariables extends DartCapturedVariables {
NullCapturedVariables() : super(null);
}
@@ -416,17 +416,6 @@ class ThisParameterLocal implements Local {
abstract class IrBuilder {
IrBuilder _makeInstance();
// TODO(johnniwinther): Remove this from the [IrBuilder].
/// A map from TryStatements in the AST to their analysis information.
///
/// This includes which variables should be copied into [ir.MutableVariable]s
/// on entry to the try and copied out on exit.
Map<ast.TryStatement, TryStatementInfo> get tryStatements;
/// The set of local variables that will spend their lifetime as
/// [ir.MutableVariable]s due to being captured by a nested function.
Set<Local> get mutableCapturedVariables;
/// True if [local] should currently be accessed from a [ir.MutableVariable].
bool isInMutableVariable(Local local);
@@ -1593,11 +1582,7 @@ abstract class IrBuilder {
// we can not identify all of them in the same pass where we identify the
// variables assigned in the try (they may be captured by a closure after
// the try statement).
Iterable<LocalVariableElement> boxedOnEntry =
tryStatementInfo.boxedOnEntry.where((LocalVariableElement variable) {
return !tryCatchBuilder.mutableCapturedVariables.contains(variable);
});
for (LocalVariableElement variable in boxedOnEntry) {
for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
assert(!tryCatchBuilder.isInMutableVariable(variable));
ir.Primitive value = tryCatchBuilder.buildLocalGet(variable);
tryCatchBuilder.makeMutableVariable(variable);
@@ -1607,7 +1592,7 @@ abstract class IrBuilder {
IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder();
void interceptJumps(JumpCollector collector) {
collector.enterTry(boxedOnEntry);
collector.enterTry(tryStatementInfo.boxedOnEntry);
}
void restoreJumps(JumpCollector collector) {
collector.leaveTry();
@@ -1624,7 +1609,7 @@ abstract class IrBuilder {
tryBuilder.state.continueCollectors.forEach(restoreJumps);
IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder();
for (LocalVariableElement variable in boxedOnEntry) {
for (LocalVariableElement variable in tryStatementInfo.boxedOnEntry) {
assert(catchBuilder.isInMutableVariable(variable));
ir.Primitive value = catchBuilder.buildLocalGet(variable);
// Note that we remove the variable from the set of mutable variables
@@ -1902,9 +1887,6 @@ class DartIrBuilderSharedState {
final Map<Local, ir.MutableVariable> local2mutable =
<Local, ir.MutableVariable>{};
// Move this to the IrBuilderVisitor.
final DartCapturedVariables capturedVariables;
/// Creates a [MutableVariable] for the given local.
void makeMutableVariable(Local local) {
ir.MutableVariable variable =
@@ -1915,8 +1897,8 @@ class DartIrBuilderSharedState {
/// [MutableVariable]s that should temporarily be treated as registers.
final Set<Local> registerizedMutableVariables = new Set<Local>();
DartIrBuilderSharedState(this.capturedVariables) {
capturedVariables.capturedVariables.forEach(makeMutableVariable);
DartIrBuilderSharedState(Set<Local> capturedVariables) {
capturedVariables.forEach(makeMutableVariable);
}
}
@@ -1935,19 +1917,11 @@ class DartIrBuilder extends IrBuilder {
DartIrBuilder(ConstantSystem constantSystem,
ExecutableElement currentElement,
DartCapturedVariables capturedVariables)
Set<Local> capturedVariables)
: dartState = new DartIrBuilderSharedState(capturedVariables) {
_init(constantSystem, currentElement);
}
Map<ast.TryStatement, TryStatementInfo> get tryStatements {
return dartState.capturedVariables.tryStatements;
}
Set<Local> get mutableCapturedVariables {
return dartState.capturedVariables.capturedVariables;
}
bool isInMutableVariable(Local local) {
return dartState.local2mutable.containsKey(local) &&
!dartState.registerizedMutableVariables.contains(local);
@@ -142,6 +142,14 @@ abstract class IrBuilderVisitor extends SemanticVisitor<ir.Primitive, dynamic>
final Compiler compiler;
final SourceInformationBuilder sourceInformationBuilder;
/// A map from try statements in the source to analysis information about
/// them.
///
/// The analysis information includes the set of variables that must be
/// copied into [ir.MutableVariable]s on entry to the try and copied out on
/// exit.
Map<ast.TryStatement, TryStatementInfo> tryStatements = null;
// In SSA terms, join-point continuation parameters are the phis and the
// continuation invocation arguments are the corresponding phi inputs. To
// support name introduction and renaming for source level variables, we use
@@ -471,7 +479,7 @@ abstract class IrBuilderVisitor extends SemanticVisitor<ir.Primitive, dynamic>
visitTryStatement(ast.TryStatement node) {
// Try/catch is not yet implemented in the JS backend.
if (this.irBuilder.tryStatements == null) {
if (tryStatements == null) {
return giveup(node, 'try/catch in the JS backend');
}
// Multiple catch blocks are not yet implemented.
@@ -503,7 +511,7 @@ abstract class IrBuilderVisitor extends SemanticVisitor<ir.Primitive, dynamic>
}
irBuilder.buildTry(
tryStatementInfo: irBuilder.tryStatements[node],
tryStatementInfo: tryStatements[node],
buildTryBlock: subbuild(node.tryBlock),
catchClauseInfos: catchClauseInfos);
}
@@ -1817,6 +1825,18 @@ class DartCapturedVariables extends ast.Visitor {
capturedVariables.add(local);
}
analyze(ast.Node node) {
visit(node);
// Variables that are captured by a closure are boxed for their entire
// lifetime, so they never need to be boxed on entry to a try block.
// They are not filtered out before this because we cannot identify all
// of them in the same pass (they may be captured by a closure after the
// try statement).
for (TryStatementInfo info in tryStatements.values) {
info.boxedOnEntry.removeAll(capturedVariables);
}
}
visit(ast.Node node) => node.accept(this);
visitNode(ast.Node node) {
@@ -1942,19 +1962,25 @@ class DartIrBuilderVisitor extends IrBuilderVisitor {
SourceInformationBuilder sourceInformationBuilder)
: super(elements, compiler, sourceInformationBuilder);
DartIrBuilder makeIRBuilder(ast.Node node, ExecutableElement element) {
DartCapturedVariables closures = new DartCapturedVariables(elements);
DartIrBuilder makeIRBuilder(ExecutableElement element,
Set<Local> capturedVariables) {
return new DartIrBuilder(compiler.backend.constantSystem,
element,
capturedVariables);
}
DartCapturedVariables _analyzeCapturedVariables(ExecutableElement element,
ast.Node node) {
DartCapturedVariables variables = new DartCapturedVariables(elements);
if (!element.isSynthesized) {
try {
closures.visit(node);
variables.analyze(node);
} catch (e) {
bailoutMessage = closures.bailoutMessage;
bailoutMessage = variables.bailoutMessage;
rethrow;
}
}
return new DartIrBuilder(compiler.backend.constantSystem,
element,
closures);
return variables;
}
/// Recursively builds the IR for the given nested function.
@@ -2003,7 +2029,10 @@ class DartIrBuilderVisitor extends IrBuilderVisitor {
assert(fieldDefinition != null);
assert(elements[fieldDefinition] != null);
IrBuilder builder = makeIRBuilder(fieldDefinition, element);
DartCapturedVariables variables =
_analyzeCapturedVariables(element, fieldDefinition);
tryStatements = variables.tryStatements;
IrBuilder builder = makeIRBuilder(element, variables.capturedVariables);
return withBuilder(builder, () {
builder.buildFieldInitializerHeader(
@@ -2034,7 +2063,10 @@ class DartIrBuilderVisitor extends IrBuilderVisitor {
}
}
IrBuilder builder = makeIRBuilder(node, element);
DartCapturedVariables variables =
_analyzeCapturedVariables(element, node);
tryStatements = variables.tryStatements;
IrBuilder builder = makeIRBuilder(element, variables.capturedVariables);
return withBuilder(builder, () => _makeFunctionBody(element, node));
}