| 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 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1799 | 1799 |
| 1800 void generateNot(HInstruction input) { | 1800 void generateNot(HInstruction input) { |
| 1801 bool canGenerateOptimizedComparison(HInstruction instruction) { | 1801 bool canGenerateOptimizedComparison(HInstruction instruction) { |
| 1802 if (instruction is !HRelational) return false; | 1802 if (instruction is !HRelational) return false; |
| 1803 | 1803 |
| 1804 HRelational relational = instruction; | 1804 HRelational relational = instruction; |
| 1805 BinaryOperation operation = relational.operation(backend.constantSystem); | 1805 BinaryOperation operation = relational.operation(backend.constantSystem); |
| 1806 | 1806 |
| 1807 HInstruction left = relational.left; | 1807 HInstruction left = relational.left; |
| 1808 HInstruction right = relational.right; | 1808 HInstruction right = relational.right; |
| 1809 if (left.instructionType.isUseful() && left.isString() && | 1809 if (left.instructionType.isUseful() && left.isString(compiler) && |
| 1810 right.instructionType.isUseful() && right.isString()) { | 1810 right.instructionType.isUseful() && right.isString(compiler)) { |
| 1811 return true; | 1811 return true; |
| 1812 } | 1812 } |
| 1813 | 1813 |
| 1814 // This optimization doesn't work for NaN, so we only do it if the | 1814 // This optimization doesn't work for NaN, so we only do it if the |
| 1815 // type is known to be an integer. | 1815 // type is known to be an integer. |
| 1816 return left.instructionType.isUseful() && left.isInteger() | 1816 return left.instructionType.isUseful() && left.isInteger() |
| 1817 && right.instructionType.isUseful() && right.isInteger(); | 1817 && right.instructionType.isUseful() && right.isInteger(); |
| 1818 } | 1818 } |
| 1819 | 1819 |
| 1820 bool generateAtUseSite = isGenerateAtUseSite(input); | 1820 bool generateAtUseSite = isGenerateAtUseSite(input); |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2030 | 2030 |
| 2031 void visitStringConcat(HStringConcat node) { | 2031 void visitStringConcat(HStringConcat node) { |
| 2032 use(node.left); | 2032 use(node.left); |
| 2033 js.Expression jsLeft = pop(); | 2033 js.Expression jsLeft = pop(); |
| 2034 use(node.right); | 2034 use(node.right); |
| 2035 push(new js.Binary('+', jsLeft, pop()), node); | 2035 push(new js.Binary('+', jsLeft, pop()), node); |
| 2036 } | 2036 } |
| 2037 | 2037 |
| 2038 void visitStringify(HStringify node) { | 2038 void visitStringify(HStringify node) { |
| 2039 HInstruction input = node.inputs.first; | 2039 HInstruction input = node.inputs.first; |
| 2040 if (input.isString()) { | 2040 if (input.isString(compiler)) { |
| 2041 use(input); | 2041 use(input); |
| 2042 } else if (input.isInteger() || input.isBoolean()) { | 2042 } else if (input.isInteger() || input.isBoolean()) { |
| 2043 // JavaScript's + operator with a string for the left operand will convert | 2043 // JavaScript's + operator with a string for the left operand will convert |
| 2044 // the right operand to a string, and the conversion result is correct. | 2044 // the right operand to a string, and the conversion result is correct. |
| 2045 use(input); | 2045 use(input); |
| 2046 if (node.usedBy.length == 1 | 2046 if (node.usedBy.length == 1 |
| 2047 && node.usedBy[0] is HStringConcat | 2047 && node.usedBy[0] is HStringConcat |
| 2048 && node.usedBy[0].inputs[1] == node) { | 2048 && node.usedBy[0].inputs[1] == node) { |
| 2049 // The context is already <string> + value. | 2049 // The context is already <string> + value. |
| 2050 } else { | 2050 } else { |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2426 checkInt(input, '!=='); | 2426 checkInt(input, '!=='); |
| 2427 test = pop(); | 2427 test = pop(); |
| 2428 } else if (node.isNumber()) { | 2428 } else if (node.isNumber()) { |
| 2429 // input is !num | 2429 // input is !num |
| 2430 checkNum(input, '!=='); | 2430 checkNum(input, '!=='); |
| 2431 test = pop(); | 2431 test = pop(); |
| 2432 } else if (node.isBoolean()) { | 2432 } else if (node.isBoolean()) { |
| 2433 // input is !bool | 2433 // input is !bool |
| 2434 checkBool(input, '!=='); | 2434 checkBool(input, '!=='); |
| 2435 test = pop(); | 2435 test = pop(); |
| 2436 } else if (node.isString()) { | 2436 } else if (node.isString(compiler)) { |
| 2437 // input is !string | 2437 // input is !string |
| 2438 checkString(input, '!=='); | 2438 checkString(input, '!=='); |
| 2439 test = pop(); | 2439 test = pop(); |
| 2440 } else if (node.isExtendableArray(compiler)) { | 2440 } else if (node.isExtendableArray(compiler)) { |
| 2441 // input is !Object || input is !Array || input.isFixed | 2441 // input is !Object || input is !Array || input.isFixed |
| 2442 checkObject(input, '!=='); | 2442 checkObject(input, '!=='); |
| 2443 js.Expression objectTest = pop(); | 2443 js.Expression objectTest = pop(); |
| 2444 checkArray(input, '!=='); | 2444 checkArray(input, '!=='); |
| 2445 js.Expression arrayTest = pop(); | 2445 js.Expression arrayTest = pop(); |
| 2446 checkFixedArray(input); | 2446 checkFixedArray(input); |
| (...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2995 } | 2995 } |
| 2996 } | 2996 } |
| 2997 | 2997 |
| 2998 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2998 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2999 if (labeledBlockInfo.body.start.hasBailoutTargets()) { | 2999 if (labeledBlockInfo.body.start.hasBailoutTargets()) { |
| 3000 endBailoutSwitch(); | 3000 endBailoutSwitch(); |
| 3001 } | 3001 } |
| 3002 } | 3002 } |
| 3003 } | 3003 } |
| 3004 | 3004 |
| 3005 String singleIdentityComparison(HInstruction left, HInstruction right) { | 3005 String singleIdentityComparison(HInstruction left, |
| 3006 HInstruction right, |
| 3007 Compiler compiler) { |
| 3006 // Returns the single identity comparison (== or ===) or null if a more | 3008 // Returns the single identity comparison (== or ===) or null if a more |
| 3007 // complex expression is required. | 3009 // complex expression is required. |
| 3008 if ((left.isConstant() && left.isConstantSentinel()) || | 3010 if ((left.isConstant() && left.isConstantSentinel()) || |
| 3009 (right.isConstant() && right.isConstantSentinel())) return '==='; | 3011 (right.isConstant() && right.isConstantSentinel())) return '==='; |
| 3010 HType leftType = left.instructionType; | 3012 HType leftType = left.instructionType; |
| 3011 HType rightType = right.instructionType; | 3013 HType rightType = right.instructionType; |
| 3012 if (leftType.canBeNull() && rightType.canBeNull()) { | 3014 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 3013 if (left.isConstantNull() || right.isConstantNull() || | 3015 if (left.isConstantNull() || right.isConstantNull() || |
| 3014 (leftType.isPrimitive() && leftType == rightType)) { | 3016 (leftType.isPrimitive(compiler) && leftType == rightType)) { |
| 3015 return '=='; | 3017 return '=='; |
| 3016 } | 3018 } |
| 3017 return null; | 3019 return null; |
| 3018 } else { | 3020 } else { |
| 3019 return '==='; | 3021 return '==='; |
| 3020 } | 3022 } |
| 3021 } | 3023 } |
| OLD | NEW |