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 |