Chromium Code Reviews| 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 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1089 localsHandler.endLoop(loopEntry); | 1089 localsHandler.endLoop(loopEntry); |
| 1090 if (!breakLocals.isEmpty()) { | 1090 if (!breakLocals.isEmpty()) { |
| 1091 breakLocals.add(savedLocals); | 1091 breakLocals.add(savedLocals); |
| 1092 localsHandler = localsHandler.mergeMultiple(breakLocals, loopExitBlock); | 1092 localsHandler = localsHandler.mergeMultiple(breakLocals, loopExitBlock); |
| 1093 } else { | 1093 } else { |
| 1094 localsHandler = savedLocals; | 1094 localsHandler = savedLocals; |
| 1095 } | 1095 } |
| 1096 } | 1096 } |
| 1097 | 1097 |
| 1098 // For while loops, initializer and update are null. | 1098 // For while loops, initializer and update are null. |
| 1099 visitLoop(Node loop, | 1099 // The condition function must return a boolean result. |
|
ngeoffray
2012/03/21 07:58:47
Since they'are all doing, why not making it unifor
Lasse Reichstein Nielsen
2012/03/21 09:00:15
I expect to use this one in switch-with-continue,
| |
| 1100 Node initializer, | 1100 // None of the functions must leave anything on the stack. |
| 1101 Expression condition, | 1101 handleLoop(Node loop, |
| 1102 NodeList updates, | 1102 void initialize(), |
| 1103 Node body) { | 1103 HInstruction condition(), |
| 1104 void update(), | |
| 1105 void body()) { | |
| 1104 // Generate: | 1106 // Generate: |
| 1105 // <initializer> | 1107 // <initializer> |
| 1106 // loop-entry: | 1108 // loop-entry: |
| 1107 // if (!<condition>) goto loop-exit; | 1109 // if (!<condition>) goto loop-exit; |
| 1108 // <body> | 1110 // <body> |
| 1109 // <updates> | 1111 // <updates> |
| 1110 // goto loop-entry; | 1112 // goto loop-entry; |
| 1111 // loop-exit: | 1113 // loop-exit: |
| 1112 if (body === null) { | |
| 1113 compiler.unimplemented( | |
| 1114 'SsaBuilder.visitLoop with empty body', | |
| 1115 node: loop); | |
| 1116 } | |
| 1117 | 1114 |
| 1118 localsHandler.startLoop(loop); | 1115 localsHandler.startLoop(loop); |
| 1119 | 1116 |
| 1120 // The initializer. | 1117 // The initializer. |
| 1121 if (initializer !== null) { | 1118 if (initialize !== null) { |
| 1122 visit(initializer); | 1119 initialize(); |
| 1123 // We don't care about the value of the initialization. | |
| 1124 if (initializer.asExpression() !== null) pop(); | |
| 1125 } | 1120 } |
| 1126 assert(!isAborted()); | 1121 assert(!isAborted()); |
| 1127 | 1122 |
| 1128 JumpHandler jumpHandler = beginLoopHeader(loop); | 1123 JumpHandler jumpHandler = beginLoopHeader(loop); |
| 1129 HBasicBlock conditionBlock = current; | 1124 HBasicBlock conditionBlock = current; |
| 1130 | 1125 |
| 1131 HInstruction conditionInstruction; | 1126 HInstruction conditionInstruction; |
| 1132 if (condition != null) { | 1127 if (condition != null) { |
| 1133 visit(condition); | 1128 conditionInstruction = condition(); |
| 1134 conditionInstruction = popBoolified(); | |
| 1135 } else { | 1129 } else { |
| 1136 // TODO(ngeoffray): Once our loop recognition does not require a | 1130 // TODO(ngeoffray): Once our loop recognition does not require a |
| 1137 // HLoopBranch, we could just generate a HGoto. | 1131 // HLoopBranch, we could just generate a HGoto. |
| 1138 conditionInstruction = graph.addConstantBool(true); | 1132 conditionInstruction = graph.addConstantBool(true); |
| 1139 } | 1133 } |
| 1140 HBasicBlock conditionExitBlock = | 1134 HBasicBlock conditionExitBlock = |
| 1141 close(new HLoopBranch(conditionInstruction)); | 1135 close(new HLoopBranch(conditionInstruction)); |
| 1142 | 1136 |
| 1143 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1137 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| 1144 | 1138 |
| 1145 // The body. | 1139 // The body. |
| 1146 HBasicBlock beginBodyBlock = addNewBlock(); | 1140 HBasicBlock beginBodyBlock = addNewBlock(); |
| 1147 conditionExitBlock.addSuccessor(beginBodyBlock); | 1141 conditionExitBlock.addSuccessor(beginBodyBlock); |
| 1148 open(beginBodyBlock); | 1142 open(beginBodyBlock); |
| 1149 | 1143 |
| 1150 localsHandler.enterLoopBody(loop); | 1144 localsHandler.enterLoopBody(loop); |
| 1145 if (body !== null) { | |
| 1146 hackAroundPossiblyAbortingBody(loop, body); | |
| 1147 } | |
| 1151 | 1148 |
| 1152 hackAroundPossiblyAbortingBody(body); | |
| 1153 SubGraph bodyGraph = new SubGraph(beginBodyBlock, current); | 1149 SubGraph bodyGraph = new SubGraph(beginBodyBlock, current); |
| 1154 HBasicBlock bodyBlock = close(new HGoto()); | 1150 HBasicBlock bodyBlock = close(new HGoto()); |
| 1155 | 1151 |
| 1156 // Update. | 1152 // Update. |
| 1157 // We create an update block, even when we are in a while loop. There the | 1153 // We create an update block, even when we are in a while loop. There the |
| 1158 // update block is the jump-target for continue statements. We could avoid | 1154 // update block is the jump-target for continue statements. We could avoid |
| 1159 // the creation if there is no continue, but for now we always create it. | 1155 // the creation if there is no continue, but for now we always create it. |
| 1160 HBasicBlock updateBlock = addNewBlock(); | 1156 HBasicBlock updateBlock = addNewBlock(); |
| 1161 | 1157 |
| 1162 List<LocalsHandler> continueLocals = <LocalsHandler>[]; | 1158 List<LocalsHandler> continueLocals = <LocalsHandler>[]; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1174 HLabeledBlockInformation labelInfo; | 1170 HLabeledBlockInformation labelInfo; |
| 1175 List<LabelElement> labels = jumpHandler.labels(); | 1171 List<LabelElement> labels = jumpHandler.labels(); |
| 1176 if (!labels.isEmpty()) { | 1172 if (!labels.isEmpty()) { |
| 1177 beginBodyBlock.labeledBlockInformation = | 1173 beginBodyBlock.labeledBlockInformation = |
| 1178 new HLabeledBlockInformation(bodyGraph, updateBlock, | 1174 new HLabeledBlockInformation(bodyGraph, updateBlock, |
| 1179 jumpHandler.labels(), isContinue: true); | 1175 jumpHandler.labels(), isContinue: true); |
| 1180 } | 1176 } |
| 1181 | 1177 |
| 1182 localsHandler.enterLoopUpdates(loop); | 1178 localsHandler.enterLoopUpdates(loop); |
| 1183 | 1179 |
| 1184 if (updates !== null) { | 1180 if (update !== null) { |
| 1185 for (Expression expression in updates) { | 1181 update(); |
| 1186 visit(expression); | |
| 1187 assert(!isAborted()); | |
| 1188 // The result of the update instruction isn't used, and can just | |
| 1189 // be dropped. | |
| 1190 HInstruction updateInstruction = pop(); | |
| 1191 } | |
| 1192 } | 1182 } |
| 1193 updateBlock = close(new HGoto()); | 1183 updateBlock = close(new HGoto()); |
| 1194 // The back-edge completing the cycle. | 1184 // The back-edge completing the cycle. |
| 1195 updateBlock.addSuccessor(conditionBlock); | 1185 updateBlock.addSuccessor(conditionBlock); |
| 1196 conditionBlock.postProcessLoopHeader(); | 1186 conditionBlock.postProcessLoopHeader(); |
| 1197 | 1187 |
| 1198 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); | 1188 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); |
| 1199 } | 1189 } |
| 1200 | 1190 |
| 1201 visitFor(For node) { | 1191 visitFor(For node) { |
| 1202 assert(node.body !== null); | 1192 assert(node.body !== null); |
| 1203 visitLoop(node, node.initializer, node.condition, node.update, node.body); | 1193 void buildInitializer() { |
| 1194 Node initializer = node.initializer; | |
| 1195 if (initializer !== null) { | |
| 1196 visit(initializer); | |
| 1197 if (initializer.asExpression() !== null) { | |
| 1198 pop(); | |
| 1199 } | |
| 1200 } | |
| 1201 } | |
| 1202 HInstruction buildCondition() { | |
| 1203 visit(node.condition); | |
| 1204 return popBoolified(); | |
| 1205 } | |
| 1206 void buildUpdate() { | |
| 1207 for (Expression expression in node.update) { | |
| 1208 visit(expression); | |
| 1209 assert(!isAborted()); | |
| 1210 // The result of the update instruction isn't used, and can just | |
| 1211 // be dropped. | |
| 1212 HInstruction updateInstruction = pop(); | |
| 1213 } | |
| 1214 } | |
| 1215 handleLoop(node, | |
| 1216 node.initializer === null ? null : buildInitializer, | |
|
ngeoffray
2012/03/21 07:58:47
How about (for this one and all others):
node.ini
Lasse Reichstein Nielsen
2012/03/21 09:00:15
In this case, I could just put the test into the b
| |
| 1217 node.condition === null ? null : buildCondition, | |
| 1218 node.update.isEmpty() ? null : buildUpdate, | |
| 1219 () { visit(node.body); }); | |
| 1204 } | 1220 } |
| 1205 | 1221 |
| 1206 visitWhile(While node) { | 1222 visitWhile(While node) { |
| 1207 visitLoop(node, null, node.condition, null, node.body); | 1223 handleLoop(node, null, HInstruction condition() { visit(node.condition); |
|
ngeoffray
2012/03/21 07:58:47
I'd prefer one argument per line, or write the con
Lasse Reichstein Nielsen
2012/03/21 09:00:15
Done.
| |
| 1224 return popBoolified(); }, | |
| 1225 null, () { visit(node.body); }); | |
| 1208 } | 1226 } |
| 1209 | 1227 |
| 1210 visitDoWhile(DoWhile node) { | 1228 visitDoWhile(DoWhile node) { |
| 1211 localsHandler.startLoop(node); | 1229 localsHandler.startLoop(node); |
| 1212 JumpHandler jumpHandler = beginLoopHeader(node); | 1230 JumpHandler jumpHandler = beginLoopHeader(node); |
| 1213 HBasicBlock loopEntryBlock = current; | 1231 HBasicBlock loopEntryBlock = current; |
| 1214 | 1232 |
| 1215 localsHandler.enterLoopBody(node); | 1233 localsHandler.enterLoopBody(node); |
| 1216 hackAroundPossiblyAbortingBody(node.body); | 1234 hackAroundPossiblyAbortingBody(node, () { visit(node.body); }); |
| 1217 | 1235 |
| 1218 // If there are no continues we could avoid the creation of the condition | 1236 // If there are no continues we could avoid the creation of the condition |
| 1219 // block. This could also lead to a block having multiple entries and exits. | 1237 // block. This could also lead to a block having multiple entries and exits. |
| 1220 HBasicBlock bodyExitBlock = close(new HGoto()); | 1238 HBasicBlock bodyExitBlock = close(new HGoto()); |
| 1221 HBasicBlock conditionBlock = addNewBlock(); | 1239 HBasicBlock conditionBlock = addNewBlock(); |
| 1222 bodyExitBlock.addSuccessor(conditionBlock); | 1240 bodyExitBlock.addSuccessor(conditionBlock); |
| 1223 jumpHandler.forEachContinue((x,y) { | 1241 jumpHandler.forEachContinue((x,y) { |
| 1224 // TODO(lrn): Handle continue in do-while loops. | 1242 // TODO(lrn): Handle continue in do-while loops. |
| 1225 compiler.cancel("do-while with continue", node: node); | 1243 compiler.cancel("do-while with continue", node: node); |
| 1226 }); | 1244 }); |
| (...skipping 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2278 return new JumpHandler(this, element); | 2296 return new JumpHandler(this, element); |
| 2279 } | 2297 } |
| 2280 | 2298 |
| 2281 visitForInStatement(ForInStatement node) { | 2299 visitForInStatement(ForInStatement node) { |
| 2282 // Generate a structure equivalent to: | 2300 // Generate a structure equivalent to: |
| 2283 // Iterator<E> $iter = <iterable>.iterator() | 2301 // Iterator<E> $iter = <iterable>.iterator() |
| 2284 // while ($iter.hasNext()) { | 2302 // while ($iter.hasNext()) { |
| 2285 // E <declaredIdentifier> = $iter.next(); | 2303 // E <declaredIdentifier> = $iter.next(); |
| 2286 // <body> | 2304 // <body> |
| 2287 // } | 2305 // } |
| 2288 localsHandler.startLoop(node); | |
| 2289 | 2306 |
| 2290 SourceString iteratorName = const SourceString("iterator"); | 2307 // All the generated calls are to zero-argument functions. |
| 2308 Selector selector = Selector.INVOCATION_0; | |
| 2309 // The iterator is shared between initializer, condition and body. | |
| 2310 HInstruction iterator; | |
| 2311 void buildInitialize() { | |
|
ngeoffray
2012/03/21 07:58:47
buildInitializer?
Lasse Reichstein Nielsen
2012/03/21 09:00:15
Done.
| |
| 2312 SourceString iteratorName = const SourceString("iterator"); | |
| 2313 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0); | |
| 2314 assert(interceptor != null); | |
| 2315 HStatic target = new HStatic(interceptor); | |
| 2316 add(target); | |
| 2317 visit(node.expression); | |
| 2318 List<HInstruction> inputs = <HInstruction>[target, pop()]; | |
| 2319 iterator = new HInvokeInterceptor(selector, iteratorName, false, inputs); | |
| 2320 add(iterator); | |
| 2321 } | |
| 2322 HInstruction buildCondition() { | |
| 2323 push(new HInvokeDynamicMethod( | |
| 2324 selector, const SourceString('hasNext'), [iterator])); | |
|
ngeoffray
2012/03/21 07:58:47
<Instruction>[iterator]
Lasse Reichstein Nielsen
2012/03/21 09:00:15
Done.
| |
| 2325 return popBoolified(); | |
| 2326 } | |
| 2327 void buildBody() { | |
| 2328 push(new HInvokeDynamicMethod( | |
| 2329 selector, const SourceString('next'), [iterator])); | |
| 2291 | 2330 |
| 2292 Selector selector = Selector.INVOCATION_0; | 2331 Element variable; |
| 2293 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0); | 2332 if (node.declaredIdentifier.asSend() !== null) { |
| 2294 assert(interceptor != null); | 2333 variable = elements[node.declaredIdentifier]; |
| 2295 HStatic target = new HStatic(interceptor); | 2334 } else { |
| 2296 add(target); | 2335 assert(node.declaredIdentifier.asVariableDefinitions() !== null); |
| 2297 visit(node.expression); | 2336 VariableDefinitions variableDefinitions = node.declaredIdentifier; |
| 2298 List<HInstruction> inputs = <HInstruction>[target, pop()]; | 2337 variable = elements[variableDefinitions.definitions.nodes.head]; |
| 2299 HInstruction iterator = new HInvokeInterceptor( | 2338 } |
| 2300 selector, iteratorName, false, inputs); | 2339 localsHandler.updateLocal(variable, pop()); |
| 2301 add(iterator); | |
| 2302 | 2340 |
| 2303 JumpHandler jumpHandler = beginLoopHeader(node); | 2341 visit(node.body); |
| 2304 HBasicBlock conditionBlock = current; | |
| 2305 | |
| 2306 // The condition. | |
| 2307 push(new HInvokeDynamicMethod( | |
| 2308 selector, const SourceString('hasNext'), [iterator])); | |
| 2309 HBasicBlock conditionExitBlock = close(new HLoopBranch(popBoolified())); | |
| 2310 | |
| 2311 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | |
| 2312 | |
| 2313 // The body. | |
| 2314 HBasicBlock bodyBlock = addNewBlock(); | |
| 2315 conditionExitBlock.addSuccessor(bodyBlock); | |
| 2316 open(bodyBlock); | |
| 2317 | |
| 2318 // The call to next is considered to be part of the loop body. | |
| 2319 localsHandler.enterLoopBody(node); | |
| 2320 | |
| 2321 push(new HInvokeDynamicMethod( | |
| 2322 selector, const SourceString('next'), [iterator])); | |
| 2323 | |
| 2324 Element variable; | |
| 2325 if (node.declaredIdentifier.asSend() !== null) { | |
| 2326 variable = elements[node.declaredIdentifier]; | |
| 2327 } else { | |
| 2328 assert(node.declaredIdentifier.asVariableDefinitions() !== null); | |
| 2329 VariableDefinitions variableDefinitions = node.declaredIdentifier; | |
| 2330 variable = elements[variableDefinitions.definitions.nodes.head]; | |
| 2331 } | 2342 } |
| 2332 localsHandler.updateLocal(variable, pop()); | 2343 handleLoop(node, buildInitialize, buildCondition, null, buildBody); |
| 2333 | |
| 2334 hackAroundPossiblyAbortingBody(node.body); | |
| 2335 bodyBlock = close(new HGoto()); | |
| 2336 | |
| 2337 jumpHandler.forEachContinue((x,y) { | |
| 2338 // TODO(lrn): Handle continue in for-in. | |
| 2339 // TODO(lrn): Or, preferably, use an abstraction of visitLoop for for-in. | |
| 2340 compiler.cancel('for-in with continue', node: node); | |
| 2341 }); | |
| 2342 | |
| 2343 // Update. | |
| 2344 // We create an update block, even if we are in a for-in loop. The | |
| 2345 // update block is the jump-target for continue statements. We could avoid | |
| 2346 // the creation if there is no continue, but for now we always create it. | |
| 2347 HBasicBlock updateBlock = addNewBlock(); | |
| 2348 | |
| 2349 bodyBlock.addSuccessor(updateBlock); | |
| 2350 open(updateBlock); | |
| 2351 updateBlock = close(new HGoto()); | |
| 2352 // The back-edge completing the cycle. | |
| 2353 updateBlock.addSuccessor(conditionBlock); | |
| 2354 conditionBlock.postProcessLoopHeader(); | |
| 2355 | |
| 2356 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); | |
| 2357 jumpHandler.close(); | |
| 2358 } | 2344 } |
| 2359 | 2345 |
| 2360 visitLabeledStatement(LabeledStatement node) { | 2346 visitLabeledStatement(LabeledStatement node) { |
| 2361 Statement body = node.getBody(); | 2347 Statement body = node.getBody(); |
| 2362 if (body is Loop || body is SwitchStatement) { | 2348 if (body is Loop || body is SwitchStatement) { |
| 2363 // Loops and switches handle their own labels. | 2349 // Loops and switches handle their own labels. |
| 2364 visit(body); | 2350 visit(body); |
| 2365 return; | 2351 return; |
| 2366 } | 2352 } |
| 2367 // Non-loop statements can only be break targets, not continue targets. | 2353 // Non-loop statements can only be break targets, not continue targets. |
| 2368 TargetElement targetElement = elements[body]; | 2354 TargetElement targetElement = elements[body]; |
| 2369 if (targetElement === null || targetElement.statement !== body) { | 2355 if (targetElement === null || targetElement.statement !== body) { |
| 2370 // Labeled statements with no element on the body have no breaks. | 2356 // Labeled statements with no element on the body have no breaks. |
| 2371 // A different target statement only happens if the body is itself | 2357 // A different target statement only happens if the body is itself |
| 2372 // a break or continue for a different target. In that case, this | 2358 // a break or continue for a different target. In that case, this |
| 2373 // label is also always unused. | 2359 // label is also always unused. |
| 2374 visit(body); | 2360 visit(body); |
| 2375 return; | 2361 return; |
| 2376 } | 2362 } |
| 2377 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); | 2363 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); |
| 2378 assert(targetElement.isBreakTarget); | 2364 assert(targetElement.isBreakTarget); |
| 2379 JumpHandler handler = new JumpHandler(this, targetElement); | 2365 JumpHandler handler = new JumpHandler(this, targetElement); |
| 2380 // Introduce a new basic block. | 2366 // Introduce a new basic block. |
| 2381 HBasicBlock entryBlock = graph.addNewBlock(); | 2367 HBasicBlock entryBlock = graph.addNewBlock(); |
| 2382 goto(current, entryBlock); | 2368 goto(current, entryBlock); |
| 2383 open(entryBlock); | 2369 open(entryBlock); |
| 2384 hackAroundPossiblyAbortingBody(body); | 2370 hackAroundPossiblyAbortingBody(node, () { visit(body); }); |
| 2385 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); | 2371 SubGraph bodyGraph = new SubGraph(entryBlock, lastOpenedBlock); |
| 2386 | 2372 |
| 2387 HBasicBlock joinBlock = graph.addNewBlock(); | 2373 HBasicBlock joinBlock = graph.addNewBlock(); |
| 2388 List<LocalsHandler> breakLocals = <LocalsHandler>[]; | 2374 List<LocalsHandler> breakLocals = <LocalsHandler>[]; |
| 2389 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 2375 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
| 2390 breakInstruction.block.addSuccessor(joinBlock); | 2376 breakInstruction.block.addSuccessor(joinBlock); |
| 2391 breakLocals.add(locals); | 2377 breakLocals.add(locals); |
| 2392 }); | 2378 }); |
| 2393 bool hasBreak = breakLocals.length > 0; | 2379 bool hasBreak = breakLocals.length > 0; |
| 2394 if (!isAborted()) { | 2380 if (!isAborted()) { |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2692 // another unimplemented feature: aborting loop body. Simply | 2678 // another unimplemented feature: aborting loop body. Simply |
| 2693 // calling [add] does not work as it asserts that the instruction | 2679 // calling [add] does not work as it asserts that the instruction |
| 2694 // isn't a control flow instruction. So we inline parts of [add]. | 2680 // isn't a control flow instruction. So we inline parts of [add]. |
| 2695 current.addAfter(current.last, new HThrow(message)); | 2681 current.addAfter(current.last, new HThrow(message)); |
| 2696 if (isExpression) { | 2682 if (isExpression) { |
| 2697 stack.add(graph.addConstantNull()); | 2683 stack.add(graph.addConstantNull()); |
| 2698 } | 2684 } |
| 2699 } | 2685 } |
| 2700 | 2686 |
| 2701 /** HACK HACK HACK */ | 2687 /** HACK HACK HACK */ |
| 2702 void hackAroundPossiblyAbortingBody(Node body) { | 2688 void hackAroundPossiblyAbortingBody(Node statement, void body()) { |
| 2703 stack.add(graph.addConstantBool(true)); | 2689 stack.add(graph.addConstantBool(true)); |
| 2704 buildBody() { | 2690 buildBody() { |
| 2705 // TODO(lrn): Make sure to take continue into account. | 2691 // TODO(lrn): Make sure to take continue into account. |
| 2706 visit(body); | 2692 body(); |
| 2707 if (isAborted()) { | 2693 if (isAborted()) { |
| 2708 compiler.reportWarning(body, "aborting loop body"); | 2694 compiler.reportWarning(statement, "aborting loop body"); |
| 2709 } | 2695 } |
| 2710 } | 2696 } |
| 2711 handleIf(buildBody, null); | 2697 handleIf(buildBody, null); |
| 2712 } | 2698 } |
| 2713 } | 2699 } |
| 2714 | 2700 |
| 2715 /** | 2701 /** |
| 2716 * Visitor that handles generation of string literals (LiteralString, | 2702 * Visitor that handles generation of string literals (LiteralString, |
| 2717 * StringInterpolation), and otherwise delegates to the given visitor for | 2703 * StringInterpolation), and otherwise delegates to the given visitor for |
| 2718 * non-literal subexpressions. | 2704 * non-literal subexpressions. |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2805 HInstruction concat = new HAdd(target, left, right); | 2791 HInstruction concat = new HAdd(target, left, right); |
| 2806 builder.add(concat); | 2792 builder.add(concat); |
| 2807 return concat; | 2793 return concat; |
| 2808 } | 2794 } |
| 2809 | 2795 |
| 2810 HInstruction result() { | 2796 HInstruction result() { |
| 2811 flushAccumulator(); | 2797 flushAccumulator(); |
| 2812 return prefix; | 2798 return prefix; |
| 2813 } | 2799 } |
| 2814 } | 2800 } |
| OLD | NEW |