| 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 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 550 // We know 'this' cannot be modified. | 550 // We know 'this' cannot be modified. |
| 551 if (element === closureData.thisElement) { | 551 if (element === closureData.thisElement) { |
| 552 assert(directLocals[element] == instruction); | 552 assert(directLocals[element] == instruction); |
| 553 joinedLocals[element] = instruction; | 553 joinedLocals[element] = instruction; |
| 554 } else { | 554 } else { |
| 555 HInstruction mine = directLocals[element]; | 555 HInstruction mine = directLocals[element]; |
| 556 if (mine === null) return; | 556 if (mine === null) return; |
| 557 if (instruction === mine) { | 557 if (instruction === mine) { |
| 558 joinedLocals[element] = instruction; | 558 joinedLocals[element] = instruction; |
| 559 } else { | 559 } else { |
| 560 HInstruction phi = new HPhi.manyInputs(element, [instruction, mine]); | 560 HInstruction phi = |
| 561 new HPhi.manyInputs(element, <HInstruction>[instruction, mine]); |
| 561 joinBlock.addPhi(phi); | 562 joinBlock.addPhi(phi); |
| 562 joinedLocals[element] = phi; | 563 joinedLocals[element] = phi; |
| 563 } | 564 } |
| 564 } | 565 } |
| 565 }); | 566 }); |
| 566 directLocals = joinedLocals; | 567 directLocals = joinedLocals; |
| 567 } | 568 } |
| 568 | 569 |
| 569 /** | 570 /** |
| 570 * The current localsHandler is not used for its values, only for its | 571 * The current localsHandler is not used for its values, only for its |
| (...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1089 localsHandler.endLoop(loopEntry); | 1090 localsHandler.endLoop(loopEntry); |
| 1090 if (!breakLocals.isEmpty()) { | 1091 if (!breakLocals.isEmpty()) { |
| 1091 breakLocals.add(savedLocals); | 1092 breakLocals.add(savedLocals); |
| 1092 localsHandler = localsHandler.mergeMultiple(breakLocals, loopExitBlock); | 1093 localsHandler = localsHandler.mergeMultiple(breakLocals, loopExitBlock); |
| 1093 } else { | 1094 } else { |
| 1094 localsHandler = savedLocals; | 1095 localsHandler = savedLocals; |
| 1095 } | 1096 } |
| 1096 } | 1097 } |
| 1097 | 1098 |
| 1098 // For while loops, initializer and update are null. | 1099 // For while loops, initializer and update are null. |
| 1099 visitLoop(Node loop, | 1100 // The condition function must return a boolean result. |
| 1100 Node initializer, | 1101 // None of the functions must leave anything on the stack. |
| 1101 Expression condition, | 1102 handleLoop(Node loop, |
| 1102 NodeList updates, | 1103 void initialize(), |
| 1103 Node body) { | 1104 HInstruction condition(), |
| 1105 void update(), |
| 1106 void body()) { |
| 1104 // Generate: | 1107 // Generate: |
| 1105 // <initializer> | 1108 // <initializer> |
| 1106 // loop-entry: | 1109 // loop-entry: |
| 1107 // if (!<condition>) goto loop-exit; | 1110 // if (!<condition>) goto loop-exit; |
| 1108 // <body> | 1111 // <body> |
| 1109 // <updates> | 1112 // <updates> |
| 1110 // goto loop-entry; | 1113 // goto loop-entry; |
| 1111 // loop-exit: | 1114 // loop-exit: |
| 1112 if (body === null) { | |
| 1113 compiler.unimplemented( | |
| 1114 'SsaBuilder.visitLoop with empty body', | |
| 1115 node: loop); | |
| 1116 } | |
| 1117 | 1115 |
| 1118 localsHandler.startLoop(loop); | 1116 localsHandler.startLoop(loop); |
| 1119 | 1117 |
| 1120 // The initializer. | 1118 // The initializer. |
| 1121 if (initializer !== null) { | 1119 initialize(); |
| 1122 visit(initializer); | |
| 1123 // We don't care about the value of the initialization. | |
| 1124 if (initializer.asExpression() !== null) pop(); | |
| 1125 } | |
| 1126 assert(!isAborted()); | 1120 assert(!isAborted()); |
| 1127 | 1121 |
| 1128 JumpHandler jumpHandler = beginLoopHeader(loop); | 1122 JumpHandler jumpHandler = beginLoopHeader(loop); |
| 1129 HBasicBlock conditionBlock = current; | 1123 HBasicBlock conditionBlock = current; |
| 1130 | 1124 |
| 1131 HInstruction conditionInstruction; | 1125 HInstruction conditionInstruction = condition(); |
| 1132 if (condition != null) { | |
| 1133 visit(condition); | |
| 1134 conditionInstruction = popBoolified(); | |
| 1135 } else { | |
| 1136 // TODO(ngeoffray): Once our loop recognition does not require a | |
| 1137 // HLoopBranch, we could just generate a HGoto. | |
| 1138 conditionInstruction = graph.addConstantBool(true); | |
| 1139 } | |
| 1140 HBasicBlock conditionExitBlock = | 1126 HBasicBlock conditionExitBlock = |
| 1141 close(new HLoopBranch(conditionInstruction)); | 1127 close(new HLoopBranch(conditionInstruction)); |
| 1142 | 1128 |
| 1143 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); | 1129 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); |
| 1144 | 1130 |
| 1145 // The body. | 1131 // The body. |
| 1146 HBasicBlock beginBodyBlock = addNewBlock(); | 1132 HBasicBlock beginBodyBlock = addNewBlock(); |
| 1147 conditionExitBlock.addSuccessor(beginBodyBlock); | 1133 conditionExitBlock.addSuccessor(beginBodyBlock); |
| 1148 open(beginBodyBlock); | 1134 open(beginBodyBlock); |
| 1149 | 1135 |
| 1150 localsHandler.enterLoopBody(loop); | 1136 localsHandler.enterLoopBody(loop); |
| 1137 hackAroundPossiblyAbortingBody(loop, body); |
| 1151 | 1138 |
| 1152 hackAroundPossiblyAbortingBody(body); | |
| 1153 SubGraph bodyGraph = new SubGraph(beginBodyBlock, current); | 1139 SubGraph bodyGraph = new SubGraph(beginBodyBlock, current); |
| 1154 HBasicBlock bodyBlock = close(new HGoto()); | 1140 HBasicBlock bodyBlock = close(new HGoto()); |
| 1155 | 1141 |
| 1156 // Update. | 1142 // Update. |
| 1157 // We create an update block, even when we are in a while loop. There the | 1143 // 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 | 1144 // 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. | 1145 // the creation if there is no continue, but for now we always create it. |
| 1160 HBasicBlock updateBlock = addNewBlock(); | 1146 HBasicBlock updateBlock = addNewBlock(); |
| 1161 | 1147 |
| 1162 List<LocalsHandler> continueLocals = <LocalsHandler>[]; | 1148 List<LocalsHandler> continueLocals = <LocalsHandler>[]; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1174 HLabeledBlockInformation labelInfo; | 1160 HLabeledBlockInformation labelInfo; |
| 1175 List<LabelElement> labels = jumpHandler.labels(); | 1161 List<LabelElement> labels = jumpHandler.labels(); |
| 1176 if (!labels.isEmpty()) { | 1162 if (!labels.isEmpty()) { |
| 1177 beginBodyBlock.labeledBlockInformation = | 1163 beginBodyBlock.labeledBlockInformation = |
| 1178 new HLabeledBlockInformation(bodyGraph, updateBlock, | 1164 new HLabeledBlockInformation(bodyGraph, updateBlock, |
| 1179 jumpHandler.labels(), isContinue: true); | 1165 jumpHandler.labels(), isContinue: true); |
| 1180 } | 1166 } |
| 1181 | 1167 |
| 1182 localsHandler.enterLoopUpdates(loop); | 1168 localsHandler.enterLoopUpdates(loop); |
| 1183 | 1169 |
| 1184 if (updates !== null) { | 1170 update(); |
| 1185 for (Expression expression in updates) { | 1171 |
| 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 } | |
| 1193 updateBlock = close(new HGoto()); | 1172 updateBlock = close(new HGoto()); |
| 1194 // The back-edge completing the cycle. | 1173 // The back-edge completing the cycle. |
| 1195 updateBlock.addSuccessor(conditionBlock); | 1174 updateBlock.addSuccessor(conditionBlock); |
| 1196 conditionBlock.postProcessLoopHeader(); | 1175 conditionBlock.postProcessLoopHeader(); |
| 1197 | 1176 |
| 1198 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); | 1177 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals); |
| 1199 } | 1178 } |
| 1200 | 1179 |
| 1201 visitFor(For node) { | 1180 visitFor(For node) { |
| 1202 assert(node.body !== null); | 1181 assert(node.body !== null); |
| 1203 visitLoop(node, node.initializer, node.condition, node.update, node.body); | 1182 void buildInitializer() { |
| 1183 if (node.initializer === null) return; |
| 1184 Node initializer = node.initializer; |
| 1185 if (initializer !== null) { |
| 1186 visit(initializer); |
| 1187 if (initializer.asExpression() !== null) { |
| 1188 pop(); |
| 1189 } |
| 1190 } |
| 1191 } |
| 1192 HInstruction buildCondition() { |
| 1193 if (node.condition === null) { |
| 1194 return graph.addConstantBool(true); |
| 1195 } |
| 1196 visit(node.condition); |
| 1197 return popBoolified(); |
| 1198 } |
| 1199 void buildUpdate() { |
| 1200 for (Expression expression in node.update) { |
| 1201 visit(expression); |
| 1202 assert(!isAborted()); |
| 1203 // The result of the update instruction isn't used, and can just |
| 1204 // be dropped. |
| 1205 HInstruction updateInstruction = pop(); |
| 1206 } |
| 1207 } |
| 1208 void buildBody() { |
| 1209 visit(node.body); |
| 1210 } |
| 1211 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody); |
| 1204 } | 1212 } |
| 1205 | 1213 |
| 1206 visitWhile(While node) { | 1214 visitWhile(While node) { |
| 1207 visitLoop(node, null, node.condition, null, node.body); | 1215 HInstruction buildCondition() { |
| 1216 visit(node.condition); |
| 1217 return popBoolified(); |
| 1218 } |
| 1219 handleLoop(node, |
| 1220 () {}, |
| 1221 buildCondition, |
| 1222 () {}, |
| 1223 () { visit(node.body); }); |
| 1208 } | 1224 } |
| 1209 | 1225 |
| 1210 visitDoWhile(DoWhile node) { | 1226 visitDoWhile(DoWhile node) { |
| 1211 localsHandler.startLoop(node); | 1227 localsHandler.startLoop(node); |
| 1212 JumpHandler jumpHandler = beginLoopHeader(node); | 1228 JumpHandler jumpHandler = beginLoopHeader(node); |
| 1213 HBasicBlock loopEntryBlock = current; | 1229 HBasicBlock loopEntryBlock = current; |
| 1214 | 1230 |
| 1215 localsHandler.enterLoopBody(node); | 1231 localsHandler.enterLoopBody(node); |
| 1216 hackAroundPossiblyAbortingBody(node.body); | 1232 hackAroundPossiblyAbortingBody(node, () { visit(node.body); }); |
| 1217 | 1233 |
| 1218 // If there are no continues we could avoid the creation of the condition | 1234 // 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. | 1235 // block. This could also lead to a block having multiple entries and exits. |
| 1220 HBasicBlock bodyExitBlock = close(new HGoto()); | 1236 HBasicBlock bodyExitBlock = close(new HGoto()); |
| 1221 HBasicBlock conditionBlock = addNewBlock(); | 1237 HBasicBlock conditionBlock = addNewBlock(); |
| 1222 bodyExitBlock.addSuccessor(conditionBlock); | 1238 bodyExitBlock.addSuccessor(conditionBlock); |
| 1223 jumpHandler.forEachContinue((x,y) { | 1239 jumpHandler.forEachContinue((x,y) { |
| 1224 // TODO(lrn): Handle continue in do-while loops. | 1240 // TODO(lrn): Handle continue in do-while loops. |
| 1225 compiler.cancel("do-while with continue", node: node); | 1241 compiler.cancel("do-while with continue", node: node); |
| 1226 }); | 1242 }); |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1383 | 1399 |
| 1384 HBasicBlock joinBlock = addNewBlock(); | 1400 HBasicBlock joinBlock = addNewBlock(); |
| 1385 leftBlock.addSuccessor(joinBlock); | 1401 leftBlock.addSuccessor(joinBlock); |
| 1386 rightBlock.addSuccessor(joinBlock); | 1402 rightBlock.addSuccessor(joinBlock); |
| 1387 open(joinBlock); | 1403 open(joinBlock); |
| 1388 | 1404 |
| 1389 branch.blockInformation = | 1405 branch.blockInformation = |
| 1390 new HIfBlockInformation(branch, rightGraph, null, joinBlock); | 1406 new HIfBlockInformation(branch, rightGraph, null, joinBlock); |
| 1391 | 1407 |
| 1392 localsHandler.mergeWith(savedLocals, joinBlock); | 1408 localsHandler.mergeWith(savedLocals, joinBlock); |
| 1393 HPhi result = new HPhi.manyInputs(null, [boolifiedLeft, boolifiedRight]); | 1409 HPhi result = new HPhi.manyInputs(null, |
| 1410 <HInstruction>[boolifiedLeft, boolifiedRight]); |
| 1394 joinBlock.addPhi(result); | 1411 joinBlock.addPhi(result); |
| 1395 stack.add(result); | 1412 stack.add(result); |
| 1396 } | 1413 } |
| 1397 | 1414 |
| 1398 void visitLogicalNot(Send node) { | 1415 void visitLogicalNot(Send node) { |
| 1399 assert(node.argumentsNode is Prefix); | 1416 assert(node.argumentsNode is Prefix); |
| 1400 visit(node.receiver); | 1417 visit(node.receiver); |
| 1401 HNot not = new HNot(popBoolified()); | 1418 HNot not = new HNot(popBoolified()); |
| 1402 push(not); | 1419 push(not); |
| 1403 } | 1420 } |
| (...skipping 798 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2202 elseBlock = close(new HGoto()); | 2219 elseBlock = close(new HGoto()); |
| 2203 | 2220 |
| 2204 HBasicBlock joinBlock = addNewBlock(); | 2221 HBasicBlock joinBlock = addNewBlock(); |
| 2205 thenBlock.addSuccessor(joinBlock); | 2222 thenBlock.addSuccessor(joinBlock); |
| 2206 elseBlock.addSuccessor(joinBlock); | 2223 elseBlock.addSuccessor(joinBlock); |
| 2207 condition.blockInformation = | 2224 condition.blockInformation = |
| 2208 new HIfBlockInformation(condition, thenGraph, elseGraph, joinBlock); | 2225 new HIfBlockInformation(condition, thenGraph, elseGraph, joinBlock); |
| 2209 open(joinBlock); | 2226 open(joinBlock); |
| 2210 | 2227 |
| 2211 localsHandler.mergeWith(thenLocals, joinBlock); | 2228 localsHandler.mergeWith(thenLocals, joinBlock); |
| 2212 HPhi phi = new HPhi.manyInputs(null, [thenInstruction, elseInstruction]); | 2229 HPhi phi = new HPhi.manyInputs(null, |
| 2230 <HInstruction>[thenInstruction, elseInstruction]); |
| 2213 joinBlock.addPhi(phi); | 2231 joinBlock.addPhi(phi); |
| 2214 stack.add(phi); | 2232 stack.add(phi); |
| 2215 } | 2233 } |
| 2216 | 2234 |
| 2217 visitStringInterpolation(StringInterpolation node) { | 2235 visitStringInterpolation(StringInterpolation node) { |
| 2218 int offset = node.getBeginToken().charOffset; | 2236 int offset = node.getBeginToken().charOffset; |
| 2219 StringBuilderVisitor stringBuilder = | 2237 StringBuilderVisitor stringBuilder = |
| 2220 new StringBuilderVisitor(this, offset); | 2238 new StringBuilderVisitor(this, offset); |
| 2221 stringBuilder.visit(node); | 2239 stringBuilder.visit(node); |
| 2222 stack.add(stringBuilder.result()); | 2240 stack.add(stringBuilder.result()); |
| (...skipping 55 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 buildInitializer() { |
| 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'), <HInstruction>[iterator])); |
| 2325 return popBoolified(); |
| 2326 } |
| 2327 void buildBody() { |
| 2328 push(new HInvokeDynamicMethod( |
| 2329 selector, const SourceString('next'), <HInstruction>[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, buildInitializer, buildCondition, () {}, 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 |