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

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

Issue 1414043011: Mark returns from inside the try of a try/catch as ones that exit the try. (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 | no next file » | 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; 5 library dart2js.ir_builder;
6 6
7 import '../closure.dart' hide ClosureScope; 7 import '../closure.dart' hide ClosureScope;
8 import '../common.dart'; 8 import '../common.dart';
9 import '../common/names.dart' show 9 import '../common/names.dart' show
10 Names, 10 Names,
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 /// Construct a collector for a given environment and optionally a target. 152 /// Construct a collector for a given environment and optionally a target.
153 /// 153 ///
154 /// The environment is the one in effect at the point where the jump's 154 /// The environment is the one in effect at the point where the jump's
155 /// continuation will be bound. Continuations can take an extra argument 155 /// continuation will be bound. Continuations can take an extra argument
156 /// (see [addJump]). 156 /// (see [addJump]).
157 JumpCollector(this._continuationEnvironment, this.target, 157 JumpCollector(this._continuationEnvironment, this.target,
158 bool hasExtraArgument) { 158 bool hasExtraArgument) {
159 if (hasExtraArgument) _continuationEnvironment.extend(null, null); 159 if (hasExtraArgument) _continuationEnvironment.extend(null, null);
160 } 160 }
161 161
162 /// Construct a collector for collecting only return jumps.
163 ///
164 /// There is no jump target, it is implicitly the exit from the function.
165 /// There is no environment at the destination.
166 JumpCollector.retrn(this._continuation)
167 : _continuationEnvironment = null, target = null;
168
162 /// True if the collector has not recorded any jumps to its continuation. 169 /// True if the collector has not recorded any jumps to its continuation.
163 bool get isEmpty; 170 bool get isEmpty;
164 171
165 /// The continuation encapsulated by this collector. 172 /// The continuation encapsulated by this collector.
166 ir.Continuation get continuation; 173 ir.Continuation get continuation;
167 174
168 /// The compile-time environment to be used for translating code in the body 175 /// The compile-time environment to be used for translating code in the body
169 /// of the continuation. 176 /// of the continuation.
170 Environment get environment; 177 Environment get environment;
171 178
172 /// Emit a jump to the continuation for a given [IrBuilder]. 179 /// Emit a jump to the continuation for a given [IrBuilder].
173 /// 180 ///
174 /// Jumps can take a single extra argument. This is used to pass return 181 /// Jumps can take a single extra argument. This is used to pass return
175 /// values to finally blocks for returns inside try/finally and to pass 182 /// values to finally blocks for returns inside try/finally and to pass
176 /// values of expressions that have internal control flow to their join-point 183 /// values of expressions that have internal control flow to their join-point
177 /// continuations. 184 /// continuations.
178 void addJump(IrBuilder builder, [ir.Primitive value]); 185 void addJump(IrBuilder builder,
186 [ir.Primitive value, SourceInformation sourceInformation]);
179 187
180 /// Add a set of variables that were boxed on entry to a try block. 188 /// Add a set of variables that were boxed on entry to a try block.
181 /// 189 ///
182 /// All jumps from a try block to targets outside have to unbox the 190 /// All jumps from a try block to targets outside have to unbox the
183 /// variables that were boxed on entry before invoking the target 191 /// variables that were boxed on entry before invoking the target
184 /// continuation. Call this function before translating a try block and 192 /// continuation. Call this function before translating a try block and
185 /// call [leaveTry] after translating it. 193 /// call [leaveTry] after translating it.
186 void enterTry(Iterable<LocalVariableElement> boxedOnEntry) { 194 void enterTry(Iterable<LocalVariableElement> boxedOnEntry) {
187 // The boxed variables are maintained as a stack to make leaving easy. 195 // The boxed variables are maintained as a stack to make leaving easy.
188 _boxedTryVariables.add(boxedOnEntry); 196 _boxedTryVariables.add(boxedOnEntry);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 ir.Continuation get continuation { 260 ir.Continuation get continuation {
253 if (_continuation == null) _setContinuation(); 261 if (_continuation == null) _setContinuation();
254 return _continuation; 262 return _continuation;
255 } 263 }
256 264
257 Environment get environment { 265 Environment get environment {
258 if (_continuation == null) _setContinuation(); 266 if (_continuation == null) _setContinuation();
259 return _continuationEnvironment; 267 return _continuationEnvironment;
260 } 268 }
261 269
262 void addJump(IrBuilder builder, [ir.Primitive value]) { 270 void addJump(IrBuilder builder,
271 [ir.Primitive value, SourceInformation sourceInformation]) {
263 assert(_continuation == null); 272 assert(_continuation == null);
264 _buildTryExit(builder); 273 _buildTryExit(builder);
265 ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized( 274 ir.InvokeContinuation invoke = new ir.InvokeContinuation.uninitialized(
266 isEscapingTry: isEscapingTry); 275 isEscapingTry: isEscapingTry);
267 builder.add(invoke); 276 builder.add(invoke);
268 _invocations.add(invoke); 277 _invocations.add(invoke);
269 // Truncate the environment at the invocation site so it only includes 278 // Truncate the environment at the invocation site so it only includes
270 // values that will be continuation arguments. If an extra value is passed 279 // values that will be continuation arguments. If an extra value is passed
271 // it will already be included in the continuation environment, but it is 280 // it will already be included in the continuation environment, but it is
272 // not present in the invocation environment. 281 // not present in the invocation environment.
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 List<ir.Parameter> parameters = 370 List<ir.Parameter> parameters =
362 new List<ir.Parameter>.from(_continuationEnvironment.index2value); 371 new List<ir.Parameter>.from(_continuationEnvironment.index2value);
363 _continuation = new ir.Continuation(parameters, isRecursive: true); 372 _continuation = new ir.Continuation(parameters, isRecursive: true);
364 } 373 }
365 374
366 bool isEmpty = true; 375 bool isEmpty = true;
367 376
368 ir.Continuation get continuation => _continuation; 377 ir.Continuation get continuation => _continuation;
369 Environment get environment => _continuationEnvironment; 378 Environment get environment => _continuationEnvironment;
370 379
371 void addJump(IrBuilder builder, [ir.Primitive value]) { 380 void addJump(IrBuilder builder,
381 [ir.Primitive value, SourceInformation sourceInformation]) {
372 assert(_continuation.parameters.length <= builder.environment.length); 382 assert(_continuation.parameters.length <= builder.environment.length);
373 isEmpty = false; 383 isEmpty = false;
374 _buildTryExit(builder); 384 _buildTryExit(builder);
375 // Truncate the environment at the invocation site so it only includes 385 // Truncate the environment at the invocation site so it only includes
376 // values that will be continuation arguments. If an extra value is passed 386 // values that will be continuation arguments. If an extra value is passed
377 // it will already be included in the continuation environment, but it is 387 // it will already be included in the continuation environment, but it is
378 // not present in the invocation environment. 388 // not present in the invocation environment.
379 int delta = builder.environment.length - _continuationEnvironment.length; 389 int delta = builder.environment.length - _continuationEnvironment.length;
380 if (value != null) ++delta; 390 if (value != null) ++delta;
381 if (delta > 0) builder.environment.discard(delta); 391 if (delta > 0) builder.environment.discard(delta);
382 if (value != null) builder.environment.extend(null, value); 392 if (value != null) builder.environment.extend(null, value);
383 builder.add(new ir.InvokeContinuation(_continuation, 393 builder.add(new ir.InvokeContinuation(_continuation,
384 builder.environment.index2value, 394 builder.environment.index2value,
385 isRecursive: true, 395 isRecursive: true,
386 isEscapingTry: isEscapingTry)); 396 isEscapingTry: isEscapingTry));
387 builder._current = null; 397 builder._current = null;
388 } 398 }
389 } 399 }
390 400
401 /// Collect 'return' jumps.
402 ///
403 /// A return jump is one that targets the return continuation of a function.
404 /// Thus, returns from inside try/finally are not return jumps because they are
405 /// intercepted by a block that contains the finally handler code.
406 class ReturnJumpCollector extends JumpCollector {
407 bool isEmpty = true;
408 ir.Continuation get continuation => _continuation;
409 Environment environment = null;
410
411 /// Construct a return jump collector for a given return continuation.
412 ReturnJumpCollector(ir.Continuation continuation) : super.retrn(continuation);
413
414 void addJump(IrBuilder builder,
415 [ir.Primitive value, SourceInformation sourceInformation]) {
416 isEmpty = false;
417 builder.add(new ir.InvokeContinuation(continuation, <ir.Primitive>[value],
418 isEscapingTry: isEscapingTry,
419 sourceInformation: sourceInformation));
420 builder._current = null;
421 }
422 }
423
391 /// Function for building a node in the context of the current builder. 424 /// Function for building a node in the context of the current builder.
392 typedef ir.Node BuildFunction(node); 425 typedef ir.Node BuildFunction(node);
393 426
394 /// Function for building nodes in the context of the provided [builder]. 427 /// Function for building nodes in the context of the provided [builder].
395 typedef ir.Node SubbuildFunction(IrBuilder builder); 428 typedef ir.Node SubbuildFunction(IrBuilder builder);
396 429
397 /// Mixin that provides encapsulated access to nested builders. 430 /// Mixin that provides encapsulated access to nested builders.
398 abstract class IrBuilderMixin<N> { 431 abstract class IrBuilderMixin<N> {
399 IrBuilder _irBuilder; 432 IrBuilder _irBuilder;
400 433
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 492
460 final ExecutableElement currentElement; 493 final ExecutableElement currentElement;
461 494
462 final ir.Continuation returnContinuation = new ir.Continuation.retrn(); 495 final ir.Continuation returnContinuation = new ir.Continuation.retrn();
463 496
464 /// The target of a return from the function. 497 /// The target of a return from the function.
465 /// 498 ///
466 /// A null value indicates that the target is the function's return 499 /// A null value indicates that the target is the function's return
467 /// continuation. Otherwise, when inside the try block of try/finally 500 /// continuation. Otherwise, when inside the try block of try/finally
468 /// a return is intercepted to give a place to generate the finally code. 501 /// a return is intercepted to give a place to generate the finally code.
469 JumpCollector returnCollector = null; 502 JumpCollector returnCollector;
470 503
471 /// Parameter holding the internal value of 'this' passed to the function. 504 /// Parameter holding the internal value of 'this' passed to the function.
472 /// 505 ///
473 /// For nested functions, this is *not* captured receiver, but the function 506 /// For nested functions, this is *not* captured receiver, but the function
474 /// object itself. 507 /// object itself.
475 ir.Parameter thisParameter; 508 ir.Parameter thisParameter;
476 509
477 /// If non-null, this refers to the receiver (`this`) in the enclosing method. 510 /// If non-null, this refers to the receiver (`this`) in the enclosing method.
478 ir.Primitive enclosingThis; 511 ir.Primitive enclosingThis;
479 512
480 final List<ir.Parameter> functionParameters = <ir.Parameter>[]; 513 final List<ir.Parameter> functionParameters = <ir.Parameter>[];
481 514
482 /// Maps boxed locals to their location. These locals are not part of 515 /// Maps boxed locals to their location. These locals are not part of
483 /// the environment. 516 /// the environment.
484 final Map<Local, ClosureLocation> boxedVariables = {}; 517 final Map<Local, ClosureLocation> boxedVariables = {};
485 518
486 IrBuilderSharedState(this.program, this.constants, this.currentElement); 519 IrBuilderSharedState(this.program, this.constants, this.currentElement) {
520 returnCollector = new ReturnJumpCollector(returnContinuation);
521 }
487 } 522 }
488 523
489 class ThisParameterLocal implements Local { 524 class ThisParameterLocal implements Local {
490 final ExecutableElement executableContext; 525 final ExecutableElement executableContext;
491 ThisParameterLocal(this.executableContext); 526 ThisParameterLocal(this.executableContext);
492 String get name => 'this'; 527 String get name => 'this';
493 toString() => 'ThisParameterLocal($executableContext)'; 528 toString() => 'ThisParameterLocal($executableContext)';
494 } 529 }
495 530
496 /// The IR builder maintains an environment and an IR fragment. 531 /// The IR builder maintains an environment and an IR fragment.
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after
1153 if (elseBuilder._root != null) _current = elseBuilder._current; 1188 if (elseBuilder._root != null) _current = elseBuilder._current;
1154 environment = elseBuilder.environment; 1189 environment = elseBuilder.environment;
1155 } else { 1190 } else {
1156 _current = null; 1191 _current = null;
1157 } 1192 }
1158 } else { 1193 } else {
1159 environment = join.environment; 1194 environment = join.environment;
1160 } 1195 }
1161 } 1196 }
1162 1197
1163 void jumpTo(JumpCollector collector, [ir.Primitive value]) { 1198 void jumpTo(JumpCollector collector,
1164 collector.addJump(this, value); 1199 [ir.Primitive value, SourceInformation sourceInformation]) {
1200 collector.addJump(this, value, sourceInformation);
1165 } 1201 }
1166 1202
1167 void addRecursiveContinuation(BackwardJumpCollector collector) { 1203 void addRecursiveContinuation(BackwardJumpCollector collector) {
1168 assert(environment.length == collector.environment.length); 1204 assert(environment.length == collector.environment.length);
1169 add(new ir.LetCont(collector.continuation, 1205 add(new ir.LetCont(collector.continuation,
1170 new ir.InvokeContinuation(collector.continuation, 1206 new ir.InvokeContinuation(collector.continuation,
1171 environment.index2value))); 1207 environment.index2value)));
1172 environment = collector.environment; 1208 environment = collector.environment;
1173 } 1209 }
1174 1210
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after
1804 // variables are unboxed in the catch block and at the join point. 1840 // variables are unboxed in the catch block and at the join point.
1805 1841
1806 void enterTry(IrBuilder builder) { 1842 void enterTry(IrBuilder builder) {
1807 // On entry to try of try/catch, update the builder's state to reflect the 1843 // On entry to try of try/catch, update the builder's state to reflect the
1808 // variables that have been boxed. 1844 // variables that have been boxed.
1809 void interceptJump(JumpCollector collector) { 1845 void interceptJump(JumpCollector collector) {
1810 collector.enterTry(variables.boxedOnEntry); 1846 collector.enterTry(variables.boxedOnEntry);
1811 } 1847 }
1812 builder.state.breakCollectors.forEach(interceptJump); 1848 builder.state.breakCollectors.forEach(interceptJump);
1813 builder.state.continueCollectors.forEach(interceptJump); 1849 builder.state.continueCollectors.forEach(interceptJump);
1850 interceptJump(builder.state.returnCollector);
1814 } 1851 }
1815 1852
1816 void leaveTry(IrBuilder builder) { 1853 void leaveTry(IrBuilder builder) {
1817 // On exit from try of try/catch, update the builder's state to reflect 1854 // On exit from try of try/catch, update the builder's state to reflect
1818 // the variables that are no longer boxed. 1855 // the variables that are no longer boxed.
1819 void restoreJump(JumpCollector collector) { 1856 void restoreJump(JumpCollector collector) {
1820 collector.leaveTry(); 1857 collector.leaveTry();
1821 } 1858 }
1822 builder.state.breakCollectors.forEach(restoreJump); 1859 builder.state.breakCollectors.forEach(restoreJump);
1823 builder.state.continueCollectors.forEach(restoreJump); 1860 builder.state.continueCollectors.forEach(restoreJump);
1861 restoreJump(builder.state.returnCollector);
1824 } 1862 }
1825 1863
1826 List<ir.Parameter> buildCatch(IrBuilder builder, 1864 List<ir.Parameter> buildCatch(IrBuilder builder,
1827 JumpCollector join) { 1865 JumpCollector join) {
1828 // Translate the catch clauses. Multiple clauses are translated as if 1866 // Translate the catch clauses. Multiple clauses are translated as if
1829 // they were explicitly cascaded if/else type tests. 1867 // they were explicitly cascaded if/else type tests.
1830 1868
1831 // Handlers are always translated as having both exception and stack trace 1869 // Handlers are always translated as having both exception and stack trace
1832 // parameters. Multiple clauses do not have to use the same names for 1870 // parameters. Multiple clauses do not have to use the same names for
1833 // them. Choose the first of each as the name hint for the respective 1871 // them. Choose the first of each as the name hint for the respective
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
2022 /// null. 2060 /// null.
2023 void buildReturn({ir.Primitive value, SourceInformation sourceInformation}) { 2061 void buildReturn({ir.Primitive value, SourceInformation sourceInformation}) {
2024 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] 2062 // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
2025 // where (C', x) = Build(e, C) 2063 // where (C', x) = Build(e, C)
2026 // 2064 //
2027 // Return without a subexpression is translated as if it were return null. 2065 // Return without a subexpression is translated as if it were return null.
2028 assert(isOpen); 2066 assert(isOpen);
2029 if (value == null) { 2067 if (value == null) {
2030 value = buildNullConstant(); 2068 value = buildNullConstant();
2031 } 2069 }
2032 if (state.returnCollector == null) { 2070 jumpTo(state.returnCollector, value, sourceInformation);
2033 add(new ir.InvokeContinuation(state.returnContinuation, [value],
2034 sourceInformation: sourceInformation));
2035 _current = null;
2036 } else {
2037 // Inside the try block of try/finally, all returns go to a join-point
2038 // continuation that contains the finally code. The return value is
2039 // passed as an extra argument.
2040 jumpTo(state.returnCollector, value);
2041 }
2042 } 2071 }
2043 2072
2044 /// Build a call to the closure conversion helper for the [Function] typed 2073 /// Build a call to the closure conversion helper for the [Function] typed
2045 /// value in [value]. 2074 /// value in [value].
2046 ir.Primitive _convertDartClosure(ir.Primitive value, FunctionType type) { 2075 ir.Primitive _convertDartClosure(ir.Primitive value, FunctionType type) {
2047 ir.Constant arity = buildIntegerConstant(type.computeArity()); 2076 ir.Constant arity = buildIntegerConstant(type.computeArity());
2048 return buildStaticFunctionInvocation( 2077 return buildStaticFunctionInvocation(
2049 program.closureConverter, 2078 program.closureConverter,
2050 CallStructure.TWO_ARGS, 2079 CallStructure.TWO_ARGS,
2051 <ir.Primitive>[value, arity]); 2080 <ir.Primitive>[value, arity]);
(...skipping 837 matching lines...) Expand 10 before | Expand all | Expand 10 after
2889 } 2918 }
2890 2919
2891 class SwitchCaseInfo { 2920 class SwitchCaseInfo {
2892 final List<ir.Primitive> constants = <ir.Primitive>[]; 2921 final List<ir.Primitive> constants = <ir.Primitive>[];
2893 final SubbuildFunction buildBody; 2922 final SubbuildFunction buildBody;
2894 2923
2895 SwitchCaseInfo(this.buildBody); 2924 SwitchCaseInfo(this.buildBody);
2896 2925
2897 void addConstant(ir.Primitive constant) => constants.add(constant); 2926 void addConstant(ir.Primitive constant) => constants.add(constant);
2898 } 2927 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698