| 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 class Interceptors { | 5 class Interceptors { |
| 6 Compiler compiler; | 6 Compiler compiler; |
| 7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
| 8 | 8 |
| 9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
| 10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
| (...skipping 613 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 } | 624 } |
| 625 | 625 |
| 626 | 626 |
| 627 interface JumpHandler default JumpHandlerImpl { | 627 interface JumpHandler default JumpHandlerImpl { |
| 628 JumpHandler(SsaBuilder builder, TargetElement target); | 628 JumpHandler(SsaBuilder builder, TargetElement target); |
| 629 void generateBreak([LabelElement label]); | 629 void generateBreak([LabelElement label]); |
| 630 void generateContinue([LabelElement label]); | 630 void generateContinue([LabelElement label]); |
| 631 void forEachBreak(void action(HBreak instruction, LocalsHandler locals)); | 631 void forEachBreak(void action(HBreak instruction, LocalsHandler locals)); |
| 632 void forEachContinue(void action(HBreak instruction, LocalsHandler locals)); | 632 void forEachContinue(void action(HBreak instruction, LocalsHandler locals)); |
| 633 void close(); | 633 void close(); |
| 634 final TargetElement target; |
| 634 List<LabelElement> labels(); | 635 List<LabelElement> labels(); |
| 635 } | 636 } |
| 636 | 637 |
| 637 // Insert break handler used to avoid null checks when a target isn't | 638 // Insert break handler used to avoid null checks when a target isn't |
| 638 // used as the target of a break, and therefore doesn't need a break | 639 // used as the target of a break, and therefore doesn't need a break |
| 639 // handler associated with it. | 640 // handler associated with it. |
| 640 class NullJumpHandler implements JumpHandler { | 641 class NullJumpHandler implements JumpHandler { |
| 641 const NullJumpHandler(); | 642 const NullJumpHandler(); |
| 642 void generateBreak([LabelElement label]) { unreachable(); } | 643 void generateBreak([LabelElement label]) { unreachable(); } |
| 643 void generateContinue([LabelElement label]) { unreachable(); } | 644 void generateContinue([LabelElement label]) { unreachable(); } |
| 644 void forEachBreak(Function ignored) { } | 645 void forEachBreak(Function ignored) { } |
| 645 void forEachContinue(Function ignored) { } | 646 void forEachContinue(Function ignored) { } |
| 646 void close() { } | 647 void close() { } |
| 648 final TargetElement target = null; |
| 647 List<LabelElement> labels() => const <LabelElement>[]; | 649 List<LabelElement> labels() => const <LabelElement>[]; |
| 648 } | 650 } |
| 649 | 651 |
| 650 // Records breaks until a target block is available. | 652 // Records breaks until a target block is available. |
| 651 // Breaks are always forward jumps. | 653 // Breaks are always forward jumps. |
| 652 // Continues in loops are implemented as breaks of the body. | 654 // Continues in loops are implemented as breaks of the body. |
| 653 // Continues in switches is currently not handled. | 655 // Continues in switches is currently not handled. |
| 654 class JumpHandlerImpl implements JumpHandler { | 656 class JumpHandlerImpl implements JumpHandler { |
| 655 final SsaBuilder builder; | 657 final SsaBuilder builder; |
| 656 final TargetElement target; | 658 final TargetElement target; |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1058 /** | 1060 /** |
| 1059 * Creates a new loop-header block. The previous [current] block | 1061 * Creates a new loop-header block. The previous [current] block |
| 1060 * is closed with an [HGoto] and replaced by the newly created block. | 1062 * is closed with an [HGoto] and replaced by the newly created block. |
| 1061 * Also notifies the locals handler that we're entering a loop. | 1063 * Also notifies the locals handler that we're entering a loop. |
| 1062 */ | 1064 */ |
| 1063 JumpHandler beginLoopHeader(Node node) { | 1065 JumpHandler beginLoopHeader(Node node) { |
| 1064 assert(!isAborted()); | 1066 assert(!isAborted()); |
| 1065 HBasicBlock previousBlock = close(new HGoto()); | 1067 HBasicBlock previousBlock = close(new HGoto()); |
| 1066 | 1068 |
| 1067 JumpHandler jumpHandler = createJumpHandler(node); | 1069 JumpHandler jumpHandler = createJumpHandler(node); |
| 1068 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock(jumpHandler.labels()); | 1070 HBasicBlock loopEntry = graph.addNewLoopHeaderBlock( |
| 1071 HLoopInformation.loopType(node), |
| 1072 jumpHandler.target, |
| 1073 jumpHandler.labels()); |
| 1069 previousBlock.addSuccessor(loopEntry); | 1074 previousBlock.addSuccessor(loopEntry); |
| 1070 open(loopEntry); | 1075 open(loopEntry); |
| 1071 | 1076 |
| 1072 localsHandler.beginLoopHeader(node, loopEntry); | 1077 localsHandler.beginLoopHeader(node, loopEntry); |
| 1073 return jumpHandler; | 1078 return jumpHandler; |
| 1074 } | 1079 } |
| 1075 | 1080 |
| 1076 /** | 1081 /** |
| 1077 * Ends the loop: | 1082 * Ends the loop: |
| 1078 * - creates a new block and adds it as successor to the [branchBlock]. | 1083 * - creates a new block and adds it as successor to the [branchBlock]. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1114 // loop-entry: | 1119 // loop-entry: |
| 1115 // if (!<condition>) goto loop-exit; | 1120 // if (!<condition>) goto loop-exit; |
| 1116 // <body> | 1121 // <body> |
| 1117 // <updates> | 1122 // <updates> |
| 1118 // goto loop-entry; | 1123 // goto loop-entry; |
| 1119 // loop-exit: | 1124 // loop-exit: |
| 1120 | 1125 |
| 1121 localsHandler.startLoop(loop); | 1126 localsHandler.startLoop(loop); |
| 1122 | 1127 |
| 1123 // The initializer. | 1128 // The initializer. |
| 1129 HBasicBlock initializerBlock = graph.addNewBlock(); |
| 1130 goto(current, initializerBlock); |
| 1131 open(initializerBlock); |
| 1124 initialize(); | 1132 initialize(); |
| 1125 assert(!isAborted()); | 1133 assert(!isAborted()); |
| 1134 SubGraph initializerGraph = new SubGraph(initializerBlock, current); |
| 1126 | 1135 |
| 1127 JumpHandler jumpHandler = beginLoopHeader(loop); | 1136 JumpHandler jumpHandler = beginLoopHeader(loop); |
| 1128 HBasicBlock conditionBlock = current; | 1137 HBasicBlock conditionBlock = current; |
| 1138 HLoopInformation loopInfo = current.loopInformation; |
| 1139 // The initializer graph is currently unused due to the way we |
| 1140 // generate code. |
| 1141 loopInfo.initializer = initializerGraph; |
| 1129 | 1142 |
| 1130 HInstruction conditionInstruction = condition(); | 1143 HInstruction conditionInstruction = condition(); |
| 1131 HBasicBlock conditionExitBlock = | 1144 HBasicBlock conditionExitBlock = |
| 1132 close(new HLoopBranch(conditionInstruction)); | 1145 close(new HLoopBranch(conditionInstruction)); |
| 1146 loopInfo.condition = new SubExpression(conditionBlock, |
| 1147 conditionExitBlock, |
| 1148 conditionInstruction); |
| 1133 | 1149 |
| 1134 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1150 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| 1135 | 1151 |
| 1136 // The body. | 1152 // The body. |
| 1137 HBasicBlock beginBodyBlock = addNewBlock(); | 1153 HBasicBlock beginBodyBlock = addNewBlock(); |
| 1138 conditionExitBlock.addSuccessor(beginBodyBlock); | 1154 conditionExitBlock.addSuccessor(beginBodyBlock); |
| 1139 open(beginBodyBlock); | 1155 open(beginBodyBlock); |
| 1140 | 1156 |
| 1141 localsHandler.enterLoopBody(loop); | 1157 localsHandler.enterLoopBody(loop); |
| 1142 hackAroundPossiblyAbortingBody(loop, body); | 1158 hackAroundPossiblyAbortingBody(loop, body); |
| 1143 | 1159 |
| 1144 SubGraph bodyGraph = new SubGraph(beginBodyBlock, current); | 1160 SubGraph bodyGraph = new SubGraph(beginBodyBlock, current); |
| 1145 HBasicBlock bodyBlock = close(new HGoto()); | 1161 HBasicBlock bodyBlock = close(new HGoto()); |
| 1162 loopInfo.body = bodyGraph; |
| 1146 | 1163 |
| 1147 // Update. | 1164 // Update. |
| 1148 // We create an update block, even when we are in a while loop. There the | 1165 // We create an update block, even when we are in a while loop. There the |
| 1149 // update block is the jump-target for continue statements. We could avoid | 1166 // update block is the jump-target for continue statements. We could avoid |
| 1150 // the creation if there is no continue, but for now we always create it. | 1167 // the creation if there is no continue, but for now we always create it. |
| 1151 HBasicBlock updateBlock = addNewBlock(); | 1168 HBasicBlock updateBlock = addNewBlock(); |
| 1152 | 1169 |
| 1153 List<LocalsHandler> continueLocals = <LocalsHandler>[]; | 1170 List<LocalsHandler> continueLocals = <LocalsHandler>[]; |
| 1154 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { | 1171 jumpHandler.forEachContinue((HContinue instruction, LocalsHandler locals) { |
| 1155 instruction.block.addSuccessor(updateBlock); | 1172 instruction.block.addSuccessor(updateBlock); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1172 } else if (target !== null && target.isContinueTarget) { | 1189 } else if (target !== null && target.isContinueTarget) { |
| 1173 beginBodyBlock.labeledBlockInformation = | 1190 beginBodyBlock.labeledBlockInformation = |
| 1174 new HLabeledBlockInformation.implicit(bodyGraph, updateBlock, | 1191 new HLabeledBlockInformation.implicit(bodyGraph, updateBlock, |
| 1175 target, isContinue: true); | 1192 target, isContinue: true); |
| 1176 } | 1193 } |
| 1177 | 1194 |
| 1178 localsHandler.enterLoopUpdates(loop); | 1195 localsHandler.enterLoopUpdates(loop); |
| 1179 | 1196 |
| 1180 update(); | 1197 update(); |
| 1181 | 1198 |
| 1182 updateBlock = close(new HGoto()); | 1199 HBasicBlock updateEndBlock = close(new HGoto()); |
| 1183 // The back-edge completing the cycle. | 1200 // The back-edge completing the cycle. |
| 1184 updateBlock.addSuccessor(conditionBlock); | 1201 updateEndBlock.addSuccessor(conditionBlock); |
| 1185 conditionBlock.postProcessLoopHeader(); | 1202 conditionBlock.postProcessLoopHeader(); |
| 1203 loopInfo.updates = new SubGraph(updateBlock, updateEndBlock); |
| 1186 | 1204 |
| 1187 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); | 1205 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); |
| 1206 loopInfo.joinBlock = current; |
| 1188 } | 1207 } |
| 1189 | 1208 |
| 1190 visitFor(For node) { | 1209 visitFor(For node) { |
| 1191 assert(node.body !== null); | 1210 assert(node.body !== null); |
| 1192 void buildInitializer() { | 1211 void buildInitializer() { |
| 1193 if (node.initializer === null) return; | 1212 if (node.initializer === null) return; |
| 1194 Node initializer = node.initializer; | 1213 Node initializer = node.initializer; |
| 1195 if (initializer !== null) { | 1214 if (initializer !== null) { |
| 1196 visit(initializer); | 1215 visit(initializer); |
| 1197 if (initializer.asExpression() !== null) { | 1216 if (initializer.asExpression() !== null) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1230 () {}, | 1249 () {}, |
| 1231 buildCondition, | 1250 buildCondition, |
| 1232 () {}, | 1251 () {}, |
| 1233 () { visit(node.body); }); | 1252 () { visit(node.body); }); |
| 1234 } | 1253 } |
| 1235 | 1254 |
| 1236 visitDoWhile(DoWhile node) { | 1255 visitDoWhile(DoWhile node) { |
| 1237 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1256 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| 1238 localsHandler.startLoop(node); | 1257 localsHandler.startLoop(node); |
| 1239 JumpHandler jumpHandler = beginLoopHeader(node); | 1258 JumpHandler jumpHandler = beginLoopHeader(node); |
| 1259 HLoopInformation loopInfo = current.loopInformation; |
| 1240 HBasicBlock loopEntryBlock = current; | 1260 HBasicBlock loopEntryBlock = current; |
| 1241 HBasicBlock bodyEntryBlock = current; | 1261 HBasicBlock bodyEntryBlock = current; |
| 1242 TargetElement target = elements[node]; | 1262 TargetElement target = elements[node]; |
| 1243 bool hasContinues = target !== null && target.isContinueTarget; | 1263 bool hasContinues = target !== null && target.isContinueTarget; |
| 1244 if (hasContinues) { | 1264 if (hasContinues) { |
| 1245 // Add extra block to hang labels on. | 1265 // Add extra block to hang labels on. |
| 1246 // It doesn't currently work if they are on the same block as the | 1266 // It doesn't currently work if they are on the same block as the |
| 1247 // HLoopInfo. The handling of HLabeledBlockInformation will visit a | 1267 // HLoopInfo. The handling of HLabeledBlockInformation will visit a |
| 1248 // SubGraph that starts at the same block again, so the HLoopInfo is | 1268 // SubGraph that starts at the same block again, so the HLoopInfo is |
| 1249 // either handled twice, or it's handled after the labeled block info, | 1269 // either handled twice, or it's handled after the labeled block info, |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1283 new HLabeledBlockInformation.implicit(bodyGraph, | 1303 new HLabeledBlockInformation.implicit(bodyGraph, |
| 1284 conditionBlock, | 1304 conditionBlock, |
| 1285 target, | 1305 target, |
| 1286 isContinue: true); | 1306 isContinue: true); |
| 1287 } | 1307 } |
| 1288 } | 1308 } |
| 1289 open(conditionBlock); | 1309 open(conditionBlock); |
| 1290 | 1310 |
| 1291 visit(node.condition); | 1311 visit(node.condition); |
| 1292 assert(!isAborted()); | 1312 assert(!isAborted()); |
| 1293 conditionBlock = close(new HLoopBranch(popBoolified(), | 1313 HInstruction conditionInstruction = popBoolified(); |
| 1294 HLoopBranch.DO_WHILE_LOOP)); | 1314 HBasicBLock conditionEndBlock = |
| 1315 close(new HLoopBranch(conditionInstruction, HLoopBranch.DO_WHILE_LOOP)); |
| 1295 | 1316 |
| 1296 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge. | 1317 conditionEndBlock.addSuccessor(loopEntryBlock); // The back-edge. |
| 1297 loopEntryBlock.postProcessLoopHeader(); | 1318 loopEntryBlock.postProcessLoopHeader(); |
| 1298 | 1319 |
| 1299 endLoop(loopEntryBlock, conditionBlock, jumpHandler, localsHandler); | 1320 endLoop(loopEntryBlock, conditionEndBlock, jumpHandler, localsHandler); |
| 1300 jumpHandler.close(); | 1321 jumpHandler.close(); |
| 1322 |
| 1323 loopInfo.body = new SubGraph(bodyEntryBlock, bodyExitBlock); |
| 1324 loopInfo.condition = new SubExpression(conditionBlock, conditionEndBlock, |
| 1325 conditionInstruction); |
| 1326 loopInfo.joinBlock = current; |
| 1301 } | 1327 } |
| 1302 | 1328 |
| 1303 visitFunctionExpression(FunctionExpression node) { | 1329 visitFunctionExpression(FunctionExpression node) { |
| 1304 ClosureData nestedClosureData = compiler.builder.closureDataCache[node]; | 1330 ClosureData nestedClosureData = compiler.builder.closureDataCache[node]; |
| 1305 if (nestedClosureData === null) { | 1331 if (nestedClosureData === null) { |
| 1306 // TODO(floitsch): we can only assume that the reason for not having a | 1332 // TODO(floitsch): we can only assume that the reason for not having a |
| 1307 // closure data here is, because the function is inside an initializer. | 1333 // closure data here is, because the function is inside an initializer. |
| 1308 compiler.unimplemented("Closures inside initializers", node: node); | 1334 compiler.unimplemented("Closures inside initializers", node: node); |
| 1309 } | 1335 } |
| 1310 assert(nestedClosureData !== null); | 1336 assert(nestedClosureData !== null); |
| (...skipping 1057 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2368 */ | 2394 */ |
| 2369 JumpHandler createJumpHandler(Statement node) { | 2395 JumpHandler createJumpHandler(Statement node) { |
| 2370 TargetElement element = elements[node]; | 2396 TargetElement element = elements[node]; |
| 2371 if (element === null || element.statement !== node) { | 2397 if (element === null || element.statement !== node) { |
| 2372 // No breaks or continues to this node. | 2398 // No breaks or continues to this node. |
| 2373 return const NullJumpHandler(); | 2399 return const NullJumpHandler(); |
| 2374 } | 2400 } |
| 2375 return new JumpHandler(this, element); | 2401 return new JumpHandler(this, element); |
| 2376 } | 2402 } |
| 2377 | 2403 |
| 2378 visitForInStatement(ForInStatement node) { | 2404 visitForIn(ForIn node) { |
| 2379 // Generate a structure equivalent to: | 2405 // Generate a structure equivalent to: |
| 2380 // Iterator<E> $iter = <iterable>.iterator() | 2406 // Iterator<E> $iter = <iterable>.iterator() |
| 2381 // while ($iter.hasNext()) { | 2407 // while ($iter.hasNext()) { |
| 2382 // E <declaredIdentifier> = $iter.next(); | 2408 // E <declaredIdentifier> = $iter.next(); |
| 2383 // <body> | 2409 // <body> |
| 2384 // } | 2410 // } |
| 2385 | 2411 |
| 2386 // All the generated calls are to zero-argument functions. | 2412 // All the generated calls are to zero-argument functions. |
| 2387 Selector selector = Selector.INVOCATION_0; | 2413 Selector selector = Selector.INVOCATION_0; |
| 2388 // The iterator is shared between initializer, condition and body. | 2414 // The iterator is shared between initializer, condition and body. |
| (...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2928 false, | 2954 false, |
| 2929 <HInstruction>[target, input])); | 2955 <HInstruction>[target, input])); |
| 2930 return builder.pop(); | 2956 return builder.pop(); |
| 2931 } | 2957 } |
| 2932 | 2958 |
| 2933 HInstruction result() { | 2959 HInstruction result() { |
| 2934 flushLiterals(); | 2960 flushLiterals(); |
| 2935 return prefix; | 2961 return prefix; |
| 2936 } | 2962 } |
| 2937 } | 2963 } |
| OLD | NEW |