Skip to content

Commit 8a3b4ab

Browse files
scheglovCommit Queue
authored andcommitted
Elements. Restore lazy reading ClassElement members.
Bug: flutter/flutter#161306 Change-Id: I65b606b8aa012cebf62d866128bc35c5532e5638 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/403924 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 519e288 commit 8a3b4ab

File tree

6 files changed

+120
-28
lines changed

6 files changed

+120
-28
lines changed

pkg/analyzer/lib/src/dart/analysis/driver.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ import 'package:meta/meta.dart';
9999
// TODO(scheglov): Clean up the list of implicitly analyzed files.
100100
class AnalysisDriver {
101101
/// The version of data format, should be incremented on every format change.
102-
static const int DATA_VERSION = 426;
102+
static const int DATA_VERSION = 427;
103103

104104
/// The number of exception contexts allowed to write. Once this field is
105105
/// zero, we stop writing any new exception contexts in this process.

pkg/analyzer/lib/src/dart/element/element.dart

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ class ClassElementImpl extends ClassOrMixinElementImpl
451451
}
452452

453453
@override
454-
ClassFragment? get nextFragment => super.nextFragment as ClassFragment?;
454+
ClassElementImpl? get nextFragment => super.nextFragment as ClassElementImpl?;
455455

456456
@override
457457
ClassFragment? get previousFragment =>
@@ -5433,6 +5433,11 @@ abstract class InstanceElementImpl extends _ExistingElementImpl
54335433

54345434
@override
54355435
List<PropertyAccessorElementImpl> get accessors {
5436+
if (!identical(_accessors, _Sentinel.propertyAccessorElement)) {
5437+
return _accessors;
5438+
}
5439+
5440+
linkedData?.readMembers(this);
54365441
return _accessors;
54375442
}
54385443

@@ -5462,6 +5467,11 @@ abstract class InstanceElementImpl extends _ExistingElementImpl
54625467

54635468
@override
54645469
List<FieldElementImpl> get fields {
5470+
if (!identical(_fields, _Sentinel.fieldElement)) {
5471+
return _fields;
5472+
}
5473+
5474+
linkedData?.readMembers(this);
54655475
return _fields;
54665476
}
54675477

@@ -5490,6 +5500,11 @@ abstract class InstanceElementImpl extends _ExistingElementImpl
54905500

54915501
@override
54925502
List<MethodElementImpl> get methods {
5503+
if (!identical(_methods, _Sentinel.methodElement)) {
5504+
return _methods;
5505+
}
5506+
5507+
linkedData?.readMembers(this);
54935508
return _methods;
54945509
}
54955510

@@ -5975,6 +5990,7 @@ abstract class InterfaceElementImpl extends InstanceElementImpl
59755990
}
59765991

59775992
_buildMixinAppConstructors();
5993+
linkedData?.readMembers(this);
59785994
return _constructors;
59795995
}
59805996

