| 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 library js_backend.backend; | 5 library js_backend.backend; |
| 6 | 6 |
| 7 import 'dart:async' show Future; | 7 import 'dart:async' show Future; |
| 8 | 8 |
| 9 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; | 9 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; |
| 10 | 10 |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 534 /// Builds kernel representation for the program. | 534 /// Builds kernel representation for the program. |
| 535 KernelTask kernelTask; | 535 KernelTask kernelTask; |
| 536 | 536 |
| 537 JavaScriptConstantTask constantCompilerTask; | 537 JavaScriptConstantTask constantCompilerTask; |
| 538 | 538 |
| 539 JavaScriptImpactTransformer impactTransformer; | 539 JavaScriptImpactTransformer impactTransformer; |
| 540 | 540 |
| 541 PatchResolverTask patchResolverTask; | 541 PatchResolverTask patchResolverTask; |
| 542 | 542 |
| 543 bool enabledNoSuchMethod = false; | 543 bool enabledNoSuchMethod = false; |
| 544 bool _noSuchMethodEnabledForCodegen = false; |
| 544 | 545 |
| 545 SourceInformationStrategy sourceInformationStrategy; | 546 SourceInformationStrategy sourceInformationStrategy; |
| 546 | 547 |
| 547 JavaScriptBackendSerialization serialization; | 548 JavaScriptBackendSerialization serialization; |
| 548 | 549 |
| 549 StagedWorldImpactBuilder constantImpactsForResolution = | 550 StagedWorldImpactBuilder constantImpactsForResolution = |
| 550 new StagedWorldImpactBuilder(); | 551 new StagedWorldImpactBuilder(); |
| 551 | 552 |
| 552 StagedWorldImpactBuilder constantImpactsForCodegen = | 553 StagedWorldImpactBuilder constantImpactsForCodegen = |
| 553 new StagedWorldImpactBuilder(); | 554 new StagedWorldImpactBuilder(); |
| (...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1299 rti.computeClassesNeedingRti( | 1300 rti.computeClassesNeedingRti( |
| 1300 compiler.enqueuer.resolution.universe, closedWorld); | 1301 compiler.enqueuer.resolution.universe, closedWorld); |
| 1301 _registeredMetadata.clear(); | 1302 _registeredMetadata.clear(); |
| 1302 } | 1303 } |
| 1303 | 1304 |
| 1304 onTypeInferenceComplete() { | 1305 onTypeInferenceComplete() { |
| 1305 super.onTypeInferenceComplete(); | 1306 super.onTypeInferenceComplete(); |
| 1306 noSuchMethodRegistry.onTypeInferenceComplete(); | 1307 noSuchMethodRegistry.onTypeInferenceComplete(); |
| 1307 } | 1308 } |
| 1308 | 1309 |
| 1310 /// Called to register that an instantiated generic class has a call method. |
| 1311 /// Any backend specific [WorldImpact] of this is returned. |
| 1312 /// |
| 1313 /// Note: The [callMethod] is registered even thought it doesn't reference |
| 1314 /// the type variables. |
| 1309 WorldImpact registerCallMethodWithFreeTypeVariables(Element callMethod, | 1315 WorldImpact registerCallMethodWithFreeTypeVariables(Element callMethod, |
| 1310 {bool forResolution}) { | 1316 {bool forResolution}) { |
| 1311 if (forResolution || methodNeedsRti(callMethod)) { | 1317 if (forResolution || methodNeedsRti(callMethod)) { |
| 1312 return _registerComputeSignature(); | 1318 return _registerComputeSignature(); |
| 1313 } | 1319 } |
| 1314 return const WorldImpact(); | 1320 return const WorldImpact(); |
| 1315 } | 1321 } |
| 1316 | 1322 |
| 1317 WorldImpact registerClosureWithFreeTypeVariables(Element closure, | 1323 WorldImpact registerClosureWithFreeTypeVariables(Element closure, |
| 1318 {bool forResolution}) { | 1324 {bool forResolution}) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1381 } | 1387 } |
| 1382 } | 1388 } |
| 1383 } | 1389 } |
| 1384 reporter.reportErrorMessage( | 1390 reporter.reportErrorMessage( |
| 1385 node, MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); | 1391 node, MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); |
| 1386 } | 1392 } |
| 1387 // No native behavior for this call. | 1393 // No native behavior for this call. |
| 1388 return null; | 1394 return null; |
| 1389 } | 1395 } |
| 1390 | 1396 |
| 1391 WorldImpact enableNoSuchMethod() { | 1397 WorldImpact computeNoSuchMethodImpact() { |
| 1392 return impactTransformer.createImpactFor(impacts.noSuchMethodSupport); | 1398 return impactTransformer.createImpactFor(impacts.noSuchMethodSupport); |
| 1393 } | 1399 } |
| 1394 | 1400 |
| 1395 WorldImpact enableIsolateSupport({bool forResolution}) { | 1401 WorldImpact enableIsolateSupport({bool forResolution}) { |
| 1396 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); | 1402 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); |
| 1397 // TODO(floitsch): We should also ensure that the class IsolateMessage is | 1403 // TODO(floitsch): We should also ensure that the class IsolateMessage is |
| 1398 // instantiated. Currently, just enabling isolate support works. | 1404 // instantiated. Currently, just enabling isolate support works. |
| 1399 if (compiler.mainFunction != null) { | 1405 if (compiler.mainFunction != null) { |
| 1400 // The JavaScript backend implements [Isolate.spawn] by looking up | 1406 // The JavaScript backend implements [Isolate.spawn] by looking up |
| 1401 // top-level functions by name. So all top-level function tear-off | 1407 // top-level functions by name. So all top-level function tear-off |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1780 } | 1786 } |
| 1781 } | 1787 } |
| 1782 } else if (element == helpers.requiresPreambleMarker) { | 1788 } else if (element == helpers.requiresPreambleMarker) { |
| 1783 requiresPreamble = true; | 1789 requiresPreamble = true; |
| 1784 } else if (element == helpers.invokeOnMethod && forResolution) { | 1790 } else if (element == helpers.invokeOnMethod && forResolution) { |
| 1785 hasInvokeOnSupport = true; | 1791 hasInvokeOnSupport = true; |
| 1786 } | 1792 } |
| 1787 customElementsAnalysis.registerStaticUse(element, | 1793 customElementsAnalysis.registerStaticUse(element, |
| 1788 forResolution: forResolution); | 1794 forResolution: forResolution); |
| 1789 | 1795 |
| 1796 if (element.isFunction && element.isInstanceMember) { |
| 1797 MemberElement function = element; |
| 1798 ClassElement cls = function.enclosingClass; |
| 1799 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { |
| 1800 worldImpact.addImpact(registerCallMethodWithFreeTypeVariables(function, |
| 1801 forResolution: forResolution)); |
| 1802 } |
| 1803 } |
| 1790 if (forResolution) { | 1804 if (forResolution) { |
| 1791 if (element.isFunction && element.isInstanceMember) { | |
| 1792 MemberElement function = element; | |
| 1793 ClassElement cls = function.enclosingClass; | |
| 1794 if (function.name == Identifiers.call && !cls.typeVariables.isEmpty) { | |
| 1795 worldImpact.addImpact(registerCallMethodWithFreeTypeVariables( | |
| 1796 function, | |
| 1797 forResolution: true)); | |
| 1798 } | |
| 1799 } | |
| 1800 // Enable isolate support if we start using something from the isolate | 1805 // Enable isolate support if we start using something from the isolate |
| 1801 // library, or timers for the async library. We exclude constant fields, | 1806 // library, or timers for the async library. We exclude constant fields, |
| 1802 // which are ending here because their initializing expression is | 1807 // which are ending here because their initializing expression is |
| 1803 // compiled. | 1808 // compiled. |
| 1804 LibraryElement library = element.library; | 1809 LibraryElement library = element.library; |
| 1805 if (!hasIsolateSupport && !(element.isField && element.isConst)) { | 1810 if (!hasIsolateSupport && !(element.isField && element.isConst)) { |
| 1806 Uri uri = library.canonicalUri; | 1811 Uri uri = library.canonicalUri; |
| 1807 if (uri == Uris.dart_isolate) { | 1812 if (uri == Uris.dart_isolate) { |
| 1808 hasIsolateSupport = true; | 1813 hasIsolateSupport = true; |
| 1809 worldImpact | 1814 worldImpact |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1824 // Enable runtime type support if we discover a getter called | 1829 // Enable runtime type support if we discover a getter called |
| 1825 // runtimeType. We have to enable runtime type before hitting the | 1830 // runtimeType. We have to enable runtime type before hitting the |
| 1826 // codegen, so that constructors know whether they need to generate code | 1831 // codegen, so that constructors know whether they need to generate code |
| 1827 // for runtime type. | 1832 // for runtime type. |
| 1828 hasRuntimeTypeSupport = true; | 1833 hasRuntimeTypeSupport = true; |
| 1829 // TODO(ahe): Record precise dependency here. | 1834 // TODO(ahe): Record precise dependency here. |
| 1830 worldImpact.addImpact(registerRuntimeType()); | 1835 worldImpact.addImpact(registerRuntimeType()); |
| 1831 } else if (compiler.commonElements.isFunctionApplyMethod(element)) { | 1836 } else if (compiler.commonElements.isFunctionApplyMethod(element)) { |
| 1832 hasFunctionApplySupport = true; | 1837 hasFunctionApplySupport = true; |
| 1833 } | 1838 } |
| 1839 } else { |
| 1840 // TODO(sigmund): add other missing dependencies (internals, selectors |
| 1841 // enqueued after allocations). |
| 1842 compiler.dumpInfoTask.registerDependency(element); |
| 1834 } | 1843 } |
| 1835 return worldImpact; | 1844 return worldImpact; |
| 1836 } | 1845 } |
| 1837 | 1846 |
| 1838 /// Called when [:const Symbol(name):] is seen. | 1847 /// Called when [:const Symbol(name):] is seen. |
| 1839 void registerConstSymbol(String name) { | 1848 void registerConstSymbol(String name) { |
| 1840 symbolsUsed.add(name); | 1849 symbolsUsed.add(name); |
| 1841 if (name.endsWith('=')) { | 1850 if (name.endsWith('=')) { |
| 1842 symbolsUsed.add(name.substring(0, name.length - 1)); | 1851 symbolsUsed.add(name.substring(0, name.length - 1)); |
| 1843 } | 1852 } |
| (...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2230 // | 2239 // |
| 2231 // Return early if any elements are added to avoid counting the elements as | 2240 // Return early if any elements are added to avoid counting the elements as |
| 2232 // due to mirrors. | 2241 // due to mirrors. |
| 2233 enqueuer.applyImpact(customElementsAnalysis.flush( | 2242 enqueuer.applyImpact(customElementsAnalysis.flush( |
| 2234 forResolution: enqueuer.isResolutionQueue)); | 2243 forResolution: enqueuer.isResolutionQueue)); |
| 2235 enqueuer.applyImpact( | 2244 enqueuer.applyImpact( |
| 2236 lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue)); | 2245 lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue)); |
| 2237 enqueuer.applyImpact( | 2246 enqueuer.applyImpact( |
| 2238 typeVariableHandler.flush(forResolution: enqueuer.isResolutionQueue)); | 2247 typeVariableHandler.flush(forResolution: enqueuer.isResolutionQueue)); |
| 2239 | 2248 |
| 2240 if (!enqueuer.queueIsEmpty) return false; | 2249 if (enqueuer.isResolutionQueue) { |
| 2241 | 2250 for (ClassElement cls in recentClasses) { |
| 2242 for (ClassElement cls in recentClasses) { | 2251 Element element = cls.lookupLocalMember(Identifiers.noSuchMethod_); |
| 2243 Element element = cls.lookupLocalMember(Identifiers.noSuchMethod_); | 2252 if (element != null && element.isInstanceMember && element.isFunction) { |
| 2244 if (element != null && element.isInstanceMember && element.isFunction) { | 2253 registerNoSuchMethod(element); |
| 2245 registerNoSuchMethod(element); | 2254 } |
| 2246 } | 2255 } |
| 2247 } | 2256 } |
| 2248 noSuchMethodRegistry.onQueueEmpty(); | 2257 noSuchMethodRegistry.onQueueEmpty(); |
| 2249 if (!enabledNoSuchMethod && | 2258 if (enqueuer.isResolutionQueue) { |
| 2250 (noSuchMethodRegistry.hasThrowingNoSuchMethod || | 2259 if (!enabledNoSuchMethod && |
| 2251 noSuchMethodRegistry.hasComplexNoSuchMethod)) { | 2260 (noSuchMethodRegistry.hasThrowingNoSuchMethod || |
| 2252 enqueuer.applyImpact(enableNoSuchMethod()); | 2261 noSuchMethodRegistry.hasComplexNoSuchMethod)) { |
| 2253 enabledNoSuchMethod = true; | 2262 enqueuer.applyImpact(computeNoSuchMethodImpact()); |
| 2263 enabledNoSuchMethod = true; |
| 2264 } |
| 2265 } else { |
| 2266 if (enabledNoSuchMethod && !_noSuchMethodEnabledForCodegen) { |
| 2267 enqueuer.applyImpact(computeNoSuchMethodImpact()); |
| 2268 _noSuchMethodEnabledForCodegen = true; |
| 2269 } |
| 2254 } | 2270 } |
| 2255 | 2271 |
| 2272 if (!enqueuer.queueIsEmpty) return false; |
| 2273 |
| 2256 if (compiler.options.useKernel && compiler.mainApp != null) { | 2274 if (compiler.options.useKernel && compiler.mainApp != null) { |
| 2257 kernelTask.buildKernelIr(); | 2275 kernelTask.buildKernelIr(); |
| 2258 } | 2276 } |
| 2259 | 2277 |
| 2260 if (compiler.options.hasIncrementalSupport && | 2278 if (compiler.options.hasIncrementalSupport && |
| 2261 !hasIncrementalTearOffSupport) { | 2279 !hasIncrementalTearOffSupport) { |
| 2262 // Always enable tear-off closures during incremental compilation. | 2280 // Always enable tear-off closures during incremental compilation. |
| 2263 Element element = helpers.closureFromTearOff; | 2281 Element element = helpers.closureFromTearOff; |
| 2264 if (element != null) { | 2282 if (element != null) { |
| 2265 enqueuer.applyImpact( | 2283 enqueuer.applyImpact( |
| (...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3246 @override | 3264 @override |
| 3247 bool isInterceptorClass(ClassElement cls) { | 3265 bool isInterceptorClass(ClassElement cls) { |
| 3248 return helpers.backend.isInterceptorClass(cls); | 3266 return helpers.backend.isInterceptorClass(cls); |
| 3249 } | 3267 } |
| 3250 | 3268 |
| 3251 @override | 3269 @override |
| 3252 bool isNative(Element element) { | 3270 bool isNative(Element element) { |
| 3253 return helpers.backend.isNative(element); | 3271 return helpers.backend.isNative(element); |
| 3254 } | 3272 } |
| 3255 } | 3273 } |
| OLD | NEW |