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

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

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