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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_builder_task.dart

Issue 1410123005: dart2js cps: Remove unneeded bailout on captured loop variables. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Remove show clause for DartCapturedVariables Created 5 years, 1 month 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 unified diff | Download patch
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart ('k') | tests/co19/co19-dart2js.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.ir_builder_task; 5 library dart2js.ir_builder_task;
6 6
7 import '../closure.dart' as closurelib; 7 import '../closure.dart' as closurelib;
8 import '../closure.dart' hide ClosureScope; 8 import '../closure.dart' hide ClosureScope;
9 import '../common.dart'; 9 import '../common.dart';
10 import '../common/names.dart' show 10 import '../common/names.dart' show
(...skipping 2259 matching lines...) Expand 10 before | Expand all | Expand 10 after
2270 } 2270 }
2271 2271
2272 dynamic giveup(ast.Node node, [String reason]) { 2272 dynamic giveup(ast.Node node, [String reason]) {
2273 bailoutMessage = '($node): $reason'; 2273 bailoutMessage = '($node): $reason';
2274 throw ABORT_IRNODE_BUILDER; 2274 throw ABORT_IRNODE_BUILDER;
2275 } 2275 }
2276 } 2276 }
2277 2277
2278 final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; 2278 final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
2279 2279
2280 /// Classifies local variables and local functions as captured, if they 2280 /// Determines which local variables should be boxed in a mutable variable
2281 /// are accessed from within a nested function. 2281 /// inside a given try block.
2282 /// 2282 class TryBoxedVariables extends ast.Visitor {
2283 /// This class is specific to the [DartIrBuilder], in that it gives up if it
2284 /// sees a feature that is currently unsupport by that builder. In particular,
2285 /// loop variables captured in a for-loop initializer, condition, or update
2286 /// expression are unsupported.
2287 class DartCapturedVariables extends ast.Visitor {
2288 final TreeElements elements; 2283 final TreeElements elements;
2289 DartCapturedVariables(this.elements); 2284 TryBoxedVariables(this.elements);
2290 2285
2291 FunctionElement currentFunction; 2286 FunctionElement currentFunction;
2292 bool insideInitializer = false; 2287 bool insideInitializer = false;
2293 Set<Local> capturedVariables = new Set<Local>(); 2288 Set<Local> capturedVariables = new Set<Local>();
2294 2289
2295 /// A map containing variables boxed inside try blocks. 2290 /// A map containing variables boxed inside try blocks.
2296 /// 2291 ///
2297 /// The map is keyed by the [NodeList] of catch clauses for try/catch and 2292 /// The map is keyed by the [NodeList] of catch clauses for try/catch and
2298 /// by the finally block for try/finally. try/catch/finally is treated 2293 /// by the finally block for try/finally. try/catch/finally is treated
2299 /// as a try/catch nested in the try block of a try/finally. 2294 /// as a try/catch nested in the try block of a try/finally.
(...skipping 25 matching lines...) Expand all
2325 info.boxedOnEntry.removeAll(capturedVariables); 2320 info.boxedOnEntry.removeAll(capturedVariables);
2326 } 2321 }
2327 } 2322 }
2328 2323
2329 visit(ast.Node node) => node.accept(this); 2324 visit(ast.Node node) => node.accept(this);
2330 2325
2331 visitNode(ast.Node node) { 2326 visitNode(ast.Node node) {
2332 node.visitChildren(this); 2327 node.visitChildren(this);
2333 } 2328 }
2334 2329
2335 visitFor(ast.For node) {
2336 if (node.initializer != null) visit(node.initializer);
2337 if (node.condition != null) visit(node.condition);
2338 if (node.update != null) visit(node.update);
2339
2340 // Give up if a variable was captured outside of the loop body.
2341 if (node.initializer is ast.VariableDefinitions) {
2342 ast.VariableDefinitions definitions = node.initializer;
2343 for (ast.Node node in definitions.definitions.nodes) {
2344 LocalElement loopVariable = elements[node];
2345 if (capturedVariables.contains(loopVariable)) {
2346 return giveup(node, 'For-loop variable captured in loop header');
2347 }
2348 }
2349 }
2350
2351 if (node.body != null) visit(node.body);
2352 }
2353
2354 void handleSend(ast.Send node) { 2330 void handleSend(ast.Send node) {
2355 Element element = elements[node]; 2331 Element element = elements[node];
2356 if (Elements.isLocal(element) && 2332 if (Elements.isLocal(element) &&
2357 !element.isConst && 2333 !element.isConst &&
2358 element.enclosingElement != currentFunction) { 2334 element.enclosingElement != currentFunction) {
2359 LocalElement local = element; 2335 LocalElement local = element;
2360 markAsCaptured(local); 2336 markAsCaptured(local);
2361 } 2337 }
2362 } 2338 }
2363 2339
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
2401 node.visitChildren(this); 2377 node.visitChildren(this);
2402 } 2378 }
2403 2379
2404 visitFunctionExpression(ast.FunctionExpression node) { 2380 visitFunctionExpression(ast.FunctionExpression node) {
2405 FunctionElement savedFunction = currentFunction; 2381 FunctionElement savedFunction = currentFunction;
2406 currentFunction = elements[node]; 2382 currentFunction = elements[node];
2407 2383
2408 if (currentFunction.asyncMarker != AsyncMarker.SYNC && 2384 if (currentFunction.asyncMarker != AsyncMarker.SYNC &&
2409 currentFunction.asyncMarker != AsyncMarker.SYNC_STAR && 2385 currentFunction.asyncMarker != AsyncMarker.SYNC_STAR &&
2410 currentFunction.asyncMarker != AsyncMarker.ASYNC) { 2386 currentFunction.asyncMarker != AsyncMarker.ASYNC) {
2411 giveup(node, "cannot handle sync*/async* functions"); 2387 giveup(node, "cannot handle async* functions");
2412 } 2388 }
2413 2389
2414 bool savedInsideInitializer = insideInitializer;
2415 if (node.initializers != null) { 2390 if (node.initializers != null) {
2416 insideInitializer = true;
2417 visit(node.initializers); 2391 visit(node.initializers);
2418 } 2392 }
2419 insideInitializer = false;
2420 visit(node.body); 2393 visit(node.body);
2421 currentFunction = savedFunction; 2394 currentFunction = savedFunction;
2422 insideInitializer = savedInsideInitializer;
2423 } 2395 }
2424 2396
2425 visitTryStatement(ast.TryStatement node) { 2397 visitTryStatement(ast.TryStatement node) {
2426 // Try/catch/finally is treated as two simpler constructs: try/catch and 2398 // Try/catch/finally is treated as two simpler constructs: try/catch and
2427 // try/finally. The encoding is: 2399 // try/finally. The encoding is:
2428 // 2400 //
2429 // try S0 catch (ex, st) S1 finally S2 2401 // try S0 catch (ex, st) S1 finally S2
2430 // ==> 2402 // ==>
2431 // try { try S0 catch (ex, st) S1 } finally S2 2403 // try { try S0 catch (ex, st) S1 } finally S2
2432 // 2404 //
(...skipping 687 matching lines...) Expand 10 before | Expand all | Expand 10 after
3120 body.functionSignature.orderedForEachParameter((ParameterElement param) { 3092 body.functionSignature.orderedForEachParameter((ParameterElement param) {
3121 if (scope != null && scope.capturedVariables.containsKey(param)) { 3093 if (scope != null && scope.capturedVariables.containsKey(param)) {
3122 // Do not pass this parameter; the box will carry its value. 3094 // Do not pass this parameter; the box will carry its value.
3123 } else { 3095 } else {
3124 parameters.add(param); 3096 parameters.add(param);
3125 } 3097 }
3126 }); 3098 });
3127 return parameters; 3099 return parameters;
3128 } 3100 }
3129 3101
3130 DartCapturedVariables _analyzeCapturedVariables(ast.Node node) { 3102 TryBoxedVariables _analyzeTryBoxedVariables(ast.Node node) {
3131 DartCapturedVariables variables = new DartCapturedVariables(elements); 3103 TryBoxedVariables variables = new TryBoxedVariables(elements);
3132 try { 3104 try {
3133 variables.analyze(node); 3105 variables.analyze(node);
3134 } catch (e) { 3106 } catch (e) {
3135 bailoutMessage = variables.bailoutMessage; 3107 bailoutMessage = variables.bailoutMessage;
3136 rethrow; 3108 rethrow;
3137 } 3109 }
3138 return variables; 3110 return variables;
3139 } 3111 }
3140 3112
3141 /// Builds the IR for the body of a constructor. 3113 /// Builds the IR for the body of a constructor.
3142 /// 3114 ///
3143 /// This function is invoked from one or more "factory" constructors built by 3115 /// This function is invoked from one or more "factory" constructors built by
3144 /// [buildConstructor]. 3116 /// [buildConstructor].
3145 ir.FunctionDefinition buildConstructorBody(ConstructorBodyElement body) { 3117 ir.FunctionDefinition buildConstructorBody(ConstructorBodyElement body) {
3146 ConstructorElement constructor = body.constructor; 3118 ConstructorElement constructor = body.constructor;
3147 ast.FunctionExpression node = constructor.node; 3119 ast.FunctionExpression node = constructor.node;
3148 closureClassMap = 3120 closureClassMap =
3149 compiler.closureToClassMapper.computeClosureToClassMapping( 3121 compiler.closureToClassMapper.computeClosureToClassMapping(
3150 constructor, 3122 constructor,
3151 node, 3123 node,
3152 elements); 3124 elements);
3153 3125
3154 // We compute variables boxed in mutable variables on entry to each try 3126 // We compute variables boxed in mutable variables on entry to each try
3155 // block, not including variables captured by a closure (which are boxed 3127 // block, not including variables captured by a closure (which are boxed
3156 // in the heap). This duplicates some of the work of closure conversion 3128 // in the heap). This duplicates some of the work of closure conversion
3157 // without directly using the results. This duplication is wasteful and 3129 // without directly using the results. This duplication is wasteful and
3158 // error-prone. 3130 // error-prone.
3159 // TODO(kmillikin): We should combine closure conversion and try/catch 3131 // TODO(kmillikin): We should combine closure conversion and try/catch
3160 // variable analysis in some way. 3132 // variable analysis in some way.
3161 DartCapturedVariables variables = _analyzeCapturedVariables(node); 3133 TryBoxedVariables variables = _analyzeTryBoxedVariables(node);
3162 tryStatements = variables.tryStatements; 3134 tryStatements = variables.tryStatements;
3163 IrBuilder builder = getBuilderFor(body); 3135 IrBuilder builder = getBuilderFor(body);
3164 3136
3165 return withBuilder(builder, () { 3137 return withBuilder(builder, () {
3166 irBuilder.buildConstructorBodyHeader(getConstructorBodyParameters(body), 3138 irBuilder.buildConstructorBodyHeader(getConstructorBodyParameters(body),
3167 getClosureScopeForNode(node)); 3139 getClosureScopeForNode(node));
3168 visit(node.body); 3140 visit(node.body);
3169 return irBuilder.makeFunctionDefinition(); 3141 return irBuilder.makeFunctionDefinition();
3170 }); 3142 });
3171 } 3143 }
3172 3144
3173 ir.FunctionDefinition buildFunction(FunctionElement element) { 3145 ir.FunctionDefinition buildFunction(FunctionElement element) {
3174 assert(invariant(element, element.isImplementation)); 3146 assert(invariant(element, element.isImplementation));
3175 ast.FunctionExpression node = element.node; 3147 ast.FunctionExpression node = element.node;
3176 3148
3177 assert(!element.isSynthesized); 3149 assert(!element.isSynthesized);
3178 assert(node != null); 3150 assert(node != null);
3179 assert(elements[node] != null); 3151 assert(elements[node] != null);
3180 3152
3181 closureClassMap = 3153 closureClassMap =
3182 compiler.closureToClassMapper.computeClosureToClassMapping( 3154 compiler.closureToClassMapper.computeClosureToClassMapping(
3183 element, 3155 element,
3184 node, 3156 node,
3185 elements); 3157 elements);
3186 DartCapturedVariables variables = _analyzeCapturedVariables(node); 3158 TryBoxedVariables variables = _analyzeTryBoxedVariables(node);
3187 tryStatements = variables.tryStatements; 3159 tryStatements = variables.tryStatements;
3188 IrBuilder builder = getBuilderFor(element); 3160 IrBuilder builder = getBuilderFor(element);
3189 return withBuilder(builder, () => _makeFunctionBody(element, node)); 3161 return withBuilder(builder, () => _makeFunctionBody(element, node));
3190 } 3162 }
3191 3163
3192 /// Creates a primitive for the default value of [parameter]. 3164 /// Creates a primitive for the default value of [parameter].
3193 ir.Primitive translateDefaultValue(ParameterElement parameter) { 3165 ir.Primitive translateDefaultValue(ParameterElement parameter) {
3194 if (parameter.initializer == null) { 3166 if (parameter.initializer == null) {
3195 return irBuilder.buildNullConstant(); 3167 return irBuilder.buildNullConstant();
3196 } else { 3168 } else {
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
3579 if (compiler.backend.isForeign(function)) { 3551 if (compiler.backend.isForeign(function)) {
3580 return handleForeignCode(node, function, argumentList, callStructure); 3552 return handleForeignCode(node, function, argumentList, callStructure);
3581 } else { 3553 } else {
3582 return irBuilder.buildStaticFunctionInvocation(function, callStructure, 3554 return irBuilder.buildStaticFunctionInvocation(function, callStructure,
3583 translateStaticArguments(argumentList, function, callStructure), 3555 translateStaticArguments(argumentList, function, callStructure),
3584 sourceInformation: 3556 sourceInformation:
3585 sourceInformationBuilder.buildCall(node, node.selector)); 3557 sourceInformationBuilder.buildCall(node, node.selector));
3586 } 3558 }
3587 } 3559 }
3588 } 3560 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart ('k') | tests/co19/co19-dart2js.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698