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 const VERBOSE_OPTIMIZER_HINTS = false; | 7 const VERBOSE_OPTIMIZER_HINTS = false; |
8 | 8 |
9 class JavaScriptItemCompilationContext extends ItemCompilationContext { | 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 new Uri(scheme: 'dart', path: '_isolate_helper'); | 230 new Uri(scheme: 'dart', path: '_isolate_helper'); |
231 static final Uri DART_HTML = | 231 static final Uri DART_HTML = |
232 new Uri(scheme: 'dart', path: 'html'); | 232 new Uri(scheme: 'dart', path: 'html'); |
233 | 233 |
234 static const String INVOKE_ON = '_getCachedInvocation'; | 234 static const String INVOKE_ON = '_getCachedInvocation'; |
235 static const String START_ROOT_ISOLATE = 'startRootIsolate'; | 235 static const String START_ROOT_ISOLATE = 'startRootIsolate'; |
236 | 236 |
237 | 237 |
238 String get patchVersion => USE_NEW_EMITTER ? 'new' : 'old'; | 238 String get patchVersion => USE_NEW_EMITTER ? 'new' : 'old'; |
239 | 239 |
240 final Annotations annotations = new Annotations(); | 240 final Annotations annotations; |
241 | 241 |
242 /// Reference to the internal library to lookup functions to always inline. | 242 /// Reference to the internal library to lookup functions to always inline. |
243 LibraryElement internalLibrary; | 243 LibraryElement internalLibrary; |
244 | 244 |
245 | 245 |
246 /// Set of classes that need to be considered for reflection although not | 246 /// Set of classes that need to be considered for reflection although not |
247 /// otherwise visible during resolution. | 247 /// otherwise visible during resolution. |
248 Iterable<ClassElement> get classesRequiredForReflection { | 248 Iterable<ClassElement> get classesRequiredForReflection { |
249 // TODO(herhut): Clean this up when classes needed for rti are tracked. | 249 // TODO(herhut): Clean this up when classes needed for rti are tracked. |
250 return [closureClass, jsIndexableClass]; | 250 return [closureClass, jsIndexableClass]; |
(...skipping 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 bool enabledNoSuchMethod = false; | 613 bool enabledNoSuchMethod = false; |
614 | 614 |
615 JavaScriptBackend(Compiler compiler, | 615 JavaScriptBackend(Compiler compiler, |
616 SourceInformationFactory sourceInformationFactory, | 616 SourceInformationFactory sourceInformationFactory, |
617 {bool generateSourceMap: true}) | 617 {bool generateSourceMap: true}) |
618 : namer = determineNamer(compiler), | 618 : namer = determineNamer(compiler), |
619 oneShotInterceptors = new Map<String, Selector>(), | 619 oneShotInterceptors = new Map<String, Selector>(), |
620 interceptedElements = new Map<String, Set<Element>>(), | 620 interceptedElements = new Map<String, Set<Element>>(), |
621 rti = new RuntimeTypes(compiler), | 621 rti = new RuntimeTypes(compiler), |
622 specializedGetInterceptors = new Map<String, Set<ClassElement>>(), | 622 specializedGetInterceptors = new Map<String, Set<ClassElement>>(), |
| 623 annotations = new Annotations(compiler), |
623 super(compiler) { | 624 super(compiler) { |
624 emitter = new CodeEmitterTask(compiler, namer, generateSourceMap); | 625 emitter = new CodeEmitterTask(compiler, namer, generateSourceMap); |
625 typeVariableHandler = new TypeVariableHandler(compiler); | 626 typeVariableHandler = new TypeVariableHandler(compiler); |
626 customElementsAnalysis = new CustomElementsAnalysis(this); | 627 customElementsAnalysis = new CustomElementsAnalysis(this); |
627 noSuchMethodRegistry = new NoSuchMethodRegistry(this); | 628 noSuchMethodRegistry = new NoSuchMethodRegistry(this); |
628 constantCompilerTask = new JavaScriptConstantTask(compiler); | 629 constantCompilerTask = new JavaScriptConstantTask(compiler); |
629 resolutionCallbacks = new JavaScriptResolutionCallbacks(this); | 630 resolutionCallbacks = new JavaScriptResolutionCallbacks(this); |
630 patchResolverTask = new PatchResolverTask(compiler); | 631 patchResolverTask = new PatchResolverTask(compiler); |
631 functionCompiler = compiler.useCpsIr | 632 functionCompiler = compiler.useCpsIr |
632 ? new CpsFunctionCompiler( | 633 ? new CpsFunctionCompiler( |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 // helper so we register a use of that. | 965 // helper so we register a use of that. |
965 registry.registerStaticInvocation(getCreateRuntimeType()); | 966 registry.registerStaticInvocation(getCreateRuntimeType()); |
966 } | 967 } |
967 } | 968 } |
968 } | 969 } |
969 | 970 |
970 void registerMetadataConstant(MetadataAnnotation metadata, | 971 void registerMetadataConstant(MetadataAnnotation metadata, |
971 Element annotatedElement, | 972 Element annotatedElement, |
972 Registry registry) { | 973 Registry registry) { |
973 assert(registry.isForResolution); | 974 assert(registry.isForResolution); |
974 ConstantValue constant = constants.getConstantForMetadata(metadata).value; | 975 ConstantValue constant = constants.getConstantValueForMetadata(metadata); |
975 registerCompileTimeConstant(constant, registry); | 976 registerCompileTimeConstant(constant, registry); |
976 metadataConstants.add(new Dependency(constant, annotatedElement)); | 977 metadataConstants.add(new Dependency(constant, annotatedElement)); |
977 } | 978 } |
978 | 979 |
979 void registerInstantiatedClass(ClassElement cls, | 980 void registerInstantiatedClass(ClassElement cls, |
980 Enqueuer enqueuer, | 981 Enqueuer enqueuer, |
981 Registry registry) { | 982 Registry registry) { |
982 if (!cls.typeVariables.isEmpty) { | 983 if (!cls.typeVariables.isEmpty) { |
983 typeVariableHandler.registerClassWithTypeVariables(cls, enqueuer, | 984 typeVariableHandler.registerClassWithTypeVariables(cls, enqueuer, |
984 registry); | 985 registry); |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1393 } | 1394 } |
1394 var kind = element.kind; | 1395 var kind = element.kind; |
1395 if (kind == ElementKind.TYPEDEF) { | 1396 if (kind == ElementKind.TYPEDEF) { |
1396 return const WorldImpact(); | 1397 return const WorldImpact(); |
1397 } | 1398 } |
1398 if (element.isConstructor && element.enclosingClass == jsNullClass) { | 1399 if (element.isConstructor && element.enclosingClass == jsNullClass) { |
1399 // Work around a problem compiling JSNull's constructor. | 1400 // Work around a problem compiling JSNull's constructor. |
1400 return const WorldImpact(); | 1401 return const WorldImpact(); |
1401 } | 1402 } |
1402 if (kind.category == ElementCategory.VARIABLE) { | 1403 if (kind.category == ElementCategory.VARIABLE) { |
1403 ConstantExpression initialValue = | 1404 ConstantValue initialValue = |
1404 constants.getConstantForVariable(element); | 1405 constants.getConstantValueForVariable(element); |
1405 if (initialValue != null) { | 1406 if (initialValue != null) { |
1406 registerCompileTimeConstant(initialValue.value, work.registry); | 1407 registerCompileTimeConstant(initialValue, work.registry); |
1407 constants.addCompileTimeConstantForEmission(initialValue.value); | 1408 constants.addCompileTimeConstantForEmission(initialValue); |
1408 // We don't need to generate code for static or top-level | 1409 // We don't need to generate code for static or top-level |
1409 // variables. For instance variables, we may need to generate | 1410 // variables. For instance variables, we may need to generate |
1410 // the checked setter. | 1411 // the checked setter. |
1411 if (Elements.isStaticOrTopLevel(element)) { | 1412 if (Elements.isStaticOrTopLevel(element)) { |
1412 return const WorldImpact(); | 1413 return const WorldImpact(); |
1413 } | 1414 } |
1414 } else { | 1415 } else { |
1415 // If the constant-handler was not able to produce a result we have to | 1416 // If the constant-handler was not able to produce a result we have to |
1416 // go through the builder (below) to generate the lazy initializer for | 1417 // go through the builder (below) to generate the lazy initializer for |
1417 // the static variable. | 1418 // the static variable. |
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1947 if (name == '') return false; | 1948 if (name == '') return false; |
1948 return symbolsUsed.contains(name); | 1949 return symbolsUsed.contains(name); |
1949 } | 1950 } |
1950 | 1951 |
1951 bool retainMetadataOf(Element element) { | 1952 bool retainMetadataOf(Element element) { |
1952 if (mustRetainMetadata) hasRetainedMetadata = true; | 1953 if (mustRetainMetadata) hasRetainedMetadata = true; |
1953 if (mustRetainMetadata && referencedFromMirrorSystem(element)) { | 1954 if (mustRetainMetadata && referencedFromMirrorSystem(element)) { |
1954 for (MetadataAnnotation metadata in element.metadata) { | 1955 for (MetadataAnnotation metadata in element.metadata) { |
1955 metadata.ensureResolved(compiler); | 1956 metadata.ensureResolved(compiler); |
1956 ConstantValue constant = | 1957 ConstantValue constant = |
1957 constants.getConstantForMetadata(metadata).value; | 1958 constants.getConstantValueForMetadata(metadata); |
1958 constants.addCompileTimeConstantForEmission(constant); | 1959 constants.addCompileTimeConstantForEmission(constant); |
1959 } | 1960 } |
1960 return true; | 1961 return true; |
1961 } | 1962 } |
1962 return false; | 1963 return false; |
1963 } | 1964 } |
1964 | 1965 |
1965 void onLibraryCreated(LibraryElement library) { | 1966 void onLibraryCreated(LibraryElement library) { |
1966 Uri uri = library.canonicalUri; | 1967 Uri uri = library.canonicalUri; |
1967 if (uri == DART_JS_HELPER) { | 1968 if (uri == DART_JS_HELPER) { |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2231 * of a type that is used as a meta target for reflection. | 2232 * of a type that is used as a meta target for reflection. |
2232 */ | 2233 */ |
2233 bool matchesMirrorsMetaTarget(Element element) { | 2234 bool matchesMirrorsMetaTarget(Element element) { |
2234 if (metaTargetsUsed.isEmpty) return false; | 2235 if (metaTargetsUsed.isEmpty) return false; |
2235 for (Link link = element.metadata; !link.isEmpty; link = link.tail) { | 2236 for (Link link = element.metadata; !link.isEmpty; link = link.tail) { |
2236 MetadataAnnotation metadata = link.head; | 2237 MetadataAnnotation metadata = link.head; |
2237 // TODO(kasperl): It would be nice if we didn't have to resolve | 2238 // TODO(kasperl): It would be nice if we didn't have to resolve |
2238 // all metadata but only stuff that potentially would match one | 2239 // all metadata but only stuff that potentially would match one |
2239 // of the used meta targets. | 2240 // of the used meta targets. |
2240 metadata.ensureResolved(compiler); | 2241 metadata.ensureResolved(compiler); |
2241 ConstantValue value = metadata.constant.value; | 2242 ConstantValue value = |
| 2243 compiler.constants.getConstantValue(metadata.constant); |
2242 if (value == null) continue; | 2244 if (value == null) continue; |
2243 DartType type = value.getType(compiler.coreTypes); | 2245 DartType type = value.getType(compiler.coreTypes); |
2244 if (metaTargetsUsed.contains(type.element)) return true; | 2246 if (metaTargetsUsed.contains(type.element)) return true; |
2245 } | 2247 } |
2246 return false; | 2248 return false; |
2247 } | 2249 } |
2248 | 2250 |
2249 /** | 2251 /** |
2250 * Visits all classes and computes whether its members are needed for | 2252 * Visits all classes and computes whether its members are needed for |
2251 * reflection. | 2253 * reflection. |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2529 } | 2531 } |
2530 | 2532 |
2531 LibraryElement library = element.library; | 2533 LibraryElement library = element.library; |
2532 if (!library.isPlatformLibrary && !library.canUseNative) return; | 2534 if (!library.isPlatformLibrary && !library.canUseNative) return; |
2533 bool hasNoInline = false; | 2535 bool hasNoInline = false; |
2534 bool hasForceInline = false; | 2536 bool hasForceInline = false; |
2535 bool hasNoThrows = false; | 2537 bool hasNoThrows = false; |
2536 bool hasNoSideEffects = false; | 2538 bool hasNoSideEffects = false; |
2537 for (MetadataAnnotation metadata in element.metadata) { | 2539 for (MetadataAnnotation metadata in element.metadata) { |
2538 metadata.ensureResolved(compiler); | 2540 metadata.ensureResolved(compiler); |
2539 if (!metadata.constant.value.isConstructedObject) continue; | 2541 ConstantValue constantValue = |
2540 ObjectConstantValue value = metadata.constant.value; | 2542 compiler.constants.getConstantValue(metadata.constant); |
| 2543 if (!constantValue.isConstructedObject) continue; |
| 2544 ObjectConstantValue value = constantValue; |
2541 ClassElement cls = value.type.element; | 2545 ClassElement cls = value.type.element; |
2542 if (cls == forceInlineClass) { | 2546 if (cls == forceInlineClass) { |
2543 hasForceInline = true; | 2547 hasForceInline = true; |
2544 if (VERBOSE_OPTIMIZER_HINTS) { | 2548 if (VERBOSE_OPTIMIZER_HINTS) { |
2545 compiler.reportHint(element, | 2549 compiler.reportHint(element, |
2546 MessageKind.GENERIC, | 2550 MessageKind.GENERIC, |
2547 {'text': "Must inline"}); | 2551 {'text': "Must inline"}); |
2548 } | 2552 } |
2549 inlineCache.markAsMustInline(element); | 2553 inlineCache.markAsMustInline(element); |
2550 } else if (cls == noInlineClass) { | 2554 } else if (cls == noInlineClass) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2665 enqueue(enqueuer, getStreamIteratorConstructor(), registry); | 2669 enqueue(enqueuer, getStreamIteratorConstructor(), registry); |
2666 } | 2670 } |
2667 } | 2671 } |
2668 } | 2672 } |
2669 | 2673 |
2670 /// Handling of special annotations for tests. | 2674 /// Handling of special annotations for tests. |
2671 class Annotations { | 2675 class Annotations { |
2672 static final Uri PACKAGE_EXPECT = | 2676 static final Uri PACKAGE_EXPECT = |
2673 new Uri(scheme: 'package', path: 'expect/expect.dart'); | 2677 new Uri(scheme: 'package', path: 'expect/expect.dart'); |
2674 | 2678 |
| 2679 final Compiler compiler; |
| 2680 |
2675 ClassElement expectNoInlineClass; | 2681 ClassElement expectNoInlineClass; |
2676 ClassElement expectTrustTypeAnnotationsClass; | 2682 ClassElement expectTrustTypeAnnotationsClass; |
2677 ClassElement expectAssumeDynamicClass; | 2683 ClassElement expectAssumeDynamicClass; |
2678 | 2684 |
| 2685 Annotations(this.compiler); |
| 2686 |
2679 void onLibraryScanned(LibraryElement library) { | 2687 void onLibraryScanned(LibraryElement library) { |
2680 if (library.canonicalUri == PACKAGE_EXPECT) { | 2688 if (library.canonicalUri == PACKAGE_EXPECT) { |
2681 expectNoInlineClass = library.find('NoInline'); | 2689 expectNoInlineClass = library.find('NoInline'); |
2682 expectTrustTypeAnnotationsClass = library.find('TrustTypeAnnotations'); | 2690 expectTrustTypeAnnotationsClass = library.find('TrustTypeAnnotations'); |
2683 expectAssumeDynamicClass = library.find('AssumeDynamic'); | 2691 expectAssumeDynamicClass = library.find('AssumeDynamic'); |
2684 if (expectNoInlineClass == null || | 2692 if (expectNoInlineClass == null || |
2685 expectTrustTypeAnnotationsClass == null || | 2693 expectTrustTypeAnnotationsClass == null || |
2686 expectAssumeDynamicClass == null) { | 2694 expectAssumeDynamicClass == null) { |
2687 // This is not the package you're looking for. | 2695 // This is not the package you're looking for. |
2688 expectNoInlineClass = null; | 2696 expectNoInlineClass = null; |
(...skipping 19 matching lines...) Expand all Loading... |
2708 bool assumeDynamic(Element element) { | 2716 bool assumeDynamic(Element element) { |
2709 return _hasAnnotation(element, expectAssumeDynamicClass); | 2717 return _hasAnnotation(element, expectAssumeDynamicClass); |
2710 } | 2718 } |
2711 | 2719 |
2712 /// Returns `true` if [element] is annotated with [annotationClass]. | 2720 /// Returns `true` if [element] is annotated with [annotationClass]. |
2713 bool _hasAnnotation(Element element, ClassElement annotationClass) { | 2721 bool _hasAnnotation(Element element, ClassElement annotationClass) { |
2714 if (annotationClass == null) return false; | 2722 if (annotationClass == null) return false; |
2715 for (Link<MetadataAnnotation> link = element.metadata; | 2723 for (Link<MetadataAnnotation> link = element.metadata; |
2716 !link.isEmpty; | 2724 !link.isEmpty; |
2717 link = link.tail) { | 2725 link = link.tail) { |
2718 ConstantValue value = link.head.constant.value; | 2726 ConstantValue value = |
| 2727 compiler.constants.getConstantValue(link.head.constant); |
2719 if (value.isConstructedObject) { | 2728 if (value.isConstructedObject) { |
2720 ConstructedConstantValue constructedConstant = value; | 2729 ConstructedConstantValue constructedConstant = value; |
2721 if (constructedConstant.type.element == annotationClass) { | 2730 if (constructedConstant.type.element == annotationClass) { |
2722 return true; | 2731 return true; |
2723 } | 2732 } |
2724 } | 2733 } |
2725 } | 2734 } |
2726 return false; | 2735 return false; |
2727 } | 2736 } |
2728 } | 2737 } |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2942 } | 2951 } |
2943 } | 2952 } |
2944 | 2953 |
2945 /// Records that [constant] is used by the element behind [registry]. | 2954 /// Records that [constant] is used by the element behind [registry]. |
2946 class Dependency { | 2955 class Dependency { |
2947 final ConstantValue constant; | 2956 final ConstantValue constant; |
2948 final Element annotatedElement; | 2957 final Element annotatedElement; |
2949 | 2958 |
2950 const Dependency(this.constant, this.annotatedElement); | 2959 const Dependency(this.constant, this.annotatedElement); |
2951 } | 2960 } |
OLD | NEW |