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

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

Issue 2828873002: Revert "Remove JavaScriptBackend from ClosedWorldBase" (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_elements.dart' show CommonElements, ElementEnvironment; 8 import '../common_elements.dart' show CommonElements, ElementEnvironment;
9 import '../elements/elements.dart' show MemberElement; 9 import '../elements/elements.dart' show MemberElement;
10 import '../elements/entities.dart'; 10 import '../elements/entities.dart';
11 import '../elements/types.dart'; 11 import '../elements/types.dart';
12 import '../js/js.dart' as jsAst; 12 import '../js/js.dart' as jsAst;
13 import '../types/types.dart' show TypeMask; 13 import '../types/types.dart' show TypeMask;
14 import '../universe/selector.dart'; 14 import '../universe/selector.dart';
15 import '../world.dart' show ClosedWorld; 15 import '../world.dart' show ClosedWorld;
16 import 'namer.dart'; 16 import 'namer.dart';
17 import 'native_data.dart'; 17 import 'native_data.dart';
18 18
19 abstract class InterceptorData { 19 abstract class InterceptorData {
20 /// Returns `true` if [cls] is an intercepted class. 20 /// Returns `true` if [cls] is an intercepted class.
21 bool isInterceptedClass(ClassEntity element); 21 bool isInterceptedClass(ClassEntity element);
22 22
23 bool isInterceptedMethod(MemberEntity element); 23 bool isInterceptedMethod(MemberEntity element);
24 bool fieldHasInterceptedGetter(FieldEntity element); 24 bool fieldHasInterceptedGetter(FieldEntity element);
25 bool fieldHasInterceptedSetter(FieldEntity element); 25 bool fieldHasInterceptedSetter(FieldEntity element);
26 bool isInterceptedName(String name); 26 bool isInterceptedName(String name);
27 bool isInterceptedSelector(Selector selector); 27 bool isInterceptedSelector(Selector selector);
28 bool isInterceptedMixinSelector( 28 bool isInterceptedMixinSelector(Selector selector, TypeMask mask);
29 Selector selector, TypeMask mask, ClosedWorld closedWorld);
30 Iterable<ClassEntity> get interceptedClasses; 29 Iterable<ClassEntity> get interceptedClasses;
31 bool isMixedIntoInterceptedClass(ClassEntity element); 30 bool isMixedIntoInterceptedClass(ClassEntity element);
32 31
33 /// Returns a set of interceptor classes that contain a member named [name] 32 /// Returns a set of interceptor classes that contain a member named [name]
34 /// 33 ///
35 /// Returns an empty set if there is no class. Do not modify the returned set. 34 /// Returns an empty set if there is no class. Do not modify the returned set.
36 Set<ClassEntity> getInterceptedClassesOn( 35 Set<ClassEntity> getInterceptedClassesOn(String name);
37 String name, ClosedWorld closedWorld);
38 36
39 /// Whether the compiler can use the native `instanceof` check to test for 37 /// Whether the compiler can use the native `instanceof` check to test for
40 /// instances of [type]. This is true for types that are not used as mixins or 38 /// instances of [type]. This is true for types that are not used as mixins or
41 /// interfaces. 39 /// interfaces.
42 bool mayGenerateInstanceofCheck(DartType type, ClosedWorld closedWorld); 40 bool mayGenerateInstanceofCheck(DartType type);
43 } 41 }
44 42
45 abstract class InterceptorDataBuilder { 43 abstract class InterceptorDataBuilder {
46 void addInterceptors(ClassEntity cls); 44 void addInterceptors(ClassEntity cls);
47 void addInterceptorsForNativeClassMembers(ClassEntity cls); 45 void addInterceptorsForNativeClassMembers(ClassEntity cls);
48 InterceptorData onResolutionComplete(); 46 InterceptorData onResolutionComplete(ClosedWorld closedWorld);
49 } 47 }
50 48
51 class InterceptorDataImpl implements InterceptorData { 49 class InterceptorDataImpl implements InterceptorData {
52 final NativeBasicData _nativeData; 50 final NativeBasicData _nativeData;
53 final CommonElements _commonElements; 51 final CommonElements _commonElements;
52 final ClosedWorld _closedWorld;
54 53
55 /// The members of instantiated interceptor classes: maps a member name to the 54 /// The members of instantiated interceptor classes: maps a member name to the
56 /// list of members that have that name. This map is used by the codegen to 55 /// list of members that have that name. This map is used by the codegen to
57 /// know whether a send must be intercepted or not. 56 /// know whether a send must be intercepted or not.
58 final Map<String, Set<MemberEntity>> _interceptedElements; 57 final Map<String, Set<MemberEntity>> _interceptedElements;
59 58
60 /// Set of classes whose methods are intercepted. 59 /// Set of classes whose methods are intercepted.
61 final Set<ClassEntity> _interceptedClasses; 60 final Set<ClassEntity> _interceptedClasses;
62 61
63 /// Set of classes used as mixins on intercepted (native and primitive) 62 /// Set of classes used as mixins on intercepted (native and primitive)
(...skipping 14 matching lines...) Expand all
78 new Map<String, Set<MemberEntity>>(); 77 new Map<String, Set<MemberEntity>>();
79 78
80 final Map<String, Set<ClassEntity>> _interceptedClassesCache = 79 final Map<String, Set<ClassEntity>> _interceptedClassesCache =
81 new Map<String, Set<ClassEntity>>(); 80 new Map<String, Set<ClassEntity>>();
82 81
83 final Set<ClassEntity> _noClasses = new Set<ClassEntity>(); 82 final Set<ClassEntity> _noClasses = new Set<ClassEntity>();
84 83
85 InterceptorDataImpl( 84 InterceptorDataImpl(
86 this._nativeData, 85 this._nativeData,
87 this._commonElements, 86 this._commonElements,
87 this._closedWorld,
88 this._interceptedElements, 88 this._interceptedElements,
89 this._interceptedClasses, 89 this._interceptedClasses,
90 this._classesMixedIntoInterceptedClasses); 90 this._classesMixedIntoInterceptedClasses);
91 91
92 bool isInterceptedMethod(MemberElement element) { 92 bool isInterceptedMethod(MemberElement element) {
93 if (!element.isInstanceMember) return false; 93 if (!element.isInstanceMember) return false;
94 if (element.isGenerativeConstructorBody) { 94 if (element.isGenerativeConstructorBody) {
95 return _nativeData.isNativeOrExtendsNative(element.enclosingClass); 95 return _nativeData.isNativeOrExtendsNative(element.enclosingClass);
96 } 96 }
97 return _interceptedElements[element.name] != null; 97 return _interceptedElements[element.name] != null;
(...skipping 11 matching lines...) Expand all
109 return _interceptedElements[name] != null; 109 return _interceptedElements[name] != null;
110 } 110 }
111 111
112 bool isInterceptedSelector(Selector selector) { 112 bool isInterceptedSelector(Selector selector) {
113 return _interceptedElements[selector.name] != null; 113 return _interceptedElements[selector.name] != null;
114 } 114 }
115 115
116 /// Returns `true` iff [selector] matches an element defined in a class mixed 116 /// Returns `true` iff [selector] matches an element defined in a class mixed
117 /// into an intercepted class. These selectors are not eligible for the 117 /// into an intercepted class. These selectors are not eligible for the
118 /// 'dummy explicit receiver' optimization. 118 /// 'dummy explicit receiver' optimization.
119 bool isInterceptedMixinSelector( 119 bool isInterceptedMixinSelector(Selector selector, TypeMask mask) {
120 Selector selector, TypeMask mask, ClosedWorld closedWorld) {
121 Set<MemberEntity> elements = 120 Set<MemberEntity> elements =
122 _interceptedMixinElements.putIfAbsent(selector.name, () { 121 _interceptedMixinElements.putIfAbsent(selector.name, () {
123 Set<MemberEntity> elements = _interceptedElements[selector.name]; 122 Set<MemberEntity> elements = _interceptedElements[selector.name];
124 if (elements == null) return null; 123 if (elements == null) return null;
125 return elements 124 return elements
126 .where((element) => _classesMixedIntoInterceptedClasses 125 .where((element) => _classesMixedIntoInterceptedClasses
127 .contains(element.enclosingClass)) 126 .contains(element.enclosingClass))
128 .toSet(); 127 .toSet();
129 }); 128 });
130 129
131 if (elements == null) return false; 130 if (elements == null) return false;
132 if (elements.isEmpty) return false; 131 if (elements.isEmpty) return false;
133 return elements.any((element) { 132 return elements.any((element) {
134 return selector.applies(element) && 133 return selector.applies(element) &&
135 (mask == null || mask.canHit(element, selector, closedWorld)); 134 (mask == null || mask.canHit(element, selector, _closedWorld));
136 }); 135 });
137 } 136 }
138 137
139 /// True if the given class is an internal class used for type inference 138 /// True if the given class is an internal class used for type inference
140 /// and never exists at runtime. 139 /// and never exists at runtime.
141 bool _isCompileTimeOnlyClass(ClassEntity class_) { 140 bool _isCompileTimeOnlyClass(ClassEntity class_) {
142 return class_ == _commonElements.jsPositiveIntClass || 141 return class_ == _commonElements.jsPositiveIntClass ||
143 class_ == _commonElements.jsUInt32Class || 142 class_ == _commonElements.jsUInt32Class ||
144 class_ == _commonElements.jsUInt31Class || 143 class_ == _commonElements.jsUInt31Class ||
145 class_ == _commonElements.jsFixedArrayClass || 144 class_ == _commonElements.jsFixedArrayClass ||
146 class_ == _commonElements.jsUnmodifiableArrayClass || 145 class_ == _commonElements.jsUnmodifiableArrayClass ||
147 class_ == _commonElements.jsMutableArrayClass || 146 class_ == _commonElements.jsMutableArrayClass ||
148 class_ == _commonElements.jsExtendableArrayClass; 147 class_ == _commonElements.jsExtendableArrayClass;
149 } 148 }
150 149
151 /// Returns a set of interceptor classes that contain a member named [name] 150 /// Returns a set of interceptor classes that contain a member named [name]
152 /// 151 ///
153 /// Returns an empty set if there is no class. Do not modify the returned set. 152 /// Returns an empty set if there is no class. Do not modify the returned set.
154 Set<ClassEntity> getInterceptedClassesOn( 153 Set<ClassEntity> getInterceptedClassesOn(String name) {
155 String name, ClosedWorld closedWorld) {
156 Set<MemberEntity> intercepted = _interceptedElements[name]; 154 Set<MemberEntity> intercepted = _interceptedElements[name];
157 if (intercepted == null) return _noClasses; 155 if (intercepted == null) return _noClasses;
158 return _interceptedClassesCache.putIfAbsent(name, () { 156 return _interceptedClassesCache.putIfAbsent(name, () {
159 // Populate the cache by running through all the elements and 157 // Populate the cache by running through all the elements and
160 // determine if the given selector applies to them. 158 // determine if the given selector applies to them.
161 Set<ClassEntity> result = new Set<ClassEntity>(); 159 Set<ClassEntity> result = new Set<ClassEntity>();
162 for (MemberEntity element in intercepted) { 160 for (MemberEntity element in intercepted) {
163 ClassEntity classElement = element.enclosingClass; 161 ClassEntity classElement = element.enclosingClass;
164 if (_isCompileTimeOnlyClass(classElement)) continue; 162 if (_isCompileTimeOnlyClass(classElement)) continue;
165 if (_nativeData.isNativeOrExtendsNative(classElement) || 163 if (_nativeData.isNativeOrExtendsNative(classElement) ||
166 interceptedClasses.contains(classElement)) { 164 interceptedClasses.contains(classElement)) {
167 result.add(classElement); 165 result.add(classElement);
168 } 166 }
169 if (_classesMixedIntoInterceptedClasses.contains(classElement)) { 167 if (_classesMixedIntoInterceptedClasses.contains(classElement)) {
170 Set<ClassEntity> nativeSubclasses = 168 Set<ClassEntity> nativeSubclasses =
171 nativeSubclassesOfMixin(classElement, closedWorld); 169 nativeSubclassesOfMixin(classElement);
172 if (nativeSubclasses != null) result.addAll(nativeSubclasses); 170 if (nativeSubclasses != null) result.addAll(nativeSubclasses);
173 } 171 }
174 } 172 }
175 return result; 173 return result;
176 }); 174 });
177 } 175 }
178 176
179 Set<ClassEntity> nativeSubclassesOfMixin( 177 Set<ClassEntity> nativeSubclassesOfMixin(ClassEntity mixin) {
180 ClassEntity mixin, ClosedWorld closedWorld) { 178 Iterable<ClassEntity> uses = _closedWorld.mixinUsesOf(mixin);
181 Iterable<ClassEntity> uses = closedWorld.mixinUsesOf(mixin);
182 Set<ClassEntity> result = null; 179 Set<ClassEntity> result = null;
183 for (ClassEntity use in uses) { 180 for (ClassEntity use in uses) {
184 closedWorld.forEachStrictSubclassOf(use, (ClassEntity subclass) { 181 _closedWorld.forEachStrictSubclassOf(use, (ClassEntity subclass) {
185 if (_nativeData.isNativeOrExtendsNative(subclass)) { 182 if (_nativeData.isNativeOrExtendsNative(subclass)) {
186 if (result == null) result = new Set<ClassEntity>(); 183 if (result == null) result = new Set<ClassEntity>();
187 result.add(subclass); 184 result.add(subclass);
188 } 185 }
189 }); 186 });
190 } 187 }
191 return result; 188 return result;
192 } 189 }
193 190
194 bool isInterceptedClass(ClassEntity element) { 191 bool isInterceptedClass(ClassEntity element) {
195 if (element == null) return false; 192 if (element == null) return false;
196 if (_nativeData.isNativeOrExtendsNative(element)) return true; 193 if (_nativeData.isNativeOrExtendsNative(element)) return true;
197 if (interceptedClasses.contains(element)) return true; 194 if (interceptedClasses.contains(element)) return true;
198 if (_classesMixedIntoInterceptedClasses.contains(element)) return true; 195 if (_classesMixedIntoInterceptedClasses.contains(element)) return true;
199 return false; 196 return false;
200 } 197 }
201 198
202 bool isMixedIntoInterceptedClass(ClassEntity element) => 199 bool isMixedIntoInterceptedClass(ClassEntity element) =>
203 _classesMixedIntoInterceptedClasses.contains(element); 200 _classesMixedIntoInterceptedClasses.contains(element);
204 201
205 Iterable<ClassEntity> get interceptedClasses => _interceptedClasses; 202 Iterable<ClassEntity> get interceptedClasses => _interceptedClasses;
206 203
207 bool mayGenerateInstanceofCheck(DartType type, ClosedWorld closedWorld) { 204 bool mayGenerateInstanceofCheck(DartType type) {
208 // We can use an instanceof check for raw types that have no subclass that 205 // We can use an instanceof check for raw types that have no subclass that
209 // is mixed-in or in an implements clause. 206 // is mixed-in or in an implements clause.
210 207
211 if (!type.treatAsRaw) return false; 208 if (!type.treatAsRaw) return false;
212 InterfaceType interfaceType = type; 209 InterfaceType interfaceType = type;
213 ClassEntity classElement = interfaceType.element; 210 ClassEntity classElement = interfaceType.element;
214 if (isInterceptedClass(classElement)) return false; 211 if (isInterceptedClass(classElement)) return false;
215 return closedWorld.hasOnlySubclasses(classElement); 212 return _closedWorld.hasOnlySubclasses(classElement);
216 } 213 }
217 } 214 }
218 215
219 class InterceptorDataBuilderImpl implements InterceptorDataBuilder { 216 class InterceptorDataBuilderImpl implements InterceptorDataBuilder {
220 final NativeBasicData _nativeData; 217 final NativeBasicData _nativeData;
221 final ElementEnvironment _elementEnvironment; 218 final ElementEnvironment _elementEnvironment;
222 final CommonElements _commonElements; 219 final CommonElements _commonElements;
223 220
224 /// The members of instantiated interceptor classes: maps a member name to the 221 /// The members of instantiated interceptor classes: maps a member name to the
225 /// list of members that have that name. This map is used by the codegen to 222 /// list of members that have that name. This map is used by the codegen to
226 /// know whether a send must be intercepted or not. 223 /// know whether a send must be intercepted or not.
227 final Map<String, Set<MemberEntity>> _interceptedElements = 224 final Map<String, Set<MemberEntity>> _interceptedElements =
228 <String, Set<MemberEntity>>{}; 225 <String, Set<MemberEntity>>{};
229 226
230 /// Set of classes whose methods are intercepted. 227 /// Set of classes whose methods are intercepted.
231 final Set<ClassEntity> _interceptedClasses = new Set<ClassEntity>(); 228 final Set<ClassEntity> _interceptedClasses = new Set<ClassEntity>();
232 229
233 /// Set of classes used as mixins on intercepted (native and primitive) 230 /// Set of classes used as mixins on intercepted (native and primitive)
234 /// classes. Methods on these classes might also be mixed in to regular Dart 231 /// classes. Methods on these classes might also be mixed in to regular Dart
235 /// (unintercepted) classes. 232 /// (unintercepted) classes.
236 final Set<ClassEntity> _classesMixedIntoInterceptedClasses = 233 final Set<ClassEntity> _classesMixedIntoInterceptedClasses =
237 new Set<ClassEntity>(); 234 new Set<ClassEntity>();
238 235
239 InterceptorDataBuilderImpl( 236 InterceptorDataBuilderImpl(
240 this._nativeData, this._elementEnvironment, this._commonElements); 237 this._nativeData, this._elementEnvironment, this._commonElements);
241 238
242 InterceptorData onResolutionComplete() { 239 InterceptorData onResolutionComplete(ClosedWorld closedWorld) {
243 return new InterceptorDataImpl( 240 return new InterceptorDataImpl(
244 _nativeData, 241 _nativeData,
245 _commonElements, 242 _commonElements,
243 closedWorld,
246 _interceptedElements, 244 _interceptedElements,
247 _interceptedClasses, 245 _interceptedClasses,
248 _classesMixedIntoInterceptedClasses); 246 _classesMixedIntoInterceptedClasses);
249 } 247 }
250 248
251 void addInterceptorsForNativeClassMembers(ClassEntity cls) { 249 void addInterceptorsForNativeClassMembers(ClassEntity cls) {
252 _elementEnvironment.forEachClassMember(cls, 250 _elementEnvironment.forEachClassMember(cls,
253 (ClassEntity cls, MemberEntity member) { 251 (ClassEntity cls, MemberEntity member) {
254 if (member.name == Identifiers.call) return; 252 if (member.name == Identifiers.call) return;
255 // All methods on [Object] are shadowed by [Interceptor]. 253 // All methods on [Object] are shadowed by [Interceptor].
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 /// contains all possible type checks is also stored in this map. 302 /// contains all possible type checks is also stored in this map.
305 final Map<jsAst.Name, Set<ClassEntity>> _specializedGetInterceptors = 303 final Map<jsAst.Name, Set<ClassEntity>> _specializedGetInterceptors =
306 <jsAst.Name, Set<ClassEntity>>{}; 304 <jsAst.Name, Set<ClassEntity>>{};
307 305
308 Iterable<jsAst.Name> get specializedGetInterceptorNames => 306 Iterable<jsAst.Name> get specializedGetInterceptorNames =>
309 _specializedGetInterceptors.keys.toList()..sort(); 307 _specializedGetInterceptors.keys.toList()..sort();
310 308
311 Set<ClassEntity> getSpecializedGetInterceptorsFor(jsAst.Name name) => 309 Set<ClassEntity> getSpecializedGetInterceptorsFor(jsAst.Name name) =>
312 _specializedGetInterceptors[name]; 310 _specializedGetInterceptors[name];
313 311
314 jsAst.Name registerOneShotInterceptor( 312 jsAst.Name registerOneShotInterceptor(Selector selector, Namer namer) {
315 Selector selector, Namer namer, ClosedWorld closedWorld) {
316 Set<ClassEntity> classes = 313 Set<ClassEntity> classes =
317 _interceptorData.getInterceptedClassesOn(selector.name, closedWorld); 314 _interceptorData.getInterceptedClassesOn(selector.name);
318 jsAst.Name name = namer.nameForGetOneShotInterceptor(selector, classes); 315 jsAst.Name name = namer.nameForGetOneShotInterceptor(selector, classes);
319 if (!_oneShotInterceptors.containsKey(name)) { 316 if (!_oneShotInterceptors.containsKey(name)) {
320 registerSpecializedGetInterceptor(classes, namer); 317 registerSpecializedGetInterceptor(classes, namer);
321 _oneShotInterceptors[name] = selector; 318 _oneShotInterceptors[name] = selector;
322 } 319 }
323 return name; 320 return name;
324 } 321 }
325 322
326 void registerSpecializedGetInterceptor( 323 void registerSpecializedGetInterceptor(
327 Set<ClassEntity> classes, Namer namer) { 324 Set<ClassEntity> classes, Namer namer) {
328 jsAst.Name name = namer.nameForGetInterceptor(classes); 325 jsAst.Name name = namer.nameForGetInterceptor(classes);
329 if (classes.contains(_commonElements.jsInterceptorClass)) { 326 if (classes.contains(_commonElements.jsInterceptorClass)) {
330 // We can't use a specialized [getInterceptorMethod], so we make 327 // We can't use a specialized [getInterceptorMethod], so we make
331 // sure we emit the one with all checks. 328 // sure we emit the one with all checks.
332 _specializedGetInterceptors[name] = _interceptorData.interceptedClasses; 329 _specializedGetInterceptors[name] = _interceptorData.interceptedClasses;
333 } else { 330 } else {
334 _specializedGetInterceptors[name] = classes; 331 _specializedGetInterceptors[name] = classes;
335 } 332 }
336 } 333 }
337 } 334 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend.dart ('k') | pkg/compiler/lib/src/js_emitter/interceptor_stub_generator.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698