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 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 531 joinedLocals[element] = instruction; | 531 joinedLocals[element] = instruction; |
| 532 } else { | 532 } else { |
| 533 HInstruction phi = new HPhi.manyInputs(element, [instruction, mine]); | 533 HInstruction phi = new HPhi.manyInputs(element, [instruction, mine]); |
| 534 joinBlock.addPhi(phi); | 534 joinBlock.addPhi(phi); |
| 535 joinedLocals[element] = phi; | 535 joinedLocals[element] = phi; |
| 536 } | 536 } |
| 537 } | 537 } |
| 538 }); | 538 }); |
| 539 directLocals = joinedLocals; | 539 directLocals = joinedLocals; |
| 540 } | 540 } |
| 541 | |
| 542 /** | |
| 543 * The current localsHandler is not used for its values, only for its | |
| 544 * declared variables. This is a way exclude local values from the | |
|
ngeoffray
2012/02/29 10:02:54
way *to*
Lasse Reichstein Nielsen
2012/02/29 10:42:02
Done.
| |
| 545 * result when they are no longer in scope. | |
| 546 * Returns the new LocalsHandler to use (may not be [this]). | |
| 547 */ | |
| 548 void mergeMultiple(List<LocalsHandler> locals, HBasicBlock joinBlock) { | |
|
ngeoffray
2012/02/29 10:02:54
void -> LocalsHandler
Lasse Reichstein Nielsen
2012/02/29 10:42:02
Done.
| |
| 549 assert(locals.length > 0); | |
| 550 if (locals.length == 1) return locals[0]; | |
| 551 Map<Element, HInstruction> joinedLocals = new Map<Element,HInstruction>(); | |
| 552 HInstruction thisValue = null; | |
| 553 directLocals.forEach((Element element, HInstruction instruction) { | |
| 554 if (element !== closureData.thisElement) { | |
| 555 HPhi phi = new HPhi(element); | |
| 556 joinedLocals[element] = phi; | |
| 557 joinBlock.addPhi(phi); | |
| 558 } else { | |
| 559 // We know that "this" never changes, if it's there. | |
| 560 // Save it for later. While merging, there is no phi for "this", | |
| 561 // so we don't have to special case it in the merge loop. | |
| 562 thisValue = instruction; | |
| 563 } | |
| 564 }); | |
| 565 for (LocalsHandler local in locals) { | |
| 566 local.directLocals.forEach((Element element, HInstruction instruction) { | |
| 567 HPhi phi = joinedLocals[element]; | |
| 568 if (phi !== null) { | |
| 569 phi.addInput(instruction); | |
| 570 } | |
| 571 }); | |
| 572 } | |
| 573 if (thisValue !== null) { | |
| 574 // If there was a "this" for the scope, add it to the new locals. | |
| 575 joinedLocals[closureData.thisElement] = thisValue; | |
| 576 } | |
| 577 directLocals = joinedLocals; | |
| 578 return this; | |
| 579 } | |
| 541 } | 580 } |
| 542 | 581 |
| 543 | 582 |
| 544 // Represents a single break instruction. | 583 // Represents a single break instruction. |
| 545 class BreakHandlerEntry { | 584 class BreakHandlerEntry { |
| 546 final HBreak breakInstruction; | 585 final HBreak breakInstruction; |
| 547 final LocalsHandler locals; | 586 final LocalsHandler locals; |
| 548 BreakHandlerEntry(this.breakInstruction, this.locals); | 587 BreakHandlerEntry(this.breakInstruction, this.locals); |
| 549 } | 588 } |
| 550 | 589 |
| (...skipping 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 962 * Ends the loop: | 1001 * Ends the loop: |
| 963 * - creates a new block and adds it as successor to the [branchBlock]. | 1002 * - creates a new block and adds it as successor to the [branchBlock]. |
| 964 * - opens the new block (setting as [current]). | 1003 * - opens the new block (setting as [current]). |
| 965 * - notifies the locals handler that we're exiting a loop. | 1004 * - notifies the locals handler that we're exiting a loop. |
| 966 */ | 1005 */ |
| 967 void endLoop(HBasicBlock loopEntry, | 1006 void endLoop(HBasicBlock loopEntry, |
| 968 HBasicBlock branchBlock, | 1007 HBasicBlock branchBlock, |
| 969 BreakHandler breakHandler) { | 1008 BreakHandler breakHandler) { |
| 970 HBasicBlock loopExitBlock = addNewBlock(); | 1009 HBasicBlock loopExitBlock = addNewBlock(); |
| 971 assert(branchBlock.successors.length == 1); | 1010 assert(branchBlock.successors.length == 1); |
| 1011 List<LocalsHandler> breakLocals = <LocalsHandler>[]; | |
| 1012 breakHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | |
| 1013 breakInstruction.block.addSuccessor(loopExitBlock); | |
| 1014 breakLocals.add(locals); | |
| 1015 }); | |
| 972 branchBlock.addSuccessor(loopExitBlock); | 1016 branchBlock.addSuccessor(loopExitBlock); |
| 973 open(loopExitBlock); | 1017 open(loopExitBlock); |
| 974 localsHandler.endLoop(loopEntry); | 1018 localsHandler.endLoop(loopEntry); |
| 975 breakHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 1019 if (!breakLocals.isEmpty()) { |
| 976 HBasicBlock joinBlock = addNewBlock(); | 1020 breakLocals.add(localsHandler); |
| 977 breakInstruction.block.addSuccessor(joinBlock); | 1021 localsHandler = localsHandler.mergeMultiple(breakLocals, loopExitBlock); |
| 978 goto(current, joinBlock); | 1022 } |
| 979 open(joinBlock); | |
| 980 localsHandler.mergeWith(locals, joinBlock); | |
| 981 }); | |
| 982 } | 1023 } |
| 983 | 1024 |
| 984 // For while loops, initializer and update are null. | 1025 // For while loops, initializer and update are null. |
| 985 visitLoop(Node loop, Node initializer, Expression condition, NodeList updates, | 1026 visitLoop(Node loop, Node initializer, Expression condition, NodeList updates, |
| 986 Node body) { | 1027 Node body) { |
| 987 // Generate: | 1028 // Generate: |
| 988 // <initializer> | 1029 // <initializer> |
| 989 // loop-entry: | 1030 // loop-entry: |
| 990 // if (!<condition>) goto loop-exit; | 1031 // if (!<condition>) goto loop-exit; |
| 991 // <body> | 1032 // <body> |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1081 } | 1122 } |
| 1082 | 1123 |
| 1083 // If there are no continues we could avoid the creation of the condition | 1124 // If there are no continues we could avoid the creation of the condition |
| 1084 // block. This could also lead to a block having multiple entries and exits. | 1125 // block. This could also lead to a block having multiple entries and exits. |
| 1085 HBasicBlock bodyExitBlock = close(new HGoto()); | 1126 HBasicBlock bodyExitBlock = close(new HGoto()); |
| 1086 HBasicBlock conditionBlock = addNewBlock(); | 1127 HBasicBlock conditionBlock = addNewBlock(); |
| 1087 bodyExitBlock.addSuccessor(conditionBlock); | 1128 bodyExitBlock.addSuccessor(conditionBlock); |
| 1088 open(conditionBlock); | 1129 open(conditionBlock); |
| 1089 visit(node.condition); | 1130 visit(node.condition); |
| 1090 assert(!isAborted()); | 1131 assert(!isAborted()); |
| 1091 conditionBlock = close(new HLoopBranch(popBoolified())); | 1132 conditionBlock = close(new HLoopBranch(popBoolified(), |
| 1133 HLoopBranch.DO_WHILE_LOOP)); | |
| 1092 | 1134 |
| 1093 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge. | 1135 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge. |
| 1094 loopEntryBlock.postProcessLoopHeader(); | 1136 loopEntryBlock.postProcessLoopHeader(); |
| 1095 | 1137 |
| 1096 endLoop(loopEntryBlock, conditionBlock, breakHandler); | 1138 endLoop(loopEntryBlock, conditionBlock, breakHandler); |
| 1097 } | 1139 } |
| 1098 | 1140 |
| 1099 visitFunctionExpression(FunctionExpression node) { | 1141 visitFunctionExpression(FunctionExpression node) { |
| 1100 ClosureData nestedClosureData = closureDataCache[node]; | 1142 ClosureData nestedClosureData = closureDataCache[node]; |
| 1101 assert(nestedClosureData !== null); | 1143 assert(nestedClosureData !== null); |
| (...skipping 1045 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2147 if (handler === null) { | 2189 if (handler === null) { |
| 2148 // The labels are not break targets. | 2190 // The labels are not break targets. |
| 2149 visit(currentNode); | 2191 visit(currentNode); |
| 2150 } else if (currentNode is Loop || currentNode is SwitchStatement) { | 2192 } else if (currentNode is Loop || currentNode is SwitchStatement) { |
| 2151 // The labels apply to that statement, and will be handled there. | 2193 // The labels apply to that statement, and will be handled there. |
| 2152 loopBreakHandler = handler; | 2194 loopBreakHandler = handler; |
| 2153 visit(currentNode); | 2195 visit(currentNode); |
| 2154 assert(loopBreakHandler === null); | 2196 assert(loopBreakHandler === null); |
| 2155 } else { | 2197 } else { |
| 2156 // Introduce a new basic block. | 2198 // Introduce a new basic block. |
| 2199 LocalsHandler beforeLocals = new LocalsHandler.from(localsHandler); | |
| 2157 HBasicBlock entryBlock = graph.addNewBlock(); | 2200 HBasicBlock entryBlock = graph.addNewBlock(); |
| 2158 goto(current, entryBlock); | 2201 goto(current, entryBlock); |
| 2159 open(entryBlock); | 2202 open(entryBlock); |
| 2160 visit(currentNode); | 2203 visit(currentNode); |
| 2161 if (isAborted()) { | 2204 if (isAborted()) { |
| 2162 compiler.unimplemented( | 2205 compiler.unimplemented( |
| 2163 "SsaBuilder for labeled statement with aborting body", node: node); | 2206 "SsaBuilder for labeled statement with aborting body", node: node); |
| 2164 } | 2207 } |
| 2165 HBasicBlock exitBlock = current; | 2208 HBasicBlock joinBlock = graph.addNewBlock(); |
| 2209 List<LocalsHandler> breakLocals = <LocalsHandler>[]; | |
| 2166 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 2210 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
| 2167 HBasicBlock joinBlock = graph.addNewBlock(); | |
| 2168 breakInstruction.block.addSuccessor(joinBlock); | 2211 breakInstruction.block.addSuccessor(joinBlock); |
| 2169 if (!isAborted()) { | 2212 breakLocals.add(locals); |
| 2170 goto(current, joinBlock); | |
| 2171 open(joinBlock); | |
| 2172 localsHandler.mergeWith(locals, joinBlock); | |
| 2173 } else { | |
| 2174 open(joinBlock); | |
| 2175 localsHandler = locals; | |
| 2176 } | |
| 2177 }); | 2213 }); |
| 2178 if (current !== exitBlock) { | 2214 bool hasBreak = breakLocals.length > 0; |
| 2215 if (!isAborted()) { | |
| 2216 goto(current, joinBlock); | |
| 2217 breakLocals.add(localsHandler); | |
| 2218 } | |
| 2219 localsHandler = beforeLocals.mergeMultiple(breakLocals, joinBlock); | |
| 2220 | |
| 2221 if (hasBreak) { | |
| 2179 // There was at least one reachable break, so the label is needed. | 2222 // There was at least one reachable break, so the label is needed. |
| 2180 HLabeledBlockInformation blockInfo = | 2223 HLabeledBlockInformation blockInfo = |
| 2181 new HLabeledBlockInformation(entryBlock, current, | 2224 new HLabeledBlockInformation(entryBlock, current, |
| 2182 handler.labels()); | 2225 handler.labels()); |
| 2183 handler.close(); | 2226 handler.close(); |
| 2184 entryBlock.labeledBlockInformation = blockInfo; | |
| 2185 // Mark both entry and exit with the information. You can | 2227 // Mark both entry and exit with the information. You can |
| 2186 // tell which one is which by comparing with blockInfo.start/end. | 2228 // tell which one is which by comparing with blockInfo.start/end. |
| 2187 // It doesn't matter which merge block we use, they won't be generating | 2229 // It doesn't matter which merge block we use, they won't be generating |
| 2188 // any code, so put the end-marker on the last join block. | 2230 // any code, so put the end-marker on the last join block. |
| 2231 entryBlock.labeledBlockInformation = blockInfo; | |
| 2189 current.labeledBlockInformation = blockInfo; | 2232 current.labeledBlockInformation = blockInfo; |
| 2190 } | 2233 } |
| 2191 } | 2234 } |
| 2192 } | 2235 } |
| 2193 | 2236 |
| 2194 visitLiteralMap(LiteralMap node) { | 2237 visitLiteralMap(LiteralMap node) { |
| 2195 compiler.unimplemented('SsaBuilder.visitLiteralMap', node: node); | 2238 compiler.unimplemented('SsaBuilder.visitLiteralMap', node: node); |
| 2196 } | 2239 } |
| 2197 | 2240 |
| 2198 visitLiteralMapEntry(LiteralMapEntry node) { | 2241 visitLiteralMapEntry(LiteralMapEntry node) { |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2308 } | 2351 } |
| 2309 | 2352 |
| 2310 visitCatchBlock(CatchBlock node) { | 2353 visitCatchBlock(CatchBlock node) { |
| 2311 visit(node.block); | 2354 visit(node.block); |
| 2312 } | 2355 } |
| 2313 | 2356 |
| 2314 visitTypedef(Typedef node) { | 2357 visitTypedef(Typedef node) { |
| 2315 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); | 2358 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); |
| 2316 } | 2359 } |
| 2317 } | 2360 } |
| OLD | NEW |