Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(494)

Side by Side Diff: pkg/compiler/lib/src/js_backend/backend.dart

Issue 2680823002: Extract InterceptorData from JavaScriptBackend. (Closed)
Patch Set: Updated cf. comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_backend/backend_helpers.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 import '../closure.dart'; 11 import '../closure.dart';
12 import '../common.dart'; 12 import '../common.dart';
13 import '../common/backend_api.dart' 13 import '../common/backend_api.dart'
14 show BackendClasses, ImpactTransformer, ForeignResolver, NativeRegistry; 14 show BackendClasses, ImpactTransformer, ForeignResolver, NativeRegistry;
15 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem; 15 import '../common/codegen.dart' show CodegenImpact, CodegenWorkItem;
16 import '../common/names.dart' show Identifiers, Uris; 16 import '../common/names.dart' show Identifiers, Uris;
17 import '../common/resolution.dart' 17 import '../common/resolution.dart'
18 show Frontend, Resolution, ResolutionImpact, Target; 18 show Frontend, Resolution, ResolutionImpact, Target;
19 import '../common/tasks.dart' show CompilerTask; 19 import '../common/tasks.dart' show CompilerTask;
20 import '../compiler.dart' show Compiler; 20 import '../compiler.dart' show Compiler;
21 import '../constants/constant_system.dart'; 21 import '../constants/constant_system.dart';
22 import '../constants/expressions.dart'; 22 import '../constants/expressions.dart';
23 import '../constants/values.dart'; 23 import '../constants/values.dart';
24 import '../core_types.dart' show CommonElements; 24 import '../core_types.dart' show CommonElements, ElementEnvironment;
25 import '../deferred_load.dart' show DeferredLoadTask; 25 import '../deferred_load.dart' show DeferredLoadTask;
26 import '../dump_info.dart' show DumpInfoTask; 26 import '../dump_info.dart' show DumpInfoTask;
27 import '../elements/elements.dart'; 27 import '../elements/elements.dart';
28 import '../elements/entities.dart'; 28 import '../elements/entities.dart';
29 import '../elements/resolution_types.dart'; 29 import '../elements/resolution_types.dart';
30 import '../elements/types.dart'; 30 import '../elements/types.dart';
31 import '../enqueue.dart' 31 import '../enqueue.dart'
32 show Enqueuer, EnqueueTask, ResolutionEnqueuer, TreeShakingEnqueuerStrategy; 32 show Enqueuer, EnqueueTask, ResolutionEnqueuer, TreeShakingEnqueuerStrategy;
33 import '../io/position_information.dart' show PositionSourceInformationStrategy; 33 import '../io/position_information.dart' show PositionSourceInformationStrategy;
34 import '../io/source_information.dart' show SourceInformationStrategy; 34 import '../io/source_information.dart' show SourceInformationStrategy;
35 import '../io/start_end_information.dart' 35 import '../io/start_end_information.dart'
36 show StartEndSourceInformationStrategy; 36 show StartEndSourceInformationStrategy;
37 import '../js/js.dart' as jsAst; 37 import '../js/js.dart' as jsAst;
38 import '../js/js.dart' show js; 38 import '../js/js.dart' show js;
39 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy; 39 import '../js/js_source_mapping.dart' show JavaScriptSourceInformationStrategy;
40 import '../js/rewrite_async.dart'; 40 import '../js/rewrite_async.dart';
41 import '../js_emitter/js_emitter.dart' show CodeEmitterTask; 41 import '../js_emitter/js_emitter.dart' show CodeEmitterTask;
42 import '../kernel/task.dart';
42 import '../library_loader.dart' show LibraryLoader, LoadedLibraries; 43 import '../library_loader.dart' show LibraryLoader, LoadedLibraries;
43 import '../native/native.dart' as native; 44 import '../native/native.dart' as native;
44 import '../patch_parser.dart' 45 import '../patch_parser.dart'
45 show checkNativeAnnotation, checkJsInteropAnnotation; 46 show checkNativeAnnotation, checkJsInteropAnnotation;
46 import '../ssa/ssa.dart' show SsaFunctionCompiler; 47 import '../ssa/ssa.dart' show SsaFunctionCompiler;
47 import '../tracer.dart'; 48 import '../tracer.dart';
48 import '../tree/tree.dart'; 49 import '../tree/tree.dart';
49 import '../types/types.dart';
50 import '../universe/call_structure.dart' show CallStructure; 50 import '../universe/call_structure.dart' show CallStructure;
51 import '../universe/feature.dart'; 51 import '../universe/feature.dart';
52 import '../universe/selector.dart' show Selector; 52 import '../universe/selector.dart' show Selector;
53 import '../universe/world_builder.dart'; 53 import '../universe/world_builder.dart';
54 import '../universe/use.dart' 54 import '../universe/use.dart'
55 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; 55 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind;
56 import '../universe/world_impact.dart' 56 import '../universe/world_impact.dart'
57 show 57 show
58 ImpactStrategy, 58 ImpactStrategy,
59 ImpactUseCase, 59 ImpactUseCase,
60 TransformedWorldImpact, 60 TransformedWorldImpact,
61 WorldImpact, 61 WorldImpact,
62 WorldImpactBuilder, 62 WorldImpactBuilder,
63 WorldImpactBuilderImpl, 63 WorldImpactBuilderImpl,
64 WorldImpactVisitor, 64 WorldImpactVisitor,
65 StagedWorldImpactBuilder; 65 StagedWorldImpactBuilder;
66 import '../util/util.dart'; 66 import '../util/util.dart';
67 import '../world.dart' show ClosedWorld, ClosedWorldRefiner; 67 import '../world.dart' show ClosedWorld, ClosedWorldRefiner;
68 import 'backend_helpers.dart'; 68 import 'backend_helpers.dart';
69 import 'backend_impact.dart'; 69 import 'backend_impact.dart';
70 import 'backend_serialization.dart' show JavaScriptBackendSerialization; 70 import 'backend_serialization.dart' show JavaScriptBackendSerialization;
71 import 'checked_mode_helpers.dart'; 71 import 'checked_mode_helpers.dart';
72 import 'constant_handler_javascript.dart'; 72 import 'constant_handler_javascript.dart';
73 import 'custom_elements_analysis.dart'; 73 import 'custom_elements_analysis.dart';
74 import 'enqueuer.dart'; 74 import 'enqueuer.dart';
75 import 'interceptor_data.dart' show InterceptorData;
75 import 'js_interop_analysis.dart' show JsInteropAnalysis; 76 import 'js_interop_analysis.dart' show JsInteropAnalysis;
76 import '../kernel/task.dart';
77 import 'lookup_map_analysis.dart' show LookupMapAnalysis; 77 import 'lookup_map_analysis.dart' show LookupMapAnalysis;
78 import 'mirrors_analysis.dart'; 78 import 'mirrors_analysis.dart';
79 import 'namer.dart'; 79 import 'namer.dart';
80 import 'native_data.dart' show NativeData; 80 import 'native_data.dart' show NativeData;
81 import 'no_such_method_registry.dart'; 81 import 'no_such_method_registry.dart';
82 import 'patch_resolver.dart'; 82 import 'patch_resolver.dart';
83 import 'type_variable_handler.dart'; 83 import 'type_variable_handler.dart';
84 84
85 part 'runtime_types.dart'; 85 part 'runtime_types.dart';
86 86
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 347
348 Namer _namer; 348 Namer _namer;
349 349
350 Namer get namer { 350 Namer get namer {
351 assert(invariant(NO_LOCATION_SPANNABLE, _namer != null, 351 assert(invariant(NO_LOCATION_SPANNABLE, _namer != null,
352 message: "Namer has not been created yet.")); 352 message: "Namer has not been created yet."));
353 return _namer; 353 return _namer;
354 } 354 }
355 355
356 /** 356 /**
357 * A collection of selectors that must have a one shot interceptor
358 * generated.
359 */
360 final Map<jsAst.Name, Selector> oneShotInterceptors;
361
362 /**
363 * The members of instantiated interceptor classes: maps a member name to the
364 * list of members that have that name. This map is used by the codegen to
365 * know whether a send must be intercepted or not.
366 */
367 final Map<String, Set<Element>> interceptedElements;
368
369 /**
370 * The members of mixin classes that are mixed into an instantiated
371 * interceptor class. This is a cached subset of [interceptedElements].
372 *
373 * Mixin methods are not specialized for the class they are mixed into.
374 * Methods mixed into intercepted classes thus always make use of the explicit
375 * receiver argument, even when mixed into non-interceptor classes.
376 *
377 * These members must be invoked with a correct explicit receiver even when
378 * the receiver is not an intercepted class.
379 */
380 final Map<String, Set<Element>> interceptedMixinElements =
381 new Map<String, Set<Element>>();
382
383 /**
384 * A map of specialized versions of the [getInterceptorMethod].
385 * Since [getInterceptorMethod] is a hot method at runtime, we're
386 * always specializing it based on the incoming type. The keys in
387 * the map are the names of these specialized versions. Note that
388 * the generic version that contains all possible type checks is
389 * also stored in this map.
390 */
391 final Map<jsAst.Name, Set<ClassElement>> specializedGetInterceptors;
392
393 /**
394 * Set of classes whose methods are intercepted.
395 */
396 final Set<ClassElement> _interceptedClasses = new Set<ClassElement>();
397
398 /**
399 * Set of classes used as mixins on intercepted (native and primitive)
400 * classes. Methods on these classes might also be mixed in to regular Dart
401 * (unintercepted) classes.
402 */
403 final Set<ClassElement> classesMixedIntoInterceptedClasses =
404 new Set<ClassElement>();
405
406 /**
407 * Set of classes whose `operator ==` methods handle `null` themselves. 357 * Set of classes whose `operator ==` methods handle `null` themselves.
408 */ 358 */
409 final Set<ClassElement> specialOperatorEqClasses = new Set<ClassElement>(); 359 final Set<ClassElement> specialOperatorEqClasses = new Set<ClassElement>();
410 360
411 /** 361 /**
412 * A set of members that are called from subclasses via `super`. 362 * A set of members that are called from subclasses via `super`.
413 */ 363 */
414 final Set<MethodElement> aliasedSuperMembers = new Setlet<MethodElement>(); 364 final Set<MethodElement> aliasedSuperMembers = new Setlet<MethodElement>();
415 365
416 List<CompilerTask> get tasks { 366 List<CompilerTask> get tasks {
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 /// Interface for serialization of backend specific data. 500 /// Interface for serialization of backend specific data.
551 JavaScriptBackendSerialization serialization; 501 JavaScriptBackendSerialization serialization;
552 502
553 StagedWorldImpactBuilder constantImpactsForResolution = 503 StagedWorldImpactBuilder constantImpactsForResolution =
554 new StagedWorldImpactBuilder(); 504 new StagedWorldImpactBuilder();
555 505
556 StagedWorldImpactBuilder constantImpactsForCodegen = 506 StagedWorldImpactBuilder constantImpactsForCodegen =
557 new StagedWorldImpactBuilder(); 507 new StagedWorldImpactBuilder();
558 508
559 final NativeData nativeData = new NativeData(); 509 final NativeData nativeData = new NativeData();
510 InterceptorData _interceptorData;
560 511
561 BackendHelpers helpers; 512 BackendHelpers helpers;
562 final BackendImpacts impacts; 513 final BackendImpacts impacts;
563 514
564 /// Common classes used by the backend. 515 /// Common classes used by the backend.
565 BackendClasses backendClasses; 516 BackendClasses backendClasses;
566 517
567 /// Backend access to the front-end. 518 /// Backend access to the front-end.
568 final JSFrontendAccess frontend; 519 final JSFrontendAccess frontend;
569 520
570 Tracer tracer; 521 Tracer tracer;
571 522
572 JavaScriptBackend(Compiler compiler, 523 JavaScriptBackend(Compiler compiler,
573 {bool generateSourceMap: true, 524 {bool generateSourceMap: true,
574 bool useStartupEmitter: false, 525 bool useStartupEmitter: false,
575 bool useNewSourceInfo: false, 526 bool useNewSourceInfo: false,
576 bool useKernel: false}) 527 bool useKernel: false})
577 : oneShotInterceptors = new Map<jsAst.Name, Selector>(), 528 : rti = new _RuntimeTypes(compiler),
578 interceptedElements = new Map<String, Set<Element>>(),
579 rti = new _RuntimeTypes(compiler),
580 rtiEncoder = new _RuntimeTypesEncoder(compiler), 529 rtiEncoder = new _RuntimeTypesEncoder(compiler),
581 specializedGetInterceptors = new Map<jsAst.Name, Set<ClassElement>>(),
582 annotations = new Annotations(compiler), 530 annotations = new Annotations(compiler),
583 this.sourceInformationStrategy = generateSourceMap 531 this.sourceInformationStrategy = generateSourceMap
584 ? (useNewSourceInfo 532 ? (useNewSourceInfo
585 ? new PositionSourceInformationStrategy() 533 ? new PositionSourceInformationStrategy()
586 : const StartEndSourceInformationStrategy()) 534 : const StartEndSourceInformationStrategy())
587 : const JavaScriptSourceInformationStrategy(), 535 : const JavaScriptSourceInformationStrategy(),
588 impacts = new BackendImpacts(compiler), 536 impacts = new BackendImpacts(compiler),
589 frontend = new JSFrontendAccess(compiler), 537 frontend = new JSFrontendAccess(compiler),
590 this.compiler = compiler { 538 this.compiler = compiler {
591 helpers = 539 helpers =
592 new BackendHelpers(compiler.elementEnvironment, this, commonElements); 540 new BackendHelpers(compiler.elementEnvironment, this, commonElements);
593 emitter = 541 emitter =
594 new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter); 542 new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter);
595 typeVariableHandler = new TypeVariableHandler(compiler); 543 typeVariableHandler = new TypeVariableHandler(compiler);
596 customElementsAnalysis = new CustomElementsAnalysis(this); 544 customElementsAnalysis = new CustomElementsAnalysis(this);
597 lookupMapAnalysis = new LookupMapAnalysis(this, reporter); 545 lookupMapAnalysis = new LookupMapAnalysis(this, reporter);
598 jsInteropAnalysis = new JsInteropAnalysis(this); 546 jsInteropAnalysis = new JsInteropAnalysis(this);
599 mirrorsAnalysis = new MirrorsAnalysis(this, compiler.resolution); 547 mirrorsAnalysis = new MirrorsAnalysis(this, compiler.resolution);
600 548
601 noSuchMethodRegistry = new NoSuchMethodRegistry(this); 549 noSuchMethodRegistry = new NoSuchMethodRegistry(this);
602 kernelTask = new KernelTask(compiler); 550 kernelTask = new KernelTask(compiler);
603 constantCompilerTask = new JavaScriptConstantTask(compiler); 551 constantCompilerTask = new JavaScriptConstantTask(compiler);
604 impactTransformer = new JavaScriptImpactTransformer(this); 552 impactTransformer = new JavaScriptImpactTransformer(this);
605 patchResolverTask = new PatchResolverTask(compiler); 553 patchResolverTask = new PatchResolverTask(compiler);
606 functionCompiler = 554 functionCompiler =
607 new SsaFunctionCompiler(this, sourceInformationStrategy, useKernel); 555 new SsaFunctionCompiler(this, sourceInformationStrategy, useKernel);
608 serialization = new JavaScriptBackendSerialization(this); 556 serialization = new JavaScriptBackendSerialization(this);
609 backendClasses = new JavaScriptBackendClasses(helpers); 557 _interceptorData = new InterceptorData(nativeData, helpers, commonElements);
558 backendClasses = new JavaScriptBackendClasses(
559 compiler.elementEnvironment, helpers, nativeData, _interceptorData);
610 } 560 }
611 561
612 /// The [ConstantSystem] used to interpret compile-time constants for this 562 /// The [ConstantSystem] used to interpret compile-time constants for this
613 /// backend. 563 /// backend.
614 ConstantSystem get constantSystem => constants.constantSystem; 564 ConstantSystem get constantSystem => constants.constantSystem;
615 565
616 DiagnosticReporter get reporter => compiler.reporter; 566 DiagnosticReporter get reporter => compiler.reporter;
617 567
618 CommonElements get commonElements => compiler.commonElements; 568 CommonElements get commonElements => compiler.commonElements;
619 569
620 Resolution get resolution => compiler.resolution; 570 Resolution get resolution => compiler.resolution;
621 571
572 InterceptorData get interceptorData => _interceptorData;
573
622 /// Returns constant environment for the JavaScript interpretation of the 574 /// Returns constant environment for the JavaScript interpretation of the
623 /// constants. 575 /// constants.
624 JavaScriptConstantCompiler get constants { 576 JavaScriptConstantCompiler get constants {
625 return constantCompilerTask.jsConstantCompiler; 577 return constantCompilerTask.jsConstantCompiler;
626 } 578 }
627 579
628 @override 580 @override
629 bool isDefaultNoSuchMethod(MethodElement element) { 581 bool isDefaultNoSuchMethod(MethodElement element) {
630 return noSuchMethodRegistry.isDefaultNoSuchMethodImplementation(element); 582 return noSuchMethodRegistry.isDefaultNoSuchMethodImplementation(element);
631 } 583 }
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
747 } 699 }
748 700
749 /// Returns true if global optimizations such as type inferencing 701 /// Returns true if global optimizations such as type inferencing
750 /// can apply to this element. One category of elements that do not 702 /// can apply to this element. One category of elements that do not
751 /// apply is runtime helpers that the backend calls, but the 703 /// apply is runtime helpers that the backend calls, but the
752 /// optimizations don't see those calls. 704 /// optimizations don't see those calls.
753 bool canBeUsedForGlobalOptimizations(Element element) { 705 bool canBeUsedForGlobalOptimizations(Element element) {
754 return !usedByBackend(element) && !invokedReflectively(element); 706 return !usedByBackend(element) && !invokedReflectively(element);
755 } 707 }
756 708
757 bool isInterceptorClass(ClassElement element) {
758 if (element == null) return false;
759 if (isNativeOrExtendsNative(element)) return true;
760 if (interceptedClasses.contains(element)) return true;
761 if (classesMixedIntoInterceptedClasses.contains(element)) return true;
762 return false;
763 }
764
765 jsAst.Name registerOneShotInterceptor(Selector selector) {
766 Set<ClassElement> classes = getInterceptedClassesOn(selector.name);
767 jsAst.Name name = namer.nameForGetOneShotInterceptor(selector, classes);
768 if (!oneShotInterceptors.containsKey(name)) {
769 registerSpecializedGetInterceptor(classes);
770 oneShotInterceptors[name] = selector;
771 }
772 return name;
773 }
774
775 /** 709 /**
776 * Record that [method] is called from a subclass via `super`. 710 * Record that [method] is called from a subclass via `super`.
777 */ 711 */
778 bool maybeRegisterAliasedSuperMember( 712 bool maybeRegisterAliasedSuperMember(
779 MemberElement member, Selector selector) { 713 MemberElement member, Selector selector) {
780 if (!canUseAliasedSuperMember(member, selector)) { 714 if (!canUseAliasedSuperMember(member, selector)) {
781 // Invoking a super getter isn't supported, this would require changes to 715 // Invoking a super getter isn't supported, this would require changes to
782 // compact field descriptors in the emitter. 716 // compact field descriptors in the emitter.
783 return false; 717 return false;
784 } 718 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 // TODO(sra): Process fields for storing separately. 791 // TODO(sra): Process fields for storing separately.
858 // We have to handle both loading and storing to the field because we 792 // We have to handle both loading and storing to the field because we
859 // only get one look at each member and there might be a load or store 793 // only get one look at each member and there might be a load or store
860 // we have not seen yet. 794 // we have not seen yet.
861 registry.registerNativeData(fieldLoadBehavior); 795 registry.registerNativeData(fieldLoadBehavior);
862 registry.registerNativeData(fieldStoreBehavior); 796 registry.registerNativeData(fieldStoreBehavior);
863 } 797 }
864 } 798 }
865 } 799 }
866 800
867 bool isNativeOrExtendsNative(ClassElement element) {
868 if (element == null) return false;
869 if (isNative(element) || isJsInterop(element)) {
870 return true;
871 }
872 assert(element.isResolved);
873 return isNativeOrExtendsNative(element.superclass);
874 }
875
876 bool isInterceptedMethod(MemberElement element) {
877 if (!element.isInstanceMember) return false;
878 if (element.isGenerativeConstructorBody) {
879 return isNativeOrExtendsNative(element.enclosingClass);
880 }
881 return interceptedElements[element.name] != null;
882 }
883
884 bool fieldHasInterceptedGetter(Element element) {
885 assert(element.isField);
886 return interceptedElements[element.name] != null;
887 }
888
889 bool fieldHasInterceptedSetter(Element element) {
890 assert(element.isField);
891 return interceptedElements[element.name] != null;
892 }
893
894 bool isInterceptedName(String name) {
895 return interceptedElements[name] != null;
896 }
897
898 bool isInterceptedSelector(Selector selector) {
899 return interceptedElements[selector.name] != null;
900 }
901
902 /**
903 * Returns `true` iff [selector] matches an element defined in a class mixed
904 * into an intercepted class. These selectors are not eligible for the 'dummy
905 * explicit receiver' optimization.
906 */
907 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) {
908 Set<Element> elements =
909 interceptedMixinElements.putIfAbsent(selector.name, () {
910 Set<Element> elements = interceptedElements[selector.name];
911 if (elements == null) return null;
912 return elements
913 .where((element) => classesMixedIntoInterceptedClasses
914 .contains(element.enclosingClass))
915 .toSet();
916 });
917
918 if (elements == null) return false;
919 if (elements.isEmpty) return false;
920 return elements.any((element) {
921 return selector.applies(element) &&
922 (mask == null ||
923 mask.canHit(element as MemberElement, selector, _closedWorld));
924 });
925 }
926
927 /// True if the given class is an internal class used for type inference
928 /// and never exists at runtime.
929 bool isCompileTimeOnlyClass(ClassElement class_) {
930 return class_ == helpers.jsPositiveIntClass ||
931 class_ == helpers.jsUInt32Class ||
932 class_ == helpers.jsUInt31Class ||
933 class_ == helpers.jsFixedArrayClass ||
934 class_ == helpers.jsUnmodifiableArrayClass ||
935 class_ == helpers.jsMutableArrayClass ||
936 class_ == helpers.jsExtendableArrayClass;
937 }
938
939 /// Maps compile-time classes to their runtime class. The runtime class is 801 /// Maps compile-time classes to their runtime class. The runtime class is
940 /// always a superclass or the class itself. 802 /// always a superclass or the class itself.
941 ClassElement getRuntimeClass(ClassElement class_) { 803 ClassElement getRuntimeClass(ClassElement class_) {
942 if (class_.isSubclassOf(helpers.jsIntClass)) return helpers.jsIntClass; 804 if (class_.isSubclassOf(helpers.jsIntClass)) return helpers.jsIntClass;
943 if (class_.isSubclassOf(helpers.jsArrayClass)) return helpers.jsArrayClass; 805 if (class_.isSubclassOf(helpers.jsArrayClass)) return helpers.jsArrayClass;
944 return class_; 806 return class_;
945 } 807 }
946 808
947 final Map<String, Set<ClassElement>> interceptedClassesCache =
948 new Map<String, Set<ClassElement>>();
949 final Set<ClassElement> _noClasses = new Set<ClassElement>();
950
951 /// Returns a set of interceptor classes that contain a member named [name]
952 ///
953 /// Returns an empty set if there is no class. Do not modify the returned set.
954 Set<ClassElement> getInterceptedClassesOn(String name) {
955 Set<Element> intercepted = interceptedElements[name];
956 if (intercepted == null) return _noClasses;
957 return interceptedClassesCache.putIfAbsent(name, () {
958 // Populate the cache by running through all the elements and
959 // determine if the given selector applies to them.
960 Set<ClassElement> result = new Set<ClassElement>();
961 for (Element element in intercepted) {
962 ClassElement classElement = element.enclosingClass;
963 if (isCompileTimeOnlyClass(classElement)) continue;
964 if (isNativeOrExtendsNative(classElement) ||
965 interceptedClasses.contains(classElement)) {
966 result.add(classElement);
967 }
968 if (classesMixedIntoInterceptedClasses.contains(classElement)) {
969 Set<ClassElement> nativeSubclasses =
970 nativeSubclassesOfMixin(classElement);
971 if (nativeSubclasses != null) result.addAll(nativeSubclasses);
972 }
973 }
974 return result;
975 });
976 }
977
978 Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) {
979 Iterable<MixinApplicationElement> uses = _closedWorld.mixinUsesOf(mixin);
980 Set<ClassElement> result = null;
981 for (MixinApplicationElement use in uses) {
982 _closedWorld.forEachStrictSubclassOf(use, (ClassElement subclass) {
983 if (isNativeOrExtendsNative(subclass)) {
984 if (result == null) result = new Set<ClassElement>();
985 result.add(subclass);
986 }
987 });
988 }
989 return result;
990 }
991
992 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) { 809 bool operatorEqHandlesNullArgument(FunctionElement operatorEqfunction) {
993 return specialOperatorEqClasses.contains(operatorEqfunction.enclosingClass); 810 return specialOperatorEqClasses.contains(operatorEqfunction.enclosingClass);
994 } 811 }
995 812
996 void validateInterceptorImplementsAllObjectMethods( 813 void validateInterceptorImplementsAllObjectMethods(
997 ClassElement interceptorClass) { 814 ClassElement interceptorClass) {
998 if (interceptorClass == null) return; 815 if (interceptorClass == null) return;
999 interceptorClass.ensureResolved(resolution); 816 interceptorClass.ensureResolved(resolution);
1000 ClassElement objectClass = commonElements.objectClass; 817 ClassElement objectClass = commonElements.objectClass;
1001 objectClass.forEachMember((_, Element member) { 818 objectClass.forEachMember((_, Element member) {
1002 if (member.isGenerativeConstructor) return; 819 if (member.isGenerativeConstructor) return;
1003 Element interceptorMember = interceptorClass.lookupMember(member.name); 820 Element interceptorMember = interceptorClass.lookupMember(member.name);
1004 // Interceptors must override all Object methods due to calling convention 821 // Interceptors must override all Object methods due to calling convention
1005 // differences. 822 // differences.
1006 assert(invariant(interceptorMember, 823 assert(invariant(interceptorMember,
1007 interceptorMember.enclosingClass == interceptorClass, 824 interceptorMember.enclosingClass == interceptorClass,
1008 message: 825 message:
1009 "Member ${member.name} not overridden in ${interceptorClass}. " 826 "Member ${member.name} not overridden in ${interceptorClass}. "
1010 "Found $interceptorMember from " 827 "Found $interceptorMember from "
1011 "${interceptorMember.enclosingClass}.")); 828 "${interceptorMember.enclosingClass}."));
1012 }); 829 });
1013 } 830 }
1014 831
1015 void addInterceptorsForNativeClassMembers(ClassElement cls, 832 void addInterceptorsForNativeClassMembers(ClassElement cls,
1016 {bool forResolution}) { 833 {bool forResolution}) {
1017 if (forResolution) { 834 if (forResolution) {
1018 cls.ensureResolved(resolution); 835 cls.ensureResolved(resolution);
1019 cls.forEachMember((ClassElement classElement, Element member) { 836 interceptorData.addInterceptorsForNativeClassMembers(cls);
1020 if (member.name == Identifiers.call) {
1021 return;
1022 }
1023 if (member.isSynthesized) return;
1024 // All methods on [Object] are shadowed by [Interceptor].
1025 if (classElement == commonElements.objectClass) return;
1026 Set<Element> set = interceptedElements.putIfAbsent(
1027 member.name, () => new Set<Element>());
1028 set.add(member);
1029 }, includeSuperAndInjectedMembers: true);
1030
1031 // Walk superclass chain to find mixins.
1032 for (; cls != null; cls = cls.superclass) {
1033 if (cls.isMixinApplication) {
1034 MixinApplicationElement mixinApplication = cls;
1035 classesMixedIntoInterceptedClasses.add(mixinApplication.mixin);
1036 }
1037 }
1038 } 837 }
1039 } 838 }
1040 839
1041 void addInterceptors(ClassElement cls, WorldImpactBuilder impactBuilder, 840 void addInterceptors(ClassElement cls, WorldImpactBuilder impactBuilder,
1042 {bool forResolution}) { 841 {bool forResolution}) {
1043 if (forResolution) { 842 if (forResolution) {
1044 if (_interceptedClasses.add(cls)) { 843 cls.ensureResolved(resolution);
1045 cls.ensureResolved(resolution); 844 interceptorData.addInterceptors(cls);
1046 cls.forEachMember((ClassElement classElement, Element member) {
1047 // All methods on [Object] are shadowed by [Interceptor].
1048 if (classElement == commonElements.objectClass) return;
1049 Set<Element> set = interceptedElements.putIfAbsent(
1050 member.name, () => new Set<Element>());
1051 set.add(member);
1052 }, includeSuperAndInjectedMembers: true);
1053 }
1054 _interceptedClasses.add(helpers.jsInterceptorClass);
1055 } 845 }
1056 impactTransformer.registerBackendInstantiation(impactBuilder, cls); 846 impactTransformer.registerBackendInstantiation(impactBuilder, cls);
1057 } 847 }
1058 848
1059 Set<ClassElement> get interceptedClasses {
1060 assert(compiler.enqueuer.resolution.queueIsClosed);
1061 return _interceptedClasses;
1062 }
1063
1064 void registerSpecializedGetInterceptor(Set<ClassElement> classes) {
1065 jsAst.Name name = namer.nameForGetInterceptor(classes);
1066 if (classes.contains(helpers.jsInterceptorClass)) {
1067 // We can't use a specialized [getInterceptorMethod], so we make
1068 // sure we emit the one with all checks.
1069 specializedGetInterceptors[name] = interceptedClasses;
1070 } else {
1071 specializedGetInterceptors[name] = classes;
1072 }
1073 }
1074
1075 /// Called during codegen when [constant] has been used. 849 /// Called during codegen when [constant] has been used.
1076 void computeImpactForCompileTimeConstant(ConstantValue constant, 850 void computeImpactForCompileTimeConstant(ConstantValue constant,
1077 WorldImpactBuilder impactBuilder, bool isForResolution) { 851 WorldImpactBuilder impactBuilder, bool isForResolution) {
1078 computeImpactForCompileTimeConstantInternal( 852 computeImpactForCompileTimeConstantInternal(
1079 constant, impactBuilder, isForResolution); 853 constant, impactBuilder, isForResolution);
1080 854
1081 if (!isForResolution && lookupMapAnalysis.isLookupMap(constant)) { 855 if (!isForResolution && lookupMapAnalysis.isLookupMap(constant)) {
1082 // Note: internally, this registration will temporarily remove the 856 // Note: internally, this registration will temporarily remove the
1083 // constant dependencies and add them later on-demand. 857 // constant dependencies and add them later on-demand.
1084 lookupMapAnalysis.registerLookupMapReference(constant); 858 lookupMapAnalysis.registerLookupMapReference(constant);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 impactBuilder, impacts.functionClass); 956 impactBuilder, impacts.functionClass);
1183 } else if (cls == commonElements.mapClass) { 957 } else if (cls == commonElements.mapClass) {
1184 impactTransformer.registerBackendImpact( 958 impactTransformer.registerBackendImpact(
1185 impactBuilder, impacts.mapClass); 959 impactBuilder, impacts.mapClass);
1186 // For map literals, the dependency between the implementation class 960 // For map literals, the dependency between the implementation class
1187 // and [Map] is not visible, so we have to add it manually. 961 // and [Map] is not visible, so we have to add it manually.
1188 rti.registerRtiDependency(helpers.mapLiteralClass, cls); 962 rti.registerRtiDependency(helpers.mapLiteralClass, cls);
1189 } else if (cls == helpers.boundClosureClass) { 963 } else if (cls == helpers.boundClosureClass) {
1190 impactTransformer.registerBackendImpact( 964 impactTransformer.registerBackendImpact(
1191 impactBuilder, impacts.boundClosureClass); 965 impactBuilder, impacts.boundClosureClass);
1192 } else if (isNativeOrExtendsNative(cls)) { 966 } else if (nativeData.isNativeOrExtendsNative(cls)) {
1193 impactTransformer.registerBackendImpact( 967 impactTransformer.registerBackendImpact(
1194 impactBuilder, impacts.nativeOrExtendsClass); 968 impactBuilder, impacts.nativeOrExtendsClass);
1195 } else if (cls == helpers.mapLiteralClass) { 969 } else if (cls == helpers.mapLiteralClass) {
1196 impactTransformer.registerBackendImpact( 970 impactTransformer.registerBackendImpact(
1197 impactBuilder, impacts.mapLiteralClass); 971 impactBuilder, impacts.mapLiteralClass);
1198 } 972 }
1199 } 973 }
1200 if (cls == helpers.closureClass) { 974 if (cls == helpers.closureClass) {
1201 impactTransformer.registerBackendImpact( 975 impactTransformer.registerBackendImpact(
1202 impactBuilder, impacts.closureClass); 976 impactBuilder, impacts.closureClass);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1264 forResolution: forResolution); 1038 forResolution: forResolution);
1265 } else if (cls == helpers.jsPlainJavaScriptObjectClass) { 1039 } else if (cls == helpers.jsPlainJavaScriptObjectClass) {
1266 addInterceptors(helpers.jsPlainJavaScriptObjectClass, impactBuilder, 1040 addInterceptors(helpers.jsPlainJavaScriptObjectClass, impactBuilder,
1267 forResolution: forResolution); 1041 forResolution: forResolution);
1268 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) { 1042 } else if (cls == helpers.jsUnknownJavaScriptObjectClass) {
1269 addInterceptors(helpers.jsUnknownJavaScriptObjectClass, impactBuilder, 1043 addInterceptors(helpers.jsUnknownJavaScriptObjectClass, impactBuilder,
1270 forResolution: forResolution); 1044 forResolution: forResolution);
1271 } else if (cls == helpers.jsJavaScriptFunctionClass) { 1045 } else if (cls == helpers.jsJavaScriptFunctionClass) {
1272 addInterceptors(helpers.jsJavaScriptFunctionClass, impactBuilder, 1046 addInterceptors(helpers.jsJavaScriptFunctionClass, impactBuilder,
1273 forResolution: forResolution); 1047 forResolution: forResolution);
1274 } else if (isNativeOrExtendsNative(cls)) { 1048 } else if (nativeData.isNativeOrExtendsNative(cls)) {
1275 addInterceptorsForNativeClassMembers(cls, forResolution: forResolution); 1049 addInterceptorsForNativeClassMembers(cls, forResolution: forResolution);
1276 } else if (cls == helpers.jsIndexingBehaviorInterface) { 1050 } else if (cls == helpers.jsIndexingBehaviorInterface) {
1277 impactTransformer.registerBackendImpact( 1051 impactTransformer.registerBackendImpact(
1278 impactBuilder, impacts.jsIndexingBehavior); 1052 impactBuilder, impacts.jsIndexingBehavior);
1279 } 1053 }
1280 1054
1281 customElementsAnalysis.registerInstantiatedClass(cls, 1055 customElementsAnalysis.registerInstantiatedClass(cls,
1282 forResolution: forResolution); 1056 forResolution: forResolution);
1283 if (!forResolution) { 1057 if (!forResolution) {
1284 lookupMapAnalysis.registerInstantiatedClass(cls); 1058 lookupMapAnalysis.registerInstantiatedClass(cls);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1319 1093
1320 void onResolutionComplete( 1094 void onResolutionComplete(
1321 ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) { 1095 ClosedWorld closedWorld, ClosedWorldRefiner closedWorldRefiner) {
1322 for (Entity entity in compiler.enqueuer.resolution.processedEntities) { 1096 for (Entity entity in compiler.enqueuer.resolution.processedEntities) {
1323 processAnnotations(entity, closedWorldRefiner); 1097 processAnnotations(entity, closedWorldRefiner);
1324 } 1098 }
1325 computeMembersNeededForReflection(closedWorld); 1099 computeMembersNeededForReflection(closedWorld);
1326 rti.computeClassesNeedingRti( 1100 rti.computeClassesNeedingRti(
1327 compiler.enqueuer.resolution.worldBuilder, closedWorld); 1101 compiler.enqueuer.resolution.worldBuilder, closedWorld);
1328 _registeredMetadata.clear(); 1102 _registeredMetadata.clear();
1103 interceptorData.onResolutionComplete(closedWorld);
1329 } 1104 }
1330 1105
1331 void onTypeInferenceComplete() { 1106 void onTypeInferenceComplete() {
1332 noSuchMethodRegistry.onTypeInferenceComplete(); 1107 noSuchMethodRegistry.onTypeInferenceComplete();
1333 } 1108 }
1334 1109
1335 /// Called to register that an instantiated generic class has a call method. 1110 /// Called to register that an instantiated generic class has a call method.
1336 /// Any backend specific [WorldImpact] of this is returned. 1111 /// Any backend specific [WorldImpact] of this is returned.
1337 /// 1112 ///
1338 /// Note: The [callMethod] is registered even thought it doesn't reference 1113 /// Note: The [callMethod] is registered even thought it doesn't reference
(...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after
1795 element == helpers.jsFixedArrayClass || 1570 element == helpers.jsFixedArrayClass ||
1796 element == helpers.jsUnmodifiableArrayClass; 1571 element == helpers.jsUnmodifiableArrayClass;
1797 } 1572 }
1798 1573
1799 bool mayGenerateInstanceofCheck(ResolutionDartType type) { 1574 bool mayGenerateInstanceofCheck(ResolutionDartType type) {
1800 // We can use an instanceof check for raw types that have no subclass that 1575 // We can use an instanceof check for raw types that have no subclass that
1801 // is mixed-in or in an implements clause. 1576 // is mixed-in or in an implements clause.
1802 1577
1803 if (!type.isRaw) return false; 1578 if (!type.isRaw) return false;
1804 ClassElement classElement = type.element; 1579 ClassElement classElement = type.element;
1805 if (isInterceptorClass(classElement)) return false; 1580 if (interceptorData.isInterceptorClass(classElement)) return false;
1806 return _closedWorld.hasOnlySubclasses(classElement); 1581 return _closedWorld.hasOnlySubclasses(classElement);
1807 } 1582 }
1808 1583
1809 /// Called to register that [element] is statically known to be used. Any 1584 /// Called to register that [element] is statically known to be used. Any
1810 /// backend specific [WorldImpact] of this is returned. 1585 /// backend specific [WorldImpact] of this is returned.
1811 WorldImpact registerUsedElement(MemberElement element, {bool forResolution}) { 1586 WorldImpact registerUsedElement(MemberElement element, {bool forResolution}) {
1812 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl(); 1587 WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl();
1813 if (element == helpers.disableTreeShakingMarker) { 1588 if (element == helpers.disableTreeShakingMarker) {
1814 isTreeShakingDisabled = true; 1589 isTreeShakingDisabled = true;
1815 } else if (element == helpers.preserveNamesMarker) { 1590 } else if (element == helpers.preserveNamesMarker) {
(...skipping 1429 matching lines...) Expand 10 before | Expand all | Expand 10 after
3245 break; 3020 break;
3246 default: 3021 default:
3247 } 3022 }
3248 } 3023 }
3249 3024
3250 for (String name in impact.constSymbols) { 3025 for (String name in impact.constSymbols) {
3251 backend.registerConstSymbol(name); 3026 backend.registerConstSymbol(name);
3252 } 3027 }
3253 3028
3254 for (Set<ClassElement> classes in impact.specializedGetInterceptors) { 3029 for (Set<ClassElement> classes in impact.specializedGetInterceptors) {
3255 backend.registerSpecializedGetInterceptor(classes); 3030 backend.interceptorData
3031 .registerSpecializedGetInterceptor(classes, backend.namer);
3256 } 3032 }
3257 3033
3258 if (impact.usesInterceptor) { 3034 if (impact.usesInterceptor) {
3259 if (backend.codegenEnqueuer.nativeEnqueuer.hasInstantiatedNativeClasses) { 3035 if (backend.codegenEnqueuer.nativeEnqueuer.hasInstantiatedNativeClasses) {
3260 registerBackendImpact(transformed, impacts.interceptorUse); 3036 registerBackendImpact(transformed, impacts.interceptorUse);
3261 } 3037 }
3262 } 3038 }
3263 3039
3264 for (ClassElement element in impact.typeConstants) { 3040 for (ClassElement element in impact.typeConstants) {
3265 backend.customElementsAnalysis.registerTypeConstant(element); 3041 backend.customElementsAnalysis.registerTypeConstant(element);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
3335 void onImpactUsed(ImpactUseCase impactUse) { 3111 void onImpactUsed(ImpactUseCase impactUse) {
3336 if (impactUse == DeferredLoadTask.IMPACT_USE && !supportSerialization) { 3112 if (impactUse == DeferredLoadTask.IMPACT_USE && !supportSerialization) {
3337 // TODO(johnniwinther): Allow emptying when serialization has been 3113 // TODO(johnniwinther): Allow emptying when serialization has been
3338 // performed. 3114 // performed.
3339 resolution.emptyCache(); 3115 resolution.emptyCache();
3340 } 3116 }
3341 } 3117 }
3342 } 3118 }
3343 3119
3344 class JavaScriptBackendClasses implements BackendClasses { 3120 class JavaScriptBackendClasses implements BackendClasses {
3121 final ElementEnvironment _env;
3345 final BackendHelpers helpers; 3122 final BackendHelpers helpers;
3123 final NativeData _nativeData;
3124 final InterceptorData _interceptorData;
3346 3125
3347 JavaScriptBackendClasses(this.helpers); 3126 JavaScriptBackendClasses(
3127 this._env, this.helpers, this._nativeData, this._interceptorData);
3348 3128
3349 ClassElement get intClass => helpers.jsIntClass; 3129 ClassElement get intClass => helpers.jsIntClass;
3350 ClassElement get uint32Class => helpers.jsUInt32Class; 3130 ClassElement get uint32Class => helpers.jsUInt32Class;
3351 ClassElement get uint31Class => helpers.jsUInt31Class; 3131 ClassElement get uint31Class => helpers.jsUInt31Class;
3352 ClassElement get positiveIntClass => helpers.jsPositiveIntClass; 3132 ClassElement get positiveIntClass => helpers.jsPositiveIntClass;
3353 ClassElement get doubleClass => helpers.jsDoubleClass; 3133 ClassElement get doubleClass => helpers.jsDoubleClass;
3354 ClassElement get numClass => helpers.jsNumberClass; 3134 ClassElement get numClass => helpers.jsNumberClass;
3355 ClassElement get stringClass => helpers.jsStringClass; 3135 ClassElement get stringClass => helpers.jsStringClass;
3356 ClassElement get listClass => helpers.jsArrayClass; 3136 ClassElement get listClass => helpers.jsArrayClass;
3357 ClassElement get mutableListClass => helpers.jsMutableArrayClass; 3137 ClassElement get mutableListClass => helpers.jsMutableArrayClass;
3358 ClassElement get constListClass => helpers.jsUnmodifiableArrayClass; 3138 ClassElement get constListClass => helpers.jsUnmodifiableArrayClass;
3359 ClassElement get fixedListClass => helpers.jsFixedArrayClass; 3139 ClassElement get fixedListClass => helpers.jsFixedArrayClass;
3360 ClassElement get growableListClass => helpers.jsExtendableArrayClass; 3140 ClassElement get growableListClass => helpers.jsExtendableArrayClass;
3361 ClassElement get mapClass => helpers.mapLiteralClass; 3141 ClassElement get mapClass => helpers.mapLiteralClass;
3362 ClassElement get constMapClass => helpers.constMapLiteralClass; 3142 ClassElement get constMapClass => helpers.constMapLiteralClass;
3363 ClassElement get typeClass => helpers.typeLiteralClass; 3143 ClassElement get typeClass => helpers.typeLiteralClass;
3364 ResolutionInterfaceType get typeType { 3144 InterfaceType get typeType => _env.getRawType(typeClass);
3365 return typeClass.computeType(helpers.backend.compiler.resolution);
3366 }
3367 3145
3368 ClassElement get boolClass => helpers.jsBoolClass; 3146 ClassElement get boolClass => helpers.jsBoolClass;
3369 ClassElement get nullClass => helpers.jsNullClass; 3147 ClassElement get nullClass => helpers.jsNullClass;
3370 ClassElement get syncStarIterableClass => helpers.syncStarIterable; 3148 ClassElement get syncStarIterableClass => helpers.syncStarIterable;
3371 ClassElement get asyncFutureClass => helpers.futureImplementation; 3149 ClassElement get asyncFutureClass => helpers.futureImplementation;
3372 ClassElement get asyncStarStreamClass => helpers.controllerStream; 3150 ClassElement get asyncStarStreamClass => helpers.controllerStream;
3373 ClassElement get functionClass => helpers.commonElements.functionClass; 3151 ClassElement get functionClass => helpers.commonElements.functionClass;
3374 ClassElement get indexableClass => helpers.jsIndexableClass; 3152 ClassElement get indexableClass => helpers.jsIndexableClass;
3375 ClassElement get mutableIndexableClass => helpers.jsMutableIndexableClass; 3153 ClassElement get mutableIndexableClass => helpers.jsMutableIndexableClass;
3376 ClassElement get indexingBehaviorClass => helpers.jsIndexingBehaviorInterface; 3154 ClassElement get indexingBehaviorClass => helpers.jsIndexingBehaviorInterface;
3377 ClassElement get interceptorClass => helpers.jsInterceptorClass; 3155 ClassElement get interceptorClass => helpers.jsInterceptorClass;
3378 3156
3379 bool isDefaultEqualityImplementation(MemberElement element) { 3157 bool isDefaultEqualityImplementation(MemberElement element) {
3380 assert(element.name == '=='); 3158 assert(element.name == '==');
3381 ClassElement classElement = element.enclosingClass; 3159 ClassElement classElement = element.enclosingClass;
3382 return classElement == helpers.commonElements.objectClass || 3160 return classElement == helpers.commonElements.objectClass ||
3383 classElement == helpers.jsInterceptorClass || 3161 classElement == helpers.jsInterceptorClass ||
3384 classElement == helpers.jsNullClass; 3162 classElement == helpers.jsNullClass;
3385 } 3163 }
3386 3164
3387 @override 3165 @override
3388 bool isInterceptorClass(ClassElement cls) { 3166 bool isInterceptorClass(ClassElement cls) {
3389 return helpers.backend.isInterceptorClass(cls); 3167 return _interceptorData.isInterceptorClass(cls);
3390 } 3168 }
3391 3169
3392 @override 3170 @override
3393 bool isNativeClass(ClassElement element) { 3171 bool isNativeClass(ClassElement element) {
3394 return helpers.backend.isNative(element); 3172 return _nativeData.isNative(element);
3395 } 3173 }
3396 3174
3397 @override 3175 @override
3398 bool isNativeMember(MemberElement element) { 3176 bool isNativeMember(MemberElement element) {
3399 return helpers.backend.isNative(element); 3177 return _nativeData.isNative(element);
3400 } 3178 }
3401 } 3179 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_backend/backend_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698