Version 2.12.0-24.0.dev
Merge commit 'd13eaddf97d60c706f8a8969a8998ab6b083f753' into 'dev'
diff --git a/pkg/analyzer/lib/file_system/file_system.dart b/pkg/analyzer/lib/file_system/file_system.dart
index ac8456c..7f6e20e 100644
--- a/pkg/analyzer/lib/file_system/file_system.dart
+++ b/pkg/analyzer/lib/file_system/file_system.dart
@@ -43,7 +43,7 @@
/// If [newPath] identifies an existing file, that file is replaced.
/// If [newPath] identifies an existing resource the operation might fail and
/// an exception is thrown.
- File renameSync(String newPath);
+ File renameSync(String /*!*/ newPath);
/// Synchronously write the given [bytes] to the file. The new content will
/// replace any existing content.
@@ -81,12 +81,12 @@
///
/// However, regardless of whether [path] is relative or absolute, normalize
/// it by removing path components of the form '.' or '..'.
- String canonicalizePath(String path);
+ String canonicalizePath(String /*!*/ path);
/// Return `true` if the [path] references a resource in this folder.
///
/// The [path] must be absolute and normalized.
- bool contains(String path);
+ bool contains(String /*!*/ path);
@override
Folder copyTo(Folder parentFolder);
@@ -96,19 +96,19 @@
/// Return an existing child [Resource] with the given [relPath].
/// Return a not existing [File] if no such child exist.
- Resource getChild(String relPath);
+ Resource getChild(String /*!*/ relPath);
/// Return a [File] representing a child [Resource] with the given
/// [relPath]. This call does not check whether a file with the given name
/// exists on the filesystem - client must call the [File]'s `exists` getter
/// to determine whether the folder actually exists.
- File getChildAssumingFile(String relPath);
+ File getChildAssumingFile(String /*!*/ relPath);
/// Return a [Folder] representing a child [Resource] with the given
/// [relPath]. This call does not check whether a folder with the given name
/// exists on the filesystem--client must call the [Folder]'s `exists` getter
/// to determine whether the folder actually exists.
- Folder getChildAssumingFolder(String relPath);
+ Folder getChildAssumingFolder(String /*!*/ relPath);
/// Return a list of existing direct children [Resource]s (folders and files)
/// in this folder, in no particular order.
@@ -145,7 +145,7 @@
/// Existing files and folders will be overwritten.
///
/// Return the resource corresponding to this resource in the parent folder.
- Resource copyTo(Folder parentFolder);
+ Resource copyTo(Folder /*!*/ parentFolder);
/// Synchronously deletes this resource and its children.
///
@@ -156,7 +156,7 @@
/// this folder.
///
/// The [path] must be absolute and normalized.
- bool isOrContains(String path);
+ bool isOrContains(String /*!*/ path);
/// Return a resource that refers to the same resource as this resource, but
/// whose path does not contain any symbolic links.
@@ -177,14 +177,14 @@
/// The [path] must be absolute and normalized.
///
/// A file may or may not exist at this location.
- File getFile(String path);
+ File getFile(String /*!*/ path);
/// Return a [Folder] that corresponds to the given [path].
///
/// The [path] must be absolute and normalized.
///
/// A folder may or may not exist at this location.
- Folder getFolder(String path);
+ Folder getFolder(String /*!*/ path);
/// Complete with a list of modification times for the given [sources].
///
@@ -195,7 +195,7 @@
/// Return the [Resource] that corresponds to the given [path].
///
/// The [path] must be absolute and normalized.
- Resource getResource(String path);
+ Resource getResource(String /*!*/ path);
/// Return the folder in which the plugin with the given [pluginId] can store
/// state that will persist across sessions. The folder returned for a given
diff --git a/pkg/analyzer/lib/file_system/memory_file_system.dart b/pkg/analyzer/lib/file_system/memory_file_system.dart
index d852cb0..caaeae1 100644
--- a/pkg/analyzer/lib/file_system/memory_file_system.dart
+++ b/pkg/analyzer/lib/file_system/memory_file_system.dart
@@ -44,6 +44,7 @@
/// This is a utility method for testing; paths passed in to other methods in
/// this class are never converted automatically.
String convertPath(String path) {
+ assert(path != null);
if (pathContext.style == pathos.windows.style) {
if (path.startsWith(pathos.posix.separator)) {
path = r'C:' + path;
@@ -84,12 +85,14 @@
@override
File getFile(String path) {
+ assert(path != null);
_ensureAbsoluteAndNormalized(path);
return _MemoryFile(this, path);
}
@override
Folder getFolder(String path) {
+ assert(path != null);
_ensureAbsoluteAndNormalized(path);
return _MemoryFolder(this, path);
}
@@ -104,6 +107,7 @@
@override
Resource getResource(String path) {
+ assert(path != null);
_ensureAbsoluteAndNormalized(path);
return _pathToResource[path] ?? _MemoryFile(this, path);
}
@@ -115,6 +119,7 @@
}
void modifyFile(String path, String content) {
+ assert(content != null);
_checkFileAtPath(path);
_pathToBytes[path] = utf8.encode(content) as Uint8List;
_pathToTimestamp[path] = nextStamp++;
@@ -203,6 +208,7 @@
}
void _checkFileAtPath(String path) {
+ assert(path != null);
// TODO(brianwilkerson) Consider throwing a FileSystemException rather than
// an ArgumentError.
_MemoryResource resource = _pathToResource[path];
@@ -216,6 +222,7 @@
}
void _checkFolderAtPath(String path) {
+ assert(path != null);
// TODO(brianwilkerson) Consider throwing a FileSystemException rather than
// an ArgumentError.
_MemoryResource resource = _pathToResource[path];
@@ -228,6 +235,7 @@
/// The file system abstraction supports only absolute and normalized paths.
/// This method is used to validate any input paths to prevent errors later.
void _ensureAbsoluteAndNormalized(String path) {
+ assert(path != null);
if (!pathContext.isAbsolute(path)) {
throw ArgumentError("Path must be absolute : $path");
}
@@ -238,6 +246,7 @@
/// Create a new [_MemoryFile] without any content.
_MemoryFile _newFile(String path) {
+ assert(path != null);
String folderPath = pathContext.dirname(path);
_MemoryResource folder = _pathToResource[folderPath];
if (folder == null) {
@@ -251,6 +260,7 @@
}
void _notifyWatchers(String path, ChangeType changeType) {
+ assert(path != null);
_pathToWatchers.forEach((String watcherPath,
List<StreamController<WatchEvent>> streamControllers) {
if (watcherPath == path || pathContext.isWithin(watcherPath, path)) {
@@ -263,6 +273,7 @@
}
_MemoryFile _renameFileSync(_MemoryFile file, String newPath) {
+ assert(newPath != null);
String path = file.path;
if (newPath == path) {
return file;
@@ -285,6 +296,7 @@
}
String _resolveLinks(String path) {
+ assert(path != null);
var linkTarget = _pathToLinkedPath[path];
if (linkTarget != null) {
return linkTarget;
@@ -424,6 +436,7 @@
@override
File copyTo(Folder parentFolder) {
+ assert(parentFolder != null);
parentFolder.create();
File destination = parentFolder.getChildAssumingFile(shortName);
destination.writeAsBytesSync(readAsBytesSync());
@@ -504,6 +517,7 @@
@override
String canonicalizePath(String relPath) {
+ assert(relPath != null);
relPath = provider.pathContext.normalize(relPath);
String childPath = provider.pathContext.join(path, relPath);
childPath = provider.pathContext.normalize(childPath);
@@ -512,6 +526,7 @@
@override
bool contains(String path) {
+ assert(path != null);
return provider.pathContext.isWithin(this.path, path);
}
diff --git a/pkg/expect/lib/expect.dart b/pkg/expect/lib/expect.dart
index 6e6b8e6..a030354 100644
--- a/pkg/expect/lib/expect.dart
+++ b/pkg/expect/lib/expect.dart
@@ -10,11 +10,11 @@
import 'package:meta/meta.dart';
-/// Whether the program is running with weak null safety checking.
-bool get isWeakMode => const <Null>[] is List<Object>;
+/// Whether the program is running without sound null safety.
+bool get hasUnsoundNullSafety => const <Null>[] is List<Object>;
-/// Whether the program is running with strong null safety checking.
-bool get isStrongMode => !isWeakMode;
+/// Whether the program is running with sound null safety.
+bool get hasSoundNullSafety => !hasUnsoundNullSafety;
/**
* Expect is used for tests that do not want to make use of the
@@ -620,11 +620,11 @@
/// Checks that [f] throws an appropriate error on a null argument.
///
- /// In strong mode, this is expected to be a [TypeError] when casting the
- /// `null` to some non-nullable type. In weak mode, that cast is ignored and
- /// some later explicit validation should handle it and [ArgumentError].
+ /// With sound null safety, this is expected to be a [TypeError] when casting
+ /// the `null` to some non-nullable type. In weak mode, that cast is ignored
+ /// and some later explicit validation should handle it and [ArgumentError].
static void throwsNullCheckError(void f()) {
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
throwsTypeError(f);
} else {
throwsArgumentError(f);
diff --git a/pkg/expect/test/nnbd_mode_test.dart b/pkg/expect/test/nnbd_mode_test.dart
index 47fb624..35dd345 100644
--- a/pkg/expect/test/nnbd_mode_test.dart
+++ b/pkg/expect/test/nnbd_mode_test.dart
@@ -14,6 +14,6 @@
}();
void main() {
- Expect.equals(strong, isStrongMode);
- Expect.equals(!strong, isWeakMode);
+ Expect.equals(strong, hasSoundNullSafety);
+ Expect.equals(!strong, hasUnsoundNullSafety);
}
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 366e68c..a4eebe8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -324,8 +324,8 @@
/// List of built type aliased factory constructor invocations that require
/// unaliasing.
- final List<StaticInvocation> typeAliasedFactoryInvocations =
- <StaticInvocation>[];
+ final List<TypeAliasedFactoryInvocationJudgment>
+ typeAliasedFactoryInvocations = [];
/// Variables with metadata. Their types need to be inferred late, for
/// example, in [finishFunction].
@@ -1151,6 +1151,74 @@
_resolveRedirectingFactoryTargets();
}
+ /// Return an [Expression] resolving the argument invocation.
+ ///
+ /// The arguments specify the [StaticInvocation] whose `.target` is
+ /// [target], `.arguments` is [arguments], `.fileOffset` is [fileOffset],
+ /// and `.isConst` is [isConst].
+ Expression _resolveRedirectingFactoryTarget(
+ Procedure target, Arguments arguments, int fileOffset, bool isConst) {
+ Procedure initialTarget = target;
+ Expression replacementNode;
+
+ RedirectionTarget redirectionTarget =
+ getRedirectionTarget(initialTarget, this);
+ Member resolvedTarget = redirectionTarget?.target;
+
+ if (resolvedTarget == null) {
+ String name = constructorNameForDiagnostics(initialTarget.name.text,
+ className: initialTarget.enclosingClass.name);
+ // TODO(dmitryas): Report this error earlier.
+ replacementNode = buildProblem(
+ fasta.templateCyclicRedirectingFactoryConstructors
+ .withArguments(name),
+ initialTarget.fileOffset,
+ name.length);
+ } else if (resolvedTarget is Constructor &&
+ resolvedTarget.enclosingClass.isAbstract) {
+ replacementNode = evaluateArgumentsBefore(
+ forest.createArguments(noLocation, arguments.positional,
+ types: arguments.types, named: arguments.named),
+ buildAbstractClassInstantiationError(
+ fasta.templateAbstractRedirectedClassInstantiation
+ .withArguments(resolvedTarget.enclosingClass.name),
+ resolvedTarget.enclosingClass.name,
+ initialTarget.fileOffset));
+ } else {
+ RedirectingFactoryBody redirectingFactoryBody =
+ getRedirectingFactoryBody(resolvedTarget);
+ if (redirectingFactoryBody != null) {
+ // If the redirection target is itself a redirecting factory, it means
+ // that it is unresolved.
+ assert(redirectingFactoryBody.isUnresolved);
+ String errorName = redirectingFactoryBody.unresolvedName;
+ replacementNode = buildProblem(
+ fasta.templateMethodNotFound.withArguments(errorName),
+ fileOffset,
+ noLength,
+ suppressMessage: true);
+ } else {
+ Substitution substitution = Substitution.fromPairs(
+ initialTarget.function.typeParameters, arguments.types);
+ arguments.types.clear();
+ arguments.types.length = redirectionTarget.typeArguments.length;
+ for (int i = 0; i < arguments.types.length; i++) {
+ arguments.types[i] =
+ substitution.substituteType(redirectionTarget.typeArguments[i]);
+ }
+
+ replacementNode = buildStaticInvocation(
+ resolvedTarget,
+ forest.createArguments(noLocation, arguments.positional,
+ types: arguments.types, named: arguments.named),
+ constness:
+ isConst ? Constness.explicitConst : Constness.explicitNew,
+ charOffset: fileOffset);
+ }
+ }
+ return replacementNode;
+ }
+
void _resolveRedirectingFactoryTargets() {
for (StaticInvocation invocation in redirectingFactoryInvocations) {
// If the invocation was invalid, it or its parent has already been
@@ -1172,73 +1240,8 @@
}
if (parent == null) continue;
}
-
- Procedure initialTarget = invocation.target;
- Expression replacementNode;
-
- RedirectionTarget redirectionTarget =
- getRedirectionTarget(initialTarget, this);
- Member resolvedTarget = redirectionTarget?.target;
-
- if (resolvedTarget == null) {
- String name = constructorNameForDiagnostics(initialTarget.name.text,
- className: initialTarget.enclosingClass.name);
- // TODO(dmitryas): Report this error earlier.
- replacementNode = buildProblem(
- fasta.templateCyclicRedirectingFactoryConstructors
- .withArguments(name),
- initialTarget.fileOffset,
- name.length);
- } else if (resolvedTarget is Constructor &&
- resolvedTarget.enclosingClass.isAbstract) {
- replacementNode = evaluateArgumentsBefore(
- forest.createArguments(noLocation, invocation.arguments.positional,
- types: invocation.arguments.types,
- named: invocation.arguments.named),
- buildAbstractClassInstantiationError(
- fasta.templateAbstractRedirectedClassInstantiation
- .withArguments(resolvedTarget.enclosingClass.name),
- resolvedTarget.enclosingClass.name,
- initialTarget.fileOffset));
- } else {
- RedirectingFactoryBody redirectingFactoryBody =
- getRedirectingFactoryBody(resolvedTarget);
- if (redirectingFactoryBody != null) {
- // If the redirection target is itself a redirecting factory, it means
- // that it is unresolved.
- assert(redirectingFactoryBody.isUnresolved);
- String errorName = redirectingFactoryBody.unresolvedName;
- replacementNode = buildProblem(
- fasta.templateMethodNotFound.withArguments(errorName),
- invocation.fileOffset,
- noLength,
- suppressMessage: true);
- } else {
- Substitution substitution = Substitution.fromPairs(
- initialTarget.function.typeParameters,
- invocation.arguments.types);
- invocation.arguments.types.clear();
- invocation.arguments.types.length =
- redirectionTarget.typeArguments.length;
- for (int i = 0; i < invocation.arguments.types.length; i++) {
- invocation.arguments.types[i] =
- substitution.substituteType(redirectionTarget.typeArguments[i]);
- }
-
- replacementNode = buildStaticInvocation(
- resolvedTarget,
- forest.createArguments(
- noLocation, invocation.arguments.positional,
- types: invocation.arguments.types,
- named: invocation.arguments.named),
- constness: invocation.isConst
- ? Constness.explicitConst
- : Constness.explicitNew,
- charOffset: invocation.fileOffset);
- }
- }
-
- invocation.replaceWith(replacementNode);
+ invocation.replaceWith(_resolveRedirectingFactoryTarget(invocation.target,
+ invocation.arguments, invocation.fileOffset, invocation.isConst));
}
redirectingFactoryInvocations.clear();
}
@@ -1255,10 +1258,9 @@
if (unaliasedType is InterfaceType) {
invocationTypeArguments = unaliasedType.typeArguments;
}
- Arguments invocationArguments = new ArgumentsImpl(
- invocation.arguments.positional,
- types: invocationTypeArguments,
- named: invocation.arguments.named);
+ Arguments invocationArguments = forest.createArguments(
+ noLocation, invocation.arguments.positional,
+ types: invocationTypeArguments, named: invocation.arguments.named);
invocation.replaceWith(new ConstructorInvocation(
invocation.target, invocationArguments,
isConst: invocation.isConst));
@@ -1267,10 +1269,22 @@
}
void _unaliasTypeAliasedFactoryInvocations() {
- for (StaticInvocation invocation in typeAliasedFactoryInvocations) {
- // TODO(eernst): Should replace aliased factory invocations,
- // such that back ends don't see instance creations on type aliases.
- invocation.replaceWith(new NullLiteral());
+ for (TypeAliasedFactoryInvocationJudgment invocation
+ in typeAliasedFactoryInvocations) {
+ DartType unaliasedType = new TypedefType(
+ invocation.typeAliasBuilder.typedef,
+ Nullability.nonNullable,
+ invocation.arguments.types)
+ .unalias;
+ List<DartType> invocationTypeArguments = null;
+ if (unaliasedType is InterfaceType) {
+ invocationTypeArguments = unaliasedType.typeArguments;
+ }
+ Arguments invocationArguments = forest.createArguments(
+ noLocation, invocation.arguments.positional,
+ types: invocationTypeArguments, named: invocation.arguments.named);
+ invocation.replaceWith(_resolveRedirectingFactoryTarget(invocation.target,
+ invocationArguments, invocation.fileOffset, invocation.isConst));
}
typeAliasedFactoryInvocations.clear();
}
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
index 918b045..bb85a96 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -54,9 +54,9 @@
//
// You must check [IsConcreteNativeType] and [CheckSized] first to verify that
// this type has a defined size.
-static size_t SizeOf(const AbstractType& type, Zone* zone) {
+static size_t SizeOf(Zone* zone, const AbstractType& type) {
if (IsFfiTypeClassId(type.type_class_id())) {
- return compiler::ffi::NativeType::FromAbstractType(type, zone)
+ return compiler::ffi::NativeType::FromAbstractType(zone, type)
.SizeInBytes();
} else {
Class& struct_class = Class::Handle(type.type_class());
@@ -122,7 +122,7 @@
// TODO(36370): Make representation consistent with kUnboxedFfiIntPtr.
const size_t address =
pointer.NativeAddress() + static_cast<intptr_t>(index.AsInt64Value()) *
- SizeOf(pointer_type_arg, zone);
+ SizeOf(zone, pointer_type_arg);
const Pointer& pointer_offset =
Pointer::Handle(zone, Pointer::New(pointer_type_arg, address));
@@ -142,7 +142,7 @@
GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
CheckSized(type_arg);
- return Integer::New(SizeOf(type_arg, zone));
+ return Integer::New(SizeOf(zone, type_arg));
}
// Static invocations to this method are translated directly in streaming FGB.
diff --git a/runtime/observatory/tests/service/get_stack_limit_rpc_test.dart b/runtime/observatory/tests/service/get_stack_limit_rpc_test.dart
index d80e4e1..99a8bf1 100644
--- a/runtime/observatory/tests/service/get_stack_limit_rpc_test.dart
+++ b/runtime/observatory/tests/service/get_stack_limit_rpc_test.dart
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--causal-async-stacks --no-lazy-async-stacks
+
import 'dart:async';
import 'dart:developer';
diff --git a/runtime/observatory_2/tests/service_2/get_stack_limit_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_stack_limit_rpc_test.dart
index 4c2f286..5248ebc 100644
--- a/runtime/observatory_2/tests/service_2/get_stack_limit_rpc_test.dart
+++ b/runtime/observatory_2/tests/service_2/get_stack_limit_rpc_test.dart
@@ -2,6 +2,8 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
+// VMOptions=--causal-async-stacks --no-lazy-async-stacks
+
import 'dart:async';
import 'dart:developer';
diff --git a/runtime/tests/vm/dart/error_messages_in_null_checks_test.dart b/runtime/tests/vm/dart/error_messages_in_null_checks_test.dart
index 2a64885..30e08ef 100644
--- a/runtime/tests/vm/dart/error_messages_in_null_checks_test.dart
+++ b/runtime/tests/vm/dart/error_messages_in_null_checks_test.dart
@@ -89,7 +89,7 @@
Expect.throws(
() => 9.81 - doubleNull,
- (e) => isWeakMode
+ (e) => hasUnsoundNullSafety
? (e is NoSuchMethodError &&
// If '-' is specialized.
(e.toString().startsWith(
diff --git a/runtime/tests/vm/dart/null_checks_with_dwarf_stack_traces_test.dart b/runtime/tests/vm/dart/null_checks_with_dwarf_stack_traces_test.dart
index b508ea8..7a87925 100644
--- a/runtime/tests/vm/dart/null_checks_with_dwarf_stack_traces_test.dart
+++ b/runtime/tests/vm/dart/null_checks_with_dwarf_stack_traces_test.dart
@@ -52,8 +52,10 @@
Expect.throws(() => doubleNull + 2.17, (e) => e is NoSuchMethodError);
- Expect.throws(() => 9.81 - doubleNull,
- (e) => isWeakMode ? (e is NoSuchMethodError) : (e is TypeError));
+ Expect.throws(
+ () => 9.81 - doubleNull,
+ (e) =>
+ hasUnsoundNullSafety ? (e is NoSuchMethodError) : (e is TypeError));
Expect.throws(() => intNull * 7, (e) => e is NoSuchMethodError);
}
diff --git a/runtime/tests/vm/dart/transferable_throws_test.dart b/runtime/tests/vm/dart/transferable_throws_test.dart
index c2a35d6..2ad3605 100644
--- a/runtime/tests/vm/dart/transferable_throws_test.dart
+++ b/runtime/tests/vm/dart/transferable_throws_test.dart
@@ -107,7 +107,7 @@
throwsIfCummulativeListIsTooLargeOn32bitPlatform();
dynamic myNull;
- if (isWeakMode) {
+ if (hasUnsoundNullSafety) {
Expect.throwsArgumentError(() => TransferableTypedData.fromList(myNull));
Expect.throwsArgumentError(() => TransferableTypedData.fromList([myNull]));
Expect.throwsArgumentError(
diff --git a/runtime/vm/compiler/assembler/assembler_x64.cc b/runtime/vm/compiler/assembler/assembler_x64.cc
index 779eadd..4310ef2 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1671,19 +1671,27 @@
LeaveStubFrame();
}
-void Assembler::CallCFunction(Register reg) {
+void Assembler::CallCFunction(Register reg, bool restore_rsp) {
// Reserve shadow space for outgoing arguments.
if (CallingConventions::kShadowSpaceBytes != 0) {
subq(RSP, Immediate(CallingConventions::kShadowSpaceBytes));
}
call(reg);
+ // Restore stack.
+ if (restore_rsp && CallingConventions::kShadowSpaceBytes != 0) {
+ addq(RSP, Immediate(CallingConventions::kShadowSpaceBytes));
+ }
}
-void Assembler::CallCFunction(Address address) {
+void Assembler::CallCFunction(Address address, bool restore_rsp) {
// Reserve shadow space for outgoing arguments.
if (CallingConventions::kShadowSpaceBytes != 0) {
subq(RSP, Immediate(CallingConventions::kShadowSpaceBytes));
}
call(address);
+ // Restore stack.
+ if (restore_rsp && CallingConventions::kShadowSpaceBytes != 0) {
+ addq(RSP, Immediate(CallingConventions::kShadowSpaceBytes));
+ }
}
void Assembler::CallRuntime(const RuntimeEntry& entry,
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index 19bf03f..f6576ff 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -829,9 +829,9 @@
void CallRuntime(const RuntimeEntry& entry, intptr_t argument_count);
// Call runtime function. Reserves shadow space on the stack before calling
- // if platform ABI requires that. Does not restore RSP after the call itself.
- void CallCFunction(Register reg);
- void CallCFunction(Address address);
+ // if platform ABI requires that.
+ void CallCFunction(Register reg, bool restore_rsp = false);
+ void CallCFunction(Address address, bool restore_rsp = false);
void ExtractClassIdFromTags(Register result, Register tags);
void ExtractInstanceSizeFromTags(Register result, Register tags);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 1c0f9db..e943f75 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -2748,8 +2748,8 @@
const intptr_t dst_container_size = dst_container_type.SizeInBytes();
// This function does not know how to do larger mem copy moves yet.
- ASSERT(src_payload_type.IsFundamental());
- ASSERT(dst_payload_type.IsFundamental());
+ ASSERT(src_payload_type.IsPrimitive());
+ ASSERT(dst_payload_type.IsPrimitive());
// This function does not deal with sign conversions yet.
ASSERT(src_payload_type.IsSigned() == dst_payload_type.IsSigned());
@@ -2773,9 +2773,9 @@
// The upper bits of the source are already properly sign or zero
// extended, so just copy the required amount of bits.
return EmitNativeMove(destination.WithOtherNativeType(
- dst_container_type, dst_container_type, zone_),
+ zone_, dst_container_type, dst_container_type),
source.WithOtherNativeType(
- dst_container_type, dst_container_type, zone_),
+ zone_, dst_container_type, dst_container_type),
temp);
}
if (src_payload_size >= dst_payload_size &&
@@ -2783,9 +2783,9 @@
// The upper bits of the source are not properly sign or zero extended
// to be copied to the target, so regard the source as smaller.
return EmitNativeMove(
- destination.WithOtherNativeType(dst_container_type,
- dst_container_type, zone_),
- source.WithOtherNativeType(dst_payload_type, dst_payload_type, zone_),
+ destination.WithOtherNativeType(zone_, dst_container_type,
+ dst_container_type),
+ source.WithOtherNativeType(zone_, dst_payload_type, dst_payload_type),
temp);
}
UNREACHABLE();
@@ -2800,8 +2800,8 @@
!destination.IsFpuRegisters()) {
// TODO(40209): If this is stack to stack, we could use FpuTMP.
// Test the impact on code size and speed.
- EmitNativeMove(destination.Split(0, zone_), source.Split(0, zone_), temp);
- EmitNativeMove(destination.Split(1, zone_), source.Split(1, zone_), temp);
+ EmitNativeMove(destination.Split(zone_, 0), source.Split(zone_, 0), temp);
+ EmitNativeMove(destination.Split(zone_, 1), source.Split(zone_, 1), temp);
return;
}
@@ -2829,7 +2829,7 @@
if (sign_or_zero_extend && destination.IsStack()) {
ASSERT(source.IsRegisters());
const auto& intermediate =
- source.WithOtherNativeType(dst_payload_type, dst_container_type, zone_);
+ source.WithOtherNativeType(zone_, dst_payload_type, dst_container_type);
EmitNativeMove(intermediate, source, temp);
EmitNativeMove(destination, intermediate, temp);
return;
@@ -2840,7 +2840,7 @@
if (sign_or_zero_extend && source.IsStack()) {
ASSERT(destination.IsRegisters());
const auto& intermediate = destination.WithOtherNativeType(
- src_payload_type, src_container_type, zone_);
+ zone_, src_payload_type, src_container_type);
EmitNativeMove(intermediate, source, temp);
EmitNativeMove(destination, intermediate, temp);
return;
@@ -2875,12 +2875,12 @@
if (src_loc.IsPairLocation()) {
for (intptr_t i : {0, 1}) {
const auto& src_split = compiler::ffi::NativeLocation::FromPairLocation(
- src_loc, src_type, i, zone_);
- EmitNativeMove(dst.Split(i, zone_), src_split, temp);
+ zone_, src_loc, src_type, i);
+ EmitNativeMove(dst.Split(zone_, i), src_split, temp);
}
} else {
const auto& src =
- compiler::ffi::NativeLocation::FromLocation(src_loc, src_type, zone_);
+ compiler::ffi::NativeLocation::FromLocation(zone_, src_loc, src_type);
EmitNativeMove(dst, src, temp);
}
}
@@ -2895,12 +2895,12 @@
if (dst_loc.IsPairLocation()) {
for (intptr_t i : {0, 1}) {
const auto& dest_split = compiler::ffi::NativeLocation::FromPairLocation(
- dst_loc, dst_type, i, zone_);
- EmitNativeMove(dest_split, src.Split(i, zone_), temp);
+ zone_, dst_loc, dst_type, i);
+ EmitNativeMove(dest_split, src.Split(zone_, i), temp);
}
} else {
const auto& dest =
- compiler::ffi::NativeLocation::FromLocation(dst_loc, dst_type, zone_);
+ compiler::ffi::NativeLocation::FromLocation(zone_, dst_loc, dst_type);
EmitNativeMove(dest, src, temp);
}
}
@@ -2935,20 +2935,20 @@
if (src.IsPairLocation()) {
for (intptr_t i : {0, 1}) {
const Representation src_type_split =
- compiler::ffi::NativeType::FromUnboxedRepresentation(src_type,
- zone_)
- .Split(i, zone_)
+ compiler::ffi::NativeType::FromUnboxedRepresentation(zone_,
+ src_type)
+ .Split(zone_, i)
.AsRepresentation();
const auto& intermediate_native =
- compiler::ffi::NativeLocation::FromLocation(intermediate,
- src_type_split, zone_);
+ compiler::ffi::NativeLocation::FromLocation(zone_, intermediate,
+ src_type_split);
EmitMove(intermediate, src.AsPairLocation()->At(i), temp);
- EmitNativeMove(dst.Split(i, zone_), intermediate_native, temp);
+ EmitNativeMove(dst.Split(zone_, i), intermediate_native, temp);
}
} else {
const auto& intermediate_native =
- compiler::ffi::NativeLocation::FromLocation(intermediate, src_type,
- zone_);
+ compiler::ffi::NativeLocation::FromLocation(zone_, intermediate,
+ src_type);
EmitMove(intermediate, src, temp);
EmitNativeMove(dst, intermediate_native, temp);
}
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index d1de64a..66f966d 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -1446,8 +1446,8 @@
ASSERT(src_container_type.IsFloat() == dst_container_type.IsFloat());
ASSERT(src_container_type.IsInt() == dst_container_type.IsInt());
ASSERT(src_payload_type.IsSigned() == dst_payload_type.IsSigned());
- ASSERT(src_payload_type.IsFundamental());
- ASSERT(dst_payload_type.IsFundamental());
+ ASSERT(src_payload_type.IsPrimitive());
+ ASSERT(dst_payload_type.IsPrimitive());
const intptr_t src_size = src_payload_type.SizeInBytes();
const intptr_t dst_size = dst_payload_type.SizeInBytes();
const bool sign_or_zero_extend = dst_size > src_size;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 4ed5b4a..14cb38c 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -1393,8 +1393,8 @@
ASSERT(src_type.IsFloat() == dst_type.IsFloat());
ASSERT(src_type.IsInt() == dst_type.IsInt());
ASSERT(src_type.IsSigned() == dst_type.IsSigned());
- ASSERT(src_type.IsFundamental());
- ASSERT(dst_type.IsFundamental());
+ ASSERT(src_type.IsPrimitive());
+ ASSERT(dst_type.IsPrimitive());
const intptr_t src_size = src_type.SizeInBytes();
const intptr_t dst_size = dst_type.SizeInBytes();
const bool sign_or_zero_extend = dst_size > src_size;
@@ -1420,7 +1420,7 @@
UNIMPLEMENTED();
}
} else {
- switch (src_type.AsFundamental().representation()) {
+ switch (src_type.AsPrimitive().representation()) {
case compiler::ffi::kInt8: // Sign extend operand.
__ sxtb(dst_reg, src_reg);
return;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 6b96aff..83f47d6 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -1302,8 +1302,8 @@
ASSERT(src_type.IsFloat() == dst_type.IsFloat());
ASSERT(src_type.IsInt() == dst_type.IsInt());
ASSERT(src_type.IsSigned() == dst_type.IsSigned());
- ASSERT(src_type.IsFundamental());
- ASSERT(dst_type.IsFundamental());
+ ASSERT(src_type.IsPrimitive());
+ ASSERT(dst_type.IsPrimitive());
const intptr_t src_size = src_type.SizeInBytes();
const intptr_t dst_size = dst_type.SizeInBytes();
const bool sign_or_zero_extend = dst_size > src_size;
@@ -1322,7 +1322,7 @@
ASSERT(dst_size == 4);
__ movl(dst_reg, src_reg);
} else {
- switch (src_type.AsFundamental().representation()) {
+ switch (src_type.AsPrimitive().representation()) {
case compiler::ffi::kInt8: // Sign extend operand.
__ movsxb(dst_reg, ByteRegisterOf(src_reg));
return;
@@ -1410,7 +1410,7 @@
ASSERT(dst_size == 4);
__ movl(dst_reg, src_addr);
} else {
- switch (src_type.AsFundamental().representation()) {
+ switch (src_type.AsPrimitive().representation()) {
case compiler::ffi::kInt8: // Sign extend operand.
__ movsxb(dst_reg, src_addr);
return;
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 72a326f..41e5961 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -1354,8 +1354,8 @@
ASSERT(src_type.IsFloat() == dst_type.IsFloat());
ASSERT(src_type.IsInt() == dst_type.IsInt());
ASSERT(src_type.IsSigned() == dst_type.IsSigned());
- ASSERT(src_type.IsFundamental());
- ASSERT(dst_type.IsFundamental());
+ ASSERT(src_type.IsPrimitive());
+ ASSERT(dst_type.IsPrimitive());
const intptr_t src_size = src_type.SizeInBytes();
const intptr_t dst_size = dst_type.SizeInBytes();
const bool sign_or_zero_extend = dst_size > src_size;
@@ -1381,7 +1381,7 @@
UNIMPLEMENTED();
}
} else {
- switch (src_type.AsFundamental().representation()) {
+ switch (src_type.AsPrimitive().representation()) {
case compiler::ffi::kInt8: // Sign extend operand.
__ movsxb(dst_reg, src_reg);
return;
@@ -1479,7 +1479,7 @@
UNIMPLEMENTED();
}
} else {
- switch (src_type.AsFundamental().representation()) {
+ switch (src_type.AsPrimitive().representation()) {
case compiler::ffi::kInt8: // Sign extend operand.
__ movsxb(dst_reg, src_addr);
return;
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index fafae7a..fa55d52 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -4509,10 +4509,10 @@
// for the two frame pointers and two return addresses of the entry frame.
constexpr intptr_t kEntryFramePadding = 4;
compiler::ffi::FrameRebase rebase(
+ compiler->zone(),
/*old_base=*/SPREG, /*new_base=*/FPREG,
(-kExitLinkSlotFromEntryFp + kEntryFramePadding) *
- compiler::target::kWordSize,
- compiler->zone());
+ compiler::target::kWordSize);
const auto& src =
rebase.Rebase(marshaller_.NativeLocationOfNativeParameter(index_));
NoTemporaryAllocator no_temp;
@@ -6198,8 +6198,9 @@
const Register saved_fp = locs()->temp(0).reg();
const Register temp = locs()->temp(1).reg();
- compiler::ffi::FrameRebase rebase(/*old_base=*/FPREG, /*new_base=*/saved_fp,
- /*stack_delta=*/0, zone_);
+ compiler::ffi::FrameRebase rebase(zone_, /*old_base=*/FPREG,
+ /*new_base=*/saved_fp,
+ /*stack_delta=*/0);
for (intptr_t i = 0, n = NativeArgCount(); i < n; ++i) {
const Location origin = rebase.Rebase(locs()->in(i));
const Representation origin_rep = RequiredInputRepresentation(i);
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index cdc4f79..50b1287 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -1082,7 +1082,7 @@
__ TransitionGeneratedToNative(target_address, FPREG, TMP,
/*enter_safepoint=*/true);
- __ CallCFunction(target_address);
+ __ CallCFunction(target_address, /*restore_rsp=*/true);
// Update information in the thread object and leave the safepoint.
__ TransitionNativeToGenerated(/*leave_safepoint=*/true);
diff --git a/runtime/vm/compiler/ffi/frame_rebase.h b/runtime/vm/compiler/ffi/frame_rebase.h
index ba58a5c..618d33f 100644
--- a/runtime/vm/compiler/ffi/frame_rebase.h
+++ b/runtime/vm/compiler/ffi/frame_rebase.h
@@ -31,24 +31,24 @@
// This class can be used to rebase both Locations and NativeLocations.
class FrameRebase : public ValueObject {
public:
- FrameRebase(const Register old_base,
+ FrameRebase(Zone* zone,
+ const Register old_base,
const Register new_base,
- intptr_t stack_delta_in_bytes,
- Zone* zone)
- : old_base_(old_base),
+ intptr_t stack_delta_in_bytes)
+ : zone_(zone),
+ old_base_(old_base),
new_base_(new_base),
- stack_delta_in_bytes_(stack_delta_in_bytes),
- zone_(zone) {}
+ stack_delta_in_bytes_(stack_delta_in_bytes) {}
const NativeLocation& Rebase(const NativeLocation& loc) const;
Location Rebase(const Location loc) const;
private:
+ Zone* zone_;
const Register old_base_;
const Register new_base_;
const intptr_t stack_delta_in_bytes_;
- Zone* zone_;
};
} // namespace ffi
diff --git a/runtime/vm/compiler/ffi/marshaller.cc b/runtime/vm/compiler/ffi/marshaller.cc
index 09dd56d..c095e9e 100644
--- a/runtime/vm/compiler/ffi/marshaller.cc
+++ b/runtime/vm/compiler/ffi/marshaller.cc
@@ -78,8 +78,8 @@
class CallbackArgumentTranslator : public ValueObject {
public:
static NativeLocations& TranslateArgumentLocations(
- const NativeLocations& arg_locs,
- Zone* zone) {
+ Zone* zone,
+ const NativeLocations& arg_locs) {
auto& pushed_locs = *(new NativeLocations(arg_locs.length()));
CallbackArgumentTranslator translator;
@@ -122,10 +122,10 @@
stack_delta += StubCodeCompiler::kNativeCallbackTrampolineStackDelta;
}
FrameRebase rebase(
+ zone,
/*old_base=*/SPREG, /*new_base=*/SPREG,
/*stack_delta=*/(argument_slots_required_ + stack_delta) *
- compiler::target::kWordSize,
- zone);
+ compiler::target::kWordSize);
return rebase.Rebase(arg);
}
@@ -153,8 +153,8 @@
const Function& dart_signature)
: BaseMarshaller(zone, dart_signature),
callback_locs_(
- CallbackArgumentTranslator::TranslateArgumentLocations(arg_locs_,
- zone_)) {}
+ CallbackArgumentTranslator::TranslateArgumentLocations(zone_,
+ arg_locs_)) {}
} // namespace ffi
diff --git a/runtime/vm/compiler/ffi/native_calling_convention.cc b/runtime/vm/compiler/ffi/native_calling_convention.cc
index 47f6adc..84081aa 100644
--- a/runtime/vm/compiler/ffi/native_calling_convention.cc
+++ b/runtime/vm/compiler/ffi/native_calling_convention.cc
@@ -31,14 +31,14 @@
}
// In Soft FP, floats are treated as 4 byte ints, and doubles as 8 byte ints.
-static const NativeType& ConvertIfSoftFp(const NativeType& rep, Zone* zone) {
+static const NativeType& ConvertIfSoftFp(Zone* zone, const NativeType& rep) {
if (SoftFpAbi() && rep.IsFloat()) {
ASSERT(rep.IsFloat());
if (rep.SizeInBytes() == 4) {
- return *new (zone) NativeFundamentalType(kInt32);
+ return *new (zone) NativePrimitiveType(kInt32);
}
if (rep.SizeInBytes() == 8) {
- return *new (zone) NativeFundamentalType(kInt64);
+ return *new (zone) NativePrimitiveType(kInt64);
}
}
return rep;
@@ -46,25 +46,25 @@
// Representations of the arguments to a C signature function.
static ZoneGrowableArray<const NativeType*>& ArgumentRepresentations(
- const Function& signature,
- Zone* zone) {
+ Zone* zone,
+ const Function& signature) {
const intptr_t num_arguments =
signature.num_fixed_parameters() - kNativeParamsStartAt;
auto& result = *new ZoneGrowableArray<const NativeType*>(zone, num_arguments);
for (intptr_t i = 0; i < num_arguments; i++) {
AbstractType& arg_type = AbstractType::Handle(
zone, signature.ParameterTypeAt(i + kNativeParamsStartAt));
- const auto& rep = NativeType::FromAbstractType(arg_type, zone);
+ const auto& rep = NativeType::FromAbstractType(zone, arg_type);
result.Add(&rep);
}
return result;
}
// Representation of the result of a C signature function.
-static NativeType& ResultRepresentation(const Function& signature, Zone* zone) {
+static NativeType& ResultRepresentation(Zone* zone, const Function& signature) {
AbstractType& result_type =
AbstractType::Handle(zone, signature.result_type());
- return NativeType::FromAbstractType(result_type, zone);
+ return NativeType::FromAbstractType(zone, result_type);
}
// Represents the state of a stack frame going into a call, between allocations
@@ -74,7 +74,7 @@
explicit ArgumentAllocator(Zone* zone) : zone_(zone) {}
const NativeLocation& AllocateArgument(const NativeType& payload_type) {
- const auto& payload_type_converted = ConvertIfSoftFp(payload_type, zone_);
+ const auto& payload_type_converted = ConvertIfSoftFp(zone_, payload_type);
if (payload_type_converted.IsFloat()) {
const auto kind = FpuRegKind(payload_type);
const intptr_t reg_index = FirstFreeFpuRegisterIndex(kind);
@@ -224,8 +224,8 @@
// Location for the arguments of a C signature function.
static NativeLocations& ArgumentLocations(
- const ZoneGrowableArray<const NativeType*>& arg_reps,
- Zone* zone) {
+ Zone* zone,
+ const ZoneGrowableArray<const NativeType*>& arg_reps) {
intptr_t num_arguments = arg_reps.length();
auto& result = *new NativeLocations(zone, num_arguments);
@@ -239,9 +239,9 @@
}
// Location for the result of a C signature function.
-static NativeLocation& ResultLocation(const NativeType& payload_type,
- Zone* zone) {
- const auto& payload_type_converted = ConvertIfSoftFp(payload_type, zone);
+static NativeLocation& ResultLocation(Zone* zone,
+ const NativeType& payload_type) {
+ const auto& payload_type_converted = ConvertIfSoftFp(zone, payload_type);
const auto& container_type =
CallingConventions::kReturnRegisterExtension == kExtendedTo4
? payload_type_converted.WidenTo4Bytes(zone)
@@ -267,10 +267,11 @@
const Function& c_signature)
: zone_(ASSERT_NOTNULL(zone)),
c_signature_(c_signature),
- arg_locs_(ArgumentLocations(ArgumentRepresentations(c_signature_, zone_),
- zone_)),
+ arg_locs_(
+ ArgumentLocations(zone_,
+ ArgumentRepresentations(zone_, c_signature_))),
result_loc_(
- ResultLocation(ResultRepresentation(c_signature_, zone_), zone_)) {}
+ ResultLocation(zone_, ResultRepresentation(zone_, c_signature_))) {}
intptr_t NativeCallingConvention::num_args() const {
ASSERT(c_signature_.NumOptionalParameters() == 0);
diff --git a/runtime/vm/compiler/ffi/native_location.cc b/runtime/vm/compiler/ffi/native_location.cc
index bbc762e..f954e9f 100644
--- a/runtime/vm/compiler/ffi/native_location.cc
+++ b/runtime/vm/compiler/ffi/native_location.cc
@@ -29,14 +29,14 @@
return false;
}
-NativeLocation& NativeLocation::FromLocation(Location loc,
- Representation rep,
- Zone* zone) {
+NativeLocation& NativeLocation::FromLocation(Zone* zone,
+ Location loc,
+ Representation rep) {
// TODO(36730): We could possibly consume a pair location as struct.
ASSERT(LocationCanBeExpressed(loc, rep));
const NativeType& native_rep =
- NativeType::FromUnboxedRepresentation(rep, zone);
+ NativeType::FromUnboxedRepresentation(zone, rep);
switch (loc.kind()) {
case Location::Kind::kRegister:
@@ -61,18 +61,18 @@
}
// TODO(36730): Remove when being able to consume as struct.
-NativeLocation& NativeLocation::FromPairLocation(Location pair_loc,
+NativeLocation& NativeLocation::FromPairLocation(Zone* zone,
+ Location pair_loc,
Representation pair_rep,
- intptr_t index,
- Zone* zone) {
+ intptr_t index) {
ASSERT(pair_loc.IsPairLocation());
ASSERT(index == 0 || index == 1);
const Representation rep =
- NativeType::FromUnboxedRepresentation(pair_rep, zone)
- .Split(index, zone)
+ NativeType::FromUnboxedRepresentation(zone, pair_rep)
+ .Split(zone, index)
.AsRepresentation();
const Location loc = pair_loc.AsPairLocation()->At(index);
- return FromLocation(loc, rep, zone);
+ return FromLocation(zone, loc, rep);
}
const NativeRegistersLocation& NativeLocation::AsRegisters() const {
@@ -117,36 +117,36 @@
}
} else {
ASSERT(payload_type().IsFloat());
- if (payload_type().AsFundamental().representation() == kFloat) {
+ if (payload_type().AsPrimitive().representation() == kFloat) {
return Location::StackSlot(offset_in_words(), base_register_);
} else {
- ASSERT(payload_type().AsFundamental().representation() == kDouble);
+ ASSERT(payload_type().AsPrimitive().representation() == kDouble);
return Location::DoubleStackSlot(offset_in_words(), base_register_);
}
}
UNREACHABLE();
}
-NativeRegistersLocation& NativeRegistersLocation::Split(intptr_t index,
- Zone* zone) const {
+NativeRegistersLocation& NativeRegistersLocation::Split(Zone* zone,
+ intptr_t index) const {
ASSERT(num_regs() == 2);
return *new (zone) NativeRegistersLocation(
- payload_type().Split(index, zone), container_type().Split(index, zone),
+ payload_type().Split(zone, index), container_type().Split(zone, index),
reg_at(index));
}
-NativeStackLocation& NativeStackLocation::Split(intptr_t index,
- Zone* zone) const {
+NativeStackLocation& NativeStackLocation::Split(Zone* zone,
+ intptr_t index) const {
ASSERT(index == 0 || index == 1);
const intptr_t size = payload_type().SizeInBytes();
return *new (zone) NativeStackLocation(
- payload_type().Split(index, zone), container_type().Split(index, zone),
+ payload_type().Split(zone, index), container_type().Split(zone, index),
base_register_, offset_in_bytes_ + size / 2 * index);
}
NativeLocation& NativeLocation::WidenTo4Bytes(Zone* zone) const {
- return WithOtherNativeType(payload_type().WidenTo4Bytes(zone),
- container_type().WidenTo4Bytes(zone), zone);
+ return WithOtherNativeType(zone, payload_type().WidenTo4Bytes(zone),
+ container_type().WidenTo4Bytes(zone));
}
#if defined(TARGET_ARCH_ARM)
diff --git a/runtime/vm/compiler/ffi/native_location.h b/runtime/vm/compiler/ffi/native_location.h
index fefee76..78caa24 100644
--- a/runtime/vm/compiler/ffi/native_location.h
+++ b/runtime/vm/compiler/ffi/native_location.h
@@ -54,13 +54,13 @@
class NativeLocation : public ZoneAllocated {
public:
static bool LocationCanBeExpressed(Location loc, Representation rep);
- static NativeLocation& FromLocation(Location loc,
- Representation rep,
- Zone* zone);
- static NativeLocation& FromPairLocation(Location loc,
+ static NativeLocation& FromLocation(Zone* zone,
+ Location loc,
+ Representation rep);
+ static NativeLocation& FromPairLocation(Zone* zone,
+ Location loc,
Representation rep,
- intptr_t index,
- Zone* zone);
+ intptr_t index);
// The type of the data at this location.
const NativeType& payload_type() const { return payload_type_; }
@@ -74,9 +74,9 @@
const NativeType& container_type() const { return container_type_; }
virtual NativeLocation& WithOtherNativeType(
+ Zone* zone,
const NativeType& new_payload_type,
- const NativeType& new_container_type,
- Zone* zone) const = 0;
+ const NativeType& new_container_type) const = 0;
#if defined(TARGET_ARCH_ARM)
const NativeLocation& WidenToQFpuRegister(Zone* zone) const;
@@ -101,7 +101,7 @@
const NativeFpuRegistersLocation& AsFpuRegisters() const;
const NativeStackLocation& AsStack() const;
- virtual NativeLocation& Split(intptr_t index, Zone* zone) const {
+ virtual NativeLocation& Split(Zone* zone, intptr_t index) const {
ASSERT(index == 0 || index == 1);
UNREACHABLE();
}
@@ -152,9 +152,9 @@
virtual ~NativeRegistersLocation() {}
virtual NativeRegistersLocation& WithOtherNativeType(
+ Zone* zone,
const NativeType& new_payload_type,
- const NativeType& new_container_type,
- Zone* zone) const {
+ const NativeType& new_container_type) const {
return *new (zone)
NativeRegistersLocation(new_payload_type, new_container_type, regs_);
}
@@ -167,7 +167,7 @@
intptr_t num_regs() const { return regs_->length(); }
Register reg_at(intptr_t index) const { return regs_->At(index); }
- virtual NativeRegistersLocation& Split(intptr_t index, Zone* zone) const;
+ virtual NativeRegistersLocation& Split(Zone* zone, intptr_t index) const;
virtual void PrintTo(BaseTextBuffer* f) const;
@@ -220,9 +220,9 @@
virtual ~NativeFpuRegistersLocation() {}
virtual NativeFpuRegistersLocation& WithOtherNativeType(
+ Zone* zone,
const NativeType& new_payload_type,
- const NativeType& new_container_type,
- Zone* zone) const {
+ const NativeType& new_container_type) const {
return *new (zone) NativeFpuRegistersLocation(
new_payload_type, new_container_type, fpu_reg_kind_, fpu_reg_);
}
@@ -276,9 +276,9 @@
virtual ~NativeStackLocation() {}
virtual NativeStackLocation& WithOtherNativeType(
+ Zone* zone,
const NativeType& new_payload_type,
- const NativeType& new_container_type,
- Zone* zone) const {
+ const NativeType& new_container_type) const {
return *new (zone) NativeStackLocation(new_payload_type, new_container_type,
base_register_, offset_in_bytes_);
}
@@ -301,7 +301,7 @@
return Location::DoubleStackSlot(offset_in_words(), base_register_);
}
- virtual NativeStackLocation& Split(intptr_t index, Zone* zone) const;
+ virtual NativeStackLocation& Split(Zone* zone, intptr_t index) const;
virtual void PrintTo(BaseTextBuffer* f) const;
diff --git a/runtime/vm/compiler/ffi/native_type.cc b/runtime/vm/compiler/ffi/native_type.cc
index e4daa47..5bb9f4c 100644
--- a/runtime/vm/compiler/ffi/native_type.cc
+++ b/runtime/vm/compiler/ffi/native_type.cc
@@ -19,12 +19,12 @@
namespace ffi {
-const NativeFundamentalType& NativeType::AsFundamental() const {
- ASSERT(IsFundamental());
- return static_cast<const NativeFundamentalType&>(*this);
+const NativePrimitiveType& NativeType::AsPrimitive() const {
+ ASSERT(IsPrimitive());
+ return static_cast<const NativePrimitiveType&>(*this);
}
-bool NativeFundamentalType::IsInt() const {
+bool NativePrimitiveType::IsInt() const {
switch (representation_) {
case kInt8:
case kUint8:
@@ -40,16 +40,16 @@
}
}
-bool NativeFundamentalType::IsFloat() const {
+bool NativePrimitiveType::IsFloat() const {
return representation_ == kFloat || representation_ == kDouble ||
representation_ == kHalfDouble;
}
-bool NativeFundamentalType::IsVoid() const {
+bool NativePrimitiveType::IsVoid() const {
return representation_ == kVoid;
}
-bool NativeFundamentalType::IsSigned() const {
+bool NativePrimitiveType::IsSigned() const {
ASSERT(IsInt() || IsFloat());
switch (representation_) {
case kInt8:
@@ -84,11 +84,11 @@
0, // kVoid,
};
-intptr_t NativeFundamentalType::SizeInBytes() const {
+intptr_t NativePrimitiveType::SizeInBytes() const {
return fundamental_size_in_bytes[representation_];
}
-intptr_t NativeFundamentalType::AlignmentInBytesStack() const {
+intptr_t NativePrimitiveType::AlignmentInBytesStack() const {
switch (CallingConventions::kArgumentStackAlignment) {
case kAlignedToWordSize:
// The default is to align stack arguments to word size.
@@ -108,7 +108,7 @@
}
}
-intptr_t NativeFundamentalType::AlignmentInBytesField() const {
+intptr_t NativePrimitiveType::AlignmentInBytesField() const {
switch (CallingConventions::kFieldAlignment) {
case kAlignedToValueSize:
// The default is to align fields to their own size.
@@ -127,7 +127,7 @@
}
#if !defined(DART_PRECOMPILED_RUNTIME)
-bool NativeFundamentalType::IsExpressibleAsRepresentation() const {
+bool NativePrimitiveType::IsExpressibleAsRepresentation() const {
switch (representation_) {
case kInt8:
case kUint8:
@@ -149,7 +149,7 @@
}
}
-Representation NativeFundamentalType::AsRepresentation() const {
+Representation NativePrimitiveType::AsRepresentation() const {
ASSERT(IsExpressibleAsRepresentation());
switch (representation_) {
case kInt32:
@@ -171,14 +171,14 @@
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
-bool NativeFundamentalType::Equals(const NativeType& other) const {
- if (!other.IsFundamental()) {
+bool NativePrimitiveType::Equals(const NativeType& other) const {
+ if (!other.IsPrimitive()) {
return false;
}
- return other.AsFundamental().representation_ == representation_;
+ return other.AsPrimitive().representation_ == representation_;
}
-static FundamentalType split_fundamental(FundamentalType in) {
+static PrimitiveType split_fundamental(PrimitiveType in) {
switch (in) {
case kInt16:
return kInt8;
@@ -199,14 +199,14 @@
}
}
-NativeFundamentalType& NativeFundamentalType::Split(intptr_t index,
- Zone* zone) const {
+NativePrimitiveType& NativePrimitiveType::Split(Zone* zone,
+ intptr_t index) const {
ASSERT(index == 0 || index == 1);
auto new_rep = split_fundamental(representation());
- return *new (zone) NativeFundamentalType(new_rep);
+ return *new (zone) NativePrimitiveType(new_rep);
}
-static FundamentalType TypeRepresentation(classid_t class_id) {
+static PrimitiveType TypeRepresentation(classid_t class_id) {
switch (class_id) {
case kFfiInt8Cid:
return kInt8;
@@ -242,19 +242,19 @@
}
}
-NativeType& NativeType::FromTypedDataClassId(classid_t class_id, Zone* zone) {
+NativeType& NativeType::FromTypedDataClassId(Zone* zone, classid_t class_id) {
// TODO(36730): Support composites.
const auto fundamental_rep = TypeRepresentation(class_id);
- return *new (zone) NativeFundamentalType(fundamental_rep);
+ return *new (zone) NativePrimitiveType(fundamental_rep);
}
-NativeType& NativeType::FromAbstractType(const AbstractType& type, Zone* zone) {
+NativeType& NativeType::FromAbstractType(Zone* zone, const AbstractType& type) {
// TODO(36730): Support composites.
- return NativeType::FromTypedDataClassId(type.type_class_id(), zone);
+ return NativeType::FromTypedDataClassId(zone, type.type_class_id());
}
#if !defined(DART_PRECOMPILED_RUNTIME)
-static FundamentalType fundamental_rep(Representation rep) {
+static PrimitiveType fundamental_rep(Representation rep) {
switch (rep) {
case kUnboxedDouble:
return kDouble;
@@ -272,9 +272,9 @@
UNREACHABLE();
}
-NativeFundamentalType& NativeType::FromUnboxedRepresentation(Representation rep,
- Zone* zone) {
- return *new (zone) NativeFundamentalType(fundamental_rep(rep));
+NativePrimitiveType& NativeType::FromUnboxedRepresentation(Zone* zone,
+ Representation rep) {
+ return *new (zone) NativePrimitiveType(fundamental_rep(rep));
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
@@ -285,7 +285,7 @@
return Thread::Current()->zone()->MakeCopyOfString(buffer);
}
-static const char* FundamentalTypeToCString(FundamentalType rep) {
+static const char* PrimitiveTypeToCString(PrimitiveType rep) {
switch (rep) {
case kInt8:
return "int8";
@@ -320,16 +320,16 @@
f->AddString("I");
}
-void NativeFundamentalType::PrintTo(BaseTextBuffer* f) const {
- f->Printf("%s", FundamentalTypeToCString(representation_));
+void NativePrimitiveType::PrintTo(BaseTextBuffer* f) const {
+ f->Printf("%s", PrimitiveTypeToCString(representation_));
}
const NativeType& NativeType::WidenTo4Bytes(Zone* zone) const {
if (IsInt() && SizeInBytes() <= 2) {
if (IsSigned()) {
- return *new (zone) NativeFundamentalType(kInt32);
+ return *new (zone) NativePrimitiveType(kInt32);
} else {
- return *new (zone) NativeFundamentalType(kUint32);
+ return *new (zone) NativePrimitiveType(kUint32);
}
}
return *this;
diff --git a/runtime/vm/compiler/ffi/native_type.h b/runtime/vm/compiler/ffi/native_type.h
index b0dc39b..66d5f31 100644
--- a/runtime/vm/compiler/ffi/native_type.h
+++ b/runtime/vm/compiler/ffi/native_type.h
@@ -23,7 +23,7 @@
namespace ffi {
-class NativeFundamentalType;
+class NativePrimitiveType;
// NativeTypes are the types used in calling convention specifications:
// integers, floats, and composites.
@@ -38,29 +38,29 @@
//
// Instead, NativeTypes support representations not supported in Dart's unboxed
// Representations, such as:
-// * Fundamental types (https://en.cppreference.com/w/cpp/language/types):
+// * Primitive types:
// * int8_t
// * int16_t
// * uint8_t
// * uint16t
// * void
-// * Compound types (https://en.cppreference.com/w/cpp/language/type):
+// * Compound types:
// * Struct
// * Union
//
// TODO(36730): Add composites.
class NativeType : public ZoneAllocated {
public:
- static NativeType& FromAbstractType(const AbstractType& type, Zone* zone);
- static NativeType& FromTypedDataClassId(classid_t class_id, Zone* zone);
+ static NativeType& FromAbstractType(Zone* zone, const AbstractType& type);
+ static NativeType& FromTypedDataClassId(Zone* zone, classid_t class_id);
#if !defined(DART_PRECOMPILED_RUNTIME)
- static NativeFundamentalType& FromUnboxedRepresentation(Representation rep,
- Zone* zone);
+ static NativePrimitiveType& FromUnboxedRepresentation(Zone* zone,
+ Representation rep);
#endif
- virtual bool IsFundamental() const { return false; }
- const NativeFundamentalType& AsFundamental() const;
+ virtual bool IsPrimitive() const { return false; }
+ const NativePrimitiveType& AsPrimitive() const;
virtual bool IsInt() const { return false; }
virtual bool IsFloat() const { return false; }
@@ -96,7 +96,7 @@
virtual bool Equals(const NativeType& other) const { UNREACHABLE(); }
// Split representation in two.
- virtual NativeType& Split(intptr_t index, Zone* zone) const { UNREACHABLE(); }
+ virtual NativeType& Split(Zone* zone, intptr_t index) const { UNREACHABLE(); }
// If this is a 8 or 16 bit int, returns a 32 bit container.
// Otherwise, return original representation.
@@ -111,7 +111,7 @@
NativeType() {}
};
-enum FundamentalType {
+enum PrimitiveType {
kInt8,
kUint8,
kInt16,
@@ -127,13 +127,19 @@
// TODO(37470): Add packed data structures.
};
-class NativeFundamentalType : public NativeType {
+// Represents a primitive native type.
+//
+// These are called object types in the C standard (ISO/IEC 9899:2011) and
+// fundamental types in C++ (https://en.cppreference.com/w/cpp/language/types)
+// but more commonly these are called primitive types
+// (https://en.wikipedia.org/wiki/Primitive_data_type).
+class NativePrimitiveType : public NativeType {
public:
- explicit NativeFundamentalType(FundamentalType rep) : representation_(rep) {}
+ explicit NativePrimitiveType(PrimitiveType rep) : representation_(rep) {}
- FundamentalType representation() const { return representation_; }
+ PrimitiveType representation() const { return representation_; }
- virtual bool IsFundamental() const { return true; }
+ virtual bool IsPrimitive() const { return true; }
virtual bool IsInt() const;
virtual bool IsFloat() const;
@@ -151,14 +157,14 @@
#endif // !defined(DART_PRECOMPILED_RUNTIME)
virtual bool Equals(const NativeType& other) const;
- virtual NativeFundamentalType& Split(intptr_t part, Zone* zone) const;
+ virtual NativePrimitiveType& Split(Zone* zone, intptr_t part) const;
virtual void PrintTo(BaseTextBuffer* f) const;
- virtual ~NativeFundamentalType() {}
+ virtual ~NativePrimitiveType() {}
private:
- const FundamentalType representation_;
+ const PrimitiveType representation_;
};
} // namespace ffi
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 7bcb54a..48aae11 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1255,7 +1255,7 @@
const classid_t typed_data_cid =
compiler::ffi::ElementTypedDataCid(ffi_type_arg_cid);
const auto& native_rep = compiler::ffi::NativeType::FromTypedDataClassId(
- ffi_type_arg_cid, zone_);
+ zone_, ffi_type_arg_cid);
ASSERT(function.NumParameters() == 2);
LocalVariable* arg_pointer = parsed_function_->RawParameterVariable(0);
@@ -1336,7 +1336,7 @@
const classid_t typed_data_cid =
compiler::ffi::ElementTypedDataCid(ffi_type_arg_cid);
const auto& native_rep = compiler::ffi::NativeType::FromTypedDataClassId(
- ffi_type_arg_cid, zone_);
+ zone_, ffi_type_arg_cid);
LocalVariable* arg_pointer = parsed_function_->RawParameterVariable(0);
LocalVariable* arg_offset = parsed_function_->RawParameterVariable(1);
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index 26f8292..b3c99af 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -282,7 +282,7 @@
/*enter_safepoint=*/true);
__ popq(R12);
- __ CallCFunction(RBX);
+ __ CallCFunction(RBX, /*restore_rsp=*/true);
__ TransitionNativeToGenerated(/*leave_safepoint=*/true);
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index dc2e794..c1fb6c3 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -304,6 +304,16 @@
// same time? (Windows no, rest yes)
static const bool kArgumentIntRegXorFpuReg = true;
+ // > The x64 Application Binary Interface (ABI) uses a four-register
+ // > fast-call calling convention by default. Space is allocated on the call
+ // > stack as a shadow store for callees to save those registers.
+ // https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-160
+ //
+ // The caller allocates this space. The caller should also reclaim this space
+ // after the call to restore the stack to its original state if needed.
+ //
+ // This is also known as home space.
+ // https://devblogs.microsoft.com/oldnewthing/20160623-00/?p=93735
static const intptr_t kShadowSpaceBytes = 4 * kWordSize;
static const intptr_t kVolatileCpuRegisters =
diff --git a/tests/corelib/reg_exp_all_matches_test.dart b/tests/corelib/reg_exp_all_matches_test.dart
index 54fbf10..a289723 100644
--- a/tests/corelib/reg_exp_all_matches_test.dart
+++ b/tests/corelib/reg_exp_all_matches_test.dart
@@ -10,7 +10,7 @@
static testIterator() {
var matches = new RegExp("foo").allMatches("foo foo");
Iterator it = matches.iterator;
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
Expect.throws(() => it.current);
} else {
Expect.isNull(it.current);
diff --git a/tests/dart2js/internal/rti/required_named_parameters_test.dart b/tests/dart2js/internal/rti/required_named_parameters_test.dart
index c07f7a4..ccf3f7d 100644
--- a/tests/dart2js/internal/rti/required_named_parameters_test.dart
+++ b/tests/dart2js/internal/rti/required_named_parameters_test.dart
@@ -51,11 +51,13 @@
// Subtype may not redeclare optional parameters as required
rti2 = rti.testingUniverseEval(universe, "@(A,{a!A,b!A,c!A})");
- Expect.equals(isWeakMode, rti.testingIsSubtype(universe, rti2, rti1));
+ Expect.equals(
+ hasUnsoundNullSafety, rti.testingIsSubtype(universe, rti2, rti1));
// Subtype may not declare new required named parameters
rti2 = rti.testingUniverseEval(universe, "@(A,{a!A,b:A,c!A,d!A})");
- Expect.equals(isWeakMode, rti.testingIsSubtype(universe, rti2, rti1));
+ Expect.equals(
+ hasUnsoundNullSafety, rti.testingIsSubtype(universe, rti2, rti1));
// Rti.toString() appears as expected
Expect.equals('(B, {required B a, B b, required B c}) => dynamic',
diff --git a/tests/dart2js/internal/rti/subtype_test.dart b/tests/dart2js/internal/rti/subtype_test.dart
index 68f4de7..d4f0c48 100644
--- a/tests/dart2js/internal/rti/subtype_test.dart
+++ b/tests/dart2js/internal/rti/subtype_test.dart
@@ -78,7 +78,7 @@
}
void testNull() {
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
unrelated(nullName, 'int');
unrelated(nullName, 'Iterable<CodeUnits>');
unrelated(nullName, objectName);
@@ -93,7 +93,7 @@
void testBottom() {
String never = '0&';
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
strictSubtype(never, nullName);
} else {
equivalent(never, nullName);
diff --git a/tests/dart2js_2/internal/rti/required_named_parameters_test.dart b/tests/dart2js_2/internal/rti/required_named_parameters_test.dart
index c07f7a4..ccf3f7d 100644
--- a/tests/dart2js_2/internal/rti/required_named_parameters_test.dart
+++ b/tests/dart2js_2/internal/rti/required_named_parameters_test.dart
@@ -51,11 +51,13 @@
// Subtype may not redeclare optional parameters as required
rti2 = rti.testingUniverseEval(universe, "@(A,{a!A,b!A,c!A})");
- Expect.equals(isWeakMode, rti.testingIsSubtype(universe, rti2, rti1));
+ Expect.equals(
+ hasUnsoundNullSafety, rti.testingIsSubtype(universe, rti2, rti1));
// Subtype may not declare new required named parameters
rti2 = rti.testingUniverseEval(universe, "@(A,{a!A,b:A,c!A,d!A})");
- Expect.equals(isWeakMode, rti.testingIsSubtype(universe, rti2, rti1));
+ Expect.equals(
+ hasUnsoundNullSafety, rti.testingIsSubtype(universe, rti2, rti1));
// Rti.toString() appears as expected
Expect.equals('(B, {required B a, B b, required B c}) => dynamic',
diff --git a/tests/language/function_subtype/bound_closure5_test.dart b/tests/language/function_subtype/bound_closure5_test.dart
index 1844a42..d498a19 100644
--- a/tests/language/function_subtype/bound_closure5_test.dart
+++ b/tests/language/function_subtype/bound_closure5_test.dart
@@ -39,7 +39,7 @@
new D<String, bool>().test('bool', true);
new D<bool, int>().test('int', false);
new D<Object, Object>().test('Object', false);
- new D<Null, Null>().test('Null', isWeakMode);
+ new D<Null, Null>().test('Null', hasUnsoundNullSafety);
new D<Never, Never>().test('Never', true);
new D<dynamic, dynamic>().test('dynamic', false);
}
diff --git a/tests/language/function_subtype/bound_closure5a_test.dart b/tests/language/function_subtype/bound_closure5a_test.dart
index 38b173d..b5d274b 100644
--- a/tests/language/function_subtype/bound_closure5a_test.dart
+++ b/tests/language/function_subtype/bound_closure5a_test.dart
@@ -41,7 +41,7 @@
new D<String, bool>().test('bool', true);
new D<bool, int>().test('int', false);
new D<Object, Object>().test('Object', false);
- new D<Null, Null>().test('Null', isWeakMode);
+ new D<Null, Null>().test('Null', hasUnsoundNullSafety);
new D<Never, Never>().test('Never', true);
new D<dynamic, dynamic>().test('dynamic', false);
}
diff --git a/tests/language/function_subtype/bound_closure6_test.dart b/tests/language/function_subtype/bound_closure6_test.dart
index e26d21f..ea119a5 100644
--- a/tests/language/function_subtype/bound_closure6_test.dart
+++ b/tests/language/function_subtype/bound_closure6_test.dart
@@ -42,6 +42,6 @@
new C<int>().test('int', false);
new C<Object>().test('Object', false);
new C<dynamic>().test('dynamic', false);
- new C<Null>().test('Null', isWeakMode);
+ new C<Null>().test('Null', hasUnsoundNullSafety);
new C<Never>().test('Never', true);
}
diff --git a/tests/language/function_subtype/cast2_test.dart b/tests/language/function_subtype/cast2_test.dart
index 03a8f53..5e0f5b7 100644
--- a/tests/language/function_subtype/cast2_test.dart
+++ b/tests/language/function_subtype/cast2_test.dart
@@ -26,7 +26,7 @@
void main() {
new Class<dynamic>().test(false, bar, "dynamic");
new Class<Object>().test(false, bar, "Object");
- new Class<Null>().test(isWeakMode, bar, "Null");
+ new Class<Null>().test(hasUnsoundNullSafety, bar, "Null");
new Class<Never>().test(true, bar, "Never");
new Class<int>().test(true, bar, "int");
new Class<bool>().test(false, bar, "bool");
diff --git a/tests/language/function_subtype/checked0_test.dart b/tests/language/function_subtype/checked0_test.dart
index a314529..40abf58 100644
--- a/tests/language/function_subtype/checked0_test.dart
+++ b/tests/language/function_subtype/checked0_test.dart
@@ -69,6 +69,6 @@
new C<int>().test('int', false);
new C<dynamic>().test('dynamic', false);
new C<Object>().test('Object', false);
- new C<Null>().test('Null', isWeakMode);
+ new C<Null>().test('Null', hasUnsoundNullSafety);
new C<Never>().test('Null', true);
}
diff --git a/tests/language/function_subtype/inline0_test.dart b/tests/language/function_subtype/inline0_test.dart
index 4e99998..c28d1d0 100644
--- a/tests/language/function_subtype/inline0_test.dart
+++ b/tests/language/function_subtype/inline0_test.dart
@@ -41,7 +41,7 @@
}
main() {
- new C<bool>().test('bool', true, isWeakMode);
+ new C<bool>().test('bool', true, hasUnsoundNullSafety);
new C<int>().test('int', false, false);
- new C<dynamic>().test('dynamic', true, isWeakMode);
+ new C<dynamic>().test('dynamic', true, hasUnsoundNullSafety);
}
diff --git a/tests/language/function_subtype/inline2_test.dart b/tests/language/function_subtype/inline2_test.dart
index a3f4078..2f63a3d 100644
--- a/tests/language/function_subtype/inline2_test.dart
+++ b/tests/language/function_subtype/inline2_test.dart
@@ -23,7 +23,7 @@
testDynamicTypeError(false, () => f(m1), "'new C.$constructorName(m1)'");
testDynamicTypeError(true, () => f(m2), "'new C.$constructorName(m2)'");
testDynamicTypeError(
- isStrongMode, () => f(m3), "'new C.$constructorName(m3)'");
+ hasSoundNullSafety, () => f(m3), "'new C.$constructorName(m3)'");
testDynamicTypeError(true, () => f(m4), "'new C.$constructorName(m4)'");
testDynamicTypeError(false, () => f(m5), "'new C.$constructorName(m5)'");
}
diff --git a/tests/language/function_subtype/local2_test.dart b/tests/language/function_subtype/local2_test.dart
index 7b0d19d..fe3de21 100644
--- a/tests/language/function_subtype/local2_test.dart
+++ b/tests/language/function_subtype/local2_test.dart
@@ -38,6 +38,6 @@
new C<int>().test('int', false);
new C<dynamic>().test('dynamic', false);
new C<Object>().test('Object', false);
- new C<Null>().test('Null', isWeakMode);
+ new C<Null>().test('Null', hasUnsoundNullSafety);
new C<Never>().test('Never', true);
}
diff --git a/tests/language/function_subtype/local5_test.dart b/tests/language/function_subtype/local5_test.dart
index 92d570f..18c887c 100644
--- a/tests/language/function_subtype/local5_test.dart
+++ b/tests/language/function_subtype/local5_test.dart
@@ -40,6 +40,6 @@
new D<bool, int>().test('int', false);
new D<dynamic, dynamic>().test('dynamic', false);
new D<Object, Object>().test('Object', false);
- new D<Null, Null>().test('Null', isWeakMode);
+ new D<Null, Null>().test('Null', hasUnsoundNullSafety);
new D<Never, Never>().test('Never', true);
}
diff --git a/tests/language/function_subtype/not2_test.dart b/tests/language/function_subtype/not2_test.dart
index 03b0110..ffad8f7 100644
--- a/tests/language/function_subtype/not2_test.dart
+++ b/tests/language/function_subtype/not2_test.dart
@@ -22,7 +22,7 @@
void main() {
new Class<dynamic>().test(true, bar, "dynamic");
new Class<Object>().test(true, bar, "Object");
- new Class<Null>().test(isStrongMode, bar, "Null");
+ new Class<Null>().test(hasSoundNullSafety, bar, "Null");
new Class<Never>().test(false, bar, "Never");
new Class<int>().test(false, bar, "int");
new Class<bool>().test(true, bar, "bool");
diff --git a/tests/language/function_subtype/not3_test.dart b/tests/language/function_subtype/not3_test.dart
index 0c03826..e3d23bc6 100644
--- a/tests/language/function_subtype/not3_test.dart
+++ b/tests/language/function_subtype/not3_test.dart
@@ -26,7 +26,7 @@
void main() {
new Class<dynamic>().test(true, bar, "dynamic");
new Class<Object>().test(true, bar, "Object");
- new Class<Null>().test(isStrongMode, bar, "Null");
+ new Class<Null>().test(hasSoundNullSafety, bar, "Null");
new Class<Never>().test(false, bar, "Never");
new Class<int>().test(false, bar, "int");
new Class<bool>().test(true, bar, "bool");
diff --git a/tests/language/function_subtype/top_level1_test.dart b/tests/language/function_subtype/top_level1_test.dart
index 4e2d763..92aac32 100644
--- a/tests/language/function_subtype/top_level1_test.dart
+++ b/tests/language/function_subtype/top_level1_test.dart
@@ -40,6 +40,6 @@
new C<int>().test('int', false);
new C<Object>().test('Object', false);
new C<dynamic>().test('dynamic', false);
- new C<Null>().test('Null', isWeakMode);
+ new C<Null>().test('Null', hasUnsoundNullSafety);
new C<Never>().test('Never', true);
}
diff --git a/tests/language/generic/instanceof.dart b/tests/language/generic/instanceof.dart
index 547239c..d90b97e 100644
--- a/tests/language/generic/instanceof.dart
+++ b/tests/language/generic/instanceof.dart
@@ -56,7 +56,7 @@
}
{
Foo foo = new Foo<List<Object>>();
- Expect.equals(isWeakMode, foo.isT(new List.filled(5, null)));
+ Expect.equals(hasUnsoundNullSafety, foo.isT(new List.filled(5, null)));
Expect.equals(true, foo.isT(new List<Object>.filled(5, "o")));
Expect.equals(true, foo.isT(new List<int>.filled(5, 0)));
Expect.equals(true, foo.isT(new List<num>.filled(5, 0)));
@@ -64,7 +64,7 @@
}
{
Foo foo = new Foo<List<int>>();
- Expect.equals(isWeakMode, foo.isT(new List.filled(5, null)));
+ Expect.equals(hasUnsoundNullSafety, foo.isT(new List.filled(5, null)));
Expect.equals(false, foo.isT(new List<Object>.filled(5, "o")));
Expect.equals(true, foo.isT(new List<int>.filled(5, 0)));
Expect.equals(false, foo.isT(new List<num>.filled(5, 0)));
@@ -72,7 +72,7 @@
}
{
Foo foo = new Foo<List<num>>();
- Expect.equals(isWeakMode, foo.isT(new List.filled(5, null)));
+ Expect.equals(hasUnsoundNullSafety, foo.isT(new List.filled(5, null)));
Expect.equals(false, foo.isT(new List<Object>.filled(5, "o")));
Expect.equals(true, foo.isT(new List<int>.filled(5, 0)));
Expect.equals(true, foo.isT(new List<num>.filled(5, 0)));
@@ -80,7 +80,7 @@
}
{
Foo foo = new Foo<List<String>>();
- Expect.equals(isWeakMode, foo.isT(new List.filled(5, null)));
+ Expect.equals(hasUnsoundNullSafety, foo.isT(new List.filled(5, null)));
Expect.equals(false, foo.isT(new List<Object>.filled(5, "o")));
Expect.equals(false, foo.isT(new List<int>.filled(5, 0)));
Expect.equals(false, foo.isT(new List<num>.filled(5, 0)));
@@ -96,7 +96,8 @@
}
{
Foo foo = new Foo<Object>();
- Expect.equals(isWeakMode, foo.isListT(new List.filled(5, null)));
+ Expect.equals(
+ hasUnsoundNullSafety, foo.isListT(new List.filled(5, null)));
Expect.equals(true, foo.isListT(new List<Object>.filled(5, "o")));
Expect.equals(true, foo.isListT(new List<int>.filled(5, 0)));
Expect.equals(true, foo.isListT(new List<num>.filled(5, 0)));
@@ -104,7 +105,8 @@
}
{
Foo foo = new Foo<int>();
- Expect.equals(isWeakMode, foo.isListT(new List.filled(5, null)));
+ Expect.equals(
+ hasUnsoundNullSafety, foo.isListT(new List.filled(5, null)));
Expect.equals(false, foo.isListT(new List<Object>.filled(5, "o")));
Expect.equals(true, foo.isListT(new List<int>.filled(5, 0)));
Expect.equals(false, foo.isListT(new List<num>.filled(5, 0)));
@@ -112,7 +114,8 @@
}
{
Foo foo = new Foo<num>();
- Expect.equals(isWeakMode, foo.isListT(new List.filled(5, null)));
+ Expect.equals(
+ hasUnsoundNullSafety, foo.isListT(new List.filled(5, null)));
Expect.equals(false, foo.isListT(new List<Object>.filled(5, "o")));
Expect.equals(true, foo.isListT(new List<int>.filled(5, 0)));
Expect.equals(true, foo.isListT(new List<num>.filled(5, 0)));
@@ -120,7 +123,8 @@
}
{
Foo foo = new Foo<String>();
- Expect.equals(isWeakMode, foo.isListT(new List.filled(5, null)));
+ Expect.equals(
+ hasUnsoundNullSafety, foo.isListT(new List.filled(5, null)));
Expect.equals(false, foo.isListT(new List<Object>.filled(5, "o")));
Expect.equals(false, foo.isListT(new List<int>.filled(5, 0)));
Expect.equals(false, foo.isListT(new List<num>.filled(5, 0)));
diff --git a/tests/language/generic_methods/generic_class_tearoff_test.dart b/tests/language/generic_methods/generic_class_tearoff_test.dart
index 6c98ba8..28e9b8f 100644
--- a/tests/language/generic_methods/generic_class_tearoff_test.dart
+++ b/tests/language/generic_methods/generic_class_tearoff_test.dart
@@ -38,6 +38,6 @@
Expect.isTrue(h is! Int2Int);
Expect.isTrue(h is! String2String);
- Expect.equals(isWeakMode, h is Object2Object);
+ Expect.equals(hasUnsoundNullSafety, h is Object2Object);
Expect.isTrue(h is! GenericMethod);
}
diff --git a/tests/language/is/is2_test.dart b/tests/language/is/is2_test.dart
index 93f6fb2..1d418b7 100644
--- a/tests/language/is/is2_test.dart
+++ b/tests/language/is/is2_test.dart
@@ -59,7 +59,7 @@
var a = new List.empty();
Expect.equals(true, a is List);
Expect.equals(true, a is List<Object?>);
- Expect.equals(isWeakMode, a is List<Object>);
+ Expect.equals(hasUnsoundNullSafety, a is List<Object>);
Expect.equals(false, a is List<int>);
Expect.equals(false, a is List<num>);
Expect.equals(false, a is List<String>);
diff --git a/tests/language/nnbd/constant_null_safety_mode_test.dart b/tests/language/nnbd/constant_null_safety_mode_test.dart
index 131a2ff..6e89c75 100644
--- a/tests/language/nnbd/constant_null_safety_mode_test.dart
+++ b/tests/language/nnbd/constant_null_safety_mode_test.dart
@@ -5,15 +5,15 @@
import 'package:expect/expect.dart';
main() {
- const trueInWeakMode = <Null>[] is List<int>;
- Expect.equals(isWeakMode, trueInWeakMode);
+ const trueInNoSoundMode = <Null>[] is List<int>;
+ Expect.equals(hasUnsoundNullSafety, trueInNoSoundMode);
// The following tests use the Uri.pathSegments() to access a constant list
// that is defined in the SDK and verify the type associated with it does not
// allow null when running with sound null safety.
var emptyUri = Uri(pathSegments: []);
dynamic stringList = emptyUri.pathSegments.toList();
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
Expect.throwsTypeError(() {
stringList.add(null);
});
diff --git a/tests/language/null/null_test.dart b/tests/language/null/null_test.dart
index f13312d..48e9b25 100644
--- a/tests/language/null/null_test.dart
+++ b/tests/language/null/null_test.dart
@@ -145,13 +145,13 @@
// Test cast, "as", operator.
Expect.equals(null, null as Null);
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
Expect.throwsTypeError(() => null as Object);
} else {
Expect.equals(null, null as Object);
}
Expect.equals(null, null as Object?);
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
Expect.throwsTypeError(() => null as int);
} else {
Expect.equals(null, null as int);
@@ -163,13 +163,13 @@
Expect.equals(null, new Generic<int?>().cast(null));
Expect.equals(null, obj as Null);
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
Expect.throwsTypeError(() => obj as Object);
} else {
Expect.equals(null, obj as Object);
}
Expect.equals(null, obj as Object?);
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
Expect.throwsTypeError(() => obj as int);
} else {
Expect.equals(null, obj as int);
diff --git a/tests/language/regress/regress34147_test.dart b/tests/language/regress/regress34147_test.dart
index 20ab478..ab7197e 100644
--- a/tests/language/regress/regress34147_test.dart
+++ b/tests/language/regress/regress34147_test.dart
@@ -16,7 +16,7 @@
}
void expectError(Function() callback) {
- if (isWeakMode) {
+ if (hasUnsoundNullSafety) {
Expect.throwsAssertionError(callback);
} else {
Expect.throwsTypeError(callback);
diff --git a/tests/language/regress/regress41890_test.dart b/tests/language/regress/regress41890_test.dart
index 86e43a7..9374e28 100644
--- a/tests/language/regress/regress41890_test.dart
+++ b/tests/language/regress/regress41890_test.dart
@@ -43,8 +43,8 @@
var item = items[i];
String code = answers[i];
bool expected = code == 'T' ||
- (code == 'S' && isStrongMode) ||
- (code == 'W' && isWeakMode);
+ (code == 'S' && hasSoundNullSafety) ||
+ (code == 'W' && hasUnsoundNullSafety);
Expect.equals(expected, predicate(item), "$predicate '$code' $item");
}
}
diff --git a/tests/language/vm/bool_check_stack_traces_test.dart b/tests/language/vm/bool_check_stack_traces_test.dart
index bdc9ce5..e27da73 100644
--- a/tests/language/vm/bool_check_stack_traces_test.dart
+++ b/tests/language/vm/bool_check_stack_traces_test.dart
@@ -81,7 +81,7 @@
print(stacktrace);
print('-----------------------------');
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
Expect.isTrue(e is TypeError);
Expect.equals(
"type 'Null' is not a subtype of type 'bool'", e.toString());
diff --git a/tests/lib/mirrors/null_test.dart b/tests/lib/mirrors/null_test.dart
index 0d58539..ab4c915 100644
--- a/tests/lib/mirrors/null_test.dart
+++ b/tests/lib/mirrors/null_test.dart
@@ -18,7 +18,7 @@
InstanceMirror im1 = reflect(null);
Expect.equals(cm, im1.type);
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
Expect.throwsTypeError(() => im1.invoke(const Symbol("=="), [null]),
'null not assignable to Object');
} else {
@@ -29,7 +29,7 @@
var obj = confuse(null); // Null value that isn't known at compile-time.
InstanceMirror im2 = reflect(obj);
Expect.equals(cm, im2.type);
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
Expect.throwsTypeError(() => im2.invoke(const Symbol("=="), [null]),
'null not assignable to Object');
} else {
@@ -41,7 +41,7 @@
Expect.isTrue(nullMirror.getField(#hashCode).reflectee is int);
Expect.equals(null.hashCode, nullMirror.getField(#hashCode).reflectee);
Expect.equals('Null', nullMirror.getField(#runtimeType).reflectee.toString());
- if (isStrongMode) {
+ if (hasSoundNullSafety) {
Expect.throwsTypeError(
() => nullMirror.invoke(#==, [null]), 'null not assignable to Object');
} else {
diff --git a/tools/VERSION b/tools/VERSION
index fd9047b..e96dbff 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 12
PATCH 0
-PRERELEASE 23
+PRERELEASE 24
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/patches/flutter-engine/a3815b659047cfc6b63d41d180aa1ca1b781ee68.patch b/tools/patches/flutter-engine/a3815b659047cfc6b63d41d180aa1ca1b781ee68.patch
deleted file mode 100644
index 94120c0..0000000
--- a/tools/patches/flutter-engine/a3815b659047cfc6b63d41d180aa1ca1b781ee68.patch
+++ /dev/null
@@ -1,596 +0,0 @@
-diff --git a/DEPS b/DEPS
-index 01113f340..e55da1cff 100644
---- a/DEPS
-+++ b/DEPS
-@@ -34,14 +34,14 @@ vars = {
- # Dart is: https://github.com/dart-lang/sdk/blob/master/DEPS.
- # You can use //tools/dart/create_updated_flutter_deps.py to produce
- # updated revision list of existing dependencies.
- 'dart_revision': 'a3815b659047cfc6b63d41d180aa1ca1b781ee68',
-
- # WARNING: DO NOT EDIT MANUALLY
- # The lines between blank lines above and below are generated by a script. See create_updated_flutter_deps.py
- 'dart_args_tag': '1.6.0',
- 'dart_boringssl_gen_rev': '429ccb1877f7987a6f3988228bc2440e61293499',
- 'dart_boringssl_rev': '4dfd5af70191b068aebe567b8e29ce108cee85ce',
-- 'dart_collection_rev': '80f5b6de8a8d8d584732a71bb59912da3e44883b',
-+ 'dart_collection_rev': '583693680fc067e34ca5b72503df25e8b80579f9',
- 'dart_dart2js_info_tag': '0.6.0',
- 'dart_dart_style_tag': '1.3.6',
- 'dart_http_retry_tag': '0.1.1',
-@@ -49,7 +49,6 @@ vars = {
- 'dart_intl_tag': '0.16.1',
- 'dart_linter_tag': '0.1.117',
- 'dart_oauth2_tag': '1.6.0',
-- 'dart_pedantic_tag': 'v1.9.0',
- 'dart_protobuf_rev': '3746c8fd3f2b0147623a8e3db89c3ff4330de760',
- 'dart_pub_rev': '04b054b62cc437cf23451785fdc50e49cd9de139',
- 'dart_pub_semver_tag': 'v1.4.4',
-@@ -61,15 +60,13 @@ vars = {
- 'dart_shelf_static_rev': 'v0.2.8',
- 'dart_shelf_tag': '0.7.3+3',
- 'dart_shelf_web_socket_tag': '0.2.2+3',
-- 'dart_source_map_stack_trace_tag': '2.0.0',
-- 'dart_source_span_tag': '1.7.0',
- 'dart_sse_tag': 'e5cf68975e8e87171a3dc297577aa073454a91dc',
-- 'dart_stack_trace_tag': '56811dbb2530d823b764fe167ec335879a4adb32',
-+ 'dart_stack_trace_tag': 'd3813ca0a77348e0faf0d6af0cc17913e36afa39',
- 'dart_stagehand_tag': 'v3.3.9',
-- 'dart_stream_channel_tag': '70433d577be02c48cb16d72d65654f3b4d82c6ed',
-+ 'dart_stream_channel_tag': 'c446774fd077c9bdbd6235a7aadc661ef60a9727',
- 'dart_test_reflective_loader_tag': '0.1.9',
- 'dart_tflite_native_rev': '3c777c40608a2a9f1427bfe0028ab48e7116b4c1',
-- 'dart_typed_data_tag': '0c369b73a9b7ebf042c06512951bfe5b52b84a5f',
-+ 'dart_typed_data_tag': 'f94fc57b8e8c0e4fe4ff6cfd8290b94af52d3719',
- 'dart_usage_tag': '3.4.0',
- 'dart_watcher_rev': 'fc3c9aae5d31d707b3013b42634dde8d8a1161b4',
-
-@@ -171,13 +168,13 @@ deps = {
- Var('dart_git') + '/args.git' + '@' + Var('dart_args_tag'),
-
- 'src/third_party/dart/third_party/pkg/async':
-- Var('dart_git') + '/async.git@6b90f4557f330e1ead021f501ee7f1d8b0e77815',
-+ Var('dart_git') + '/async.git@128c461a97dbdbd9336ba000ba5a5c02e79b8651',
-
- 'src/third_party/dart/third_party/pkg/bazel_worker':
- Var('dart_git') + '/bazel_worker.git@26680d5e249b249c7216ab2fed0ac8ed4ee285c5',
-
- 'src/third_party/dart/third_party/pkg/boolean_selector':
-- Var('dart_git') + '/boolean_selector.git@1309eabed510cc3b7536fd4367d39b97ebee3d69',
-+ Var('dart_git') + '/boolean_selector.git@665e6921ab246569420376f827bff4585dff0b14',
-
- 'src/third_party/dart/third_party/pkg/charcode':
- Var('dart_git') + '/charcode.git@af1e2d59a9c383da94f99ea51dac4b93fb0626c4',
-@@ -207,7 +204,7 @@ deps = {
- Var('dart_git') + '/ffi.git@454ab0f9ea6bd06942a983238d8a6818b1357edb',
-
- 'src/third_party/dart/third_party/pkg/fixnum':
-- Var('dart_git') + '/fixnum.git@9b38f49f6679654d66a363e69e48173cca07e882',
-+ Var('dart_git') + '/fixnum.git@300c3f025e94a72b7b6770e15f76a4de15f77668',
-
- 'src/third_party/dart/third_party/pkg/glob':
- Var('dart_git') + '/glob.git@e9f4e6b7ae8abe5071461cf8f47191bb19cf7ef6',
-@@ -246,7 +243,7 @@ deps = {
- Var('dart_git') + '/markdown.git@dd150bb64c5f3b41d31f20f399ae2a855f7f8c00',
-
- 'src/third_party/dart/third_party/pkg/matcher':
-- Var('dart_git') + '/matcher.git@8f8d965933c94a489b1a39e20d558a32841bfa5b',
-+ Var('dart_git') + '/matcher.git@9cae8faa7868bf3a88a7ba45eb0bd128e66ac515',
-
- 'src/third_party/dart/third_party/pkg/mime':
- Var('dart_git') + '/mime.git@179b5e6a88f4b63f36dc1b8fcbc1e83e5e0cd3a7',
-@@ -261,13 +258,13 @@ deps = {
- Var('dart_git') + '/oauth2.git' + '@' + Var('dart_oauth2_tag'),
-
- 'src/third_party/dart/third_party/pkg/path':
-- Var('dart_git') + '/path.git@4f3bb71843fe5493ba490828a1721821d7b33746',
-+ Var('dart_git') + '/path.git@62ecd5a78ffe5734d14ed0df76d20309084cd04a',
-
- 'src/third_party/dart/third_party/pkg/pedantic':
-- Var('dart_git') + '/pedantic.git' + '@' + Var('dart_pedantic_tag'),
-+ Var('dart_git') + '/pedantic.git@24b38df72430d7e21cb4257828580becb9a39c72',
-
- 'src/third_party/dart/third_party/pkg/pool':
-- Var('dart_git') + '/pool.git@86fbb2cde9bbc66c8d159909d2f65a5981ea5b50',
-+ Var('dart_git') + '/pool.git@eedbd5fde84f9a1a8da643b475305a81841da599',
-
- 'src/third_party/dart/third_party/pkg/protobuf':
- Var('dart_git') + '/protobuf.git' + '@' + Var('dart_protobuf_rev'),
-@@ -300,13 +297,13 @@ deps = {
- Var('dart_git') + '/shelf_web_socket.git' + '@' + Var('dart_shelf_web_socket_tag'),
-
- 'src/third_party/dart/third_party/pkg/source_map_stack_trace':
-- Var('dart_git') + '/source_map_stack_trace.git' + '@' + Var('dart_source_map_stack_trace_tag'),
-+ Var('dart_git') + '/source_map_stack_trace.git@1c3026f69d9771acf2f8c176a1ab750463309cce',
-
- 'src/third_party/dart/third_party/pkg/source_maps':
-- Var('dart_git') + '/source_maps.git@87b4fd9027378bbd51b02e9d7df794eee8a82b7a',
-+ Var('dart_git') + '/source_maps.git@53eb92ccfe6e64924054f83038a534b959b12b3e',
-
- 'src/third_party/dart/third_party/pkg/source_span':
-- Var('dart_git') + '/source_span.git' + '@' + Var('dart_source_span_tag'),
-+ Var('dart_git') + '/source_span.git@94833d6cbf4552ebe5d2aa6714acecd93834e53a',
-
- 'src/third_party/dart/third_party/pkg/sse':
- Var('dart_git') + '/sse.git' + '@' + Var('dart_sse_tag'),
-@@ -321,13 +318,13 @@ deps = {
- Var('dart_git') + '/stream_channel.git' + '@' + Var('dart_stream_channel_tag'),
-
- 'src/third_party/dart/third_party/pkg/string_scanner':
-- Var('dart_git') + '/string_scanner.git@a918e7371af6b6e73bfd534ff9da6084741c1f99',
-+ Var('dart_git') + '/string_scanner.git@1b63e6e5db5933d7be0a45da6e1129fe00262734',
-
- 'src/third_party/dart/third_party/pkg/term_glyph':
-- Var('dart_git') + '/term_glyph.git@b3da31e9684a99cfe5f192b89914492018b44da7',
-+ Var('dart_git') + '/term_glyph.git@6a0f9b6fb645ba75e7a00a4e20072678327a0347',
-
- 'src/third_party/dart/third_party/pkg/test':
-- Var('dart_git') + '/test.git@718fe6f93c4655208460f28e89d887c5ef4144c5',
-+ Var('dart_git') + '/test.git@c6b3fe63eda87da1687580071cad1eefd575f851',
-
- 'src/third_party/dart/third_party/pkg/test_reflective_loader':
- Var('dart_git') + '/test_reflective_loader.git' + '@' + Var('dart_test_reflective_loader_tag'),
-@@ -357,7 +354,7 @@ deps = {
- Var('dart_git') + '/package_config.git@9c586d04bd26fef01215fd10e7ab96a3050cfa64',
-
- 'src/third_party/dart/tools/sdks':
-- {'packages': [{'version': 'version:2.9.0-21.0.dev', 'package': 'dart/dart-sdk/${{platform}}'}], 'dep_type': 'cipd'},
-+ {'packages': [{'version': 'version:2.10.0-0.2-preview', 'package': 'dart/dart-sdk/${{platform}}'}], 'dep_type': 'cipd'},
-
- # WARNING: end of dart dependencies list that is cleaned up automatically - see create_updated_flutter_deps.py.
-
-diff --git a/lib/ui/annotations.dart b/lib/ui/annotations.dart
-index 45d8ca6cc..b300af073 100644
---- a/lib/ui/annotations.dart
-+++ b/lib/ui/annotations.dart
-@@ -4,7 +4,7 @@
-
- // TODO(dnfield): Remove unused_import ignores when https://github.com/dart-lang/sdk/issues/35164 is resolved.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/channel_buffers.dart b/lib/ui/channel_buffers.dart
-index cb32c4581..39d31d271 100644
---- a/lib/ui/channel_buffers.dart
-+++ b/lib/ui/channel_buffers.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/compositing.dart b/lib/ui/compositing.dart
-index ea3c0b714..4e0553936 100644
---- a/lib/ui/compositing.dart
-+++ b/lib/ui/compositing.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/geometry.dart b/lib/ui/geometry.dart
-index 2739048e7..a7404996c 100644
---- a/lib/ui/geometry.dart
-+++ b/lib/ui/geometry.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/hash_codes.dart b/lib/ui/hash_codes.dart
-index a6ede7849..7da175a27 100644
---- a/lib/ui/hash_codes.dart
-+++ b/lib/ui/hash_codes.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/hooks.dart b/lib/ui/hooks.dart
-index ff2dcaa12..39bab1240 100644
---- a/lib/ui/hooks.dart
-+++ b/lib/ui/hooks.dart
-@@ -4,7 +4,7 @@
-
- // TODO(dnfield): Remove unused_import ignores when https://github.com/dart-lang/sdk/issues/35164 is resolved.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/isolate_name_server.dart b/lib/ui/isolate_name_server.dart
-index d976e0ac2..4b5c2c84d 100644
---- a/lib/ui/isolate_name_server.dart
-+++ b/lib/ui/isolate_name_server.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/lerp.dart b/lib/ui/lerp.dart
-index db9f7b2ec..0bb0a08b7 100644
---- a/lib/ui/lerp.dart
-+++ b/lib/ui/lerp.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/natives.dart b/lib/ui/natives.dart
-index ce29fe15c..0f2939592 100644
---- a/lib/ui/natives.dart
-+++ b/lib/ui/natives.dart
-@@ -4,7 +4,7 @@
-
- // TODO(dnfield): remove unused_element ignores when https://github.com/dart-lang/sdk/issues/35164 is resolved.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/painting.dart b/lib/ui/painting.dart
-index 992db71cf..2599f90e2 100644
---- a/lib/ui/painting.dart
-+++ b/lib/ui/painting.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/plugins.dart b/lib/ui/plugins.dart
-index 64eca6e04..9622852fd 100644
---- a/lib/ui/plugins.dart
-+++ b/lib/ui/plugins.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/pointer.dart b/lib/ui/pointer.dart
-index 3c12cb971..3c8ffefaf 100644
---- a/lib/ui/pointer.dart
-+++ b/lib/ui/pointer.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/semantics.dart b/lib/ui/semantics.dart
-index bee542328..518a69412 100644
---- a/lib/ui/semantics.dart
-+++ b/lib/ui/semantics.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/text.dart b/lib/ui/text.dart
-index 8bdc0f05d..c246731d8 100644
---- a/lib/ui/text.dart
-+++ b/lib/ui/text.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
-
- part of dart.ui;
-
-diff --git a/lib/ui/ui.dart b/lib/ui/ui.dart
-index 7612cf509..fe0e4fa16 100644
---- a/lib/ui/ui.dart
-+++ b/lib/ui/ui.dart
-@@ -9,7 +9,7 @@
- /// This library exposes the lowest-level services that Flutter frameworks use
- /// to bootstrap applications, such as classes for driving the input, graphics
- /// text, layout, and rendering subsystems.
--// @dart = 2.9
-+// @dart = 2.10
- library dart.ui;
-
- import 'dart:_internal' hide Symbol; // ignore: unused_import
-diff --git a/lib/ui/window.dart b/lib/ui/window.dart
-index 815bee5a1..22f9ed0c3 100644
---- a/lib/ui/window.dart
-+++ b/lib/ui/window.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of dart.ui;
-
- /// Signature of callbacks that have no arguments and return no data.
-diff --git a/lib/web_ui/lib/src/ui/annotations.dart b/lib/web_ui/lib/src/ui/annotations.dart
-index 977ca70ca..7dac0c567 100644
---- a/lib/web_ui/lib/src/ui/annotations.dart
-+++ b/lib/web_ui/lib/src/ui/annotations.dart
-@@ -4,7 +4,7 @@
-
- // TODO(dnfield): Remove unused_import ignores when https://github.com/dart-lang/sdk/issues/35164 is resolved.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- // TODO(dnfield): Update this if/when we default this to on in the tool,
-diff --git a/lib/web_ui/lib/src/ui/canvas.dart b/lib/web_ui/lib/src/ui/canvas.dart
-index 1061ab718..ee185ef29 100644
---- a/lib/web_ui/lib/src/ui/canvas.dart
-+++ b/lib/web_ui/lib/src/ui/canvas.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// Defines how a list of points is interpreted when drawing a set of points.
-diff --git a/lib/web_ui/lib/src/ui/channel_buffers.dart b/lib/web_ui/lib/src/ui/channel_buffers.dart
-index 5d3db5da5..6ce0bc962 100644
---- a/lib/web_ui/lib/src/ui/channel_buffers.dart
-+++ b/lib/web_ui/lib/src/ui/channel_buffers.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// A saved platform message for a channel with its callback.
-diff --git a/lib/web_ui/lib/src/ui/compositing.dart b/lib/web_ui/lib/src/ui/compositing.dart
-index 635dd7261..11a0e1199 100644
---- a/lib/web_ui/lib/src/ui/compositing.dart
-+++ b/lib/web_ui/lib/src/ui/compositing.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// An opaque object representing a composited scene.
-diff --git a/lib/web_ui/lib/src/ui/geometry.dart b/lib/web_ui/lib/src/ui/geometry.dart
-index 904cec065..c528c8c73 100644
---- a/lib/web_ui/lib/src/ui/geometry.dart
-+++ b/lib/web_ui/lib/src/ui/geometry.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// Base class for [Size] and [Offset], which are both ways to describe
-diff --git a/lib/web_ui/lib/src/ui/hash_codes.dart b/lib/web_ui/lib/src/ui/hash_codes.dart
-index 69aeb33bb..e91fb1cc5 100644
---- a/lib/web_ui/lib/src/ui/hash_codes.dart
-+++ b/lib/web_ui/lib/src/ui/hash_codes.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- class _HashEnd { const _HashEnd(); }
-diff --git a/lib/web_ui/lib/src/ui/initialization.dart b/lib/web_ui/lib/src/ui/initialization.dart
-index 2749fa9e5..6865da812 100644
---- a/lib/web_ui/lib/src/ui/initialization.dart
-+++ b/lib/web_ui/lib/src/ui/initialization.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// Initializes the platform.
-diff --git a/lib/web_ui/lib/src/ui/lerp.dart b/lib/web_ui/lib/src/ui/lerp.dart
-index bcc278f8a..5cd4c8ac1 100644
---- a/lib/web_ui/lib/src/ui/lerp.dart
-+++ b/lib/web_ui/lib/src/ui/lerp.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// Linearly interpolate between two numbers.
-diff --git a/lib/web_ui/lib/src/ui/natives.dart b/lib/web_ui/lib/src/ui/natives.dart
-index e4bf1a2f5..4763db34e 100644
---- a/lib/web_ui/lib/src/ui/natives.dart
-+++ b/lib/web_ui/lib/src/ui/natives.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- // Corelib 'print' implementation.
-diff --git a/lib/web_ui/lib/src/ui/painting.dart b/lib/web_ui/lib/src/ui/painting.dart
-index a9bd10662..67da1842f 100644
---- a/lib/web_ui/lib/src/ui/painting.dart
-+++ b/lib/web_ui/lib/src/ui/painting.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- // ignore: unused_element, Used in Shader assert.
-diff --git a/lib/web_ui/lib/src/ui/path.dart b/lib/web_ui/lib/src/ui/path.dart
-index 18e351f53..1514d2432 100644
---- a/lib/web_ui/lib/src/ui/path.dart
-+++ b/lib/web_ui/lib/src/ui/path.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// A complex, one-dimensional subset of a plane.
-diff --git a/lib/web_ui/lib/src/ui/path_metrics.dart b/lib/web_ui/lib/src/ui/path_metrics.dart
-index 6d54888c2..b65e2b928 100644
---- a/lib/web_ui/lib/src/ui/path_metrics.dart
-+++ b/lib/web_ui/lib/src/ui/path_metrics.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// An iterable collection of [PathMetric] objects describing a [Path].
-diff --git a/lib/web_ui/lib/src/ui/pointer.dart b/lib/web_ui/lib/src/ui/pointer.dart
-index 698badcc4..e2f351caf 100644
---- a/lib/web_ui/lib/src/ui/pointer.dart
-+++ b/lib/web_ui/lib/src/ui/pointer.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// How the pointer has changed since the last report.
-diff --git a/lib/web_ui/lib/src/ui/semantics.dart b/lib/web_ui/lib/src/ui/semantics.dart
-index c6dffe2fc..a0fde9a5b 100644
---- a/lib/web_ui/lib/src/ui/semantics.dart
-+++ b/lib/web_ui/lib/src/ui/semantics.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// The possible actions that can be conveyed from the operating system
-diff --git a/lib/web_ui/lib/src/ui/test_embedding.dart b/lib/web_ui/lib/src/ui/test_embedding.dart
-index f72a5c75e..955dbfe53 100644
---- a/lib/web_ui/lib/src/ui/test_embedding.dart
-+++ b/lib/web_ui/lib/src/ui/test_embedding.dart
-@@ -4,7 +4,7 @@
-
- // TODO(flutter_web): the Web-only API below need to be cleaned up.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// Used to track when the platform is initialized. This ensures the test fonts
-diff --git a/lib/web_ui/lib/src/ui/text.dart b/lib/web_ui/lib/src/ui/text.dart
-index ec9a45943..58698d862 100644
---- a/lib/web_ui/lib/src/ui/text.dart
-+++ b/lib/web_ui/lib/src/ui/text.dart
-@@ -3,7 +3,7 @@
- // found in the LICENSE file.
- // Synced 2019-05-30T14:20:57.833907.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// Whether to slant the glyphs in the font
-diff --git a/lib/web_ui/lib/src/ui/tile_mode.dart b/lib/web_ui/lib/src/ui/tile_mode.dart
-index 8fd24ae58..9ce9ddf3c 100644
---- a/lib/web_ui/lib/src/ui/tile_mode.dart
-+++ b/lib/web_ui/lib/src/ui/tile_mode.dart
-@@ -2,7 +2,7 @@
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// Defines what happens at the edge of the gradient.
-diff --git a/lib/web_ui/lib/src/ui/window.dart b/lib/web_ui/lib/src/ui/window.dart
-index 557e6aa84..fd9e66740 100644
---- a/lib/web_ui/lib/src/ui/window.dart
-+++ b/lib/web_ui/lib/src/ui/window.dart
-@@ -3,7 +3,7 @@
- // found in the LICENSE file.
- // Synced 2019-05-30T14:20:57.841444.
-
--// @dart = 2.9
-+// @dart = 2.10
- part of ui;
-
- /// Signature of callbacks that have no arguments and return no data.
-diff --git a/lib/web_ui/lib/ui.dart b/lib/web_ui/lib/ui.dart
-index 49217e14a..13d5ee281 100644
---- a/lib/web_ui/lib/ui.dart
-+++ b/lib/web_ui/lib/ui.dart
-@@ -5,7 +5,7 @@
- /// This library defines the web equivalent of the native dart:ui.
- ///
- /// All types in this library are public.
--// @dart = 2.9
-+// @dart = 2.10
- library ui;
-
- import 'dart:async';
diff --git a/tools/patches/flutter-engine/d2577410a5016eadc111919355e19d42dd45d816.patch b/tools/patches/flutter-engine/d2577410a5016eadc111919355e19d42dd45d816.patch
deleted file mode 100644
index c7446e9..0000000
--- a/tools/patches/flutter-engine/d2577410a5016eadc111919355e19d42dd45d816.patch
+++ /dev/null
@@ -1,804 +0,0 @@
-diff --git a/BUILD.gn b/BUILD.gn
-index edbeb6803..e280ae901 100644
---- a/BUILD.gn
-+++ b/BUILD.gn
-@@ -98,6 +98,7 @@ group("flutter") {
- "//flutter/shell/platform/embedder:embedder_proctable_unittests",
- "//flutter/shell/platform/embedder:embedder_unittests",
- "//flutter/testing:testing_unittests",
-+ "//flutter/third_party/tonic/tests:tonic_unittests",
- "//flutter/third_party/txt:txt_unittests",
- ]
-
-diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
-index f13271aa9..6b84f6a83 100755
---- a/ci/licenses_golden/licenses_flutter
-+++ b/ci/licenses_golden/licenses_flutter
-@@ -1463,6 +1463,8 @@ FILE: ../../../flutter/third_party/tonic/dart_persistent_value.cc
- FILE: ../../../flutter/third_party/tonic/dart_persistent_value.h
- FILE: ../../../flutter/third_party/tonic/dart_state.cc
- FILE: ../../../flutter/third_party/tonic/dart_state.h
-+FILE: ../../../flutter/third_party/tonic/dart_weak_persistent_value.cc
-+FILE: ../../../flutter/third_party/tonic/dart_weak_persistent_value.h
- FILE: ../../../flutter/third_party/tonic/dart_wrappable.cc
- FILE: ../../../flutter/third_party/tonic/dart_wrappable.h
- FILE: ../../../flutter/third_party/tonic/dart_wrapper_info.h
-diff --git a/lib/ui/painting/image_decoder.cc b/lib/ui/painting/image_decoder.cc
-index d6c4a668f..b6ffb20f5 100644
---- a/lib/ui/painting/image_decoder.cc
-+++ b/lib/ui/painting/image_decoder.cc
-@@ -224,12 +224,13 @@ void ImageDecoder::Decode(fml::RefPtr<ImageDescriptor> descriptor,
- FML_DCHECK(callback);
- FML_DCHECK(runners_.GetUITaskRunner()->RunsTasksOnCurrentThread());
-
-- // Always service the callback on the UI thread.
-- auto result = [callback, ui_runner = runners_.GetUITaskRunner()](
-+ // Always service the callback (and cleanup the descriptor) on the UI thread.
-+ auto result = [callback, descriptor, ui_runner = runners_.GetUITaskRunner()](
- SkiaGPUObject<SkImage> image,
- fml::tracing::TraceFlow flow) {
-- ui_runner->PostTask(fml::MakeCopyable(
-- [callback, image = std::move(image), flow = std::move(flow)]() mutable {
-+ ui_runner->PostTask(
-+ fml::MakeCopyable([callback, descriptor, image = std::move(image),
-+ flow = std::move(flow)]() mutable {
- // We are going to terminate the trace flow here. Flows cannot
- // terminate without a base trace. Add one explicitly.
- TRACE_EVENT0("flutter", "ImageDecodeCallback");
-diff --git a/lib/ui/painting/image_encoding.cc b/lib/ui/painting/image_encoding.cc
-index c17a784c5..8a7653f0b 100644
---- a/lib/ui/painting/image_encoding.cc
-+++ b/lib/ui/painting/image_encoding.cc
-@@ -35,9 +35,7 @@ enum ImageByteFormat {
- kPNG,
- };
-
--void FinalizeSkData(void* isolate_callback_data,
-- Dart_WeakPersistentHandle handle,
-- void* peer) {
-+void FinalizeSkData(void* isolate_callback_data, void* peer) {
- SkData* buffer = reinterpret_cast<SkData*>(peer);
- buffer->unref();
- }
-diff --git a/runtime/dart_isolate.cc b/runtime/dart_isolate.cc
-index b834957a9..8a6215110 100644
---- a/runtime/dart_isolate.cc
-+++ b/runtime/dart_isolate.cc
-@@ -981,6 +981,11 @@ void DartIsolate::AddIsolateShutdownCallback(const fml::closure& closure) {
- }
-
- void DartIsolate::OnShutdownCallback() {
-+ tonic::DartState* state = tonic::DartState::Current();
-+ if (state != nullptr) {
-+ state->SetIsShuttingDown();
-+ }
-+
- {
- tonic::DartApiScope api_scope;
- Dart_Handle sticky_error = Dart_GetStickyError();
-diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc
-index ae9849a5a..b0c61a1b5 100644
---- a/shell/platform/embedder/embedder.cc
-+++ b/shell/platform/embedder/embedder.cc
-@@ -1922,8 +1922,7 @@ FlutterEngineResult FlutterEnginePostDartObject(
- dart_object.value.as_external_typed_data.data = buffer;
- dart_object.value.as_external_typed_data.peer = peer;
- dart_object.value.as_external_typed_data.callback =
-- +[](void* unused_isolate_callback_data,
-- Dart_WeakPersistentHandle unused_handle, void* peer) {
-+ +[](void* unused_isolate_callback_data, void* peer) {
- auto typed_peer = reinterpret_cast<ExternalTypedDataPeer*>(peer);
- typed_peer->trampoline(typed_peer->user_data);
- delete typed_peer;
-diff --git a/shell/platform/fuchsia/dart_runner/dart_runner.cc b/shell/platform/fuchsia/dart_runner/dart_runner.cc
-index 76d85405a..415d2885c 100644
---- a/shell/platform/fuchsia/dart_runner/dart_runner.cc
-+++ b/shell/platform/fuchsia/dart_runner/dart_runner.cc
-@@ -86,6 +86,10 @@ void IsolateShutdownCallback(void* isolate_group_data, void* isolate_data) {
- tonic::DartMicrotaskQueue::GetForCurrentThread()->Destroy();
- async_loop_quit(loop);
- }
-+
-+ auto state =
-+ static_cast<std::shared_ptr<tonic::DartState>*>(isolate_group_data);
-+ state->get()->SetIsShuttingDown();
- }
-
- void IsolateGroupCleanupCallback(void* isolate_group_data) {
-diff --git a/testing/run_tests.py b/testing/run_tests.py
-index 06b8256d0..8bdd114f4 100755
---- a/testing/run_tests.py
-+++ b/testing/run_tests.py
-@@ -132,6 +132,8 @@ def RunCCTests(build_dir, filter):
-
- RunEngineExecutable(build_dir, 'runtime_unittests', filter, shuffle_flags)
-
-+ RunEngineExecutable(build_dir, 'tonic_unittests', filter, shuffle_flags)
-+
- if not IsWindows():
- # https://github.com/flutter/flutter/issues/36295
- RunEngineExecutable(build_dir, 'shell_unittests', filter, shuffle_flags)
-diff --git a/third_party/tonic/BUILD.gn b/third_party/tonic/BUILD.gn
-index f5bedda8d..9a6abda8b 100644
---- a/third_party/tonic/BUILD.gn
-+++ b/third_party/tonic/BUILD.gn
-@@ -35,6 +35,8 @@ source_set("tonic") {
- "dart_persistent_value.h",
- "dart_state.cc",
- "dart_state.h",
-+ "dart_weak_persistent_value.cc",
-+ "dart_weak_persistent_value.h",
- "dart_wrappable.cc",
- "dart_wrappable.h",
- "dart_wrapper_info.h",
-diff --git a/third_party/tonic/dart_state.cc b/third_party/tonic/dart_state.cc
-index b711a2297..3f37685c5 100644
---- a/third_party/tonic/dart_state.cc
-+++ b/third_party/tonic/dart_state.cc
-@@ -27,7 +27,8 @@ DartState::DartState(int dirfd,
- message_handler_(new DartMessageHandler()),
- file_loader_(new FileLoader(dirfd)),
- message_epilogue_(message_epilogue),
-- has_set_return_code_(false) {}
-+ has_set_return_code_(false),
-+ is_shutting_down_(false) {}
-
- DartState::~DartState() {}
-
-diff --git a/third_party/tonic/dart_state.h b/third_party/tonic/dart_state.h
-index 845914937..1984a66bf 100644
---- a/third_party/tonic/dart_state.h
-+++ b/third_party/tonic/dart_state.h
-@@ -5,6 +5,7 @@
- #ifndef LIB_TONIC_DART_STATE_H_
- #define LIB_TONIC_DART_STATE_H_
-
-+#include <atomic>
- #include <functional>
- #include <memory>
-
-@@ -68,6 +69,9 @@ class DartState : public std::enable_shared_from_this<DartState> {
- void SetReturnCodeCallback(std::function<void(uint32_t)> callback);
- bool has_set_return_code() const { return has_set_return_code_; }
-
-+ void SetIsShuttingDown() { is_shutting_down_ = true; }
-+ bool IsShuttingDown() { return is_shutting_down_; }
-+
- virtual void DidSetIsolate();
-
- static Dart_Handle HandleLibraryTag(Dart_LibraryTag tag,
-@@ -83,6 +87,7 @@ class DartState : public std::enable_shared_from_this<DartState> {
- std::function<void(Dart_Handle)> message_epilogue_;
- std::function<void(uint32_t)> set_return_code_callback_;
- bool has_set_return_code_;
-+ std::atomic<bool> is_shutting_down_;
-
- protected:
- TONIC_DISALLOW_COPY_AND_ASSIGN(DartState);
-diff --git a/third_party/tonic/dart_weak_persistent_value.cc b/third_party/tonic/dart_weak_persistent_value.cc
-new file mode 100644
-index 000000000..a2664d3e0
---- /dev/null
-+++ b/third_party/tonic/dart_weak_persistent_value.cc
-@@ -0,0 +1,70 @@
-+// Copyright 2013 The Flutter Authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#include "tonic/dart_weak_persistent_value.h"
-+
-+#include "tonic/dart_state.h"
-+#include "tonic/scopes/dart_isolate_scope.h"
-+
-+namespace tonic {
-+
-+DartWeakPersistentValue::DartWeakPersistentValue() : handle_(nullptr) {}
-+
-+DartWeakPersistentValue::~DartWeakPersistentValue() {
-+ Clear();
-+}
-+
-+void DartWeakPersistentValue::Set(DartState* dart_state,
-+ Dart_Handle object,
-+ void* peer,
-+ intptr_t external_allocation_size,
-+ Dart_HandleFinalizer callback) {
-+ TONIC_DCHECK(is_empty());
-+ dart_state_ = dart_state->GetWeakPtr();
-+ handle_ = Dart_NewWeakPersistentHandle(object, peer, external_allocation_size,
-+ callback);
-+}
-+
-+void DartWeakPersistentValue::Clear() {
-+ if (!handle_) {
-+ return;
-+ }
-+
-+ auto dart_state = dart_state_.lock();
-+ if (!dart_state) {
-+ // The DartVM that the handle used to belong to has been shut down and that
-+ // handle has already been deleted.
-+ handle_ = nullptr;
-+ return;
-+ }
-+
-+ // The DartVM frees the handles during shutdown and calls the finalizers.
-+ // Freeing handles during shutdown would fail.
-+ if (!dart_state->IsShuttingDown()) {
-+ if (Dart_CurrentIsolateGroup()) {
-+ Dart_DeleteWeakPersistentHandle(handle_);
-+ } else {
-+ // If we are not on the mutator thread, this will fail. The caller must
-+ // ensure to be on the mutator thread.
-+ DartIsolateScope scope(dart_state->isolate());
-+ Dart_DeleteWeakPersistentHandle(handle_);
-+ }
-+ }
-+ // If it's shutting down, the handle will be deleted already.
-+
-+ dart_state_.reset();
-+ handle_ = nullptr;
-+}
-+
-+Dart_Handle DartWeakPersistentValue::Get() {
-+ auto dart_state = dart_state_.lock();
-+ TONIC_DCHECK(dart_state);
-+ TONIC_DCHECK(!dart_state->IsShuttingDown());
-+ if (!handle_) {
-+ return nullptr;
-+ }
-+ return Dart_HandleFromWeakPersistent(handle_);
-+}
-+
-+} // namespace tonic
-diff --git a/third_party/tonic/dart_weak_persistent_value.h b/third_party/tonic/dart_weak_persistent_value.h
-new file mode 100644
-index 000000000..5f8aed5ee
---- /dev/null
-+++ b/third_party/tonic/dart_weak_persistent_value.h
-@@ -0,0 +1,48 @@
-+// Copyright 2013 The Flutter Authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#ifndef LIB_TONIC_DART_WEAK_PERSISTENT_VALUE_H_
-+#define LIB_TONIC_DART_WEAK_PERSISTENT_VALUE_H_
-+
-+#include <memory>
-+
-+#include "third_party/dart/runtime/include/dart_api.h"
-+#include "tonic/common/macros.h"
-+
-+namespace tonic {
-+class DartState;
-+
-+// DartWeakPersistentValue is a bookkeeping class to help pair calls to
-+// Dart_NewWeakPersistentHandle with Dart_DeleteWeakPersistentHandle even in
-+// the case if IsolateGroup shutdown. Consider using this class instead of
-+// holding a Dart_PersistentHandle directly so that you don't leak the
-+// Dart_WeakPersistentHandle.
-+class DartWeakPersistentValue {
-+ public:
-+ DartWeakPersistentValue();
-+ ~DartWeakPersistentValue();
-+
-+ Dart_WeakPersistentHandle value() const { return handle_; }
-+ bool is_empty() const { return handle_ == nullptr; }
-+
-+ void Set(DartState* dart_state,
-+ Dart_Handle object,
-+ void* peer,
-+ intptr_t external_allocation_size,
-+ Dart_HandleFinalizer callback);
-+ void Clear();
-+ Dart_Handle Get();
-+
-+ const std::weak_ptr<DartState>& dart_state() const { return dart_state_; }
-+
-+ private:
-+ std::weak_ptr<DartState> dart_state_;
-+ Dart_WeakPersistentHandle handle_;
-+
-+ TONIC_DISALLOW_COPY_AND_ASSIGN(DartWeakPersistentValue);
-+};
-+
-+} // namespace tonic
-+
-+#endif // LIB_TONIC_DART_WEAK_PERSISTENT_VALUE_H_
-diff --git a/third_party/tonic/dart_wrappable.cc b/third_party/tonic/dart_wrappable.cc
-index 3bdfe3e6e..858215c11 100644
---- a/third_party/tonic/dart_wrappable.cc
-+++ b/third_party/tonic/dart_wrappable.cc
-@@ -12,12 +12,17 @@
- namespace tonic {
-
- DartWrappable::~DartWrappable() {
-- TONIC_CHECK(!dart_wrapper_);
-+ // Calls the destructor of dart_wrapper_ to delete WeakPersistentHandle.
- }
-
- // TODO(dnfield): Delete this. https://github.com/flutter/flutter/issues/50997
- Dart_Handle DartWrappable::CreateDartWrapper(DartState* dart_state) {
-- TONIC_DCHECK(!dart_wrapper_);
-+ if (!dart_wrapper_.is_empty()) {
-+ // Any previously given out wrapper must have been GCed.
-+ TONIC_DCHECK(Dart_IsNull(dart_wrapper_.Get()));
-+ dart_wrapper_.Clear();
-+ }
-+
- const DartWrapperInfo& info = GetDartWrapperInfo();
-
- Dart_PersistentHandle type = dart_state->class_library().GetClass(info);
-@@ -36,14 +41,19 @@ Dart_Handle DartWrappable::CreateDartWrapper(DartState* dart_state) {
- TONIC_DCHECK(!LogIfError(res));
-
- this->RetainDartWrappableReference(); // Balanced in FinalizeDartWrapper.
-- dart_wrapper_ = Dart_NewWeakPersistentHandle(
-- wrapper, this, GetAllocationSize(), &FinalizeDartWrapper);
-+ dart_wrapper_.Set(dart_state, wrapper, this, GetAllocationSize(),
-+ &FinalizeDartWrapper);
-
- return wrapper;
- }
-
- void DartWrappable::AssociateWithDartWrapper(Dart_Handle wrapper) {
-- TONIC_DCHECK(!dart_wrapper_);
-+ if (!dart_wrapper_.is_empty()) {
-+ // Any previously given out wrapper must have been GCed.
-+ TONIC_DCHECK(Dart_IsNull(dart_wrapper_.Get()));
-+ dart_wrapper_.Clear();
-+ }
-+
- TONIC_CHECK(!LogIfError(wrapper));
-
- const DartWrapperInfo& info = GetDartWrapperInfo();
-@@ -54,26 +64,25 @@ void DartWrappable::AssociateWithDartWrapper(Dart_Handle wrapper) {
- wrapper, kWrapperInfoIndex, reinterpret_cast<intptr_t>(&info))));
-
- this->RetainDartWrappableReference(); // Balanced in FinalizeDartWrapper.
-- dart_wrapper_ = Dart_NewWeakPersistentHandle(
-- wrapper, this, GetAllocationSize(), &FinalizeDartWrapper);
-+
-+ DartState* dart_state = DartState::Current();
-+ dart_wrapper_.Set(dart_state, wrapper, this, GetAllocationSize(),
-+ &FinalizeDartWrapper);
- }
-
- void DartWrappable::ClearDartWrapper() {
-- TONIC_DCHECK(dart_wrapper_);
-- Dart_Handle wrapper = Dart_HandleFromWeakPersistent(dart_wrapper_);
-+ TONIC_DCHECK(!dart_wrapper_.is_empty());
-+ Dart_Handle wrapper = dart_wrapper_.Get();
- TONIC_CHECK(!LogIfError(Dart_SetNativeInstanceField(wrapper, kPeerIndex, 0)));
- TONIC_CHECK(
- !LogIfError(Dart_SetNativeInstanceField(wrapper, kWrapperInfoIndex, 0)));
-- Dart_DeleteWeakPersistentHandle(dart_wrapper_);
-- dart_wrapper_ = nullptr;
-+ dart_wrapper_.Clear();
- this->ReleaseDartWrappableReference();
- }
-
- void DartWrappable::FinalizeDartWrapper(void* isolate_callback_data,
-- Dart_WeakPersistentHandle wrapper,
- void* peer) {
- DartWrappable* wrappable = reinterpret_cast<DartWrappable*>(peer);
-- wrappable->dart_wrapper_ = nullptr;
- wrappable->ReleaseDartWrappableReference(); // Balanced in CreateDartWrapper.
- }
-
-diff --git a/third_party/tonic/dart_wrappable.h b/third_party/tonic/dart_wrappable.h
-index a036abb85..f944dacef 100644
---- a/third_party/tonic/dart_wrappable.h
-+++ b/third_party/tonic/dart_wrappable.h
-@@ -9,6 +9,7 @@
- #include "tonic/common/macros.h"
- #include "tonic/converter/dart_converter.h"
- #include "tonic/dart_state.h"
-+#include "tonic/dart_weak_persistent_value.h"
- #include "tonic/dart_wrapper_info.h"
- #include "tonic/logging/dart_error.h"
-
-@@ -26,7 +27,7 @@ class DartWrappable {
- kNumberOfNativeFields,
- };
-
-- DartWrappable() : dart_wrapper_(nullptr) {}
-+ DartWrappable() : dart_wrapper_(DartWeakPersistentValue()) {}
-
- // Subclasses that wish to expose a new interface must override this function
- // and provide information about their wrapper. There is no need to call your
-@@ -49,7 +50,9 @@ class DartWrappable {
- Dart_Handle CreateDartWrapper(DartState* dart_state);
- void AssociateWithDartWrapper(Dart_Handle wrappable);
- void ClearDartWrapper(); // Warning: Might delete this.
-- Dart_WeakPersistentHandle dart_wrapper() const { return dart_wrapper_; }
-+ Dart_WeakPersistentHandle dart_wrapper() const {
-+ return dart_wrapper_.value();
-+ }
-
- protected:
- virtual ~DartWrappable();
-@@ -59,11 +62,9 @@ class DartWrappable {
- const tonic::DartWrapperInfo& wrapper_info);
-
- private:
-- static void FinalizeDartWrapper(void* isolate_callback_data,
-- Dart_WeakPersistentHandle wrapper,
-- void* peer);
-+ static void FinalizeDartWrapper(void* isolate_callback_data, void* peer);
-
-- Dart_WeakPersistentHandle dart_wrapper_;
-+ DartWeakPersistentValue dart_wrapper_;
-
- TONIC_DISALLOW_COPY_AND_ASSIGN(DartWrappable);
- };
-@@ -103,22 +104,36 @@ struct DartConverter<
- typename std::enable_if<
- std::is_convertible<T*, const DartWrappable*>::value>::type> {
- static Dart_Handle ToDart(DartWrappable* val) {
-- if (!val)
-+ if (!val) {
- return Dart_Null();
-- if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper())
-- return Dart_HandleFromWeakPersistent(wrapper);
-+ }
-+ if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper()) {
-+ auto strong_handle = Dart_HandleFromWeakPersistent(wrapper);
-+ if (!Dart_IsNull(strong_handle)) {
-+ return strong_handle;
-+ }
-+ // After the weak referenced object has been GCed, the handle points to
-+ // Dart_Null(). Fall through create a new wrapper object.
-+ }
- return val->CreateDartWrapper(DartState::Current());
- }
-
- static void SetReturnValue(Dart_NativeArguments args,
- DartWrappable* val,
- bool auto_scope = true) {
-- if (!val)
-+ if (!val) {
- Dart_SetReturnValue(args, Dart_Null());
-- else if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper())
-- Dart_SetWeakHandleReturnValue(args, wrapper);
-- else
-- Dart_SetReturnValue(args, val->CreateDartWrapper(DartState::Current()));
-+ return;
-+ } else if (Dart_WeakPersistentHandle wrapper = val->dart_wrapper()) {
-+ auto strong_handle = Dart_HandleFromWeakPersistent(wrapper);
-+ if (!Dart_IsNull(strong_handle)) {
-+ Dart_SetReturnValue(args, strong_handle);
-+ return;
-+ }
-+ // After the weak referenced object has been GCed, the handle points to
-+ // Dart_Null(). Fall through create a new wrapper object.
-+ }
-+ Dart_SetReturnValue(args, val->CreateDartWrapper(DartState::Current()));
- }
-
- static T* FromDart(Dart_Handle handle) {
-diff --git a/third_party/tonic/tests/BUILD.gn b/third_party/tonic/tests/BUILD.gn
-new file mode 100644
-index 000000000..359deb13b
---- /dev/null
-+++ b/third_party/tonic/tests/BUILD.gn
-@@ -0,0 +1,33 @@
-+# Copyright 2013 The Flutter Authors. All rights reserved.
-+# Use of this source code is governed by a BSD-style license that can be
-+# found in the LICENSE file.
-+
-+import("//flutter/testing/testing.gni")
-+
-+test_fixtures("tonic_fixtures") {
-+ dart_main = "fixtures/tonic_test.dart"
-+ fixtures = []
-+}
-+
-+executable("tonic_unittests") {
-+ testonly = true
-+
-+ public_configs = [ "//flutter:export_dynamic_symbols" ]
-+
-+ sources = [
-+ "dart_state_unittest.cc",
-+ "dart_weak_persistent_handle_unittest.cc",
-+ ]
-+
-+ public_deps = [
-+ ":tonic_fixtures",
-+ "//flutter/runtime:libdart",
-+ "//flutter/runtime:runtime",
-+ "//flutter/testing",
-+ "//flutter/testing:fixture_test",
-+ "//third_party/dart/runtime:dart_api",
-+ "//third_party/googletest:gtest",
-+ ]
-+
-+ deps = [ "../:tonic" ]
-+}
-diff --git a/third_party/tonic/tests/dart_state_unittest.cc b/third_party/tonic/tests/dart_state_unittest.cc
-new file mode 100644
-index 000000000..3d053de40
---- /dev/null
-+++ b/third_party/tonic/tests/dart_state_unittest.cc
-@@ -0,0 +1,61 @@
-+// Copyright 2013 The Flutter Authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#include "flutter/common/task_runners.h"
-+#include "flutter/runtime/dart_vm_lifecycle.h"
-+#include "flutter/runtime/isolate_configuration.h"
-+#include "flutter/testing/fixture_test.h"
-+
-+namespace flutter {
-+namespace testing {
-+
-+using DartState = FixtureTest;
-+
-+TEST_F(DartState, IsShuttingDown) {
-+ ASSERT_FALSE(DartVMRef::IsInstanceRunning());
-+ auto settings = CreateSettingsForFixture();
-+ auto vm_ref = DartVMRef::Create(settings);
-+ ASSERT_TRUE(vm_ref);
-+ auto vm_data = vm_ref.GetVMData();
-+ ASSERT_TRUE(vm_data);
-+ TaskRunners task_runners(GetCurrentTestName(), //
-+ GetCurrentTaskRunner(), //
-+ GetCurrentTaskRunner(), //
-+ GetCurrentTaskRunner(), //
-+ GetCurrentTaskRunner() //
-+ );
-+ auto isolate_configuration =
-+ IsolateConfiguration::InferFromSettings(settings);
-+ auto weak_isolate = DartIsolate::CreateRunningRootIsolate(
-+ vm_data->GetSettings(), // settings
-+ vm_data->GetIsolateSnapshot(), // isolate snapshot
-+ std::move(task_runners), // task runners
-+ nullptr, // window
-+ {}, // snapshot delegate
-+ {}, // hint freed delegate
-+ {}, // io manager
-+ {}, // unref queue
-+ {}, // image decoder
-+ "main.dart", // advisory uri
-+ "main", // advisory entrypoint
-+ DartIsolate::Flags{}, // flags
-+ settings.isolate_create_callback, // isolate create callback
-+ settings.isolate_shutdown_callback, // isolate shutdown callback
-+ "main", // dart entrypoint
-+ std::nullopt, // dart entrypoint library
-+ std::move(isolate_configuration) // isolate configuration
-+ );
-+ auto root_isolate = weak_isolate.lock();
-+ ASSERT_TRUE(root_isolate);
-+
-+ tonic::DartState* dart_state = root_isolate.get();
-+ ASSERT_FALSE(dart_state->IsShuttingDown());
-+
-+ ASSERT_TRUE(root_isolate->Shutdown());
-+
-+ ASSERT_TRUE(dart_state->IsShuttingDown());
-+}
-+
-+} // namespace testing
-+} // namespace flutter
-diff --git a/third_party/tonic/tests/dart_weak_persistent_handle_unittest.cc b/third_party/tonic/tests/dart_weak_persistent_handle_unittest.cc
-new file mode 100644
-index 000000000..65d5e116c
---- /dev/null
-+++ b/third_party/tonic/tests/dart_weak_persistent_handle_unittest.cc
-@@ -0,0 +1,167 @@
-+// Copyright 2013 The Flutter Authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+#include "flutter/testing/dart_isolate_runner.h"
-+#include "flutter/testing/fixture_test.h"
-+
-+namespace flutter {
-+namespace testing {
-+
-+class DartWeakPersistentHandle : public FixtureTest {
-+ public:
-+ DartWeakPersistentHandle()
-+ : settings_(CreateSettingsForFixture()),
-+ vm_(DartVMRef::Create(settings_)) {}
-+
-+ ~DartWeakPersistentHandle() = default;
-+
-+ [[nodiscard]] bool RunWithEntrypoint(const std::string& entrypoint) {
-+ if (running_isolate_) {
-+ return false;
-+ }
-+ auto thread = CreateNewThread();
-+ TaskRunners single_threaded_task_runner(GetCurrentTestName(), thread,
-+ thread, thread, thread);
-+ auto isolate =
-+ RunDartCodeInIsolate(vm_, settings_, single_threaded_task_runner,
-+ entrypoint, {}, GetFixturesPath());
-+ if (!isolate || isolate->get()->GetPhase() != DartIsolate::Phase::Running) {
-+ return false;
-+ }
-+
-+ running_isolate_ = std::move(isolate);
-+ return true;
-+ }
-+
-+ [[nodiscard]] bool RunInIsolateScope(std::function<bool(void)> closure) {
-+ return running_isolate_->RunInIsolateScope(closure);
-+ }
-+
-+ private:
-+ Settings settings_;
-+ DartVMRef vm_;
-+ std::unique_ptr<AutoIsolateShutdown> running_isolate_;
-+ FML_DISALLOW_COPY_AND_ASSIGN(DartWeakPersistentHandle);
-+};
-+
-+void NopFinalizer(void* isolate_callback_data, void* peer) {}
-+
-+TEST_F(DartWeakPersistentHandle, ClearImmediately) {
-+ auto weak_persistent_value = tonic::DartWeakPersistentValue();
-+
-+ fml::AutoResetWaitableEvent event;
-+
-+ AddNativeCallback(
-+ "GiveObjectToNative", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
-+ auto handle = Dart_GetNativeArgument(args, 0);
-+
-+ auto dart_state = tonic::DartState::Current();
-+ ASSERT_TRUE(dart_state);
-+ ASSERT_TRUE(tonic::DartState::Current());
-+ weak_persistent_value.Set(dart_state, handle, nullptr, 0, NopFinalizer);
-+
-+ weak_persistent_value.Clear();
-+
-+ event.Signal();
-+ }));
-+
-+ ASSERT_TRUE(RunWithEntrypoint("callGiveObjectToNative"));
-+
-+ event.Wait();
-+}
-+
-+TEST_F(DartWeakPersistentHandle, ClearLaterCc) {
-+ auto weak_persistent_value = tonic::DartWeakPersistentValue();
-+
-+ fml::AutoResetWaitableEvent event;
-+
-+ AddNativeCallback(
-+ "GiveObjectToNative", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
-+ auto handle = Dart_GetNativeArgument(args, 0);
-+
-+ auto dart_state = tonic::DartState::Current();
-+ ASSERT_TRUE(dart_state);
-+ ASSERT_TRUE(tonic::DartState::Current());
-+ weak_persistent_value.Set(dart_state, handle, nullptr, 0, NopFinalizer);
-+
-+ // Do not clear handle immediately.
-+
-+ event.Signal();
-+ }));
-+
-+ ASSERT_TRUE(RunWithEntrypoint("callGiveObjectToNative"));
-+
-+ event.Wait();
-+
-+ ASSERT_TRUE(RunInIsolateScope([&weak_persistent_value]() -> bool {
-+ // Clear on initiative of native.
-+ weak_persistent_value.Clear();
-+ return true;
-+ }));
-+}
-+
-+TEST_F(DartWeakPersistentHandle, ClearLaterDart) {
-+ auto weak_persistent_value = tonic::DartWeakPersistentValue();
-+
-+ fml::AutoResetWaitableEvent event;
-+
-+ AddNativeCallback(
-+ "GiveObjectToNative", CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
-+ auto handle = Dart_GetNativeArgument(args, 0);
-+
-+ auto dart_state = tonic::DartState::Current();
-+ ASSERT_TRUE(dart_state);
-+ ASSERT_TRUE(tonic::DartState::Current());
-+ weak_persistent_value.Set(dart_state, handle, nullptr, 0, NopFinalizer);
-+
-+ // Do not clear handle immediately.
-+ }));
-+
-+ AddNativeCallback("SignalDone",
-+ CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
-+ // Clear on initiative of Dart.
-+ weak_persistent_value.Clear();
-+
-+ event.Signal();
-+ }));
-+
-+ ASSERT_TRUE(RunWithEntrypoint("testClearLater"));
-+
-+ event.Wait();
-+}
-+
-+// Handle outside the test body scope so it survives until isolate shutdown.
-+tonic::DartWeakPersistentValue global_weak_persistent_value =
-+ tonic::DartWeakPersistentValue();
-+
-+TEST_F(DartWeakPersistentHandle, ClearOnShutdown) {
-+ fml::AutoResetWaitableEvent event;
-+
-+ AddNativeCallback("GiveObjectToNative",
-+ CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) {
-+ auto handle = Dart_GetNativeArgument(args, 0);
-+
-+ auto dart_state = tonic::DartState::Current();
-+ ASSERT_TRUE(dart_state);
-+ ASSERT_TRUE(tonic::DartState::Current());
-+
-+ // The test is repeated, ensure the global var is
-+ // cleared before use.
-+ global_weak_persistent_value.Clear();
-+
-+ global_weak_persistent_value.Set(
-+ dart_state, handle, nullptr, 0, NopFinalizer);
-+
-+ // Do not clear handle, so it is cleared on shutdown.
-+
-+ event.Signal();
-+ }));
-+
-+ ASSERT_TRUE(RunWithEntrypoint("callGiveObjectToNative"));
-+
-+ event.Wait();
-+}
-+
-+} // namespace testing
-+} // namespace flutter
-diff --git a/third_party/tonic/tests/fixtures/tonic_test.dart b/third_party/tonic/tests/fixtures/tonic_test.dart
-new file mode 100644
-index 000000000..83e92d4dc
---- /dev/null
-+++ b/third_party/tonic/tests/fixtures/tonic_test.dart
-@@ -0,0 +1,25 @@
-+// Copyright 2013 The Flutter Authors. All rights reserved.
-+// Use of this source code is governed by a BSD-style license that can be
-+// found in the LICENSE file.
-+
-+void main() {}
-+
-+class SomeClass {
-+ int i;
-+ SomeClass(this.i);
-+}
-+
-+void giveObjectToNative(Object someObject) native 'GiveObjectToNative';
-+
-+void signalDone() native 'SignalDone';
-+
-+@pragma('vm:entry-point')
-+void callGiveObjectToNative() {
-+ giveObjectToNative(SomeClass(123));
-+}
-+
-+@pragma('vm:entry-point')
-+void testClearLater() {
-+ giveObjectToNative(SomeClass(123));
-+ signalDone();
-+}
-diff --git a/third_party/tonic/typed_data/dart_byte_data.cc b/third_party/tonic/typed_data/dart_byte_data.cc
-index dc312de3f..cfb07399f 100644
---- a/third_party/tonic/typed_data/dart_byte_data.cc
-+++ b/third_party/tonic/typed_data/dart_byte_data.cc
-@@ -16,9 +16,7 @@ namespace {
- // with a buffer allocated outside the Dart heap.
- const int kExternalSizeThreshold = 1000;
-
--void FreeFinalizer(void* isolate_callback_data,
-- Dart_WeakPersistentHandle handle,
-- void* peer) {
-+void FreeFinalizer(void* isolate_callback_data, void* peer) {
- free(peer);
- }
-