Version 2.15.0-118.0.dev
Merge commit '78b9f5495796463bd09e01ab7f90477840d8f0e4' into 'dev'
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index fe38ee1..722a3f4 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
@@ -21,10 +21,11 @@
Element,
ElementKind,
FieldElement,
+ FunctionElement,
LibraryElement,
+ LocalVariableElement,
PropertyAccessorElement,
- TopLevelVariableElement,
- LocalVariableElement;
+ TopLevelVariableElement;
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/dart/element/type_system.dart';
@@ -322,7 +323,9 @@
// override of `noSuchMethod`.
return 0.0;
}
- return proposedMemberName == 'noSuchMethod' ? -1.0 : 0.0;
+ return proposedMemberName == FunctionElement.NO_SUCH_METHOD_METHOD_NAME
+ ? -1.0
+ : 0.0;
}
/// Return the value of the _keyword_ feature for the [keyword] when
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
index 9bcd314..71cc613 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/suggestion_builder.dart
@@ -457,9 +457,8 @@
/// Add a suggestion for the `call` method defined on functions.
void suggestFunctionCall() {
- const callString = 'call';
- final element = protocol.Element(
- protocol.ElementKind.METHOD, callString, protocol.Element.makeFlags(),
+ final element = protocol.Element(protocol.ElementKind.METHOD,
+ FunctionElement.CALL_METHOD_NAME, protocol.Element.makeFlags(),
location: null,
typeParameters: null,
parameters: '()',
@@ -467,8 +466,8 @@
_add(CompletionSuggestion(
CompletionSuggestionKind.INVOCATION,
Relevance.callFunction,
- callString,
- callString.length,
+ FunctionElement.CALL_METHOD_NAME,
+ FunctionElement.CALL_METHOD_NAME.length,
0,
false,
false,
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index 8387f8a..26da055 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -140,7 +140,8 @@
if (elementKind == ElementKind.CONSTRUCTOR) {
kind = IndexSyntheticElementKind.constructor;
element = element.enclosingElement!;
- } else if (element is FunctionElement && element.name == 'loadLibrary') {
+ } else if (element is FunctionElement &&
+ element.name == FunctionElement.LOAD_LIBRARY_NAME) {
kind = IndexSyntheticElementKind.loadLibrary;
element = element.library;
} else if (elementKind == ElementKind.FIELD) {
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
index 4f0e447..86ad536 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager3.dart
@@ -43,7 +43,8 @@
/// Manages knowledge about interface types and their members.
class InheritanceManager3 {
- static final _noSuchMethodName = Name(null, 'noSuchMethod');
+ static final _noSuchMethodName =
+ Name(null, FunctionElement.NO_SUCH_METHOD_METHOD_NAME);
/// Cached instance interfaces for [ClassElement].
final Map<ClassElement, Interface> _interfaces = {};
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index 4e01067..ce90a43 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -316,7 +316,9 @@
/// return the function type for the call method, otherwise return null.
FunctionType? getCallMethodType(DartType t) {
if (t is InterfaceType) {
- return t.lookUpMethod2('call', t.element.library)?.type;
+ return t
+ .lookUpMethod2(FunctionElement.CALL_METHOD_NAME, t.element.library)
+ ?.type;
}
return null;
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
index 790cd79..0427d04 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_reference_resolver.dart
@@ -77,6 +77,31 @@
}
}
+ /// Checks for a type instantiation of a `dynamic`-typed expression.
+ ///
+ /// Returns `true` if an error was reported, and resolution can stop.
+ bool _checkDynamicTypeInstantiation(FunctionReferenceImpl node,
+ PrefixedIdentifierImpl function, Element prefixElement) {
+ DartType? prefixType;
+ if (prefixElement is VariableElement) {
+ prefixType = prefixElement.type;
+ } else if (prefixElement is PropertyAccessorElement) {
+ prefixType = prefixElement.returnType;
+ }
+
+ function.prefix.staticType = prefixType;
+ if (prefixType != null && prefixType.isDynamic) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.GENERIC_METHOD_TYPE_INSTANTIATION_ON_DYNAMIC,
+ function,
+ [],
+ );
+ node.staticType = DynamicTypeImpl.instance;
+ return true;
+ }
+ return false;
+ }
+
List<DartType> _checkTypeArguments(
TypeArgumentList typeArgumentList,
String? name,
@@ -271,6 +296,36 @@
_resolve(node: node, rawType: member.type, name: propertyName.name);
}
+ /// Resolve a possible function tearoff of a [FunctionElement] receiver.
+ ///
+ /// There are three possible valid cases: tearing off the `call` method of a
+ /// function element, tearing off an extension element declared on [Function],
+ /// and tearing off an extension element declared on a function type.
+ ExecutableElement? _resolveFunctionElementFunction(
+ Expression receiver,
+ SimpleIdentifier methodName,
+ FunctionElement receiverElement,
+ ) {
+ if (methodName.name == FunctionElement.CALL_METHOD_NAME) {
+ return receiverElement;
+ }
+
+ var methodElement = _resolver.typePropertyResolver
+ .resolve(
+ receiver: receiver,
+ receiverType: receiverElement.type,
+ name: methodName.name,
+ propertyErrorEntity: methodName,
+ nameErrorEntity: methodName,
+ )
+ .getter;
+ if (methodElement != null && methodElement.isStatic) {
+ _reportInvalidAccessToStaticMember(methodName, methodElement,
+ implicitReceiver: false);
+ }
+ return methodElement;
+ }
+
void _resolvePrefixedIdentifierFunction(
FunctionReferenceImpl node, PrefixedIdentifierImpl function) {
var prefixElement = function.prefix.scopeLookupResult!.getter;
@@ -287,14 +342,15 @@
}
function.prefix.staticElement = prefixElement;
+ var functionName = function.identifier.name;
+
if (prefixElement is PrefixElement) {
- var functionName = function.identifier.name;
var functionElement = prefixElement.scope.lookup(functionName).getter;
if (functionElement == null) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.UNDEFINED_PREFIXED_NAME,
function.identifier,
- [function.identifier.name, function.prefix.name],
+ [functionName, function.prefix.name],
);
function.staticType = DynamicTypeImpl.instance;
node.staticType = DynamicTypeImpl.instance;
@@ -306,21 +362,17 @@
}
}
- DartType? prefixType;
- if (prefixElement is VariableElement) {
- prefixType = prefixElement.type;
- } else if (prefixElement is PropertyAccessorElement) {
- prefixType = prefixElement.returnType;
+ if (_checkDynamicTypeInstantiation(node, function, prefixElement)) {
+ return;
}
- function.prefix.staticType = prefixType;
- if (prefixType != null && prefixType.isDynamic) {
- _errorReporter.reportErrorForNode(
- CompileTimeErrorCode.GENERIC_METHOD_TYPE_INSTANTIATION_ON_DYNAMIC,
- function,
- [],
+ if (prefixElement is FunctionElement &&
+ functionName == FunctionElement.CALL_METHOD_NAME) {
+ _resolve(
+ node: node,
+ rawType: prefixElement.type,
+ name: functionName,
);
- node.staticType = DynamicTypeImpl.instance;
return;
}
@@ -337,7 +389,7 @@
_resolve(
node: node,
rawType: methodElement.type,
- name: function.identifier.name,
+ name: functionName,
);
return;
}
@@ -686,6 +738,8 @@
}
if (receiverElement is ClassElement) {
return _resolveStaticElement(receiverElement, name);
+ } else if (receiverElement is FunctionElement) {
+ return _resolveFunctionElementFunction(receiver, name, receiverElement);
} else if (receiverElement is TypeAliasElement) {
var aliasedType = receiverElement.aliasedType;
if (aliasedType is InterfaceType) {
diff --git a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
index 86f1008..307a656 100644
--- a/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/property_element_resolver.dart
@@ -350,7 +350,8 @@
var targetType = target.typeOrThrow;
- if (targetType is FunctionType && propertyName.name == 'call') {
+ if (targetType is FunctionType &&
+ propertyName.name == FunctionElement.CALL_METHOD_NAME) {
return PropertyElementResolverResult(
functionTypeCallType: targetType,
);
diff --git a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
index 1f2aaf5..2a71f1d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/type_property_resolver.dart
@@ -170,14 +170,16 @@
if (_hasGetterOrSetter) {
return _toResult();
}
- if (receiverTypeResolved.isDartCoreFunction && _name == 'call') {
+ if (receiverTypeResolved.isDartCoreFunction &&
+ _name == FunctionElement.CALL_METHOD_NAME) {
_needsGetterError = false;
_needsSetterError = false;
return _toResult();
}
}
- if (receiverTypeResolved is FunctionType && _name == 'call') {
+ if (receiverTypeResolved is FunctionType &&
+ _name == FunctionElement.CALL_METHOD_NAME) {
return _toResult();
}
diff --git a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
index 9415a30..ca0efc9 100644
--- a/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
+++ b/pkg/analyzer/lib/src/error/duplicate_definition_verifier.dart
@@ -14,7 +14,7 @@
static final Set<String> _enumInstanceMembers = {
'hashCode',
'index',
- 'noSuchMethod',
+ FunctionElement.NO_SUCH_METHOD_METHOD_NAME,
'runtimeType',
'toString',
};
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 31e2553..bf8620e 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -2396,7 +2396,7 @@
name == 'hashCode' ||
name == 'toString' ||
name == 'runtimeType' ||
- name == 'noSuchMethod') {
+ name == FunctionElement.NO_SUCH_METHOD_METHOD_NAME) {
errorReporter.reportErrorForNode(
CompileTimeErrorCode.EXTENSION_DECLARES_MEMBER_OF_OBJECT,
node.name,
diff --git a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
index 37dddf5..9585048 100644
--- a/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/function_reference_test.dart
@@ -334,6 +334,102 @@
reference, findElement.method('foo'), 'void Function(int)');
}
+ test_function_call() async {
+ await assertNoErrorsInCode('''
+void foo<T>(T a) {}
+
+void bar() {
+ foo.call<int>;
+}
+''');
+
+ assertFunctionReference(findNode.functionReference('foo.call<int>;'), null,
+ 'void Function(int)');
+ }
+
+ test_function_call_tooFewTypeArgs() async {
+ await assertErrorsInCode('''
+void foo<T, U>(T a, U b) {}
+
+void bar() {
+ foo.call<int>;
+}
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 52, 5),
+ ]);
+
+ assertFunctionReference(findNode.functionReference('foo.call<int>;'), null,
+ 'void Function(dynamic, dynamic)');
+ }
+
+ test_function_call_tooManyTypeArgs() async {
+ await assertErrorsInCode('''
+void foo(String a) {}
+
+void bar() {
+ foo.call<int>;
+}
+''', [
+ error(
+ CompileTimeErrorCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_FUNCTION, 46, 5),
+ ]);
+
+ assertFunctionReference(findNode.functionReference('foo.call<int>;'), null,
+ 'void Function(String)');
+ }
+
+ test_function_call_typeArgNotMatchingBound() async {
+ await assertNoErrorsInCode('''
+void foo<T extends num>(T a) {}
+
+void bar() {
+ foo.call<String>;
+}
+''');
+
+ assertFunctionReference(findNode.functionReference('foo.call<String>;'),
+ null, 'void Function(String)');
+ }
+
+ test_function_extensionOnFunction() async {
+ // TODO(srawlins): Test extension on function type, like
+ // `extension on void Function<T>(T)`.
+ await assertNoErrorsInCode('''
+void foo<T>(T a) {}
+
+void bar() {
+ foo.m<int>;
+}
+
+extension on Function {
+ void m<T>(T t) {}
+}
+''');
+
+ assertFunctionReference(findNode.functionReference('foo.m<int>;'),
+ findElement.method('m'), 'void Function(int)');
+ }
+
+ test_function_extensionOnFunction_static() async {
+ await assertErrorsInCode('''
+void foo<T>(T a) {}
+
+void bar() {
+ foo.m<int>;
+}
+
+extension on Function {
+ static void m<T>(T t) {}
+}
+''', [
+ error(CompileTimeErrorCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, 40, 1),
+ ]);
+
+ assertFunctionReference(findNode.functionReference('foo.m<int>;'),
+ findElement.method('m'), 'void Function(int)');
+ }
+
test_instanceGetter_explicitReceiver() async {
await assertErrorsInCode('''
class A {
@@ -1040,6 +1136,21 @@
findNode.functionReference('foo<int>;'), null, 'dynamic');
}
+ test_topLevelFunction_targetOfCall() async {
+ await assertNoErrorsInCode('''
+void foo<T>(T a) {}
+
+void bar() {
+ foo<int>.call;
+}
+''');
+
+ assertFunctionReference(findNode.functionReference('foo<int>.call;'),
+ findElement.topFunction('foo'), 'void Function(int)');
+ assertSimpleIdentifier(findNode.simple('call;'),
+ element: null, type: 'void Function(int)');
+ }
+
test_topLevelFunction_targetOfFunctionCall() async {
await assertNoErrorsInCode('''
void foo<T>(T arg) {}
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index 8f0efb1..0884b17 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -49,6 +49,7 @@
import 'null_compiler_output.dart' show NullCompilerOutput;
import 'options.dart' show CompilerOptions;
import 'serialization/task.dart';
+import 'serialization/serialization.dart';
import 'serialization/strategies.dart';
import 'ssa/nodes.dart' show HInstruction;
import 'universe/selector.dart' show Selector;
@@ -90,6 +91,7 @@
List<CodeLocation> _userCodeLocations = <CodeLocation>[];
JClosedWorld backendClosedWorldForTesting;
+ DataSourceIndices closedWorldIndicesForTesting;
DiagnosticReporter get reporter => _reporter;
Map<Entity, WorldImpact> get impactCache => _impactCache;
@@ -257,15 +259,18 @@
if (onlyPerformGlobalTypeInference) {
ir.Component component =
await serializationTask.deserializeComponentAndUpdateOptions();
- JsClosedWorld closedWorld =
+ var closedWorldAndIndices =
await serializationTask.deserializeClosedWorld(
environment, abstractValueStrategy, component);
+ if (retainDataForTesting) {
+ closedWorldIndicesForTesting = closedWorldAndIndices.indices;
+ }
GlobalTypeInferenceResults globalTypeInferenceResults =
- performGlobalTypeInference(closedWorld);
+ performGlobalTypeInference(closedWorldAndIndices.closedWorld);
if (options.writeDataUri != null) {
if (options.noClosedWorldInData) {
- serializationTask
- .serializeGlobalTypeInference(globalTypeInferenceResults);
+ serializationTask.serializeGlobalTypeInference(
+ globalTypeInferenceResults, closedWorldAndIndices.indices);
} else {
serializationTask
.serializeGlobalTypeInferenceLegacy(globalTypeInferenceResults);
@@ -277,12 +282,15 @@
GlobalTypeInferenceResults globalTypeInferenceResults;
ir.Component component =
await serializationTask.deserializeComponentAndUpdateOptions();
- JsClosedWorld closedWorld =
+ var closedWorldAndIndices =
await serializationTask.deserializeClosedWorld(
environment, abstractValueStrategy, component);
globalTypeInferenceResults =
await serializationTask.deserializeGlobalTypeInferenceResults(
- environment, abstractValueStrategy, component, closedWorld);
+ environment,
+ abstractValueStrategy,
+ component,
+ closedWorldAndIndices);
await generateJavaScriptCode(globalTypeInferenceResults);
} else if (options.readDataUri != null) {
// TODO(joshualitt) delete and clean up after google3 roll
@@ -480,15 +488,25 @@
List<int> irData = strategy.unpackAndSerializeComponent(results);
List<int> closedWorldData =
strategy.serializeClosedWorld(results.closedWorld);
+ var component = strategy.deserializeComponent(irData);
+ var closedWorldAndIndices = strategy.deserializeClosedWorld(
+ options,
+ reporter,
+ environment,
+ abstractValueStrategy,
+ component,
+ closedWorldData);
List<int> globalTypeInferenceResultsData =
- strategy.serializeGlobalTypeInferenceResults(results);
+ strategy.serializeGlobalTypeInferenceResults(
+ closedWorldAndIndices.indices, results);
return strategy.deserializeGlobalTypeInferenceResults(
options,
reporter,
environment,
abstractValueStrategy,
- strategy.deserializeComponent(irData),
- closedWorldData,
+ component,
+ closedWorldAndIndices.closedWorld,
+ closedWorldAndIndices.indices,
globalTypeInferenceResultsData);
}
@@ -515,8 +533,7 @@
if (options.writeDataUri != null) {
// TODO(joshualitt) delete after google3 roll.
if (options.noClosedWorldInData) {
- serializationTask
- .serializeGlobalTypeInference(globalInferenceResults);
+ throw '"no-closed-world-in-data" requires serializing closed world.';
} else {
serializationTask
.serializeGlobalTypeInferenceLegacy(globalInferenceResults);
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index d4a4746..8cf7074 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -13,6 +13,7 @@
/// This is used for debugging data inconsistencies between serialization
/// and deserialization.
final bool useDataKinds;
+ DataSourceIndices importedIndices;
/// Visitor used for serializing [ir.DartType]s.
DartTypeNodeWriter _dartTypeNodeWriter;
@@ -40,13 +41,23 @@
ir.Member _currentMemberContext;
_MemberData _currentMemberData;
- AbstractDataSink({this.useDataKinds: false, this.tagFrequencyMap}) {
- _dartTypeNodeWriter = new DartTypeNodeWriter(this);
- _stringIndex = new IndexedSink<String>(this);
- _uriIndex = new IndexedSink<Uri>(this);
- _memberNodeIndex = new IndexedSink<ir.Member>(this);
- _importIndex = new IndexedSink<ImportEntity>(this);
- _constantIndex = new IndexedSink<ConstantValue>(this);
+ IndexedSink<T> _createSink<T>() {
+ if (importedIndices == null || !importedIndices.caches.containsKey(T)) {
+ return IndexedSink<T>(this);
+ } else {
+ Map<T, int> cacheCopy = Map.from(importedIndices.caches[T].cache);
+ return IndexedSink<T>(this, cache: cacheCopy);
+ }
+ }
+
+ AbstractDataSink(
+ {this.useDataKinds: false, this.tagFrequencyMap, this.importedIndices}) {
+ _dartTypeNodeWriter = DartTypeNodeWriter(this);
+ _stringIndex = _createSink<String>();
+ _uriIndex = _createSink<Uri>();
+ _memberNodeIndex = _createSink<ir.Member>();
+ _importIndex = _createSink<ImportEntity>();
+ _constantIndex = _createSink<ConstantValue>();
}
@override
@@ -93,7 +104,7 @@
@override
void writeCached<E>(E value, void f(E value)) {
- IndexedSink sink = _generalCaches[E] ??= new IndexedSink<E>(this);
+ IndexedSink sink = _generalCaches[E] ??= _createSink<E>();
sink.write(value, (v) => f(v));
}
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index ed14321..bda940e 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -12,6 +12,7 @@
List<ir.DartType>.filled(0, null, growable: false);
final bool useDataKinds;
+ DataSourceIndices importedIndices;
EntityReader _entityReader = const EntityReader();
ComponentLookup _componentLookup;
EntityLookup _entityLookup;
@@ -29,12 +30,39 @@
ir.Member _currentMemberContext;
_MemberData _currentMemberData;
- AbstractDataSource({this.useDataKinds: false}) {
- _stringIndex = new IndexedSource<String>(this);
- _uriIndex = new IndexedSource<Uri>(this);
- _memberNodeIndex = new IndexedSource<_MemberData>(this);
- _importIndex = new IndexedSource<ImportEntity>(this);
- _constantIndex = new IndexedSource<ConstantValue>(this);
+ IndexedSource<T> _createSource<T>() {
+ if (importedIndices == null || !importedIndices.caches.containsKey(T)) {
+ return IndexedSource<T>(this);
+ } else {
+ List<T> cacheCopy = importedIndices.caches[T].cacheAsList.toList();
+ return IndexedSource<T>(this, cache: cacheCopy);
+ }
+ }
+
+ AbstractDataSource({this.useDataKinds: false, this.importedIndices}) {
+ _stringIndex = _createSource<String>();
+ _uriIndex = _createSource<Uri>();
+ _memberNodeIndex = _createSource<_MemberData>();
+ _importIndex = _createSource<ImportEntity>();
+ _constantIndex = _createSource<ConstantValue>();
+ }
+
+ @override
+ DataSourceIndices exportIndices() {
+ var indices = DataSourceIndices();
+ indices.caches[String] = DataSourceTypeIndices(_stringIndex.cache);
+ indices.caches[Uri] = DataSourceTypeIndices(_uriIndex.cache);
+ indices.caches[ImportEntity] = DataSourceTypeIndices(_importIndex.cache);
+ // _memberNodeIndex needs two entries depending on if the indices will be
+ // consumed by a [DataSource] or [DataSink].
+ indices.caches[_MemberData] = DataSourceTypeIndices(_memberNodeIndex.cache);
+ indices.caches[ir.Member] = DataSourceTypeIndices<ir.Member, _MemberData>(
+ _memberNodeIndex.cache, (_MemberData data) => data?.node);
+ indices.caches[ConstantValue] = DataSourceTypeIndices(_constantIndex.cache);
+ _generalCaches.forEach((type, indexedSource) {
+ indices.caches[type] = DataSourceTypeIndices(indexedSource.cache);
+ });
+ return indices;
}
@override
@@ -119,7 +147,7 @@
@override
E readCached<E>(E f()) {
- IndexedSource source = _generalCaches[E] ??= new IndexedSource<E>(this);
+ IndexedSource source = _generalCaches[E] ??= _createSource<E>();
return source.read(f);
}
diff --git a/pkg/compiler/lib/src/serialization/binary_sink.dart b/pkg/compiler/lib/src/serialization/binary_sink.dart
index 6d46fb4..7394824 100644
--- a/pkg/compiler/lib/src/serialization/binary_sink.dart
+++ b/pkg/compiler/lib/src/serialization/binary_sink.dart
@@ -13,9 +13,14 @@
int _length = 0;
BinarySink(this.sink,
- {bool useDataKinds: false, Map<String, int> tagFrequencyMap})
+ {bool useDataKinds: false,
+ Map<String, int> tagFrequencyMap,
+ DataSourceIndices importedIndices})
: _bufferedSink = new BufferedSink(sink),
- super(useDataKinds: useDataKinds, tagFrequencyMap: tagFrequencyMap);
+ super(
+ useDataKinds: useDataKinds,
+ tagFrequencyMap: tagFrequencyMap,
+ importedIndices: importedIndices);
@override
void _begin(String tag) {
diff --git a/pkg/compiler/lib/src/serialization/binary_source.dart b/pkg/compiler/lib/src/serialization/binary_source.dart
index 92888ad..0bbe4d0 100644
--- a/pkg/compiler/lib/src/serialization/binary_source.dart
+++ b/pkg/compiler/lib/src/serialization/binary_source.dart
@@ -13,9 +13,11 @@
final StringInterner _stringInterner;
BinarySourceImpl(this._bytes,
- {bool useDataKinds: false, StringInterner stringInterner})
+ {bool useDataKinds: false,
+ StringInterner stringInterner,
+ DataSourceIndices importedIndices})
: _stringInterner = stringInterner,
- super(useDataKinds: useDataKinds);
+ super(useDataKinds: useDataKinds, importedIndices: importedIndices);
@override
void _begin(String tag) {}
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index 70a8662..17a3eda 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -264,9 +264,12 @@
/// Data sink helper that canonicalizes [E] values using indices.
class IndexedSink<E> {
final AbstractDataSink _sink;
- final Map<E, int> _cache = {null: 0}; // slot 0 is pre-allocated to `null`.
+ Map<E, int> cache;
- IndexedSink(this._sink);
+ 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.
///
@@ -274,13 +277,13 @@
/// serialize the [value] itself.
void write(E value, void writeValue(E value)) {
const int pending = -1;
- int index = _cache[value];
+ int index = cache[value];
if (index == null) {
- index = _cache.length;
+ index = cache.length;
_sink._writeIntInternal(index);
- _cache[value] = pending; // Increments length to allocate slot.
+ cache[value] = pending; // Increments length to allocate slot.
writeValue(value);
- _cache[value] = index;
+ cache[value] = index;
} else if (index == pending) {
throw ArgumentError("Cyclic dependency on cached value: $value");
} else {
@@ -292,9 +295,12 @@
/// Data source helper reads canonicalized [E] values through indices.
class IndexedSource<E> {
final AbstractDataSource _source;
- final List<E> _cache = [null]; // slot 0 is pre-allocated to `null`.
+ List<E> cache;
- IndexedSource(this._source);
+ IndexedSource(this._source, {this.cache}) {
+ // [cache] slot 0 is pre-allocated to `null`.
+ this.cache ??= [null];
+ }
/// Reads a reference to an [E] value from the data source.
///
@@ -302,14 +308,14 @@
/// the value itself.
E read(E readValue()) {
int index = _source._readIntInternal();
- if (index >= _cache.length) {
- assert(index == _cache.length);
- _cache.add(null); // placeholder.
+ if (index >= cache.length) {
+ assert(index == cache.length);
+ cache.add(null); // placeholder.
E value = readValue();
- _cache[index] = value;
+ cache[index] = value;
return value;
} else {
- E value = _cache[index];
+ E value = cache[index];
if (value == null && index != 0) {
throw StateError('Unfilled index $index of $E');
}
diff --git a/pkg/compiler/lib/src/serialization/object_sink.dart b/pkg/compiler/lib/src/serialization/object_sink.dart
index 82c8885..623e104 100644
--- a/pkg/compiler/lib/src/serialization/object_sink.dart
+++ b/pkg/compiler/lib/src/serialization/object_sink.dart
@@ -11,8 +11,14 @@
class ObjectSink extends AbstractDataSink {
List<dynamic> _data;
- ObjectSink(this._data, {bool useDataKinds, Map<String, int> tagFrequencyMap})
- : super(useDataKinds: useDataKinds, tagFrequencyMap: tagFrequencyMap);
+ ObjectSink(this._data,
+ {bool useDataKinds,
+ Map<String, int> tagFrequencyMap,
+ DataSourceIndices importedIndices})
+ : super(
+ useDataKinds: useDataKinds,
+ tagFrequencyMap: tagFrequencyMap,
+ importedIndices: importedIndices);
@override
void _begin(String tag) {
diff --git a/pkg/compiler/lib/src/serialization/object_source.dart b/pkg/compiler/lib/src/serialization/object_source.dart
index 54207a2..2d61f96 100644
--- a/pkg/compiler/lib/src/serialization/object_source.dart
+++ b/pkg/compiler/lib/src/serialization/object_source.dart
@@ -12,8 +12,9 @@
int _index = 0;
final List<dynamic> _data;
- ObjectSource(this._data, {bool useDataKinds})
- : super(useDataKinds: useDataKinds);
+ ObjectSource(this._data,
+ {bool useDataKinds, DataSourceIndices importedIndices})
+ : super(useDataKinds: useDataKinds, importedIndices: importedIndices);
T _read<T>() {
dynamic value = _data[_index++];
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 8e2cf4d..051be85 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -460,8 +460,50 @@
void inMemberContext(ir.Member member, void f());
}
+/// Data class representing cache information for a given [T] which can be
+/// passed from a [DataSource] to other [DataSource]s and [DataSink]s.
+class DataSourceTypeIndices<E, T> {
+ /// Reshapes a [List<T>] to a [Map<E, int>] using [_getValue].
+ Map<E, int> _reshape() {
+ var cache = <E, int>{};
+ for (int i = 0; i < cacheAsList.length; i++) {
+ cache[_getValue(cacheAsList[i])] = i;
+ }
+ return cache;
+ }
+
+ Map<E, int> get cache {
+ return _cache ??= _reshape();
+ }
+
+ final List<T> cacheAsList;
+ E Function(T value) _getValue;
+ Map<E, int> _cache;
+
+ /// Though [DataSourceTypeIndices] supports two types of caches. If the
+ /// exported indices are imported into a [DataSource] then the [cacheAsList]
+ /// will be used as is. If, however, the exported indices are imported into a
+ /// [DataSink] then we need to reshape the [List<T>] into a [Map<E, int>]
+ /// where [E] is either [T] or some value which can be derived from [T] by
+ /// [_getValue].
+ DataSourceTypeIndices(this.cacheAsList, [this._getValue]) {
+ assert(_getValue != null || T == E);
+ _getValue ??= (T t) => t as E;
+ }
+}
+
+/// Data class representing the sum of all cache information for a given
+/// [DataSource].
+class DataSourceIndices {
+ final Map<Type, DataSourceTypeIndices> caches = {};
+}
+
/// Interface for deserialization.
abstract class DataSource {
+ /// Exports [DataSourceIndices] for use in other [DataSource]s and
+ /// [DataSink]s.
+ DataSourceIndices exportIndices();
+
/// Registers that the section [tag] starts.
///
/// This is used for debugging to verify that sections are correctly aligned
diff --git a/pkg/compiler/lib/src/serialization/strategies.dart b/pkg/compiler/lib/src/serialization/strategies.dart
index 9269eed..909e909 100644
--- a/pkg/compiler/lib/src/serialization/strategies.dart
+++ b/pkg/compiler/lib/src/serialization/strategies.dart
@@ -31,7 +31,7 @@
}
List<T> serializeGlobalTypeInferenceResults(
- GlobalTypeInferenceResults results);
+ DataSourceIndices indices, GlobalTypeInferenceResults results);
List<int> serializeComponent(ir.Component component) {
return ir.serializeComponent(component);
@@ -49,12 +49,13 @@
Environment environment,
AbstractValueStrategy abstractValueStrategy,
ir.Component component,
- List<T> closedWorldData,
+ JsClosedWorld closedWorld,
+ DataSourceIndices indices,
List<T> globalTypeInferenceResultsData);
List<T> serializeClosedWorld(JsClosedWorld closedWorld);
- JsClosedWorld deserializeClosedWorld(
+ ClosedWorldAndIndices deserializeClosedWorld(
CompilerOptions options,
DiagnosticReporter reporter,
Environment environment,
@@ -70,9 +71,10 @@
@override
List<int> serializeGlobalTypeInferenceResults(
- GlobalTypeInferenceResults results) {
+ DataSourceIndices indices, GlobalTypeInferenceResults results) {
ByteSink byteSink = new ByteSink();
- DataSink sink = new BinarySink(byteSink, useDataKinds: useDataKinds);
+ DataSink sink = new BinarySink(byteSink,
+ useDataKinds: useDataKinds, importedIndices: indices);
serializeGlobalTypeInferenceResultsToSink(results, sink);
return byteSink.builder.takeBytes();
}
@@ -84,20 +86,13 @@
Environment environment,
AbstractValueStrategy abstractValueStrategy,
ir.Component component,
- List<int> closedWorldData,
+ JsClosedWorld closedWorld,
+ DataSourceIndices indices,
List<int> globalTypeInferenceResultsData) {
- DataSource closedWorldSource =
- BinarySourceImpl(closedWorldData, useDataKinds: useDataKinds);
DataSource globalTypeInferenceResultsSource = BinarySourceImpl(
globalTypeInferenceResultsData,
- useDataKinds: useDataKinds);
- JsClosedWorld closedWorld = deserializeClosedWorldFromSource(
- options,
- reporter,
- environment,
- abstractValueStrategy,
- component,
- closedWorldSource);
+ useDataKinds: useDataKinds,
+ importedIndices: indices);
return deserializeGlobalTypeInferenceResultsFromSource(
options,
reporter,
@@ -117,7 +112,7 @@
}
@override
- JsClosedWorld deserializeClosedWorld(
+ ClosedWorldAndIndices deserializeClosedWorld(
CompilerOptions options,
DiagnosticReporter reporter,
Environment environment,
@@ -125,8 +120,9 @@
ir.Component component,
List<int> data) {
DataSource source = new BinarySourceImpl(data, useDataKinds: useDataKinds);
- return deserializeClosedWorldFromSource(options, reporter, environment,
- abstractValueStrategy, component, source);
+ var closedWorld = deserializeClosedWorldFromSource(options, reporter,
+ environment, abstractValueStrategy, component, source);
+ return ClosedWorldAndIndices(closedWorld, source.exportIndices());
}
}
@@ -137,11 +133,12 @@
@override
List<int> serializeGlobalTypeInferenceResults(
- GlobalTypeInferenceResults results) {
+ DataSourceIndices indices, GlobalTypeInferenceResults results) {
Uri uri = Uri.base.resolve('world.data');
DataSink sink = new BinarySink(
new BinaryOutputSinkAdapter(new RandomAccessBinaryOutputSink(uri)),
- useDataKinds: useDataKinds);
+ useDataKinds: useDataKinds,
+ importedIndices: indices);
serializeGlobalTypeInferenceResultsToSink(results, sink);
return new File.fromUri(uri).readAsBytesSync();
}
@@ -153,20 +150,13 @@
Environment environment,
AbstractValueStrategy abstractValueStrategy,
ir.Component component,
- List<int> closedWorldData,
+ JsClosedWorld closedWorld,
+ DataSourceIndices indices,
List<int> globalTypeInferenceResultsData) {
- DataSource closedWorldSource =
- BinarySourceImpl(closedWorldData, useDataKinds: useDataKinds);
DataSource globalTypeInferenceResultsSource = BinarySourceImpl(
globalTypeInferenceResultsData,
- useDataKinds: useDataKinds);
- JsClosedWorld closedWorld = deserializeClosedWorldFromSource(
- options,
- reporter,
- environment,
- abstractValueStrategy,
- component,
- closedWorldSource);
+ useDataKinds: useDataKinds,
+ importedIndices: indices);
return deserializeGlobalTypeInferenceResultsFromSource(
options,
reporter,
@@ -188,7 +178,7 @@
}
@override
- JsClosedWorld deserializeClosedWorld(
+ ClosedWorldAndIndices deserializeClosedWorld(
CompilerOptions options,
DiagnosticReporter reporter,
Environment environment,
@@ -196,8 +186,9 @@
ir.Component component,
List<int> data) {
DataSource source = new BinarySourceImpl(data, useDataKinds: useDataKinds);
- return deserializeClosedWorldFromSource(options, reporter, environment,
- abstractValueStrategy, component, source);
+ var closedWorld = deserializeClosedWorldFromSource(options, reporter,
+ environment, abstractValueStrategy, component, source);
+ return ClosedWorldAndIndices(closedWorld, source.exportIndices());
}
}
@@ -209,9 +200,10 @@
@override
List<Object> serializeGlobalTypeInferenceResults(
- GlobalTypeInferenceResults results) {
+ DataSourceIndices indices, GlobalTypeInferenceResults results) {
List<Object> data = [];
- DataSink sink = new ObjectSink(data, useDataKinds: useDataKinds);
+ DataSink sink = new ObjectSink(data,
+ useDataKinds: useDataKinds, importedIndices: indices);
serializeGlobalTypeInferenceResultsToSink(results, sink);
return data;
}
@@ -223,20 +215,13 @@
Environment environment,
AbstractValueStrategy abstractValueStrategy,
ir.Component component,
- List<Object> closedWorldData,
+ JsClosedWorld closedWorld,
+ DataSourceIndices indices,
List<Object> globalTypeInferenceResultsData) {
- DataSource closedWorldSource =
- ObjectSource(closedWorldData, useDataKinds: useDataKinds);
DataSource globalTypeInferenceResultsSource = ObjectSource(
globalTypeInferenceResultsData,
- useDataKinds: useDataKinds);
- JsClosedWorld closedWorld = deserializeClosedWorldFromSource(
- options,
- reporter,
- environment,
- abstractValueStrategy,
- component,
- closedWorldSource);
+ useDataKinds: useDataKinds,
+ importedIndices: indices);
return deserializeGlobalTypeInferenceResultsFromSource(
options,
reporter,
@@ -256,7 +241,7 @@
}
@override
- JsClosedWorld deserializeClosedWorld(
+ ClosedWorldAndIndices deserializeClosedWorld(
CompilerOptions options,
DiagnosticReporter reporter,
Environment environment,
@@ -264,7 +249,8 @@
ir.Component component,
List<Object> data) {
DataSource source = new ObjectSource(data, useDataKinds: useDataKinds);
- return deserializeClosedWorldFromSource(options, reporter, environment,
- abstractValueStrategy, component, source);
+ var closedWorld = deserializeClosedWorldFromSource(options, reporter,
+ environment, abstractValueStrategy, component, source);
+ return ClosedWorldAndIndices(closedWorld, source.exportIndices());
}
}
diff --git a/pkg/compiler/lib/src/serialization/task.dart b/pkg/compiler/lib/src/serialization/task.dart
index 72bd9b1..479a2aa 100644
--- a/pkg/compiler/lib/src/serialization/task.dart
+++ b/pkg/compiler/lib/src/serialization/task.dart
@@ -28,6 +28,15 @@
import '../world.dart';
import 'serialization.dart';
+/// A data class holding a [JsClosedWorld] and the associated
+/// [DataSourceIndices].
+class ClosedWorldAndIndices {
+ final JsClosedWorld closedWorld;
+ final DataSourceIndices indices;
+
+ ClosedWorldAndIndices(this.closedWorld, this.indices);
+}
+
void serializeGlobalTypeInferenceResultsToSink(
GlobalTypeInferenceResults results, DataSink sink) {
JsClosedWorld closedWorld = results.closedWorld;
@@ -255,7 +264,7 @@
});
}
- Future<JsClosedWorld> deserializeClosedWorld(
+ Future<ClosedWorldAndIndices> deserializeClosedWorld(
Environment environment,
AbstractValueStrategy abstractValueStrategy,
ir.Component component) async {
@@ -266,12 +275,14 @@
inputKind: api.InputKind.binary);
DataSource source =
BinarySourceImpl(dataInput.data, stringInterner: _stringInterner);
- return deserializeClosedWorldFromSource(_options, _reporter, environment,
- abstractValueStrategy, component, source);
+ var closedWorld = deserializeClosedWorldFromSource(_options, _reporter,
+ environment, abstractValueStrategy, component, source);
+ return ClosedWorldAndIndices(closedWorld, source.exportIndices());
});
}
- void serializeGlobalTypeInference(GlobalTypeInferenceResults results) {
+ void serializeGlobalTypeInference(
+ GlobalTypeInferenceResults results, DataSourceIndices indices) {
JsClosedWorld closedWorld = results.closedWorld;
ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
serializeComponent(component);
@@ -280,7 +291,8 @@
_reporter.log('Writing data to ${_options.writeDataUri}');
api.BinaryOutputSink dataOutput =
_outputProvider.createBinarySink(_options.writeDataUri);
- DataSink sink = new BinarySink(new BinaryOutputSinkAdapter(dataOutput));
+ DataSink sink = BinarySink(BinaryOutputSinkAdapter(dataOutput),
+ importedIndices: indices);
serializeGlobalTypeInferenceResultsToSink(results, sink);
});
}
@@ -289,20 +301,21 @@
Environment environment,
AbstractValueStrategy abstractValueStrategy,
ir.Component component,
- JsClosedWorld closedWorld) async {
+ ClosedWorldAndIndices closedWorldAndIndices) async {
return await measureIoSubtask('deserialize data', () async {
_reporter.log('Reading data from ${_options.readDataUri}');
api.Input<List<int>> dataInput = await _provider
.readFromUri(_options.readDataUri, inputKind: api.InputKind.binary);
- DataSource source =
- BinarySourceImpl(dataInput.data, stringInterner: _stringInterner);
+ DataSource source = BinarySourceImpl(dataInput.data,
+ stringInterner: _stringInterner,
+ importedIndices: closedWorldAndIndices.indices);
return deserializeGlobalTypeInferenceResultsFromSource(
_options,
_reporter,
environment,
abstractValueStrategy,
component,
- closedWorld,
+ closedWorldAndIndices.closedWorld,
source);
});
}
@@ -338,6 +351,8 @@
});
}
+ // TODO(joshualitt): Investigate whether closed world indices can be shared
+ // with codegen.
void serializeCodegen(
BackendStrategy backendStrategy, CodegenResults codegenResults) {
GlobalTypeInferenceResults globalTypeInferenceResults =
diff --git a/pkg/compiler/test/serialization/serialization_test.dart b/pkg/compiler/test/serialization/serialization_test.dart
index 139dde5..3b052f5 100644
--- a/pkg/compiler/test/serialization/serialization_test.dart
+++ b/pkg/compiler/test/serialization/serialization_test.dart
@@ -52,7 +52,6 @@
testCount++;
List<String> testOptions = options.toList();
testOptions.add(Flags.dumpInfo);
- testOptions.add('--out=out.js');
if (onTest != null) {
onTest(entity.uri);
}
diff --git a/pkg/compiler/test/serialization/serialization_test_helper.dart b/pkg/compiler/test/serialization/serialization_test_helper.dart
index b7b771c..2507434 100644
--- a/pkg/compiler/test/serialization/serialization_test_helper.dart
+++ b/pkg/compiler/test/serialization/serialization_test_helper.dart
@@ -4,11 +4,16 @@
// @dart = 2.7
+import 'dart:io';
+
import 'package:compiler/compiler_new.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/js_model/js_world.dart';
import 'package:compiler/src/inferrer/types.dart';
+import 'package:compiler/src/serialization/serialization.dart';
import 'package:compiler/src/serialization/strategies.dart';
+import 'package:compiler/src/serialization/task.dart';
import 'package:expect/expect.dart';
import 'package:kernel/ast.dart' as ir;
import '../helpers/memory_compiler.dart';
@@ -30,16 +35,18 @@
bool stoppedAfterTypeInference = false}) {
if (stoppedAfterClosedWorld) {
JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
- JsClosedWorld newClosedWorld =
+ var newClosedWorldAndIndices =
cloneClosedWorld(compiler, closedWorld, strategy);
- compiler.performGlobalTypeInference(newClosedWorld);
+ compiler.performGlobalTypeInference(newClosedWorldAndIndices.closedWorld);
}
if (stoppedAfterClosedWorld || stoppedAfterTypeInference) {
GlobalTypeInferenceResults globalInferenceResults =
compiler.globalInference.resultsForTesting;
+ var indices = compiler.closedWorldIndicesForTesting;
GlobalTypeInferenceResults newGlobalInferenceResults =
- cloneInferenceResults(compiler, globalInferenceResults, strategy);
+ cloneInferenceResults(
+ indices, compiler, globalInferenceResults, strategy);
compiler.generateJavaScriptCode(newGlobalInferenceResults);
}
var actualOutput = actualOutputCollector.clear();
@@ -88,13 +95,14 @@
List<String> options,
SerializationStrategy strategy: const BytesInMemorySerializationStrategy(),
bool useDataKinds: false}) async {
+ var commonOptions = options + ['--out=out.js'];
OutputCollector collector = new OutputCollector();
CompilationResult result = await runCompiler(
entryPoint: entryPoint,
memorySourceFiles: memorySourceFiles,
packageConfig: packageConfig,
librariesSpecificationUri: librariesSpecificationUri,
- options: options,
+ options: commonOptions,
outputProvider: collector,
beforeRun: (Compiler compiler) {
compiler.kernelLoader.forceSerialization = true;
@@ -108,7 +116,7 @@
memorySourceFiles: memorySourceFiles,
packageConfig: packageConfig,
librariesSpecificationUri: librariesSpecificationUri,
- options: options,
+ options: commonOptions,
outputProvider: collector2,
beforeRun: (Compiler compiler) {
compiler.kernelLoader.forceSerialization = true;
@@ -116,26 +124,57 @@
});
Expect.isTrue(result2.isSuccess);
- OutputCollector collector3 = new OutputCollector();
- CompilationResult result3 = await runCompiler(
+ var dillUri = Uri.parse('out.dill');
+ var closedWorldUri = Uri.parse('world.data');
+ OutputCollector collector3a = new OutputCollector();
+ CompilationResult result3a = await runCompiler(
entryPoint: entryPoint,
memorySourceFiles: memorySourceFiles,
packageConfig: packageConfig,
librariesSpecificationUri: librariesSpecificationUri,
- options: options,
- outputProvider: collector3,
+ options: options +
+ ['--out=$dillUri', '${Flags.writeClosedWorld}=$closedWorldUri'],
+ outputProvider: collector3a,
+ beforeRun: (Compiler compiler) {
+ compiler.kernelLoader.forceSerialization = true;
+ });
+ Expect.isTrue(result3a.isSuccess);
+ Expect.isTrue(collector3a.binaryOutputMap.containsKey(dillUri));
+ Expect.isTrue(collector3a.binaryOutputMap.containsKey(closedWorldUri));
+
+ Directory dir =
+ await Directory.systemTemp.createTemp('serialization_test_helper');
+ var dillFileUri = dir.uri.resolve('out.dill');
+ var closedWorldFileUri = dir.uri.resolve('world.data');
+ var dillBytes = collector3a.binaryOutputMap[dillUri].list;
+ var closedWorldBytes = collector3a.binaryOutputMap[closedWorldUri].list;
+ File(dillFileUri.path).writeAsBytesSync(dillBytes);
+ File(closedWorldFileUri.path).writeAsBytesSync(closedWorldBytes);
+ OutputCollector collector3b = new OutputCollector();
+ CompilationResult result3b = await runCompiler(
+ entryPoint: dillFileUri,
+ memorySourceFiles: memorySourceFiles,
+ packageConfig: packageConfig,
+ librariesSpecificationUri: librariesSpecificationUri,
+ options: commonOptions +
+ [
+ '${Flags.readClosedWorld}=$closedWorldFileUri',
+ '${Flags.writeData}=global.data'
+ ],
+ outputProvider: collector3b,
beforeRun: (Compiler compiler) {
compiler.kernelLoader.forceSerialization = true;
compiler.stopAfterTypeInference = true;
});
- Expect.isTrue(result3.isSuccess);
+ Expect.isTrue(result3b.isSuccess);
finishCompileAndCompare(
expectedOutput, collector2, result2.compiler, strategy,
stoppedAfterClosedWorld: true);
finishCompileAndCompare(
- expectedOutput, collector3, result3.compiler, strategy,
+ expectedOutput, collector3b, result3b.compiler, strategy,
stoppedAfterTypeInference: true);
+ await dir.delete(recursive: true);
}
void checkData(List<int> data, List<int> newData) {
@@ -161,35 +200,48 @@
Expect.listEquals(data, newData);
}
-JsClosedWorld cloneClosedWorld(Compiler compiler, JsClosedWorld closedWorld,
- SerializationStrategy strategy) {
+ClosedWorldAndIndices cloneClosedWorld(Compiler compiler,
+ JsClosedWorld closedWorld, SerializationStrategy strategy) {
ir.Component component = closedWorld.elementMap.programEnv.mainComponent;
List<int> irData = strategy.serializeComponent(component);
List<int> closedWorldData = strategy.serializeClosedWorld(closedWorld);
print('data size: ${closedWorldData.length}');
ir.Component newComponent = strategy.deserializeComponent(irData);
- JsClosedWorld newClosedWorld = strategy.deserializeClosedWorld(
+ var newClosedWorldAndIndices = strategy.deserializeClosedWorld(
compiler.options,
compiler.reporter,
compiler.environment,
compiler.abstractValueStrategy,
newComponent,
closedWorldData);
- List<int> newClosedWorldData = strategy.serializeClosedWorld(newClosedWorld);
+ List<int> newClosedWorldData =
+ strategy.serializeClosedWorld(newClosedWorldAndIndices.closedWorld);
checkData(closedWorldData, newClosedWorldData);
- return newClosedWorld;
+ return newClosedWorldAndIndices;
}
-GlobalTypeInferenceResults cloneInferenceResults(Compiler compiler,
- GlobalTypeInferenceResults results, SerializationStrategy strategy) {
+GlobalTypeInferenceResults cloneInferenceResults(
+ DataSourceIndices indices,
+ Compiler compiler,
+ GlobalTypeInferenceResults results,
+ SerializationStrategy strategy) {
List<int> irData = strategy.unpackAndSerializeComponent(results);
List<int> closedWorldData =
strategy.serializeClosedWorld(results.closedWorld);
- List<int> worldData = strategy.serializeGlobalTypeInferenceResults(results);
+ List<int> worldData =
+ strategy.serializeGlobalTypeInferenceResults(indices, results);
print('data size: ${worldData.length}');
ir.Component newComponent = strategy.deserializeComponent(irData);
+ var newClosedWorldAndIndices = strategy.deserializeClosedWorld(
+ compiler.options,
+ compiler.reporter,
+ compiler.environment,
+ compiler.abstractValueStrategy,
+ newComponent,
+ closedWorldData);
+ var newIndices = indices == null ? null : newClosedWorldAndIndices.indices;
GlobalTypeInferenceResults newResults =
strategy.deserializeGlobalTypeInferenceResults(
compiler.options,
@@ -197,10 +249,11 @@
compiler.environment,
compiler.abstractValueStrategy,
newComponent,
- closedWorldData,
+ newClosedWorldAndIndices.closedWorld,
+ newIndices,
worldData);
List<int> newWorldData =
- strategy.serializeGlobalTypeInferenceResults(newResults);
+ strategy.serializeGlobalTypeInferenceResults(newIndices, newResults);
checkData(worldData, newWorldData);
return newResults;
}
diff --git a/pkg/compiler/tool/kernel_visitor/dart_html_metrics_visitor.dart b/pkg/compiler/tool/kernel_visitor/dart_html_metrics_visitor.dart
index 13cc373..79b8b41 100644
--- a/pkg/compiler/tool/kernel_visitor/dart_html_metrics_visitor.dart
+++ b/pkg/compiler/tool/kernel_visitor/dart_html_metrics_visitor.dart
@@ -4,7 +4,6 @@
import "dart:convert";
import "dart:io";
import "package:kernel/kernel.dart";
-import "package:kernel/ast.dart";
main(List<String> args) async {
// Ensure right args are passed.
diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart
index 22e9e1a..ace7285 100644
--- a/pkg/dartdev/lib/src/commands/run.dart
+++ b/pkg/dartdev/lib/src/commands/run.dart
@@ -165,6 +165,12 @@
negatable: false,
help: 'Enables tracing of library and script loading.',
)
+ ..addFlag('dds',
+ hide: !verbose,
+ help: 'Use the Dart Development Service (DDS) for enhanced debugging '
+ 'functionality. Note: Disabling DDS may break some functionality '
+ 'in IDEs and other tooling.',
+ defaultsTo: true)
..addFlag(
'debug-dds',
hide: true,
diff --git a/pkg/dartdev/test/commands/run_test.dart b/pkg/dartdev/test/commands/run_test.dart
index 45eb00c..613a508 100644
--- a/pkg/dartdev/test/commands/run_test.dart
+++ b/pkg/dartdev/test/commands/run_test.dart
@@ -12,6 +12,9 @@
import '../utils.dart';
const String soundNullSafetyMessage = 'Info: Compiling with sound null safety';
+const devToolsMessagePrefix =
+ 'The Dart DevTools debugger and profiler is available at: http://127.0.0.1:';
+const observatoryMessagePrefix = 'Observatory listening on http://127.0.0.1:';
void main() {
group('run', run, timeout: longTimeout);
@@ -347,10 +350,59 @@
expect(result.exitCode, 0);
});
- group('DevTools', () {
- const devToolsMessagePrefix =
- 'The Dart DevTools debugger and profiler is available at: http://127.0.0.1:';
+ group('DDS', () {
+ group('disable', () {
+ test('dart run simple', () {
+ p = project(mainSrc: "void main() { print('Hello World'); }");
+ ProcessResult result = p.runSync([
+ 'run',
+ '--no-dds',
+ '--enable-vm-service',
+ p.relativeFilePath,
+ ]);
+ expect(result.stdout, isNot(contains(devToolsMessagePrefix)));
+ expect(result.stdout, contains(observatoryMessagePrefix));
+ });
+ test('dart simple', () {
+ p = project(mainSrc: "void main() { print('Hello World'); }");
+ ProcessResult result = p.runSync([
+ '--no-dds',
+ '--enable-vm-service',
+ p.relativeFilePath,
+ ]);
+ expect(result.stdout, isNot(contains(devToolsMessagePrefix)));
+ expect(result.stdout, contains(observatoryMessagePrefix));
+ });
+ });
+
+ group('explicit enable', () {
+ test('dart run simple', () {
+ p = project(mainSrc: "void main() { print('Hello World'); }");
+ ProcessResult result = p.runSync([
+ 'run',
+ '--dds',
+ '--enable-vm-service',
+ p.relativeFilePath,
+ ]);
+ expect(result.stdout, contains(devToolsMessagePrefix));
+ expect(result.stdout, contains(observatoryMessagePrefix));
+ });
+
+ test('dart simple', () {
+ p = project(mainSrc: "void main() { print('Hello World'); }");
+ ProcessResult result = p.runSync([
+ '--dds',
+ '--enable-vm-service',
+ p.relativeFilePath,
+ ]);
+ expect(result.stdout, contains(devToolsMessagePrefix));
+ expect(result.stdout, contains(observatoryMessagePrefix));
+ });
+ });
+ });
+
+ group('DevTools', () {
test('dart run simple', () async {
p = project(mainSrc: "void main() { print('Hello World'); }");
ProcessResult result = p.runSync([
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index d3ca835..64f1715 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -538,7 +538,7 @@
CHECK_RESULT(result);
int vm_service_server_port = INVALID_VM_SERVICE_SERVER_PORT;
- if (Options::disable_dart_dev()) {
+ if (Options::disable_dart_dev() || Options::disable_dds()) {
vm_service_server_port = Options::vm_service_server_port();
} else if (Options::vm_service_server_port() !=
INVALID_VM_SERVICE_SERVER_PORT) {
@@ -549,12 +549,14 @@
// the following scenarios:
// - The DartDev CLI is disabled (CLI isolate starts DDS) and VM service is
// enabled.
+ // - DDS is disabled.
// TODO(bkonyi): do we want to tie DevTools / DDS to the CLI in the long run?
- bool wait_for_dds_to_advertise_service = !Options::disable_dart_dev();
+ bool wait_for_dds_to_advertise_service =
+ !(Options::disable_dart_dev() || Options::disable_dds());
// Load embedder specific bits and return.
if (!VmService::Setup(
- Options::disable_dart_dev() ? Options::vm_service_server_ip()
- : DEFAULT_VM_SERVICE_SERVER_IP,
+ !wait_for_dds_to_advertise_service ? Options::vm_service_server_ip()
+ : DEFAULT_VM_SERVICE_SERVER_IP,
vm_service_server_port, Options::vm_service_dev_mode(),
Options::vm_service_auth_disabled(),
Options::vm_write_service_info_filename(), Options::trace_loading(),
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 44386ec..e213e70 100644
--- a/runtime/bin/main_options.cc
+++ b/runtime/bin/main_options.cc
@@ -454,6 +454,11 @@
} else if (IsOption(argv[i], "no-serve-devtools")) {
serve_devtools = false;
skipVmOption = true;
+ } else if (IsOption(argv[i], "dds")) {
+ // This flag is set by default in dartdev, so we ignore it. --no-dds is
+ // a VM flag as disabling DDS changes how we configure the VM service,
+ // so we don't need to handle that case here.
+ skipVmOption = true;
}
if (!skipVmOption) {
temp_vm_options.AddArgument(argv[i]);
@@ -623,7 +628,8 @@
if (!run_command && strcmp(argv[i - 1], "run") == 0) {
run_command = true;
}
- if (!Options::disable_dart_dev() && enable_vm_service_ && run_command) {
+ if (!Options::disable_dart_dev() && !Options::disable_dds() &&
+ enable_vm_service_ && run_command) {
const char* dds_format_str = "--launch-dds=%s\\:%d";
size_t size =
snprintf(nullptr, 0, dds_format_str, vm_service_server_ip(),
diff --git a/runtime/bin/main_options.h b/runtime/bin/main_options.h
index 66e6fde..e1daacf 100644
--- a/runtime/bin/main_options.h
+++ b/runtime/bin/main_options.h
@@ -44,6 +44,7 @@
V(suppress_core_dump, suppress_core_dump) \
V(enable_service_port_fallback, enable_service_port_fallback) \
V(disable_dart_dev, disable_dart_dev) \
+ V(no_dds, disable_dds) \
V(long_ssl_cert_evaluation, long_ssl_cert_evaluation) \
V(bypass_trusting_system_roots, bypass_trusting_system_roots) \
V(delayed_filewatch_callback, delayed_filewatch_callback) \
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index f478245..38ee528 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -68,11 +68,13 @@
dart/regress_40753_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
dart/trigger_gc_in_native_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
dart/use_strip_flag_test: Pass, Slow # This test can take a longer time to complete.
+dart/v8_snapshot_profile_writer_test: SkipSlow
dart_2/appjit_cha_deopt_test: SkipSlow
dart_2/regress_40462_test: SkipSlow
dart_2/regress_40753_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
dart_2/trigger_gc_in_native_test: Skip # This test crashes on the bot, but not locally, and infrastructure repeatly fails to locate its coredump.
dart_2/use_strip_flag_test: Pass, Slow # This test can take a longer time to complete.
+dart_2/v8_snapshot_profile_writer_test: SkipSlow
[ $compiler == app_jitk ]
dart/snapshot_version_test: RuntimeError
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index e62c225..76a9ecd 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -136,7 +136,13 @@
return addr;
}
- old_space_.TryReleaseReservation();
+ if (old_space_.GrowthControlState()) {
+ WaitForSweeperTasks(Thread::Current());
+ old_space_.TryReleaseReservation();
+ } else {
+ // We may or may not be a safepoint, so we don't know how to wait for the
+ // sweeper.
+ }
// Give up allocating this object.
OS::PrintErr("Exhausted heap space, trying to allocate %" Pd " bytes.\n",
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index 0cda99e..0c8a740 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -1037,6 +1037,8 @@
}
void PageSpace::TryReleaseReservation() {
+ ASSERT(phase() != kSweepingLarge);
+ ASSERT(phase() != kSweepingRegular);
if (oom_reservation_ == nullptr) return;
uword addr = reinterpret_cast<uword>(oom_reservation_);
intptr_t size = oom_reservation_->HeapSize();
diff --git a/runtime/vm/longjump.cc b/runtime/vm/longjump.cc
index c778dc7..e789ecf 100644
--- a/runtime/vm/longjump.cc
+++ b/runtime/vm/longjump.cc
@@ -36,13 +36,6 @@
Thread* thread = Thread::Current();
DEBUG_ASSERT(thread->TopErrorHandlerIsSetJump());
-#if defined(DEBUG)
-#define CHECK_REUSABLE_HANDLE(name) \
- ASSERT(!thread->reusable_##name##_handle_scope_active());
- REUSABLE_HANDLE_LIST(CHECK_REUSABLE_HANDLE)
-#undef CHECK_REUSABLE_HANDLE
-#endif // defined(DEBUG)
-
// Destruct all the active StackResource objects.
StackResource::UnwindAbove(thread, top_);
longjmp(environment_, value);
diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc
index 2853b37..45642c8 100644
--- a/runtime/vm/object_graph_copy.cc
+++ b/runtime/vm/object_graph_copy.cc
@@ -1795,9 +1795,13 @@
const intptr_t cid = UntaggedObject::ClassIdTag::decode(tags);
// External typed data is already initialized.
if (!IsExternalTypedDataClassId(cid) && !IsTypedDataViewClassId(cid)) {
+#if defined(DART_COMPRESSED_POINTERS)
+ const bool compressed = true;
+#else
+ const bool compressed = false;
+#endif
Object::InitializeObject(reinterpret_cast<uword>(to.untag()), cid,
- from.untag()->HeapSize(),
- /*compressed=*/cid != kContextCid);
+ from.untag()->HeapSize(), compressed);
UpdateLengthField(cid, from, to);
}
}
diff --git a/runtime/vm/reusable_handles.h b/runtime/vm/reusable_handles.h
index e2ac116..5fcb2f7 100644
--- a/runtime/vm/reusable_handles.h
+++ b/runtime/vm/reusable_handles.h
@@ -32,16 +32,13 @@
#if defined(DEBUG)
#define REUSABLE_SCOPE(name) \
- class Reusable##name##HandleScope : public ValueObject { \
+ class Reusable##name##HandleScope : public StackResource { \
public: \
- explicit Reusable##name##HandleScope(Thread* thread) : thread_(thread) { \
+ explicit Reusable##name##HandleScope(Thread* thread = Thread::Current()) \
+ : StackResource(thread), thread_(thread) { \
ASSERT(!thread->reusable_##name##_handle_scope_active()); \
thread->set_reusable_##name##_handle_scope_active(true); \
} \
- Reusable##name##HandleScope() : thread_(Thread::Current()) { \
- ASSERT(!thread_->reusable_##name##_handle_scope_active()); \
- thread_->set_reusable_##name##_handle_scope_active(true); \
- } \
~Reusable##name##HandleScope() { \
ASSERT(thread_->reusable_##name##_handle_scope_active()); \
thread_->set_reusable_##name##_handle_scope_active(false); \
@@ -60,10 +57,8 @@
#define REUSABLE_SCOPE(name) \
class Reusable##name##HandleScope : public ValueObject { \
public: \
- explicit Reusable##name##HandleScope(Thread* thread) \
+ explicit Reusable##name##HandleScope(Thread* thread = Thread::Current()) \
: handle_(thread->name##_handle_) {} \
- Reusable##name##HandleScope() \
- : handle_(Thread::Current()->name##_handle_) {} \
~Reusable##name##HandleScope() { handle_->ptr_ = name::null(); } \
name& Handle() const { \
ASSERT(handle_ != NULL); \
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index 971e2ce..d3b0fe3 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -24,6 +24,8 @@
LibTest/async/Stream/Stream.periodic_all_t02: Skip # Issue 42898
[ $arch == simarm || $arch == simarm64 || $arch == simarm64c ]
+Language/Libraries_and_Scripts/Scripts/top_level_main_t01: SkipSlow # Very slow on sim* architectures.
+Language/Libraries_and_Scripts/Scripts/top_level_main_t06: SkipSlow # Very slow on sim* architectures.
LibTest/collection/ListBase/ListBase_class_A01_t01: SkipSlow # Very slow on sim* architectures.
LibTest/collection/ListBase/ListBase_class_A01_t04: SkipSlow # Very slow on sim* architectures.
LibTest/collection/ListBase/ListBase_class_A01_t05: SkipSlow # Very slow on sim* architectures.
diff --git a/tools/VERSION b/tools/VERSION
index 90c741d..cff4e45 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 15
PATCH 0
-PRERELEASE 117
+PRERELEASE 118
PRERELEASE_PATCH 0
\ No newline at end of file