| 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 SsaCodeGeneratorTask extends CompilerTask { | 5 class SsaCodeGeneratorTask extends CompilerTask { |
| 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); | 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); |
| 7 String get name() => 'SSA code generator'; | 7 String get name() => 'SSA code generator'; |
| 8 | 8 |
| 9 String generate(WorkItem work, HGraph graph) { | 9 String generate(WorkItem work, HGraph graph) { |
| 10 return measure(() { | 10 return measure(() { |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 /** | 208 /** |
| 209 * Only visits the arguments starting at inputs[HInvoke.ARGUMENTS_OFFSET]. | 209 * Only visits the arguments starting at inputs[HInvoke.ARGUMENTS_OFFSET]. |
| 210 */ | 210 */ |
| 211 void visitArguments(List<HInstruction> inputs) { | 211 void visitArguments(List<HInstruction> inputs) { |
| 212 assert(inputs.length >= HInvoke.ARGUMENTS_OFFSET); | 212 assert(inputs.length >= HInvoke.ARGUMENTS_OFFSET); |
| 213 buffer.add('('); | 213 buffer.add('('); |
| 214 for (int i = HInvoke.ARGUMENTS_OFFSET; i < inputs.length; i++) { | 214 for (int i = HInvoke.ARGUMENTS_OFFSET; i < inputs.length; i++) { |
| 215 if (i != HInvoke.ARGUMENTS_OFFSET) buffer.add(', '); | 215 if (i != HInvoke.ARGUMENTS_OFFSET) buffer.add(', '); |
| 216 use(inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); | 216 use(inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| 217 } | 217 } |
| 218 buffer.add(")"); | 218 buffer.add(')'); |
| 219 } | 219 } |
| 220 | 220 |
| 221 void define(HInstruction instruction) { | 221 void define(HInstruction instruction) { |
| 222 buffer.add('var ${temporary(instruction)} = '); | 222 buffer.add('var ${temporary(instruction)} = '); |
| 223 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); | 223 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| 224 } | 224 } |
| 225 | 225 |
| 226 void use(HInstruction argument, int expectedPrecedence) { | 226 void use(HInstruction argument, int expectedPrecedence) { |
| 227 if (argument.generateAtUseSite()) { | 227 if (argument.generateAtUseSite()) { |
| 228 visit(argument, expectedPrecedence); | 228 visit(argument, expectedPrecedence); |
| 229 } else { | 229 } else { |
| 230 buffer.add(temporary(argument)); | 230 buffer.add(temporary(argument)); |
| 231 } | 231 } |
| 232 } | 232 } |
| 233 | 233 |
| 234 visit(HInstruction node, int expectedPrecedence) { | 234 visit(HInstruction node, int expectedPrecedence) { |
| 235 int oldPrecedence = this.expectedPrecedence; | 235 int oldPrecedence = this.expectedPrecedence; |
| 236 this.expectedPrecedence = expectedPrecedence; | 236 this.expectedPrecedence = expectedPrecedence; |
| 237 node.accept(this); | 237 node.accept(this); |
| 238 this.expectedPrecedence = oldPrecedence; | 238 this.expectedPrecedence = oldPrecedence; |
| 239 } | 239 } |
| 240 | 240 |
| 241 void handleLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 241 void handleLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 242 addIndentation(); | 242 addIndentation(); |
| 243 for (SourceString label in labeledBlockInfo.labels) { | 243 for (LabelElement label in labeledBlockInfo.labels) { |
| 244 addLabel(label); | 244 addLabel(label); |
| 245 buffer.add(":"); | 245 buffer.add(':'); |
| 246 } | 246 } |
| 247 buffer.add("{\n"); | 247 String implicitLabel = labeledBlockInfo.target.implicitLabel(); |
| 248 if (implicitLabel !== null) { |
| 249 buffer.add(@'$'); |
| 250 buffer.add(implicitLabel); |
| 251 buffer.add(@':'); |
| 252 } |
| 253 buffer.add('{\n'); |
| 248 indent++; | 254 indent++; |
| 249 | 255 |
| 250 visitSubGraph(labeledBlockInfo.body); | 256 visitSubGraph(labeledBlockInfo.body); |
| 251 | 257 |
| 252 indent--; | 258 indent--; |
| 253 addIndentation(); | 259 addIndentation(); |
| 254 buffer.add("}\n"); | 260 buffer.add('}\n'); |
| 255 | 261 |
| 256 visitBasicBlock(labeledBlockInfo.joinBlock); | 262 if (labeledBlockInfo.joinBlock !== null) { |
| 263 visitBasicBlock(labeledBlockInfo.joinBlock); |
| 264 } |
| 257 } | 265 } |
| 258 | 266 |
| 259 | 267 |
| 260 visitBasicBlock(HBasicBlock node) { | 268 visitBasicBlock(HBasicBlock node) { |
| 261 // Abort traversal if we are leaving the currently active sub-graph. | 269 // Abort traversal if we are leaving the currently active sub-graph. |
| 262 if (!subGraph.contains(node)) return; | 270 if (!subGraph.contains(node)) return; |
| 263 | 271 |
| 264 // If this node has special behavior attached, handle it. | 272 // If this node has special behavior attached, handle it. |
| 265 // If we reach here again while handling the attached information, | 273 // If we reach here again while handling the attached information, |
| 266 // e.g., because we call visitSubGraph on a subgraph starting here, | 274 // e.g., because we call visitSubGraph on a subgraph starting here, |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 if (dominated.length == 2 && currentBlock !== currentGraph.entry) { | 423 if (dominated.length == 2 && currentBlock !== currentGraph.entry) { |
| 416 unreachable(); | 424 unreachable(); |
| 417 } | 425 } |
| 418 assert(dominated[0] == currentBlock.successors[0]); | 426 assert(dominated[0] == currentBlock.successors[0]); |
| 419 visitBasicBlock(dominated[0]); | 427 visitBasicBlock(dominated[0]); |
| 420 } | 428 } |
| 421 | 429 |
| 422 // Used to write the name of labels. | 430 // Used to write the name of labels. |
| 423 // The default implementation uses the unmodified Dart label name. | 431 // The default implementation uses the unmodified Dart label name. |
| 424 // Specializations might change this. | 432 // Specializations might change this. |
| 425 void addLabel(SourceString label) { | 433 void addLabel(LabelElement label) { |
| 426 buffer.add(label.slowToString()); | 434 buffer.add(@'$'); |
| 435 buffer.add(label.labelName); |
| 427 } | 436 } |
| 428 | 437 |
| 429 visitBreak(HBreak node) { | 438 visitBreak(HBreak node) { |
| 430 assert(currentBlock.successors.length == 1); | 439 assert(currentBlock.successors.length == 1); |
| 431 // No block finishing with a 'break' can have more than | 440 // No block finishing with a 'break' can have more than |
| 432 // one dominated block (since it has only one successor). | 441 // one dominated block (since it has only one successor). |
| 433 // If the successor is dominated by another block, then the other block | 442 // If the successor is dominated by another block, then the other block |
| 434 // is responsible for visiting the successor. | 443 // is responsible for visiting the successor. |
| 435 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; | 444 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; |
| 436 assert(dominated.isEmpty()); | 445 assert(dominated.isEmpty()); |
| 437 // Otherwise we would have bailed out in the builder. | 446 // Otherwise we would have bailed out in the builder. |
| 438 addIndentation(); | 447 addIndentation(); |
| 439 buffer.add("break"); | 448 buffer.add("break"); |
| 440 if (node.label !== null) { | 449 if (node.target is LabelElement) { |
| 450 LabelElement target = node.target; |
| 441 buffer.add(" "); | 451 buffer.add(" "); |
| 442 addLabel(node.label); | 452 addLabel(target); |
| 453 } else { |
| 454 StatementElement target = node.target; |
| 455 String implicitLabel = target.implicitLabel(); |
| 456 if (implicitLabel !== null) { |
| 457 buffer.add(@' $'); |
| 458 buffer.add(implicitLabel); |
| 459 } |
| 443 } | 460 } |
| 444 buffer.add(";\n"); | 461 buffer.add(";\n"); |
| 445 } | 462 } |
| 446 | 463 |
| 447 visitTry(HTry node) { | 464 visitTry(HTry node) { |
| 448 addIndentation(); | 465 addIndentation(); |
| 449 buffer.add('try {\n'); | 466 buffer.add('try {\n'); |
| 450 indent++; | 467 indent++; |
| 451 List<HBasicBlock> successors = node.block.successors; | 468 List<HBasicBlock> successors = node.block.successors; |
| 452 visitBasicBlock(successors[0]); | 469 visitBasicBlock(successors[0]); |
| (...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1131 checkArray(input, '!=='); | 1148 checkArray(input, '!=='); |
| 1132 buffer.add(')) '); | 1149 buffer.add(')) '); |
| 1133 bailout(node, 'Not a string or array'); | 1150 bailout(node, 'Not a string or array'); |
| 1134 } else { | 1151 } else { |
| 1135 unreachable(); | 1152 unreachable(); |
| 1136 } | 1153 } |
| 1137 } | 1154 } |
| 1138 | 1155 |
| 1139 void beginLoop(HBasicBlock block) { | 1156 void beginLoop(HBasicBlock block) { |
| 1140 addIndentation(); | 1157 addIndentation(); |
| 1141 for (SourceString label in block.loopInformation.labels) { | 1158 for (LabelElement label in block.loopInformation.labels) { |
| 1142 buffer.add("${label.slowToString()}:"); | 1159 addLabel(label); |
| 1160 buffer.add(":"); |
| 1143 } | 1161 } |
| 1144 buffer.add('while (true) {\n'); | 1162 buffer.add('while (true) {\n'); |
| 1145 indent++; | 1163 indent++; |
| 1146 } | 1164 } |
| 1147 | 1165 |
| 1148 void endLoop(HBasicBlock block) { | 1166 void endLoop(HBasicBlock block) { |
| 1149 indent--; | 1167 indent--; |
| 1150 addIndentation(); | 1168 addIndentation(); |
| 1151 buffer.add('}\n'); // Close 'while' loop. | 1169 buffer.add('}\n'); // Close 'while' loop. |
| 1152 } | 1170 } |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1298 void endBailoutSwitch() { | 1316 void endBailoutSwitch() { |
| 1299 indent--; // Close 'case'. | 1317 indent--; // Close 'case'. |
| 1300 indent--; | 1318 indent--; |
| 1301 addIndentation(); | 1319 addIndentation(); |
| 1302 buffer.add('}\n'); // Close 'switch'. | 1320 buffer.add('}\n'); // Close 'switch'. |
| 1303 } | 1321 } |
| 1304 | 1322 |
| 1305 // Adds a "$" in front of names of labels from the original source. | 1323 // Adds a "$" in front of names of labels from the original source. |
| 1306 // This avoids conflicts with labels introduced by bailouts, which | 1324 // This avoids conflicts with labels introduced by bailouts, which |
| 1307 // starts with a non-"$" character. | 1325 // starts with a non-"$" character. |
| 1308 void addLabel(SourceString label) { | 1326 void addLabel(LabelElement label) { |
| 1309 buffer.add("\$$label"); | 1327 buffer.add("\$${label.labelName}"); |
| 1310 } | 1328 } |
| 1311 | 1329 |
| 1312 void beginLoop(HBasicBlock block) { | 1330 void beginLoop(HBasicBlock block) { |
| 1313 // TODO(ngeoffray): Don't put labels on loops that don't bailout. | 1331 // TODO(ngeoffray): Don't put labels on loops that don't bailout. |
| 1314 String newLabel = pushLabel(); | 1332 String newLabel = pushLabel(); |
| 1315 if (block.hasBailouts()) { | 1333 if (block.hasBailouts()) { |
| 1316 startBailoutCase(block.bailouts, const <HBailoutTarget>[]); | 1334 startBailoutCase(block.bailouts, const <HBailoutTarget>[]); |
| 1317 } | 1335 } |
| 1318 | 1336 |
| 1319 addIndentation(); | 1337 addIndentation(); |
| 1320 for (SourceString label in block.loopInformation.labels) { | 1338 for (LabelElement label in block.loopInformation.labels) { |
| 1321 addLabel(label); | 1339 addLabel(label); |
| 1322 buffer.add(":"); | 1340 buffer.add(":"); |
| 1323 } | 1341 } |
| 1324 buffer.add('$newLabel: while (true) {\n'); | 1342 buffer.add('$newLabel: while (true) {\n'); |
| 1325 indent++; | 1343 indent++; |
| 1326 | 1344 |
| 1327 if (block.hasBailouts()) { | 1345 if (block.hasBailouts()) { |
| 1328 startBailoutSwitch(); | 1346 startBailoutSwitch(); |
| 1329 } | 1347 } |
| 1330 } | 1348 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1403 startBailoutSwitch(); | 1421 startBailoutSwitch(); |
| 1404 } | 1422 } |
| 1405 } | 1423 } |
| 1406 | 1424 |
| 1407 void endElse(HIf node) { | 1425 void endElse(HIf node) { |
| 1408 if (node.elseBlock.hasBailouts()) { | 1426 if (node.elseBlock.hasBailouts()) { |
| 1409 endBailoutSwitch(); | 1427 endBailoutSwitch(); |
| 1410 } | 1428 } |
| 1411 } | 1429 } |
| 1412 } | 1430 } |
| OLD | NEW |