| 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 js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
| 9 * from the given element. | 9 * from the given element. |
| 10 */ | 10 */ |
| (...skipping 1306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1317 | 1317 |
| 1318 emitClassConstructor(classElement, builder); | 1318 emitClassConstructor(classElement, builder); |
| 1319 emitSuper(superName, builder); | 1319 emitSuper(superName, builder); |
| 1320 emitClassFields(classElement, builder, | 1320 emitClassFields(classElement, builder, |
| 1321 superClass: superName, classIsNative: false); | 1321 superClass: superName, classIsNative: false); |
| 1322 emitClassGettersSetters(classElement, builder); | 1322 emitClassGettersSetters(classElement, builder); |
| 1323 emitInstanceMembers(classElement, builder); | 1323 emitInstanceMembers(classElement, builder); |
| 1324 | 1324 |
| 1325 jsAst.Expression init = | 1325 jsAst.Expression init = |
| 1326 js[classesCollector][className].assign(builder.toObjectInitializer()); | 1326 js[classesCollector][className].assign(builder.toObjectInitializer()); |
| 1327 buffer.add(jsAst.prettyPrint(init.toStatement(), compiler)); | 1327 buffer.add(jsAst.prettyPrint(init, compiler)); |
| 1328 buffer.add(n); | 1328 buffer.add('$N$n'); |
| 1329 } | 1329 } |
| 1330 | 1330 |
| 1331 bool get getterAndSetterCanBeImplementedByFieldSpec => true; | 1331 bool get getterAndSetterCanBeImplementedByFieldSpec => true; |
| 1332 | 1332 |
| 1333 int _selectorRank(Selector selector) { | 1333 int _selectorRank(Selector selector) { |
| 1334 int arity = selector.argumentCount * 3; | 1334 int arity = selector.argumentCount * 3; |
| 1335 if (selector.isGetter()) return arity + 2; | 1335 if (selector.isGetter()) return arity + 2; |
| 1336 if (selector.isSetter()) return arity + 1; | 1336 if (selector.isSetter()) return arity + 1; |
| 1337 return arity; | 1337 return arity; |
| 1338 } | 1338 } |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1597 // Reset the map. | 1597 // Reset the map. |
| 1598 buffer.add("$classesCollector$_=$_{}$N"); | 1598 buffer.add("$classesCollector$_=$_{}$N"); |
| 1599 } | 1599 } |
| 1600 } | 1600 } |
| 1601 | 1601 |
| 1602 void emitStaticFunction(CodeBuffer buffer, | 1602 void emitStaticFunction(CodeBuffer buffer, |
| 1603 String name, | 1603 String name, |
| 1604 jsAst.Expression functionExpression) { | 1604 jsAst.Expression functionExpression) { |
| 1605 jsAst.Expression assignment = | 1605 jsAst.Expression assignment = |
| 1606 js[isolateProperties][name].assign(functionExpression); | 1606 js[isolateProperties][name].assign(functionExpression); |
| 1607 buffer.add(jsAst.prettyPrint(assignment.toStatement(), compiler)); | 1607 buffer.add(jsAst.prettyPrint(assignment, compiler)); |
| 1608 buffer.add(n); | 1608 buffer.add('$N$n'); |
| 1609 } | 1609 } |
| 1610 | 1610 |
| 1611 void emitStaticFunctions(CodeBuffer eagerBuffer) { | 1611 void emitStaticFunctions(CodeBuffer eagerBuffer) { |
| 1612 bool isStaticFunction(Element element) => | 1612 bool isStaticFunction(Element element) => |
| 1613 !element.isInstanceMember() && !element.isField(); | 1613 !element.isInstanceMember() && !element.isField(); |
| 1614 | 1614 |
| 1615 Iterable<Element> elements = | 1615 Iterable<Element> elements = |
| 1616 backend.generatedCode.keys.where(isStaticFunction); | 1616 backend.generatedCode.keys.where(isStaticFunction); |
| 1617 Set<Element> pendingElementsWithBailouts = | 1617 Set<Element> pendingElementsWithBailouts = |
| 1618 backend.generatedBailoutCode.keys | 1618 backend.generatedBailoutCode.keys |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1656 String staticName = namer.getName(element); | 1656 String staticName = namer.getName(element); |
| 1657 String invocationName = namer.instanceMethodName(callElement); | 1657 String invocationName = namer.instanceMethodName(callElement); |
| 1658 String fieldAccess = '$isolateProperties.$staticName'; | 1658 String fieldAccess = '$isolateProperties.$staticName'; |
| 1659 buffer.add("$fieldAccess.$invocationName$_=$_$fieldAccess$N"); | 1659 buffer.add("$fieldAccess.$invocationName$_=$_$fieldAccess$N"); |
| 1660 | 1660 |
| 1661 addParameterStubs(callElement, (String name, jsAst.Expression value) { | 1661 addParameterStubs(callElement, (String name, jsAst.Expression value) { |
| 1662 jsAst.Expression assignment = | 1662 jsAst.Expression assignment = |
| 1663 js[isolateProperties][staticName][name].assign(value); | 1663 js[isolateProperties][staticName][name].assign(value); |
| 1664 buffer.add( | 1664 buffer.add( |
| 1665 jsAst.prettyPrint(assignment.toStatement(), compiler)); | 1665 jsAst.prettyPrint(assignment.toStatement(), compiler)); |
| 1666 buffer.add('$N'); |
| 1666 }); | 1667 }); |
| 1667 | 1668 |
| 1668 // If a static function is used as a closure we need to add its name | 1669 // If a static function is used as a closure we need to add its name |
| 1669 // in case it is used in spawnFunction. | 1670 // in case it is used in spawnFunction. |
| 1670 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; | 1671 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; |
| 1671 buffer.add('$fieldAccess.$fieldName$_=$_"$staticName"$N'); | 1672 buffer.add('$fieldAccess.$fieldName$_=$_"$staticName"$N'); |
| 1672 getTypedefChecksOn(element.computeType(compiler)).forEach( | 1673 getTypedefChecksOn(element.computeType(compiler)).forEach( |
| 1673 (Element typedef) { | 1674 (Element typedef) { |
| 1674 String operator = namer.operatorIs(typedef); | 1675 String operator = namer.operatorIs(typedef); |
| 1675 buffer.add('$fieldAccess.$operator$_=${_}true$N'); | 1676 buffer.add('$fieldAccess.$operator$_=${_}true$N'); |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1797 | 1798 |
| 1798 addParameterStubs(callElement, boundClosureBuilder.addProperty); | 1799 addParameterStubs(callElement, boundClosureBuilder.addProperty); |
| 1799 typedefChecks.forEach((Element typedef) { | 1800 typedefChecks.forEach((Element typedef) { |
| 1800 String operator = namer.operatorIs(typedef); | 1801 String operator = namer.operatorIs(typedef); |
| 1801 boundClosureBuilder.addProperty(operator, new jsAst.LiteralBool(true)); | 1802 boundClosureBuilder.addProperty(operator, new jsAst.LiteralBool(true)); |
| 1802 }); | 1803 }); |
| 1803 | 1804 |
| 1804 jsAst.Expression init = | 1805 jsAst.Expression init = |
| 1805 js[classesCollector][mangledName].assign( | 1806 js[classesCollector][mangledName].assign( |
| 1806 boundClosureBuilder.toObjectInitializer()); | 1807 boundClosureBuilder.toObjectInitializer()); |
| 1807 boundClosureBuffer.add(jsAst.prettyPrint(init.toStatement(), compiler)); | 1808 boundClosureBuffer.add(jsAst.prettyPrint(init, compiler)); |
| 1809 boundClosureBuffer.add("$N"); |
| 1808 | 1810 |
| 1809 closureClass = namer.isolateAccess(closureClassElement); | 1811 closureClass = namer.isolateAccess(closureClassElement); |
| 1810 | 1812 |
| 1811 // Cache it. | 1813 // Cache it. |
| 1812 if (canBeShared) { | 1814 if (canBeShared) { |
| 1813 cache[parameterCount] = closureClass; | 1815 cache[parameterCount] = closureClass; |
| 1814 } | 1816 } |
| 1815 } | 1817 } |
| 1816 | 1818 |
| 1817 // And finally the getter. | 1819 // And finally the getter. |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1905 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { | 1907 void emitStaticNonFinalFieldInitializations(CodeBuffer buffer) { |
| 1906 ConstantHandler handler = compiler.constantHandler; | 1908 ConstantHandler handler = compiler.constantHandler; |
| 1907 Iterable<VariableElement> staticNonFinalFields = | 1909 Iterable<VariableElement> staticNonFinalFields = |
| 1908 handler.getStaticNonFinalFieldsForEmission(); | 1910 handler.getStaticNonFinalFieldsForEmission(); |
| 1909 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { | 1911 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { |
| 1910 compiler.withCurrentElement(element, () { | 1912 compiler.withCurrentElement(element, () { |
| 1911 Constant initialValue = handler.getInitialValueFor(element); | 1913 Constant initialValue = handler.getInitialValueFor(element); |
| 1912 jsAst.Expression init = | 1914 jsAst.Expression init = |
| 1913 js[isolateProperties][namer.getName(element)].assign( | 1915 js[isolateProperties][namer.getName(element)].assign( |
| 1914 constantEmitter.referenceInInitializationContext(initialValue)); | 1916 constantEmitter.referenceInInitializationContext(initialValue)); |
| 1915 buffer.add(jsAst.prettyPrint(init.toStatement(), compiler)); | 1917 buffer.add(jsAst.prettyPrint(init, compiler)); |
| 1918 buffer.add('$N'); |
| 1916 }); | 1919 }); |
| 1917 } | 1920 } |
| 1918 } | 1921 } |
| 1919 | 1922 |
| 1920 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { | 1923 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { |
| 1921 ConstantHandler handler = compiler.constantHandler; | 1924 ConstantHandler handler = compiler.constantHandler; |
| 1922 List<VariableElement> lazyFields = | 1925 List<VariableElement> lazyFields = |
| 1923 handler.getLazilyInitializedFieldsForEmission(); | 1926 handler.getLazilyInitializedFieldsForEmission(); |
| 1924 if (!lazyFields.isEmpty) { | 1927 if (!lazyFields.isEmpty) { |
| 1925 needsLazyInitializer = true; | 1928 needsLazyInitializer = true; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1936 arguments.add(js[isolateProperties]); | 1939 arguments.add(js[isolateProperties]); |
| 1937 arguments.add(js.string(element.name.slowToString())); | 1940 arguments.add(js.string(element.name.slowToString())); |
| 1938 arguments.add(js.string(namer.getName(element))); | 1941 arguments.add(js.string(namer.getName(element))); |
| 1939 arguments.add(js.string(namer.getLazyInitializerName(element))); | 1942 arguments.add(js.string(namer.getLazyInitializerName(element))); |
| 1940 arguments.add(code); | 1943 arguments.add(code); |
| 1941 jsAst.Expression getter = buildLazyInitializedGetter(element); | 1944 jsAst.Expression getter = buildLazyInitializedGetter(element); |
| 1942 if (getter != null) { | 1945 if (getter != null) { |
| 1943 arguments.add(getter); | 1946 arguments.add(getter); |
| 1944 } | 1947 } |
| 1945 jsAst.Expression init = js[lazyInitializerName](arguments); | 1948 jsAst.Expression init = js[lazyInitializerName](arguments); |
| 1946 buffer.add(jsAst.prettyPrint(init.toStatement(), compiler)); | 1949 buffer.add(jsAst.prettyPrint(init, compiler)); |
| 1950 buffer.add("$N"); |
| 1947 } | 1951 } |
| 1948 } | 1952 } |
| 1949 } | 1953 } |
| 1950 | 1954 |
| 1951 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { | 1955 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { |
| 1952 // Nothing to do, the 'lazy' function will create the getter. | 1956 // Nothing to do, the 'lazy' function will create the getter. |
| 1953 return null; | 1957 return null; |
| 1954 } | 1958 } |
| 1955 | 1959 |
| 1956 void emitCompileTimeConstants(CodeBuffer buffer) { | 1960 void emitCompileTimeConstants(CodeBuffer buffer) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1967 // The name is null when the constant is already a JS constant. | 1971 // The name is null when the constant is already a JS constant. |
| 1968 // TODO(floitsch): every constant should be registered, so that we can | 1972 // TODO(floitsch): every constant should be registered, so that we can |
| 1969 // share the ones that take up too much space (like some strings). | 1973 // share the ones that take up too much space (like some strings). |
| 1970 if (name == null) continue; | 1974 if (name == null) continue; |
| 1971 if (!addedMakeConstantList && constant.isList()) { | 1975 if (!addedMakeConstantList && constant.isList()) { |
| 1972 addedMakeConstantList = true; | 1976 addedMakeConstantList = true; |
| 1973 emitMakeConstantList(buffer); | 1977 emitMakeConstantList(buffer); |
| 1974 } | 1978 } |
| 1975 jsAst.Expression init = js[isolateProperties][name].assign( | 1979 jsAst.Expression init = js[isolateProperties][name].assign( |
| 1976 constantInitializerExpression(constant)); | 1980 constantInitializerExpression(constant)); |
| 1977 buffer.add(jsAst.prettyPrint(init.toStatement(), compiler)); | 1981 buffer.add(jsAst.prettyPrint(init, compiler)); |
| 1982 buffer.add('$N'); |
| 1978 } | 1983 } |
| 1979 } | 1984 } |
| 1980 | 1985 |
| 1981 void emitMakeConstantList(CodeBuffer buffer) { | 1986 void emitMakeConstantList(CodeBuffer buffer) { |
| 1982 buffer.add(namer.isolateName); | 1987 buffer.add(namer.isolateName); |
| 1983 buffer.add(r'''.makeConstantList = function(list) { | 1988 buffer.add(r'''.makeConstantList = function(list) { |
| 1984 list.immutable$list = true; | 1989 list.immutable$list = true; |
| 1985 list.fixed$length = true; | 1990 list.fixed$length = true; |
| 1986 return list; | 1991 return list; |
| 1987 }; | 1992 }; |
| (...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2308 block.statements.add(buildInterceptorCheck(backend.jsBoolClass)); | 2313 block.statements.add(buildInterceptorCheck(backend.jsBoolClass)); |
| 2309 } | 2314 } |
| 2310 // TODO(ahe): It might be faster to check for Array before | 2315 // TODO(ahe): It might be faster to check for Array before |
| 2311 // function and bool. | 2316 // function and bool. |
| 2312 if (hasArray) { | 2317 if (hasArray) { |
| 2313 block.statements.add(buildInterceptorCheck(backend.jsArrayClass)); | 2318 block.statements.add(buildInterceptorCheck(backend.jsArrayClass)); |
| 2314 } | 2319 } |
| 2315 block.statements.add(js.return_(js[objectName]['prototype'])); | 2320 block.statements.add(js.return_(js[objectName]['prototype'])); |
| 2316 | 2321 |
| 2317 buffer.add(jsAst.prettyPrint( | 2322 buffer.add(jsAst.prettyPrint( |
| 2318 js[isolateProperties][key].assign( | 2323 js[isolateProperties][key].assign(js.fun(['receiver'], block)), |
| 2319 js.fun(['receiver'], block)).toStatement(), | |
| 2320 compiler)); | 2324 compiler)); |
| 2325 buffer.add(N); |
| 2321 } | 2326 } |
| 2322 | 2327 |
| 2323 /** | 2328 /** |
| 2324 * Emit all versions of the [:getInterceptor:] method. | 2329 * Emit all versions of the [:getInterceptor:] method. |
| 2325 */ | 2330 */ |
| 2326 void emitGetInterceptorMethods(CodeBuffer buffer) { | 2331 void emitGetInterceptorMethods(CodeBuffer buffer) { |
| 2327 // If no class needs to be intercepted, just return. | 2332 // If no class needs to be intercepted, just return. |
| 2328 if (backend.objectInterceptorClass == null) return; | 2333 if (backend.objectInterceptorClass == null) return; |
| 2329 String objectName = namer.isolateAccess(backend.objectInterceptorClass); | 2334 String objectName = namer.isolateAccess(backend.objectInterceptorClass); |
| 2330 var specializedGetInterceptors = backend.specializedGetInterceptors; | 2335 var specializedGetInterceptors = backend.specializedGetInterceptors; |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2541 String invocationName = backend.namer.invocationName(selector); | 2546 String invocationName = backend.namer.invocationName(selector); |
| 2542 body.add(js.return_( | 2547 body.add(js.return_( |
| 2543 js[isolateProperties][getInterceptorName]('receiver')[invocationName]( | 2548 js[isolateProperties][getInterceptorName]('receiver')[invocationName]( |
| 2544 arguments))); | 2549 arguments))); |
| 2545 | 2550 |
| 2546 jsAst.Fun function = js.fun(parameters, body); | 2551 jsAst.Fun function = js.fun(parameters, body); |
| 2547 | 2552 |
| 2548 jsAst.PropertyAccess property = | 2553 jsAst.PropertyAccess property = |
| 2549 js[isolateProperties][name]; | 2554 js[isolateProperties][name]; |
| 2550 | 2555 |
| 2551 buffer.add(jsAst.prettyPrint(property.assign(function).toStatement(), | 2556 buffer.add(jsAst.prettyPrint(property.assign(function), compiler)); |
| 2552 compiler)); | 2557 buffer.add(N); |
| 2553 } | 2558 } |
| 2554 } | 2559 } |
| 2555 | 2560 |
| 2556 void emitInitFunction(CodeBuffer buffer) { | 2561 void emitInitFunction(CodeBuffer buffer) { |
| 2557 jsAst.Fun fun = js.fun([], [ | 2562 jsAst.Fun fun = js.fun([], [ |
| 2558 js['$isolateProperties = {}'], | 2563 js['$isolateProperties = {}'], |
| 2559 ] | 2564 ] |
| 2560 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) | 2565 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) |
| 2561 ..addAll(buildLazyInitializerFunctionIfNecessary()) | 2566 ..addAll(buildLazyInitializerFunctionIfNecessary()) |
| 2562 ..addAll(buildFinishIsolateConstructor()) | 2567 ..addAll(buildFinishIsolateConstructor()) |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2701 """; | 2706 """; |
| 2702 const String HOOKS_API_USAGE = """ | 2707 const String HOOKS_API_USAGE = """ |
| 2703 // The code supports the following hooks: | 2708 // The code supports the following hooks: |
| 2704 // dartPrint(message) - if this function is defined it is called | 2709 // dartPrint(message) - if this function is defined it is called |
| 2705 // instead of the Dart [print] method. | 2710 // instead of the Dart [print] method. |
| 2706 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2711 // dartMainRunner(main) - if this function is defined, the Dart [main] |
| 2707 // method will not be invoked directly. | 2712 // method will not be invoked directly. |
| 2708 // Instead, a closure that will invoke [main] is | 2713 // Instead, a closure that will invoke [main] is |
| 2709 // passed to [dartMainRunner]. | 2714 // passed to [dartMainRunner]. |
| 2710 """; | 2715 """; |
| OLD | NEW |