| 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 | |
| 432 // one dominated block (since it has only one successor). | |
| 433 // If the successor is dominated by another block, then the other block | |
| 434 // is responsible for visiting the successor. | |
| 435 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; | |
| 436 assert(dominated.isEmpty()); | |
| 437 // Otherwise we would have bailed out in the builder. | |
| 438 addIndentation(); | 440 addIndentation(); |
| 439 buffer.add("break"); | 441 buffer.add("break"); |
| 440 if (node.label !== null) { | 442 if (node.label !== null) { |
| 441 buffer.add(" "); | 443 buffer.add(" "); |
| 442 addLabel(node.label); | 444 addLabel(node.label); |
| 445 } else { |
| 446 StatementElement target = node.target; |
| 447 String implicitLabel = target.implicitLabel(); |
| 448 if (implicitLabel !== null) { |
| 449 buffer.add(@' $'); |
| 450 buffer.add(implicitLabel); |
| 451 } |
| 443 } | 452 } |
| 444 buffer.add(";\n"); | 453 buffer.add(";\n"); |
| 454 // We never follow the break to its target, even if it dominates the |
| 455 // break target block. That block is always handled by the structure |
| 456 // that introduced the break. |
| 445 } | 457 } |
| 446 | 458 |
| 447 visitTry(HTry node) { | 459 visitTry(HTry node) { |
| 448 addIndentation(); | 460 addIndentation(); |
| 449 buffer.add('try {\n'); | 461 buffer.add('try {\n'); |
| 450 indent++; | 462 indent++; |
| 451 List<HBasicBlock> successors = node.block.successors; | 463 List<HBasicBlock> successors = node.block.successors; |
| 452 visitBasicBlock(successors[0]); | 464 visitBasicBlock(successors[0]); |
| 453 indent--; | 465 indent--; |
| 454 | 466 |
| (...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 checkArray(input, '!=='); | 1167 checkArray(input, '!=='); |
| 1156 buffer.add(')) '); | 1168 buffer.add(')) '); |
| 1157 bailout(node, 'Not a string or array'); | 1169 bailout(node, 'Not a string or array'); |
| 1158 } else { | 1170 } else { |
| 1159 unreachable(); | 1171 unreachable(); |
| 1160 } | 1172 } |
| 1161 } | 1173 } |
| 1162 | 1174 |
| 1163 void beginLoop(HBasicBlock block) { | 1175 void beginLoop(HBasicBlock block) { |
| 1164 addIndentation(); | 1176 addIndentation(); |
| 1165 for (SourceString label in block.loopInformation.labels) { | 1177 for (LabelElement label in block.loopInformation.labels) { |
| 1166 buffer.add("${label.slowToString()}:"); | 1178 addLabel(label); |
| 1179 buffer.add(":"); |
| 1167 } | 1180 } |
| 1168 buffer.add('while (true) {\n'); | 1181 buffer.add('while (true) {\n'); |
| 1169 indent++; | 1182 indent++; |
| 1170 } | 1183 } |
| 1171 | 1184 |
| 1172 void endLoop(HBasicBlock block) { | 1185 void endLoop(HBasicBlock block) { |
| 1173 indent--; | 1186 indent--; |
| 1174 addIndentation(); | 1187 addIndentation(); |
| 1175 buffer.add('}\n'); // Close 'while' loop. | 1188 buffer.add('}\n'); // Close 'while' loop. |
| 1176 } | 1189 } |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1322 void endBailoutSwitch() { | 1335 void endBailoutSwitch() { |
| 1323 indent--; // Close 'case'. | 1336 indent--; // Close 'case'. |
| 1324 indent--; | 1337 indent--; |
| 1325 addIndentation(); | 1338 addIndentation(); |
| 1326 buffer.add('}\n'); // Close 'switch'. | 1339 buffer.add('}\n'); // Close 'switch'. |
| 1327 } | 1340 } |
| 1328 | 1341 |
| 1329 // Adds a "$" in front of names of labels from the original source. | 1342 // Adds a "$" in front of names of labels from the original source. |
| 1330 // This avoids conflicts with labels introduced by bailouts, which | 1343 // This avoids conflicts with labels introduced by bailouts, which |
| 1331 // starts with a non-"$" character. | 1344 // starts with a non-"$" character. |
| 1332 void addLabel(SourceString label) { | 1345 void addLabel(LabelElement label) { |
| 1333 buffer.add("\$$label"); | 1346 buffer.add("\$${label.labelName}"); |
| 1334 } | 1347 } |
| 1335 | 1348 |
| 1336 void beginLoop(HBasicBlock block) { | 1349 void beginLoop(HBasicBlock block) { |
| 1337 // TODO(ngeoffray): Don't put labels on loops that don't bailout. | 1350 // TODO(ngeoffray): Don't put labels on loops that don't bailout. |
| 1338 String newLabel = pushLabel(); | 1351 String newLabel = pushLabel(); |
| 1339 if (block.hasBailouts()) { | 1352 if (block.hasBailouts()) { |
| 1340 startBailoutCase(block.bailouts, const <HBailoutTarget>[]); | 1353 startBailoutCase(block.bailouts, const <HBailoutTarget>[]); |
| 1341 } | 1354 } |
| 1342 | 1355 |
| 1343 addIndentation(); | 1356 addIndentation(); |
| 1344 for (SourceString label in block.loopInformation.labels) { | 1357 for (LabelElement label in block.loopInformation.labels) { |
| 1345 addLabel(label); | 1358 addLabel(label); |
| 1346 buffer.add(":"); | 1359 buffer.add(":"); |
| 1347 } | 1360 } |
| 1348 buffer.add('$newLabel: while (true) {\n'); | 1361 buffer.add('$newLabel: while (true) {\n'); |
| 1349 indent++; | 1362 indent++; |
| 1350 | 1363 |
| 1351 if (block.hasBailouts()) { | 1364 if (block.hasBailouts()) { |
| 1352 startBailoutSwitch(); | 1365 startBailoutSwitch(); |
| 1353 } | 1366 } |
| 1354 } | 1367 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1427 startBailoutSwitch(); | 1440 startBailoutSwitch(); |
| 1428 } | 1441 } |
| 1429 } | 1442 } |
| 1430 | 1443 |
| 1431 void endElse(HIf node) { | 1444 void endElse(HIf node) { |
| 1432 if (node.elseBlock.hasBailouts()) { | 1445 if (node.elseBlock.hasBailouts()) { |
| 1433 endBailoutSwitch(); | 1446 endBailoutSwitch(); |
| 1434 } | 1447 } |
| 1435 } | 1448 } |
| 1436 } | 1449 } |
| OLD | NEW |