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