mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 10:49:00 +00:00
[dart2js] Migrate more of serialization/ to NNBD
This CL reduces the number of part files in serialization/ by moving classes into smaller libraries. This allows the {Data,Binary,Object}{Sink,Source} to be migrated to NNBD while sink.dart and source.dart still have dependencies. Change-Id: I0ea44f95841f18978e78c2e1697fbc97a3bf73c4 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/243711 Reviewed-by: Nate Biggs <natebiggs@google.com> Commit-Queue: Stephen Adams <sra@google.com>
This commit is contained in:
parent
5898dcd1ad
commit
56765625e0
13 changed files with 188 additions and 161 deletions
|
@ -2,16 +2,17 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// @dart = 2.10
|
||||
|
||||
part of 'serialization.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:kernel/binary/ast_to_binary.dart';
|
||||
import 'data_sink.dart';
|
||||
|
||||
/// [DataSink] that writes data as a sequence of bytes.
|
||||
///
|
||||
/// This data sink works together with [BinarySourceWriter].
|
||||
class BinaryDataSink implements DataSink {
|
||||
final Sink<List<int>> sink;
|
||||
BufferedSink _bufferedSink;
|
||||
// Nullable and non-final to allow storage to be released.
|
||||
BufferedSink? _bufferedSink;
|
||||
int _length = 0;
|
||||
|
||||
BinaryDataSink(this.sink) : _bufferedSink = BufferedSink(sink);
|
||||
|
@ -33,7 +34,7 @@ class BinaryDataSink implements DataSink {
|
|||
void writeString(String value) {
|
||||
List<int> bytes = utf8.encode(value);
|
||||
writeInt(bytes.length);
|
||||
_bufferedSink.addBytes(bytes);
|
||||
_bufferedSink!.addBytes(bytes);
|
||||
_length += bytes.length;
|
||||
}
|
||||
|
||||
|
@ -41,13 +42,13 @@ class BinaryDataSink implements DataSink {
|
|||
void writeInt(int value) {
|
||||
assert(value >= 0 && value >> 30 == 0);
|
||||
if (value < 0x80) {
|
||||
_bufferedSink.addByte(value);
|
||||
_bufferedSink!.addByte(value);
|
||||
_length += 1;
|
||||
} else if (value < 0x4000) {
|
||||
_bufferedSink.addByte2((value >> 8) | 0x80, value & 0xFF);
|
||||
_bufferedSink!.addByte2((value >> 8) | 0x80, value & 0xFF);
|
||||
_length += 2;
|
||||
} else {
|
||||
_bufferedSink.addByte4((value >> 24) | 0xC0, (value >> 16) & 0xFF,
|
||||
_bufferedSink!.addByte4((value >> 24) | 0xC0, (value >> 16) & 0xFF,
|
||||
(value >> 8) & 0xFF, value & 0xFF);
|
||||
_length += 4;
|
||||
}
|
||||
|
@ -60,7 +61,7 @@ class BinaryDataSink implements DataSink {
|
|||
|
||||
@override
|
||||
void close() {
|
||||
_bufferedSink.flushAndDestroy();
|
||||
_bufferedSink!.flushAndDestroy();
|
||||
_bufferedSink = null;
|
||||
sink.close();
|
||||
}
|
||||
|
|
|
@ -2,9 +2,10 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// @dart = 2.10
|
||||
|
||||
part of 'serialization.dart';
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'data_source.dart';
|
||||
import 'serialization_interfaces.dart' show StringInterner;
|
||||
|
||||
/// [DataSource] that reads data from a sequence of bytes.
|
||||
///
|
||||
|
@ -12,10 +13,12 @@ part of 'serialization.dart';
|
|||
class BinaryDataSource implements DataSource {
|
||||
int _byteOffset = 0;
|
||||
final List<int> _bytes;
|
||||
final StringInterner _stringInterner;
|
||||
final StringInterner? _stringInterner;
|
||||
|
||||
BinaryDataSource(this._bytes, {StringInterner stringInterner})
|
||||
: _stringInterner = stringInterner;
|
||||
BinaryDataSource(this._bytes, {StringInterner? stringInterner})
|
||||
: _stringInterner = stringInterner {
|
||||
assert((_bytes as dynamic) != null); // TODO(48820): Remove when sound.
|
||||
}
|
||||
|
||||
@override
|
||||
void begin(String tag) {}
|
||||
|
@ -33,7 +36,7 @@ class BinaryDataSource implements DataSource {
|
|||
_byteOffset += bytes.length;
|
||||
String string = utf8.decode(bytes);
|
||||
if (_stringInterner == null) return string;
|
||||
return _stringInterner.internString(string);
|
||||
return _stringInterner!.internString(string);
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
30
pkg/compiler/lib/src/serialization/data_sink.dart
Normal file
30
pkg/compiler/lib/src/serialization/data_sink.dart
Normal file
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
/// Interface handling [DataSinkWriter] low-level data serialization.
|
||||
///
|
||||
/// Each implementation of [DataSink] should have a corresponding
|
||||
/// [DataSource] that deserializes data serialized by that implementation.
|
||||
// TODO(48820): Move this interface back to 'sink.dart'.
|
||||
abstract class DataSink {
|
||||
int get length;
|
||||
|
||||
/// Serialization of a non-negative integer value.
|
||||
void writeInt(int value);
|
||||
|
||||
/// Serialization of an enum value.
|
||||
void writeEnum(dynamic value);
|
||||
|
||||
/// Serialization of a String value.
|
||||
void writeString(String value);
|
||||
|
||||
/// Serialization of a section begin tag. May be omitted by some writers.
|
||||
void beginTag(String tag);
|
||||
|
||||
/// Serialization of a section end tag. May be omitted by some writers.
|
||||
void endTag(String tag);
|
||||
|
||||
/// Closes any underlying data sinks.
|
||||
void close();
|
||||
}
|
29
pkg/compiler/lib/src/serialization/data_source.dart
Normal file
29
pkg/compiler/lib/src/serialization/data_source.dart
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
/// Interface handling [DataSourceReader] low-level data deserialization.
|
||||
///
|
||||
/// Each implementation of [DataSource] should have a corresponding
|
||||
/// [DataSink] for which it deserializes data.
|
||||
abstract class DataSource {
|
||||
/// Deserialization of a section begin tag.
|
||||
void begin(String tag);
|
||||
|
||||
/// Deserialization of a section end tag.
|
||||
void end(String tag);
|
||||
|
||||
/// Deserialization of a string value.
|
||||
String readString();
|
||||
|
||||
/// Deserialization of a non-negative integer value.
|
||||
int readInt();
|
||||
|
||||
/// Deserialization of an enum value in [values].
|
||||
E readEnum<E>(List<E> values);
|
||||
|
||||
/// Returns a string representation of the current state of the data source
|
||||
/// useful for debugging in consistencies between serialization and
|
||||
/// deserialization.
|
||||
String get errorContext;
|
||||
}
|
|
@ -166,66 +166,3 @@ class DartTypeNodeWriter
|
|||
visitTypes(node.typeArguments, functionTypeVariables);
|
||||
}
|
||||
}
|
||||
|
||||
/// Data sink helper that canonicalizes [E] values using indices.
|
||||
class IndexedSink<E> {
|
||||
final DataSink _sink;
|
||||
Map<E, int> cache;
|
||||
|
||||
IndexedSink(this._sink, {this.cache}) {
|
||||
// [cache] slot 0 is pre-allocated to `null`.
|
||||
this.cache ??= {null: 0};
|
||||
}
|
||||
|
||||
/// Write a reference to [value] to the data sink.
|
||||
///
|
||||
/// If [value] has not been canonicalized yet, [writeValue] is called to
|
||||
/// serialize the [value] itself.
|
||||
void write(E value, void writeValue(E value)) {
|
||||
const int pending = -1;
|
||||
int index = cache[value];
|
||||
if (index == null) {
|
||||
index = cache.length;
|
||||
_sink.writeInt(index);
|
||||
cache[value] = pending; // Increments length to allocate slot.
|
||||
writeValue(value);
|
||||
cache[value] = index;
|
||||
} else if (index == pending) {
|
||||
throw ArgumentError("Cyclic dependency on cached value: $value");
|
||||
} else {
|
||||
_sink.writeInt(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Data source helper reads canonicalized [E] values through indices.
|
||||
class IndexedSource<E> {
|
||||
final DataSource _sourceReader;
|
||||
List<E> cache;
|
||||
|
||||
IndexedSource(this._sourceReader, {this.cache}) {
|
||||
// [cache] slot 0 is pre-allocated to `null`.
|
||||
this.cache ??= [null];
|
||||
}
|
||||
|
||||
/// Reads a reference to an [E] value from the data source.
|
||||
///
|
||||
/// If the value hasn't yet been read, [readValue] is called to deserialize
|
||||
/// the value itself.
|
||||
E read(E readValue()) {
|
||||
int index = _sourceReader.readInt();
|
||||
if (index >= cache.length) {
|
||||
assert(index == cache.length);
|
||||
cache.add(null); // placeholder.
|
||||
E value = readValue();
|
||||
cache[index] = value;
|
||||
return value;
|
||||
} else {
|
||||
E value = cache[index];
|
||||
if (value == null && index != 0) {
|
||||
throw StateError('Unfilled index $index of $E');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
75
pkg/compiler/lib/src/serialization/indexed_sink_source.dart
Normal file
75
pkg/compiler/lib/src/serialization/indexed_sink_source.dart
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'data_sink.dart';
|
||||
import 'data_source.dart';
|
||||
|
||||
/// Data sink helper that canonicalizes [E?] values using indices.
|
||||
class IndexedSink<E extends Object> {
|
||||
final DataSink _sink;
|
||||
final Map<E?, int> cache;
|
||||
|
||||
IndexedSink._(this._sink, this.cache);
|
||||
|
||||
factory IndexedSink(DataSink sink, {Map<E?, int>? cache}) {
|
||||
// [cache] slot 0 is pre-allocated to `null`.
|
||||
cache ??= {null: 0};
|
||||
return IndexedSink._(sink, cache);
|
||||
}
|
||||
|
||||
/// Write a reference to [value] to the data sink.
|
||||
///
|
||||
/// If [value] has not been canonicalized yet, [writeValue] is called to
|
||||
/// serialize the [value] itself.
|
||||
void write(E? value, void writeValue(E value)) {
|
||||
const int pending = -1;
|
||||
int? index = cache[value];
|
||||
if (index == null) {
|
||||
index = cache.length;
|
||||
_sink.writeInt(index);
|
||||
cache[value] = pending; // Increments length to allocate slot.
|
||||
writeValue(value!); // `null` would have been found in slot 0.
|
||||
cache[value] = index;
|
||||
} else if (index == pending) {
|
||||
throw ArgumentError("Cyclic dependency on cached value: $value");
|
||||
} else {
|
||||
_sink.writeInt(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Data source helper reads canonicalized [E?] values through indices.
|
||||
class IndexedSource<E extends Object> {
|
||||
final DataSource _source;
|
||||
final List<E?> cache;
|
||||
|
||||
IndexedSource._(this._source, this.cache);
|
||||
|
||||
factory IndexedSource(DataSource source, {List<E?>? cache}) {
|
||||
// [cache] slot 0 is pre-allocated to `null`.
|
||||
cache ??= [null];
|
||||
return IndexedSource._(source, cache);
|
||||
}
|
||||
|
||||
/// Reads a reference to an [E] value from the data source.
|
||||
///
|
||||
/// If the value hasn't yet been read, [readValue] is called to deserialize
|
||||
/// the value itself.
|
||||
E? read(E readValue()) {
|
||||
int index = _source.readInt();
|
||||
if (index >= cache.length) {
|
||||
assert(index == cache.length);
|
||||
cache.add(null); // placeholder.
|
||||
E value = readValue();
|
||||
cache[index] = value;
|
||||
return value;
|
||||
} else {
|
||||
E? value = cache[index];
|
||||
if (value == null && index != 0) {
|
||||
throw StateError('Unfilled index $index of $E');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,45 +2,45 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// @dart = 2.10
|
||||
|
||||
part of 'serialization.dart';
|
||||
import 'data_sink.dart';
|
||||
import 'tags.dart' show Tag;
|
||||
|
||||
/// [DataSinkWriter] that writes to a list of objects, useful for debugging
|
||||
/// inconsistencies between serialization and deserialization.
|
||||
///
|
||||
/// This data sink writer works together with [ObjectDataSource].
|
||||
class ObjectDataSink implements DataSink {
|
||||
List<dynamic> _data;
|
||||
// [_data] is nullable and non-final to allow storage to be released.
|
||||
List<dynamic>? _data;
|
||||
|
||||
ObjectDataSink(this._data);
|
||||
|
||||
@override
|
||||
void beginTag(String tag) {
|
||||
_data.add(Tag('begin:$tag'));
|
||||
_data!.add(Tag('begin:$tag'));
|
||||
}
|
||||
|
||||
@override
|
||||
void endTag(String tag) {
|
||||
_data.add(Tag('end:$tag'));
|
||||
_data!.add(Tag('end:$tag'));
|
||||
}
|
||||
|
||||
@override
|
||||
void writeEnum(dynamic value) {
|
||||
assert(value != null);
|
||||
_data.add(value);
|
||||
assert((value as dynamic) != null); // TODO(48820): Remove when sound.
|
||||
_data!.add(value);
|
||||
}
|
||||
|
||||
@override
|
||||
void writeInt(int value) {
|
||||
assert(value != null);
|
||||
_data.add(value);
|
||||
assert((value as dynamic) != null); // TODO(48820): Remove when sound.
|
||||
_data!.add(value);
|
||||
}
|
||||
|
||||
@override
|
||||
void writeString(String value) {
|
||||
assert(value != null);
|
||||
_data.add(value);
|
||||
assert((value as dynamic) != null); // TODO(48820): Remove when sound.
|
||||
_data!.add(value);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -50,5 +50,5 @@ class ObjectDataSink implements DataSink {
|
|||
|
||||
/// Returns the number of objects written to this data sink.
|
||||
@override
|
||||
int get length => _data.length;
|
||||
int get length => _data!.length;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// @dart = 2.10
|
||||
|
||||
part of 'serialization.dart';
|
||||
import 'data_source.dart';
|
||||
import 'tags.dart' show Tag;
|
||||
|
||||
/// [DataSource] that read from a list of objects, useful for debugging
|
||||
/// inconsistencies between serialization and deserialization.
|
||||
|
@ -17,9 +16,9 @@ class ObjectDataSource implements DataSource {
|
|||
ObjectDataSource(this._data);
|
||||
|
||||
T _read<T>() {
|
||||
dynamic value = _data[_index++];
|
||||
assert(value is T, "Expected $T value, found $value.$errorContext");
|
||||
return value;
|
||||
Object? value = _data[_index++];
|
||||
if (value is T) return value;
|
||||
throw StateError('Expected $T value, found $value.$errorContext');
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -5,10 +5,8 @@
|
|||
// @dart = 2.10
|
||||
|
||||
import 'dart:collection';
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
import 'package:kernel/ast.dart' as ir;
|
||||
import 'package:kernel/binary/ast_to_binary.dart';
|
||||
import '../closure.dart';
|
||||
import '../constants/constant_system.dart' as constant_system;
|
||||
import '../constants/values.dart';
|
||||
|
@ -25,24 +23,24 @@ import '../js_model/closure.dart';
|
|||
import '../js_model/locals.dart';
|
||||
import '../js_model/type_recipe.dart' show TypeRecipe;
|
||||
|
||||
import 'data_sink.dart';
|
||||
import 'data_source.dart';
|
||||
import 'member_data.dart';
|
||||
export 'member_data.dart' show ComponentLookup, computeMemberName;
|
||||
import 'serialization_interfaces.dart' as migrated
|
||||
show DataSourceReader, DataSinkWriter;
|
||||
import 'indexed_sink_source.dart';
|
||||
import 'tags.dart';
|
||||
|
||||
export 'binary_sink.dart';
|
||||
export 'binary_source.dart';
|
||||
export 'member_data.dart' show ComponentLookup, computeMemberName;
|
||||
export 'object_sink.dart';
|
||||
export 'object_source.dart';
|
||||
export 'tags.dart';
|
||||
|
||||
part 'sink.dart';
|
||||
part 'source.dart';
|
||||
part 'binary_sink.dart';
|
||||
part 'binary_source.dart';
|
||||
part 'helpers.dart';
|
||||
part 'object_sink.dart';
|
||||
part 'object_source.dart';
|
||||
|
||||
abstract class StringInterner {
|
||||
String internString(String string);
|
||||
}
|
||||
|
||||
class ValueInterner {
|
||||
final Map<DartType, DartType> _dartTypeMap = HashMap();
|
||||
|
|
|
@ -9,6 +9,10 @@ import '../elements/types.dart' show DartType;
|
|||
|
||||
export 'tags.dart';
|
||||
|
||||
abstract class StringInterner {
|
||||
String internString(String string);
|
||||
}
|
||||
|
||||
/// NNBD-migrated interface for methods of DataSinkWriter.
|
||||
///
|
||||
/// This is a pure interface or facade for DataSinkWriter.
|
||||
|
@ -73,6 +77,7 @@ abstract class DataSinkWriter {
|
|||
{bool allowNull = false});
|
||||
|
||||
void writeCached<E extends Object>(E value, void f(E value));
|
||||
|
||||
void writeList<E extends Object>(Iterable<E> values, void f(E value),
|
||||
{bool allowNull = false});
|
||||
}
|
||||
|
@ -112,6 +117,7 @@ abstract class DataSourceReader {
|
|||
Map<K, V>? readTreeNodeMapInContextOrNull<K extends ir.TreeNode, V>(V f());
|
||||
|
||||
E readCached<E extends Object>(E f());
|
||||
|
||||
List<E> readList<E extends Object>(E f());
|
||||
List<E>? readListOrNull<E extends Object>(E f());
|
||||
}
|
||||
|
|
|
@ -6,32 +6,6 @@
|
|||
|
||||
part of 'serialization.dart';
|
||||
|
||||
/// Interface handling [DataSinkWriter] low-level data serialization.
|
||||
///
|
||||
/// Each implementation of [DataSink] should have a corresponding
|
||||
/// [DataSource] that deserializes data serialized by that implementation.
|
||||
abstract class DataSink {
|
||||
int get length;
|
||||
|
||||
/// Serialization of a non-negative integer value.
|
||||
void writeInt(int value);
|
||||
|
||||
/// Serialization of an enum value.
|
||||
void writeEnum(dynamic value);
|
||||
|
||||
/// Serialization of a String value.
|
||||
void writeString(String value);
|
||||
|
||||
/// Serialization of a section begin tag. May be omitted by some writers.
|
||||
void beginTag(String tag);
|
||||
|
||||
/// Serialization of a section end tag. May be omitted by some writers.
|
||||
void endTag(String tag);
|
||||
|
||||
/// Closes any underlying data sinks.
|
||||
void close();
|
||||
}
|
||||
|
||||
/// Serialization writer
|
||||
///
|
||||
/// To be used with [DataSourceReader] to read and write serialized data.
|
||||
|
|
|
@ -6,32 +6,6 @@
|
|||
|
||||
part of 'serialization.dart';
|
||||
|
||||
/// Interface handling [DataSourceReader] low-level data deserialization.
|
||||
///
|
||||
/// Each implementation of [DataSource] should have a corresponding
|
||||
/// [DataSink] for which it deserializes data.
|
||||
abstract class DataSource {
|
||||
/// Deserialization of a section begin tag.
|
||||
void begin(String tag);
|
||||
|
||||
/// Deserialization of a section end tag.
|
||||
void end(String tag);
|
||||
|
||||
/// Deserialization of a string value.
|
||||
String readString();
|
||||
|
||||
/// Deserialization of a non-negative integer value.
|
||||
int readInt();
|
||||
|
||||
/// Deserialization of an enum value in [values].
|
||||
E readEnum<E>(List<E> values);
|
||||
|
||||
/// Returns a string representation of the current state of the data source
|
||||
/// useful for debugging in consistencies between serialization and
|
||||
/// deserialization.
|
||||
String get errorContext;
|
||||
}
|
||||
|
||||
/// Deserialization reader
|
||||
///
|
||||
/// To be used with [DataSinkWriter] to read and write serialized data.
|
||||
|
|
|
@ -29,6 +29,7 @@ import '../options.dart';
|
|||
import '../util/sink_adapter.dart';
|
||||
import '../world.dart';
|
||||
import 'serialization.dart';
|
||||
import 'serialization_interfaces.dart' show StringInterner;
|
||||
|
||||
/// A data class holding a [JsClosedWorld] and the associated
|
||||
/// [DataSourceIndices].
|
||||
|
|
Loading…
Reference in a new issue