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

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

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

Powered by Google App Engine
This is Rietveld 408576698