Skip to content

Commit 9d78664

Browse files
rakudramacommit-bot@chromium.org
authored andcommitted
[dart2js] Use Indexed{Sink/Source} for ConstantValue
This avoids naive tree-expansion of constant DAGs. Fixes a bug in IndexedSink where multiple nodes in a tree or list can be written as the same index, so on reading the second node is returned instead of the first. This affects source information of inlined methods where some frames are dropped. The .map files are about 10% larger with the frames. Change-Id: I7e39c72510145a5ee52ea07ad2a3860bd382ee20 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/110181 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Stephen Adams <[email protected]>
1 parent f38a719 commit 9d78664

File tree

3 files changed

+26
-9
lines changed

3 files changed

+26
-9
lines changed

pkg/compiler/lib/src/serialization/abstract_sink.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ abstract class AbstractDataSink extends DataSinkMixin implements DataSink {
3131
IndexedSink<Uri> _uriIndex;
3232
IndexedSink<ir.Member> _memberNodeIndex;
3333
IndexedSink<ImportEntity> _importIndex;
34+
IndexedSink<ConstantValue> _constantIndex;
3435

3536
Map<Type, IndexedSink> _generalCaches = {};
3637

@@ -49,6 +50,7 @@ abstract class AbstractDataSink extends DataSinkMixin implements DataSink {
4950
_uriIndex = new IndexedSink<Uri>(this);
5051
_memberNodeIndex = new IndexedSink<ir.Member>(this);
5152
_importIndex = new IndexedSink<ImportEntity>(this);
53+
_constantIndex = new IndexedSink<ConstantValue>(this);
5254
}
5355

5456
@override
@@ -465,6 +467,10 @@ abstract class AbstractDataSink extends DataSinkMixin implements DataSink {
465467
}
466468

467469
void _writeConstant(ConstantValue value) {
470+
_constantIndex.write(value, _writeConstantInternal);
471+
}
472+
473+
void _writeConstantInternal(ConstantValue value) {
468474
_writeEnumInternal(value.kind);
469475
switch (value.kind) {
470476
case ConstantValueKind.BOOL:

pkg/compiler/lib/src/serialization/abstract_source.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ abstract class AbstractDataSource extends DataSourceMixin
1919
IndexedSource<Uri> _uriIndex;
2020
IndexedSource<_MemberData> _memberNodeIndex;
2121
IndexedSource<ImportEntity> _importIndex;
22+
IndexedSource<ConstantValue> _constantIndex;
2223

2324
Map<Type, IndexedSource> _generalCaches = {};
2425

@@ -30,6 +31,7 @@ abstract class AbstractDataSource extends DataSourceMixin
3031
_uriIndex = new IndexedSource<Uri>(this);
3132
_memberNodeIndex = new IndexedSource<_MemberData>(this);
3233
_importIndex = new IndexedSource<ImportEntity>(this);
34+
_constantIndex = new IndexedSource<ConstantValue>(this);
3335
}
3436

3537
@override
@@ -533,6 +535,10 @@ abstract class AbstractDataSource extends DataSourceMixin
533535
}
534536

535537
ConstantValue _readConstant() {
538+
return _constantIndex.read(_readConstantInternal);
539+
}
540+
541+
ConstantValue _readConstantInternal() {
536542
ConstantValueKind kind = _readEnumInternal(ConstantValueKind.values);
537543
switch (kind) {
538544
case ConstantValueKind.BOOL:

pkg/compiler/lib/src/serialization/helpers.dart

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -335,8 +335,7 @@ class DartTypeNodeWriter
335335
/// Data sink helper that canonicalizes [E] values using indices.
336336
class IndexedSink<E> {
337337
final AbstractDataSink _sink;
338-
final Map<E, int> _cache = {};
339-
Set<E> _current = {};
338+
final Map<E, int> _cache = {null: 0}; // slot 0 is pre-allocated to `null`.
340339

341340
IndexedSink(this._sink);
342341

@@ -345,16 +344,16 @@ class IndexedSink<E> {
345344
/// If [value] has not been canonicalized yet, [writeValue] is called to
346345
/// serialize the [value] itself.
347346
void write(E value, void writeValue(E value)) {
347+
const int pending = -1;
348348
int index = _cache[value];
349349
if (index == null) {
350-
if (!_current.add(value)) {
351-
throw new ArgumentError("Cyclic dependency on cached value: $value");
352-
}
353350
index = _cache.length;
354351
_sink._writeIntInternal(index);
352+
_cache[value] = pending; // Increments length to allocate slot.
355353
writeValue(value);
356354
_cache[value] = index;
357-
_current.remove(value);
355+
} else if (index == pending) {
356+
throw ArgumentError("Cyclic dependency on cached value: $value");
358357
} else {
359358
_sink._writeIntInternal(index);
360359
}
@@ -364,7 +363,7 @@ class IndexedSink<E> {
364363
/// Data source helper reads canonicalized [E] values through indices.
365364
class IndexedSource<E> {
366365
final AbstractDataSource _source;
367-
final List<E> _cache = [];
366+
final List<E> _cache = [null]; // slot 0 is pre-allocated to `null`.
368367

369368
IndexedSource(this._source);
370369

@@ -375,11 +374,17 @@ class IndexedSource<E> {
375374
E read(E readValue()) {
376375
int index = _source._readIntInternal();
377376
if (index >= _cache.length) {
377+
assert(index == _cache.length);
378+
_cache.add(null); // placeholder.
378379
E value = readValue();
379-
_cache.add(value);
380+
_cache[index] = value;
380381
return value;
381382
} else {
382-
return _cache[index];
383+
E value = _cache[index];
384+
if (value == null && index != 0) {
385+
throw StateError('Unfilled index $index of $E');
386+
}
387+
return value;
383388
}
384389
}
385390
}

0 commit comments

Comments
 (0)