| 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 | 6 |
| 7 final JavaScriptBackend backend; | 7 final JavaScriptBackend backend; |
| 8 | 8 |
| 9 SsaCodeGeneratorTask(JavaScriptBackend backend) | 9 SsaCodeGeneratorTask(JavaScriptBackend backend) |
| 10 : this.backend = backend, | 10 : this.backend = backend, |
| (...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 } | 312 } |
| 313 } | 313 } |
| 314 return hasNonBitOpUser(instruction, new Set<HPhi>()); | 314 return hasNonBitOpUser(instruction, new Set<HPhi>()); |
| 315 } | 315 } |
| 316 | 316 |
| 317 /** | 317 /** |
| 318 * If the [instruction] is not `null` it will be used to attach the position | 318 * If the [instruction] is not `null` it will be used to attach the position |
| 319 * to the [statement]. | 319 * to the [statement]. |
| 320 */ | 320 */ |
| 321 void pushStatement(js.Statement statement, [HInstruction instruction]) { | 321 void pushStatement(js.Statement statement, [HInstruction instruction]) { |
| 322 assert(expressionStack.isEmpty()); | 322 assert(expressionStack.isEmpty); |
| 323 if (instruction != null) { | 323 if (instruction != null) { |
| 324 attachLocation(statement, instruction); | 324 attachLocation(statement, instruction); |
| 325 } | 325 } |
| 326 currentContainer.statements.add(statement); | 326 currentContainer.statements.add(statement); |
| 327 } | 327 } |
| 328 | 328 |
| 329 /** | 329 /** |
| 330 * If the [instruction] is not `null` it will be used to attach the position | 330 * If the [instruction] is not `null` it will be used to attach the position |
| 331 * to the [expression]. | 331 * to the [expression]. |
| 332 */ | 332 */ |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 variableNames = allocator.names; | 398 variableNames = allocator.names; |
| 399 } | 399 } |
| 400 | 400 |
| 401 visitGraph(HGraph graph) { | 401 visitGraph(HGraph graph) { |
| 402 preGenerateMethod(graph); | 402 preGenerateMethod(graph); |
| 403 currentGraph = graph; | 403 currentGraph = graph; |
| 404 indent++; // We are already inside a function. | 404 indent++; // We are already inside a function. |
| 405 subGraph = new SubGraph(graph.entry, graph.exit); | 405 subGraph = new SubGraph(graph.entry, graph.exit); |
| 406 HBasicBlock start = beginGraph(graph); | 406 HBasicBlock start = beginGraph(graph); |
| 407 visitBasicBlock(start); | 407 visitBasicBlock(start); |
| 408 if (!delayedVariableDeclarations.isEmpty()) { | 408 if (!delayedVariableDeclarations.isEmpty) { |
| 409 List<js.VariableInitialization> declarations = | 409 List<js.VariableInitialization> declarations = |
| 410 <js.VariableInitialization>[]; | 410 <js.VariableInitialization>[]; |
| 411 delayedVariableDeclarations.forEach((String name) { | 411 delayedVariableDeclarations.forEach((String name) { |
| 412 declarations.add(new js.VariableInitialization( | 412 declarations.add(new js.VariableInitialization( |
| 413 new js.VariableDeclaration(name), null)); | 413 new js.VariableDeclaration(name), null)); |
| 414 }); | 414 }); |
| 415 pushExpressionAsStatement(new js.VariableDeclarationList(declarations)); | 415 pushExpressionAsStatement(new js.VariableDeclarationList(declarations)); |
| 416 } | 416 } |
| 417 endGraph(graph); | 417 endGraph(graph); |
| 418 } | 418 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 do { | 453 do { |
| 454 HInstruction current = basicBlock.first; | 454 HInstruction current = basicBlock.first; |
| 455 while (current != basicBlock.last) { | 455 while (current != basicBlock.last) { |
| 456 // E.g, type guards. | 456 // E.g, type guards. |
| 457 if (current.isControlFlow()) { | 457 if (current.isControlFlow()) { |
| 458 return TYPE_STATEMENT; | 458 return TYPE_STATEMENT; |
| 459 } | 459 } |
| 460 // HFieldSet generates code on the form x.y = ..., which isn't | 460 // HFieldSet generates code on the form x.y = ..., which isn't |
| 461 // valid in a declaration, but it also always have no uses, so | 461 // valid in a declaration, but it also always have no uses, so |
| 462 // it's caught by that test too. | 462 // it's caught by that test too. |
| 463 assert(current is! HFieldSet || current.usedBy.isEmpty()); | 463 assert(current is! HFieldSet || current.usedBy.isEmpty); |
| 464 if (current.usedBy.isEmpty()) { | 464 if (current.usedBy.isEmpty) { |
| 465 result = TYPE_EXPRESSION; | 465 result = TYPE_EXPRESSION; |
| 466 } | 466 } |
| 467 current = current.next; | 467 current = current.next; |
| 468 } | 468 } |
| 469 if (current is HGoto) { | 469 if (current is HGoto) { |
| 470 basicBlock = basicBlock.successors[0]; | 470 basicBlock = basicBlock.successors[0]; |
| 471 } else if (current is HConditionalBranch) { | 471 } else if (current is HConditionalBranch) { |
| 472 if (generateAtUseSite.contains(current)) { | 472 if (generateAtUseSite.contains(current)) { |
| 473 // Short-circuit control flow operator trickery. | 473 // Short-circuit control flow operator trickery. |
| 474 // Check the second half, which will continue into the join. | 474 // Check the second half, which will continue into the join. |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 552 | 552 |
| 553 bool oldIsGeneratingExpression = isGeneratingExpression; | 553 bool oldIsGeneratingExpression = isGeneratingExpression; |
| 554 isGeneratingExpression = true; | 554 isGeneratingExpression = true; |
| 555 List<js.Expression> oldExpressionStack = expressionStack; | 555 List<js.Expression> oldExpressionStack = expressionStack; |
| 556 List<js.Expression> sequenceElements = <js.Expression>[]; | 556 List<js.Expression> sequenceElements = <js.Expression>[]; |
| 557 expressionStack = sequenceElements; | 557 expressionStack = sequenceElements; |
| 558 HSubExpressionBlockInformation expressionSubGraph = expression; | 558 HSubExpressionBlockInformation expressionSubGraph = expression; |
| 559 visitSubGraph(expressionSubGraph.subExpression); | 559 visitSubGraph(expressionSubGraph.subExpression); |
| 560 expressionStack = oldExpressionStack; | 560 expressionStack = oldExpressionStack; |
| 561 isGeneratingExpression = oldIsGeneratingExpression; | 561 isGeneratingExpression = oldIsGeneratingExpression; |
| 562 if (sequenceElements.isEmpty()) { | 562 if (sequenceElements.isEmpty) { |
| 563 // Happens when the initializer, condition or update of a loop is empty. | 563 // Happens when the initializer, condition or update of a loop is empty. |
| 564 return null; | 564 return null; |
| 565 } else if (sequenceElements.length == 1) { | 565 } else if (sequenceElements.length == 1) { |
| 566 return sequenceElements[0]; | 566 return sequenceElements[0]; |
| 567 } else { | 567 } else { |
| 568 return new js.Sequence(sequenceElements); | 568 return new js.Sequence(sequenceElements); |
| 569 } | 569 } |
| 570 } | 570 } |
| 571 | 571 |
| 572 /** | 572 /** |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 680 visitExpression(HInstruction node) { | 680 visitExpression(HInstruction node) { |
| 681 bool oldIsGeneratingExpression = isGeneratingExpression; | 681 bool oldIsGeneratingExpression = isGeneratingExpression; |
| 682 isGeneratingExpression = true; | 682 isGeneratingExpression = true; |
| 683 visit(node); | 683 visit(node); |
| 684 isGeneratingExpression = oldIsGeneratingExpression; | 684 isGeneratingExpression = oldIsGeneratingExpression; |
| 685 } | 685 } |
| 686 | 686 |
| 687 visitStatement(HInstruction node) { | 687 visitStatement(HInstruction node) { |
| 688 assert(!isGeneratingExpression); | 688 assert(!isGeneratingExpression); |
| 689 visit(node); | 689 visit(node); |
| 690 if (!expressionStack.isEmpty()) { | 690 if (!expressionStack.isEmpty) { |
| 691 assert(expressionStack.length == 1); | 691 assert(expressionStack.length == 1); |
| 692 pushExpressionAsStatement(pop()); | 692 pushExpressionAsStatement(pop()); |
| 693 } | 693 } |
| 694 } | 694 } |
| 695 | 695 |
| 696 void continueAsBreak(LabelElement target) { | 696 void continueAsBreak(LabelElement target) { |
| 697 pushStatement(new js.Break(backend.namer.continueLabelName(target))); | 697 pushStatement(new js.Break(backend.namer.continueLabelName(target))); |
| 698 } | 698 } |
| 699 | 699 |
| 700 void implicitContinueAsBreak(TargetElement target) { | 700 void implicitContinueAsBreak(TargetElement target) { |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 998 breakAction[target] = implicitBreakWithLabel; | 998 breakAction[target] = implicitBreakWithLabel; |
| 999 } | 999 } |
| 1000 } | 1000 } |
| 1001 | 1001 |
| 1002 currentContainer = body; | 1002 currentContainer = body; |
| 1003 startLabeledBlock(labeledBlockInfo); | 1003 startLabeledBlock(labeledBlockInfo); |
| 1004 generateStatements(labeledBlockInfo.body); | 1004 generateStatements(labeledBlockInfo.body); |
| 1005 endLabeledBlock(labeledBlockInfo); | 1005 endLabeledBlock(labeledBlockInfo); |
| 1006 | 1006 |
| 1007 if (labeledBlockInfo.isContinue) { | 1007 if (labeledBlockInfo.isContinue) { |
| 1008 while (!continueOverrides.isEmpty()) { | 1008 while (!continueOverrides.isEmpty) { |
| 1009 continueAction.remove(continueOverrides.head); | 1009 continueAction.remove(continueOverrides.head); |
| 1010 continueOverrides = continueOverrides.tail; | 1010 continueOverrides = continueOverrides.tail; |
| 1011 } | 1011 } |
| 1012 } else { | 1012 } else { |
| 1013 breakAction.remove(labeledBlockInfo.target); | 1013 breakAction.remove(labeledBlockInfo.target); |
| 1014 } | 1014 } |
| 1015 | 1015 |
| 1016 currentContainer = oldContainer; | 1016 currentContainer = oldContainer; |
| 1017 pushStatement(result); | 1017 pushStatement(result); |
| 1018 return true; | 1018 return true; |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1139 } | 1139 } |
| 1140 | 1140 |
| 1141 // For each copy, if the destination does not have a current | 1141 // For each copy, if the destination does not have a current |
| 1142 // location, then we can safely assign to it. | 1142 // location, then we can safely assign to it. |
| 1143 for (Copy copy in copies) { | 1143 for (Copy copy in copies) { |
| 1144 if (currentLocation[copy.destination] == null) { | 1144 if (currentLocation[copy.destination] == null) { |
| 1145 ready.add(copy.destination); | 1145 ready.add(copy.destination); |
| 1146 } | 1146 } |
| 1147 } | 1147 } |
| 1148 | 1148 |
| 1149 while (!worklist.isEmpty()) { | 1149 while (!worklist.isEmpty) { |
| 1150 while (!ready.isEmpty()) { | 1150 while (!ready.isEmpty) { |
| 1151 String destination = ready.removeLast(); | 1151 String destination = ready.removeLast(); |
| 1152 String source = initialValue[destination]; | 1152 String source = initialValue[destination]; |
| 1153 // Since [source] might have been updated, use the current | 1153 // Since [source] might have been updated, use the current |
| 1154 // location of [source] | 1154 // location of [source] |
| 1155 String copy = currentLocation[source]; | 1155 String copy = currentLocation[source]; |
| 1156 emitAssignment(destination, copy); | 1156 emitAssignment(destination, copy); |
| 1157 // Now [destination] is the current location of [source]. | 1157 // Now [destination] is the current location of [source]. |
| 1158 currentLocation[source] = destination; | 1158 currentLocation[source] = destination; |
| 1159 // If [source] hasn't been updated and needs to have a value, | 1159 // If [source] hasn't been updated and needs to have a value, |
| 1160 // add it to the list of variables that can be updated. Copies | 1160 // add it to the list of variables that can be updated. Copies |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1316 } | 1316 } |
| 1317 | 1317 |
| 1318 visitGoto(HGoto node) { | 1318 visitGoto(HGoto node) { |
| 1319 assert(currentBlock.successors.length == 1); | 1319 assert(currentBlock.successors.length == 1); |
| 1320 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; | 1320 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; |
| 1321 // With the exception of the entry-node which dominates its successor | 1321 // With the exception of the entry-node which dominates its successor |
| 1322 // and the exit node, no block finishing with a 'goto' can have more than | 1322 // and the exit node, no block finishing with a 'goto' can have more than |
| 1323 // one dominated block (since it has only one successor). | 1323 // one dominated block (since it has only one successor). |
| 1324 // If the successor is dominated by another block, then the other block | 1324 // If the successor is dominated by another block, then the other block |
| 1325 // is responsible for visiting the successor. | 1325 // is responsible for visiting the successor. |
| 1326 if (dominated.isEmpty()) return; | 1326 if (dominated.isEmpty) return; |
| 1327 if (dominated.length > 2) { | 1327 if (dominated.length > 2) { |
| 1328 compiler.internalError('dominated.length = ${dominated.length}', | 1328 compiler.internalError('dominated.length = ${dominated.length}', |
| 1329 instruction: node); | 1329 instruction: node); |
| 1330 } | 1330 } |
| 1331 if (dominated.length == 2 && !identical(currentBlock, currentGraph.entry)) { | 1331 if (dominated.length == 2 && !identical(currentBlock, currentGraph.entry)) { |
| 1332 compiler.internalError('currentBlock !== currentGraph.entry', | 1332 compiler.internalError('currentBlock !== currentGraph.entry', |
| 1333 instruction: node); | 1333 instruction: node); |
| 1334 } | 1334 } |
| 1335 assert(dominated[0] == currentBlock.successors[0]); | 1335 assert(dominated[0] == currentBlock.successors[0]); |
| 1336 visitBasicBlock(dominated[0]); | 1336 visitBasicBlock(dominated[0]); |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1668 | 1668 |
| 1669 visitLocalSet(HLocalSet node) { | 1669 visitLocalSet(HLocalSet node) { |
| 1670 use(node.value); | 1670 use(node.value); |
| 1671 assignVariable(variableNames.getName(node.receiver), pop()); | 1671 assignVariable(variableNames.getName(node.receiver), pop()); |
| 1672 } | 1672 } |
| 1673 | 1673 |
| 1674 visitForeign(HForeign node) { | 1674 visitForeign(HForeign node) { |
| 1675 String code = node.code.slowToString(); | 1675 String code = node.code.slowToString(); |
| 1676 List<HInstruction> inputs = node.inputs; | 1676 List<HInstruction> inputs = node.inputs; |
| 1677 if (node.isJsStatement(types)) { | 1677 if (node.isJsStatement(types)) { |
| 1678 if (!inputs.isEmpty()) { | 1678 if (!inputs.isEmpty) { |
| 1679 compiler.internalError("foreign statement with inputs: $code", | 1679 compiler.internalError("foreign statement with inputs: $code", |
| 1680 instruction: node); | 1680 instruction: node); |
| 1681 } | 1681 } |
| 1682 pushStatement(new js.LiteralStatement(code), node); | 1682 pushStatement(new js.LiteralStatement(code), node); |
| 1683 } else { | 1683 } else { |
| 1684 List<js.Expression> data = <js.Expression>[]; | 1684 List<js.Expression> data = <js.Expression>[]; |
| 1685 for (int i = 0; i < inputs.length; i++) { | 1685 for (int i = 0; i < inputs.length; i++) { |
| 1686 use(inputs[i]); | 1686 use(inputs[i]); |
| 1687 data.add(pop()); | 1687 data.add(pop()); |
| 1688 } | 1688 } |
| (...skipping 1301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2990 if (leftType.canBeNull() && rightType.canBeNull()) { | 2990 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 2991 if (left.isConstantNull() || right.isConstantNull() || | 2991 if (left.isConstantNull() || right.isConstantNull() || |
| 2992 (leftType.isPrimitive() && leftType == rightType)) { | 2992 (leftType.isPrimitive() && leftType == rightType)) { |
| 2993 return '=='; | 2993 return '=='; |
| 2994 } | 2994 } |
| 2995 return null; | 2995 return null; |
| 2996 } else { | 2996 } else { |
| 2997 return '==='; | 2997 return '==='; |
| 2998 } | 2998 } |
| 2999 } | 2999 } |
| OLD | NEW |