@@ -14,7 +14,6 @@ import 'constants/values.dart'
14
14
show
15
15
ConstantValue,
16
16
ConstructedConstantValue,
17
- TypeConstantValue,
18
17
DeferredGlobalConstantValue,
19
18
InstantiationConstantValue;
20
19
import 'elements/types.dart' ;
@@ -141,31 +140,6 @@ abstract class DeferredLoadTask extends CompilerTask {
141
140
compiler.frontendStrategy.elementEnvironment;
142
141
DiagnosticReporter get reporter => compiler.reporter;
143
142
144
- /// Given [imports] that refer to an element from a library, determine whether
145
- /// the element is explicitly deferred.
146
- static bool _isExplicitlyDeferred (Iterable <ImportEntity > imports) {
147
- // If the element is not imported explicitly, it is implicitly imported
148
- // not deferred.
149
- if (imports.isEmpty) return false ;
150
- // An element could potentially be loaded by several imports. If all of them
151
- // is explicitly deferred, we say the element is explicitly deferred.
152
- // TODO(sigurdm): We might want to give a warning if the imports do not
153
- // agree.
154
- return imports.every ((ImportEntity import) => import.isDeferred);
155
- }
156
-
157
- /// Returns every [ImportEntity] that imports [element] into [library] .
158
- Iterable <ImportEntity > classImportsTo (
159
- ClassEntity element, LibraryEntity library);
160
-
161
- /// Returns every [ImportEntity] that imports [element] into [library] .
162
- Iterable <ImportEntity > memberImportsTo (
163
- MemberEntity element, LibraryEntity library);
164
-
165
- /// Returns every [ImportEntity] that imports [element] into [library] .
166
- Iterable <ImportEntity > typedefImportsTo (
167
- TypedefEntity element, LibraryEntity library);
168
-
169
143
/// Collects all direct dependencies of [element] .
170
144
///
171
145
/// The collected dependent elements and constants are are added to
@@ -193,7 +167,7 @@ abstract class DeferredLoadTask extends CompilerTask {
193
167
void addLiveInstanceMember (MemberEntity member) {
194
168
if (! compiler.resolutionWorldBuilder.isMemberUsed (member)) return ;
195
169
if (! member.isInstanceMember) return ;
196
- dependencies.members. add (member);
170
+ dependencies.addMember (member);
197
171
_collectDirectMemberDependencies (member, dependencies);
198
172
}
199
173
@@ -202,7 +176,7 @@ abstract class DeferredLoadTask extends CompilerTask {
202
176
elementEnvironment.forEachSupertype (cls, (InterfaceType type) {
203
177
_collectTypeDependencies (type, dependencies);
204
178
});
205
- dependencies.classes. add (cls);
179
+ dependencies.addClass (cls);
206
180
}
207
181
208
182
/// Finds all elements and constants that [element] depends directly on.
@@ -216,7 +190,7 @@ abstract class DeferredLoadTask extends CompilerTask {
216
190
elementEnvironment.getFunctionType (element), dependencies);
217
191
}
218
192
if (element.isStatic || element.isTopLevel || element.isConstructor) {
219
- dependencies.members. add (element);
193
+ dependencies.addMember (element);
220
194
_collectDirectMemberDependencies (element, dependencies);
221
195
}
222
196
if (element is ConstructorEntity && element.isGenerativeConstructor) {
@@ -243,21 +217,26 @@ abstract class DeferredLoadTask extends CompilerTask {
243
217
244
218
/// Recursively collects all the dependencies of [type] .
245
219
void _collectTypeDependencies (DartType type, Dependencies dependencies) {
246
- // TODO(het): we would like to separate out types that are only needed for
247
- // rti from types that are needed for their members.
248
220
if (type is FunctionType ) {
249
221
_collectFunctionTypeDependencies (type, dependencies);
250
222
} else if (type is TypedefType ) {
251
- type.typeArguments
252
- .forEach ((t) => _collectTypeDependencies (t, dependencies));
223
+ _collectTypeArgumentDependencies (type.typeArguments, dependencies);
253
224
_collectTypeDependencies (type.unaliased, dependencies);
254
225
} else if (type is InterfaceType ) {
255
- type.typeArguments
256
- .forEach ((t) => _collectTypeDependencies (t, dependencies));
257
- dependencies.classes.add (type.element);
226
+ _collectTypeArgumentDependencies (type.typeArguments, dependencies);
227
+ // TODO(sigmund): when we are able to split classes from types in our
228
+ // runtime-type representation, this should track type.element as a type
229
+ // dependency instead.
230
+ dependencies.addClass (type.element);
258
231
}
259
232
}
260
233
234
+ void _collectTypeArgumentDependencies (
235
+ Iterable <DartType > typeArguments, Dependencies dependencies) {
236
+ if (typeArguments == null ) return ;
237
+ typeArguments.forEach ((t) => _collectTypeDependencies (t, dependencies));
238
+ }
239
+
261
240
void _collectFunctionTypeDependencies (
262
241
FunctionType type, Dependencies dependencies) {
263
242
for (FunctionTypeVariable typeVariable in type.typeVariables) {
@@ -285,7 +264,7 @@ abstract class DeferredLoadTask extends CompilerTask {
285
264
new WorldImpactVisitorImpl (visitStaticUse: (StaticUse staticUse) {
286
265
Entity usedEntity = staticUse.element;
287
266
if (usedEntity is MemberEntity ) {
288
- dependencies.members. add (usedEntity);
267
+ dependencies.addMember (usedEntity, staticUse.deferredImport );
289
268
} else {
290
269
assert (usedEntity is KLocalFunction ,
291
270
failedAt (usedEntity, "Unexpected static use $staticUse ." ));
@@ -298,19 +277,23 @@ abstract class DeferredLoadTask extends CompilerTask {
298
277
switch (staticUse.kind) {
299
278
case StaticUseKind .CONSTRUCTOR_INVOKE :
300
279
case StaticUseKind .CONST_CONSTRUCTOR_INVOKE :
301
- _collectTypeDependencies (staticUse.type, dependencies);
280
+ // The receiver type of generative constructors is a dependency of
281
+ // the constructor (handled by `addMember` above) and not a
282
+ // dependency at the call site.
283
+ // Factory methods, on the other hand, are like static methods so
284
+ // the target type is not relevant.
285
+ // TODO(johnniwinther): Use rti need data to skip unneeded type
286
+ // arguments.
287
+ _collectTypeArgumentDependencies (
288
+ staticUse.type.typeArguments, dependencies);
302
289
break ;
303
290
case StaticUseKind .INVOKE :
304
291
case StaticUseKind .CLOSURE_CALL :
305
292
case StaticUseKind .DIRECT_INVOKE :
306
293
// TODO(johnniwinther): Use rti need data to skip unneeded type
307
294
// arguments.
308
- List <DartType > typeArguments = staticUse.typeArguments;
309
- if (typeArguments != null ) {
310
- for (DartType typeArgument in typeArguments) {
311
- _collectTypeDependencies (typeArgument, dependencies);
312
- }
313
- }
295
+ _collectTypeArgumentDependencies (
296
+ staticUse.typeArguments, dependencies);
314
297
break ;
315
298
default :
316
299
}
@@ -320,7 +303,8 @@ abstract class DeferredLoadTask extends CompilerTask {
320
303
case TypeUseKind .TYPE_LITERAL :
321
304
if (type.isInterfaceType) {
322
305
InterfaceType interface = type;
323
- dependencies.classes.add (interface .element);
306
+ dependencies.addClass (
307
+ interface .element, typeUse.deferredImport);
324
308
}
325
309
break ;
326
310
case TypeUseKind .INSTANTIATION :
@@ -352,12 +336,8 @@ abstract class DeferredLoadTask extends CompilerTask {
352
336
}, visitDynamicUse: (DynamicUse dynamicUse) {
353
337
// TODO(johnniwinther): Use rti need data to skip unneeded type
354
338
// arguments.
355
- List <DartType > typeArguments = dynamicUse.typeArguments;
356
- if (typeArguments != null ) {
357
- for (DartType typeArgument in typeArguments) {
358
- _collectTypeDependencies (typeArgument, dependencies);
359
- }
360
- }
339
+ _collectTypeArgumentDependencies (
340
+ dynamicUse.typeArguments, dependencies);
361
341
}),
362
342
DeferredLoadTask .IMPACT_USE );
363
343
}
@@ -489,58 +469,46 @@ abstract class DeferredLoadTask extends CompilerTask {
489
469
490
470
void _processDependencies (LibraryEntity library, Dependencies dependencies,
491
471
ImportSet oldSet, ImportSet newSet, WorkQueue queue) {
492
- for (ClassEntity cls in dependencies.classes) {
493
- Iterable <ImportEntity > imports = classImportsTo (cls, library);
494
- if (_isExplicitlyDeferred (imports)) {
472
+ dependencies.classes.forEach ((ClassEntity cls, DependencyInfo info) {
473
+ if (info.isDeferred) {
495
474
if (_shouldAddDeferredDependency (newSet)) {
496
- for (ImportEntity deferredImport in imports) {
475
+ for (ImportEntity deferredImport in info. imports) {
497
476
queue.addClass (cls, importSets.singleton (deferredImport));
498
477
}
499
478
}
500
479
} else {
501
480
_updateClassRecursive (cls, oldSet, newSet, queue);
502
481
}
503
- }
482
+ });
504
483
505
- for (MemberEntity member in dependencies.members) {
506
- Iterable <ImportEntity > imports = memberImportsTo (member, library);
507
- if (_isExplicitlyDeferred (imports)) {
484
+ dependencies.members.forEach ((MemberEntity member, DependencyInfo info) {
485
+ if (info.isDeferred) {
508
486
if (_shouldAddDeferredDependency (newSet)) {
509
- for (ImportEntity deferredImport in imports) {
487
+ for (ImportEntity deferredImport in info. imports) {
510
488
queue.addMember (member, importSets.singleton (deferredImport));
511
489
}
512
490
}
513
491
} else {
514
492
_updateMemberRecursive (member, oldSet, newSet, queue);
515
493
}
516
- }
494
+ });
517
495
518
496
for (Local localFunction in dependencies.localFunctions) {
519
497
_updateLocalFunction (localFunction, oldSet, newSet);
520
498
}
521
499
522
- for (ConstantValue dependency in dependencies.constants) {
523
- if (dependency is TypeConstantValue ) {
524
- var type = dependency.representedType;
525
- var imports = const < ImportEntity > [];
526
- if (type is InterfaceType ) {
527
- imports = classImportsTo (type.element, library);
528
- } else if (type is TypedefType ) {
529
- imports = typedefImportsTo (type.element, library);
530
- }
531
- if (_isExplicitlyDeferred (imports)) {
532
- if (_shouldAddDeferredDependency (newSet)) {
533
- for (ImportEntity deferredImport in imports) {
534
- queue.addConstant (
535
- dependency, importSets.singleton (deferredImport));
536
- }
500
+ dependencies.constants
501
+ .forEach ((ConstantValue dependency, DependencyInfo info) {
502
+ if (info.isDeferred) {
503
+ if (_shouldAddDeferredDependency (newSet)) {
504
+ for (ImportEntity deferredImport in info.imports) {
505
+ queue.addConstant (dependency, importSets.singleton (deferredImport));
537
506
}
538
- continue ;
539
507
}
508
+ } else {
509
+ _updateConstantRecursive (dependency, oldSet, newSet, queue);
540
510
}
541
-
542
- _updateConstantRecursive (dependency, oldSet, newSet, queue);
543
- }
511
+ });
544
512
}
545
513
546
514
/// Adds extra dependencies coming from mirror usage.
@@ -767,7 +735,6 @@ abstract class DeferredLoadTask extends CompilerTask {
767
735
_memberToSet = null ;
768
736
_localFunctionToSet = null ;
769
737
_constantToSet = null ;
770
- cleanup ();
771
738
return new OutputUnitData (
772
739
this .isProgramSplit && ! disableProgramSplit,
773
740
this ._mainOutputUnit,
@@ -781,9 +748,6 @@ abstract class DeferredLoadTask extends CompilerTask {
781
748
_deferredImportDescriptions);
782
749
}
783
750
784
- /// Frees up strategy-specific temporary data.
785
- void cleanup () {}
786
-
787
751
void beforeResolution (Uri rootLibraryUri, Iterable <Uri > libraries) {
788
752
measureSubtask ('prepare' , () {
789
753
for (Uri uri in libraries) {
@@ -1488,8 +1452,36 @@ String deferredPartFileName(CompilerOptions options, String name,
1488
1452
}
1489
1453
1490
1454
class Dependencies {
1491
- final Set <ClassEntity > classes = new Set < ClassEntity >() ;
1492
- final Set <MemberEntity > members = new Set < MemberEntity >() ;
1455
+ final Map <ClassEntity , DependencyInfo > classes = {} ;
1456
+ final Map <MemberEntity , DependencyInfo > members = {} ;
1493
1457
final Set <Local > localFunctions = new Set <Local >();
1494
- final Set <ConstantValue > constants = new Set <ConstantValue >();
1458
+ final Map <ConstantValue , DependencyInfo > constants = {};
1459
+
1460
+ void addClass (ClassEntity cls, [ImportEntity import]) {
1461
+ (classes[cls] ?? = new DependencyInfo ()).registerImport (import);
1462
+ }
1463
+
1464
+ void addMember (MemberEntity m, [ImportEntity import]) {
1465
+ (members[m] ?? = new DependencyInfo ()).registerImport (import);
1466
+ }
1467
+
1468
+ void addConstant (ConstantValue c, [ImportEntity import]) {
1469
+ (constants[c] ?? = new DependencyInfo ()).registerImport (import);
1470
+ }
1471
+ }
1472
+
1473
+ class DependencyInfo {
1474
+ bool isDeferred = true ;
1475
+ List <ImportEntity > imports;
1476
+
1477
+ registerImport (ImportEntity import) {
1478
+ if (! isDeferred) return ;
1479
+ // A null import represents a direct non-deferred dependency.
1480
+ if (import != null ) {
1481
+ (imports ?? = []).add (import);
1482
+ } else {
1483
+ imports = null ;
1484
+ isDeferred = false ;
1485
+ }
1486
+ }
1495
1487
}
0 commit comments