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

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

Issue 2589183002: Move CodegenEnqueuer.generatedCode to JavaScriptBackend. (Closed)
Patch Set: dartfmt Created 4 years 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.js.enqueue; 5 library dart2js.js.enqueue;
6 6
7 import 'dart:collection' show Queue; 7 import 'dart:collection' show Queue;
8 8
9 import '../cache_strategy.dart' show CacheStrategy; 9 import '../cache_strategy.dart' show CacheStrategy;
10 import '../common/backend_api.dart' show Backend; 10 import '../common/backend_api.dart' show Backend;
11 import '../common/codegen.dart' show CodegenWorkItem; 11 import '../common/codegen.dart' show CodegenWorkItem;
12 import '../common/tasks.dart' show CompilerTask; 12 import '../common/tasks.dart' show CompilerTask;
13 import '../common/work.dart' show WorkItem; 13 import '../common/work.dart' show WorkItem;
14 import '../common.dart'; 14 import '../common.dart';
15 import '../compiler.dart' show Compiler; 15 import '../compiler.dart' show Compiler;
16 import '../dart_types.dart' show DartType, InterfaceType; 16 import '../dart_types.dart' show DartType, InterfaceType;
17 import '../elements/elements.dart' 17 import '../elements/elements.dart' show Element, Entity, TypedElement;
18 show ClassElement, Element, Entity, MemberElement, TypedElement;
19 import '../elements/entities.dart'; 18 import '../elements/entities.dart';
20 import '../enqueue.dart'; 19 import '../enqueue.dart';
21 import '../js/js.dart' as js;
22 import '../native/native.dart' as native; 20 import '../native/native.dart' as native;
23 import '../options.dart'; 21 import '../options.dart';
24 import '../types/types.dart' show TypeMaskStrategy; 22 import '../types/types.dart' show TypeMaskStrategy;
25 import '../universe/world_builder.dart'; 23 import '../universe/world_builder.dart';
26 import '../universe/use.dart' 24 import '../universe/use.dart'
27 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind; 25 show DynamicUse, StaticUse, StaticUseKind, TypeUse, TypeUseKind;
28 import '../universe/world_impact.dart' 26 import '../universe/world_impact.dart'
29 show ImpactUseCase, WorldImpact, WorldImpactVisitor; 27 show ImpactUseCase, WorldImpact, WorldImpactVisitor;
30 import '../util/enumset.dart'; 28 import '../util/enumset.dart';
31 import '../util/util.dart' show Setlet; 29 import '../util/util.dart' show Setlet;
32 30
33 /// [Enqueuer] which is specific to code generation. 31 /// [Enqueuer] which is specific to code generation.
34 class CodegenEnqueuer extends EnqueuerImpl { 32 class CodegenEnqueuer extends EnqueuerImpl {
35 final String name; 33 final String name;
36 final EnqueuerStrategy strategy; 34 final EnqueuerStrategy strategy;
37 35
38 Set<ClassElement> _recentClasses = new Setlet<ClassElement>(); 36 Set<ClassEntity> _recentClasses = new Setlet<ClassEntity>();
39 final CodegenWorldBuilderImpl _universe; 37 final CodegenWorldBuilderImpl _universe;
40 38
41 bool queueIsClosed = false; 39 bool queueIsClosed = false;
42 final CompilerTask task; 40 final CompilerTask task;
43 final native.NativeEnqueuer nativeEnqueuer; 41 final native.NativeEnqueuer nativeEnqueuer;
44 final Backend _backend; 42 final Backend _backend;
45 final CompilerOptions _options; 43 final CompilerOptions _options;
46 44
47 WorldImpactVisitor _impactVisitor; 45 WorldImpactVisitor _impactVisitor;
48 46
49 final Queue<WorkItem> _queue = new Queue<WorkItem>(); 47 final Queue<WorkItem> _queue = new Queue<WorkItem>();
50 final Map<Element, js.Expression> generatedCode = <Element, js.Expression>{};
51 48
52 final Set<Element> newlyEnqueuedElements; 49 /// All declaration elements that have been processed by codegen.
50 final Set<Entity> _processedEntities = new Set<Entity>();
51
52 final Set<Entity> newlyEnqueuedElements;
53 53
54 final Set<DynamicUse> newlySeenSelectors; 54 final Set<DynamicUse> newlySeenSelectors;
55 55
56 static const ImpactUseCase IMPACT_USE = 56 static const ImpactUseCase IMPACT_USE =
57 const ImpactUseCase('CodegenEnqueuer'); 57 const ImpactUseCase('CodegenEnqueuer');
58 58
59 CodegenEnqueuer(this.task, CacheStrategy cacheStrategy, Backend backend, 59 CodegenEnqueuer(this.task, CacheStrategy cacheStrategy, Backend backend,
60 this._options, this.strategy) 60 this._options, this.strategy)
61 : _universe = 61 : _universe =
62 new CodegenWorldBuilderImpl(backend, const TypeMaskStrategy()), 62 new CodegenWorldBuilderImpl(backend, const TypeMaskStrategy()),
(...skipping 14 matching lines...) Expand all
77 77
78 /** 78 /**
79 * Documentation wanted -- johnniwinther 79 * Documentation wanted -- johnniwinther
80 * 80 *
81 * Invariant: [element] must be a declaration element. 81 * Invariant: [element] must be a declaration element.
82 */ 82 */
83 void _addToWorkList(Element element) { 83 void _addToWorkList(Element element) {
84 assert(invariant(element, element.isDeclaration)); 84 assert(invariant(element, element.isDeclaration));
85 // Don't generate code for foreign elements. 85 // Don't generate code for foreign elements.
86 if (_backend.isForeign(element)) return; 86 if (_backend.isForeign(element)) return;
87 if (element.isAbstract) return;
87 88
88 // Codegen inlines field initializers. It only needs to generate 89 // Codegen inlines field initializers. It only needs to generate
89 // code for checked setters. 90 // code for checked setters.
90 if (element.isField && element.isInstanceMember) { 91 if (element.isField && element.isInstanceMember) {
91 if (!_options.enableTypeAssertions || 92 if (!_options.enableTypeAssertions ||
92 element.enclosingElement.isClosure) { 93 element.enclosingElement.isClosure) {
93 return; 94 return;
94 } 95 }
95 } 96 }
96 97
97 if (_options.hasIncrementalSupport && !isProcessed(element)) { 98 if (_options.hasIncrementalSupport &&
99 !_processedEntities.contains(element)) {
98 newlyEnqueuedElements.add(element); 100 newlyEnqueuedElements.add(element);
99 } 101 }
100 102
101 if (queueIsClosed) { 103 if (queueIsClosed) {
102 throw new SpannableAssertionFailure( 104 throw new SpannableAssertionFailure(
103 element, "Codegen work list is closed. Trying to add $element"); 105 element, "Codegen work list is closed. Trying to add $element");
104 } 106 }
105 _queue.add(new CodegenWorkItem(_backend, element)); 107 _queue.add(new CodegenWorkItem(_backend, element));
106 applyImpact(_backend.registerUsedElement(element, forResolution: false)); 108 applyImpact(_backend.registerUsedElement(element, forResolution: false));
107 } 109 }
108 110
109 void applyImpact(WorldImpact worldImpact, {Element impactSource}) { 111 void applyImpact(WorldImpact worldImpact, {var impactSource}) {
Siggi Cherem (dart-lang) 2016/12/20 19:26:34 var => Entity?
Johnni Winther 2016/12/21 09:43:40 No. The plan it to allow for any key; elements, bu
110 if (worldImpact.isEmpty) return; 112 if (worldImpact.isEmpty) return;
111 impactStrategy.visitImpact( 113 impactStrategy.visitImpact(
112 impactSource, worldImpact, _impactVisitor, impactUse); 114 impactSource, worldImpact, _impactVisitor, impactUse);
113 } 115 }
114 116
115 void _registerInstantiatedType(InterfaceType type, 117 void _registerInstantiatedType(InterfaceType type,
116 {bool mirrorUsage: false, bool nativeUsage: false}) { 118 {bool mirrorUsage: false, bool nativeUsage: false}) {
117 task.measure(() { 119 task.measure(() {
118 _universe.registerTypeInstantiation(type, _applyClassUse, 120 _universe.registerTypeInstantiation(type, _applyClassUse,
119 byMirrors: mirrorUsage); 121 byMirrors: mirrorUsage);
120 if (nativeUsage) { 122 if (nativeUsage) {
121 nativeEnqueuer.onInstantiatedType(type); 123 nativeEnqueuer.onInstantiatedType(type);
122 } 124 }
123 _backend.registerInstantiatedType(type); 125 _backend.registerInstantiatedType(type);
124 }); 126 });
125 } 127 }
126 128
127 bool checkNoEnqueuedInvokedInstanceMethods() { 129 bool checkNoEnqueuedInvokedInstanceMethods() {
128 return strategy.checkEnqueuerConsistency(this); 130 return strategy.checkEnqueuerConsistency(this);
129 } 131 }
130 132
131 void checkClass(ClassElement cls) { 133 void checkClass(ClassEntity cls) {
132 _universe.processClassMembers(cls, (MemberElement member, useSet) { 134 _universe.processClassMembers(cls, (MemberEntity member, useSet) {
133 if (useSet.isNotEmpty) { 135 if (useSet.isNotEmpty) {
134 _backend.compiler.reporter.internalError(member, 136 _backend.compiler.reporter.internalError(member,
135 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}'); 137 'Unenqueued use of $member: ${useSet.iterable(MemberUse.values)}');
136 } 138 }
137 }); 139 });
138 } 140 }
139 141
140 /// Callback for applying the use of a [cls]. 142 /// Callback for applying the use of a [cls].
141 void _applyClassUse(ClassEntity cls, EnumSet<ClassUse> useSet) { 143 void _applyClassUse(ClassEntity cls, EnumSet<ClassUse> useSet) {
142 if (useSet.contains(ClassUse.INSTANTIATED)) { 144 if (useSet.contains(ClassUse.INSTANTIATED)) {
(...skipping 27 matching lines...) Expand all
170 task.measure(() { 172 task.measure(() {
171 if (_universe.registerDynamicUse(dynamicUse, _applyMemberUse)) { 173 if (_universe.registerDynamicUse(dynamicUse, _applyMemberUse)) {
172 if (_options.hasIncrementalSupport) { 174 if (_options.hasIncrementalSupport) {
173 newlySeenSelectors.add(dynamicUse); 175 newlySeenSelectors.add(dynamicUse);
174 } 176 }
175 } 177 }
176 }); 178 });
177 } 179 }
178 180
179 void processStaticUse(StaticUse staticUse) { 181 void processStaticUse(StaticUse staticUse) {
180 Element element = staticUse.element;
181 assert(invariant(element, element.isDeclaration,
182 message: "Element ${element} is not the declaration."));
183 _universe.registerStaticUse(staticUse, _applyMemberUse); 182 _universe.registerStaticUse(staticUse, _applyMemberUse);
184 switch (staticUse.kind) { 183 switch (staticUse.kind) {
185 case StaticUseKind.CONSTRUCTOR_INVOKE: 184 case StaticUseKind.CONSTRUCTOR_INVOKE:
186 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE: 185 case StaticUseKind.CONST_CONSTRUCTOR_INVOKE:
187 case StaticUseKind.REDIRECTION: 186 case StaticUseKind.REDIRECTION:
188 processTypeUse(new TypeUse.instantiation(staticUse.type)); 187 processTypeUse(new TypeUse.instantiation(staticUse.type));
189 break; 188 break;
190 default: 189 default:
191 break; 190 break;
192 } 191 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 forResolution: false)); 233 forResolution: false));
235 } 234 }
236 applyImpact(_backend.registerBoundClosure()); 235 applyImpact(_backend.registerBoundClosure());
237 } 236 }
238 237
239 void forEach(void f(WorkItem work)) { 238 void forEach(void f(WorkItem work)) {
240 do { 239 do {
241 while (_queue.isNotEmpty) { 240 while (_queue.isNotEmpty) {
242 // TODO(johnniwinther): Find an optimal process order. 241 // TODO(johnniwinther): Find an optimal process order.
243 WorkItem work = _queue.removeLast(); 242 WorkItem work = _queue.removeLast();
244 if (!isProcessed(work.element)) { 243 if (!_processedEntities.contains(work.element)) {
245 strategy.processWorkItem(f, work); 244 strategy.processWorkItem(f, work);
246 // TODO(johnniwinther): Register the processed element here. This 245 // TODO(johnniwinther): Register the processed element here. This
247 // is currently a side-effect of calling `work.run`. 246 // is currently a side-effect of calling `work.run`.
247 _processedEntities.add(work.element);
248 } 248 }
249 } 249 }
250 List recents = _recentClasses.toList(growable: false); 250 List recents = _recentClasses.toList(growable: false);
251 _recentClasses.clear(); 251 _recentClasses.clear();
252 if (!_onQueueEmpty(recents)) _recentClasses.addAll(recents); 252 if (!_onQueueEmpty(recents)) _recentClasses.addAll(recents);
253 } while (_queue.isNotEmpty || _recentClasses.isNotEmpty); 253 } while (_queue.isNotEmpty || _recentClasses.isNotEmpty);
254 } 254 }
255 255
256 /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses] 256 /// [_onQueueEmpty] is called whenever the queue is drained. [recentClasses]
257 /// contains the set of all classes seen for the first time since 257 /// contains the set of all classes seen for the first time since
258 /// [_onQueueEmpty] was called last. A return value of [true] indicates that 258 /// [_onQueueEmpty] was called last. A return value of [true] indicates that
259 /// the [recentClasses] have been processed and may be cleared. If [false] is 259 /// the [recentClasses] have been processed and may be cleared. If [false] is
260 /// returned, [_onQueueEmpty] will be called once the queue is empty again (or 260 /// returned, [_onQueueEmpty] will be called once the queue is empty again (or
261 /// still empty) and [recentClasses] will be a superset of the current value. 261 /// still empty) and [recentClasses] will be a superset of the current value.
262 bool _onQueueEmpty(Iterable<ClassElement> recentClasses) { 262 bool _onQueueEmpty(Iterable<ClassEntity> recentClasses) {
263 return _backend.onQueueEmpty(this, recentClasses); 263 return _backend.onQueueEmpty(this, recentClasses);
264 } 264 }
265 265
266 void logSummary(log(message)) { 266 void logSummary(log(message)) {
267 log('Compiled ${generatedCode.length} methods.'); 267 log('Compiled ${_processedEntities.length} methods.');
268 nativeEnqueuer.logSummary(log); 268 nativeEnqueuer.logSummary(log);
269 } 269 }
270 270
271 String toString() => 'Enqueuer($name)'; 271 String toString() => 'Enqueuer($name)';
272 272
273 ImpactUseCase get impactUse => IMPACT_USE; 273 ImpactUseCase get impactUse => IMPACT_USE;
274 274
275 bool isProcessed(Element member) => 275 void forgetEntity(Entity entity, Compiler compiler) {
276 member.isAbstract || generatedCode.containsKey(member); 276 _universe.forgetElement(entity, compiler);
277 277 _processedEntities.remove(entity);
278 void forgetEntity(Element element, Compiler compiler) {
279 _universe.forgetElement(element, compiler);
280 generatedCode.remove(element);
281 if (element is MemberElement) {
282 for (Element closure in element.nestedClosures) {
283 generatedCode.remove(closure);
284 }
285 }
286 } 278 }
287 279
288 @override 280 @override
289 Iterable<Entity> get processedEntities => generatedCode.keys; 281 Iterable<Entity> get processedEntities => _processedEntities;
290 282
291 @override 283 @override
292 Iterable<ClassEntity> get processedClasses => _universe.processedClasses; 284 Iterable<ClassEntity> get processedClasses => _universe.processedClasses;
293 } 285 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend.dart ('k') | tests/compiler/dart2js/mirrors_used_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698