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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ssa/builder.dart

Issue 11366085: Fix control flow graph in the presence of aborting instructions in a try/catch/finally. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 part of ssa; 5 part of ssa;
6 6
7 class Interceptors { 7 class Interceptors {
8 Compiler compiler; 8 Compiler compiler;
9 Interceptors(Compiler this.compiler); 9 Interceptors(Compiler this.compiler);
10 10
(...skipping 908 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 rti = builder.compiler.codegenWorld.rti, 919 rti = builder.compiler.codegenWorld.rti,
920 super(work.resolutionTree) { 920 super(work.resolutionTree) {
921 localsHandler = new LocalsHandler(this); 921 localsHandler = new LocalsHandler(this);
922 } 922 }
923 923
924 static const MAX_INLINING_DEPTH = 3; 924 static const MAX_INLINING_DEPTH = 3;
925 static const MAX_INLINING_SOURCE_SIZE = 128; 925 static const MAX_INLINING_SOURCE_SIZE = 128;
926 List<InliningState> inliningStack; 926 List<InliningState> inliningStack;
927 Element returnElement; 927 Element returnElement;
928 DartType returnType; 928 DartType returnType;
929 bool inTryStatement = false;
929 930
930 void disableMethodInterception() { 931 void disableMethodInterception() {
931 assert(methodInterceptionEnabled); 932 assert(methodInterceptionEnabled);
932 methodInterceptionEnabled = false; 933 methodInterceptionEnabled = false;
933 } 934 }
934 935
935 void enableMethodInterception() { 936 void enableMethodInterception() {
936 assert(!methodInterceptionEnabled); 937 assert(!methodInterceptionEnabled);
937 methodInterceptionEnabled = true; 938 methodInterceptionEnabled = true;
938 } 939 }
(...skipping 2498 matching lines...) Expand 10 before | Expand all | Expand 10 after
3437 visit(node.expression); 3438 visit(node.expression);
3438 // Remove the result and reveal the duplicated receiver on the stack. 3439 // Remove the result and reveal the duplicated receiver on the stack.
3439 pop(); 3440 pop();
3440 } 3441 }
3441 3442
3442 visitCascadeReceiver(CascadeReceiver node) { 3443 visitCascadeReceiver(CascadeReceiver node) {
3443 visit(node.expression); 3444 visit(node.expression);
3444 dup(); 3445 dup();
3445 } 3446 }
3446 3447
3448 void handleInTryStatement() {
3449 if (!inTryStatement) return;
3450 HBasicBlock block = close(new HExitTry());
3451 HBasicBlock newBlock = graph.addNewBlock();
3452 block.addSuccessor(newBlock);
3453 open(newBlock);
3454 }
3455
3447 visitReturn(Return node) { 3456 visitReturn(Return node) {
3448 if (identical(node.getBeginToken().stringValue, 'native')) { 3457 if (identical(node.getBeginToken().stringValue, 'native')) {
3449 native.handleSsaNative(this, node.expression); 3458 native.handleSsaNative(this, node.expression);
3450 return; 3459 return;
3451 } 3460 }
3452 if (node.isRedirectingFactoryBody) { 3461 if (node.isRedirectingFactoryBody) {
3453 compiler.internalError("Unimplemented: Redirecting factory constructor", 3462 compiler.internalError("Unimplemented: Redirecting factory constructor",
3454 node: node); 3463 node: node);
3455 } 3464 }
3456 HInstruction value; 3465 HInstruction value;
3457 if (node.expression == null) { 3466 if (node.expression == null) {
3458 value = graph.addConstantNull(constantSystem); 3467 value = graph.addConstantNull(constantSystem);
3459 } else { 3468 } else {
3460 visit(node.expression); 3469 visit(node.expression);
3461 value = pop(); 3470 value = pop();
3462 value = potentiallyCheckType(value, returnType); 3471 value = potentiallyCheckType(value, returnType);
3463 } 3472 }
3473
3474 handleInTryStatement();
3475
3464 if (!inliningStack.isEmpty) { 3476 if (!inliningStack.isEmpty) {
3465 localsHandler.updateLocal(returnElement, value); 3477 localsHandler.updateLocal(returnElement, value);
3466 } else { 3478 } else {
3467 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit); 3479 close(attachPosition(new HReturn(value), node)).addSuccessor(graph.exit);
3468 } 3480 }
3469 } 3481 }
3470 3482
3471 visitThrow(Throw node) { 3483 visitThrow(Throw node) {
3472 if (node.expression == null) { 3484 if (node.expression == null) {
3473 HInstruction exception = rethrowableException; 3485 HInstruction exception = rethrowableException;
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
3544 visitEmptyStatement(EmptyStatement node) { 3556 visitEmptyStatement(EmptyStatement node) {
3545 // Do nothing, empty statement. 3557 // Do nothing, empty statement.
3546 } 3558 }
3547 3559
3548 visitModifiers(Modifiers node) { 3560 visitModifiers(Modifiers node) {
3549 compiler.unimplemented('SsaBuilder.visitModifiers', node: node); 3561 compiler.unimplemented('SsaBuilder.visitModifiers', node: node);
3550 } 3562 }
3551 3563
3552 visitBreakStatement(BreakStatement node) { 3564 visitBreakStatement(BreakStatement node) {
3553 assert(!isAborted()); 3565 assert(!isAborted());
3566 handleInTryStatement();
3554 TargetElement target = elements[node]; 3567 TargetElement target = elements[node];
3555 assert(target != null); 3568 assert(target != null);
3556 JumpHandler handler = jumpTargets[target]; 3569 JumpHandler handler = jumpTargets[target];
3557 assert(handler != null); 3570 assert(handler != null);
3558 if (node.target == null) { 3571 if (node.target == null) {
3559 handler.generateBreak(); 3572 handler.generateBreak();
3560 } else { 3573 } else {
3561 LabelElement label = elements[node.target]; 3574 LabelElement label = elements[node.target];
3562 handler.generateBreak(label); 3575 handler.generateBreak(label);
3563 } 3576 }
3564 } 3577 }
3565 3578
3566 visitContinueStatement(ContinueStatement node) { 3579 visitContinueStatement(ContinueStatement node) {
3580 handleInTryStatement();
3567 TargetElement target = elements[node]; 3581 TargetElement target = elements[node];
3568 assert(target != null); 3582 assert(target != null);
3569 JumpHandler handler = jumpTargets[target]; 3583 JumpHandler handler = jumpTargets[target];
3570 assert(handler != null); 3584 assert(handler != null);
3571 if (node.target == null) { 3585 if (node.target == null) {
3572 handler.generateContinue(); 3586 handler.generateContinue();
3573 } else { 3587 } else {
3574 LabelElement label = elements[node.target]; 3588 LabelElement label = elements[node.target];
3575 assert(label != null); 3589 assert(label != null);
3576 handler.generateContinue(label); 3590 handler.generateContinue(label);
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after
4096 // Save the current locals. The catch block and the finally block 4110 // Save the current locals. The catch block and the finally block
4097 // must not reuse the existing locals handler. None of the variables 4111 // must not reuse the existing locals handler. None of the variables
4098 // that have been defined in the body-block will be used, but for 4112 // that have been defined in the body-block will be used, but for
4099 // loops we will add (unnecessary) phis that will reference the body 4113 // loops we will add (unnecessary) phis that will reference the body
4100 // variables. This makes it look as if the variables were used 4114 // variables. This makes it look as if the variables were used
4101 // in a non-dominated block. 4115 // in a non-dominated block.
4102 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 4116 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
4103 HBasicBlock enterBlock = openNewBlock(); 4117 HBasicBlock enterBlock = openNewBlock();
4104 HTry tryInstruction = new HTry(); 4118 HTry tryInstruction = new HTry();
4105 close(tryInstruction); 4119 close(tryInstruction);
4120 bool oldInTryStatement = inTryStatement;
4121 inTryStatement = true;
4106 4122
4107 HBasicBlock startTryBlock; 4123 HBasicBlock startTryBlock;
4108 HBasicBlock endTryBlock; 4124 HBasicBlock endTryBlock;
4109 HBasicBlock startCatchBlock; 4125 HBasicBlock startCatchBlock;
4110 HBasicBlock endCatchBlock; 4126 HBasicBlock endCatchBlock;
4111 HBasicBlock startFinallyBlock; 4127 HBasicBlock startFinallyBlock;
4112 HBasicBlock endFinallyBlock; 4128 HBasicBlock endFinallyBlock;
4113 4129
4114 startTryBlock = graph.addNewBlock(); 4130 startTryBlock = graph.addNewBlock();
4115 open(startTryBlock); 4131 open(startTryBlock);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
4210 open(startFinallyBlock); 4226 open(startFinallyBlock);
4211 visit(node.finallyBlock); 4227 visit(node.finallyBlock);
4212 if (!isAborted()) endFinallyBlock = close(new HGoto()); 4228 if (!isAborted()) endFinallyBlock = close(new HGoto());
4213 tryInstruction.finallyBlock = startFinallyBlock; 4229 tryInstruction.finallyBlock = startFinallyBlock;
4214 finallyGraph = new SubGraph(startFinallyBlock, lastOpenedBlock); 4230 finallyGraph = new SubGraph(startFinallyBlock, lastOpenedBlock);
4215 } 4231 }
4216 4232
4217 HBasicBlock exitBlock = graph.addNewBlock(); 4233 HBasicBlock exitBlock = graph.addNewBlock();
4218 4234
4219 addOptionalSuccessor(b1, b2) { if (b2 != null) b1.addSuccessor(b2); } 4235 addOptionalSuccessor(b1, b2) { if (b2 != null) b1.addSuccessor(b2); }
4236 addExitTrySuccessor(successor) {
4237 if (successor == null) return;
4238 // Iterate over all blocks created inside this try/catch, and
4239 // attach successor information to blocks that end with
4240 // [HExitTry].
4241 for (int i = startTryBlock.id; i < successor.id; i++) {
4242 HBasicBlock block = graph.blocks[i];
4243 var last = block.last;
4244 if (last is HExitTry) {
4245 block.addSuccessor(successor);
4246 } else if (last is HTry) {
4247 // Skip all blocks inside this nested try/catch.
4248 i = last.joinBlock.id;
4249 }
4250 }
4251 }
4220 4252
4221 // Setup all successors. The entry block that contains the [HTry] 4253 // Setup all successors. The entry block that contains the [HTry]
4222 // has 1) the body, 2) the catch, 3) the finally, and 4) the exit 4254 // has 1) the body, 2) the catch, 3) the finally, and 4) the exit
4223 // blocks as successors. 4255 // blocks as successors.
4224 enterBlock.addSuccessor(startTryBlock); 4256 enterBlock.addSuccessor(startTryBlock);
4225 addOptionalSuccessor(enterBlock, startCatchBlock); 4257 addOptionalSuccessor(enterBlock, startCatchBlock);
4226 addOptionalSuccessor(enterBlock, startFinallyBlock); 4258 addOptionalSuccessor(enterBlock, startFinallyBlock);
4227 enterBlock.addSuccessor(exitBlock); 4259 enterBlock.addSuccessor(exitBlock);
4228 4260
4229 // The body has either the catch or the finally block as successor. 4261 // The body has either the catch or the finally block as successor.
4230 if (endTryBlock != null) { 4262 if (endTryBlock != null) {
4231 assert(startCatchBlock != null || startFinallyBlock != null); 4263 assert(startCatchBlock != null || startFinallyBlock != null);
4232 endTryBlock.addSuccessor( 4264 endTryBlock.addSuccessor(
4233 startCatchBlock != null ? startCatchBlock : startFinallyBlock); 4265 startCatchBlock != null ? startCatchBlock : startFinallyBlock);
4234 } 4266 }
4235 4267
4236 // The catch block has either the finally or the exit block as 4268 // The catch block has either the finally or the exit block as
4237 // successor. 4269 // successor.
4238 if (endCatchBlock != null) { 4270 if (endCatchBlock != null) {
4239 endCatchBlock.addSuccessor( 4271 endCatchBlock.addSuccessor(
4240 startFinallyBlock != null ? startFinallyBlock : exitBlock); 4272 startFinallyBlock != null ? startFinallyBlock : exitBlock);
4241 } 4273 }
4242 4274
4243 // The finally block has the exit block as successor. 4275 // The finally block has the exit block as successor.
4244 if (endFinallyBlock != null) { 4276 if (endFinallyBlock != null) {
4245 endFinallyBlock.addSuccessor(exitBlock); 4277 endFinallyBlock.addSuccessor(exitBlock);
4246 } 4278 }
4279
4280 // If a block inside try/catch aborts (eg with a return statement),
4281 // we explicitely mark this block a predecessor of the catch
4282 // block and the finally block.
4283 addExitTrySuccessor(startCatchBlock);
4284 addExitTrySuccessor(startFinallyBlock);
4247 4285
4248 // Use the locals handler not altered by the catch and finally 4286 // Use the locals handler not altered by the catch and finally
4249 // blocks. 4287 // blocks.
4250 localsHandler = savedLocals; 4288 localsHandler = savedLocals;
4251 open(exitBlock); 4289 open(exitBlock);
4252 enterBlock.setBlockFlow( 4290 enterBlock.setBlockFlow(
4253 new HTryBlockInformation( 4291 new HTryBlockInformation(
4254 wrapStatementGraph(bodyGraph), 4292 wrapStatementGraph(bodyGraph),
4255 exception, 4293 exception,
4256 wrapStatementGraph(catchGraph), 4294 wrapStatementGraph(catchGraph),
4257 wrapStatementGraph(finallyGraph)), 4295 wrapStatementGraph(finallyGraph)),
4258 exitBlock); 4296 exitBlock);
4297 inTryStatement = oldInTryStatement;
4259 } 4298 }
4260 4299
4261 visitScriptTag(ScriptTag node) { 4300 visitScriptTag(ScriptTag node) {
4262 compiler.unimplemented('SsaBuilder.visitScriptTag', node: node); 4301 compiler.unimplemented('SsaBuilder.visitScriptTag', node: node);
4263 } 4302 }
4264 4303
4265 visitCatchBlock(CatchBlock node) { 4304 visitCatchBlock(CatchBlock node) {
4266 visit(node.block); 4305 visit(node.block);
4267 } 4306 }
4268 4307
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after
4675 new HSubGraphBlockInformation(elseBranch.graph)); 4714 new HSubGraphBlockInformation(elseBranch.graph));
4676 4715
4677 HBasicBlock conditionStartBlock = conditionBranch.block; 4716 HBasicBlock conditionStartBlock = conditionBranch.block;
4678 conditionStartBlock.setBlockFlow(info, joinBlock); 4717 conditionStartBlock.setBlockFlow(info, joinBlock);
4679 SubGraph conditionGraph = conditionBranch.graph; 4718 SubGraph conditionGraph = conditionBranch.graph;
4680 HIf branch = conditionGraph.end.last; 4719 HIf branch = conditionGraph.end.last;
4681 assert(branch is HIf); 4720 assert(branch is HIf);
4682 branch.blockInformation = conditionStartBlock.blockFlow; 4721 branch.blockInformation = conditionStartBlock.blockFlow;
4683 } 4722 }
4684 } 4723 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698