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

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

Issue 2781483002: Mostly use Entity in InterceptorData (Closed)
Patch Set: Created 3 years, 8 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
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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.interceptor_data; 5 library js_backend.interceptor_data;
6 6
7 import '../common/names.dart' show Identifiers; 7 import '../common/names.dart' show Identifiers;
8 import '../common/resolution.dart' show Resolution; 8 import '../common/resolution.dart' show Resolution;
9 import '../common_elements.dart' show CommonElements; 9 import '../common_elements.dart' show CommonElements, ElementEnvironment;
10 import '../elements/elements.dart'; 10 import '../elements/elements.dart' show MemberElement;
11 import '../elements/entities.dart'; 11 import '../elements/entities.dart';
12 import '../elements/types.dart'; 12 import '../elements/types.dart';
13 import '../js/js.dart' as jsAst; 13 import '../js/js.dart' as jsAst;
14 import '../types/types.dart' show TypeMask; 14 import '../types/types.dart' show TypeMask;
15 import '../universe/selector.dart'; 15 import '../universe/selector.dart';
16 import '../world.dart' show ClosedWorld; 16 import '../world.dart' show ClosedWorld;
17 import 'backend_helpers.dart'; 17 import 'backend_helpers.dart';
18 import 'namer.dart'; 18 import 'namer.dart';
19 import 'native_data.dart'; 19 import 'native_data.dart';
20 20
(...skipping 28 matching lines...) Expand all
49 } 49 }
50 50
51 class InterceptorDataImpl implements InterceptorData { 51 class InterceptorDataImpl implements InterceptorData {
52 final NativeBasicData _nativeData; 52 final NativeBasicData _nativeData;
53 final BackendHelpers _helpers; 53 final BackendHelpers _helpers;
54 final ClosedWorld _closedWorld; 54 final ClosedWorld _closedWorld;
55 55
56 /// The members of instantiated interceptor classes: maps a member name to the 56 /// The members of instantiated interceptor classes: maps a member name to the
57 /// list of members that have that name. This map is used by the codegen to 57 /// list of members that have that name. This map is used by the codegen to
58 /// know whether a send must be intercepted or not. 58 /// know whether a send must be intercepted or not.
59 final Map<String, Set<Element>> _interceptedElements; 59 final Map<String, Set<MemberEntity>> _interceptedElements;
60 60
61 /// Set of classes whose methods are intercepted. 61 /// Set of classes whose methods are intercepted.
62 final Set<ClassElement> _interceptedClasses; 62 final Set<ClassEntity> _interceptedClasses;
63 63
64 /// Set of classes used as mixins on intercepted (native and primitive) 64 /// Set of classes used as mixins on intercepted (native and primitive)
65 /// classes. Methods on these classes might also be mixed in to regular Dart 65 /// classes. Methods on these classes might also be mixed in to regular Dart
66 /// (unintercepted) classes. 66 /// (unintercepted) classes.
67 final Set<ClassElement> _classesMixedIntoInterceptedClasses; 67 final Set<ClassEntity> _classesMixedIntoInterceptedClasses;
68 68
69 /// The members of mixin classes that are mixed into an instantiated 69 /// The members of mixin classes that are mixed into an instantiated
70 /// interceptor class. This is a cached subset of [_interceptedElements]. 70 /// interceptor class. This is a cached subset of [_interceptedElements].
71 /// 71 ///
72 /// Mixin methods are not specialized for the class they are mixed into. 72 /// Mixin methods are not specialized for the class they are mixed into.
73 /// Methods mixed into intercepted classes thus always make use of the 73 /// Methods mixed into intercepted classes thus always make use of the
74 /// explicit receiver argument, even when mixed into non-interceptor classes. 74 /// explicit receiver argument, even when mixed into non-interceptor classes.
75 /// 75 ///
76 /// These members must be invoked with a correct explicit receiver even when 76 /// These members must be invoked with a correct explicit receiver even when
77 /// the receiver is not an intercepted class. 77 /// the receiver is not an intercepted class.
78 final Map<String, Set<Element>> _interceptedMixinElements = 78 final Map<String, Set<MemberEntity>> _interceptedMixinElements =
79 new Map<String, Set<Element>>(); 79 new Map<String, Set<MemberEntity>>();
80 80
81 final Map<String, Set<ClassElement>> _interceptedClassesCache = 81 final Map<String, Set<ClassEntity>> _interceptedClassesCache =
82 new Map<String, Set<ClassElement>>(); 82 new Map<String, Set<ClassEntity>>();
83 83
84 final Set<ClassElement> _noClasses = new Set<ClassElement>(); 84 final Set<ClassEntity> _noClasses = new Set<ClassEntity>();
85 85
86 InterceptorDataImpl( 86 InterceptorDataImpl(
87 this._nativeData, 87 this._nativeData,
88 this._helpers, 88 this._helpers,
89 this._closedWorld, 89 this._closedWorld,
90 this._interceptedElements, 90 this._interceptedElements,
91 this._interceptedClasses, 91 this._interceptedClasses,
92 this._classesMixedIntoInterceptedClasses); 92 this._classesMixedIntoInterceptedClasses);
93 93
94 bool isInterceptedMethod(MemberElement element) { 94 bool isInterceptedMethod(MemberElement element) {
95 if (!element.isInstanceMember) return false; 95 if (!element.isInstanceMember) return false;
96 if (element.isGenerativeConstructorBody) { 96 if (element.isGenerativeConstructorBody) {
97 return _nativeData.isNativeOrExtendsNative(element.enclosingClass); 97 return _nativeData.isNativeOrExtendsNative(element.enclosingClass);
98 } 98 }
99 return _interceptedElements[element.name] != null; 99 return _interceptedElements[element.name] != null;
100 } 100 }
101 101
102 bool fieldHasInterceptedGetter(FieldElement element) { 102 bool fieldHasInterceptedGetter(FieldEntity element) {
103 return _interceptedElements[element.name] != null; 103 return _interceptedElements[element.name] != null;
104 } 104 }
105 105
106 bool fieldHasInterceptedSetter(FieldElement element) { 106 bool fieldHasInterceptedSetter(FieldEntity element) {
107 return _interceptedElements[element.name] != null; 107 return _interceptedElements[element.name] != null;
108 } 108 }
109 109
110 bool isInterceptedName(String name) { 110 bool isInterceptedName(String name) {
111 return _interceptedElements[name] != null; 111 return _interceptedElements[name] != null;
112 } 112 }
113 113
114 bool isInterceptedSelector(Selector selector) { 114 bool isInterceptedSelector(Selector selector) {
115 return _interceptedElements[selector.name] != null; 115 return _interceptedElements[selector.name] != null;
116 } 116 }
117 117
118 /// Returns `true` iff [selector] matches an element defined in a class mixed 118 /// Returns `true` iff [selector] matches an element defined in a class mixed
119 /// into an intercepted class. These selectors are not eligible for the 119 /// into an intercepted class. These selectors are not eligible for the
120 /// 'dummy explicit receiver' optimization. 120 /// 'dummy explicit receiver' optimization.
121 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) { 121 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) {
122 Set<Element> elements = 122 Set<MemberEntity> elements =
123 _interceptedMixinElements.putIfAbsent(selector.name, () { 123 _interceptedMixinElements.putIfAbsent(selector.name, () {
124 Set<Element> elements = _interceptedElements[selector.name]; 124 Set<MemberEntity> elements = _interceptedElements[selector.name];
125 if (elements == null) return null; 125 if (elements == null) return null;
126 return elements 126 return elements
127 .where((element) => _classesMixedIntoInterceptedClasses 127 .where((element) => _classesMixedIntoInterceptedClasses
128 .contains(element.enclosingClass)) 128 .contains(element.enclosingClass))
129 .toSet(); 129 .toSet();
130 }); 130 });
131 131
132 if (elements == null) return false; 132 if (elements == null) return false;
133 if (elements.isEmpty) return false; 133 if (elements.isEmpty) return false;
134 return elements.any((element) { 134 return elements.any((element) {
135 return selector.applies(element) && 135 return selector.applies(element) &&
136 (mask == null || 136 (mask == null || mask.canHit(element, selector, _closedWorld));
137 mask.canHit(element as MemberElement, selector, _closedWorld));
138 }); 137 });
139 } 138 }
140 139
141 /// True if the given class is an internal class used for type inference 140 /// True if the given class is an internal class used for type inference
142 /// and never exists at runtime. 141 /// and never exists at runtime.
143 bool _isCompileTimeOnlyClass(ClassElement class_) { 142 bool _isCompileTimeOnlyClass(ClassEntity class_) {
144 return class_ == _helpers.jsPositiveIntClass || 143 return class_ == _helpers.jsPositiveIntClass ||
145 class_ == _helpers.jsUInt32Class || 144 class_ == _helpers.jsUInt32Class ||
146 class_ == _helpers.jsUInt31Class || 145 class_ == _helpers.jsUInt31Class ||
147 class_ == _helpers.jsFixedArrayClass || 146 class_ == _helpers.jsFixedArrayClass ||
148 class_ == _helpers.jsUnmodifiableArrayClass || 147 class_ == _helpers.jsUnmodifiableArrayClass ||
149 class_ == _helpers.jsMutableArrayClass || 148 class_ == _helpers.jsMutableArrayClass ||
150 class_ == _helpers.jsExtendableArrayClass; 149 class_ == _helpers.jsExtendableArrayClass;
151 } 150 }
152 151
153 /// Returns a set of interceptor classes that contain a member named [name] 152 /// Returns a set of interceptor classes that contain a member named [name]
154 /// 153 ///
155 /// Returns an empty set if there is no class. Do not modify the returned set. 154 /// Returns an empty set if there is no class. Do not modify the returned set.
156 Set<ClassElement> getInterceptedClassesOn(String name) { 155 Set<ClassEntity> getInterceptedClassesOn(String name) {
157 Set<Element> intercepted = _interceptedElements[name]; 156 Set<MemberEntity> intercepted = _interceptedElements[name];
158 if (intercepted == null) return _noClasses; 157 if (intercepted == null) return _noClasses;
159 return _interceptedClassesCache.putIfAbsent(name, () { 158 return _interceptedClassesCache.putIfAbsent(name, () {
160 // Populate the cache by running through all the elements and 159 // Populate the cache by running through all the elements and
161 // determine if the given selector applies to them. 160 // determine if the given selector applies to them.
162 Set<ClassElement> result = new Set<ClassElement>(); 161 Set<ClassEntity> result = new Set<ClassEntity>();
163 for (Element element in intercepted) { 162 for (MemberEntity element in intercepted) {
164 ClassElement classElement = element.enclosingClass; 163 ClassEntity classElement = element.enclosingClass;
165 if (_isCompileTimeOnlyClass(classElement)) continue; 164 if (_isCompileTimeOnlyClass(classElement)) continue;
166 if (_nativeData.isNativeOrExtendsNative(classElement) || 165 if (_nativeData.isNativeOrExtendsNative(classElement) ||
167 interceptedClasses.contains(classElement)) { 166 interceptedClasses.contains(classElement)) {
168 result.add(classElement); 167 result.add(classElement);
169 } 168 }
170 if (_classesMixedIntoInterceptedClasses.contains(classElement)) { 169 if (_classesMixedIntoInterceptedClasses.contains(classElement)) {
171 Set<ClassElement> nativeSubclasses = 170 Set<ClassEntity> nativeSubclasses =
172 nativeSubclassesOfMixin(classElement); 171 nativeSubclassesOfMixin(classElement);
173 if (nativeSubclasses != null) result.addAll(nativeSubclasses); 172 if (nativeSubclasses != null) result.addAll(nativeSubclasses);
174 } 173 }
175 } 174 }
176 return result; 175 return result;
177 }); 176 });
178 } 177 }
179 178
180 Set<ClassElement> nativeSubclassesOfMixin(ClassElement mixin) { 179 Set<ClassEntity> nativeSubclassesOfMixin(ClassEntity mixin) {
181 Iterable<MixinApplicationElement> uses = _closedWorld.mixinUsesOf(mixin); 180 Iterable<ClassEntity> uses = _closedWorld.mixinUsesOf(mixin);
182 Set<ClassElement> result = null; 181 Set<ClassEntity> result = null;
183 for (MixinApplicationElement use in uses) { 182 for (ClassEntity use in uses) {
184 _closedWorld.forEachStrictSubclassOf(use, (ClassElement subclass) { 183 _closedWorld.forEachStrictSubclassOf(use, (ClassEntity subclass) {
185 if (_nativeData.isNativeOrExtendsNative(subclass)) { 184 if (_nativeData.isNativeOrExtendsNative(subclass)) {
186 if (result == null) result = new Set<ClassElement>(); 185 if (result == null) result = new Set<ClassEntity>();
187 result.add(subclass); 186 result.add(subclass);
188 } 187 }
189 }); 188 });
190 } 189 }
191 return result; 190 return result;
192 } 191 }
193 192
194 bool isInterceptedClass(ClassElement element) { 193 bool isInterceptedClass(ClassEntity element) {
195 if (element == null) return false; 194 if (element == null) return false;
196 if (_nativeData.isNativeOrExtendsNative(element)) return true; 195 if (_nativeData.isNativeOrExtendsNative(element)) return true;
197 if (interceptedClasses.contains(element)) return true; 196 if (interceptedClasses.contains(element)) return true;
198 if (_classesMixedIntoInterceptedClasses.contains(element)) return true; 197 if (_classesMixedIntoInterceptedClasses.contains(element)) return true;
199 return false; 198 return false;
200 } 199 }
201 200
202 bool isMixedIntoInterceptedClass(ClassElement element) => 201 bool isMixedIntoInterceptedClass(ClassEntity element) =>
203 _classesMixedIntoInterceptedClasses.contains(element); 202 _classesMixedIntoInterceptedClasses.contains(element);
204 203
205 Iterable<ClassElement> get interceptedClasses => _interceptedClasses; 204 Iterable<ClassEntity> get interceptedClasses => _interceptedClasses;
206 205
207 bool mayGenerateInstanceofCheck(DartType type) { 206 bool mayGenerateInstanceofCheck(DartType type) {
208 // We can use an instanceof check for raw types that have no subclass that 207 // We can use an instanceof check for raw types that have no subclass that
209 // is mixed-in or in an implements clause. 208 // is mixed-in or in an implements clause.
210 209
211 if (!type.treatAsRaw) return false; 210 if (!type.treatAsRaw) return false;
212 InterfaceType interfaceType = type; 211 InterfaceType interfaceType = type;
213 ClassEntity classElement = interfaceType.element; 212 ClassEntity classElement = interfaceType.element;
214 if (isInterceptedClass(classElement)) return false; 213 if (isInterceptedClass(classElement)) return false;
215 return _closedWorld.hasOnlySubclasses(classElement); 214 return _closedWorld.hasOnlySubclasses(classElement);
216 } 215 }
217 } 216 }
218 217
219 class InterceptorDataBuilderImpl implements InterceptorDataBuilder { 218 class InterceptorDataBuilderImpl implements InterceptorDataBuilder {
220 final NativeBasicData _nativeData; 219 final NativeBasicData _nativeData;
221 final BackendHelpers _helpers; 220 final BackendHelpers _helpers;
221 final ElementEnvironment _elementEnvironment;
222 final CommonElements _commonElements; 222 final CommonElements _commonElements;
223 final Resolution _resolution; 223 final Resolution _resolution;
224 224
225 /// The members of instantiated interceptor classes: maps a member name to the 225 /// The members of instantiated interceptor classes: maps a member name to the
226 /// list of members that have that name. This map is used by the codegen to 226 /// list of members that have that name. This map is used by the codegen to
227 /// know whether a send must be intercepted or not. 227 /// know whether a send must be intercepted or not.
228 final Map<String, Set<Element>> _interceptedElements = 228 final Map<String, Set<MemberEntity>> _interceptedElements =
229 <String, Set<Element>>{}; 229 <String, Set<MemberEntity>>{};
230 230
231 /// Set of classes whose methods are intercepted. 231 /// Set of classes whose methods are intercepted.
232 final Set<ClassElement> _interceptedClasses = new Set<ClassElement>(); 232 final Set<ClassEntity> _interceptedClasses = new Set<ClassEntity>();
233 233
234 /// Set of classes used as mixins on intercepted (native and primitive) 234 /// Set of classes used as mixins on intercepted (native and primitive)
235 /// classes. Methods on these classes might also be mixed in to regular Dart 235 /// classes. Methods on these classes might also be mixed in to regular Dart
236 /// (unintercepted) classes. 236 /// (unintercepted) classes.
237 final Set<ClassElement> _classesMixedIntoInterceptedClasses = 237 final Set<ClassEntity> _classesMixedIntoInterceptedClasses =
238 new Set<ClassElement>(); 238 new Set<ClassEntity>();
239 239
240 InterceptorDataBuilderImpl( 240 InterceptorDataBuilderImpl(this._nativeData, this._helpers,
241 this._nativeData, this._helpers, this._commonElements, this._resolution); 241 this._elementEnvironment, this._commonElements, this._resolution);
242 242
243 InterceptorData onResolutionComplete(ClosedWorld closedWorld) { 243 InterceptorData onResolutionComplete(ClosedWorld closedWorld) {
244 return new InterceptorDataImpl( 244 return new InterceptorDataImpl(
245 _nativeData, 245 _nativeData,
246 _helpers, 246 _helpers,
247 closedWorld, 247 closedWorld,
248 _interceptedElements, 248 _interceptedElements,
249 _interceptedClasses, 249 _interceptedClasses,
250 _classesMixedIntoInterceptedClasses); 250 _classesMixedIntoInterceptedClasses);
251 } 251 }
252 252
253 void addInterceptorsForNativeClassMembers(ClassElement cls) { 253 void addInterceptorsForNativeClassMembers(ClassEntity cls) {
254 cls.ensureResolved(_resolution); 254 _elementEnvironment.forEachClassMember(cls,
255 cls.forEachMember((ClassElement classElement, Element member) { 255 (ClassEntity cls, MemberEntity member) {
256 if (member.name == Identifiers.call) { 256 if (member.name == Identifiers.call) return;
257 return;
258 }
259 if (member.isSynthesized) return;
260 // All methods on [Object] are shadowed by [Interceptor]. 257 // All methods on [Object] are shadowed by [Interceptor].
261 if (classElement == _commonElements.objectClass) return; 258 if (cls == _commonElements.objectClass) return;
262 Set<Element> set = _interceptedElements.putIfAbsent( 259 Set<MemberEntity> set = _interceptedElements.putIfAbsent(
263 member.name, () => new Set<Element>()); 260 member.name, () => new Set<MemberEntity>());
264 set.add(member); 261 set.add(member);
265 }, includeSuperAndInjectedMembers: true); 262 });
266 263
267 // Walk superclass chain to find mixins. 264 // Walk superclass chain to find mixins.
268 for (; cls != null; cls = cls.superclass) { 265 _elementEnvironment.forEachMixin(cls, (ClassEntity mixin) {
269 if (cls.isMixinApplication) { 266 _classesMixedIntoInterceptedClasses.add(mixin);
270 MixinApplicationElement mixinApplication = cls; 267 });
271 _classesMixedIntoInterceptedClasses.add(mixinApplication.mixin);
272 }
273 }
274 } 268 }
275 269
276 void addInterceptors(ClassElement cls) { 270 void addInterceptors(ClassEntity cls) {
277 if (_interceptedClasses.add(cls)) { 271 if (_interceptedClasses.add(cls)) {
278 cls.ensureResolved(_resolution); 272 _elementEnvironment.forEachClassMember(cls,
279 cls.forEachMember((ClassElement classElement, Element member) { 273 (ClassEntity cls, MemberEntity member) {
280 // All methods on [Object] are shadowed by [Interceptor]. 274 // All methods on [Object] are shadowed by [Interceptor].
281 if (classElement == _commonElements.objectClass) return; 275 if (cls == _commonElements.objectClass) return;
282 Set<Element> set = _interceptedElements.putIfAbsent( 276 Set<MemberEntity> set = _interceptedElements.putIfAbsent(
283 member.name, () => new Set<Element>()); 277 member.name, () => new Set<MemberEntity>());
284 set.add(member); 278 set.add(member);
285 }, includeSuperAndInjectedMembers: true); 279 });
286 } 280 }
287 _interceptedClasses.add(_helpers.jsInterceptorClass); 281 _interceptedClasses.add(_helpers.jsInterceptorClass);
288 } 282 }
289 } 283 }
290 284
291 class OneShotInterceptorData { 285 class OneShotInterceptorData {
292 final InterceptorData _interceptorData; 286 final InterceptorData _interceptorData;
293 final BackendHelpers _helpers; 287 final BackendHelpers _helpers;
294 288
295 OneShotInterceptorData(this._interceptorData, this._helpers); 289 OneShotInterceptorData(this._interceptorData, this._helpers);
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 jsAst.Name name = namer.nameForGetInterceptor(classes); 329 jsAst.Name name = namer.nameForGetInterceptor(classes);
336 if (classes.contains(_helpers.jsInterceptorClass)) { 330 if (classes.contains(_helpers.jsInterceptorClass)) {
337 // We can't use a specialized [getInterceptorMethod], so we make 331 // We can't use a specialized [getInterceptorMethod], so we make
338 // sure we emit the one with all checks. 332 // sure we emit the one with all checks.
339 _specializedGetInterceptors[name] = _interceptorData.interceptedClasses; 333 _specializedGetInterceptors[name] = _interceptorData.interceptedClasses;
340 } else { 334 } else {
341 _specializedGetInterceptors[name] = classes; 335 _specializedGetInterceptors[name] = classes;
342 } 336 }
343 } 337 }
344 } 338 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/impact_transformer.dart ('k') | pkg/compiler/lib/src/js_backend/minify_namer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698