| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 class SsaCodeGeneratorTask extends CompilerTask { | 7 class SsaCodeGeneratorTask extends CompilerTask { |
| 8 | 8 |
| 9 final JavaScriptBackend backend; | 9 final JavaScriptBackend backend; |
| 10 | 10 |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 visitBailoutTarget(HBailoutTarget node); | 282 visitBailoutTarget(HBailoutTarget node); |
| 283 | 283 |
| 284 beginGraph(HGraph graph); | 284 beginGraph(HGraph graph); |
| 285 endGraph(HGraph graph); | 285 endGraph(HGraph graph); |
| 286 | 286 |
| 287 preLabeledBlock(HLabeledBlockInformation labeledBlockInfo); | 287 preLabeledBlock(HLabeledBlockInformation labeledBlockInfo); |
| 288 startLabeledBlock(HLabeledBlockInformation labeledBlockInfo); | 288 startLabeledBlock(HLabeledBlockInformation labeledBlockInfo); |
| 289 endLabeledBlock(HLabeledBlockInformation labeledBlockInfo); | 289 endLabeledBlock(HLabeledBlockInformation labeledBlockInfo); |
| 290 | 290 |
| 291 void preGenerateMethod(HGraph graph) { | 291 void preGenerateMethod(HGraph graph) { |
| 292 new SsaInstructionMerger(generateAtUseSite).visitGraph(graph); | 292 new SsaInstructionMerger(generateAtUseSite, compiler).visitGraph(graph); |
| 293 new SsaConditionMerger( | 293 new SsaConditionMerger( |
| 294 generateAtUseSite, controlFlowOperators).visitGraph(graph); | 294 generateAtUseSite, controlFlowOperators).visitGraph(graph); |
| 295 SsaLiveIntervalBuilder intervalBuilder = | 295 SsaLiveIntervalBuilder intervalBuilder = |
| 296 new SsaLiveIntervalBuilder(compiler, generateAtUseSite); | 296 new SsaLiveIntervalBuilder(compiler, generateAtUseSite); |
| 297 intervalBuilder.visitGraph(graph); | 297 intervalBuilder.visitGraph(graph); |
| 298 SsaVariableAllocator allocator = new SsaVariableAllocator( | 298 SsaVariableAllocator allocator = new SsaVariableAllocator( |
| 299 compiler, | 299 compiler, |
| 300 intervalBuilder.liveInstructions, | 300 intervalBuilder.liveInstructions, |
| 301 intervalBuilder.liveIntervals, | 301 intervalBuilder.liveIntervals, |
| 302 generateAtUseSite); | 302 generateAtUseSite); |
| (...skipping 911 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1214 visitBitInvokeUnary(HInvokeUnary node, String op) { | 1214 visitBitInvokeUnary(HInvokeUnary node, String op) { |
| 1215 visitInvokeUnary(node, op); | 1215 visitInvokeUnary(node, op); |
| 1216 if (requiresUintConversion(node)) { | 1216 if (requiresUintConversion(node)) { |
| 1217 push(new js.Binary(">>>", pop(), new js.LiteralNumber("0")), node); | 1217 push(new js.Binary(">>>", pop(), new js.LiteralNumber("0")), node); |
| 1218 } | 1218 } |
| 1219 } | 1219 } |
| 1220 | 1220 |
| 1221 void emitIdentityComparison(HInstruction left, | 1221 void emitIdentityComparison(HInstruction left, |
| 1222 HInstruction right, | 1222 HInstruction right, |
| 1223 bool inverse) { | 1223 bool inverse) { |
| 1224 String op = singleIdentityComparison(left, right); | 1224 String op = singleIdentityComparison(left, right, compiler); |
| 1225 if (op != null) { | 1225 if (op != null) { |
| 1226 use(left); | 1226 use(left); |
| 1227 js.Expression jsLeft = pop(); | 1227 js.Expression jsLeft = pop(); |
| 1228 use(right); | 1228 use(right); |
| 1229 push(new js.Binary(mapRelationalOperator(op, inverse), jsLeft, pop())); | 1229 push(new js.Binary(mapRelationalOperator(op, inverse), jsLeft, pop())); |
| 1230 } else { | 1230 } else { |
| 1231 assert(NullConstant.JsNull == 'null'); | 1231 assert(NullConstant.JsNull == 'null'); |
| 1232 use(left); | 1232 use(left); |
| 1233 js.Binary leftEqualsNull = | 1233 js.Binary leftEqualsNull = |
| 1234 new js.Binary("==", pop(), new js.LiteralNull()); | 1234 new js.Binary("==", pop(), new js.LiteralNull()); |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1790 | 1790 |
| 1791 void generateNot(HInstruction input) { | 1791 void generateNot(HInstruction input) { |
| 1792 bool canGenerateOptimizedComparison(HInstruction instruction) { | 1792 bool canGenerateOptimizedComparison(HInstruction instruction) { |
| 1793 if (instruction is !HRelational) return false; | 1793 if (instruction is !HRelational) return false; |
| 1794 | 1794 |
| 1795 HRelational relational = instruction; | 1795 HRelational relational = instruction; |
| 1796 BinaryOperation operation = relational.operation(backend.constantSystem); | 1796 BinaryOperation operation = relational.operation(backend.constantSystem); |
| 1797 | 1797 |
| 1798 HInstruction left = relational.left; | 1798 HInstruction left = relational.left; |
| 1799 HInstruction right = relational.right; | 1799 HInstruction right = relational.right; |
| 1800 if (left.instructionType.isUseful() && left.isString() && | 1800 if (left.instructionType.isUseful() && left.isString(compiler) && |
| 1801 right.instructionType.isUseful() && right.isString()) { | 1801 right.instructionType.isUseful() && right.isString(compiler)) { |
| 1802 return true; | 1802 return true; |
| 1803 } | 1803 } |
| 1804 | 1804 |
| 1805 // This optimization doesn't work for NaN, so we only do it if the | 1805 // This optimization doesn't work for NaN, so we only do it if the |
| 1806 // type is known to be an integer. | 1806 // type is known to be an integer. |
| 1807 return left.instructionType.isUseful() && left.isInteger() | 1807 return left.instructionType.isUseful() && left.isInteger() |
| 1808 && right.instructionType.isUseful() && right.isInteger(); | 1808 && right.instructionType.isUseful() && right.isInteger(); |
| 1809 } | 1809 } |
| 1810 | 1810 |
| 1811 bool generateAtUseSite = isGenerateAtUseSite(input); | 1811 bool generateAtUseSite = isGenerateAtUseSite(input); |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2021 | 2021 |
| 2022 void visitStringConcat(HStringConcat node) { | 2022 void visitStringConcat(HStringConcat node) { |
| 2023 use(node.left); | 2023 use(node.left); |
| 2024 js.Expression jsLeft = pop(); | 2024 js.Expression jsLeft = pop(); |
| 2025 use(node.right); | 2025 use(node.right); |
| 2026 push(new js.Binary('+', jsLeft, pop()), node); | 2026 push(new js.Binary('+', jsLeft, pop()), node); |
| 2027 } | 2027 } |
| 2028 | 2028 |
| 2029 void visitStringify(HStringify node) { | 2029 void visitStringify(HStringify node) { |
| 2030 HInstruction input = node.inputs.first; | 2030 HInstruction input = node.inputs.first; |
| 2031 if (input.isString()) { | 2031 if (input.isString(compiler)) { |
| 2032 use(input); | 2032 use(input); |
| 2033 } else if (input.isInteger() || input.isBoolean()) { | 2033 } else if (input.isInteger() || input.isBoolean()) { |
| 2034 // JavaScript's + operator with a string for the left operand will convert | 2034 // JavaScript's + operator with a string for the left operand will convert |
| 2035 // the right operand to a string, and the conversion result is correct. | 2035 // the right operand to a string, and the conversion result is correct. |
| 2036 use(input); | 2036 use(input); |
| 2037 if (node.usedBy.length == 1 | 2037 if (node.usedBy.length == 1 |
| 2038 && node.usedBy[0] is HStringConcat | 2038 && node.usedBy[0] is HStringConcat |
| 2039 && node.usedBy[0].inputs[1] == node) { | 2039 && node.usedBy[0].inputs[1] == node) { |
| 2040 // The context is already <string> + value. | 2040 // The context is already <string> + value. |
| 2041 } else { | 2041 } else { |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2417 checkInt(input, '!=='); | 2417 checkInt(input, '!=='); |
| 2418 test = pop(); | 2418 test = pop(); |
| 2419 } else if (node.isNumber()) { | 2419 } else if (node.isNumber()) { |
| 2420 // input is !num | 2420 // input is !num |
| 2421 checkNum(input, '!=='); | 2421 checkNum(input, '!=='); |
| 2422 test = pop(); | 2422 test = pop(); |
| 2423 } else if (node.isBoolean()) { | 2423 } else if (node.isBoolean()) { |
| 2424 // input is !bool | 2424 // input is !bool |
| 2425 checkBool(input, '!=='); | 2425 checkBool(input, '!=='); |
| 2426 test = pop(); | 2426 test = pop(); |
| 2427 } else if (node.isString()) { | 2427 } else if (node.isString(compiler)) { |
| 2428 // input is !string | 2428 // input is !string |
| 2429 checkString(input, '!=='); | 2429 checkString(input, '!=='); |
| 2430 test = pop(); | 2430 test = pop(); |
| 2431 } else if (node.isExtendableArray(compiler)) { | 2431 } else if (node.isExtendableArray(compiler)) { |
| 2432 // input is !Object || input is !Array || input.isFixed | 2432 // input is !Object || input is !Array || input.isFixed |
| 2433 checkObject(input, '!=='); | 2433 checkObject(input, '!=='); |
| 2434 js.Expression objectTest = pop(); | 2434 js.Expression objectTest = pop(); |
| 2435 checkArray(input, '!=='); | 2435 checkArray(input, '!=='); |
| 2436 js.Expression arrayTest = pop(); | 2436 js.Expression arrayTest = pop(); |
| 2437 checkFixedArray(input); | 2437 checkFixedArray(input); |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2986 } | 2986 } |
| 2987 } | 2987 } |
| 2988 | 2988 |
| 2989 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2989 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2990 if (labeledBlockInfo.body.start.hasBailoutTargets()) { | 2990 if (labeledBlockInfo.body.start.hasBailoutTargets()) { |
| 2991 endBailoutSwitch(); | 2991 endBailoutSwitch(); |
| 2992 } | 2992 } |
| 2993 } | 2993 } |
| 2994 } | 2994 } |
| 2995 | 2995 |
| 2996 String singleIdentityComparison(HInstruction left, HInstruction right) { | 2996 String singleIdentityComparison(HInstruction left, |
| 2997 HInstruction right, |
| 2998 Compiler compiler) { |
| 2997 // Returns the single identity comparison (== or ===) or null if a more | 2999 // Returns the single identity comparison (== or ===) or null if a more |
| 2998 // complex expression is required. | 3000 // complex expression is required. |
| 2999 if ((left.isConstant() && left.isConstantSentinel()) || | 3001 if ((left.isConstant() && left.isConstantSentinel()) || |
| 3000 (right.isConstant() && right.isConstantSentinel())) return '==='; | 3002 (right.isConstant() && right.isConstantSentinel())) return '==='; |
| 3001 HType leftType = left.instructionType; | 3003 HType leftType = left.instructionType; |
| 3002 HType rightType = right.instructionType; | 3004 HType rightType = right.instructionType; |
| 3003 if (leftType.canBeNull() && rightType.canBeNull()) { | 3005 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 3004 if (left.isConstantNull() || right.isConstantNull() || | 3006 if (left.isConstantNull() || right.isConstantNull() || |
| 3005 (leftType.isPrimitive() && leftType == rightType)) { | 3007 (leftType.isPrimitive(compiler) && leftType == rightType)) { |
| 3006 return '=='; | 3008 return '=='; |
| 3007 } | 3009 } |
| 3008 return null; | 3010 return null; |
| 3009 } else { | 3011 } else { |
| 3010 return '==='; | 3012 return '==='; |
| 3011 } | 3013 } |
| 3012 } | 3014 } |
| OLD | NEW |