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

Side by Side Diff: pkg/compiler/lib/src/world.dart

Issue 2814973003: Extract ClosedWorldRefiner implementation from ClosedWorldImpl to 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) 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 dart2js.world; 5 library dart2js.world;
6 6
7 import 'closure.dart' show ClosureClassElement, SynthesizedCallMethodElementX; 7 import 'closure.dart' show ClosureClassElement, SynthesizedCallMethodElementX;
8 import 'common/backend_api.dart' show BackendClasses; 8 import 'common/backend_api.dart' show BackendClasses;
9 import 'common.dart'; 9 import 'common.dart';
10 import 'constants/constant_system.dart'; 10 import 'constants/constant_system.dart';
11 import 'common_elements.dart' show CommonElements; 11 import 'common_elements.dart' show CommonElements;
12 import 'elements/entities.dart'; 12 import 'elements/entities.dart';
13 import 'elements/elements.dart' 13 import 'elements/elements.dart'
14 show 14 show
15 ClassElement, 15 ClassElement,
16 Element, 16 Element,
17 FunctionElement,
18 MemberElement, 17 MemberElement,
19 MixinApplicationElement, 18 MixinApplicationElement,
20 TypedefElement; 19 TypedefElement;
21 import 'elements/resolution_types.dart'; 20 import 'elements/resolution_types.dart';
22 import 'elements/types.dart'; 21 import 'elements/types.dart';
23 import 'js_backend/backend.dart' show JavaScriptBackend; 22 import 'js_backend/backend.dart' show JavaScriptBackend;
24 import 'js_backend/interceptor_data.dart' show InterceptorData; 23 import 'js_backend/interceptor_data.dart' show InterceptorData;
25 import 'js_backend/native_data.dart' show NativeData; 24 import 'js_backend/native_data.dart' show NativeData;
26 import 'ordered_typeset.dart'; 25 import 'ordered_typeset.dart';
27 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask; 26 import 'types/masks.dart' show CommonMasks, FlatTypeMask, TypeMask;
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 /// Returns the single [Element] that matches a call to [selector] on a 291 /// Returns the single [Element] that matches a call to [selector] on a
293 /// receiver of type [mask]. If multiple targets exist, `null` is returned. 292 /// receiver of type [mask]. If multiple targets exist, `null` is returned.
294 MemberEntity locateSingleElement(Selector selector, TypeMask mask); 293 MemberEntity locateSingleElement(Selector selector, TypeMask mask);
295 294
296 /// Returns the single field that matches a call to [selector] on a 295 /// Returns the single field that matches a call to [selector] on a
297 /// receiver of type [mask]. If multiple targets exist or the single target 296 /// receiver of type [mask]. If multiple targets exist or the single target
298 /// is not a field, `null` is returned. 297 /// is not a field, `null` is returned.
299 FieldEntity locateSingleField(Selector selector, TypeMask mask); 298 FieldEntity locateSingleField(Selector selector, TypeMask mask);
300 299
301 /// Returns the side effects of executing [element]. 300 /// Returns the side effects of executing [element].
302 SideEffects getSideEffectsOfElement(Element element); 301 SideEffects getSideEffectsOfElement(Entity element);
303 302
304 /// Returns the side effects of calling [selector] on a receiver of type 303 /// Returns the side effects of calling [selector] on a receiver of type
305 /// [mask]. 304 /// [mask].
306 SideEffects getSideEffectsOfSelector(Selector selector, TypeMask mask); 305 SideEffects getSideEffectsOfSelector(Selector selector, TypeMask mask);
307 306
308 /// Returns `true` if [element] is guaranteed not to throw an exception. 307 /// Returns `true` if [element] is guaranteed not to throw an exception.
309 bool getCannotThrow(Element element); 308 bool getCannotThrow(Entity element);
310 309
311 /// Returns `true` if [element] is called in a loop. 310 /// Returns `true` if [element] is called in a loop.
312 // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'? 311 // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'?
313 bool isCalledInLoop(Element element); 312 bool isCalledInLoop(Entity element);
314 313
315 /// Returns `true` if [element] might be passed to `Function.apply`. 314 /// Returns `true` if [element] might be passed to `Function.apply`.
316 // TODO(johnniwinther): Is this 'passed invocation target` or 315 // TODO(johnniwinther): Is this 'passed invocation target` or
317 // `passed as argument`? 316 // `passed as argument`?
318 bool getMightBePassedToApply(Element element); 317 bool getMightBePassedToApply(Entity element);
319 318
320 /// Returns a string representation of the closed world. 319 /// Returns a string representation of the closed world.
321 /// 320 ///
322 /// If [cls] is provided, the dump will contain only classes related to [cls]. 321 /// If [cls] is provided, the dump will contain only classes related to [cls].
323 String dump([ClassEntity cls]); 322 String dump([ClassEntity cls]);
324 } 323 }
325 324
326 /// Interface for computing side effects and uses of elements. This is used 325 /// Interface for computing side effects and uses of elements. This is used
327 /// during type inference to compute the [ClosedWorld] for code generation. 326 /// during type inference to compute the [ClosedWorld] for code generation.
328 abstract class ClosedWorldRefiner { 327 abstract class ClosedWorldRefiner {
329 /// The closed world being refined. 328 /// The closed world being refined.
330 ClosedWorld get closedWorld; 329 ClosedWorld get closedWorld;
331 330
332 /// Registers the side [effects] of executing [element]. 331 /// Registers the side [effects] of executing [element].
333 void registerSideEffects(Element element, SideEffects effects); 332 void registerSideEffects(Entity element, SideEffects effects);
334 333
335 /// Registers the executing of [element] as without side effects. 334 /// Registers the executing of [element] as without side effects.
336 void registerSideEffectsFree(Element element); 335 void registerSideEffectsFree(Entity element);
337 336
338 /// Returns the currently known side effects of executing [element]. 337 /// Returns the currently known side effects of executing [element].
339 SideEffects getCurrentlyKnownSideEffects(Element element); 338 SideEffects getCurrentlyKnownSideEffects(Entity element);
340 339
341 /// Registers that [element] might be passed to `Function.apply`. 340 /// Registers that [element] might be passed to `Function.apply`.
342 // TODO(johnniwinther): Is this 'passed invocation target` or 341 // TODO(johnniwinther): Is this 'passed invocation target` or
343 // `passed as argument`? 342 // `passed as argument`?
344 void registerMightBePassedToApply(Element element); 343 void registerMightBePassedToApply(Entity element);
345 344
346 /// Returns `true` if [element] might be passed to `Function.apply` given the 345 /// Returns `true` if [element] might be passed to `Function.apply` given the
347 /// currently inferred information. 346 /// currently inferred information.
348 bool getCurrentlyKnownMightBePassedToApply(Element element); 347 bool getCurrentlyKnownMightBePassedToApply(Entity element);
349 348
350 /// Registers that [element] is called in a loop. 349 /// Registers that [element] is called in a loop.
351 // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'? 350 // TODO(johnniwinther): Is this 'potentially called' or 'known to be called'?
352 void addFunctionCalledInLoop(Element element); 351 void addFunctionCalledInLoop(Entity element);
353 352
354 /// Registers that [element] is guaranteed not to throw an exception. 353 /// Registers that [element] is guaranteed not to throw an exception.
355 void registerCannotThrow(Element element); 354 void registerCannotThrow(Entity element);
356 355
357 /// Adds the closure class [cls] to the inference world. The class is 356 /// Adds the closure class [cls] to the inference world. The class is
358 /// considered directly instantiated. 357 /// considered directly instantiated.
359 void registerClosureClass(ClassElement cls); 358 void registerClosureClass(ClassElement cls);
360 } 359 }
361 360
362 abstract class OpenWorld implements World { 361 abstract class OpenWorld implements World {
363 /// Called to add [cls] to the set of known classes. 362 /// Called to add [cls] to the set of known classes.
364 /// 363 ///
365 /// This ensures that class hierarchy queries can be performed on [cls] and 364 /// This ensures that class hierarchy queries can be performed on [cls] and
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
402 final Map<ClassEntity, Set<ClassEntity>> _typesImplementedBySubclasses; 401 final Map<ClassEntity, Set<ClassEntity>> _typesImplementedBySubclasses;
403 402
404 // We keep track of subtype and subclass relationships in four 403 // We keep track of subtype and subclass relationships in four
405 // distinct sets to make class hierarchy analysis faster. 404 // distinct sets to make class hierarchy analysis faster.
406 final Map<ClassEntity, ClassHierarchyNode> _classHierarchyNodes; 405 final Map<ClassEntity, ClassHierarchyNode> _classHierarchyNodes;
407 final Map<ClassEntity, ClassSet> _classSets; 406 final Map<ClassEntity, ClassSet> _classSets;
408 407
409 final Map<ClassEntity, Map<ClassEntity, bool>> _subtypeCoveredByCache = 408 final Map<ClassEntity, Map<ClassEntity, bool>> _subtypeCoveredByCache =
410 <ClassEntity, Map<ClassEntity, bool>>{}; 409 <ClassEntity, Map<ClassEntity, bool>>{};
411 410
412 final Set<Element> functionsCalledInLoop = new Set<Element>(); 411 final Set<Entity> _functionsCalledInLoop = new Set<Entity>();
413 final Map<Element, SideEffects> sideEffects = new Map<Element, SideEffects>(); 412 final Map<Entity, SideEffects> _sideEffects = new Map<Entity, SideEffects>();
414 413
415 final Set<Element> sideEffectsFreeElements = new Set<Element>(); 414 final Set<Entity> _sideEffectsFreeElements = new Set<Entity>();
416 415
417 final Set<Element> elementsThatCannotThrow = new Set<Element>(); 416 final Set<Entity> _elementsThatCannotThrow = new Set<Entity>();
418 417
419 final Set<Element> functionsThatMightBePassedToApply = 418 final Set<Entity> _functionsThatMightBePassedToApply = new Set<Entity>();
420 new Set<FunctionElement>();
421 419
422 CommonMasks _commonMasks; 420 CommonMasks _commonMasks;
423 421
424 final CommonElements commonElements; 422 final CommonElements commonElements;
425 423
426 final ResolutionWorldBuilder _resolverWorld; 424 final ResolutionWorldBuilder _resolverWorld;
427 425
428 ClosedWorldBase( 426 ClosedWorldBase(
429 {JavaScriptBackend backend, 427 {JavaScriptBackend backend,
430 this.commonElements, 428 this.commonElements,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 } 461 }
464 462
465 ConstantSystem get constantSystem => _backend.constantSystem; 463 ConstantSystem get constantSystem => _backend.constantSystem;
466 464
467 TypeMask getCachedMask(ClassEntity base, int flags, TypeMask createMask()) { 465 TypeMask getCachedMask(ClassEntity base, int flags, TypeMask createMask()) {
468 Map<ClassEntity, TypeMask> cachedMasks = 466 Map<ClassEntity, TypeMask> cachedMasks =
469 _canonicalizedTypeMasks[flags] ??= <ClassEntity, TypeMask>{}; 467 _canonicalizedTypeMasks[flags] ??= <ClassEntity, TypeMask>{};
470 return cachedMasks.putIfAbsent(base, createMask); 468 return cachedMasks.putIfAbsent(base, createMask);
471 } 469 }
472 470
471 bool _checkEntity(Entity element);
472
473 bool _checkClass(ClassEntity cls); 473 bool _checkClass(ClassEntity cls);
474 474
475 bool _checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true}); 475 bool _checkInvariants(ClassEntity cls, {bool mustBeInstantiated: true});
476 476
477 @override 477 @override
478 bool isInstantiated(ClassEntity cls) { 478 bool isInstantiated(ClassEntity cls) {
479 assert(_checkClass(cls)); 479 assert(_checkClass(cls));
480 ClassHierarchyNode node = _classHierarchyNodes[cls]; 480 ClassHierarchyNode node = _classHierarchyNodes[cls];
481 return node != null && node.isInstantiated; 481 return node != null && node.isInstantiated;
482 } 482 }
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after
895 assert(selector.isCall); 895 assert(selector.isCall);
896 sideEffects.setAllSideEffects(); 896 sideEffects.setAllSideEffects();
897 sideEffects.setDependsOnSomething(); 897 sideEffects.setDependsOnSomething();
898 } 898 }
899 } else { 899 } else {
900 sideEffects.add(getSideEffectsOfElement(e)); 900 sideEffects.add(getSideEffectsOfElement(e));
901 } 901 }
902 } 902 }
903 return sideEffects; 903 return sideEffects;
904 } 904 }
905
906 SideEffects getSideEffectsOfElement(Entity element) {
Emily Fortuna 2017/04/12 18:07:18 getSideEffectsOfEntity?
Johnni Winther 2017/04/18 07:36:08 I'll stick with the name for now. I think needs to
907 assert(_checkEntity(element));
908 return _sideEffects.putIfAbsent(element, () {
909 return new SideEffects();
910 });
911 }
912
913 @override
914 SideEffects getCurrentlyKnownSideEffects(Entity element) {
915 return getSideEffectsOfElement(element);
916 }
917
918 void registerSideEffects(Entity element, SideEffects effects) {
919 assert(_checkEntity(element));
920 if (_sideEffectsFreeElements.contains(element)) return;
921 _sideEffects[element] = effects;
922 }
923
924 void registerSideEffectsFree(Entity element) {
925 assert(_checkEntity(element));
926 _sideEffects[element] = new SideEffects.empty();
927 _sideEffectsFreeElements.add(element);
928 }
929
930 void addFunctionCalledInLoop(Entity element) {
931 assert(_checkEntity(element));
932 _functionsCalledInLoop.add(element);
933 }
934
935 bool isCalledInLoop(Entity element) {
936 assert(_checkEntity(element));
937 return _functionsCalledInLoop.contains(element);
938 }
939
940 void registerCannotThrow(Entity element) {
941 assert(_checkEntity(element));
942 _elementsThatCannotThrow.add(element);
943 }
944
945 bool getCannotThrow(Entity element) {
946 return _elementsThatCannotThrow.contains(element);
947 }
948
949 void registerMightBePassedToApply(Entity element) {
950 _functionsThatMightBePassedToApply.add(element);
951 }
952
953 bool getMightBePassedToApply(Entity element) {
954 // We have to check whether the element we look at was created after
955 // type inference ran. This is currently only the case for the call
956 // method of function classes that were generated for function
957 // expressions. In such a case, we have to look at the original
958 // function expressions's element.
959 // TODO(herhut): Generate classes for function expressions earlier.
960 if (element is SynthesizedCallMethodElementX) {
961 return getMightBePassedToApply(element.expression);
962 }
963 return _functionsThatMightBePassedToApply.contains(element);
964 }
965
966 @override
967 bool getCurrentlyKnownMightBePassedToApply(Entity element) {
968 return getMightBePassedToApply(element);
969 }
905 } 970 }
906 971
907 class ClosedWorldImpl extends ClosedWorldBase { 972 class ClosedWorldImpl extends ClosedWorldBase {
908 ClosedWorldImpl( 973 ClosedWorldImpl(
909 {JavaScriptBackend backend, 974 {JavaScriptBackend backend,
910 CommonElements commonElements, 975 CommonElements commonElements,
911 ResolutionWorldBuilder resolutionWorldBuilder, 976 ResolutionWorldBuilder resolutionWorldBuilder,
912 FunctionSetBuilder functionSetBuilder, 977 FunctionSetBuilder functionSetBuilder,
913 Iterable<TypedefElement> allTypedefs, 978 Iterable<TypedefElement> allTypedefs,
914 Map<ClassEntity, Set<ClassEntity>> mixinUses, 979 Map<ClassEntity, Set<ClassEntity>> mixinUses,
915 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses, 980 Map<ClassEntity, Set<ClassEntity>> typesImplementedBySubclasses,
916 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes, 981 Map<ClassEntity, ClassHierarchyNode> classHierarchyNodes,
917 Map<ClassEntity, ClassSet> classSets}) 982 Map<ClassEntity, ClassSet> classSets})
918 : super( 983 : super(
919 backend: backend, 984 backend: backend,
920 commonElements: commonElements, 985 commonElements: commonElements,
921 resolutionWorldBuilder: resolutionWorldBuilder, 986 resolutionWorldBuilder: resolutionWorldBuilder,
922 functionSetBuilder: functionSetBuilder, 987 functionSetBuilder: functionSetBuilder,
923 allTypedefs: allTypedefs, 988 allTypedefs: allTypedefs,
924 mixinUses: mixinUses, 989 mixinUses: mixinUses,
925 typesImplementedBySubclasses: typesImplementedBySubclasses, 990 typesImplementedBySubclasses: typesImplementedBySubclasses,
926 classHierarchyNodes: classHierarchyNodes, 991 classHierarchyNodes: classHierarchyNodes,
927 classSets: classSets); 992 classSets: classSets);
928 993
929 bool _checkClass(ClassElement cls) => cls.isDeclaration; 994 bool _checkClass(ClassElement cls) => cls.isDeclaration;
995 bool _checkEntity(Element element) => element.isDeclaration;
930 996
931 bool _checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) { 997 bool _checkInvariants(ClassElement cls, {bool mustBeInstantiated: true}) {
932 return invariant(cls, cls.isDeclaration, 998 return invariant(cls, cls.isDeclaration,
933 message: '$cls must be the declaration.') && 999 message: '$cls must be the declaration.') &&
934 invariant(cls, cls.isResolved, 1000 invariant(cls, cls.isResolved,
935 message: 1001 message:
936 '$cls must be resolved.') /* && 1002 '$cls must be resolved.') /* &&
937 // TODO(johnniwinther): Reinsert this or similar invariant. Currently 1003 // TODO(johnniwinther): Reinsert this or similar invariant. Currently
938 // various call sites use uninstantiated classes for isSubtypeOf or 1004 // various call sites use uninstantiated classes for isSubtypeOf or
939 // isSubclassOf. Some are valid, some are not. Work out better invariants 1005 // isSubclassOf. Some are valid, some are not. Work out better invariants
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
1145 1211
1146 SideEffects getSideEffectsOfElement(Element element) { 1212 SideEffects getSideEffectsOfElement(Element element) {
1147 // The type inferrer (where the side effects are being computed), 1213 // The type inferrer (where the side effects are being computed),
1148 // does not see generative constructor bodies because they are 1214 // does not see generative constructor bodies because they are
1149 // created by the backend. Also, it does not make any distinction 1215 // created by the backend. Also, it does not make any distinction
1150 // between a constructor and its body for side effects. This 1216 // between a constructor and its body for side effects. This
1151 // implies that currently, the side effects of a constructor body 1217 // implies that currently, the side effects of a constructor body
1152 // contain the side effects of the initializers. 1218 // contain the side effects of the initializers.
1153 assert(!element.isGenerativeConstructorBody); 1219 assert(!element.isGenerativeConstructorBody);
1154 assert(!element.isField); 1220 assert(!element.isField);
1155 return sideEffects.putIfAbsent(element.declaration, () { 1221 return super.getSideEffectsOfElement(element);
1156 return new SideEffects();
1157 });
1158 }
1159
1160 @override
1161 SideEffects getCurrentlyKnownSideEffects(Element element) {
1162 return getSideEffectsOfElement(element);
1163 }
1164
1165 void registerSideEffects(Element element, SideEffects effects) {
1166 if (sideEffectsFreeElements.contains(element)) return;
1167 sideEffects[element.declaration] = effects;
1168 }
1169
1170 void registerSideEffectsFree(Element element) {
1171 sideEffects[element.declaration] = new SideEffects.empty();
1172 sideEffectsFreeElements.add(element);
1173 }
1174
1175 void addFunctionCalledInLoop(Element element) {
1176 functionsCalledInLoop.add(element.declaration);
1177 }
1178
1179 bool isCalledInLoop(Element element) {
1180 return functionsCalledInLoop.contains(element.declaration);
1181 }
1182
1183 void registerCannotThrow(Element element) {
1184 elementsThatCannotThrow.add(element);
1185 }
1186
1187 bool getCannotThrow(Element element) {
1188 return elementsThatCannotThrow.contains(element);
1189 }
1190
1191 void registerMightBePassedToApply(Element element) {
1192 functionsThatMightBePassedToApply.add(element);
1193 }
1194
1195 bool getMightBePassedToApply(Element element) {
1196 // We have to check whether the element we look at was created after
1197 // type inference ran. This is currently only the case for the call
1198 // method of function classes that were generated for function
1199 // expressions. In such a case, we have to look at the original
1200 // function expressions's element.
1201 // TODO(herhut): Generate classes for function expressions earlier.
1202 if (element is SynthesizedCallMethodElementX) {
1203 return getMightBePassedToApply(element.expression);
1204 }
1205 return functionsThatMightBePassedToApply.contains(element);
1206 }
1207
1208 @override
1209 bool getCurrentlyKnownMightBePassedToApply(Element element) {
1210 return getMightBePassedToApply(element);
1211 } 1222 }
1212 } 1223 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder.dart ('k') | tests/compiler/dart2js/embedded_category_api_boundary_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698