| 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 to exclude local values from the |
| 545 * result when they are no longer in scope. |
| 546 * Returns the new LocalsHandler to use (may not be [this]). |
| 547 */ |
| 548 LocalsHandler mergeMultiple(List<LocalsHandler> locals, |
| 549 HBasicBlock joinBlock) { |
| 550 assert(locals.length > 0); |
| 551 if (locals.length == 1) return locals[0]; |
| 552 Map<Element, HInstruction> joinedLocals = new Map<Element,HInstruction>(); |
| 553 HInstruction thisValue = null; |
| 554 directLocals.forEach((Element element, HInstruction instruction) { |
| 555 if (element !== closureData.thisElement) { |
| 556 HPhi phi = new HPhi.noInputs(element); |
| 557 joinedLocals[element] = phi; |
| 558 joinBlock.addPhi(phi); |
| 559 } else { |
| 560 // We know that "this" never changes, if it's there. |
| 561 // Save it for later. While merging, there is no phi for "this", |
| 562 // so we don't have to special case it in the merge loop. |
| 563 thisValue = instruction; |
| 564 } |
| 565 }); |
| 566 for (LocalsHandler local in locals) { |
| 567 local.directLocals.forEach((Element element, HInstruction instruction) { |
| 568 HPhi phi = joinedLocals[element]; |
| 569 if (phi !== null) { |
| 570 phi.addInput(instruction); |
| 571 } |
| 572 }); |
| 573 } |
| 574 if (thisValue !== null) { |
| 575 // If there was a "this" for the scope, add it to the new locals. |
| 576 joinedLocals[closureData.thisElement] = thisValue; |
| 577 } |
| 578 directLocals = joinedLocals; |
| 579 return this; |
| 580 } |
| 541 } | 581 } |
| 542 | 582 |
| 543 | 583 |
| 544 // Represents a single break instruction. | 584 // Represents a single break instruction. |
| 545 class BreakHandlerEntry { | 585 class BreakHandlerEntry { |
| 546 final HBreak breakInstruction; | 586 final HBreak breakInstruction; |
| 547 final LocalsHandler locals; | 587 final LocalsHandler locals; |
| 548 BreakHandlerEntry(this.breakInstruction, this.locals); | 588 BreakHandlerEntry(this.breakInstruction, this.locals); |
| 549 } | 589 } |
| 550 | 590 |
| (...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 951 * Ends the loop: | 991 * Ends the loop: |
| 952 * - creates a new block and adds it as successor to the [branchBlock]. | 992 * - creates a new block and adds it as successor to the [branchBlock]. |
| 953 * - opens the new block (setting as [current]). | 993 * - opens the new block (setting as [current]). |
| 954 * - notifies the locals handler that we're exiting a loop. | 994 * - notifies the locals handler that we're exiting a loop. |
| 955 */ | 995 */ |
| 956 void endLoop(HBasicBlock loopEntry, | 996 void endLoop(HBasicBlock loopEntry, |
| 957 HBasicBlock branchBlock, | 997 HBasicBlock branchBlock, |
| 958 BreakHandler breakHandler) { | 998 BreakHandler breakHandler) { |
| 959 HBasicBlock loopExitBlock = addNewBlock(); | 999 HBasicBlock loopExitBlock = addNewBlock(); |
| 960 assert(branchBlock.successors.length == 1); | 1000 assert(branchBlock.successors.length == 1); |
| 1001 List<LocalsHandler> breakLocals = <LocalsHandler>[]; |
| 1002 breakHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
| 1003 breakInstruction.block.addSuccessor(loopExitBlock); |
| 1004 breakLocals.add(locals); |
| 1005 }); |
| 961 branchBlock.addSuccessor(loopExitBlock); | 1006 branchBlock.addSuccessor(loopExitBlock); |
| 962 open(loopExitBlock); | 1007 open(loopExitBlock); |
| 963 localsHandler.endLoop(loopEntry); | 1008 localsHandler.endLoop(loopEntry); |
| 964 breakHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 1009 if (!breakLocals.isEmpty()) { |
| 965 HBasicBlock joinBlock = addNewBlock(); | 1010 breakLocals.add(localsHandler); |
| 966 breakInstruction.block.addSuccessor(joinBlock); | 1011 localsHandler = localsHandler.mergeMultiple(breakLocals, loopExitBlock); |
| 967 goto(current, joinBlock); | 1012 } |
| 968 open(joinBlock); | |
| 969 localsHandler.mergeWith(locals, joinBlock); | |
| 970 }); | |
| 971 } | 1013 } |
| 972 | 1014 |
| 973 // For while loops, initializer and update are null. | 1015 // For while loops, initializer and update are null. |
| 974 visitLoop(Node loop, Node initializer, Expression condition, NodeList updates, | 1016 visitLoop(Node loop, Node initializer, Expression condition, NodeList updates, |
| 975 Node body) { | 1017 Node body) { |
| 976 // Generate: | 1018 // Generate: |
| 977 // <initializer> | 1019 // <initializer> |
| 978 // loop-entry: | 1020 // loop-entry: |
| 979 // if (!<condition>) goto loop-exit; | 1021 // if (!<condition>) goto loop-exit; |
| 980 // <body> | 1022 // <body> |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1070 } | 1112 } |
| 1071 | 1113 |
| 1072 // If there are no continues we could avoid the creation of the condition | 1114 // If there are no continues we could avoid the creation of the condition |
| 1073 // block. This could also lead to a block having multiple entries and exits. | 1115 // block. This could also lead to a block having multiple entries and exits. |
| 1074 HBasicBlock bodyExitBlock = close(new HGoto()); | 1116 HBasicBlock bodyExitBlock = close(new HGoto()); |
| 1075 HBasicBlock conditionBlock = addNewBlock(); | 1117 HBasicBlock conditionBlock = addNewBlock(); |
| 1076 bodyExitBlock.addSuccessor(conditionBlock); | 1118 bodyExitBlock.addSuccessor(conditionBlock); |
| 1077 open(conditionBlock); | 1119 open(conditionBlock); |
| 1078 visit(node.condition); | 1120 visit(node.condition); |
| 1079 assert(!isAborted()); | 1121 assert(!isAborted()); |
| 1080 conditionBlock = close(new HLoopBranch(popBoolified())); | 1122 conditionBlock = close(new HLoopBranch(popBoolified(), |
| 1123 HLoopBranch.DO_WHILE_LOOP)); |
| 1081 | 1124 |
| 1082 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge. | 1125 conditionBlock.addSuccessor(loopEntryBlock); // The back-edge. |
| 1083 loopEntryBlock.postProcessLoopHeader(); | 1126 loopEntryBlock.postProcessLoopHeader(); |
| 1084 | 1127 |
| 1085 endLoop(loopEntryBlock, conditionBlock, breakHandler); | 1128 endLoop(loopEntryBlock, conditionBlock, breakHandler); |
| 1086 } | 1129 } |
| 1087 | 1130 |
| 1088 visitFunctionExpression(FunctionExpression node) { | 1131 visitFunctionExpression(FunctionExpression node) { |
| 1089 ClosureData nestedClosureData = closureDataCache[node]; | 1132 ClosureData nestedClosureData = closureDataCache[node]; |
| 1090 assert(nestedClosureData !== null); | 1133 assert(nestedClosureData !== null); |
| (...skipping 1048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2139 BreakHandler handler = new BreakHandler(this, targetElement); | 2182 BreakHandler handler = new BreakHandler(this, targetElement); |
| 2140 // Introduce a new basic block. | 2183 // Introduce a new basic block. |
| 2141 HBasicBlock entryBlock = graph.addNewBlock(); | 2184 HBasicBlock entryBlock = graph.addNewBlock(); |
| 2142 goto(current, entryBlock); | 2185 goto(current, entryBlock); |
| 2143 open(entryBlock); | 2186 open(entryBlock); |
| 2144 visit(body); | 2187 visit(body); |
| 2145 if (isAborted()) { | 2188 if (isAborted()) { |
| 2146 compiler.unimplemented( | 2189 compiler.unimplemented( |
| 2147 "SsaBuilder for labeled statement with aborting body", node: node); | 2190 "SsaBuilder for labeled statement with aborting body", node: node); |
| 2148 } | 2191 } |
| 2149 HBasicBlock exitBlock = current; | 2192 |
| 2193 HBasicBlock joinBlock = graph.addNewBlock(); |
| 2194 List<LocalsHandler> breakLocals = <LocalsHandler>[]; |
| 2150 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { | 2195 handler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) { |
| 2151 HBasicBlock joinBlock = graph.addNewBlock(); | |
| 2152 breakInstruction.block.addSuccessor(joinBlock); | 2196 breakInstruction.block.addSuccessor(joinBlock); |
| 2153 if (!isAborted()) { | 2197 breakLocals.add(locals); |
| 2154 goto(current, joinBlock); | |
| 2155 open(joinBlock); | |
| 2156 localsHandler.mergeWith(locals, joinBlock); | |
| 2157 } else { | |
| 2158 open(joinBlock); | |
| 2159 localsHandler = locals; | |
| 2160 } | |
| 2161 }); | 2198 }); |
| 2162 if (current !== exitBlock) { | 2199 bool hasBreak = breakLocals.length > 0; |
| 2200 if (!isAborted()) { |
| 2201 goto(current, joinBlock); |
| 2202 breakLocals.add(localsHandler); |
| 2203 } |
| 2204 localsHandler = beforeLocals.mergeMultiple(breakLocals, joinBlock); |
| 2205 |
| 2206 if (hasBreak) { |
| 2163 // There was at least one reachable break, so the label is needed. | 2207 // There was at least one reachable break, so the label is needed. |
| 2164 HLabeledBlockInformation blockInfo = | 2208 HLabeledBlockInformation blockInfo = |
| 2165 new HLabeledBlockInformation(entryBlock, current, | 2209 new HLabeledBlockInformation(entryBlock, current, |
| 2166 handler.labels()); | 2210 handler.labels()); |
| 2167 handler.close(); | 2211 handler.close(); |
| 2168 entryBlock.labeledBlockInformation = blockInfo; | |
| 2169 // Mark both entry and exit with the information. You can | 2212 // Mark both entry and exit with the information. You can |
| 2170 // tell which one is which by comparing with blockInfo.start/end. | 2213 // tell which one is which by comparing with blockInfo.start/end. |
| 2171 // It doesn't matter which merge block we use, they won't be generating | 2214 // It doesn't matter which merge block we use, they won't be generating |
| 2172 // any code, so put the end-marker on the last join block. | 2215 // any code, so put the end-marker on the last join block. |
| 2216 entryBlock.labeledBlockInformation = blockInfo; |
| 2173 current.labeledBlockInformation = blockInfo; | 2217 current.labeledBlockInformation = blockInfo; |
| 2174 } | 2218 } |
| 2175 } | 2219 } |
| 2176 | 2220 |
| 2177 visitLiteralMap(LiteralMap node) { | 2221 visitLiteralMap(LiteralMap node) { |
| 2178 compiler.unimplemented('SsaBuilder.visitLiteralMap', node: node); | 2222 compiler.unimplemented('SsaBuilder.visitLiteralMap', node: node); |
| 2179 } | 2223 } |
| 2180 | 2224 |
| 2181 visitLiteralMapEntry(LiteralMapEntry node) { | 2225 visitLiteralMapEntry(LiteralMapEntry node) { |
| 2182 compiler.unimplemented('SsaBuilder.visitLiteralMapEntry', node: node); | 2226 compiler.unimplemented('SsaBuilder.visitLiteralMapEntry', node: node); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2291 } | 2335 } |
| 2292 | 2336 |
| 2293 visitCatchBlock(CatchBlock node) { | 2337 visitCatchBlock(CatchBlock node) { |
| 2294 visit(node.block); | 2338 visit(node.block); |
| 2295 } | 2339 } |
| 2296 | 2340 |
| 2297 visitTypedef(Typedef node) { | 2341 visitTypedef(Typedef node) { |
| 2298 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); | 2342 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); |
| 2299 } | 2343 } |
| 2300 } | 2344 } |
| OLD | NEW |