| 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 |