| 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 final JavaScriptBackend backend; | 6 final JavaScriptBackend backend; |
| 7 SsaCodeGeneratorTask(JavaScriptBackend backend) | 7 SsaCodeGeneratorTask(JavaScriptBackend backend) |
| 8 : this.backend = backend, | 8 : this.backend = backend, |
| 9 super(backend.compiler); | 9 super(backend.compiler); |
| 10 String get name() => 'SSA code generator'; | 10 String get name() => 'SSA code generator'; |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 140 static final int TYPE_STATEMENT = 0; | 140 static final int TYPE_STATEMENT = 0; |
| 141 static final int TYPE_EXPRESSION = 1; | 141 static final int TYPE_EXPRESSION = 1; |
| 142 static final int TYPE_DECLARATION = 2; | 142 static final int TYPE_DECLARATION = 2; |
| 143 | 143 |
| 144 final JavaScriptBackend backend; | 144 final JavaScriptBackend backend; |
| 145 final WorkItem work; | 145 final WorkItem work; |
| 146 final StringBuffer buffer; | 146 final StringBuffer buffer; |
| 147 final String parameters; | 147 final String parameters; |
| 148 | 148 |
| 149 final Set<HInstruction> generateAtUseSite; | 149 final Set<HInstruction> generateAtUseSite; |
| 150 final Map<HPhi, String> logicalOperations; | 150 final Set<HInstruction> logicalOperations; |
| 151 final Map<Element, ElementAction> breakAction; | 151 final Map<Element, ElementAction> breakAction; |
| 152 final Map<Element, ElementAction> continueAction; | 152 final Map<Element, ElementAction> continueAction; |
| 153 final Map<Element, String> parameterNames; | 153 final Map<Element, String> parameterNames; |
| 154 | 154 |
| 155 /** | 155 /** |
| 156 * Contains the names of the instructions, as well as the parallel | 156 * Contains the names of the instructions, as well as the parallel |
| 157 * copies to perform on block transitioning. | 157 * copies to perform on block transitioning. |
| 158 */ | 158 */ |
| 159 VariableNames variableNames; | 159 VariableNames variableNames; |
| 160 | 160 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 } | 199 } |
| 200 | 200 |
| 201 SsaCodeGenerator(this.backend, | 201 SsaCodeGenerator(this.backend, |
| 202 this.work, | 202 this.work, |
| 203 this.parameters, | 203 this.parameters, |
| 204 this.parameterNames) | 204 this.parameterNames) |
| 205 : declaredVariables = new Set<String>(), | 205 : declaredVariables = new Set<String>(), |
| 206 delayedVariablesDeclaration = new List<String>(), | 206 delayedVariablesDeclaration = new List<String>(), |
| 207 buffer = new StringBuffer(), | 207 buffer = new StringBuffer(), |
| 208 generateAtUseSite = new Set<HInstruction>(), | 208 generateAtUseSite = new Set<HInstruction>(), |
| 209 logicalOperations = new Map<HPhi, String>(), | 209 logicalOperations = new Set<HInstruction>(), |
| 210 breakAction = new Map<Element, ElementAction>(), | 210 breakAction = new Map<Element, ElementAction>(), |
| 211 continueAction = new Map<Element, ElementAction>(), | 211 continueAction = new Map<Element, ElementAction>(), |
| 212 unsignedShiftPrecedences = JSPrecedence.binary['>>>'] { | 212 unsignedShiftPrecedences = JSPrecedence.binary['>>>'] { |
| 213 | 213 |
| 214 Interceptors interceptors = backend.builder.interceptors; | 214 Interceptors interceptors = backend.builder.interceptors; |
| 215 equalsNullElement = interceptors.getEqualsNullInterceptor(); | 215 equalsNullElement = interceptors.getEqualsNullInterceptor(); |
| 216 boolifiedEqualsNullElement = | 216 boolifiedEqualsNullElement = |
| 217 interceptors.getBoolifiedVersionOf(equalsNullElement); | 217 interceptors.getBoolifiedVersionOf(equalsNullElement); |
| 218 } | 218 } |
| 219 | 219 |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 buffer.add("var "); | 480 buffer.add("var "); |
| 481 } | 481 } |
| 482 buffer.add(variableName); | 482 buffer.add(variableName); |
| 483 } | 483 } |
| 484 | 484 |
| 485 void declareInstruction(HInstruction instruction) { | 485 void declareInstruction(HInstruction instruction) { |
| 486 declareVariable(variableNames.getName(instruction)); | 486 declareVariable(variableNames.getName(instruction)); |
| 487 } | 487 } |
| 488 | 488 |
| 489 void define(HInstruction instruction) { | 489 void define(HInstruction instruction) { |
| 490 if (isGeneratingExpression()) { |
| 491 addExpressionSeparator(); |
| 492 } else { |
| 493 addIndentation(); |
| 494 } |
| 490 if (instruction is !HCheck && variableNames.hasName(instruction)) { | 495 if (instruction is !HCheck && variableNames.hasName(instruction)) { |
| 491 declareInstruction(instruction); | 496 declareInstruction(instruction); |
| 492 buffer.add(" = "); | 497 buffer.add(" = "); |
| 493 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); | 498 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| 494 } else { | 499 } else { |
| 495 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); | 500 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| 496 } | 501 } |
| 502 if (!isGeneratingExpression()) buffer.add(';\n'); |
| 497 } | 503 } |
| 498 | 504 |
| 499 void use(HInstruction argument, int expectedPrecedenceForArgument) { | 505 void use(HInstruction argument, int expectedPrecedenceForArgument) { |
| 500 if (isGenerateAtUseSite(argument)) { | 506 if (isGenerateAtUseSite(argument)) { |
| 501 visit(argument, expectedPrecedenceForArgument); | 507 visit(argument, expectedPrecedenceForArgument); |
| 502 } else if (argument is HCheck) { | 508 } else if (argument is HCheck) { |
| 503 HCheck check = argument; | 509 HCheck check = argument; |
| 504 use(argument.checkedInput, expectedPrecedenceForArgument); | 510 use(argument.checkedInput, expectedPrecedenceForArgument); |
| 505 } else { | 511 } else { |
| 506 buffer.add(variableNames.getName(argument)); | 512 buffer.add(variableNames.getName(argument)); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 526 buffer.add(";\n"); | 532 buffer.add(";\n"); |
| 527 } | 533 } |
| 528 | 534 |
| 529 void implicitBreakWithLabel(TargetElement target) { | 535 void implicitBreakWithLabel(TargetElement target) { |
| 530 addIndented("break "); | 536 addIndented("break "); |
| 531 writeImplicitLabel(target); | 537 writeImplicitLabel(target); |
| 532 buffer.add(";\n"); | 538 buffer.add(";\n"); |
| 533 } | 539 } |
| 534 | 540 |
| 535 bool visitIfInfo(HIfBlockInformation info) { | 541 bool visitIfInfo(HIfBlockInformation info) { |
| 542 // If the [HIf] instruction is actually a logical operation, we |
| 543 // let the flow-based traversal handle it. |
| 544 if (logicalOperations.contains(info.condition.end.last)) return false; |
| 536 HInstruction condition = info.condition.conditionExpression; | 545 HInstruction condition = info.condition.conditionExpression; |
| 537 if (condition.isConstant()) { | 546 if (condition.isConstant()) { |
| 538 // If the condition is constant, only generate one branch (if any). | 547 // If the condition is constant, only generate one branch (if any). |
| 539 HConstant constantCondition = condition; | 548 HConstant constantCondition = condition; |
| 540 Constant constant = constantCondition.constant; | 549 Constant constant = constantCondition.constant; |
| 541 generateStatements(info.condition); | 550 generateStatements(info.condition); |
| 542 if (constant.isTrue()) { | 551 if (constant.isTrue()) { |
| 543 generateStatements(info.thenGraph); | 552 generateStatements(info.thenGraph); |
| 544 } else if (info.elseGraph !== null) { | 553 } else if (info.elseGraph !== null) { |
| 545 generateStatements(info.elseGraph); | 554 generateStatements(info.elseGraph); |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 802 while (!continueOverrides.isEmpty()) { | 811 while (!continueOverrides.isEmpty()) { |
| 803 continueAction.remove(continueOverrides.head); | 812 continueAction.remove(continueOverrides.head); |
| 804 continueOverrides = continueOverrides.tail; | 813 continueOverrides = continueOverrides.tail; |
| 805 } | 814 } |
| 806 } else { | 815 } else { |
| 807 breakAction.remove(labeledBlockInfo.target); | 816 breakAction.remove(labeledBlockInfo.target); |
| 808 } | 817 } |
| 809 return true; | 818 return true; |
| 810 } | 819 } |
| 811 | 820 |
| 812 void emitLogicalOperation(HPhi node, String operation) { | |
| 813 JSBinaryOperatorPrecedence operatorPrecedence = | |
| 814 JSPrecedence.binary[operation]; | |
| 815 beginExpression(operatorPrecedence.precedence); | |
| 816 use(node.inputs[0], operatorPrecedence.left); | |
| 817 buffer.add(" $operation "); | |
| 818 use(node.inputs[1], operatorPrecedence.right); | |
| 819 endExpression(operatorPrecedence.precedence); | |
| 820 } | |
| 821 | |
| 822 // Wraps a loop body in a block to make continues have a target to break | 821 // Wraps a loop body in a block to make continues have a target to break |
| 823 // to (if necessary). | 822 // to (if necessary). |
| 824 void wrapLoopBodyForContinue(HLoopBlockInformation info) { | 823 void wrapLoopBodyForContinue(HLoopBlockInformation info) { |
| 825 TargetElement target = info.target; | 824 TargetElement target = info.target; |
| 826 if (target !== null && target.isContinueTarget) { | 825 if (target !== null && target.isContinueTarget) { |
| 827 addIndentation(); | 826 addIndentation(); |
| 828 for (LabelElement label in info.labels) { | 827 for (LabelElement label in info.labels) { |
| 829 if (label.isContinueTarget) { | 828 if (label.isContinueTarget) { |
| 830 writeContinueLabel(label); | 829 writeContinueLabel(label); |
| 831 buffer.add(":"); | 830 buffer.add(":"); |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 buffer.add(' = '); | 1004 buffer.add(' = '); |
| 1006 use(copy.source, JSPrecedence.ASSIGNMENT_PRECEDENCE); | 1005 use(copy.source, JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| 1007 if (!isGeneratingExpression()) { | 1006 if (!isGeneratingExpression()) { |
| 1008 buffer.add(';\n'); | 1007 buffer.add(';\n'); |
| 1009 } | 1008 } |
| 1010 } | 1009 } |
| 1011 } | 1010 } |
| 1012 | 1011 |
| 1013 void iterateBasicBlock(HBasicBlock node) { | 1012 void iterateBasicBlock(HBasicBlock node) { |
| 1014 HInstruction instruction = node.first; | 1013 HInstruction instruction = node.first; |
| 1015 while (instruction != null) { | 1014 while (instruction !== node.last) { |
| 1016 if (instruction === node.last) { | 1015 if (instruction is HTypeGuard) { |
| 1017 assignPhisOfSuccessors(node); | |
| 1018 } | |
| 1019 | |
| 1020 if (isGenerateAtUseSite(instruction)) { | |
| 1021 if (instruction is HIf) { | |
| 1022 HIf hif = instruction; | |
| 1023 // The "if" is implementing part of a logical expression. | |
| 1024 // Skip directly forward to to its latest successor, since everything | |
| 1025 // in-between must also be generateAtUseSite. | |
| 1026 assert(hif.trueBranch.id < hif.falseBranch.id); | |
| 1027 visitBasicBlock(hif.falseBranch); | |
| 1028 } | |
| 1029 } else if (instruction is HControlFlow) { | |
| 1030 if (instruction is HLoopBranch && isGeneratingExpression()) { | |
| 1031 addExpressionSeparator(); | |
| 1032 } | |
| 1033 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); | 1016 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| 1034 } else if (instruction is HTypeGuard) { | 1017 } else if (!isGenerateAtUseSite(instruction)) { |
| 1035 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); | |
| 1036 } else { | |
| 1037 if (isGeneratingExpression()) { | |
| 1038 addExpressionSeparator(); | |
| 1039 } else { | |
| 1040 addIndentation(); | |
| 1041 } | |
| 1042 define(instruction); | 1018 define(instruction); |
| 1043 if (!isGeneratingExpression()) buffer.add(';\n'); | |
| 1044 } | 1019 } |
| 1045 instruction = instruction.next; | 1020 instruction = instruction.next; |
| 1046 } | 1021 } |
| 1022 assignPhisOfSuccessors(node); |
| 1023 if (instruction is HLoopBranch && isGeneratingExpression()) { |
| 1024 addExpressionSeparator(); |
| 1025 } |
| 1026 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); |
| 1047 } | 1027 } |
| 1048 | 1028 |
| 1049 visitInvokeBinary(HInvokeBinary node, String op) { | 1029 visitInvokeBinary(HInvokeBinary node, String op) { |
| 1050 if (node.builtin) { | 1030 if (node.builtin) { |
| 1051 JSBinaryOperatorPrecedence operatorPrecedences = JSPrecedence.binary[op]; | 1031 JSBinaryOperatorPrecedence operatorPrecedences = JSPrecedence.binary[op]; |
| 1052 beginExpression(operatorPrecedences.precedence); | 1032 beginExpression(operatorPrecedences.precedence); |
| 1053 use(node.left, operatorPrecedences.left); | 1033 use(node.left, operatorPrecedences.left); |
| 1054 buffer.add(' $op '); | 1034 buffer.add(' $op '); |
| 1055 use(node.right, operatorPrecedences.right); | 1035 use(node.right, operatorPrecedences.right); |
| 1056 endExpression(operatorPrecedences.precedence); | 1036 endExpression(operatorPrecedences.precedence); |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1256 compiler.internalError('visitTry should not be called', instruction: node); | 1236 compiler.internalError('visitTry should not be called', instruction: node); |
| 1257 } | 1237 } |
| 1258 | 1238 |
| 1259 bool isEmptyElse(HBasicBlock start, HBasicBlock end) { | 1239 bool isEmptyElse(HBasicBlock start, HBasicBlock end) { |
| 1260 if (start !== end) return false; | 1240 if (start !== end) return false; |
| 1261 if (start.last is !HGoto | 1241 if (start.last is !HGoto |
| 1262 || start.last is HBreak | 1242 || start.last is HBreak |
| 1263 || start.last is HContinue) { | 1243 || start.last is HContinue) { |
| 1264 return false; | 1244 return false; |
| 1265 } | 1245 } |
| 1266 HInstruction instruction = start.first; | |
| 1267 for (HInstruction instruction = start.first; | 1246 for (HInstruction instruction = start.first; |
| 1268 instruction != start.last; | 1247 instruction != start.last; |
| 1269 instruction = instruction.next) { | 1248 instruction = instruction.next) { |
| 1270 // Instructions generated at use site are okay because they do | 1249 // Instructions generated at use site are okay because they do |
| 1271 // not generate code in this else block. | 1250 // not generate code in this else block. |
| 1272 if (!isGenerateAtUseSite(instruction)) return false; | 1251 if (!isGenerateAtUseSite(instruction)) return false; |
| 1273 } | 1252 } |
| 1274 CopyHandler handler = variableNames.getCopyHandler(start); | 1253 CopyHandler handler = variableNames.getCopyHandler(start); |
| 1275 if (handler == null || handler.isEmpty()) return true; | 1254 if (handler == null || handler.isEmpty()) return true; |
| 1276 if (!handler.assignments.isEmpty()) return false; | 1255 if (!handler.assignments.isEmpty()) return false; |
| 1277 // If the block has a copy where the destination and source are | 1256 // If the block has a copy where the destination and source are |
| 1278 // different, we will emit that copy, and therefore the block is | 1257 // different, we will emit that copy, and therefore the block is |
| 1279 // not empty. | 1258 // not empty. |
| 1280 for (Copy copy in handler.copies) { | 1259 for (Copy copy in handler.copies) { |
| 1281 String sourceName = variableNames.getName(copy.source); | 1260 String sourceName = variableNames.getName(copy.source); |
| 1282 String destinationName = variableNames.getName(copy.destination); | 1261 String destinationName = variableNames.getName(copy.destination); |
| 1283 if (sourceName != destinationName) return false; | 1262 if (sourceName != destinationName) return false; |
| 1284 } | 1263 } |
| 1285 return true; | 1264 return true; |
| 1286 } | 1265 } |
| 1287 | 1266 |
| 1288 visitIf(HIf node) { | 1267 visitIf(HIf node) { |
| 1268 if (logicalOperations.contains(node)) { |
| 1269 HPhi phi = node.joinBlock.phis.first; |
| 1270 if (!isGenerateAtUseSite(phi)) define(phi); |
| 1271 visitBasicBlock(node.joinBlock); |
| 1272 return; |
| 1273 } |
| 1274 |
| 1289 if (subGraph !== null && node.block === subGraph.end) { | 1275 if (subGraph !== null && node.block === subGraph.end) { |
| 1290 if (isGeneratingExpression()) { | 1276 if (isGeneratingExpression()) { |
| 1291 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); | 1277 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); |
| 1292 } | 1278 } |
| 1293 return; | 1279 return; |
| 1294 } | 1280 } |
| 1281 |
| 1295 HInstruction condition = node.inputs[0]; | 1282 HInstruction condition = node.inputs[0]; |
| 1296 int preVisitedBlocks = 0; | 1283 int preVisitedBlocks = 0; |
| 1297 List<HBasicBlock> dominated = node.block.dominatedBlocks; | 1284 List<HBasicBlock> dominated = node.block.dominatedBlocks; |
| 1298 HIfBlockInformation info = node.blockInformation.body; | 1285 HIfBlockInformation info = node.blockInformation.body; |
| 1299 HBasicBlock joinBlock = node.joinBlock; | 1286 HBasicBlock joinBlock = node.joinBlock; |
| 1300 if (condition.isConstant()) { | 1287 if (condition.isConstant()) { |
| 1301 HConstant constant = condition; | 1288 HConstant constant = condition; |
| 1302 if (constant.constant.isTrue()) { | 1289 if (constant.constant.isTrue()) { |
| 1303 generateStatements(info.thenGraph); | 1290 generateStatements(info.thenGraph); |
| 1304 } else if (node.hasElse) { | 1291 } else if (node.hasElse) { |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1580 visitBasicBlock(branchBlock.successors[1]); | 1567 visitBasicBlock(branchBlock.successors[1]); |
| 1581 // With labeled breaks we can have more dominated blocks. | 1568 // With labeled breaks we can have more dominated blocks. |
| 1582 if (dominated.length >= 3) { | 1569 if (dominated.length >= 3) { |
| 1583 for (int i = 2; i < dominated.length; i++) { | 1570 for (int i = 2; i < dominated.length; i++) { |
| 1584 visitBasicBlock(dominated[i]); | 1571 visitBasicBlock(dominated[i]); |
| 1585 } | 1572 } |
| 1586 } | 1573 } |
| 1587 } | 1574 } |
| 1588 | 1575 |
| 1589 visitNot(HNot node) { | 1576 visitNot(HNot node) { |
| 1577 assert(node.inputs.length == 1); |
| 1578 generateNot(node.inputs[0]); |
| 1579 } |
| 1580 |
| 1581 |
| 1582 void generateNot(HInstruction input) { |
| 1590 bool isBuiltinRelational(HInstruction instruction) { | 1583 bool isBuiltinRelational(HInstruction instruction) { |
| 1591 if (instruction is !HRelational) return false; | 1584 if (instruction is !HRelational) return false; |
| 1592 HRelational relational = instruction; | 1585 HRelational relational = instruction; |
| 1593 return relational.builtin; | 1586 return relational.builtin; |
| 1594 } | 1587 } |
| 1595 | 1588 |
| 1596 assert(node.inputs.length == 1); | |
| 1597 HInstruction input = node.inputs[0]; | |
| 1598 if (input is HBoolify && isGenerateAtUseSite(input)) { | 1589 if (input is HBoolify && isGenerateAtUseSite(input)) { |
| 1599 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 1590 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1600 assert(node.inputs.length == 1); | |
| 1601 use(input.inputs[0], JSPrecedence.EQUALITY_PRECEDENCE); | 1591 use(input.inputs[0], JSPrecedence.EQUALITY_PRECEDENCE); |
| 1602 buffer.add(' !== true'); | 1592 buffer.add(' !== true'); |
| 1603 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 1593 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1604 } else if (isBuiltinRelational(input) && | 1594 } else if (isBuiltinRelational(input) && |
| 1605 isGenerateAtUseSite(input) && | 1595 isGenerateAtUseSite(input) && |
| 1606 input.inputs[0].propagatedType.isUseful() && | 1596 input.inputs[0].propagatedType.isUseful() && |
| 1607 !input.inputs[0].isDouble() && | 1597 !input.inputs[0].isDouble() && |
| 1608 input.inputs[1].propagatedType.isUseful() && | 1598 input.inputs[1].propagatedType.isUseful() && |
| 1609 !input.inputs[1].isDouble()) { | 1599 !input.inputs[1].isDouble()) { |
| 1610 // This optimization doesn't work for NaN, so we only do it if the | 1600 // This optimization doesn't work for NaN, so we only do it if the |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1629 endExpression(JSPrecedence.PREFIX_PRECEDENCE); | 1619 endExpression(JSPrecedence.PREFIX_PRECEDENCE); |
| 1630 } | 1620 } |
| 1631 } | 1621 } |
| 1632 | 1622 |
| 1633 visitParameterValue(HParameterValue node) { | 1623 visitParameterValue(HParameterValue node) { |
| 1634 assert(isGenerateAtUseSite(node)); | 1624 assert(isGenerateAtUseSite(node)); |
| 1635 buffer.add(variableNames.getName(node)); | 1625 buffer.add(variableNames.getName(node)); |
| 1636 } | 1626 } |
| 1637 | 1627 |
| 1638 visitPhi(HPhi node) { | 1628 visitPhi(HPhi node) { |
| 1639 String operation = logicalOperations[node]; | 1629 HBasicBlock ifBlock = node.block.predecessors[0].predecessors[0]; |
| 1640 if (operation !== null) { | 1630 // This method is only called for phis that are generated at use |
| 1641 emitLogicalOperation(node, operation); | 1631 // site. A phi can be generated at use site only if it is the |
| 1632 // result of a logical operation. |
| 1633 assert(logicalOperations.contains(ifBlock.last)); |
| 1634 HInstruction input = ifBlock.last.inputs[0]; |
| 1635 if (input.isConstantFalse()) { |
| 1636 use(node.inputs[1], expectedPrecedence); |
| 1637 } else if (input.isConstantTrue()) { |
| 1638 use(node.inputs[0], expectedPrecedence); |
| 1642 } else { | 1639 } else { |
| 1643 buffer.add('${variableNames.getName(node)}'); | 1640 String operation = node.inputs[1].isConstantFalse() ? '&&' : '||'; |
| 1641 JSBinaryOperatorPrecedence operatorPrecedence = |
| 1642 JSPrecedence.binary[operation]; |
| 1643 beginExpression(operatorPrecedence.precedence); |
| 1644 if (operation == '||') { |
| 1645 if (input is HNot) { |
| 1646 use(input.inputs[0], operatorPrecedence.left); |
| 1647 } else { |
| 1648 generateNot(input); |
| 1649 } |
| 1650 } else { |
| 1651 use(input, operatorPrecedence.left); |
| 1652 } |
| 1653 buffer.add(" $operation "); |
| 1654 use(node.inputs[0], operatorPrecedence.right); |
| 1655 endExpression(operatorPrecedence.precedence); |
| 1644 } | 1656 } |
| 1645 } | 1657 } |
| 1646 | 1658 |
| 1647 visitReturn(HReturn node) { | 1659 visitReturn(HReturn node) { |
| 1648 addIndentation(); | 1660 addIndentation(); |
| 1649 assert(node.inputs.length == 1); | 1661 assert(node.inputs.length == 1); |
| 1650 HInstruction input = node.inputs[0]; | 1662 HInstruction input = node.inputs[0]; |
| 1651 if (input.isConstantNull()) { | 1663 if (input.isConstantNull()) { |
| 1652 buffer.add('return;\n'); | 1664 buffer.add('return;\n'); |
| 1653 } else { | 1665 } else { |
| (...skipping 851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2505 startBailoutSwitch(); | 2517 startBailoutSwitch(); |
| 2506 } | 2518 } |
| 2507 } | 2519 } |
| 2508 | 2520 |
| 2509 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2521 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2510 if (labeledBlockInfo.body.start.hasGuards()) { | 2522 if (labeledBlockInfo.body.start.hasGuards()) { |
| 2511 endBailoutSwitch(); | 2523 endBailoutSwitch(); |
| 2512 } | 2524 } |
| 2513 } | 2525 } |
| 2514 } | 2526 } |
| OLD | NEW |