| 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 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 | 330 |
| 331 /// If [true], the compiler will emit code that logs whenever a method is | 331 /// If [true], the compiler will emit code that logs whenever a method is |
| 332 /// called. When TRACE_METHOD is 'console' this will be logged | 332 /// called. When TRACE_METHOD is 'console' this will be logged |
| 333 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the | 333 /// directly in the JavaScript console. When TRACE_METHOD is 'post' the |
| 334 /// information will be sent to a server via a POST request. | 334 /// information will be sent to a server via a POST request. |
| 335 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); | 335 static const String TRACE_METHOD = const String.fromEnvironment('traceCalls'); |
| 336 static const bool TRACE_CALLS = | 336 static const bool TRACE_CALLS = |
| 337 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; | 337 TRACE_METHOD == 'post' || TRACE_METHOD == 'console'; |
| 338 MethodElement traceHelper; | 338 MethodElement traceHelper; |
| 339 | 339 |
| 340 TypeMask get stringType => compiler.commonMasks.stringType; | 340 TypeMask get stringType => compiler.closedWorld.commonMasks.stringType; |
| 341 TypeMask get doubleType => compiler.commonMasks.doubleType; | 341 TypeMask get doubleType => compiler.closedWorld.commonMasks.doubleType; |
| 342 TypeMask get intType => compiler.commonMasks.intType; | 342 TypeMask get intType => compiler.closedWorld.commonMasks.intType; |
| 343 TypeMask get uint32Type => compiler.commonMasks.uint32Type; | 343 TypeMask get uint32Type => compiler.closedWorld.commonMasks.uint32Type; |
| 344 TypeMask get uint31Type => compiler.commonMasks.uint31Type; | 344 TypeMask get uint31Type => compiler.closedWorld.commonMasks.uint31Type; |
| 345 TypeMask get positiveIntType => compiler.commonMasks.positiveIntType; | 345 TypeMask get positiveIntType => |
| 346 TypeMask get numType => compiler.commonMasks.numType; | 346 compiler.closedWorld.commonMasks.positiveIntType; |
| 347 TypeMask get boolType => compiler.commonMasks.boolType; | 347 TypeMask get numType => compiler.closedWorld.commonMasks.numType; |
| 348 TypeMask get dynamicType => compiler.commonMasks.dynamicType; | 348 TypeMask get boolType => compiler.closedWorld.commonMasks.boolType; |
| 349 TypeMask get nullType => compiler.commonMasks.nullType; | 349 TypeMask get dynamicType => compiler.closedWorld.commonMasks.dynamicType; |
| 350 TypeMask get nullType => compiler.closedWorld.commonMasks.nullType; |
| 350 TypeMask get emptyType => const TypeMask.nonNullEmpty(); | 351 TypeMask get emptyType => const TypeMask.nonNullEmpty(); |
| 351 TypeMask get nonNullType => compiler.commonMasks.nonNullType; | 352 TypeMask get nonNullType => compiler.closedWorld.commonMasks.nonNullType; |
| 352 | 353 |
| 353 TypeMask _indexablePrimitiveTypeCache; | 354 TypeMask _indexablePrimitiveTypeCache; |
| 354 TypeMask get indexablePrimitiveType { | 355 TypeMask get indexablePrimitiveType { |
| 355 if (_indexablePrimitiveTypeCache == null) { | 356 if (_indexablePrimitiveTypeCache == null) { |
| 356 _indexablePrimitiveTypeCache = new TypeMask.nonNullSubtype( | 357 _indexablePrimitiveTypeCache = new TypeMask.nonNullSubtype( |
| 357 helpers.jsIndexableClass, compiler.closedWorld); | 358 helpers.jsIndexableClass, compiler.closedWorld); |
| 358 } | 359 } |
| 359 return _indexablePrimitiveTypeCache; | 360 return _indexablePrimitiveTypeCache; |
| 360 } | 361 } |
| 361 | 362 |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 | 513 |
| 513 /// True if a core-library function requires the preamble file to function. | 514 /// True if a core-library function requires the preamble file to function. |
| 514 bool requiresPreamble = false; | 515 bool requiresPreamble = false; |
| 515 | 516 |
| 516 /// True if the html library has been loaded. | 517 /// True if the html library has been loaded. |
| 517 bool htmlLibraryIsLoaded = false; | 518 bool htmlLibraryIsLoaded = false; |
| 518 | 519 |
| 519 /// True when we enqueue the loadLibrary code. | 520 /// True when we enqueue the loadLibrary code. |
| 520 bool isLoadLibraryFunctionResolved = false; | 521 bool isLoadLibraryFunctionResolved = false; |
| 521 | 522 |
| 523 /// `true` if access to [BackendHelpers.invokeOnMethod] is supported. |
| 524 bool hasInvokeOnSupport = false; |
| 525 |
| 522 /// List of constants from metadata. If metadata must be preserved, | 526 /// List of constants from metadata. If metadata must be preserved, |
| 523 /// these constants must be registered. | 527 /// these constants must be registered. |
| 524 final List<Dependency> metadataConstants = <Dependency>[]; | 528 final List<Dependency> metadataConstants = <Dependency>[]; |
| 525 | 529 |
| 526 /// Set of elements for which metadata has been registered as dependencies. | 530 /// Set of elements for which metadata has been registered as dependencies. |
| 527 final Set<Element> _registeredMetadata = new Set<Element>(); | 531 final Set<Element> _registeredMetadata = new Set<Element>(); |
| 528 | 532 |
| 529 /// List of elements that the user has requested for reflection. | 533 /// List of elements that the user has requested for reflection. |
| 530 final Set<Element> targetsUsed = new Set<Element>(); | 534 final Set<Element> targetsUsed = new Set<Element>(); |
| 531 | 535 |
| (...skipping 950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1482 | 1486 |
| 1483 enqueue(helpers.startRootIsolate); | 1487 enqueue(helpers.startRootIsolate); |
| 1484 enqueue(helpers.currentIsolate); | 1488 enqueue(helpers.currentIsolate); |
| 1485 enqueue(helpers.callInIsolate); | 1489 enqueue(helpers.callInIsolate); |
| 1486 } else { | 1490 } else { |
| 1487 enqueuer.addToWorkList(helpers.startRootIsolate); | 1491 enqueuer.addToWorkList(helpers.startRootIsolate); |
| 1488 } | 1492 } |
| 1489 } | 1493 } |
| 1490 | 1494 |
| 1491 bool classNeedsRti(ClassElement cls) { | 1495 bool classNeedsRti(ClassElement cls) { |
| 1492 if (compiler.enabledRuntimeType) return true; | 1496 if (compiler.resolverWorld.hasRuntimeTypeSupport) return true; |
| 1493 return rti.classesNeedingRti.contains(cls.declaration); | 1497 return rti.classesNeedingRti.contains(cls.declaration); |
| 1494 } | 1498 } |
| 1495 | 1499 |
| 1496 bool classNeedsRtiField(ClassElement cls) { | 1500 bool classNeedsRtiField(ClassElement cls) { |
| 1497 if (cls.rawType.typeArguments.isEmpty) return false; | 1501 if (cls.rawType.typeArguments.isEmpty) return false; |
| 1498 if (compiler.enabledRuntimeType) return true; | 1502 if (compiler.resolverWorld.hasRuntimeTypeSupport) return true; |
| 1499 return rti.classesNeedingRti.contains(cls.declaration); | 1503 return rti.classesNeedingRti.contains(cls.declaration); |
| 1500 } | 1504 } |
| 1501 | 1505 |
| 1502 bool isComplexNoSuchMethod(FunctionElement element) => | 1506 bool isComplexNoSuchMethod(FunctionElement element) => |
| 1503 noSuchMethodRegistry.isComplex(element); | 1507 noSuchMethodRegistry.isComplex(element); |
| 1504 | 1508 |
| 1505 bool isDefaultEqualityImplementation(Element element) { | 1509 bool isDefaultEqualityImplementation(Element element) { |
| 1506 assert(element.name == '=='); | 1510 assert(element.name == '=='); |
| 1507 ClassElement classElement = element.enclosingClass; | 1511 ClassElement classElement = element.enclosingClass; |
| 1508 return classElement == coreClasses.objectClass || | 1512 return classElement == coreClasses.objectClass || |
| 1509 classElement == helpers.jsInterceptorClass || | 1513 classElement == helpers.jsInterceptorClass || |
| 1510 classElement == helpers.jsNullClass; | 1514 classElement == helpers.jsNullClass; |
| 1511 } | 1515 } |
| 1512 | 1516 |
| 1513 bool methodNeedsRti(FunctionElement function) { | 1517 bool methodNeedsRti(FunctionElement function) { |
| 1514 return rti.methodsNeedingRti.contains(function) || | 1518 return rti.methodsNeedingRti.contains(function) || |
| 1515 compiler.enabledRuntimeType; | 1519 compiler.resolverWorld.hasRuntimeTypeSupport; |
| 1516 } | 1520 } |
| 1517 | 1521 |
| 1518 /// Enqueue [e] in [enqueuer]. | 1522 /// Enqueue [e] in [enqueuer]. |
| 1519 /// | 1523 /// |
| 1520 /// This method calls [registerBackendUse]. | 1524 /// This method calls [registerBackendUse]. |
| 1521 void enqueue(Enqueuer enqueuer, Element e) { | 1525 void enqueue(Enqueuer enqueuer, Element e) { |
| 1522 if (e == null) return; | 1526 if (e == null) return; |
| 1523 registerBackendUse(e); | 1527 registerBackendUse(e); |
| 1524 enqueuer.addToWorkList(e); | 1528 enqueuer.addToWorkList(e); |
| 1525 compiler.globalDependencies.registerDependency(e); | 1529 compiler.globalDependencies.registerDependency(e); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1564 for (ClassElement cls in impact.instantiatedClasses) { | 1568 for (ClassElement cls in impact.instantiatedClasses) { |
| 1565 enqueueClass(enqueuer, cls); | 1569 enqueueClass(enqueuer, cls); |
| 1566 } | 1570 } |
| 1567 for (BackendImpact otherImpact in impact.otherImpacts) { | 1571 for (BackendImpact otherImpact in impact.otherImpacts) { |
| 1568 enqueueImpact(enqueuer, otherImpact); | 1572 enqueueImpact(enqueuer, otherImpact); |
| 1569 } | 1573 } |
| 1570 } | 1574 } |
| 1571 | 1575 |
| 1572 CodegenEnqueuer get codegenEnqueuer => compiler.enqueuer.codegen; | 1576 CodegenEnqueuer get codegenEnqueuer => compiler.enqueuer.codegen; |
| 1573 | 1577 |
| 1574 CodegenEnqueuer createCodegenEnqueuer(Compiler compiler) { | 1578 CodegenEnqueuer createCodegenEnqueuer(CompilerTask task, Compiler compiler) { |
| 1575 return new CodegenEnqueuer(compiler, const TreeShakingEnqueuerStrategy()); | 1579 return new CodegenEnqueuer( |
| 1580 task, compiler, const TreeShakingEnqueuerStrategy()); |
| 1576 } | 1581 } |
| 1577 | 1582 |
| 1578 WorldImpact codegen(CodegenWorkItem work) { | 1583 WorldImpact codegen(CodegenWorkItem work) { |
| 1579 Element element = work.element; | 1584 Element element = work.element; |
| 1580 if (compiler.elementHasCompileTimeError(element)) { | 1585 if (compiler.elementHasCompileTimeError(element)) { |
| 1581 DiagnosticMessage message = | 1586 DiagnosticMessage message = |
| 1582 // If there's more than one error, the first is probably most | 1587 // If there's more than one error, the first is probably most |
| 1583 // informative, as the following errors may be side-effects of the | 1588 // informative, as the following errors may be side-effects of the |
| 1584 // first error. | 1589 // first error. |
| 1585 compiler.elementsWithCompileTimeErrors[element].first; | 1590 compiler.elementsWithCompileTimeErrors[element].first; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1639 function = function.withSourceInformation( | 1644 function = function.withSourceInformation( |
| 1640 sourceInformationStrategy.buildSourceMappedMarker()); | 1645 sourceInformationStrategy.buildSourceMappedMarker()); |
| 1641 } | 1646 } |
| 1642 generatedCode[element] = function; | 1647 generatedCode[element] = function; |
| 1643 WorldImpact worldImpact = | 1648 WorldImpact worldImpact = |
| 1644 impactTransformer.transformCodegenImpact(work.registry.worldImpact); | 1649 impactTransformer.transformCodegenImpact(work.registry.worldImpact); |
| 1645 compiler.dumpInfoTask.registerImpact(element, worldImpact); | 1650 compiler.dumpInfoTask.registerImpact(element, worldImpact); |
| 1646 return worldImpact; | 1651 return worldImpact; |
| 1647 } | 1652 } |
| 1648 | 1653 |
| 1649 native.NativeEnqueuer nativeResolutionEnqueuer(Enqueuer world) { | 1654 native.NativeEnqueuer nativeResolutionEnqueuer() { |
| 1650 return new native.NativeResolutionEnqueuer(compiler); | 1655 return new native.NativeResolutionEnqueuer(compiler); |
| 1651 } | 1656 } |
| 1652 | 1657 |
| 1653 native.NativeEnqueuer nativeCodegenEnqueuer(Enqueuer world) { | 1658 native.NativeEnqueuer nativeCodegenEnqueuer() { |
| 1654 return new native.NativeCodegenEnqueuer(compiler, emitter); | 1659 return new native.NativeCodegenEnqueuer(compiler, emitter); |
| 1655 } | 1660 } |
| 1656 | 1661 |
| 1657 ClassElement defaultSuperclass(ClassElement element) { | 1662 ClassElement defaultSuperclass(ClassElement element) { |
| 1658 if (isJsInterop(element)) { | 1663 if (isJsInterop(element)) { |
| 1659 return helpers.jsJavaScriptObjectClass; | 1664 return helpers.jsJavaScriptObjectClass; |
| 1660 } | 1665 } |
| 1661 // Native classes inherit from Interceptor. | 1666 // Native classes inherit from Interceptor. |
| 1662 return isNative(element) | 1667 return isNative(element) |
| 1663 ? helpers.jsInterceptorClass | 1668 ? helpers.jsInterceptorClass |
| (...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2335 return staticFields; | 2340 return staticFields; |
| 2336 } | 2341 } |
| 2337 | 2342 |
| 2338 /// Called when [enqueuer] is empty, but before it is closed. | 2343 /// Called when [enqueuer] is empty, but before it is closed. |
| 2339 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) { | 2344 bool onQueueEmpty(Enqueuer enqueuer, Iterable<ClassElement> recentClasses) { |
| 2340 // Add elements used synthetically, that is, through features rather than | 2345 // Add elements used synthetically, that is, through features rather than |
| 2341 // syntax, for instance custom elements. | 2346 // syntax, for instance custom elements. |
| 2342 // | 2347 // |
| 2343 // Return early if any elements are added to avoid counting the elements as | 2348 // Return early if any elements are added to avoid counting the elements as |
| 2344 // due to mirrors. | 2349 // due to mirrors. |
| 2345 enqueuer.applyImpact(customElementsAnalysis.flush( | |
| 2346 forResolution: enqueuer.isResolutionQueue)); | |
| 2347 enqueuer.applyImpact( | 2350 enqueuer.applyImpact( |
| 2351 compiler.impactStrategy, |
| 2352 customElementsAnalysis.flush( |
| 2353 forResolution: enqueuer.isResolutionQueue)); |
| 2354 enqueuer.applyImpact(compiler.impactStrategy, |
| 2348 lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue)); | 2355 lookupMapAnalysis.flush(forResolution: enqueuer.isResolutionQueue)); |
| 2349 enqueuer.applyImpact( | 2356 enqueuer.applyImpact(compiler.impactStrategy, |
| 2350 typeVariableHandler.flush(forResolution: enqueuer.isResolutionQueue)); | 2357 typeVariableHandler.flush(forResolution: enqueuer.isResolutionQueue)); |
| 2351 | 2358 |
| 2352 if (!enqueuer.queueIsEmpty) return false; | 2359 if (!enqueuer.queueIsEmpty) return false; |
| 2353 | 2360 |
| 2354 noSuchMethodRegistry.onQueueEmpty(); | 2361 noSuchMethodRegistry.onQueueEmpty(); |
| 2355 if (!enabledNoSuchMethod && | 2362 if (!enabledNoSuchMethod && |
| 2356 (noSuchMethodRegistry.hasThrowingNoSuchMethod || | 2363 (noSuchMethodRegistry.hasThrowingNoSuchMethod || |
| 2357 noSuchMethodRegistry.hasComplexNoSuchMethod)) { | 2364 noSuchMethodRegistry.hasComplexNoSuchMethod)) { |
| 2358 enableNoSuchMethod(enqueuer); | 2365 enableNoSuchMethod(enqueuer); |
| 2359 enabledNoSuchMethod = true; | 2366 enabledNoSuchMethod = true; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2413 // elements and process these instead. | 2420 // elements and process these instead. |
| 2414 processMetadata(compiler.enqueuer.resolution.processedElements, | 2421 processMetadata(compiler.enqueuer.resolution.processedElements, |
| 2415 registerMetadataConstant); | 2422 registerMetadataConstant); |
| 2416 } else { | 2423 } else { |
| 2417 for (Dependency dependency in metadataConstants) { | 2424 for (Dependency dependency in metadataConstants) { |
| 2418 computeImpactForCompileTimeConstant( | 2425 computeImpactForCompileTimeConstant( |
| 2419 dependency.constant, impactBuilder, enqueuer.isResolutionQueue); | 2426 dependency.constant, impactBuilder, enqueuer.isResolutionQueue); |
| 2420 } | 2427 } |
| 2421 metadataConstants.clear(); | 2428 metadataConstants.clear(); |
| 2422 } | 2429 } |
| 2423 enqueuer.applyImpact(impactBuilder.flush()); | 2430 enqueuer.applyImpact(compiler.impactStrategy, impactBuilder.flush()); |
| 2424 } | 2431 } |
| 2425 return true; | 2432 return true; |
| 2426 } | 2433 } |
| 2427 | 2434 |
| 2428 /// Call [registerMetadataConstant] on all metadata from [elements]. | 2435 /// Call [registerMetadataConstant] on all metadata from [elements]. |
| 2429 void processMetadata(Iterable<Element> elements, | 2436 void processMetadata(Iterable<Element> elements, |
| 2430 void onMetadata(MetadataAnnotation metadata)) { | 2437 void onMetadata(MetadataAnnotation metadata)) { |
| 2431 void processLibraryMetadata(LibraryElement library) { | 2438 void processLibraryMetadata(LibraryElement library) { |
| 2432 if (_registeredMetadata.add(library)) { | 2439 if (_registeredMetadata.add(library)) { |
| 2433 library.metadata.forEach(onMetadata); | 2440 library.metadata.forEach(onMetadata); |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2538 } | 2545 } |
| 2539 if (hasNoThrows && !hasNoInline) { | 2546 if (hasNoThrows && !hasNoInline) { |
| 2540 reporter.internalError( | 2547 reporter.internalError( |
| 2541 element, "@NoThrows() should always be combined with @NoInline."); | 2548 element, "@NoThrows() should always be combined with @NoInline."); |
| 2542 } | 2549 } |
| 2543 if (hasNoSideEffects && !hasNoInline) { | 2550 if (hasNoSideEffects && !hasNoInline) { |
| 2544 reporter.internalError(element, | 2551 reporter.internalError(element, |
| 2545 "@NoSideEffects() should always be combined with @NoInline."); | 2552 "@NoSideEffects() should always be combined with @NoInline."); |
| 2546 } | 2553 } |
| 2547 if (element == helpers.invokeOnMethod) { | 2554 if (element == helpers.invokeOnMethod) { |
| 2548 compiler.enabledInvokeOn = true; | 2555 hasInvokeOnSupport = true; |
| 2549 } | 2556 } |
| 2550 } | 2557 } |
| 2551 | 2558 |
| 2552 /* | 2559 /* |
| 2553 CodeBuffer codeOf(Element element) { | 2560 CodeBuffer codeOf(Element element) { |
| 2554 return generatedCode.containsKey(element) | 2561 return generatedCode.containsKey(element) |
| 2555 ? jsAst.prettyPrint(generatedCode[element], compiler) | 2562 ? jsAst.prettyPrint(generatedCode[element], compiler) |
| 2556 : null; | 2563 : null; |
| 2557 } | 2564 } |
| 2558 */ | 2565 */ |
| (...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3269 ClassElement get mapImplementation => helpers.mapLiteralClass; | 3276 ClassElement get mapImplementation => helpers.mapLiteralClass; |
| 3270 ClassElement get constMapImplementation => helpers.constMapLiteralClass; | 3277 ClassElement get constMapImplementation => helpers.constMapLiteralClass; |
| 3271 ClassElement get typeImplementation => helpers.typeLiteralClass; | 3278 ClassElement get typeImplementation => helpers.typeLiteralClass; |
| 3272 ClassElement get boolImplementation => helpers.jsBoolClass; | 3279 ClassElement get boolImplementation => helpers.jsBoolClass; |
| 3273 ClassElement get nullImplementation => helpers.jsNullClass; | 3280 ClassElement get nullImplementation => helpers.jsNullClass; |
| 3274 ClassElement get syncStarIterableImplementation => helpers.syncStarIterable; | 3281 ClassElement get syncStarIterableImplementation => helpers.syncStarIterable; |
| 3275 ClassElement get asyncFutureImplementation => helpers.futureImplementation; | 3282 ClassElement get asyncFutureImplementation => helpers.futureImplementation; |
| 3276 ClassElement get asyncStarStreamImplementation => helpers.controllerStream; | 3283 ClassElement get asyncStarStreamImplementation => helpers.controllerStream; |
| 3277 ClassElement get functionImplementation => helpers.coreClasses.functionClass; | 3284 ClassElement get functionImplementation => helpers.coreClasses.functionClass; |
| 3278 } | 3285 } |
| OLD | NEW |