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

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

Issue 979813002: Support simple try in analyzer2dart. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 months 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 | Annotate | Revision Log
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 '../constants/expressions.dart'; 7 import '../constants/expressions.dart';
8 import '../constants/values.dart' show PrimitiveConstantValue; 8 import '../constants/values.dart' show PrimitiveConstantValue;
9 import '../dart_types.dart'; 9 import '../dart_types.dart';
10 import '../dart2jslib.dart'; 10 import '../dart2jslib.dart';
11 import '../elements/elements.dart'; 11 import '../elements/elements.dart';
12 import '../io/source_file.dart'; 12 import '../io/source_file.dart';
13 import '../io/source_information.dart'; 13 import '../io/source_information.dart';
14 import '../tree/tree.dart' as ast; 14 import '../tree/tree.dart' as ast;
15 import '../scanner/scannerlib.dart' show Token, isUserDefinableOperator; 15 import '../scanner/scannerlib.dart' show Token, isUserDefinableOperator;
16 import '../universe/universe.dart' show SelectorKind; 16 import '../universe/universe.dart' show SelectorKind;
17 import 'cps_ir_nodes.dart' as ir; 17 import 'cps_ir_nodes.dart' as ir;
18 import '../elements/modelx.dart' show SynthesizedConstructorElementX, 18 import '../elements/modelx.dart' show SynthesizedConstructorElementX,
19 ConstructorBodyElementX, FunctionSignatureX; 19 ConstructorBodyElementX, FunctionSignatureX;
20 import '../closure.dart' hide ClosureScope; 20 import '../closure.dart' hide ClosureScope;
21 import '../closure.dart' as closurelib; 21 import '../closure.dart' as closurelib;
22 import '../js_backend/js_backend.dart' show JavaScriptBackend; 22 import '../js_backend/js_backend.dart' show JavaScriptBackend;
23 import '../util/util.dart' show Link;
23 24
24 part 'cps_ir_builder_visitor.dart'; 25 part 'cps_ir_builder_visitor.dart';
25 26
26 /// A mapping from variable elements to their compile-time values. 27 /// A mapping from variable elements to their compile-time values.
27 /// 28 ///
28 /// Map elements denoted by parameters and local variables to the 29 /// Map elements denoted by parameters and local variables to the
29 /// [ir.Primitive] that is their value. Parameters and locals are 30 /// [ir.Primitive] that is their value. Parameters and locals are
30 /// assigned indexes which can be used to refer to them. 31 /// assigned indexes which can be used to refer to them.
31 class Environment { 32 class Environment {
32 /// A map from locals to their environment index. 33 /// A map from locals to their environment index.
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 IrBuilderDelimitedState(this.constantSystem, this.currentElement); 234 IrBuilderDelimitedState(this.constantSystem, this.currentElement);
234 } 235 }
235 236
236 /// A factory for building the cps IR. 237 /// A factory for building the cps IR.
237 /// 238 ///
238 /// [DartIrBuilder] and [JsIrBuilder] implement nested functions and captured 239 /// [DartIrBuilder] and [JsIrBuilder] implement nested functions and captured
239 /// variables in different ways. 240 /// variables in different ways.
240 abstract class IrBuilder { 241 abstract class IrBuilder {
241 IrBuilder _makeInstance(); 242 IrBuilder _makeInstance();
242 243
244 // TODO(johnniwinther): Remove this from the [IrBuilder].
243 /// A map from TryStatements in the AST to their analysis information. 245 /// A map from TryStatements in the AST to their analysis information.
244 /// 246 ///
245 /// This includes which variables should be copied into [ir.MutableVariable]s 247 /// This includes which variables should be copied into [ir.MutableVariable]s
246 /// on entry to the try and copied out on exit. 248 /// on entry to the try and copied out on exit.
247 Map<ast.TryStatement, TryStatementInfo> get tryStatements; 249 Map<ast.TryStatement, TryStatementInfo> get tryStatements;
248 250
249 /// The set of local variables that will spend their lifetime as 251 /// The set of local variables that will spend their lifetime as
250 /// [ir.MutableVariable]s due to being captured by a nested function. 252 /// [ir.MutableVariable]s due to being captured by a nested function.
251 Set<Local> get mutableCapturedVariables; 253 Set<Local> get mutableCapturedVariables;
252 254
(...skipping 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after
1277 breakCollector.addJump(this); 1279 breakCollector.addJump(this);
1278 letJoin.continuations = 1280 letJoin.continuations =
1279 <ir.Continuation>[createJoin(environment.length, breakCollector)]; 1281 <ir.Continuation>[createJoin(environment.length, breakCollector)];
1280 _current = letJoin; 1282 _current = letJoin;
1281 } else { 1283 } else {
1282 _current = condBuilder._current; 1284 _current = condBuilder._current;
1283 environment = condBuilder.environment; 1285 environment = condBuilder.environment;
1284 } 1286 }
1285 } 1287 }
1286 1288
1289 /// Creates a try-statement.
1290 ///
1291 /// [tryInfo] provides information on local variables declared and boxed
1292 /// within this try statement.
1293 /// [buildTryBlock] builds the try block.
1294 /// [catchClauseInfos] provides access to the catch type, exception variable,
1295 /// and stack trace variable, and a function for building the catch block.
1296 void buildTry(
1297 {TryStatementInfo tryStatementInfo,
1298 SubbuildFunction buildTryBlock,
1299 List<CatchClauseInfo> catchClauseInfos: const <CatchClauseInfo>[]}) {
1300 assert(isOpen);
1301
1302 // Catch handlers are in scope for their body. The CPS translation of
1303 // [[try tryBlock catch (e) catchBlock; successor]] is:
1304 //
1305 // let cont join(v0, v1, ...) = [[successor]] in
1306 // let mutable m0 = x0 in
1307 // let mutable m1 = x1 in
1308 // ...
1309 // let handler catch_(e) =
1310 // let prim p0 = GetMutable(m0) in
1311 // let prim p1 = GetMutable(m1) in
1312 // ...
1313 // [[catchBlock]]
1314 // join(p0, p1, ...)
1315 // in
1316 // [[tryBlock]]
1317 // let prim p0' = GetMutable(m0) in
1318 // let prim p1' = GetMutable(m1) in
1319 // ...
1320 // join(p0', p1', ...)
1321 //
1322 // In other words, both the try and catch block are in the scope of the
1323 // join-point continuation, and they are both in the scope of a sequence
1324 // of mutable bindings for the variables assigned in the try. The join-
1325 // point continuation is not in the scope of these mutable bindings.
1326 // The tryBlock is in the scope of a binding for the catch handler. Each
1327 // instruction (specifically, each call) in the tryBlock is in the dynamic
1328 // scope of the handler. The mutable bindings are dereferenced at the end
1329 // of the try block and at the beginning of the catch block, so the
1330 // variables are unboxed in the catch block and at the join point.
1331
1332 IrBuilder tryCatchBuilder = makeDelimitedBuilder();
1333 // Variables that are boxed due to being captured in a closure are boxed
1334 // for their entire lifetime, and so they do not need to be boxed on
1335 // entry to any try block. We check for them here because we can not
1336 // identify all of them in the same pass where we identify the variables
1337 // assigned in the try (the may be captured by a closure after the try
1338 // statement).
1339 Iterable<LocalVariableElement> boxedOnEntry =
1340 tryStatementInfo.boxedOnEntry.where((LocalVariableElement variable) {
1341 return !tryCatchBuilder.mutableCapturedVariables.contains(variable);
1342 });
1343 for (LocalVariableElement variable in boxedOnEntry) {
1344 assert(!tryCatchBuilder.isInMutableVariable(variable));
1345 ir.Primitive value = tryCatchBuilder.buildLocalGet(variable);
1346 tryCatchBuilder.makeMutableVariable(variable);
1347 tryCatchBuilder.declareLocalVariable(variable, initialValue: value);
1348 }
1349
1350 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder();
1351 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder();
1352 List<ir.Parameter> joinParameters =
1353 new List<ir.Parameter>.generate(environment.length, (i) {
1354 return new ir.Parameter(environment.index2variable[i]);
1355 });
1356 ir.Continuation joinContinuation = new ir.Continuation(joinParameters);
1357
1358 void interceptJumps(JumpCollector collector) {
1359 collector.enterTry(boxedOnEntry);
1360 }
1361 void restoreJumps(JumpCollector collector) {
1362 collector.leaveTry();
1363 }
1364 tryBuilder.state.breakCollectors.forEach(interceptJumps);
1365 tryBuilder.state.continueCollectors.forEach(interceptJumps);
1366 buildTryBlock(tryBuilder);
1367 tryBuilder.state.breakCollectors.forEach(restoreJumps);
1368 tryBuilder.state.continueCollectors.forEach(restoreJumps);
1369 if (tryBuilder.isOpen) {
1370 for (LocalVariableElement variable in boxedOnEntry) {
1371 assert(tryBuilder.isInMutableVariable(variable));
1372 ir.Primitive value = tryBuilder.buildLocalGet(variable);
1373 tryBuilder.environment.update(variable, value);
1374 }
1375 tryBuilder.jumpTo(joinContinuation);
1376 }
1377
1378 for (LocalVariableElement variable in boxedOnEntry) {
1379 assert(catchBuilder.isInMutableVariable(variable));
1380 ir.Primitive value = catchBuilder.buildLocalGet(variable);
1381 // Note that we remove the variable from the set of mutable variables
1382 // here (and not above for the try body). This is because the set of
1383 // mutable variables is global for the whole function and not local to
1384 // a delimited builder.
1385 catchBuilder.removeMutableVariable(variable);
1386 catchBuilder.environment.update(variable, value);
1387 }
1388
1389 // TODO(kmillikin): Handle multiple catch clauses.
1390 assert(catchClauseInfos.length == 1);
1391 for (CatchClauseInfo catchClauseInfo in catchClauseInfos) {
1392 LocalVariableElement exceptionVariable =
1393 catchClauseInfo.exceptionVariable;
1394 ir.Parameter exceptionParameter = new ir.Parameter(exceptionVariable);
1395 catchBuilder.environment.extend(exceptionVariable, exceptionParameter);
1396 ir.Parameter traceParameter;
1397 LocalVariableElement stackTraceVariable =
1398 catchClauseInfo.stackTraceVariable;
1399 if (stackTraceVariable != null) {
1400 traceParameter = new ir.Parameter(stackTraceVariable);
1401 catchBuilder.environment.extend(stackTraceVariable, traceParameter);
1402 } else {
1403 // Use a dummy continuation parameter for the stack trace parameter.
1404 // This will ensure that all handlers have two parameters and so they
1405 // can be treated uniformly.
1406 traceParameter = new ir.Parameter(null);
1407 }
1408 catchClauseInfo.buildCatchBlock(catchBuilder);
1409 if (catchBuilder.isOpen) {
1410 catchBuilder.jumpTo(joinContinuation);
1411 }
1412 List<ir.Parameter> catchParameters =
1413 <ir.Parameter>[exceptionParameter, traceParameter];
1414 ir.Continuation catchContinuation = new ir.Continuation(catchParameters);
1415 catchContinuation.body = catchBuilder._root;
1416
1417 tryCatchBuilder.add(
1418 new ir.LetHandler(catchContinuation, tryBuilder._root));
1419 tryCatchBuilder._current = null;
1420 }
1421
1422 add(new ir.LetCont(joinContinuation, tryCatchBuilder._root));
1423 for (int i = 0; i < environment.length; ++i) {
1424 environment.index2value[i] = joinParameters[i];
1425 }
1426 }
1427
1287 /// Create a return statement `return value;` or `return;` if [value] is 1428 /// Create a return statement `return value;` or `return;` if [value] is
1288 /// null. 1429 /// null.
1289 void buildReturn([ir.Primitive value]) { 1430 void buildReturn([ir.Primitive value]) {
1290 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] 1431 // Build(Return(e), C) = C'[InvokeContinuation(return, x)]
1291 // where (C', x) = Build(e, C) 1432 // where (C', x) = Build(e, C)
1292 // 1433 //
1293 // Return without a subexpression is translated as if it were return null. 1434 // Return without a subexpression is translated as if it were return null.
1294 assert(isOpen); 1435 assert(isOpen);
1295 if (value == null) { 1436 if (value == null) {
1296 value = buildNullLiteral(); 1437 value = buildNullLiteral();
(...skipping 814 matching lines...) Expand 10 before | Expand all | Expand 10 after
2111 final Map<Local, ClosureLocation> freeVariables; 2252 final Map<Local, ClosureLocation> freeVariables;
2112 2253
2113 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables); 2254 ClosureEnvironment(this.selfReference, this.thisLocal, this.freeVariables);
2114 } 2255 }
2115 2256
2116 class TryStatementInfo { 2257 class TryStatementInfo {
2117 final Set<LocalVariableElement> declared = new Set<LocalVariableElement>(); 2258 final Set<LocalVariableElement> declared = new Set<LocalVariableElement>();
2118 final Set<LocalVariableElement> boxedOnEntry = 2259 final Set<LocalVariableElement> boxedOnEntry =
2119 new Set<LocalVariableElement>(); 2260 new Set<LocalVariableElement>();
2120 } 2261 }
2262
2263 // TODO(johnniwinther): Support passing of [DartType] for the exception.
2264 class CatchClauseInfo {
2265 final LocalVariableElement exceptionVariable;
2266 final LocalVariableElement stackTraceVariable;
2267 final SubbuildFunction buildCatchBlock;
2268
2269 CatchClauseInfo({this.exceptionVariable,
2270 this.stackTraceVariable,
2271 this.buildCatchBlock});
2272 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698