OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |