From 34fc9fb911ed033bf8aed5567da072b79939cc1d Mon Sep 17 00:00:00 2001 From: "kmillikin@google.com" Date: Thu, 9 Apr 2015 14:17:36 +0000 Subject: [PATCH] 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 --- pkg/analyzer2dart/lib/src/cps_generator.dart | 16 +++--- .../lib/src/cps_ir/cps_ir_builder.dart | 38 +++---------- .../lib/src/cps_ir/cps_ir_builder_task.dart | 54 +++++++++++++++---- 3 files changed, 55 insertions(+), 53 deletions(-) diff --git a/pkg/analyzer2dart/lib/src/cps_generator.dart b/pkg/analyzer2dart/lib/src/cps_generator.dart index 4ad4fc642f8..2360c161bbe 100644 --- a/pkg/analyzer2dart/lib/src/cps_generator.dart +++ b/pkg/analyzer2dart/lib/src/cps_generator.dart @@ -95,8 +95,8 @@ class CpsGeneratingVisitor extends SemanticVisitor return withBuilder( new DartIrBuilder(DART_CONSTANT_SYSTEM, element, - // TODO(johnniwinther): Supported closure variables. - new NullCapturedVariables()), + // TODO(johnniwinther): Support closure variables. + new Set()), () { irBuilder.buildFunctionHeader( constructor.parameters.map(converter.convertElement)); @@ -114,8 +114,8 @@ class CpsGeneratingVisitor extends SemanticVisitor return withBuilder( new DartIrBuilder(DART_CONSTANT_SYSTEM, element, - // TODO(johnniwinther): Supported closure variables. - new NullCapturedVariables()), + // TODO(johnniwinther): Support closure variables. + new Set()), () { irBuilder.buildFieldInitializerHeader(); ir.Primitive initializer = build(node.initializer); @@ -129,8 +129,8 @@ class CpsGeneratingVisitor extends SemanticVisitor return withBuilder( new DartIrBuilder(DART_CONSTANT_SYSTEM, element, - // TODO(johnniwinther): Supported closure variables. - new NullCapturedVariables()), + // TODO(johnniwinther): Support closure variables. + new Set()), () { irBuilder.buildFunctionHeader( function.parameters.map(converter.convertElement)); @@ -585,7 +585,3 @@ class CpsGeneratingVisitor extends SemanticVisitor catchClauseInfos: catchClauseInfos); } } - -class NullCapturedVariables extends DartCapturedVariables { - NullCapturedVariables() : super(null); -} 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 37d0fa408d0..5f35a3f0779 100644 --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart @@ -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 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 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 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 local2mutable = {}; - // 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 registerizedMutableVariables = new Set(); - DartIrBuilderSharedState(this.capturedVariables) { - capturedVariables.capturedVariables.forEach(makeMutableVariable); + DartIrBuilderSharedState(Set capturedVariables) { + capturedVariables.forEach(makeMutableVariable); } } @@ -1935,19 +1917,11 @@ class DartIrBuilder extends IrBuilder { DartIrBuilder(ConstantSystem constantSystem, ExecutableElement currentElement, - DartCapturedVariables capturedVariables) + Set capturedVariables) : dartState = new DartIrBuilderSharedState(capturedVariables) { _init(constantSystem, currentElement); } - Map get tryStatements { - return dartState.capturedVariables.tryStatements; - } - - Set get mutableCapturedVariables { - return dartState.capturedVariables.capturedVariables; - } - bool isInMutableVariable(Local local) { return dartState.local2mutable.containsKey(local) && !dartState.registerizedMutableVariables.contains(local); diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart index e56a32dd7d6..289b230a7c3 100644 --- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart +++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart @@ -142,6 +142,14 @@ abstract class IrBuilderVisitor extends SemanticVisitor 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 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 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 } 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 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)); }