Use cached serialization of source-information
This reduces the size of the serialized codegen data by 20-25%
Change-Id: I85424576d68b72a56c3c924fe704a086000bc926
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/103534
Commit-Queue: Johnni Winther <johnniwinther@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 928e70d..f7c4050 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -1096,7 +1096,10 @@
}
void _writeInfo(js.Node node) {
- SourceInformation.writeToDataSink(sink, node.sourceInformation);
+ sink.writeCached<SourceInformation>(node.sourceInformation,
+ (SourceInformation sourceInformation) {
+ SourceInformation.writeToDataSink(sink, sourceInformation);
+ });
}
@override
@@ -2091,7 +2094,9 @@
break;
}
SourceInformation sourceInformation =
- SourceInformation.readFromDataSource(source);
+ source.readCached<SourceInformation>(() {
+ return SourceInformation.readFromDataSource(source);
+ });
if (sourceInformation != null) {
node = node.withSourceInformation(sourceInformation);
}
diff --git a/pkg/compiler/lib/src/io/position_information.dart b/pkg/compiler/lib/src/io/position_information.dart
index a92ab7e..cb1c2a4 100644
--- a/pkg/compiler/lib/src/io/position_information.dart
+++ b/pkg/compiler/lib/src/io/position_information.dart
@@ -12,6 +12,7 @@
import '../js/js_debug.dart';
import '../js/js_source_mapping.dart';
import '../serialization/serialization.dart';
+import '../util/util.dart';
import 'code_output.dart' show BufferedCodeOutput;
import 'source_information.dart';
@@ -34,8 +35,10 @@
factory PositionSourceInformation.readFromDataSource(DataSource source) {
source.begin(tag);
- SourceLocation startPosition = SourceLocation.readFromDataSource(source);
- SourceLocation innerPosition = SourceLocation.readFromDataSource(source);
+ SourceLocation startPosition = source.readCached<SourceLocation>(
+ () => SourceLocation.readFromDataSource(source));
+ SourceLocation innerPosition = source.readCached<SourceLocation>(
+ () => SourceLocation.readFromDataSource(source));
List<FrameContext> inliningContext = source.readList(
() => FrameContext.readFromDataSource(source),
emptyAsNull: true);
@@ -46,8 +49,14 @@
void writeToDataSinkInternal(DataSink sink) {
sink.begin(tag);
- SourceLocation.writeToDataSink(sink, startPosition);
- SourceLocation.writeToDataSink(sink, innerPosition);
+ sink.writeCached(
+ startPosition,
+ (SourceLocation sourceLocation) =>
+ SourceLocation.writeToDataSink(sink, sourceLocation));
+ sink.writeCached(
+ innerPosition,
+ (SourceLocation sourceLocation) =>
+ SourceLocation.writeToDataSink(sink, sourceLocation));
sink.writeList(inliningContext,
(FrameContext context) => context.writeToDataSink(sink),
allowNull: true);
@@ -77,16 +86,17 @@
@override
int get hashCode {
- return 0x7FFFFFFF &
- (startPosition.hashCode * 17 + innerPosition.hashCode * 19);
+ return Hashing.listHash(
+ inliningContext, Hashing.objectsHash(startPosition, innerPosition));
}
@override
bool operator ==(other) {
if (identical(this, other)) return true;
- if (other is! PositionSourceInformation) return false;
- return startPosition == other.startPosition &&
- innerPosition == other.innerPosition;
+ return other is PositionSourceInformation &&
+ startPosition == other.startPosition &&
+ innerPosition == other.innerPosition &&
+ equalElements(inliningContext, other.inliningContext);
}
/// Create a textual representation of the source information using [uriText]
diff --git a/pkg/compiler/lib/src/io/source_information.dart b/pkg/compiler/lib/src/io/source_information.dart
index bc8f6e7..0034fb5 100644
--- a/pkg/compiler/lib/src/io/source_information.dart
+++ b/pkg/compiler/lib/src/io/source_information.dart
@@ -84,8 +84,8 @@
factory FrameContext.readFromDataSource(DataSource source) {
source.begin(tag);
- SourceInformation callInformation =
- SourceInformation.readFromDataSource(source);
+ SourceInformation callInformation = source.readCached<SourceInformation>(
+ () => SourceInformation.readFromDataSource(source));
String inlinedMethodName = source.readString();
source.end(tag);
return new FrameContext(callInformation, inlinedMethodName);
@@ -93,7 +93,10 @@
void writeToDataSink(DataSink sink) {
sink.begin(tag);
- SourceInformation.writeToDataSink(sink, callInformation);
+ sink.writeCached<SourceInformation>(
+ callInformation,
+ (SourceInformation sourceInformation) =>
+ SourceInformation.writeToDataSink(sink, sourceInformation));
sink.writeString(inlinedMethodName);
sink.end(tag);
}
@@ -317,8 +320,8 @@
@override
bool operator ==(other) {
if (identical(this, other)) return true;
- if (other is! SourceLocation) return false;
- return sourceUri == other.sourceUri &&
+ return other is SourceLocation &&
+ sourceUri == other.sourceUri &&
offset == other.offset &&
sourceName == other.sourceName;
}
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index 2015a3a..a1af8e8 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -37,7 +37,9 @@
EntityWriter _entityWriter = const EntityWriter();
CodegenWriter _codegenWriter;
- AbstractDataSink({this.useDataKinds: false}) {
+ final Map<String, int> tagFrequencyMap;
+
+ AbstractDataSink({this.useDataKinds: false, this.tagFrequencyMap}) {
_dartTypeWriter = new DartTypeWriter(this);
_dartTypeNodeWriter = new DartTypeNodeWriter(this);
_stringIndex = new IndexedSink<String>(this);
@@ -48,6 +50,10 @@
@override
void begin(String tag) {
+ if (tagFrequencyMap != null) {
+ tagFrequencyMap[tag] ??= 0;
+ tagFrequencyMap[tag]++;
+ }
if (useDataKinds) {
_tags ??= <String>[];
_tags.add(tag);
diff --git a/pkg/compiler/lib/src/serialization/binary_sink.dart b/pkg/compiler/lib/src/serialization/binary_sink.dart
index 3f771b4..6d46fb4 100644
--- a/pkg/compiler/lib/src/serialization/binary_sink.dart
+++ b/pkg/compiler/lib/src/serialization/binary_sink.dart
@@ -12,9 +12,10 @@
BufferedSink _bufferedSink;
int _length = 0;
- BinarySink(this.sink, {bool useDataKinds: false})
+ BinarySink(this.sink,
+ {bool useDataKinds: false, Map<String, int> tagFrequencyMap})
: _bufferedSink = new BufferedSink(sink),
- super(useDataKinds: useDataKinds);
+ super(useDataKinds: useDataKinds, tagFrequencyMap: tagFrequencyMap);
@override
void _begin(String tag) {
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index c0c8c29..b73a8c9 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -336,6 +336,7 @@
class IndexedSink<E> {
final AbstractDataSink _sink;
final Map<E, int> _cache = {};
+ Set<E> _current = {};
IndexedSink(this._sink);
@@ -346,10 +347,14 @@
void write(E value, void writeValue(E value)) {
int index = _cache[value];
if (index == null) {
+ if (!_current.add(value)) {
+ throw new ArgumentError("Cyclic dependency on cached value: $value");
+ }
index = _cache.length;
- _cache[value] = index;
_sink._writeIntInternal(index);
writeValue(value);
+ _cache[value] = index;
+ _current.remove(value);
} else {
_sink._writeIntInternal(index);
}
diff --git a/pkg/compiler/lib/src/serialization/object_sink.dart b/pkg/compiler/lib/src/serialization/object_sink.dart
index 31376e3..82c8885 100644
--- a/pkg/compiler/lib/src/serialization/object_sink.dart
+++ b/pkg/compiler/lib/src/serialization/object_sink.dart
@@ -11,8 +11,8 @@
class ObjectSink extends AbstractDataSink {
List<dynamic> _data;
- ObjectSink(this._data, {bool useDataKinds})
- : super(useDataKinds: useDataKinds);
+ ObjectSink(this._data, {bool useDataKinds, Map<String, int> tagFrequencyMap})
+ : super(useDataKinds: useDataKinds, tagFrequencyMap: tagFrequencyMap);
@override
void _begin(String tag) {
diff --git a/pkg/compiler/tool/modular_dart2js.dart b/pkg/compiler/tool/modular_dart2js.dart
index e313a9d..f8e15e3 100644
--- a/pkg/compiler/tool/modular_dart2js.dart
+++ b/pkg/compiler/tool/modular_dart2js.dart
@@ -9,19 +9,25 @@
main(List<String> args) async {
Stopwatch stopwatch = new Stopwatch();
String input;
+ String serializedInput;
String output = 'out.js';
List<String> arguments = [];
int start = 0;
+ int stop = 3;
int shards;
bool enableAssertions = false;
for (String arg in args) {
if (arg.startsWith('-')) {
if (arg.startsWith('--start=')) {
start = int.parse(arg.substring('--start='.length));
+ } else if (arg.startsWith('--stop=')) {
+ stop = int.parse(arg.substring('--stop='.length));
} else if (arg.startsWith('--shards=')) {
shards = int.parse(arg.substring('--shards='.length));
} else if (arg == '-ea' || arg == '--enable_asserts') {
enableAssertions = true;
+ } else if (arg.startsWith('--in=')) {
+ serializedInput = arg.substring('--in='.length);
} else if (arg.startsWith('-o')) {
output = arg.substring('-o'.length);
} else if (arg.startsWith('--out=')) {
@@ -43,6 +49,12 @@
exit(-1);
}
+ serializedInput ??= output;
+
+ String inputPrefix = serializedInput;
+ if (serializedInput.endsWith('.js')) {
+ inputPrefix = output.substring(0, output.length - '.js'.length);
+ }
String outputPrefix = output;
if (output.endsWith('.js')) {
outputPrefix = output.substring(0, output.length - '.js'.length);
@@ -55,18 +67,18 @@
baseOptions.add('package:compiler/src/dart2js.dart');
baseOptions.addAll(arguments);
- String cfeOutput = '${outputPrefix}0.dill';
- String dillOutput = '${outputPrefix}.dill';
- String dataOutput = '${outputPrefix}.dill.data';
+ String cfeOutput = '${inputPrefix}0.dill';
+ String dillOutput = '${inputPrefix}.dill';
+ String dataOutput = '${inputPrefix}.dill.data';
String codeOutput = '${outputPrefix}.code';
shards ??= 2;
stopwatch.start();
- if (start <= 0) {
+ if (start <= 0 && stop >= 0) {
await subProcess(
baseOptions, [input, Flags.cfeOnly, '--out=$cfeOutput'], '0:\t');
}
- if (start <= 1) {
+ if (start <= 1 && stop >= 1) {
await subProcess(
baseOptions,
[cfeOutput, '--out=$dillOutput', '${Flags.writeData}=${dataOutput}'],
@@ -78,7 +90,7 @@
[dillOutput, '${Flags.readData}=${dataOutput}', '--out=${output}'],
'3:\t');
} else {
- if (start <= 2) {
+ if (start <= 2 && stop >= 2) {
List<List<String>> additionalArguments = [];
List<String> outputPrefixes = [];
for (int shard = 0; shard < shards; shard++) {
@@ -101,7 +113,7 @@
subwatch.stop();
print('2:\tTotal time: ${_formatMs(subwatch.elapsedMilliseconds)}');
}
- if (start <= 3) {
+ if (start <= 3 && stop >= 3) {
await subProcess(
baseOptions,
[