| OLD | NEW |
| 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'; |
| (...skipping 1207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1218 SubbuildFunction buildBody, | 1218 SubbuildFunction buildBody, |
| 1219 JumpTarget target, | 1219 JumpTarget target, |
| 1220 ClosureScope closureScope}) { | 1220 ClosureScope closureScope}) { |
| 1221 assert(isOpen); | 1221 assert(isOpen); |
| 1222 // While loops use four named continuations: the entry to the body, the | 1222 // While loops use four named continuations: the entry to the body, the |
| 1223 // loop exit, the loop back edge (continue), and the loop exit (break). | 1223 // loop exit, the loop back edge (continue), and the loop exit (break). |
| 1224 // The CPS translation of [[while (condition) body; successor]] is: | 1224 // The CPS translation of [[while (condition) body; successor]] is: |
| 1225 // | 1225 // |
| 1226 // let cont continue(x, ...) = | 1226 // let cont continue(x, ...) = |
| 1227 // let prim cond = [[condition]] in | 1227 // let prim cond = [[condition]] in |
| 1228 // let cont break() = [[successor]] in | 1228 // let cont break(x, ...) = [[successor]] in |
| 1229 // let cont exit() = break(v, ...) in | 1229 // let cont exit() = break(v, ...) |
| 1230 // let cont body() = [[body]]; continue(v, ...) in | 1230 // and body() = [[body]]; continue(v, ...) |
| 1231 // branch cond (body, exit) in | 1231 // in branch cond (body, exit) |
| 1232 // continue(v, ...) | 1232 // in continue(v, ...) |
| 1233 // | 1233 // |
| 1234 // If there are no breaks in the body, the break continuation is inlined | 1234 // If there are no breaks in the body, the break continuation is inlined |
| 1235 // in the exit continuation (i.e., the translation of the successor | 1235 // in the exit continuation (i.e., the translation of the successor |
| 1236 // statement occurs in the exit continuation). | 1236 // statement occurs in the exit continuation). |
| 1237 | 1237 |
| 1238 // The condition and body are delimited. | 1238 // The condition and body are delimited. |
| 1239 IrBuilder condBuilder = makeRecursiveBuilder(); | 1239 IrBuilder condBuilder = makeRecursiveBuilder(); |
| 1240 ir.Primitive condition = buildCondition(condBuilder); | 1240 ir.Primitive condition = buildCondition(condBuilder); |
| 1241 | 1241 |
| 1242 JumpCollector breakCollector = new JumpCollector(target); | 1242 JumpCollector breakCollector = new JumpCollector(target); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1290 breakCollector.addJump(this); | 1290 breakCollector.addJump(this); |
| 1291 letJoin.continuations = | 1291 letJoin.continuations = |
| 1292 <ir.Continuation>[createJoin(environment.length, breakCollector)]; | 1292 <ir.Continuation>[createJoin(environment.length, breakCollector)]; |
| 1293 _current = letJoin; | 1293 _current = letJoin; |
| 1294 } else { | 1294 } else { |
| 1295 _current = condBuilder._current; | 1295 _current = condBuilder._current; |
| 1296 environment = condBuilder.environment; | 1296 environment = condBuilder.environment; |
| 1297 } | 1297 } |
| 1298 } | 1298 } |
| 1299 | 1299 |
| 1300 |
| 1301 /// Creates a do-while loop. |
| 1302 /// |
| 1303 /// The body and condition are created by [buildBody] and [buildCondition]. |
| 1304 /// The jump target [target] is the target of `break` and `continue` |
| 1305 /// statements in the body that have the loop as their target. |
| 1306 /// [closureScope] contains all the variables declared in the loop (but not |
| 1307 /// declared in some inner closure scope). |
| 1308 void buildDoWhile({SubbuildFunction buildBody, |
| 1309 SubbuildFunction buildCondition, |
| 1310 JumpTarget target, |
| 1311 ClosureScope closureScope}) { |
| 1312 assert(isOpen); |
| 1313 // The CPS translation of [[do body; while (condition); successor]] is: |
| 1314 // |
| 1315 // let cont break(x, ...) = [[successor]] in |
| 1316 // let cont rec loop(x, ...) = |
| 1317 // let cont continue(x, ...) = |
| 1318 // let prim cond = [[condition]] in |
| 1319 // let cont exit() = break(v, ...) |
| 1320 // and repeat() = loop(v, ...) |
| 1321 // in branch cond (repeat, exit) |
| 1322 // in [[body]]; continue(v, ...) |
| 1323 // in loop(v, ...) |
| 1324 IrBuilder bodyBuilder = makeRecursiveBuilder(); |
| 1325 IrBuilder continueBuilder = bodyBuilder.makeRecursiveBuilder(); |
| 1326 |
| 1327 // Construct the continue continuation (i.e., the condition). |
| 1328 // <Continue> = |
| 1329 // let prim cond = [[condition]] in |
| 1330 // let cont exit() = break(v, ...) |
| 1331 // and repeat() = loop(v, ...) |
| 1332 // in branch cond (repeat, exit) |
| 1333 ir.Primitive condition = buildCondition(continueBuilder); |
| 1334 // Use a delimited IrBuilder for the exit continuation's body so that |
| 1335 // we can capture the break with the body's break collector. |
| 1336 ir.Continuation exitContinuation = new ir.Continuation([]); |
| 1337 IrBuilder exitBuilder = continueBuilder.makeDelimitedBuilder(); |
| 1338 ir.Continuation repeatContinuation = new ir.Continuation([]); |
| 1339 ir.InvokeContinuation invokeLoop = |
| 1340 new ir.InvokeContinuation.uninitialized(recursive: true); |
| 1341 invokeLoop.arguments = |
| 1342 continueBuilder.environment.index2value.map( |
| 1343 (ir.Primitive value) => new ir.Reference(value)).toList(); |
| 1344 repeatContinuation.body = invokeLoop; |
| 1345 continueBuilder.add( |
| 1346 new ir.LetCont.many(<ir.Continuation>[exitContinuation, |
| 1347 repeatContinuation], |
| 1348 new ir.Branch(new ir.IsTrue(condition), |
| 1349 repeatContinuation, |
| 1350 exitContinuation))); |
| 1351 ir.Continuation continueContinuation = |
| 1352 new ir.Continuation(continueBuilder._parameters); |
| 1353 continueContinuation.body = continueBuilder._root; |
| 1354 |
| 1355 // Construct the loop continuation (i.e., the body and condition). |
| 1356 // <Loop> = |
| 1357 // let cont continue(x, ...) = |
| 1358 // <Continue> |
| 1359 // in [[body]]; continue(v, ...) |
| 1360 JumpCollector breakCollector = new JumpCollector(target); |
| 1361 JumpCollector continueCollector = new JumpCollector(target); |
| 1362 state.breakCollectors.add(breakCollector); |
| 1363 state.continueCollectors.add(continueCollector); |
| 1364 bodyBuilder._enterScope(closureScope); |
| 1365 buildBody(bodyBuilder); |
| 1366 assert(state.breakCollectors.last == breakCollector); |
| 1367 assert(state.continueCollectors.last == continueCollector); |
| 1368 state.breakCollectors.removeLast(); |
| 1369 state.continueCollectors.removeLast(); |
| 1370 // Add the jump from the loop's exit to the break condition. It is only |
| 1371 // here where the exitBuilder's root is non-null and we can set the |
| 1372 // exitContinuation's body. |
| 1373 breakCollector.addJump(exitBuilder); |
| 1374 exitContinuation.body = exitBuilder._root; |
| 1375 if (bodyBuilder.isOpen) { |
| 1376 continueCollector.addJump(bodyBuilder); |
| 1377 } |
| 1378 invokeFullJoin(continueContinuation, continueCollector, recursive: false); |
| 1379 ir.Continuation loopContinuation = |
| 1380 new ir.Continuation(bodyBuilder._parameters); |
| 1381 loopContinuation.isRecursive = true; |
| 1382 loopContinuation.body = |
| 1383 new ir.LetCont(continueContinuation, bodyBuilder._root); |
| 1384 invokeLoop.continuation = |
| 1385 new ir.Reference<ir.Continuation>(loopContinuation); |
| 1386 ir.LetCont letLoop = |
| 1387 new ir.LetCont(loopContinuation, |
| 1388 new ir.InvokeContinuation(loopContinuation, |
| 1389 environment.index2value)); |
| 1390 |
| 1391 // Add the break condition. |
| 1392 ir.Continuation breakContinuation; |
| 1393 if (breakCollector.length == 1) { |
| 1394 // createJoin only works when there is more than one jump to a join-point |
| 1395 // continuation. This is to potentially catch errors in the case that |
| 1396 // a join was intended and at least one jump is missing. Unfortunately |
| 1397 // we have the explicit code below for the (common?) case that the |
| 1398 // only break from the do-while is the implicit one when the condition |
| 1399 // is false. |
| 1400 List<ir.Parameter> parameters = <ir.Parameter>[]; |
| 1401 List<ir.Reference> arguments = <ir.Reference>[]; |
| 1402 for (int i = 0; i < environment.length; ++i) { |
| 1403 ir.Parameter parameter = |
| 1404 new ir.Parameter(environment.index2variable[i]); |
| 1405 parameters.add(parameter); |
| 1406 environment.index2value[i] = parameter; |
| 1407 arguments.add(new ir.Reference(breakCollector.environments.first[i])); |
| 1408 } |
| 1409 breakContinuation = new ir.Continuation(parameters); |
| 1410 breakCollector.invocations.first.arguments = arguments; |
| 1411 breakCollector.invocations.first.continuation = |
| 1412 new ir.Reference(breakContinuation); |
| 1413 } else { |
| 1414 breakContinuation = createJoin(environment.length, breakCollector); |
| 1415 } |
| 1416 add(new ir.LetCont(breakContinuation, letLoop)); |
| 1417 } |
| 1418 |
| 1300 /// Creates a try-statement. | 1419 /// Creates a try-statement. |
| 1301 /// | 1420 /// |
| 1302 /// [tryInfo] provides information on local variables declared and boxed | 1421 /// [tryInfo] provides information on local variables declared and boxed |
| 1303 /// within this try statement. | 1422 /// within this try statement. |
| 1304 /// [buildTryBlock] builds the try block. | 1423 /// [buildTryBlock] builds the try block. |
| 1305 /// [catchClauseInfos] provides access to the catch type, exception variable, | 1424 /// [catchClauseInfos] provides access to the catch type, exception variable, |
| 1306 /// and stack trace variable, and a function for building the catch block. | 1425 /// and stack trace variable, and a function for building the catch block. |
| 1307 void buildTry( | 1426 void buildTry( |
| 1308 {TryStatementInfo tryStatementInfo, | 1427 {TryStatementInfo tryStatementInfo, |
| 1309 SubbuildFunction buildTryBlock, | 1428 SubbuildFunction buildTryBlock, |
| (...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2323 // TODO(johnniwinther): Support passing of [DartType] for the exception. | 2442 // TODO(johnniwinther): Support passing of [DartType] for the exception. |
| 2324 class CatchClauseInfo { | 2443 class CatchClauseInfo { |
| 2325 final LocalVariableElement exceptionVariable; | 2444 final LocalVariableElement exceptionVariable; |
| 2326 final LocalVariableElement stackTraceVariable; | 2445 final LocalVariableElement stackTraceVariable; |
| 2327 final SubbuildFunction buildCatchBlock; | 2446 final SubbuildFunction buildCatchBlock; |
| 2328 | 2447 |
| 2329 CatchClauseInfo({this.exceptionVariable, | 2448 CatchClauseInfo({this.exceptionVariable, |
| 2330 this.stackTraceVariable, | 2449 this.stackTraceVariable, |
| 2331 this.buildCatchBlock}); | 2450 this.buildCatchBlock}); |
| 2332 } | 2451 } |
| OLD | NEW |