pkg/analyzer/lib/src/summary2/bundle_reader.dart

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ class BundleReader {
7676
return _LibraryHeader(
7777
uri: uriCache.parse(_reader.readStringReference()),
7878
offset: _reader.readUInt30(),
79+
classMembersLengths: _reader.readUInt30List(),
7980
macroGeneratedCode: _reader.readOptionalObject((reader) {
8081
return _reader.readStringUtf8();
8182
}),
@@ -94,6 +95,7 @@ class BundleReader {
9495
referenceReader: referenceReader,
9596
reference: reference,
9697
offset: libraryHeader.offset,
98+
classMembersLengths: libraryHeader.classMembersLengths,
9799
infoDeclarationStore: _infoDeclarationStore,
98100
macroGeneratedCode: libraryHeader.macroGeneratedCode,
99101
);
@@ -103,6 +105,8 @@ class BundleReader {
103105

104106
class ClassElementLinkedData extends ElementLinkedData<ClassElementImpl> {
105107
ApplyConstantOffsets? applyConstantOffsets;
108+
void Function()? _readMembers;
109+
void Function()? applyInformativeDataToMembers;
106110

107111
ClassElementLinkedData({
108112
required Reference reference,
@@ -112,17 +116,14 @@ class ClassElementLinkedData extends ElementLinkedData<ClassElementImpl> {
112116
}) : super(reference, libraryReader, unitElement, offset);
113117

114118
@override
115-
void readMembers(InstanceElementImpl element) {
116-
if (element is! ClassElementImpl) {
117-
return;
118-
}
119-
120-
// We might read class members before other properties.
121-
element.linkedData?.read(element);
122-
element.linkedData = null;
123-
124-
if (element.isMixinApplication) {
125-
element.constructors;
119+
void readMembers(covariant ClassElementImpl fragment) {
120+
// Read members of all fragments, in order.
121+
// So we always read a method augmentation after its target.
122+
for (var fragment in fragment.element.fragments) {
123+
var linkedData = fragment.linkedData;
124+
if (linkedData is ClassElementLinkedData) {
125+
linkedData._readSingleFragmentMembers(fragment);
126+
}
126127
}
127128
}
128129

@@ -154,6 +155,22 @@ class ClassElementLinkedData extends ElementLinkedData<ClassElementImpl> {
154155

155156
applyConstantOffsets?.perform();
156157
}
158+
159+
void _readSingleFragmentMembers(ClassElementImpl element) {
160+
// We might read class members before other properties.
161+
element.linkedData?.read(element);
162+
element.linkedData = null;
163+
164+
if (element.isMixinApplication) {
165+
element.constructors;
166+
} else {
167+
_readMembers?.call();
168+
_readMembers = null;
169+
170+
applyInformativeDataToMembers?.call();
171+
applyInformativeDataToMembers = null;
172+
}
173+
}
157174
}
158175

159176
class CompilationUnitElementLinkedData
@@ -615,6 +632,9 @@ class LibraryReader {
615632
final InfoDeclarationStore _deserializedDataStore;
616633
final String? macroGeneratedCode;
617634

635+
final Uint32List _classMembersLengths;
636+
int _classMembersLengthsIndex = 0;
637+
618638
late final LibraryElementImpl _libraryElement;
619639
late InstanceElementImpl2 _currentInstanceElement;
620640

@@ -627,6 +647,7 @@ class LibraryReader {
627647
required _ReferenceReader referenceReader,
628648
required Reference reference,
629649
required int offset,
650+
required Uint32List classMembersLengths,
630651
required InfoDeclarationStore infoDeclarationStore,
631652
required this.macroGeneratedCode,
632653
}) : _elementFactory = elementFactory,
@@ -636,6 +657,7 @@ class LibraryReader {
636657
_referenceReader = referenceReader,
637658
_reference = reference,
638659
_offset = offset,
660+
_classMembersLengths = classMembersLengths,
639661
_deserializedDataStore = infoDeclarationStore;
640662

641663
LibraryElementImpl readElement({required Source librarySource}) {
@@ -644,6 +666,11 @@ class LibraryReader {
644666

645667
_reader.offset = _offset;
646668

669+
// TODO(scheglov): https://github.com/dart-lang/sdk/issues/51855
670+
// This should not be needed.
671+
// But I have a suspicion that we attempt to read the library twice.
672+
_classMembersLengthsIndex = 0;
673+
647674
// Read enough data to create the library.
648675
var name = _reader.readStringReference();
649676
var featureSet = _readFeatureSet();
@@ -754,22 +781,37 @@ class LibraryReader {
754781
fragment.typeParameters = _readTypeParameters();
755782

756783
if (!fragment.isMixinApplication) {
757-
var accessors = <PropertyAccessorElementImpl>[];
758-
var fields = <FieldElementImpl>[];
759-
_readFields(unitElement, fragment, reference, accessors, fields);
760-
_readPropertyAccessors(
761-
unitElement, fragment, reference, accessors, fields, '@field');
762-
fragment.fields = fields.toFixedList();
763-
fragment.accessors = accessors.toFixedList();
764-
765-
fragment.constructors =
766-
_readConstructors(unitElement, fragment, reference);
767-
fragment.methods = _readMethods(unitElement, fragment, reference);
784+
var membersOffset = _reader.offset;
785+
linkedData._readMembers = () {
786+
_reader.offset = membersOffset;
787+
_readClassElementMembers(fragment, reference);
788+
};
789+
_reader.offset += _classMembersLengths[_classMembersLengthsIndex++];
768790
}
769791

770792
return fragment;
771793
}
772794

795+
void _readClassElementMembers(
796+
ClassElementImpl fragment,
797+
Reference reference,
798+
) {
799+
// print('[_readClassElementMembers][reference: $reference]');
800+
var unitElement = fragment.enclosingElement3;
801+
_currentInstanceElement = fragment.element;
802+
803+
var accessors = <PropertyAccessorElementImpl>[];
804+
var fields = <FieldElementImpl>[];
805+
_readFields(unitElement, fragment, reference, accessors, fields);
806+
_readPropertyAccessors(
807+
unitElement, fragment, reference, accessors, fields, '@field');
808+
fragment.fields = fields.toFixedList();
809+
fragment.accessors = accessors.toFixedList();
810+
811+
fragment.constructors = _readConstructors(unitElement, fragment, reference);
812+
fragment.methods = _readMethods(unitElement, fragment, reference);
813+
}
814+
773815
void _readClasses(
774816
CompilationUnitElementImpl unitElement,
775817
Reference unitReference,
@@ -2665,12 +2707,18 @@ class _LibraryHeader {
26652707
final Uri uri;
26662708
final int offset;
26672709

2710+
/// We don't read class members when reading libraries, by performance
2711+
/// reasons - in many cases only some classes of a library are used. But
2712+
/// we need to know how much data to skip for each class.
2713+
final Uint32List classMembersLengths;
2714+
26682715
/// The only (if any) macro generated augmentation code.
26692716
final String? macroGeneratedCode;
26702717

26712718
_LibraryHeader({
26722719
required this.uri,
26732720
required this.offset,
2721+
required this.classMembersLengths,
26742722
required this.macroGeneratedCode,
26752723
});
26762724
}

pkg/analyzer/lib/src/summary2/bundle_writer.dart

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ class BundleWriter {
5757
references: _references,
5858
);
5959

60+
/// [_writeClassElement] remembers the length of data written into [_sink]
61+
/// while writing members. So, when we read, we can skip members initially,
62+
/// and read them later on demand.
63+
List<int> _classMembersLengths = [];
64+
6065
final StringIndexer _stringIndexer = StringIndexer();
6166

6267
final List<_Library> _libraries = [];
@@ -73,6 +78,7 @@ class BundleWriter {
7378
_sink.writeList<_Library>(_libraries, (library) {
7479
_sink._writeStringReference(library.uriStr);
7580
_sink.writeUInt30(library.offset);
81+
_sink.writeUint30List(library.classMembersOffsets);
7682
_sink.writeOptionalObject(library.macroGenerated, (it) {
7783
_sink.writeStringUtf8(it.code);
7884
});
@@ -99,6 +105,7 @@ class BundleWriter {
99105

100106
void writeLibraryElement(LibraryElementImpl libraryElement) {
101107
var libraryOffset = _sink.offset;
108+
_classMembersLengths = [];
102109

103110
// Write non-resolution data for the library.
104111
_sink._writeStringReference(libraryElement.name);
@@ -128,6 +135,7 @@ class BundleWriter {
128135
_Library(
129136
uriStr: '${libraryElement.source.uri}',
130137
offset: libraryOffset,
138+
classMembersOffsets: _classMembersLengths,
131139
macroGenerated: macroGenerated,
132140
),
133141
);
@@ -171,6 +179,7 @@ class BundleWriter {
171179
}
172180

173181
if (!element.isMixinApplication) {
182+
var membersOffset = _sink.offset;
174183
_writeList(
175184
element.fields.where((e) => !e.isSynthetic).toList(),
176185
_writeFieldElement,
@@ -181,6 +190,7 @@ class BundleWriter {
181190
);
182191
_writeList(element.constructors, _writeConstructorElement);
183192
_writeList(element.methods, _writeMethodElement);
193+
_classMembersLengths.add(_sink.offset - membersOffset);
184194
}
185195
});
186196
}
@@ -1296,13 +1306,15 @@ class _BundleWriterReferences {
12961306
class _Library {
12971307
final String uriStr;
12981308
final int offset;
1309+
final List<int> classMembersOffsets;
12991310

13001311
/// The only (if any) macro generated fragment.
13011312
final MacroGeneratedLibraryFragment? macroGenerated;
13021313

13031314
_Library({
13041315
required this.uriStr,
13051316
required this.offset,
1317+
required this.classMembersOffsets,
13061318
required this.macroGenerated,
13071319
});
13081320
}

pkg/analyzer/lib/src/summary2/informative_data.dart

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,6 @@ class InformativeDataApplier {
227227
element.typeParameters_unresolved,
228228
info.typeParameters,
229229
);
230-
_applyToConstructors(element.constructors, info.constructors);
231-
_applyToFields(element.fields, info.fields);
232-
_applyToAccessors(element.accessors, info.accessors);
233-
_applyToMethods(element.methods, info.methods);
234230

235231
var applyOffsets = ApplyConstantOffsets(
236232
info.constantOffsets,
@@ -240,11 +236,20 @@ class InformativeDataApplier {
240236
},
241237
);
242238

239+
void applyToMembers() {
240+
_applyToConstructors(element.constructors, info.constructors);
241+
_applyToFields(element.fields, info.fields);
242+
_applyToAccessors(element.accessors, info.accessors);
243+
_applyToMethods(element.methods, info.methods);
244+
}
245+
243246
var linkedData = element.linkedData;
244247
if (linkedData is ClassElementLinkedData) {
245248
linkedData.applyConstantOffsets = applyOffsets;
249+
linkedData.applyInformativeDataToMembers = applyToMembers;
246250
} else {
247251
applyOffsets.perform();
252+
applyToMembers();
248253
}
249254
}
250255

pkg/analyzer/lib/src/utilities/extensions/element.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,17 @@ extension ClassElementExtension on ClassElement {
2525
}
2626
}
2727

28+
extension ClassElementImpl2Extension on ClassElementImpl2 {
29+
List<ClassElementImpl> get fragments {
30+
return [
31+
for (ClassElementImpl? fragment = firstFragment;
32+
fragment != null;
33+
fragment = fragment.nextFragment)
34+
fragment,
35+
];
36+
}
37+
}
38+
2839
extension CompilationUnitElementExtension on CompilationUnitElement {
2940
LibraryFragment get asElement2 {
3041
return this as LibraryFragment;

0 commit comments

Comments
 (0)