Version 2.19.0-37.0.dev
Merge commit 'a8be1c1e0b3452c0135c21c771c7d7f73ca45ec7' into 'dev'
diff --git a/DEPS b/DEPS
index e2150e6..73a6042 100644
--- a/DEPS
+++ b/DEPS
@@ -81,7 +81,7 @@
"args_rev": "73e8d3b55cbedc9765f8e266f3422d8914f8e62a",
"async_rev": "f3ed5f690e2ec9dbe1bfc5184705575b4f6480e5",
"bazel_worker_rev": "9710de6c9c70b1b583183db9d9721ba64e5a16fe",
- "benchmark_harness_rev": "4183c76739ed7a27c260ca9ebaab6e0f210d1a37",
+ "benchmark_harness_rev": "6a116758f2b96e92659194bcda990f42106a01d3",
"boolean_selector_rev": "1d3565e2651d16566bb556955b96ea75018cbd0c",
"boringssl_gen_rev": "ced85ef0a00bbca77ce5a91261a5f2ae61b1e62f",
"boringssl_rev": "87f316d7748268eb56f2dc147bd593254ae93198",
@@ -112,22 +112,22 @@
"devtools_rev": "95d292626da26505b02417735f77e8922783b477",
"ffi_rev": "18b2b549d55009ff594600b04705ff6161681e07",
"file_rev": "0132eeedea2933513bf230513a766a8baeab0c4f",
- "fixnum_rev": "164712f6547cdfb2709b752188186baf31fd1730",
+ "fixnum_rev": "e0b17cc1f639c55a9c24947392c64b5a68992535",
"glob_rev": "1d51fcc172e5adfbae6e82c3f8f119774cb2fca2",
"html_rev": "8243e967caad9932c13971af3b2a7c8f028383d5",
"http_multi_server_rev": "20bf079c8955d1250a45afb9cb096472a724a551",
- "http_parser_rev": "eaa63304c333316acd114e3be7ed701d7d7ba32c",
- "http_rev": "843c5ecb1ea2233ba7b7049833b5801b149fba86",
+ "http_parser_rev": "d25b3c9e7f23e31ac388a03361737110768597f6",
+ "http_rev": "5055b684ae45fb141a106ef6ced988aa37ed0ea6",
"icu_rev": "81d656878ec611cb0b42d52c82e9dae93920d9ba",
- "intl_rev": "e9b573679de5e703d89a242b9dca331c772979ef",
+ "intl_rev": "64dccc499162bebecb1ee29dc994f3e0c1416e96",
"jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
"json_rpc_2_rev": "805e6536dd961d66f6b8cd46d8f3e61774f957c9",
"linter_rev": "b4afc10055f3009478da1eac1827f9fef42c3759", # 1.26.0
"lints_rev": "8294e5648ab49474541527e2911e72e4c5aefe55",
- "logging_rev": "f6979e3bc3b6e1847a08335b7eb6304e18986195",
+ "logging_rev": "d10e24844c2e01d3f6d2b5a1a2bb8717359c6a87",
"markdown_rev": "e3f4bd28c9e61b522f75f291d4d6cfcfeccd83ee", # b/236358256
"markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
- "matcher_rev": "1a7fcae0d7af1604781afabe61fd35d9b404d8ed",
+ "matcher_rev": "cba63ebf8ed1daeffd5f3c55fd30085152c4512d",
"mime_rev": "0a75a41445eb642674a0a271eecde78cb025ee60",
"mockito_rev": "d8a2ddd2054390bd03d34bf64c940884e6f7a596",
"oauth2_rev": "199ebf15cbd5b07958438184f32e41c4447a57bf",
@@ -135,33 +135,33 @@
"path_rev": "9955b27b9bb98d87591208e19eb01c51d29fd467",
"ply_rev": "604b32590ffad5cbb82e4afef1d305512d06ae93",
"pool_rev": "fa84ddd0e39f45bf3f09dcc5d6b9fbdda7820fef",
- "protobuf_rev": "14c9c0b2d5542e73198a98054d93f0cb4acc846a",
+ "protobuf_rev": "a840335449e6a2a9617d2ebe5ecd0d577e071248",
"pub_rev": "9bf4289d6fd5d6872a8929d6312bbd7098f3ea9c", # manually rev'd
"pub_semver_rev": "5c0b4bfd5ca57fe16f1319c581dc8c882e9b8cb2",
"root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
"rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
- "shelf_rev": "f2cca46bdeb9888f29e685626bbe40654e1ca296",
+ "shelf_rev": "9dab94469d50e89a6e4e2c0086b717bddb0bf78a",
"source_map_stack_trace_rev": "72dbf21a33293b2b8434d0a9751e36f9463981ac",
"source_maps_rev": "e93565b43a7b6b367789de8ffba969c4ebeeb317",
"source_span_rev": "ff03af16474ce91c89eb3bc28182866f4cb6dfb0",
- "sse_rev": "2df072848a6090d3ed67f30c69e86ec4d6b96cd6",
+ "sse_rev": "00084c43684ddaf7e09c19c5364c4a27eb04efda",
"stack_trace_rev": "17f09c2c6845bb31c7c385acecce5befb8527a13",
"stream_channel_rev": "8e0d7ef1f4a3fb97fbd82e11cd539093f58511f3",
- "string_scanner_rev": "c637deb8d998b72a5807afbd06aba8370db725c0",
+ "string_scanner_rev": "2d84b16d8ae03c3a8c2417b71abe0fe6de7d8bf6",
"sync_http_rev": "39509d69fd5a9c3da46eab48fcafdf62e6ad4580",
- "term_glyph_rev": "741efdedf9da62ee66a06c295d36fa28f8780e24",
- "test_descriptor_rev": "5ed5d7f6bf1191592995dcb8eedbbc17df69d386",
+ "term_glyph_rev": "ec7cf7bb51ebb7d55760a1359f6697690dbc06ba",
+ "test_descriptor_rev": "c21e15daa3a22a7066f081d4d30aa5cae8b5de36",
"test_process_rev": "3e695bcfeab551473ddc288970f345f30e5e1375",
"test_reflective_loader_rev": "8d0de01bbe852fea1f8e33aba907abcba50a8a1e",
- "test_rev": "1ae207e51c0bcc6f539d878f9f7333ad977f38e5",
+ "test_rev": "b144a336776eaa1f9420f3ab38214d8c061c663e",
"typed_data_rev": "bb10b64f9a56b8fb49307d4465474bf1c1309f6d",
"usage_rev": "e287a72228974886d8a3b40ddcdf12f69d7c6a22",
- "vector_math_rev": "cdcee487bde4353a6ba7a29bfc7db3840426e50f",
+ "vector_math_rev": "09ba4fa74e668177211f917a1c14789cd05d3cab",
"watcher_rev": "e00c0ea769e32821d91c0880da8eb736839a6e6d",
"web_components_rev": "8f57dac273412a7172c8ade6f361b407e2e4ed02",
"web_socket_channel_rev": "99dbdc5769e19b9eeaf69449a59079153c6a8b1f",
"WebCore_rev": "bcb10901266c884e7b3740abc597ab95373ab55c",
- "webdev_rev": "3d2ad34a5354cfb2324d155d903b26590d79bd19",
+ "webdev_rev": "27cc5c9228ca59e721bc41fe7028e0fd6b995748",
"webdriver_rev": "e1a9ad671ee82e05eee463f922a34585ed2d2f15",
"webkit_inspection_protocol_rev": "57522d6b29d94903b765c757079d906555d5a171",
"yaml_edit_rev": "01589b3ce447b03aed991db49f1ec6445ad5476d",
diff --git a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
index 4c7ca36..3c57d35 100644
--- a/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
+++ b/pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart
@@ -114,7 +114,7 @@
int contextBuilds = 0;
/// The subscription to the stream of incoming messages from the client.
- late StreamSubscription<void> _channelSubscription;
+ late final StreamSubscription<void> _channelSubscription;
/// A completer that tracks in-progress analysis context rebuilds.
///
@@ -440,7 +440,7 @@
_channelSubscription.pause(completer.future);
try {
- // `await` here is imported to ensure `finally` doesn't execute until
+ // `await` here is important to ensure `finally` doesn't execute until
// `operation()` completes (`whenComplete` is not available on
// `FutureOr`).
return await operation();
diff --git a/pkg/analysis_server/lib/src/status/ast_writer.dart b/pkg/analysis_server/lib/src/status/ast_writer.dart
index bc19b76..f571ee9 100644
--- a/pkg/analysis_server/lib/src/status/ast_writer.dart
+++ b/pkg/analysis_server/lib/src/status/ast_writer.dart
@@ -96,7 +96,7 @@
} else if (node is InstanceCreationExpression) {
properties['static type'] = node.staticType;
} else if (node is LibraryDirective) {
- properties['element'] = node.element;
+ properties['element'] = node.element2;
} else if (node is MethodDeclaration) {
properties['declaredElement'] = node.declaredElement;
properties['external keyword'] = node.externalKeyword;
@@ -107,10 +107,10 @@
properties['static invoke type'] = node.staticInvokeType;
properties['static type'] = node.staticType;
} else if (node is PartDirective) {
- properties['element'] = node.element;
+ properties['element'] = node.element2;
properties['uriSource'] = node.uriSource;
} else if (node is PartOfDirective) {
- properties['element'] = node.element;
+ properties['element'] = node.element2;
} else if (node is PostfixExpression) {
properties['static element'] = node.staticElement;
properties['static type'] = node.staticType;
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index f7cf1fc..e16c1b4 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -4,6 +4,7 @@
* Deprecated `ClassOrMixinDeclaration.getField`, filter `members` instead.
* Deprecated `ClassOrMixinDeclaration.getMethod`, filter `members` instead.
* Deprecated `ClassDeclaration.getConstructor`, filter `members` instead.
+* Deprecated `Directive.element`, use `element2` instead.
## 4.3.1
* Fix `identifier` for `LibraryExportElement` and `LibraryImportElement`.
diff --git a/pkg/analyzer/lib/dart/analysis/utilities.dart b/pkg/analyzer/lib/dart/analysis/utilities.dart
index 64dfab7..89d8322 100644
--- a/pkg/analyzer/lib/dart/analysis/utilities.dart
+++ b/pkg/analyzer/lib/dart/analysis/utilities.dart
@@ -28,14 +28,14 @@
/// query it to get an [AnalysisSession], and then call `getParsedUnit`.
///
/// Callers that don't need the feature set to be strictly correct can pass in
-/// `FeatureSet.fromEnableFlags([])` to enable the default set of features; this
-/// is much more performant than using an analysis session, because it doesn't
-/// require the analyzer to process the SDK.
+/// `FeatureSet.latestLanguageVersion()` to enable the default set of features;
+/// this is much more performant than using an analysis session, because it
+/// doesn't require the analyzer to process the SDK.
///
/// If [throwIfDiagnostics] is `true` (the default), then if any diagnostics are
-/// produced because of syntactic errors in the [content] an `ArgumentError`
-/// will be thrown. If the parameter is `false`, then the caller can check the
-/// result to see whether there are any errors.
+/// produced because of syntactic errors in the file an `ArgumentError` will be
+/// thrown. If the parameter is `false`, then the caller can check the result
+/// to see whether there are any errors.
ParseStringResult parseFile(
{required String path,
ResourceProvider? resourceProvider,
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 74bd94d..fc24d3d 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -630,8 +630,7 @@
/// The token representing the 'augment' keyword.
Token get augmentKeyword;
- /// Return the element associated with this directive, or `null` if the AST
- /// structure has not been resolved.
+ @Deprecated('Use element2 instead')
@override
AugmentationImportElement? get element;
@@ -1526,8 +1525,13 @@
/// Return the element associated with this directive, or `null` if the AST
/// structure has not been resolved or if this directive could not be
/// resolved.
+ @Deprecated('Use element2 instead')
Element? get element;
+ /// Return the element associated with this directive, or `null` if the AST
+ /// structure has not been resolved.
+ Element? get element2;
+
/// Return the token representing the keyword that introduces this directive
/// ('import', 'export', 'library' or 'part').
@Deprecated('Use specific xyzToken instead')
@@ -1714,6 +1718,7 @@
/// Return the element associated with this directive, or `null` if the AST
/// structure has not been resolved.
+ @override
LibraryExportElement? get element2;
/// The token representing the 'export' keyword.
@@ -2893,6 +2898,7 @@
/// Return the element associated with this directive, or `null` if the AST
/// structure has not been resolved.
+ @override
LibraryImportElement? get element2;
/// The token representing the 'import' keyword.
@@ -3644,6 +3650,9 @@
///
/// Clients may not extend, implement or mix-in this class.
abstract class PartDirective implements UriBasedDirective {
+ @override
+ PartElement? get element2;
+
/// Return the token representing the 'part' keyword.
Token get partKeyword;
diff --git a/pkg/analyzer/lib/src/dart/analysis/index.dart b/pkg/analyzer/lib/src/dart/analysis/index.dart
index 7ea2d0c..265798f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/index.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/index.dart
@@ -793,7 +793,7 @@
@override
void visitPartDirective(PartDirective node) {
- final partElement = node.element;
+ final partElement = node.element2;
if (partElement is PartElement) {
final partElementUri = partElement.uri;
if (partElementUri is DirectiveUriWithUnit) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index 3eb1e38..b0ad4c6 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -590,7 +590,7 @@
if (unitResult is ResolvedUnitResult) {
CompilationUnit unit = unitResult.unit;
for (Directive directive in unit.directives) {
- if (directive is PartOfDirective && directive.element == element) {
+ if (directive is PartOfDirective && directive.element2 == element) {
results.add(
SearchResult._(
unit.declaredElement!,
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 00f3d6b..2c88c82 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -902,9 +902,15 @@
_becomeParentOf(_uri);
}
+ @Deprecated('Use element2 instead')
@override
AugmentationImportElement? get element {
- return super.element as AugmentationImportElement?;
+ throw StateError('Use element2 instead');
+ }
+
+ @override
+ AugmentationImportElement? get element2 {
+ return super.element2 as AugmentationImportElement?;
}
@override
@@ -919,7 +925,7 @@
@override
LibraryAugmentationElement? get uriElement {
- return element?.importedAugmentation;
+ return element2?.importedAugmentation;
}
@override
@@ -3274,6 +3280,7 @@
/// attribute.
DirectiveImpl(super.comment, super.metadata);
+ @Deprecated('Use element2 instead')
@override
Element? get element => _element;
@@ -3281,6 +3288,9 @@
set element(Element? element) {
_element = element;
}
+
+ @override
+ Element? get element2 => _element;
}
/// A do statement.
@@ -3799,7 +3809,7 @@
}
@override
- LibraryExportElement? get element2 => super.element as LibraryExportElement?;
+ LibraryExportElement? get element2 => super.element2 as LibraryExportElement?;
@override
Token get firstTokenAfterCommentAndMetadata => exportKeyword;
@@ -6449,7 +6459,7 @@
}
@override
- LibraryImportElement? get element2 => super.element as LibraryImportElement?;
+ LibraryImportElement? get element2 => super.element2 as LibraryImportElement?;
@override
Token get firstTokenAfterCommentAndMetadata => importKeyword;
@@ -8796,6 +8806,11 @@
: super(comment, metadata, partUri);
@override
+ PartElement? get element2 {
+ return super.element2 as PartElement?;
+ }
+
+ @override
Token get endToken => semicolon;
@override
@@ -8807,8 +8822,7 @@
@override
CompilationUnitElement? get uriElement {
- final partElement = element as PartElement?;
- final partElementUri = partElement?.uri;
+ final partElementUri = element2?.uri;
if (partElementUri is DirectiveUriWithUnit) {
return partElementUri.unit;
}
diff --git a/pkg/analyzer/lib/src/dart/ast/element_locator.dart b/pkg/analyzer/lib/src/dart/ast/element_locator.dart
index 8f676e4..279c3fb 100644
--- a/pkg/analyzer/lib/src/dart/ast/element_locator.dart
+++ b/pkg/analyzer/lib/src/dart/ast/element_locator.dart
@@ -98,12 +98,12 @@
} else if (parent is LibraryIdentifier) {
var grandParent = parent.parent;
if (grandParent is PartOfDirective) {
- var element = grandParent.element;
+ var element = grandParent.element2;
if (element is LibraryElement) {
return element.definingCompilationUnit;
}
} else if (grandParent is LibraryDirective) {
- return grandParent.element;
+ return grandParent.element2;
}
}
return node.writeOrReadElement;
@@ -126,7 +126,7 @@
@override
Element? visitLibraryDirective(LibraryDirective node) {
- return node.element;
+ return node.element2;
}
@override
@@ -141,7 +141,7 @@
@override
Element? visitPartOfDirective(PartOfDirective node) {
- return node.element;
+ return node.element2;
}
@override
diff --git a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
index 5cea4ce..ed87486 100644
--- a/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/resolution_visitor.dart
@@ -151,7 +151,7 @@
@override
void visitAugmentationImportDirective(AugmentationImportDirective node) {
- final element = node.element;
+ final element = node.element2;
if (element is AugmentationImportElementImpl) {
_setOrCreateMetadataElements(element, node.metadata);
}
@@ -828,7 +828,7 @@
@override
void visitLibraryAugmentationDirective(LibraryAugmentationDirective node) {
- final element = node.element;
+ final element = node.element2;
if (element is LibraryOrAugmentationElementImpl) {
_setOrCreateMetadataElements(element, node.metadata);
}
@@ -841,7 +841,7 @@
@override
void visitLibraryDirective(LibraryDirective node) {
++_libraryDirectiveIndex;
- var element = node.element;
+ var element = node.element2;
if (element is LibraryElementImpl && _libraryDirectiveIndex == 1) {
_setOrCreateMetadataElements(element, node.metadata);
}
@@ -924,8 +924,8 @@
@override
void visitPartDirective(PartDirective node) {
- var element = node.element;
- if (element is CompilationUnitElementImpl) {
+ var element = node.element2;
+ if (element is PartElementImpl) {
_setOrCreateMetadataElements(element, node.metadata);
}
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index 08a40f1..08751df 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -70,7 +70,7 @@
_container.documentationComment = getCommentNodeRawText(
firstDirective.documentationComment,
);
- var firstDirectiveMetadata = firstDirective.element?.metadata;
+ var firstDirectiveMetadata = firstDirective.element2?.metadata;
if (firstDirectiveMetadata != null) {
_container.metadata = firstDirectiveMetadata;
}
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index fb9ae05..b382aee 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -135,7 +135,7 @@
@override
void visitLibraryDirective(LibraryDirective node) {
- _checkResolved(node, node.element, (node) => node is LibraryElement);
+ _checkResolved(node, node.element2, (node) => node is LibraryElement);
}
@override
@@ -146,12 +146,12 @@
@override
void visitPartDirective(PartDirective node) {
_checkResolved(
- node, node.element, (node) => node is CompilationUnitElement);
+ node, node.element2, (node) => node is CompilationUnitElement);
}
@override
void visitPartOfDirective(PartOfDirective node) {
- _checkResolved(node, node.element, (node) => node is LibraryElement);
+ _checkResolved(node, node.element2, (node) => node is LibraryElement);
}
@override
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index 3139dc0..d1c30e3 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -129,7 +129,7 @@
_writeln('AugmentationImportDirective');
_withIndent(() {
_writeNamedChildEntities(node);
- _writeElement('element', node.element);
+ _writeElement('element', node.element2);
_writeRaw('uriContent', node.uriContent);
_writeElement('uriElement', node.uriElement);
_writeSource('uriSource', node.uriSource);
@@ -774,7 +774,7 @@
_writeln('LibraryAugmentationDirective');
_withIndent(() {
_writeNamedChildEntities(node);
- _writeElement('element', node.element);
+ _writeElement('element', node.element2);
});
}
@@ -783,7 +783,7 @@
_writeln('LibraryDirective');
_withIndent(() {
_writeNamedChildEntities(node);
- _writeElement('element', node.element);
+ _writeElement('element', node.element2);
});
}
@@ -901,7 +901,7 @@
_writeln('PartDirective');
_withIndent(() {
_writeNamedChildEntities(node);
- _writeElement('element', node.element);
+ _writeElement('element', node.element2);
_writeRaw('uriContent', node.uriContent);
_writePartUnitElement('uriElement', node.uriElement);
_writeSource('uriSource', node.uriSource);
@@ -913,7 +913,7 @@
_writeln('PartOfDirective');
_withIndent(() {
_writeNamedChildEntities(node);
- _writeElement('element', node.element);
+ _writeElement('element', node.element2);
});
}
diff --git a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
index c58c3e2..d0b8b44 100644
--- a/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/navigation/navigation_dart.dart
@@ -385,12 +385,12 @@
@override
void visitLibraryDirective(LibraryDirective node) {
- computer._addRegionForNode(node.name, node.element);
+ computer._addRegionForNode(node.name, node.element2);
}
@override
void visitPartDirective(PartDirective node) {
- final element = node.element;
+ final element = node.element2;
if (element is PartElement) {
final uri = element.uri;
if (uri is DirectiveUriWithUnit) {
@@ -413,7 +413,7 @@
@override
void visitPartOfDirective(PartOfDirective node) {
- computer._addRegionForNode(node.libraryName ?? node.uri, node.element);
+ computer._addRegionForNode(node.libraryName ?? node.uri, node.element2);
super.visitPartOfDirective(node);
}
diff --git a/pkg/dart2wasm/lib/constants.dart b/pkg/dart2wasm/lib/constants.dart
index 2d2a59a..70df2ad 100644
--- a/pkg/dart2wasm/lib/constants.dart
+++ b/pkg/dart2wasm/lib/constants.dart
@@ -826,4 +826,20 @@
});
}
}
+
+ @override
+ ConstantInfo? visitSymbolConstant(SymbolConstant constant) {
+ ClassInfo info = translator.classInfo[translator.symbolClass]!;
+ translator.functions.allocateClass(info.classId);
+ w.RefType stringType =
+ translator.classInfo[translator.coreTypes.stringClass]!.nonNullableType;
+ StringConstant nameConstant = StringConstant(constant.name);
+ ensureConstant(nameConstant);
+ return createConstant(constant, info.nonNullableType, (function, b) {
+ b.i32_const(info.classId);
+ b.i32_const(initialIdentityHash);
+ constants.instantiateConstant(function, b, nameConstant, stringType);
+ translator.struct_new(b, info);
+ });
+ }
}
diff --git a/pkg/dart2wasm/lib/translator.dart b/pkg/dart2wasm/lib/translator.dart
index fb50aec..dc57e39 100644
--- a/pkg/dart2wasm/lib/translator.dart
+++ b/pkg/dart2wasm/lib/translator.dart
@@ -112,6 +112,7 @@
late final Class byteDataViewClass;
late final Class typeErrorClass;
late final Class typeUniverseClass;
+ late final Class symbolClass;
late final Procedure wasmFunctionCall;
late final Procedure wasmTableCallIndirect;
late final Procedure stackTraceCurrent;
@@ -188,6 +189,7 @@
Class Function(String) lookupCore = makeLookup("dart.core");
Class Function(String) lookupCollection = makeLookup("dart.collection");
Class Function(String) lookupFfi = makeLookup("dart.ffi");
+ Class Function(String) lookupInternal = makeLookup("dart._internal");
Class Function(String) lookupTypedData = makeLookup("dart.typed_data");
Class Function(String) lookupWasm = makeLookup("dart.wasm");
@@ -235,6 +237,7 @@
typedListClass = lookupTypedData("_TypedList");
typedListViewClass = lookupTypedData("_TypedListView");
byteDataViewClass = lookupTypedData("_ByteDataView");
+ symbolClass = lookupInternal("Symbol");
wasmFunctionCall =
wasmFunctionClass.procedures.firstWhere((p) => p.name.text == "call");
wasmTableCallIndirect = wasmTableClass.procedures
diff --git a/runtime/vm/app_snapshot.cc b/runtime/vm/app_snapshot.cc
index 78cb595..14cc87c 100644
--- a/runtime/vm/app_snapshot.cc
+++ b/runtime/vm/app_snapshot.cc
@@ -330,6 +330,7 @@
if (s->kind() != Snapshot::kFullAOT) {
s->WriteTokenPosition(cls->untag()->token_pos_);
s->WriteTokenPosition(cls->untag()->end_token_pos_);
+ s->WriteCid(cls->untag()->implementor_cid_);
}
s->Write<uint32_t>(cls->untag()->state_bits_);
@@ -426,6 +427,7 @@
ASSERT(d_->kind() != Snapshot::kFullAOT);
cls->untag()->token_pos_ = d.ReadTokenPosition();
cls->untag()->end_token_pos_ = d.ReadTokenPosition();
+ cls->untag()->implementor_cid_ = d.ReadCid();
#endif // !defined(DART_PRECOMPILED_RUNTIME)
cls->untag()->state_bits_ = d.Read<uint32_t>();
@@ -469,6 +471,7 @@
ASSERT(d_->kind() != Snapshot::kFullAOT);
cls->untag()->token_pos_ = d.ReadTokenPosition();
cls->untag()->end_token_pos_ = d.ReadTokenPosition();
+ cls->untag()->implementor_cid_ = d.ReadCid();
#endif // !defined(DART_PRECOMPILED_RUNTIME)
cls->untag()->state_bits_ = d.Read<uint32_t>();
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 141ae5a..bd47dc0 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -302,6 +302,7 @@
err.ToErrorCString());
OS::Exit(255);
}
+
if (FLAG_trace_class_finalization) {
OS::PrintErr("VerifyBootstrapClasses END.\n");
}
@@ -1091,7 +1092,7 @@
// Add this class as an implementor to the implemented interface's type
// classes.
- const auto& interfaces = Array::Handle(zone, cls.interfaces());
+ auto& interfaces = Array::Handle(zone, cls.interfaces());
const intptr_t mixin_index =
cls.is_transformed_mixin_application() ? interfaces.Length() - 1 : -1;
for (intptr_t i = 0; i < interfaces.Length(); ++i) {
@@ -1100,6 +1101,25 @@
MarkImplemented(zone, other_cls);
other_cls.AddDirectImplementor(cls, /* is_mixin = */ i == mixin_index);
}
+
+ // Propogate known concrete implementors to interfaces.
+ if (!cls.is_abstract()) {
+ GrowableArray<const Class*> worklist;
+ worklist.Add(&cls);
+ while (!worklist.is_empty()) {
+ const Class& implemented = *worklist.RemoveLast();
+ if (!implemented.NoteImplementor(cls)) continue;
+ type = implemented.super_type();
+ if (!type.IsNull()) {
+ worklist.Add(&Class::Handle(zone, implemented.SuperClass()));
+ }
+ interfaces = implemented.interfaces();
+ for (intptr_t i = 0; i < interfaces.Length(); i++) {
+ type ^= interfaces.At(i);
+ worklist.Add(&Class::Handle(zone, type.type_class()));
+ }
+ }
+ }
}
#endif // defined(DART_PRECOMPILED_RUNTIME)
@@ -1493,6 +1513,7 @@
return;
}
cls->untag()->id_ = Map(old_cid);
+ cls->untag()->implementor_cid_ = Map(cls->untag()->implementor_cid_);
} else if (obj->IsField()) {
FieldPtr field = Field::RawCast(obj);
field->untag()->guarded_cid_ = Map(field->untag()->guarded_cid_);
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index c1488d8..526a2c8 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -108,12 +108,13 @@
}
const Class& cls = Class::Handle(Z, target_function.Owner());
- if (CHA::IsImplemented(cls) || CHA::HasSubclasses(cls)) {
+ intptr_t implementor_cid = kIllegalCid;
+ if (!CHA::HasSingleConcreteImplementation(cls, &implementor_cid)) {
return false;
}
call->SetTargets(
- CallTargets::CreateMonomorphic(Z, cls.id(), target_function));
+ CallTargets::CreateMonomorphic(Z, implementor_cid, target_function));
ASSERT(call->Targets().IsMonomorphic());
// If we know that the only noSuchMethod is Object.noSuchMethod then
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 086e3e5..b9804d5 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -768,38 +768,12 @@
cid_ = kSentinelCid;
} else if (type_->IsFunctionType() || type_->IsDartFunctionType()) {
cid_ = kClosureCid;
- } else if (type_->IsDoubleType()) {
- cid_ = kDoubleCid; // double's only implementor is _Double.
- } else if (type_->IsFloat32x4Type()) {
- cid_ = kFloat32x4Cid; // Float32x4's only implementor is _Float32x4.
- } else if (type_->IsFloat64x2Type()) {
- cid_ = kFloat64x2Cid; // Float64x2's only implementor is _Float64x2.
- } else if (type_->IsInt32x4Type()) {
- cid_ = kInt32x4Cid; // Int32x4's only implementor is _Int32x4.
} else if (type_->type_class_id() != kIllegalCid) {
const Class& type_class = Class::Handle(type_->type_class());
- Thread* thread = Thread::Current();
- CHA& cha = thread->compiler_state().cha();
- // Don't infer a cid from an abstract type since there can be multiple
- // compatible classes with different cids.
- if (!type_class.is_abstract() && !CHA::IsImplemented(type_class) &&
- !CHA::HasSubclasses(type_class)) {
- if (type_class.IsPrivate()) {
- // Type of a private class cannot change through later loaded libs.
- cid_ = type_class.id();
- } else if (FLAG_use_cha_deopt ||
- thread->isolate_group()->all_classes_finalized()) {
- if (FLAG_trace_cha) {
- THR_Print(" **(CHA) Compile type not subclassed: %s\n",
- type_class.ToCString());
- }
- if (FLAG_use_cha_deopt) {
- cha.AddToGuardedClasses(type_class, /*subclass_count=*/0);
- }
- cid_ = type_class.id();
- } else {
- cid_ = kDynamicCid;
- }
+ intptr_t implementation_cid = kIllegalCid;
+ if (CHA::HasSingleConcreteImplementation(type_class,
+ &implementation_cid)) {
+ cid_ = implementation_cid;
} else {
cid_ = kDynamicCid;
}
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index ae363e2..7831f36 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -1102,39 +1102,20 @@
}
// Returns true if checking against this type is a direct class id comparison.
-bool CallSpecializer::TypeCheckAsClassEquality(const AbstractType& type) {
+bool CallSpecializer::TypeCheckAsClassEquality(const AbstractType& type,
+ intptr_t* type_cid) {
+ *type_cid = kIllegalCid;
ASSERT(type.IsFinalized());
// Requires CHA.
if (!type.IsInstantiated()) return false;
// Function types have different type checking rules.
if (type.IsFunctionType()) return false;
+
const Class& type_class = Class::Handle(type.type_class());
- // Could be an interface check?
- if (CHA::IsImplemented(type_class)) return false;
- // Check if there are subclasses.
- if (CHA::HasSubclasses(type_class)) {
+ if (!CHA::HasSingleConcreteImplementation(type_class, type_cid)) {
return false;
}
- // Private classes cannot be subclassed by later loaded libs.
- if (!type_class.IsPrivate()) {
- // In AOT mode we can't use CHA deoptimizations.
- ASSERT(!CompilerState::Current().is_aot() || !FLAG_use_cha_deopt);
- if (FLAG_use_cha_deopt || isolate_group()->all_classes_finalized()) {
- if (FLAG_trace_cha) {
- THR_Print(
- " **(CHA) Typecheck as class equality since no "
- "subclasses: %s\n",
- type_class.ToCString());
- }
- if (FLAG_use_cha_deopt) {
- thread()->compiler_state().cha().AddToGuardedClasses(
- type_class, /*subclass_count=*/0);
- }
- } else {
- return false;
- }
- }
const intptr_t num_type_args = type_class.NumTypeArguments();
if (num_type_args > 0) {
// Only raw types can be directly compared, thus disregarding type
@@ -1242,10 +1223,10 @@
return;
}
- if (TypeCheckAsClassEquality(type)) {
+ intptr_t type_cid;
+ if (TypeCheckAsClassEquality(type, &type_cid)) {
LoadClassIdInstr* left_cid = new (Z) LoadClassIdInstr(new (Z) Value(left));
InsertBefore(call, left_cid, NULL, FlowGraph::kValue);
- const intptr_t type_cid = Class::Handle(Z, type.type_class()).id();
ConstantInstr* cid =
flow_graph()->GetConstant(Smi::Handle(Z, Smi::New(type_cid)));
diff --git a/runtime/vm/compiler/call_specializer.h b/runtime/vm/compiler/call_specializer.h
index c4ac095..f5e9423 100644
--- a/runtime/vm/compiler/call_specializer.h
+++ b/runtime/vm/compiler/call_specializer.h
@@ -144,7 +144,7 @@
const bool should_clone_fields_;
private:
- bool TypeCheckAsClassEquality(const AbstractType& type);
+ bool TypeCheckAsClassEquality(const AbstractType& type, intptr_t* type_cid);
// Insert a Smi check if needed.
void AddCheckSmi(Definition* to_check,
diff --git a/runtime/vm/compiler/cha.cc b/runtime/vm/compiler/cha.cc
index 06888b6..8d23e00 100644
--- a/runtime/vm/compiler/cha.cc
+++ b/runtime/vm/compiler/cha.cc
@@ -4,7 +4,9 @@
#include "vm/compiler/cha.h"
#include "vm/class_table.h"
+#include "vm/compiler/compiler_state.h"
#include "vm/flags.h"
+#include "vm/log.h"
#include "vm/object.h"
#include "vm/raw_object.h"
#include "vm/visitor.h"
@@ -12,15 +14,36 @@
namespace dart {
void CHA::AddToGuardedClasses(const Class& cls, intptr_t subclass_count) {
+ ASSERT(subclass_count >= 0);
for (intptr_t i = 0; i < guarded_classes_.length(); i++) {
if (guarded_classes_[i].cls->ptr() == cls.ptr()) {
+ // Was added as an interface guard.
+ if (guarded_classes_[i].subclass_count == -1) {
+ guarded_classes_[i].subclass_count = subclass_count;
+ }
return;
}
}
GuardedClassInfo info = {&Class::ZoneHandle(thread_->zone(), cls.ptr()),
- subclass_count};
+ subclass_count, kIllegalCid};
guarded_classes_.Add(info);
- return;
+}
+
+void CHA::AddToGuardedInterfaces(const Class& cls, intptr_t implementor_cid) {
+ ASSERT(implementor_cid != kIllegalCid);
+ ASSERT(implementor_cid != kDynamicCid);
+ for (intptr_t i = 0; i < guarded_classes_.length(); i++) {
+ if (guarded_classes_[i].cls->ptr() == cls.ptr()) {
+ // Was added as a subclass guard.
+ if (guarded_classes_[i].implementor_cid == kIllegalCid) {
+ guarded_classes_[i].implementor_cid = implementor_cid;
+ }
+ return;
+ }
+ }
+ GuardedClassInfo info = {&Class::ZoneHandle(thread_->zone(), cls.ptr()), -1,
+ implementor_cid};
+ guarded_classes_.Add(info);
}
bool CHA::IsGuardedClass(intptr_t cid) const {
@@ -93,6 +116,33 @@
return cls.is_implemented();
}
+bool CHA::HasSingleConcreteImplementation(const Class& interface,
+ intptr_t* implementation_cid) {
+ intptr_t cid = interface.implementor_cid();
+ if ((cid == kIllegalCid) || (cid == kDynamicCid)) {
+ // No implementations / multiple implementations.
+ *implementation_cid = kDynamicCid;
+ return false;
+ }
+
+ Thread* thread = Thread::Current();
+ if (FLAG_use_cha_deopt || thread->isolate_group()->all_classes_finalized()) {
+ if (FLAG_trace_cha) {
+ THR_Print(" **(CHA) Type has one implementation: %s\n",
+ interface.ToCString());
+ }
+ if (FLAG_use_cha_deopt) {
+ CHA& cha = thread->compiler_state().cha();
+ cha.AddToGuardedInterfaces(interface, cid);
+ }
+ *implementation_cid = cid;
+ return true;
+ } else {
+ *implementation_cid = kDynamicCid;
+ return false;
+ }
+}
+
static intptr_t CountFinalizedSubclasses(Thread* thread, const Class& cls) {
intptr_t count = 0;
const GrowableObjectArray& cls_direct_subclasses =
@@ -114,10 +164,19 @@
bool CHA::IsConsistentWithCurrentHierarchy() const {
for (intptr_t i = 0; i < guarded_classes_.length(); i++) {
- const intptr_t subclass_count =
- CountFinalizedSubclasses(thread_, *guarded_classes_[i].cls);
- if (guarded_classes_[i].subclass_count != subclass_count) {
- return false;
+ if (guarded_classes_[i].subclass_count != -1) {
+ intptr_t current_subclass_count =
+ CountFinalizedSubclasses(thread_, *guarded_classes_[i].cls);
+ if (guarded_classes_[i].subclass_count != current_subclass_count) {
+ return false; // New subclass appeared during compilation.
+ }
+ }
+ if (guarded_classes_[i].implementor_cid != kIllegalCid) {
+ intptr_t current_implementor_cid =
+ guarded_classes_[i].cls->implementor_cid();
+ if (guarded_classes_[i].implementor_cid != current_implementor_cid) {
+ return false; // New implementor appeared during compilation.
+ }
}
}
return true;
diff --git a/runtime/vm/compiler/cha.h b/runtime/vm/compiler/cha.h
index dd1d5b3..a52bd3e 100644
--- a/runtime/vm/compiler/cha.h
+++ b/runtime/vm/compiler/cha.h
@@ -37,9 +37,15 @@
static bool ConcreteSubclasses(const Class& cls,
GrowableArray<intptr_t>* class_ids);
- // Return true if the class is implemented by some other class.
+ // Return true if the class is implemented by some other class that is not a
+ // subclass.
static bool IsImplemented(const Class& cls);
+ // Return true if there is only one concrete class that implements
+ // 'interface'.
+ static bool HasSingleConcreteImplementation(const Class& interface,
+ intptr_t* implementation_cid);
+
// Returns true if any subclass of 'cls' contains the function.
// If no override was found subclass_count would contain total count of
// finalized subclasses that CHA looked at.
@@ -49,10 +55,12 @@
const String& function_name,
intptr_t* subclass_count);
- // Adds class 'cls' to the list of guarded classes, deoptimization occurs
- // if any of those classes gets subclassed through later loaded/finalized
- // libraries. Only classes that were used for CHA optimizations are added.
+ // Adds class 'cls' to the list of guarded classes / interfaces.
+ // Deoptimization occurs if any of those classes gets subclassed or
+ // implemented through later loaded/finalized libraries. Only classes that
+ // were used for CHA optimizations are added.
void AddToGuardedClasses(const Class& cls, intptr_t subclass_count);
+ void AddToGuardedInterfaces(const Class& cls, intptr_t implementor_cid);
// When compiling in background we need to check that no new finalized
// subclasses were added to guarded classes.
@@ -74,6 +82,12 @@
// Used to validate correctness of background compilation: if
// any subclasses were added we will discard compiled code.
intptr_t subclass_count;
+
+ // Value of implementor_cid that this class had at the moment
+ // when CHA made the first decision based on this class.
+ // Used to validate correctness of background compilation: if
+ // any implementors were added we will discard compiled code.
+ intptr_t implementor_cid;
};
GrowableArray<GuardedClassInfo> guarded_classes_;
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 098de96..078b14d 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -119,10 +119,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
52;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 88;
+ 92;
static constexpr dart::compiler::target::word Class_super_type_offset = 44;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 100;
+ Class_host_type_arguments_field_offset_in_words_offset = 104;
static constexpr dart::compiler::target::word
SharedClassTable_class_heap_stats_table_offset = 0;
static constexpr dart::compiler::target::word Closure_context_offset = 20;
@@ -583,7 +583,7 @@
static constexpr dart::compiler::target::word Array_header_size = 12;
static constexpr dart::compiler::target::word Bool_InstanceSize = 8;
static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 112;
+static constexpr dart::compiler::target::word Class_InstanceSize = 116;
static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
@@ -780,10 +780,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
104;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 164;
+ 168;
static constexpr dart::compiler::target::word Class_super_type_offset = 88;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 176;
+ Class_host_type_arguments_field_offset_in_words_offset = 180;
static constexpr dart::compiler::target::word
SharedClassTable_class_heap_stats_table_offset = 0;
static constexpr dart::compiler::target::word Closure_context_offset = 40;
@@ -1446,10 +1446,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
52;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 88;
+ 92;
static constexpr dart::compiler::target::word Class_super_type_offset = 44;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 100;
+ Class_host_type_arguments_field_offset_in_words_offset = 104;
static constexpr dart::compiler::target::word
SharedClassTable_class_heap_stats_table_offset = 0;
static constexpr dart::compiler::target::word Closure_context_offset = 20;
@@ -1907,7 +1907,7 @@
static constexpr dart::compiler::target::word Array_header_size = 12;
static constexpr dart::compiler::target::word Bool_InstanceSize = 8;
static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 112;
+static constexpr dart::compiler::target::word Class_InstanceSize = 116;
static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
@@ -2104,10 +2104,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
104;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 164;
+ 168;
static constexpr dart::compiler::target::word Class_super_type_offset = 88;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 176;
+ Class_host_type_arguments_field_offset_in_words_offset = 180;
static constexpr dart::compiler::target::word
SharedClassTable_class_heap_stats_table_offset = 0;
static constexpr dart::compiler::target::word Closure_context_offset = 40;
@@ -2771,10 +2771,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
56;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 92;
+ 96;
static constexpr dart::compiler::target::word Class_super_type_offset = 48;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 104;
+ Class_host_type_arguments_field_offset_in_words_offset = 108;
static constexpr dart::compiler::target::word
SharedClassTable_class_heap_stats_table_offset = 0;
static constexpr dart::compiler::target::word Closure_context_offset = 24;
@@ -3437,10 +3437,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
56;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 92;
+ 96;
static constexpr dart::compiler::target::word Class_super_type_offset = 48;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 104;
+ Class_host_type_arguments_field_offset_in_words_offset = 108;
static constexpr dart::compiler::target::word
SharedClassTable_class_heap_stats_table_offset = 0;
static constexpr dart::compiler::target::word Closure_context_offset = 24;
@@ -4104,10 +4104,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
52;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 88;
+ 92;
static constexpr dart::compiler::target::word Class_super_type_offset = 44;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 100;
+ Class_host_type_arguments_field_offset_in_words_offset = 104;
static constexpr dart::compiler::target::word
SharedClassTable_class_heap_stats_table_offset = 0;
static constexpr dart::compiler::target::word Closure_context_offset = 20;
@@ -4570,7 +4570,7 @@
static constexpr dart::compiler::target::word Array_header_size = 12;
static constexpr dart::compiler::target::word Bool_InstanceSize = 8;
static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 112;
+static constexpr dart::compiler::target::word Class_InstanceSize = 116;
static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
@@ -4767,10 +4767,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
104;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 164;
+ 168;
static constexpr dart::compiler::target::word Class_super_type_offset = 88;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 176;
+ Class_host_type_arguments_field_offset_in_words_offset = 180;
static constexpr dart::compiler::target::word
SharedClassTable_class_heap_stats_table_offset = 0;
static constexpr dart::compiler::target::word Closure_context_offset = 40;
@@ -5433,10 +5433,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
48;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 84;
+ 88;
static constexpr dart::compiler::target::word Class_super_type_offset = 40;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 96;
+ Class_host_type_arguments_field_offset_in_words_offset = 100;
static constexpr dart::compiler::target::word Closure_context_offset = 20;
static constexpr dart::compiler::target::word
Closure_delayed_type_arguments_offset = 12;
@@ -5892,7 +5892,7 @@
static constexpr dart::compiler::target::word Array_header_size = 12;
static constexpr dart::compiler::target::word Bool_InstanceSize = 8;
static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 108;
+static constexpr dart::compiler::target::word Class_InstanceSize = 112;
static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
@@ -6086,10 +6086,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
96;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 156;
+ 160;
static constexpr dart::compiler::target::word Class_super_type_offset = 80;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 168;
+ Class_host_type_arguments_field_offset_in_words_offset = 172;
static constexpr dart::compiler::target::word Closure_context_offset = 40;
static constexpr dart::compiler::target::word
Closure_delayed_type_arguments_offset = 24;
@@ -6744,10 +6744,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
48;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 84;
+ 88;
static constexpr dart::compiler::target::word Class_super_type_offset = 40;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 96;
+ Class_host_type_arguments_field_offset_in_words_offset = 100;
static constexpr dart::compiler::target::word Closure_context_offset = 20;
static constexpr dart::compiler::target::word
Closure_delayed_type_arguments_offset = 12;
@@ -7200,7 +7200,7 @@
static constexpr dart::compiler::target::word Array_header_size = 12;
static constexpr dart::compiler::target::word Bool_InstanceSize = 8;
static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 108;
+static constexpr dart::compiler::target::word Class_InstanceSize = 112;
static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
@@ -7394,10 +7394,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
96;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 156;
+ 160;
static constexpr dart::compiler::target::word Class_super_type_offset = 80;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 168;
+ Class_host_type_arguments_field_offset_in_words_offset = 172;
static constexpr dart::compiler::target::word Closure_context_offset = 40;
static constexpr dart::compiler::target::word
Closure_delayed_type_arguments_offset = 24;
@@ -8053,10 +8053,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
52;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 88;
+ 92;
static constexpr dart::compiler::target::word Class_super_type_offset = 44;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 100;
+ Class_host_type_arguments_field_offset_in_words_offset = 104;
static constexpr dart::compiler::target::word Closure_context_offset = 24;
static constexpr dart::compiler::target::word
Closure_delayed_type_arguments_offset = 16;
@@ -8519,7 +8519,7 @@
static constexpr dart::compiler::target::word Array_header_size = 16;
static constexpr dart::compiler::target::word Bool_InstanceSize = 16;
static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 112;
+static constexpr dart::compiler::target::word Class_InstanceSize = 120;
static constexpr dart::compiler::target::word Closure_InstanceSize = 32;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
@@ -8711,10 +8711,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
52;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 88;
+ 92;
static constexpr dart::compiler::target::word Class_super_type_offset = 44;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 100;
+ Class_host_type_arguments_field_offset_in_words_offset = 104;
static constexpr dart::compiler::target::word Closure_context_offset = 24;
static constexpr dart::compiler::target::word
Closure_delayed_type_arguments_offset = 16;
@@ -9178,7 +9178,7 @@
static constexpr dart::compiler::target::word Array_header_size = 16;
static constexpr dart::compiler::target::word Bool_InstanceSize = 16;
static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 112;
+static constexpr dart::compiler::target::word Class_InstanceSize = 120;
static constexpr dart::compiler::target::word Closure_InstanceSize = 32;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 24;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 16;
@@ -9370,10 +9370,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
48;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 84;
+ 88;
static constexpr dart::compiler::target::word Class_super_type_offset = 40;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 96;
+ Class_host_type_arguments_field_offset_in_words_offset = 100;
static constexpr dart::compiler::target::word Closure_context_offset = 20;
static constexpr dart::compiler::target::word
Closure_delayed_type_arguments_offset = 12;
@@ -9831,7 +9831,7 @@
static constexpr dart::compiler::target::word Array_header_size = 12;
static constexpr dart::compiler::target::word Bool_InstanceSize = 8;
static constexpr dart::compiler::target::word Capability_InstanceSize = 16;
-static constexpr dart::compiler::target::word Class_InstanceSize = 108;
+static constexpr dart::compiler::target::word Class_InstanceSize = 112;
static constexpr dart::compiler::target::word Closure_InstanceSize = 28;
static constexpr dart::compiler::target::word ClosureData_InstanceSize = 20;
static constexpr dart::compiler::target::word CodeSourceMap_HeaderSize = 8;
@@ -10025,10 +10025,10 @@
static constexpr dart::compiler::target::word Class_declaration_type_offset =
96;
static constexpr dart::compiler::target::word Class_num_type_arguments_offset =
- 156;
+ 160;
static constexpr dart::compiler::target::word Class_super_type_offset = 80;
static constexpr dart::compiler::target::word
- Class_host_type_arguments_field_offset_in_words_offset = 168;
+ Class_host_type_arguments_field_offset_in_words_offset = 172;
static constexpr dart::compiler::target::word Closure_context_offset = 40;
static constexpr dart::compiler::target::word
Closure_delayed_type_arguments_offset = 24;
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index fa75c09..4af9fe1 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1395,6 +1395,13 @@
}
}
#endif
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ if (obj->IsClass()) {
+ // Won't be able to update read-only VM isolate classes if implementors
+ // are discovered later.
+ static_cast<ClassPtr>(obj)->untag()->implementor_cid_ = kDynamicCid;
+ }
+#endif
}
}
@@ -2984,6 +2991,7 @@
target_next_field_offset);
COMPILE_ASSERT((FakeObject::kClassId != kInstanceCid));
result.set_id(FakeObject::kClassId);
+ NOT_IN_PRECOMPILED(result.set_implementor_cid(kIllegalCid));
result.set_num_type_arguments_unsafe(0);
result.set_num_native_fields(0);
result.set_state_bits(0);
@@ -4741,6 +4749,7 @@
result.set_next_field_offset(host_next_field_offset,
target_next_field_offset);
result.set_id(index);
+ NOT_IN_PRECOMPILED(result.set_implementor_cid(kIllegalCid));
result.set_num_type_arguments_unsafe(kUnknownNumTypeArguments);
result.set_num_native_fields(0);
result.set_state_bits(0);
@@ -4826,6 +4835,7 @@
cls.set_is_declaration_loaded();
cls.set_is_type_finalized();
cls.set_is_synthesized_class();
+ NOT_IN_PRECOMPILED(cls.set_implementor_cid(kDynamicCid));
library.AddClass(cls);
return cls.ptr();
} else {
@@ -5147,6 +5157,27 @@
ASSERT(!token_pos.IsClassifying());
StoreNonPointer(&untag()->end_token_pos_, token_pos);
}
+
+void Class::set_implementor_cid(intptr_t value) const {
+ ASSERT(value >= 0 && value < std::numeric_limits<classid_t>::max());
+ StoreNonPointer(&untag()->implementor_cid_, value);
+}
+
+bool Class::NoteImplementor(const Class& implementor) const {
+ ASSERT(!implementor.is_abstract());
+ ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
+ if (implementor_cid() == kDynamicCid) {
+ return false;
+ } else if (implementor_cid() == implementor.id()) {
+ return false;
+ } else if (implementor_cid() == kIllegalCid) {
+ set_implementor_cid(implementor.id());
+ return true; // None -> One
+ } else {
+ set_implementor_cid(kDynamicCid);
+ return true; // One -> Many
+ }
+}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
int32_t Class::SourceFingerprint() const {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 3c6cc54..28feedf 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1110,6 +1110,19 @@
StoreNonPointer(&untag()->id_, value);
}
static intptr_t id_offset() { return OFFSET_OF(UntaggedClass, id_); }
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+ // If the interface of this class has a single concrete implementation, either
+ // via `extends` or by `implements`, returns its CID.
+ // If it has no implementation, returns kIllegalCid.
+ // If it has more than one implementation, returns kDynamicCid.
+ intptr_t implementor_cid() const { return untag()->implementor_cid_; }
+
+ // Returns true if the implementor tracking state changes and so must be
+ // propagated to this class's superclass and interfaces.
+ bool NoteImplementor(const Class& implementor) const;
+#endif
+
static intptr_t num_type_arguments_offset() {
return OFFSET_OF(UntaggedClass, num_type_arguments_);
}
@@ -1531,6 +1544,9 @@
return RoundedAllocationSize(sizeof(UntaggedClass));
}
+ // Returns true if any class implements this interface via `implements`.
+ // Returns false if all possible implementations of this interface must be
+ // instances of this class or its subclasses.
bool is_implemented() const { return ImplementedBit::decode(state_bits()); }
void set_is_implemented() const;
void set_is_implemented_unsafe() const;
@@ -1874,6 +1890,7 @@
void set_user_name(const String& value) const;
const char* GenerateUserVisibleName() const;
void set_state_bits(intptr_t bits) const;
+ void set_implementor_cid(intptr_t value) const;
FunctionPtr CreateInvocationDispatcher(const String& target_name,
const Array& args_desc,
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 2df9119..3cc7a2b 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -5358,6 +5358,91 @@
EXPECT(class_a_sub.implements_finalizable());
}
+TEST_CASE(ImplementorCid) {
+ const char* kScriptChars = R"(
+abstract class AInterface {}
+
+abstract class BInterface {}
+class BImplementation implements BInterface {}
+
+abstract class CInterface {}
+class CImplementation1 implements CInterface {}
+class CImplementation2 implements CInterface {}
+
+abstract class DInterface {}
+abstract class DSubinterface implements DInterface {}
+
+abstract class EInterface {}
+abstract class ESubinterface implements EInterface {}
+class EImplementation implements ESubinterface {}
+
+abstract class FInterface {}
+abstract class FSubinterface implements FInterface {}
+class FImplementation1 implements FSubinterface {}
+class FImplementation2 implements FSubinterface {}
+
+main() {
+ new BImplementation();
+ new CImplementation1();
+ new CImplementation2();
+ new EImplementation();
+ new FImplementation1();
+ new FImplementation2();
+}
+)";
+ Dart_Handle h_lib = TestCase::LoadTestScript(kScriptChars, NULL);
+ EXPECT_VALID(h_lib);
+ Dart_Handle result = Dart_Invoke(h_lib, NewString("main"), 0, NULL);
+ EXPECT_VALID(result);
+
+ TransitionNativeToVM transition(thread);
+ const Library& lib =
+ Library::CheckedHandle(thread->zone(), Api::UnwrapHandle(h_lib));
+ EXPECT(!lib.IsNull());
+
+ const Class& AInterface = Class::Handle(GetClass(lib, "AInterface"));
+ EXPECT_EQ(AInterface.implementor_cid(), kIllegalCid);
+
+ const Class& BInterface = Class::Handle(GetClass(lib, "BInterface"));
+ const Class& BImplementation =
+ Class::Handle(GetClass(lib, "BImplementation"));
+ EXPECT_EQ(BInterface.implementor_cid(), BImplementation.id());
+ EXPECT_EQ(BImplementation.implementor_cid(), BImplementation.id());
+
+ const Class& CInterface = Class::Handle(GetClass(lib, "CInterface"));
+ const Class& CImplementation1 =
+ Class::Handle(GetClass(lib, "CImplementation1"));
+ const Class& CImplementation2 =
+ Class::Handle(GetClass(lib, "CImplementation2"));
+ EXPECT_EQ(CInterface.implementor_cid(), kDynamicCid);
+ EXPECT_EQ(CImplementation1.implementor_cid(), CImplementation1.id());
+ EXPECT_EQ(CImplementation2.implementor_cid(), CImplementation2.id());
+
+ const Class& DInterface = Class::Handle(GetClass(lib, "DInterface"));
+ const Class& DSubinterface = Class::Handle(GetClass(lib, "DSubinterface"));
+ EXPECT_EQ(DInterface.implementor_cid(), kIllegalCid);
+ EXPECT_EQ(DSubinterface.implementor_cid(), kIllegalCid);
+
+ const Class& EInterface = Class::Handle(GetClass(lib, "EInterface"));
+ const Class& ESubinterface = Class::Handle(GetClass(lib, "ESubinterface"));
+ const Class& EImplementation =
+ Class::Handle(GetClass(lib, "EImplementation"));
+ EXPECT_EQ(EInterface.implementor_cid(), EImplementation.id());
+ EXPECT_EQ(ESubinterface.implementor_cid(), EImplementation.id());
+ EXPECT_EQ(EImplementation.implementor_cid(), EImplementation.id());
+
+ const Class& FInterface = Class::Handle(GetClass(lib, "FInterface"));
+ const Class& FSubinterface = Class::Handle(GetClass(lib, "FSubinterface"));
+ const Class& FImplementation1 =
+ Class::Handle(GetClass(lib, "FImplementation1"));
+ const Class& FImplementation2 =
+ Class::Handle(GetClass(lib, "FImplementation2"));
+ EXPECT_EQ(FInterface.implementor_cid(), kDynamicCid);
+ EXPECT_EQ(FSubinterface.implementor_cid(), kDynamicCid);
+ EXPECT_EQ(FImplementation1.implementor_cid(), FImplementation1.id());
+ EXPECT_EQ(FImplementation2.implementor_cid(), FImplementation2.id());
+}
+
ISOLATE_UNIT_TEST_CASE(MirrorReference) {
const MirrorReference& reference =
MirrorReference::Handle(MirrorReference::New(Object::Handle()));
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index b4fb7b6..7acfa30 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -1059,6 +1059,7 @@
NOT_IN_PRECOMPILED(TokenPosition token_pos_);
NOT_IN_PRECOMPILED(TokenPosition end_token_pos_);
+ NOT_IN_PRECOMPILED(classid_t implementor_cid_);
classid_t id_; // Class Id, also index in the class table.
int16_t num_type_arguments_; // Number of type arguments in flattened vector.
@@ -1099,6 +1100,7 @@
friend class InstanceSerializationCluster;
friend class TypeSerializationCluster;
friend class CidRewriteVisitor;
+ friend class FinalizeVMIsolateVisitor;
friend class Api;
};
diff --git a/sdk/lib/_internal/wasm/lib/symbol_patch.dart b/sdk/lib/_internal/wasm/lib/symbol_patch.dart
new file mode 100644
index 0000000..883847d
--- /dev/null
+++ b/sdk/lib/_internal/wasm/lib/symbol_patch.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2022, 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.
+
+// part of "internal_patch.dart";
+
+// TODO(49531): This file is nearly identical to the VM's
+// symbol_patch.dart, with the exception of the added pragma on `const Symbol`.
+// Unfortunately, adding this pragma to the VM's symbol_patch causes a
+// deadlock. When this bug is fixed we can share a patch file with the VM.
+
+@patch
+class Symbol {
+ // TODO(http://dartbug.com/46716): Recognize Symbol in the VM.
+ @patch
+ @pragma("wasm:entry-point")
+ const Symbol(String name) : this._name = name;
+
+ @patch
+ String toString() => 'Symbol("${computeUnmangledName(this)}")';
+
+ @patch
+ static String computeUnmangledName(Symbol symbol) {
+ String string = Symbol.getName(symbol);
+
+ // get:foo -> foo
+ // set:foo -> foo=
+ // get:_foo@xxx -> _foo
+ // set:_foo@xxx -> _foo=
+ // Class._constructor@xxx -> Class._constructor
+ // _Class@xxx._constructor@xxx -> _Class._constructor
+ // lib._S@xxx with lib._M1@xxx, lib._M2@xxx -> lib._S with lib._M1, lib._M2
+ StringBuffer result = new StringBuffer();
+ bool add_setter_suffix = false;
+ var pos = 0;
+ if (string.length >= 4 && string[3] == ':') {
+ // Drop 'get:' or 'set:' prefix.
+ pos = 4;
+ if (string[0] == 's') {
+ add_setter_suffix = true;
+ }
+ }
+ // Skip everything between AT and PERIOD, SPACE, COMMA or END
+ bool skip = false;
+ for (; pos < string.length; pos++) {
+ var char = string[pos];
+ if (char == '@') {
+ skip = true;
+ } else if (char == '.' || char == ' ' || char == ',') {
+ skip = false;
+ }
+ if (!skip) {
+ result.write(char);
+ }
+ }
+ if (add_setter_suffix) {
+ result.write('=');
+ }
+ return result.toString();
+ }
+
+ // Must be kept in sync with Symbol::CanonicalizeHash in object.cc.
+ @patch
+ int get hashCode {
+ const arbitraryPrime = 664597;
+ return 0x1fffffff & (arbitraryPrime * _name.hashCode);
+ }
+}
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index 9f93f8b..5107be5 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -168,7 +168,7 @@
"_internal/wasm/lib/class_id.dart",
"_internal/wasm/lib/patch.dart",
"_internal/wasm/lib/print_patch.dart",
- "_internal/vm/lib/symbol_patch.dart"
+ "_internal/wasm/lib/symbol_patch.dart"
]
},
"_js_helper": {
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index b1a0e70..f9f859e 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -165,7 +165,7 @@
- _internal/wasm/lib/class_id.dart
- _internal/wasm/lib/patch.dart
- _internal/wasm/lib/print_patch.dart
- - _internal/vm/lib/symbol_patch.dart
+ - _internal/wasm/lib/symbol_patch.dart
_js_helper:
uri: _internal/wasm/lib/js_helper.dart
async:
diff --git a/tools/VERSION b/tools/VERSION
index 2637c99..6112c90 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 19
PATCH 0
-PRERELEASE 36
+PRERELEASE 37
PRERELEASE_PATCH 0
\ No newline at end of file