| 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 1506 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1517 methodName = name.slowToString(); | 1517 methodName = name.slowToString(); |
| 1518 } else if (!node.isInterceptorCall) { | 1518 } else if (!node.isInterceptorCall) { |
| 1519 if (target == backend.jsArrayAdd) { | 1519 if (target == backend.jsArrayAdd) { |
| 1520 methodName = 'push'; | 1520 methodName = 'push'; |
| 1521 } else if (target == backend.jsArrayRemoveLast) { | 1521 } else if (target == backend.jsArrayRemoveLast) { |
| 1522 methodName = 'pop'; | 1522 methodName = 'pop'; |
| 1523 } else if (target == backend.jsStringSplit) { | 1523 } else if (target == backend.jsStringSplit) { |
| 1524 methodName = 'split'; | 1524 methodName = 'split'; |
| 1525 // Split returns a List, so we make sure the backend knows the | 1525 // Split returns a List, so we make sure the backend knows the |
| 1526 // list class is instantiated. | 1526 // list class is instantiated. |
| 1527 world.registerInstantiatedClass(compiler.listClass); | 1527 world.registerInstantiatedClass( |
| 1528 compiler.listClass, work.resolutionTree); |
| 1528 } else if (target == backend.jsStringConcat) { | 1529 } else if (target == backend.jsStringConcat) { |
| 1529 push(new js.Binary('+', object, arguments[0]), node); | 1530 push(new js.Binary('+', object, arguments[0]), node); |
| 1530 return; | 1531 return; |
| 1531 } else if (target.isNative() | 1532 } else if (target.isNative() |
| 1532 && !compiler.enableTypeAssertions | 1533 && !compiler.enableTypeAssertions |
| 1533 && target.isFunction()) { | 1534 && target.isFunction()) { |
| 1534 // Enable direct calls to a native method only if we don't | 1535 // Enable direct calls to a native method only if we don't |
| 1535 // run in checked mode, where the Dart version may have | 1536 // run in checked mode, where the Dart version may have |
| 1536 // type annotations on parameters and return type that it | 1537 // type annotations on parameters and return type that it |
| 1537 // should check. | 1538 // should check. |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1638 HType valueType = node.isInterceptorCall | 1639 HType valueType = node.isInterceptorCall |
| 1639 ? node.inputs[2].instructionType | 1640 ? node.inputs[2].instructionType |
| 1640 : node.inputs[1].instructionType; | 1641 : node.inputs[1].instructionType; |
| 1641 backend.addedDynamicSetter(selector, valueType); | 1642 backend.addedDynamicSetter(selector, valueType); |
| 1642 registerInvoke(node, selector); | 1643 registerInvoke(node, selector); |
| 1643 } | 1644 } |
| 1644 | 1645 |
| 1645 void registerGetter(HInvokeDynamic node) { | 1646 void registerGetter(HInvokeDynamic node) { |
| 1646 Selector selector = getOptimizedSelectorFor(node, node.selector); | 1647 Selector selector = getOptimizedSelectorFor(node, node.selector); |
| 1647 world.registerDynamicGetter(selector.name, selector); | 1648 world.registerDynamicGetter(selector.name, selector); |
| 1648 world.registerInstantiatedClass(compiler.functionClass); | 1649 world.registerInstantiatedClass( |
| 1650 compiler.functionClass, work.resolutionTree); |
| 1649 registerInvoke(node, selector); | 1651 registerInvoke(node, selector); |
| 1650 } | 1652 } |
| 1651 | 1653 |
| 1652 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { | 1654 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { |
| 1653 use(node.receiver); | 1655 use(node.receiver); |
| 1654 String name = backend.namer.invocationName(node.selector); | 1656 String name = backend.namer.invocationName(node.selector); |
| 1655 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node); | 1657 push(jsPropertyCall(pop(), name, visitArguments(node.inputs)), node); |
| 1656 registerSetter(node); | 1658 registerSetter(node); |
| 1657 } | 1659 } |
| 1658 | 1660 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1766 use(node.value); | 1768 use(node.value); |
| 1767 assignVariable(variableNames.getName(node.receiver), pop()); | 1769 assignVariable(variableNames.getName(node.receiver), pop()); |
| 1768 } | 1770 } |
| 1769 | 1771 |
| 1770 void registerForeignType(HType type) { | 1772 void registerForeignType(HType type) { |
| 1771 DartType dartType = type.computeType(compiler); | 1773 DartType dartType = type.computeType(compiler); |
| 1772 if (dartType == null) { | 1774 if (dartType == null) { |
| 1773 assert(type == HType.UNKNOWN); | 1775 assert(type == HType.UNKNOWN); |
| 1774 return; | 1776 return; |
| 1775 } | 1777 } |
| 1776 world.registerInstantiatedClass(dartType.element); | 1778 world.registerInstantiatedClass(dartType.element, work.resolutionTree); |
| 1777 } | 1779 } |
| 1778 | 1780 |
| 1779 visitForeign(HForeign node) { | 1781 visitForeign(HForeign node) { |
| 1780 String code = node.code.slowToString(); | 1782 String code = node.code.slowToString(); |
| 1781 List<HInstruction> inputs = node.inputs; | 1783 List<HInstruction> inputs = node.inputs; |
| 1782 if (node.isJsStatement()) { | 1784 if (node.isJsStatement()) { |
| 1783 if (!inputs.isEmpty) { | 1785 if (!inputs.isEmpty) { |
| 1784 compiler.internalError("foreign statement with inputs: $code", | 1786 compiler.internalError("foreign statement with inputs: $code", |
| 1785 instruction: node); | 1787 instruction: node); |
| 1786 } | 1788 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1829 push(backend.emitter.constantReference(constant)); | 1831 push(backend.emitter.constantReference(constant)); |
| 1830 } | 1832 } |
| 1831 | 1833 |
| 1832 visitConstant(HConstant node) { | 1834 visitConstant(HConstant node) { |
| 1833 assert(isGenerateAtUseSite(node)); | 1835 assert(isGenerateAtUseSite(node)); |
| 1834 generateConstant(node.constant); | 1836 generateConstant(node.constant); |
| 1835 DartType type = node.constant.computeType(compiler); | 1837 DartType type = node.constant.computeType(compiler); |
| 1836 if (node.constant is ConstructedConstant || | 1838 if (node.constant is ConstructedConstant || |
| 1837 node.constant is InterceptorConstant) { | 1839 node.constant is InterceptorConstant) { |
| 1838 ConstantHandler handler = compiler.constantHandler; | 1840 ConstantHandler handler = compiler.constantHandler; |
| 1839 handler.registerCompileTimeConstant(node.constant); | 1841 handler.registerCompileTimeConstant(node.constant, work.resolutionTree); |
| 1840 } | 1842 } |
| 1841 if (node.constant is! InterceptorConstant) { | 1843 if (node.constant is! InterceptorConstant) { |
| 1842 world.registerInstantiatedClass(type.element); | 1844 world.registerInstantiatedClass(type.element, work.resolutionTree); |
| 1843 } | 1845 } |
| 1844 } | 1846 } |
| 1845 | 1847 |
| 1846 visitNot(HNot node) { | 1848 visitNot(HNot node) { |
| 1847 assert(node.inputs.length == 1); | 1849 assert(node.inputs.length == 1); |
| 1848 generateNot(node.inputs[0]); | 1850 generateNot(node.inputs[0]); |
| 1849 attachLocationToLast(node); | 1851 attachLocationToLast(node); |
| 1850 } | 1852 } |
| 1851 | 1853 |
| 1852 static String mapRelationalOperator(String op, bool inverse) { | 1854 static String mapRelationalOperator(String op, bool inverse) { |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2042 // Switches are handled using [visitSwitchInfo]. | 2044 // Switches are handled using [visitSwitchInfo]. |
| 2043 } | 2045 } |
| 2044 | 2046 |
| 2045 void visitStatic(HStatic node) { | 2047 void visitStatic(HStatic node) { |
| 2046 // Check whether this static is used for anything else than as a target in | 2048 // Check whether this static is used for anything else than as a target in |
| 2047 // a static call. | 2049 // a static call. |
| 2048 node.usedBy.forEach((HInstruction instr) { | 2050 node.usedBy.forEach((HInstruction instr) { |
| 2049 if (instr is !HInvokeStatic) { | 2051 if (instr is !HInvokeStatic) { |
| 2050 backend.registerNonCallStaticUse(node); | 2052 backend.registerNonCallStaticUse(node); |
| 2051 if (node.element.isFunction()) { | 2053 if (node.element.isFunction()) { |
| 2052 world.registerInstantiatedClass(compiler.functionClass); | 2054 world.registerInstantiatedClass( |
| 2055 compiler.functionClass, work.resolutionTree); |
| 2053 } | 2056 } |
| 2054 } else if (instr.target != node) { | 2057 } else if (instr.target != node) { |
| 2055 backend.registerNonCallStaticUse(node); | 2058 backend.registerNonCallStaticUse(node); |
| 2056 } | 2059 } |
| 2057 }); | 2060 }); |
| 2058 Element element = node.element; | 2061 Element element = node.element; |
| 2059 world.registerStaticUse(element); | 2062 world.registerStaticUse(element); |
| 2060 ClassElement cls = element.getEnclosingClass(); | 2063 ClassElement cls = element.getEnclosingClass(); |
| 2061 if (element.isGenerativeConstructor() | 2064 if (element.isGenerativeConstructor() |
| 2062 || (element.isFactoryConstructor() && cls == compiler.listClass)) { | 2065 || (element.isFactoryConstructor() && cls == compiler.listClass)) { |
| 2063 world.registerInstantiatedClass(cls); | 2066 world.registerInstantiatedClass(cls, work.resolutionTree); |
| 2064 } | 2067 } |
| 2065 push(new js.VariableUse(backend.namer.isolateAccess(node.element))); | 2068 push(new js.VariableUse(backend.namer.isolateAccess(node.element))); |
| 2066 } | 2069 } |
| 2067 | 2070 |
| 2068 void visitLazyStatic(HLazyStatic node) { | 2071 void visitLazyStatic(HLazyStatic node) { |
| 2069 Element element = node.element; | 2072 Element element = node.element; |
| 2070 world.registerStaticUse(element); | 2073 world.registerStaticUse(element); |
| 2071 String lazyGetter = backend.namer.isolateLazyInitializerAccess(element); | 2074 String lazyGetter = backend.namer.isolateLazyInitializerAccess(element); |
| 2072 js.VariableUse target = new js.VariableUse(lazyGetter); | 2075 js.VariableUse target = new js.VariableUse(lazyGetter); |
| 2073 js.Call call = new js.Call(target, <js.Expression>[]); | 2076 js.Call call = new js.Call(target, <js.Expression>[]); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2109 Element convertToString = backend.getStringInterpolationHelper(); | 2112 Element convertToString = backend.getStringInterpolationHelper(); |
| 2110 world.registerStaticUse(convertToString); | 2113 world.registerStaticUse(convertToString); |
| 2111 js.VariableUse variableUse = | 2114 js.VariableUse variableUse = |
| 2112 new js.VariableUse(backend.namer.isolateAccess(convertToString)); | 2115 new js.VariableUse(backend.namer.isolateAccess(convertToString)); |
| 2113 use(node); | 2116 use(node); |
| 2114 push(new js.Call(variableUse, <js.Expression>[pop()]), node); | 2117 push(new js.Call(variableUse, <js.Expression>[pop()]), node); |
| 2115 } | 2118 } |
| 2116 } | 2119 } |
| 2117 | 2120 |
| 2118 void visitLiteralList(HLiteralList node) { | 2121 void visitLiteralList(HLiteralList node) { |
| 2119 world.registerInstantiatedClass(compiler.listClass); | 2122 world.registerInstantiatedClass( |
| 2123 compiler.listClass, work.resolutionTree); |
| 2120 generateArrayLiteral(node); | 2124 generateArrayLiteral(node); |
| 2121 } | 2125 } |
| 2122 | 2126 |
| 2123 void generateArrayLiteral(HLiteralList node) { | 2127 void generateArrayLiteral(HLiteralList node) { |
| 2124 int len = node.inputs.length; | 2128 int len = node.inputs.length; |
| 2125 List<js.ArrayElement> elements = <js.ArrayElement>[]; | 2129 List<js.ArrayElement> elements = <js.ArrayElement>[]; |
| 2126 for (int i = 0; i < len; i++) { | 2130 for (int i = 0; i < len; i++) { |
| 2127 use(node.inputs[i]); | 2131 use(node.inputs[i]); |
| 2128 elements.add(new js.ArrayElement(i, pop())); | 2132 elements.add(new js.ArrayElement(i, pop())); |
| 2129 } | 2133 } |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2243 js.Expression objectTest = pop(); | 2247 js.Expression objectTest = pop(); |
| 2244 checkType(input, type); | 2248 checkType(input, type); |
| 2245 push(new js.Binary('||', | 2249 push(new js.Binary('||', |
| 2246 functionTest, | 2250 functionTest, |
| 2247 new js.Binary('&&', objectTest, pop()))); | 2251 new js.Binary('&&', objectTest, pop()))); |
| 2248 } | 2252 } |
| 2249 | 2253 |
| 2250 void checkType(HInstruction input, DartType type, {bool negative: false}) { | 2254 void checkType(HInstruction input, DartType type, {bool negative: false}) { |
| 2251 assert(invariant(input, !type.isMalformed, | 2255 assert(invariant(input, !type.isMalformed, |
| 2252 message: 'Attempt to check malformed type $type')); | 2256 message: 'Attempt to check malformed type $type')); |
| 2253 world.registerIsCheck(type); | 2257 world.registerIsCheck(type, work.resolutionTree); |
| 2254 Element element = type.element; | 2258 Element element = type.element; |
| 2255 use(input); | 2259 use(input); |
| 2256 js.PropertyAccess field = | 2260 js.PropertyAccess field = |
| 2257 new js.PropertyAccess.field(pop(), backend.namer.operatorIs(element)); | 2261 new js.PropertyAccess.field(pop(), backend.namer.operatorIs(element)); |
| 2258 if (backend.emitter.nativeEmitter.requiresNativeIsCheck(element)) { | 2262 if (backend.emitter.nativeEmitter.requiresNativeIsCheck(element)) { |
| 2259 push(new js.Call(field, <js.Expression>[])); | 2263 push(new js.Call(field, <js.Expression>[])); |
| 2260 if (negative) push(new js.Prefix('!', pop())); | 2264 if (negative) push(new js.Prefix('!', pop())); |
| 2261 } else { | 2265 } else { |
| 2262 // We always negate at least once so that the result is boolified. | 2266 // We always negate at least once so that the result is boolified. |
| 2263 push(new js.Prefix('!', field)); | 2267 push(new js.Prefix('!', field)); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2305 checkArray(input, '==='); | 2309 checkArray(input, '==='); |
| 2306 js.Expression arrayTest = pop(); | 2310 js.Expression arrayTest = pop(); |
| 2307 checkType(input, type); | 2311 checkType(input, type); |
| 2308 push(new js.Binary('&&', | 2312 push(new js.Binary('&&', |
| 2309 objectTest, | 2313 objectTest, |
| 2310 new js.Binary('||', arrayTest, pop()))); | 2314 new js.Binary('||', arrayTest, pop()))); |
| 2311 } | 2315 } |
| 2312 | 2316 |
| 2313 void visitIs(HIs node) { | 2317 void visitIs(HIs node) { |
| 2314 DartType type = node.typeExpression; | 2318 DartType type = node.typeExpression; |
| 2315 world.registerIsCheck(type); | 2319 world.registerIsCheck(type, work.resolutionTree); |
| 2316 Element element = type.element; | 2320 Element element = type.element; |
| 2317 if (identical(element.kind, ElementKind.TYPE_VARIABLE)) { | 2321 if (identical(element.kind, ElementKind.TYPE_VARIABLE)) { |
| 2318 compiler.unimplemented("visitIs for type variables", | 2322 compiler.unimplemented("visitIs for type variables", |
| 2319 instruction: node.expression); | 2323 instruction: node.expression); |
| 2320 } | 2324 } |
| 2321 LibraryElement coreLibrary = compiler.coreLibrary; | 2325 LibraryElement coreLibrary = compiler.coreLibrary; |
| 2322 ClassElement objectClass = compiler.objectClass; | 2326 ClassElement objectClass = compiler.objectClass; |
| 2323 HInstruction input = node.expression; | 2327 HInstruction input = node.expression; |
| 2324 | 2328 |
| 2325 if (identical(element, objectClass) || | 2329 if (identical(element, objectClass) || |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2378 if (node.nullOk) { | 2382 if (node.nullOk) { |
| 2379 checkNull(input); | 2383 checkNull(input); |
| 2380 push(new js.Binary('||', pop(), pop()), node); | 2384 push(new js.Binary('||', pop(), pop()), node); |
| 2381 } | 2385 } |
| 2382 } | 2386 } |
| 2383 | 2387 |
| 2384 void visitTypeConversion(HTypeConversion node) { | 2388 void visitTypeConversion(HTypeConversion node) { |
| 2385 if (node.isChecked) { | 2389 if (node.isChecked) { |
| 2386 DartType type = node.instructionType.computeType(compiler); | 2390 DartType type = node.instructionType.computeType(compiler); |
| 2387 Element element = type.element; | 2391 Element element = type.element; |
| 2388 world.registerIsCheck(type); | 2392 world.registerIsCheck(type, work.resolutionTree); |
| 2389 | 2393 |
| 2390 if (node.isArgumentTypeCheck) { | 2394 if (node.isArgumentTypeCheck) { |
| 2391 if (element == backend.jsIntClass) { | 2395 if (element == backend.jsIntClass) { |
| 2392 checkInt(node.checkedInput, '!=='); | 2396 checkInt(node.checkedInput, '!=='); |
| 2393 } else { | 2397 } else { |
| 2394 assert(element == backend.jsNumberClass); | 2398 assert(element == backend.jsNumberClass); |
| 2395 checkNum(node.checkedInput, '!=='); | 2399 checkNum(node.checkedInput, '!=='); |
| 2396 } | 2400 } |
| 2397 js.Expression test = pop(); | 2401 js.Expression test = pop(); |
| 2398 js.Block oldContainer = currentContainer; | 2402 js.Block oldContainer = currentContainer; |
| (...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2963 if (leftType.canBeNull() && rightType.canBeNull()) { | 2967 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 2964 if (left.isConstantNull() || right.isConstantNull() || | 2968 if (left.isConstantNull() || right.isConstantNull() || |
| 2965 (leftType.isPrimitive() && leftType == rightType)) { | 2969 (leftType.isPrimitive() && leftType == rightType)) { |
| 2966 return '=='; | 2970 return '=='; |
| 2967 } | 2971 } |
| 2968 return null; | 2972 return null; |
| 2969 } else { | 2973 } else { |
| 2970 return '==='; | 2974 return '==='; |
| 2971 } | 2975 } |
| 2972 } | 2976 } |
| OLD | NEW |