Version 2.17.0-284.0.dev
Merge commit '1377e006fbe8d1e22177c92662a222a96098e62d' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 0b5e2e4..765df26 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -69,7 +69,7 @@
"name": "analysis_server",
"rootUri": "../pkg/analysis_server",
"packageUri": "lib/",
- "languageVersion": "2.14"
+ "languageVersion": "2.15"
},
{
"name": "analysis_server_client",
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 2eff1ad..2b8352b 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -16,21 +16,25 @@
import 'package:analysis_server/src/computer/computer_highlights.dart';
import 'package:analysis_server/src/context_manager.dart';
import 'package:analysis_server/src/domain_analysis.dart';
-import 'package:analysis_server/src/domain_analytics.dart';
import 'package:analysis_server/src/domain_completion.dart';
-import 'package:analysis_server/src/domain_diagnostic.dart';
-import 'package:analysis_server/src/domain_kythe.dart';
import 'package:analysis_server/src/domain_server.dart';
import 'package:analysis_server/src/domains/analysis/occurrences.dart';
import 'package:analysis_server/src/domains/analysis/occurrences_dart.dart';
import 'package:analysis_server/src/edit/edit_domain.dart';
import 'package:analysis_server/src/flutter/flutter_domain.dart';
import 'package:analysis_server/src/flutter/flutter_notifications.dart';
+import 'package:analysis_server/src/handler/legacy/analytics_enable.dart';
+import 'package:analysis_server/src/handler/legacy/analytics_is_enabled.dart';
+import 'package:analysis_server/src/handler/legacy/analytics_send_event.dart';
+import 'package:analysis_server/src/handler/legacy/analytics_send_timing.dart';
+import 'package:analysis_server/src/handler/legacy/diagnostic_get_diagnostics.dart';
+import 'package:analysis_server/src/handler/legacy/diagnostic_get_server_port.dart';
import 'package:analysis_server/src/handler/legacy/execution_create_context.dart';
import 'package:analysis_server/src/handler/legacy/execution_delete_context.dart';
import 'package:analysis_server/src/handler/legacy/execution_get_suggestions.dart';
import 'package:analysis_server/src/handler/legacy/execution_map_uri.dart';
import 'package:analysis_server/src/handler/legacy/execution_set_subscriptions.dart';
+import 'package:analysis_server/src/handler/legacy/kythe_get_kythe_entries.dart';
import 'package:analysis_server/src/handler/legacy/legacy_handler.dart';
import 'package:analysis_server/src/operation/operation_analysis.dart';
import 'package:analysis_server/src/plugin/notification_manager.dart';
@@ -81,16 +85,21 @@
/// A map from the name of a request to a function used to create a request
/// handler.
static final Map<String, HandlerGenerator> handlerGenerators = {
- EXECUTION_REQUEST_CREATE_CONTEXT: (server, request, cancellationToken) =>
- ExecutionCreateContextHandler(server, request, cancellationToken),
- EXECUTION_REQUEST_DELETE_CONTEXT: (server, request, cancellationToken) =>
- ExecutionDeleteContextHandler(server, request, cancellationToken),
- EXECUTION_REQUEST_GET_SUGGESTIONS: (server, request, cancellationToken) =>
- ExecutionGetSuggestionsHandler(server, request, cancellationToken),
- EXECUTION_REQUEST_MAP_URI: (server, request, cancellationToken) =>
- ExecutionMapUriHandler(server, request, cancellationToken),
- EXECUTION_REQUEST_SET_SUBSCRIPTIONS: (server, request, cancellationToken) =>
- ExecutionSetSubscriptionsHandler(server, request, cancellationToken),
+ ANALYTICS_REQUEST_IS_ENABLED: AnalyticsIsEnabledHandler.new,
+ ANALYTICS_REQUEST_ENABLE: AnalyticsEnableHandler.new,
+ ANALYTICS_REQUEST_SEND_EVENT: AnalyticsSendEventHandler.new,
+ ANALYTICS_REQUEST_SEND_TIMING: AnalyticsSendTimingHandler.new,
+ //
+ DIAGNOSTIC_REQUEST_GET_DIAGNOSTICS: DiagnosticGetDiagnosticsHandler.new,
+ DIAGNOSTIC_REQUEST_GET_SERVER_PORT: DiagnosticGetServerPortHandler.new,
+ //
+ EXECUTION_REQUEST_CREATE_CONTEXT: ExecutionCreateContextHandler.new,
+ EXECUTION_REQUEST_DELETE_CONTEXT: ExecutionDeleteContextHandler.new,
+ EXECUTION_REQUEST_GET_SUGGESTIONS: ExecutionGetSuggestionsHandler.new,
+ EXECUTION_REQUEST_MAP_URI: ExecutionMapUriHandler.new,
+ EXECUTION_REQUEST_SET_SUBSCRIPTIONS: ExecutionSetSubscriptionsHandler.new,
+ //
+ KYTHE_REQUEST_GET_KYTHE_ENTRIES: KytheGetKytheEntriesHandler.new,
};
/// The channel from which requests are received and to which responses should
@@ -248,9 +257,6 @@
EditDomainHandler(this),
SearchDomainHandler(this),
CompletionDomainHandler(this),
- DiagnosticDomainHandler(this),
- AnalyticsDomainHandler(this),
- KytheDomainHandler(this),
FlutterDomainHandler(this)
];
}
diff --git a/pkg/analysis_server/lib/src/domain_analytics.dart b/pkg/analysis_server/lib/src/domain_analytics.dart
deleted file mode 100644
index caebdc3..0000000
--- a/pkg/analysis_server/lib/src/domain_analytics.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analysis_server/protocol/protocol.dart';
-import 'package:analysis_server/protocol/protocol_constants.dart';
-import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/handler/legacy/analytics_enable.dart';
-import 'package:analysis_server/src/handler/legacy/analytics_is_enabled.dart';
-import 'package:analysis_server/src/handler/legacy/analytics_send_event.dart';
-import 'package:analysis_server/src/handler/legacy/analytics_send_timing.dart';
-import 'package:analyzer/src/utilities/cancellation.dart';
-
-/// Instances of the class [AnalyticsDomainHandler] implement a [RequestHandler]
-/// that handles requests in the `analytics` domain.
-class AnalyticsDomainHandler implements RequestHandler {
- final AnalysisServer server;
-
- AnalyticsDomainHandler(this.server);
-
- @override
- Response? handleRequest(
- Request request, CancellationToken cancellationToken) {
- var requestName = request.method;
-
- if (requestName == ANALYTICS_REQUEST_IS_ENABLED) {
- AnalyticsIsEnabledHandler(server, request, cancellationToken).handle();
- return Response.DELAYED_RESPONSE;
- } else if (requestName == ANALYTICS_REQUEST_ENABLE) {
- AnalyticsEnableHandler(server, request, cancellationToken).handle();
- return Response.DELAYED_RESPONSE;
- } else if (requestName == ANALYTICS_REQUEST_SEND_EVENT) {
- AnalyticsSendEventHandler(server, request, cancellationToken).handle();
- return Response.DELAYED_RESPONSE;
- } else if (requestName == ANALYTICS_REQUEST_SEND_TIMING) {
- AnalyticsSendTimingHandler(server, request, cancellationToken).handle();
- return Response.DELAYED_RESPONSE;
- }
- return null;
- }
-}
diff --git a/pkg/analysis_server/lib/src/domain_diagnostic.dart b/pkg/analysis_server/lib/src/domain_diagnostic.dart
deleted file mode 100644
index e3d2eb8..0000000
--- a/pkg/analysis_server/lib/src/domain_diagnostic.dart
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analysis_server/protocol/protocol.dart';
-import 'package:analysis_server/protocol/protocol_constants.dart';
-import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/handler/legacy/diagnostic_get_diagnostics.dart';
-import 'package:analysis_server/src/handler/legacy/diagnostic_get_server_port.dart';
-import 'package:analyzer/src/utilities/cancellation.dart';
-
-/// Instances of the class [DiagnosticDomainHandler] implement a
-/// [RequestHandler] that handles requests in the `diagnostic` domain.
-class DiagnosticDomainHandler implements RequestHandler {
- /// The analysis server that is using this handler to process requests.
- final AnalysisServer server;
-
- /// Initialize a newly created handler to handle requests for the given
- /// [server].
- DiagnosticDomainHandler(this.server);
-
- @override
- Response? handleRequest(
- Request request, CancellationToken cancellationToken) {
- try {
- var requestName = request.method;
- if (requestName == DIAGNOSTIC_REQUEST_GET_DIAGNOSTICS) {
- DiagnosticGetDiagnosticsHandler(server, request, cancellationToken)
- .handle();
- return Response.DELAYED_RESPONSE;
- } else if (requestName == DIAGNOSTIC_REQUEST_GET_SERVER_PORT) {
- DiagnosticGetServerPortHandler(server, request, cancellationToken)
- .handle();
- return Response.DELAYED_RESPONSE;
- }
- } on RequestFailure catch (exception) {
- return exception.response;
- }
- return null;
- }
-}
diff --git a/pkg/analysis_server/lib/src/domain_kythe.dart b/pkg/analysis_server/lib/src/domain_kythe.dart
deleted file mode 100644
index 9b62c45..0000000
--- a/pkg/analysis_server/lib/src/domain_kythe.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analysis_server/protocol/protocol.dart';
-import 'package:analysis_server/protocol/protocol_constants.dart';
-import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/domain_abstract.dart';
-import 'package:analysis_server/src/handler/legacy/kythe_get_kythe_entries.dart';
-import 'package:analyzer/src/utilities/cancellation.dart';
-
-/// Instances of the class [KytheDomainHandler] implement a [RequestHandler]
-/// that handles requests in the `kythe` domain.
-class KytheDomainHandler extends AbstractRequestHandler {
- /// Initialize a newly created handler to handle requests for the given
- /// [server].
- KytheDomainHandler(AnalysisServer server) : super(server);
-
- @override
- Response? handleRequest(
- Request request, CancellationToken cancellationToken) {
- try {
- var requestName = request.method;
- if (requestName == KYTHE_REQUEST_GET_KYTHE_ENTRIES) {
- KytheGetKytheEntriesHandler(server, request, cancellationToken)
- .handle();
- return Response.DELAYED_RESPONSE;
- }
- } on RequestFailure catch (exception) {
- return exception.response;
- }
- return null;
- }
-}
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
index 5f62d61..e1680a0 100644
--- a/pkg/analysis_server/pubspec.yaml
+++ b/pkg/analysis_server/pubspec.yaml
@@ -3,7 +3,7 @@
publish_to: none
environment:
- sdk: '>=2.14.0 <3.0.0'
+ sdk: '>=2.15.0 <3.0.0'
dependencies:
_fe_analyzer_shared:
diff --git a/pkg/analysis_server/test/domain_diagnostic_test.dart b/pkg/analysis_server/test/domain_diagnostic_test.dart
index 13b5829..dd79a90 100644
--- a/pkg/analysis_server/test/domain_diagnostic_test.dart
+++ b/pkg/analysis_server/test/domain_diagnostic_test.dart
@@ -3,7 +3,6 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analysis_server/protocol/protocol_generated.dart';
-import 'package:analysis_server/src/domain_diagnostic.dart';
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -17,13 +16,6 @@
@reflectiveTest
class DiagnosticDomainTest extends AbstractAnalysisTest {
- @override
- void setUp() {
- super.setUp();
- handler = DiagnosticDomainHandler(server);
- server.handlers = [handler];
- }
-
Future<void> test_getDiagnostics() async {
newPubspecYamlFile('/project', 'name: project');
newFile2('/project/bin/test.dart', 'main() {}');
diff --git a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
index c09c72e..2f6f70b 100644
--- a/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/lsp_server/integration_tests.dart
@@ -150,7 +150,8 @@
var dartBinary = join(dartSdkPath, 'bin', 'dart');
- var useSnapshot = true;
+ // Prevent flow analysis from marking code below as being dead.
+ const useSnapshot = 1 > 0;
String serverPath;
if (useSnapshot) {
diff --git a/pkg/analysis_server/test/integration/support/integration_tests.dart b/pkg/analysis_server/test/integration/support/integration_tests.dart
index ceb7185..7c9fd4c 100644
--- a/pkg/analysis_server/test/integration/support/integration_tests.dart
+++ b/pkg/analysis_server/test/integration/support/integration_tests.dart
@@ -622,9 +622,8 @@
var dartBinary = path.join(dartSdkPath, 'bin', 'dart');
- // The integration tests run 3x faster when run from snapshots (you need to
- // run test.py with --use-sdk).
- var useSnapshot = true;
+ // Prevent flow analysis from marking code below as being dead.
+ const useSnapshot = 1 > 0;
String serverPath;
if (useSnapshot) {
diff --git a/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart b/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
index cd03107..9451d5c 100644
--- a/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
+++ b/pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
@@ -106,7 +106,7 @@
Reference.root(),
);
- var linkResult = await link2(elementFactory, inputLibraries);
+ var linkResult = await link(elementFactory, inputLibraries);
var bundleBuilder = PackageBundleBuilder();
for (var library in inputLibraries) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 56950bb..695ffbf 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -83,7 +83,7 @@
/// TODO(scheglov) Clean up the list of implicitly analyzed files.
class AnalysisDriver implements AnalysisDriverGeneric {
/// The version of data format, should be incremented on every format change.
- static const int DATA_VERSION = 212;
+ static const int DATA_VERSION = 213;
/// The number of exception contexts allowed to write. Once this field is
/// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index fa6f1f2..96dcbb7 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -20,7 +20,7 @@
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/summary2/bundle_reader.dart';
-import 'package:analyzer/src/summary2/link.dart' as link2;
+import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/macro.dart';
import 'package:analyzer/src/summary2/reference.dart';
@@ -164,11 +164,11 @@
timerInputLibraries.start();
inputsTimer.start();
- var inputLibraries = <link2.LinkInputLibrary>[];
+ var inputLibraries = <LinkInputLibrary>[];
for (var libraryFile in cycle.libraries) {
var librarySource = libraryFile.source;
- var inputUnits = <link2.LinkInputUnit>[];
+ var inputUnits = <LinkInputUnit>[];
var partIndex = -1;
for (var file in libraryFile.libraryFiles) {
var isSynthetic = !file.exists;
@@ -181,7 +181,7 @@
partIndex++;
inputUnits.add(
- link2.LinkInputUnit(
+ LinkInputUnit(
// TODO(scheglov) bad, group part data
partDirectiveIndex: partIndex - 1,
partUriStr: partUriStr,
@@ -194,7 +194,7 @@
}
inputLibraries.add(
- link2.LinkInputLibrary(
+ LinkInputLibrary(
source: librarySource,
units: inputUnits,
),
@@ -203,12 +203,10 @@
inputsTimer.stop();
timerInputLibraries.stop();
- link2.LinkResult linkResult;
+ LinkResult linkResult;
try {
timerLinking.start();
- // TODO(scheglov) Migrate when we are ready to switch to async.
- // ignore: deprecated_member_use_from_same_package
- linkResult = await link2.link2(elementFactory, inputLibraries);
+ linkResult = await link(elementFactory, inputLibraries);
librariesLinked += cycle.libraries.length;
counterLinkedLibraries += inputLibraries.length;
timerLinking.stop();
diff --git a/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart b/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart
index 1658a93..e1f1f9e 100644
--- a/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/unlinked_api_signature.dart
@@ -6,8 +6,10 @@
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/src/dart/ast/invokes_super_self.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/summary/api_signature.dart';
+import 'package:collection/collection.dart';
/// Return the bytes of the unlinked API signature of the given [unit].
///
@@ -39,6 +41,10 @@
for (var declaration in unit.declarations) {
if (declaration is ClassOrMixinDeclaration) {
_addClassOrMixin(declaration);
+ } else if (declaration is EnumDeclaration) {
+ _addEnum(declaration);
+ } else if (declaration is ExtensionDeclaration) {
+ _addExtension(declaration);
} else if (declaration is FunctionDeclaration) {
var functionExpression = declaration.functionExpression;
_addTokens(
@@ -54,36 +60,70 @@
}
}
+ void _addClassMembers(List<ClassMember> members, bool hasConstConstructor) {
+ signature.addInt(members.length);
+ for (var member in members) {
+ if (member is ConstructorDeclaration) {
+ _addConstructorDeclaration(member);
+ } else if (member is FieldDeclaration) {
+ _addFieldDeclaration(member, hasConstConstructor);
+ } else if (member is MethodDeclaration) {
+ _addMethodDeclaration(member);
+ } else {
+ throw UnimplementedError('(${member.runtimeType}) $member');
+ }
+ }
+ }
+
void _addClassOrMixin(ClassOrMixinDeclaration node) {
_addTokens(node.beginToken, node.leftBracket);
bool hasConstConstructor = node.members
.any((m) => m is ConstructorDeclaration && m.constKeyword != null);
- signature.addInt(node.members.length);
- for (var member in node.members) {
- if (member is ConstructorDeclaration) {
- signature.addInt(_kindConstructorDeclaration);
- _addTokens(member.beginToken, member.parameters.endToken);
- _addNodeList(member.initializers);
- _addNode(member.redirectedConstructor);
- } else if (member is FieldDeclaration) {
- signature.addInt(_kindFieldDeclaration);
- _fieldDeclaration(member, hasConstConstructor);
- } else if (member is MethodDeclaration) {
- signature.addInt(_kindMethodDeclaration);
- _addTokens(
- member.beginToken,
- (member.parameters ?? member.name).endToken,
- );
- signature.addBool(member.body is EmptyFunctionBody);
- _addFunctionBodyModifiers(member.body);
- } else {
- throw UnimplementedError('(${member.runtimeType}) $member');
- }
+ _addClassMembers(node.members, hasConstConstructor);
+ }
+
+ void _addConstructorDeclaration(ConstructorDeclaration node) {
+ signature.addInt(_kindConstructorDeclaration);
+ _addTokens(node.beginToken, node.parameters.endToken);
+ _addNodeList(node.initializers);
+ _addNode(node.redirectedConstructor);
+ }
+
+ void _addEnum(EnumDeclaration node) {
+ var members = node.members;
+
+ // If not enhanced, include the whole node.
+ var firstMember = members.firstOrNull;
+ if (firstMember == null) {
+ _addNode(node);
+ return;
}
- _addToken(node.rightBracket);
+ _addTokens(node.beginToken, firstMember.beginToken);
+ _addClassMembers(members, true);
+ }
+
+ void _addExtension(ExtensionDeclaration node) {
+ _addTokens(node.beginToken, node.leftBracket);
+ _addClassMembers(node.members, false);
+ }
+
+ void _addFieldDeclaration(FieldDeclaration node, bool hasConstConstructor) {
+ signature.addInt(_kindFieldDeclaration);
+
+ _addToken(node.abstractKeyword);
+ _addToken(node.covariantKeyword);
+ _addToken(node.externalKeyword);
+ _addToken(node.staticKeyword);
+ _addNodeList(node.metadata);
+
+ var variableList = node.fields;
+ var includeInitializers = variableList.type == null ||
+ variableList.isConst ||
+ hasConstConstructor && !node.isStatic && variableList.isFinal;
+ _variableList(variableList, includeInitializers);
}
void _addFunctionBodyModifiers(FunctionBody? node) {
@@ -93,6 +133,17 @@
}
}
+ void _addMethodDeclaration(MethodDeclaration node) {
+ signature.addInt(_kindMethodDeclaration);
+ _addTokens(
+ node.beginToken,
+ (node.parameters ?? node.name).endToken,
+ );
+ signature.addBool(node.body is EmptyFunctionBody);
+ _addFunctionBodyModifiers(node.body);
+ signature.addBool(node.invokesSuperSelf);
+ }
+
void _addNode(AstNode? node) {
if (node != null) {
signature.addInt(_notNullNode);
@@ -142,20 +193,6 @@
}
}
- void _fieldDeclaration(FieldDeclaration node, bool hasConstConstructor) {
- _addToken(node.abstractKeyword);
- _addToken(node.covariantKeyword);
- _addToken(node.externalKeyword);
- _addToken(node.staticKeyword);
- _addNodeList(node.metadata);
-
- var variableList = node.fields;
- var includeInitializers = variableList.type == null ||
- variableList.isConst ||
- hasConstConstructor && !node.isStatic && variableList.isFinal;
- _variableList(variableList, includeInitializers);
- }
-
void _topLevelVariableDeclaration(TopLevelVariableDeclaration node) {
_addToken(node.externalKeyword);
_addNodeList(node.metadata);
diff --git a/pkg/analyzer/lib/src/dart/ast/invokes_super_self.dart b/pkg/analyzer/lib/src/dart/ast/invokes_super_self.dart
new file mode 100644
index 0000000..76d4b1d
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/ast/invokes_super_self.dart
@@ -0,0 +1,62 @@
+// 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.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+
+class _SuperVisitor extends RecursiveAstVisitor<void> {
+ final String name;
+
+ /// Set to `true` if a super invocation with the [name] is found.
+ bool hasSuperInvocation = false;
+
+ _SuperVisitor(this.name);
+
+ @override
+ void visitAssignmentExpression(AssignmentExpression node) {
+ var left = node.leftHandSide;
+ if (left is PropertyAccess) {
+ if (left.target is SuperExpression && left.propertyName.name == name) {
+ hasSuperInvocation = true;
+ return;
+ }
+ }
+ super.visitAssignmentExpression(node);
+ }
+
+ @override
+ void visitBinaryExpression(BinaryExpression node) {
+ if (node.leftOperand is SuperExpression && node.operator.lexeme == name) {
+ hasSuperInvocation = true;
+ return;
+ }
+ super.visitBinaryExpression(node);
+ }
+
+ @override
+ void visitMethodInvocation(MethodInvocation node) {
+ if (node.target is SuperExpression && node.methodName.name == name) {
+ hasSuperInvocation = true;
+ return;
+ }
+ super.visitMethodInvocation(node);
+ }
+
+ @override
+ void visitPropertyAccess(PropertyAccess node) {
+ if (node.target is SuperExpression && node.propertyName.name == name) {
+ hasSuperInvocation = true;
+ return;
+ }
+ super.visitPropertyAccess(node);
+ }
+}
+
+extension MethodDeclarationExtension on MethodDeclaration {
+ bool get invokesSuperSelf {
+ var visitor = _SuperVisitor(name.name);
+ body.accept(visitor);
+ return visitor.hasSuperInvocation;
+ }
+}
diff --git a/pkg/analyzer/lib/src/dart/ast/mixin_super_invoked_names.dart b/pkg/analyzer/lib/src/dart/ast/mixin_super_invoked_names.dart
index b96dfe5..228c1d7 100644
--- a/pkg/analyzer/lib/src/dart/ast/mixin_super_invoked_names.dart
+++ b/pkg/analyzer/lib/src/dart/ast/mixin_super_invoked_names.dart
@@ -1,3 +1,7 @@
+// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
diff --git a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
index 5670310..989c73c 100644
--- a/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
+++ b/pkg/analyzer/lib/src/dart/micro/resolve_file.dart
@@ -30,7 +30,7 @@
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary2/bundle_reader.dart';
-import 'package:analyzer/src/summary2/link.dart' as link2;
+import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/reference.dart';
import 'package:analyzer/src/task/options.dart';
@@ -844,11 +844,11 @@
librariesLinkedTimer.start();
inputsTimer.start();
- var inputLibraries = <link2.LinkInputLibrary>[];
+ var inputLibraries = <LinkInputLibrary>[];
for (var libraryFile in cycle.libraries) {
var librarySource = libraryFile.source;
- var inputUnits = <link2.LinkInputUnit>[];
+ var inputUnits = <LinkInputUnit>[];
var partIndex = -1;
for (var file in libraryFile.files().ofLibrary) {
var isSynthetic = !file.exists;
@@ -869,7 +869,7 @@
partIndex++;
inputUnits.add(
- link2.LinkInputUnit(
+ LinkInputUnit(
// TODO(scheglov) bad, group part data
partDirectiveIndex: partIndex - 1,
partUriStr: partUriStr,
@@ -881,7 +881,7 @@
}
inputLibraries.add(
- link2.LinkInputLibrary(
+ LinkInputLibrary(
source: librarySource,
units: inputUnits,
),
@@ -889,7 +889,7 @@
}
inputsTimer.stop();
- var linkResult = await link2.link2(elementFactory, inputLibraries);
+ var linkResult = await link(elementFactory, inputLibraries);
librariesLinked += cycle.libraries.length;
resolutionBytes = linkResult.resolutionBytes;
diff --git a/pkg/analyzer/lib/src/error/must_call_super_verifier.dart b/pkg/analyzer/lib/src/error/must_call_super_verifier.dart
index 0cb76fe..810758d 100644
--- a/pkg/analyzer/lib/src/error/must_call_super_verifier.dart
+++ b/pkg/analyzer/lib/src/error/must_call_super_verifier.dart
@@ -5,9 +5,9 @@
import 'dart:collection';
import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/dart/ast/invokes_super_self.dart';
import 'package:analyzer/src/dart/error/hint_codes.dart';
class MustCallSuperVerifier {
@@ -133,9 +133,7 @@
void _verifySuperIsCalled(MethodDeclaration node, String methodName,
String? overriddenEnclosingName) {
- _SuperCallVerifier verifier = _SuperCallVerifier(methodName);
- node.accept(verifier);
- if (!verifier.superIsCalled) {
+ if (!node.invokesSuperSelf) {
// Overridable elements are always enclosed in named elements, so it is
// safe to assume [overriddenEnclosingName] is non-`null`.
_errorReporter.reportErrorForNode(
@@ -144,51 +142,3 @@
return;
}
}
-
-/// Recursively visits an AST, looking for method invocations.
-class _SuperCallVerifier extends RecursiveAstVisitor<void> {
- bool superIsCalled = false;
-
- final String name;
-
- _SuperCallVerifier(this.name);
-
- @override
- void visitAssignmentExpression(AssignmentExpression node) {
- var lhs = node.leftHandSide;
- if (lhs is PropertyAccess) {
- if (lhs.target is SuperExpression && lhs.propertyName.name == name) {
- superIsCalled = true;
- return;
- }
- }
- super.visitAssignmentExpression(node);
- }
-
- @override
- void visitBinaryExpression(BinaryExpression node) {
- if (node.leftOperand is SuperExpression && node.operator.lexeme == name) {
- superIsCalled = true;
- return;
- }
- super.visitBinaryExpression(node);
- }
-
- @override
- void visitMethodInvocation(MethodInvocation node) {
- if (node.target is SuperExpression && node.methodName.name == name) {
- superIsCalled = true;
- return;
- }
- super.visitMethodInvocation(node);
- }
-
- @override
- void visitPropertyAccess(PropertyAccess node) {
- if (node.target is SuperExpression && node.propertyName.name == name) {
- superIsCalled = true;
- return;
- }
- super.visitPropertyAccess(node);
- }
-}
diff --git a/pkg/analyzer/lib/src/summary2/link.dart b/pkg/analyzer/lib/src/summary2/link.dart
index 8cd98a7..b76283b 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -26,7 +26,7 @@
var timerLinkingLinkingBundle = Stopwatch();
/// Note that AST units and tokens of [inputLibraries] will be damaged.
-Future<LinkResult> link2(
+Future<LinkResult> link(
LinkedElementFactory elementFactory,
List<LinkInputLibrary> inputLibraries,
) async {
@@ -37,6 +37,15 @@
);
}
+/// Note that AST units and tokens of [inputLibraries] will be damaged.
+@Deprecated('Use link() instead')
+Future<LinkResult> link2(
+ LinkedElementFactory elementFactory,
+ List<LinkInputLibrary> inputLibraries,
+) async {
+ return link(elementFactory, inputLibraries);
+}
+
class Linker {
final LinkedElementFactory elementFactory;
diff --git a/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
index 64302a5..082f9c0 100644
--- a/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/unlinked_api_signature_test.dart
@@ -304,6 +304,14 @@
''');
}
+ test_class_field_withType_final_noConstConstructor() {
+ _assertSameSignature(r'''
+final int a = 1;
+''', r'''
+final int a = 2;
+''');
+ }
+
test_class_field_withType_hasConstConstructor() {
_assertSameSignature(r'''
class C {
@@ -449,11 +457,80 @@
''');
}
- test_classLike_field_withType_final_noConstConstructor() {
+ test_classLike_method_body_block_invokesSuperSelf_false_differentName() {
_assertSameSignature_classLike(r'''
-final int a = 1;
+void foo() {
+ super.bar();
+}
''', r'''
-final int a = 2;
+void foo() {
+ super.bar2();
+}
+''');
+ }
+
+ test_classLike_method_body_block_invokesSuperSelf_falseToTrue() {
+ _assertNotSameSignature_classLike(r'''
+void foo() {}
+''', r'''
+void foo() {
+ super.foo();
+}
+''');
+ }
+
+ test_classLike_method_body_block_invokesSuperSelf_trueToFalse_assignmentExpression() {
+ _assertNotSameSignature_classLike(r'''
+void foo() {
+ super.foo = 0;
+}
+''', r'''
+void foo() {}
+''');
+ }
+
+ test_classLike_method_body_block_invokesSuperSelf_trueToFalse_binaryExpression() {
+ _assertNotSameSignature_classLike(r'''
+int operator +() {
+ super + 2;
+ return 0;
+}
+''', r'''
+int operator +() {
+ return 0;
+}
+''');
+ }
+
+ test_classLike_method_body_block_invokesSuperSelf_trueToFalse_differentName() {
+ _assertNotSameSignature_classLike(r'''
+void foo() {
+ super.foo();
+}
+''', r'''
+void foo() {
+ super.bar();
+}
+''');
+ }
+
+ test_classLike_method_body_block_invokesSuperSelf_trueToFalse_methodInvocation() {
+ _assertNotSameSignature_classLike(r'''
+void foo() {
+ super.foo();
+}
+''', r'''
+void foo() {}
+''');
+ }
+
+ test_classLike_method_body_block_invokesSuperSelf_trueToFalse_propertyAccess() {
+ _assertNotSameSignature_classLike(r'''
+void foo() {
+ super.foo;
+}
+''', r'''
+void foo() {}
''');
}
@@ -481,6 +558,14 @@
''');
}
+ test_classLike_method_body_expression_invokesSuperSelf_trueToFalse_methodInvocation() {
+ _assertNotSameSignature_classLike(r'''
+void foo() => super.foo();
+''', r'''
+void foo() => 0;
+''');
+ }
+
test_classLike_method_getter_body_block_to_empty() {
_assertNotSameSignature_classLike(r'''
int get foo {
@@ -619,6 +704,249 @@
''');
}
+ test_enum_enumConstants_add() {
+ _assertNotSameSignature(r'''
+enum E {
+ v
+}
+''', r'''
+enum E {
+ v, v2
+}
+''');
+ }
+
+ test_enum_enumConstants_add_hasMethod() {
+ _assertNotSameSignature(r'''
+enum E {
+ v;
+ void foo() {}
+}
+''', r'''
+enum E {
+ v, v2;
+ void foo() {}
+}
+''');
+ }
+
+ test_enum_enumConstants_constructorArguments_add() {
+ _assertNotSameSignature(r'''
+enum E {
+ v;
+ E({int? a});
+}
+''', r'''
+enum E {
+ v(a: 0);
+ E({int? a});
+}
+''');
+ }
+
+ test_enum_enumConstants_constructorArguments_change() {
+ _assertNotSameSignature(r'''
+enum E {
+ v(0);
+ E(int a);
+}
+''', r'''
+enum E {
+ v(1);
+ E(int a);
+}
+''');
+ }
+
+ test_enum_enumConstants_constructorArguments_remove() {
+ _assertNotSameSignature(r'''
+enum E {
+ v(a: 0);
+ E({int? a});
+}
+''', r'''
+enum E {
+ v;
+ E({int? a});
+}
+''');
+ }
+
+ test_enum_enumConstants_remove() {
+ _assertNotSameSignature(r'''
+enum E {
+ v, v2
+}
+''', r'''
+enum E {
+ v
+}
+''');
+ }
+
+ test_enum_enumConstants_rename() {
+ _assertNotSameSignature(r'''
+enum E {
+ v
+}
+''', r'''
+enum E {
+ v2
+}
+''');
+ }
+
+ test_enum_field_withType_final() {
+ _assertNotSameSignature(r'''
+enum E {
+ v;
+ final int a = 1;
+}
+''', r'''
+enum E {
+ v;
+ final int a = 2;
+}
+''');
+ }
+
+ test_enum_implements_add() {
+ _assertNotSameSignature(r'''
+class A {}
+enum E {
+ v
+}
+''', r'''
+class A {}
+enum E implements A {
+ v
+}
+''');
+ }
+
+ test_enum_implements_change() {
+ _assertNotSameSignature(r'''
+class A {}
+class B {}
+enum E implements A {
+ v
+}
+''', r'''
+class A {}
+class B {}
+enum E implements B {
+ v
+}
+''');
+ }
+
+ test_enum_implements_remove() {
+ _assertNotSameSignature(r'''
+class A {}
+enum E implements A {
+ v
+}
+''', r'''
+class A {}
+enum E {
+ v
+}
+''');
+ }
+
+ test_enum_metadata_add() {
+ _assertNotSameSignature(r'''
+enum E {
+ v
+}
+''', r'''
+@a
+enum E {
+ v
+}
+''');
+ }
+
+ test_enum_typeParameters_add() {
+ _assertNotSameSignature(r'''
+enum E {
+ v
+}
+''', r'''
+enum E<T> {
+ v
+}
+''');
+ }
+
+ test_enum_typeParameters_remove() {
+ _assertNotSameSignature(r'''
+enum E<T> {
+ v
+}
+''', r'''
+enum E {
+ v
+}
+''');
+ }
+
+ test_enum_typeParameters_rename() {
+ _assertNotSameSignature(r'''
+enum E<T> {
+ v
+}
+''', r'''
+enum E<U> {
+ v
+}
+''');
+ }
+
+ test_enum_with_add() {
+ _assertNotSameSignature(r'''
+mixin M {}
+enum E {
+ v
+}
+''', r'''
+mixin M {}
+enum E with M {
+ v
+}
+''');
+ }
+
+ test_enum_with_change() {
+ _assertNotSameSignature(r'''
+mixin M1 {}
+mixin M2 {}
+enum E with M1 {
+ v
+}
+''', r'''
+mixin M1 {}
+mixin M2 {}
+enum E with M2 {
+ v
+}
+''');
+ }
+
+ test_enum_with_remove() {
+ _assertNotSameSignature(r'''
+mixin M {}
+enum E with M {
+ v
+}
+''', r'''
+mixin M {}
+enum E {
+ v
+}
+''');
+ }
+
test_executable_annotation() {
_assertNotSameSignature_executable(r'''
void foo() {}
@@ -808,6 +1136,38 @@
''');
}
+ test_extension_on() {
+ _assertNotSameSignature(r'''
+extension E on int {}
+''', r'''
+extension E on num {}
+''');
+ }
+
+ test_extension_typeParameter_add() {
+ _assertNotSameSignature(r'''
+extension E on int {}
+''', r'''
+extension E<T> on int {}
+''');
+ }
+
+ test_extension_typeParameter_remove() {
+ _assertNotSameSignature(r'''
+extension E<T> on int {}
+''', r'''
+extension E on int {}
+''');
+ }
+
+ test_extension_typeParameter_rename() {
+ _assertNotSameSignature(r'''
+extension E<T> on int {}
+''', r'''
+extension E<U> on int {}
+''');
+ }
+
test_featureSet_add() async {
_assertNotSameSignature(r'''
class A {}
@@ -1064,6 +1424,16 @@
''', same: same);
_assertSignature('''
+extension on int {
+$oldCode
+}
+''', '''
+extension on int {
+$newCode
+}
+''', same: same);
+
+ _assertSignature('''
mixin M {
$oldCode
}
@@ -1072,6 +1442,18 @@
$newCode
}
''', same: same);
+
+ _assertSignature('''
+enum E {
+ v;
+$oldCode
+}
+''', '''
+enum E {
+ v;
+$newCode
+}
+''', same: same);
}
void _assertSignature_executable(String oldCode, String newCode,
diff --git a/pkg/analyzer/test/src/summary/elements_base.dart b/pkg/analyzer/test/src/summary/elements_base.dart
index fb702f8..f3d2095 100644
--- a/pkg/analyzer/test/src/summary/elements_base.dart
+++ b/pkg/analyzer/test/src/summary/elements_base.dart
@@ -102,7 +102,7 @@
Reference.root(),
);
- var sdkLinkResult = await link2(elementFactory, inputLibraries);
+ var sdkLinkResult = await link(elementFactory, inputLibraries);
return _sdkBundle = _SdkBundle(
resolutionBytes: sdkLinkResult.resolutionBytes,
@@ -160,7 +160,7 @@
),
);
- var linkResult = await link2(elementFactory, inputLibraries);
+ var linkResult = await link(elementFactory, inputLibraries);
if (!keepLinkingLibraries) {
elementFactory.removeBundle(
diff --git a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
index a323582..c6fde24 100644
--- a/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
+++ b/runtime/bin/ffi_test/ffi_test_functions_vmspecific.cc
@@ -185,7 +185,10 @@
// Clobbers some registers with special meaning in Dart before re-entry, for
// stress-testing. Not used on 32-bit Windows due to complications with Windows
// "safeseh".
-#if defined(DART_TARGET_OS_WINDOWS) && defined(HOST_ARCH_IA32)
+// TODO(47824): Figure out how ARM/ARM64 syntax is different on Windows.
+#if defined(DART_TARGET_OS_WINDOWS) && \
+ (defined(HOST_ARCH_IA32) || defined(HOST_ARCH_ARM) || \
+ defined(HOST_ARCH_ARM64))
void ClobberAndCall(void (*fn)()) {
fn();
}
diff --git a/runtime/third_party/double-conversion/src/utils.h b/runtime/third_party/double-conversion/src/utils.h
index c419a6c..fe3e359 100644
--- a/runtime/third_party/double-conversion/src/utils.h
+++ b/runtime/third_party/double-conversion/src/utils.h
@@ -67,16 +67,22 @@
// the output of the division with the expected result. (Inlining must be
// disabled.)
// On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
-#if defined(_M_X64) || defined(__x86_64__) || defined(__ARMEL__) || \
- defined(__avr32__) || defined(__hppa__) || defined(__ia64__) || \
- defined(__mips__) || defined(__powerpc__) || defined(__ppc__) || \
- defined(__ppc64__) || defined(_POWER) || defined(_ARCH_PPC) || \
- defined(_ARCH_PPC64) || defined(__sparc__) || defined(__sparc) || \
- defined(__s390__) || defined(__SH4__) || defined(__alpha__) || \
- defined(_MIPS_ARCH_MIPS32R2) || defined(__AARCH64EL__) || \
- defined(__aarch64__) || defined(__riscv)
+#if defined(_M_X64) || defined(__x86_64__) || \
+ defined(__ARMEL__) || defined(__avr32__) || defined(_M_ARM) || defined(_M_ARM64) || \
+ defined(__hppa__) || defined(__ia64__) || \
+ defined(__mips__) || \
+ defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
+ defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
+ defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
+ defined(__SH4__) || defined(__alpha__) || \
+ defined(_MIPS_ARCH_MIPS32R2) || \
+ defined(__AARCH64EL__) || defined(__aarch64__) || defined(__AARCH64EB__) || \
+ defined(__riscv) || \
+ defined(__or1k__) || defined(__arc__) || \
+ defined(__EMSCRIPTEN__)
#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
-#elif defined(__mc68000__)
+#elif defined(__mc68000__) || \
+ defined(__pnacl__) || defined(__native_client__)
#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
#elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
#if defined(_WIN32)
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index 795745a..bca236c 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -271,7 +271,7 @@
EmitType01(cond, o.type(), BIC, 1, rn, rd, o);
}
-void Assembler::mvn(Register rd, Operand o, Condition cond) {
+void Assembler::mvn_(Register rd, Operand o, Condition cond) {
EmitType01(cond, o.type(), MVN, 0, R0, rd, o);
}
@@ -2779,7 +2779,7 @@
if (Operand::CanHold(value, &o)) {
mov(rd, o, cond);
} else if (Operand::CanHold(~value, &o)) {
- mvn(rd, o, cond);
+ mvn_(rd, o, cond);
} else {
LoadDecodableImmediate(rd, value, cond);
}
@@ -3072,10 +3072,10 @@
} else {
ASSERT(rn != IP);
if (Operand::CanHold(~value, &o)) {
- mvn(IP, o, cond);
+ mvn_(IP, o, cond);
add(rd, rn, Operand(IP), cond);
} else if (Operand::CanHold(~(-value), &o)) {
- mvn(IP, o, cond);
+ mvn_(IP, o, cond);
sub(rd, rn, Operand(IP), cond);
} else if (value > 0) {
LoadDecodableImmediate(IP, value, cond);
@@ -3101,11 +3101,11 @@
} else {
ASSERT(rn != IP);
if (Operand::CanHold(~value, &o)) {
- mvn(IP, o, cond);
+ mvn_(IP, o, cond);
adds(rd, rn, Operand(IP), cond);
} else if (Operand::CanHold(~(-value), &o)) {
ASSERT(value != kMinInt32); // Would cause erroneous overflow detection.
- mvn(IP, o, cond);
+ mvn_(IP, o, cond);
subs(rd, rn, Operand(IP), cond);
} else {
LoadDecodableImmediate(IP, value, cond);
@@ -3135,11 +3135,11 @@
} else {
ASSERT(rn != IP);
if (Operand::CanHold(~value, &o)) {
- mvn(IP, o, cond);
+ mvn_(IP, o, cond);
subs(rd, rn, Operand(IP), cond);
} else if (Operand::CanHold(~(-value), &o)) {
ASSERT(value != kMinInt32); // Would cause erroneous overflow detection.
- mvn(IP, o, cond);
+ mvn_(IP, o, cond);
adds(rd, rn, Operand(IP), cond);
} else {
LoadDecodableImmediate(IP, value, cond);
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 877820a..2f2f1fb 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -500,7 +500,7 @@
void bic(Register rd, Register rn, Operand o, Condition cond = AL);
void bics(Register rd, Register rn, Operand o, Condition cond = AL);
- void mvn(Register rd, Operand o, Condition cond = AL);
+ void mvn_(Register rd, Operand o, Condition cond = AL);
void mvns(Register rd, Operand o, Condition cond = AL);
// Miscellaneous data-processing instructions.
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index b5ed07b..33fa8bb 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1586,7 +1586,9 @@
}
}
void vmov(VRegister vd, VRegister vn) { vorr(vd, vn, vn); }
- void mvn(Register rd, Register rm) { orn(rd, ZR, Operand(rm)); }
+ void mvn_(Register rd, Register rm) {
+ orn(rd, ZR, Operand(rm));
+ }
void mvnw(Register rd, Register rm) { ornw(rd, ZR, Operand(rm)); }
void neg(Register rd, Register rm) { sub(rd, ZR, Operand(rm)); }
void negs(Register rd, Register rm, OperandSize sz = kEightBytes) {
diff --git a/runtime/vm/compiler/assembler/assembler_arm64_test.cc b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
index cb29a3c..a95b7fe 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm64_test.cc
@@ -3258,8 +3258,7 @@
ASSEMBLER_TEST_RUN(Smaddl3, test) {
typedef int64_t (*Int64Return)() DART_UNUSED;
- EXPECT_EQ(0xffffl * 0xffffl,
- EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
+ EXPECT_EQ(0xfffe0001, EXECUTE_TEST_CODE_INT64(Int64Return, test->entry()));
EXPECT_DISASSEMBLY(
"movz r1, #0xffff\n"
"movz r2, #0xffff\n"
diff --git a/runtime/vm/compiler/assembler/assembler_arm_test.cc b/runtime/vm/compiler/assembler/assembler_arm_test.cc
index 64db0ae..11adcf2 100644
--- a/runtime/vm/compiler/assembler/assembler_arm_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm_test.cc
@@ -75,7 +75,7 @@
}
ASSEMBLER_TEST_GENERATE(MoveNegated, assembler) {
- __ mvn(R0, Operand(42));
+ __ mvn_(R0, Operand(42));
__ Ret();
}
@@ -988,7 +988,7 @@
__ clz(R2, R2);
__ cmp(R2, Operand(26));
__ b(&error, NE);
- __ mvn(R0, Operand(0));
+ __ mvn_(R0, Operand(0));
__ clz(R1, R0);
__ cmp(R1, Operand(0));
__ b(&error, NE);
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index f92d297..fde11b60 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -5786,7 +5786,7 @@
break;
}
case Token::kBIT_NOT:
- __ mvn(result, compiler::Operand(value));
+ __ mvn_(result, compiler::Operand(value));
// Remove inverted smi-tag.
__ bic(result, result, compiler::Operand(kSmiTagMask));
break;
@@ -7071,8 +7071,8 @@
switch (op_kind()) {
case Token::kBIT_NOT:
- __ mvn(out_lo, compiler::Operand(left_lo));
- __ mvn(out_hi, compiler::Operand(left_hi));
+ __ mvn_(out_lo, compiler::Operand(left_lo));
+ __ mvn_(out_hi, compiler::Operand(left_hi));
break;
case Token::kNEGATE:
__ rsbs(out_lo, left_lo, compiler::Operand(0));
@@ -7143,7 +7143,7 @@
ASSERT(op_kind() == Token::kBIT_NOT);
- __ mvn(out, compiler::Operand(left));
+ __ mvn_(out, compiler::Operand(left));
}
LocationSummary* IntConverterInstr::MakeLocationSummary(Zone* zone,
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 3dbb6b0..7506894 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -4832,7 +4832,7 @@
break;
}
case Token::kBIT_NOT:
- __ mvn(result, value);
+ __ mvn_(result, value);
// Remove inverted smi-tag.
__ andi(result, result, compiler::Immediate(~kSmiTagMask));
break;
@@ -6145,7 +6145,7 @@
const Register out = locs()->out(0).reg();
switch (op_kind()) {
case Token::kBIT_NOT:
- __ mvn(out, left);
+ __ mvn_(out, left);
break;
case Token::kNEGATE:
__ sub(out, ZR, compiler::Operand(left));
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index ed64ffd..0034a52 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -52,6 +52,101 @@
__ Bind(&done);
}
+// In TSAN mode the runtime will throw an exception using an intermediary
+// longjmp() call to unwind the C frames in a way that TSAN can understand.
+//
+// This wrapper will setup a [jmp_buf] on the stack and initialize it to be a
+// target for a possible longjmp(). In the exceptional case we'll forward
+// control of execution to the usual JumpToFrame stub.
+//
+// In non-TSAN mode this will do nothing and the runtime will call the
+// JumpToFrame stub directly.
+//
+// The callback [fun] may be invoked with a modified [RSP] due to allocating
+// a [jmp_buf] allocating structure on the stack (as well as the saved old
+// [Thread::tsan_utils_->setjmp_buffer_]).
+static void WithExceptionCatchingTrampoline(Assembler* assembler,
+ std::function<void()> fun) {
+#if defined(USING_THREAD_SANITIZER) && !defined(USING_SIMULATOR)
+ const Register kTsanUtilsReg = R3;
+
+ // Reserve space for arguments and align frame before entering C++ world.
+ const intptr_t kJumpBufferSize = sizeof(jmp_buf);
+ // Save & Restore the volatile CPU registers across the setjmp() call.
+ const RegisterSet volatile_registers(
+ kAbiVolatileCpuRegs & ~(1 << R0) & ~(1 << SP),
+ /*fpu_registers=*/0);
+
+ const Register kSavedRspReg = R20;
+ COMPILE_ASSERT(IsCalleeSavedRegister(kSavedRspReg));
+ // We rely on THR being preserved across the setjmp() call.
+ COMPILE_ASSERT(IsCalleeSavedRegister(THR));
+
+ Label do_native_call;
+
+ // Save old jmp_buf.
+ __ ldr(kTsanUtilsReg, Address(THR, target::Thread::tsan_utils_offset()));
+ __ ldr(TMP,
+ Address(kTsanUtilsReg, target::TsanUtils::setjmp_buffer_offset()));
+ __ Push(TMP);
+
+ // Allocate jmp_buf struct on stack & remember pointer to it on the
+ // [Thread::tsan_utils_->setjmp_buffer] (which exceptions.cc will longjmp()
+ // to)
+ __ AddImmediate(SP, -kJumpBufferSize);
+ __ str(SP, Address(kTsanUtilsReg, target::TsanUtils::setjmp_buffer_offset()));
+
+ // Call setjmp() with a pointer to the allocated jmp_buf struct.
+ __ MoveRegister(R0, SP);
+ __ PushRegisters(volatile_registers);
+ __ EnterCFrame(0);
+ __ mov(R25, CSP);
+ __ mov(CSP, SP);
+ __ ldr(kTsanUtilsReg, Address(THR, target::Thread::tsan_utils_offset()));
+ __ CallCFunction(
+ Address(kTsanUtilsReg, target::TsanUtils::setjmp_function_offset()));
+ __ mov(SP, CSP);
+ __ mov(CSP, R25);
+ __ LeaveCFrame();
+ __ PopRegisters(volatile_registers);
+
+ // We are the target of a longjmp() iff setjmp() returns non-0.
+ __ cbz(&do_native_call, R0);
+
+ // We are the target of a longjmp: Cleanup the stack and tail-call the
+ // JumpToFrame stub which will take care of unwinding the stack and hand
+ // execution to the catch entry.
+ __ AddImmediate(SP, kJumpBufferSize);
+ __ ldr(kTsanUtilsReg, Address(THR, target::Thread::tsan_utils_offset()));
+ __ Pop(TMP);
+ __ str(TMP,
+ Address(kTsanUtilsReg, target::TsanUtils::setjmp_buffer_offset()));
+
+ __ ldr(R0, Address(kTsanUtilsReg, target::TsanUtils::exception_pc_offset()));
+ __ ldr(R1, Address(kTsanUtilsReg, target::TsanUtils::exception_sp_offset()));
+ __ ldr(R2, Address(kTsanUtilsReg, target::TsanUtils::exception_fp_offset()));
+ __ MoveRegister(R3, THR);
+ __ Jump(Address(THR, target::Thread::jump_to_frame_entry_point_offset()));
+
+ // We leave the created [jump_buf] structure on the stack as well as the
+ // pushed old [Thread::tsan_utils_->setjmp_buffer_].
+ __ Bind(&do_native_call);
+ __ MoveRegister(kSavedRspReg, SP);
+#endif // defined(USING_THREAD_SANITIZER) && !defined(USING_SIMULATOR)
+
+ fun();
+
+#if defined(USING_THREAD_SANITIZER) && !defined(USING_SIMULATOR)
+ __ MoveRegister(SP, kSavedRspReg);
+ __ AddImmediate(SP, kJumpBufferSize);
+ const Register kTsanUtilsReg2 = kSavedRspReg;
+ __ ldr(kTsanUtilsReg2, Address(THR, target::Thread::tsan_utils_offset()));
+ __ Pop(TMP);
+ __ str(TMP,
+ Address(kTsanUtilsReg2, target::TsanUtils::setjmp_buffer_offset()));
+#endif // defined(USING_THREAD_SANITIZER) && !defined(USING_SIMULATOR)
+}
+
// Input parameters:
// LR : return address.
// SP : address of last argument in argument array.
@@ -93,73 +188,75 @@
// Mark that the thread is executing VM code.
__ StoreToOffset(R5, THR, target::Thread::vm_tag_offset());
- // Reserve space for arguments and align frame before entering C++ world.
- // target::NativeArguments are passed in registers.
- __ Comment("align stack");
- // Reserve space for arguments.
- ASSERT(target::NativeArguments::StructSize() == 4 * target::kWordSize);
- __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
+ WithExceptionCatchingTrampoline(assembler, [&]() {
+ // Reserve space for arguments and align frame before entering C++ world.
+ // target::NativeArguments are passed in registers.
+ __ Comment("align stack");
+ // Reserve space for arguments.
+ ASSERT(target::NativeArguments::StructSize() == 4 * target::kWordSize);
+ __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
- // Pass target::NativeArguments structure by value and call runtime.
- // Registers R0, R1, R2, and R3 are used.
+ // Pass target::NativeArguments structure by value and call runtime.
+ // Registers R0, R1, R2, and R3 are used.
- ASSERT(thread_offset == 0 * target::kWordSize);
- // Set thread in NativeArgs.
- __ mov(R0, THR);
+ ASSERT(thread_offset == 0 * target::kWordSize);
+ // Set thread in NativeArgs.
+ __ mov(R0, THR);
- // There are no runtime calls to closures, so we do not need to set the tag
- // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
- ASSERT(argc_tag_offset == 1 * target::kWordSize);
- __ mov(R1, R4); // Set argc in target::NativeArguments.
+ // There are no runtime calls to closures, so we do not need to set the tag
+ // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
+ ASSERT(argc_tag_offset == 1 * target::kWordSize);
+ __ mov(R1, R4); // Set argc in target::NativeArguments.
- ASSERT(argv_offset == 2 * target::kWordSize);
- __ add(R2, ZR, Operand(R4, LSL, 3));
- __ add(R2, FP, Operand(R2)); // Compute argv.
- // Set argv in target::NativeArguments.
- __ AddImmediate(R2,
- target::frame_layout.param_end_from_fp * target::kWordSize);
+ ASSERT(argv_offset == 2 * target::kWordSize);
+ __ add(R2, ZR, Operand(R4, LSL, 3));
+ __ add(R2, FP, Operand(R2)); // Compute argv.
+ // Set argv in target::NativeArguments.
+ __ AddImmediate(R2,
+ target::frame_layout.param_end_from_fp * target::kWordSize);
- ASSERT(retval_offset == 3 * target::kWordSize);
- __ AddImmediate(R3, R2, target::kWordSize);
+ ASSERT(retval_offset == 3 * target::kWordSize);
+ __ AddImmediate(R3, R2, target::kWordSize);
- __ StoreToOffset(R0, SP, thread_offset);
- __ StoreToOffset(R1, SP, argc_tag_offset);
- __ StoreToOffset(R2, SP, argv_offset);
- __ StoreToOffset(R3, SP, retval_offset);
- __ mov(R0, SP); // Pass the pointer to the target::NativeArguments.
+ __ StoreToOffset(R0, SP, thread_offset);
+ __ StoreToOffset(R1, SP, argc_tag_offset);
+ __ StoreToOffset(R2, SP, argv_offset);
+ __ StoreToOffset(R3, SP, retval_offset);
+ __ mov(R0, SP); // Pass the pointer to the target::NativeArguments.
- // We are entering runtime code, so the C stack pointer must be restored from
- // the stack limit to the top of the stack. We cache the stack limit address
- // in a callee-saved register.
- __ mov(R25, CSP);
- __ mov(CSP, SP);
+ // We are entering runtime code, so the C stack pointer must be restored
+ // from the stack limit to the top of the stack. We cache the stack limit
+ // address in a callee-saved register.
+ __ mov(R25, CSP);
+ __ mov(CSP, SP);
- __ blr(R5);
- __ Comment("CallToRuntimeStub return");
+ __ blr(R5);
+ __ Comment("CallToRuntimeStub return");
- // Restore SP and CSP.
- __ mov(SP, CSP);
- __ mov(CSP, R25);
+ // Restore SP and CSP.
+ __ mov(SP, CSP);
+ __ mov(CSP, R25);
- // Refresh pinned registers values (inc. write barrier mask and null object).
- __ RestorePinnedRegisters();
+ // Refresh pinned registers (write barrier mask, null, dispatch table, etc).
+ __ RestorePinnedRegisters();
- // Retval is next to 1st argument.
- // Mark that the thread is executing Dart code.
- __ LoadImmediate(R2, VMTag::kDartTagId);
- __ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
+ // Retval is next to 1st argument.
+ // Mark that the thread is executing Dart code.
+ __ LoadImmediate(R2, VMTag::kDartTagId);
+ __ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
- // Mark that the thread has not exited generated Dart code.
- __ StoreToOffset(ZR, THR, target::Thread::exit_through_ffi_offset());
+ // Mark that the thread has not exited generated Dart code.
+ __ StoreToOffset(ZR, THR, target::Thread::exit_through_ffi_offset());
- // Reset exit frame information in Isolate's mutator thread structure.
- __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
+ // Reset exit frame information in Isolate's mutator thread structure.
+ __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
- // Restore the global object pool after returning from runtime (old space is
- // moving, so the GOP could have been relocated).
- if (FLAG_precompiled_mode) {
- __ SetupGlobalPoolAndDispatchTable();
- }
+ // Restore the global object pool after returning from runtime (old space is
+ // moving, so the GOP could have been relocated).
+ if (FLAG_precompiled_mode) {
+ __ SetupGlobalPoolAndDispatchTable();
+ }
+ });
__ LeaveStubFrame();
@@ -678,73 +775,76 @@
// Mark that the thread is executing native code.
__ StoreToOffset(R5, THR, target::Thread::vm_tag_offset());
- // Reserve space for the native arguments structure passed on the stack (the
- // outgoing pointer parameter to the native arguments structure is passed in
- // R0) and align frame before entering the C++ world.
- __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
+ WithExceptionCatchingTrampoline(assembler, [&]() {
+ // Reserve space for the native arguments structure passed on the stack (the
+ // outgoing pointer parameter to the native arguments structure is passed in
+ // R0) and align frame before entering the C++ world.
+ __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
- // Initialize target::NativeArguments structure and call native function.
- // Registers R0, R1, R2, and R3 are used.
+ // Initialize target::NativeArguments structure and call native function.
+ // Registers R0, R1, R2, and R3 are used.
- ASSERT(thread_offset == 0 * target::kWordSize);
- // Set thread in NativeArgs.
- __ mov(R0, THR);
+ ASSERT(thread_offset == 0 * target::kWordSize);
+ // Set thread in NativeArgs.
+ __ mov(R0, THR);
- // There are no native calls to closures, so we do not need to set the tag
- // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
- ASSERT(argc_tag_offset == 1 * target::kWordSize);
- // Set argc in target::NativeArguments: R1 already contains argc.
+ // There are no native calls to closures, so we do not need to set the tag
+ // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
+ ASSERT(argc_tag_offset == 1 * target::kWordSize);
+ // Set argc in target::NativeArguments: R1 already contains argc.
- ASSERT(argv_offset == 2 * target::kWordSize);
- // Set argv in target::NativeArguments: R2 already contains argv.
+ ASSERT(argv_offset == 2 * target::kWordSize);
+ // Set argv in target::NativeArguments: R2 already contains argv.
- // Set retval in NativeArgs.
- ASSERT(retval_offset == 3 * target::kWordSize);
- __ AddImmediate(
- R3, FP, (target::frame_layout.param_end_from_fp + 1) * target::kWordSize);
+ // Set retval in NativeArgs.
+ ASSERT(retval_offset == 3 * target::kWordSize);
+ __ AddImmediate(
+ R3, FP,
+ (target::frame_layout.param_end_from_fp + 1) * target::kWordSize);
- // Passing the structure by value as in runtime calls would require changing
- // Dart API for native functions.
- // For now, space is reserved on the stack and we pass a pointer to it.
- __ StoreToOffset(R0, SP, thread_offset);
- __ StoreToOffset(R1, SP, argc_tag_offset);
- __ StoreToOffset(R2, SP, argv_offset);
- __ StoreToOffset(R3, SP, retval_offset);
- __ mov(R0, SP); // Pass the pointer to the target::NativeArguments.
+ // Passing the structure by value as in runtime calls would require changing
+ // Dart API for native functions.
+ // For now, space is reserved on the stack and we pass a pointer to it.
+ __ StoreToOffset(R0, SP, thread_offset);
+ __ StoreToOffset(R1, SP, argc_tag_offset);
+ __ StoreToOffset(R2, SP, argv_offset);
+ __ StoreToOffset(R3, SP, retval_offset);
+ __ mov(R0, SP); // Pass the pointer to the target::NativeArguments.
- // We are entering runtime code, so the C stack pointer must be restored from
- // the stack limit to the top of the stack. We cache the stack limit address
- // in the Dart SP register, which is callee-saved in the C ABI.
- __ mov(R25, CSP);
- __ mov(CSP, SP);
+ // We are entering runtime code, so the C stack pointer must be restored
+ // from the stack limit to the top of the stack. We cache the stack limit
+ // address in the Dart SP register, which is callee-saved in the C ABI.
+ __ mov(R25, CSP);
+ __ mov(CSP, SP);
- __ mov(R1, R5); // Pass the function entrypoint to call.
+ __ mov(R1, R5); // Pass the function entrypoint to call.
- // Call native function invocation wrapper or redirection via simulator.
- __ Call(wrapper);
+ // Call native function invocation wrapper or redirection via simulator.
+ __ Call(wrapper);
- // Restore SP and CSP.
- __ mov(SP, CSP);
- __ mov(CSP, R25);
+ // Restore SP and CSP.
+ __ mov(SP, CSP);
+ __ mov(CSP, R25);
- // Refresh pinned registers values (inc. write barrier mask and null object).
- __ RestorePinnedRegisters();
+ // Refresh pinned registers (write barrier mask, null, dispatch table, etc).
+ __ RestorePinnedRegisters();
- // Mark that the thread is executing Dart code.
- __ LoadImmediate(R2, VMTag::kDartTagId);
- __ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
+ // Mark that the thread is executing Dart code.
+ __ LoadImmediate(R2, VMTag::kDartTagId);
+ __ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
- // Mark that the thread has not exited generated Dart code.
- __ StoreToOffset(ZR, THR, target::Thread::exit_through_ffi_offset());
+ // Mark that the thread has not exited generated Dart code.
+ __ StoreToOffset(ZR, THR, target::Thread::exit_through_ffi_offset());
- // Reset exit frame information in Isolate's mutator thread structure.
- __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
+ // Reset exit frame information in Isolate's mutator thread structure.
+ __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
- // Restore the global object pool after returning from runtime (old space is
- // moving, so the GOP could have been relocated).
- if (FLAG_precompiled_mode) {
- __ SetupGlobalPoolAndDispatchTable();
- }
+ // Restore the global object pool after returning from runtime (old space is
+ // moving, so the GOP could have been relocated).
+ if (FLAG_precompiled_mode) {
+ __ SetupGlobalPoolAndDispatchTable();
+ }
+ });
__ LeaveStubFrame();
__ ret();
@@ -1393,7 +1493,7 @@
__ mov(THR, R3);
}
- // Refresh pinned registers values (inc. write barrier mask and null object).
+ // Refresh pinned registers (write barrier mask, null, dispatch table, etc).
__ RestorePinnedRegisters();
// Save the current VMTag on the stack.
@@ -3125,7 +3225,7 @@
/*ignore_unwind_in_progress=*/true);
__ Bind(&exit_through_non_ffi);
- // Refresh pinned registers values (inc. write barrier mask and null object).
+ // Refresh pinned registers (write barrier mask, null, dispatch table, etc).
__ RestorePinnedRegisters();
// Set the tag.
__ LoadImmediate(R2, VMTag::kDartTagId);
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 998fac5..c817ad4 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -70,7 +70,7 @@
// [Thread::tsan_utils_->setjmp_buffer_]).
static void WithExceptionCatchingTrampoline(Assembler* assembler,
std::function<void()> fun) {
-#if defined(USING_THREAD_SANITIZER)
+#if defined(USING_THREAD_SANITIZER) && !defined(USING_SIMULATOR)
const Register kTsanUtilsReg = RAX;
// Reserve space for arguments and align frame before entering C++ world.
@@ -138,17 +138,17 @@
// pushed old [Thread::tsan_utils_->setjmp_buffer_].
__ Bind(&do_native_call);
__ MoveRegister(kSavedRspReg, RSP);
-#endif // defined(USING_THREAD_SANITIZER)
+#endif // defined(USING_THREAD_SANITIZER) && !defined(USING_SIMULATOR)
fun();
-#if defined(USING_THREAD_SANITIZER)
+#if defined(USING_THREAD_SANITIZER) && !defined(USING_SIMULATOR)
__ MoveRegister(RSP, kSavedRspReg);
__ AddImmediate(RSP, Immediate(kJumpBufferSize));
const Register kTsanUtilsReg2 = kSavedRspReg;
__ movq(kTsanUtilsReg2, Address(THR, target::Thread::tsan_utils_offset()));
__ popq(Address(kTsanUtilsReg2, target::TsanUtils::setjmp_buffer_offset()));
-#endif // defined(USING_THREAD_SANITIZER)
+#endif // defined(USING_THREAD_SANITIZER) && !defined(USING_SIMULATOR)
}
// Input parameters:
diff --git a/runtime/vm/constants_arm64.h b/runtime/vm/constants_arm64.h
index b09a94a..94fdda6 100644
--- a/runtime/vm/constants_arm64.h
+++ b/runtime/vm/constants_arm64.h
@@ -395,6 +395,9 @@
// C++ ABI call registers.
const RegList kAbiArgumentCpuRegs =
R(R0) | R(R1) | R(R2) | R(R3) | R(R4) | R(R5) | R(R6) | R(R7);
+const RegList kAbiVolatileCpuRegs =
+ kAbiArgumentCpuRegs | R(R8) | R(R9) | R(R10) | R(R11) | R(R12) | R(R13) |
+ R(R14) | R(R15) | R(R16) | R(R17);
#if defined(DART_TARGET_OS_FUCHSIA)
// We rely on R18 not being touched by Dart generated assembly or stubs at all.
// We rely on that any calls into C++ also preserve R18.
diff --git a/runtime/vm/cpu_arm.cc b/runtime/vm/cpu_arm.cc
index b18056a..eef1084 100644
--- a/runtime/vm/cpu_arm.cc
+++ b/runtime/vm/cpu_arm.cc
@@ -14,15 +14,12 @@
#include "vm/object.h"
#include "vm/simulator.h"
-#if defined(DART_HOST_OS_IOS)
+#if !defined(TARGET_HOST_MISMATCH)
+#if defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS)
#include <libkern/OSCacheControl.h>
#elif defined(DART_HOST_OS_WINDOWS)
#include <processthreadsapi.h>
#endif
-
-#if !defined(TARGET_HOST_MISMATCH)
-#include <sys/syscall.h> /* NOLINT */
-#include <unistd.h> /* NOLINT */
#endif
// ARM version differences.
diff --git a/runtime/vm/cpu_arm64.cc b/runtime/vm/cpu_arm64.cc
index 1ae9f0d..10827ba 100644
--- a/runtime/vm/cpu_arm64.cc
+++ b/runtime/vm/cpu_arm64.cc
@@ -12,19 +12,14 @@
#include "vm/simulator.h"
#if !defined(USING_SIMULATOR)
-#if !defined(DART_HOST_OS_FUCHSIA)
-#include <sys/syscall.h>
-#else
+#if defined(DART_HOST_OS_FUCHSIA)
#include <zircon/syscalls.h>
-#endif
-#include <unistd.h>
-#endif
-
-#if defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS)
+#elif defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_IOS)
#include <libkern/OSCacheControl.h>
#elif defined(DART_HOST_OS_WINDOWS)
#include <processthreadsapi.h>
#endif
+#endif
namespace dart {
diff --git a/runtime/vm/globals.h b/runtime/vm/globals.h
index 1a3d6c0..c564a48 100644
--- a/runtime/vm/globals.h
+++ b/runtime/vm/globals.h
@@ -180,12 +180,9 @@
__asm { mov fp, ebp} \
; // NOLINT
// clang-format on
-#elif defined(HOST_ARCH_X64)
-// We don't have the asm equivalent to get at the frame pointer on
-// windows x64, return the stack pointer instead.
-#define COPY_FP_REGISTER(fp) fp = OSThread::GetCurrentStackPointer();
#else
-#error Unknown host architecture.
+// Inline assembly is only available on x86; return the stack pointer instead.
+#define COPY_FP_REGISTER(fp) fp = OSThread::GetCurrentStackPointer();
#endif
#else // !defined(DART_HOST_OS_WINDOWS))
diff --git a/runtime/vm/profiler.cc b/runtime/vm/profiler.cc
index d8ae4af..fb9bb9d 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -416,6 +416,14 @@
uword pc = static_cast<uword>(ctx->Rip);
uword fp = static_cast<uword>(ctx->Rbp);
uword sp = static_cast<uword>(ctx->Rsp);
+#elif defined(HOST_ARCH_ARM)
+ uword pc = static_cast<uword>(ctx->Pc);
+ uword fp = static_cast<uword>(ctx->R11);
+ uword sp = static_cast<uword>(ctx->Sp);
+#elif defined(HOST_ARCH_ARM64)
+ uword pc = static_cast<uword>(ctx->Pc);
+ uword fp = static_cast<uword>(ctx->Fp);
+ uword sp = static_cast<uword>(ctx->Sp);
#else
#error Unsupported architecture.
#endif
diff --git a/runtime/vm/thread_interrupter_win.cc b/runtime/vm/thread_interrupter_win.cc
index 3db5023..a7cdef7 100644
--- a/runtime/vm/thread_interrupter_win.cc
+++ b/runtime/vm/thread_interrupter_win.cc
@@ -26,7 +26,8 @@
#if defined(HOST_ARCH_IA32)
// On IA32, CONTEXT_CONTROL includes Eip, Ebp, and Esp.
context.ContextFlags = CONTEXT_CONTROL;
-#elif defined(HOST_ARCH_X64)
+#elif defined(HOST_ARCH_X64) || defined(HOST_ARCH_ARM) || \
+ defined(HOST_ARCH_ARM64)
// On X64, CONTEXT_CONTROL includes Rip and Rsp. Rbp is classified
// as an "integer" register.
context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
@@ -44,6 +45,16 @@
state->fp = static_cast<uintptr_t>(context.Rbp);
state->csp = static_cast<uintptr_t>(context.Rsp);
state->dsp = static_cast<uintptr_t>(context.Rsp);
+#elif defined(HOST_ARCH_ARM)
+ state->pc = static_cast<uintptr_t>(context.Pc);
+ state->fp = static_cast<uintptr_t>(context.R11);
+ state->csp = static_cast<uintptr_t>(context.Sp);
+ state->dsp = static_cast<uintptr_t>(context.Sp);
+#elif defined(HOST_ARCH_ARM64)
+ state->pc = static_cast<uintptr_t>(context.Pc);
+ state->fp = static_cast<uintptr_t>(context.Fp);
+ state->csp = static_cast<uintptr_t>(context.Sp);
+ state->dsp = static_cast<uintptr_t>(context.X15);
#else
#error Unsupported architecture.
#endif
diff --git a/tools/VERSION b/tools/VERSION
index db9b0e4..3153c6e 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 283
+PRERELEASE 284
PRERELEASE_PATCH 0
\ No newline at end of file