Version 2.17.0-240.0.dev

Merge commit '01e1d24eea3d3000e9be695f39d6ede03b36e57d' into 'dev'
diff --git a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
index ab09a5f..c433a3e 100644
--- a/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_constructor_builder.dart
@@ -242,7 +242,9 @@
           BodyBuilder bodyBuilder = libraryBuilder.loader
               .createBodyBuilderForOutlineExpression(libraryBuilder,
                   classBuilder, this, classBuilder.scope, fileUri);
-          bodyBuilder.constantContext = ConstantContext.required;
+          if (isConst) {
+            bodyBuilder.constantContext = ConstantContext.required;
+          }
           initializers = bodyBuilder.parseInitializers(beginInitializers!,
               doFinishConstructor: false);
         }
@@ -459,7 +461,9 @@
           .createBodyBuilderForOutlineExpression(
               libraryBuilder, classBuilder, this, classBuilder.scope, fileUri,
               formalParameterScope: formalParameterScope);
-      bodyBuilder.constantContext = ConstantContext.required;
+      if (isConst) {
+        bodyBuilder.constantContext = ConstantContext.required;
+      }
       bodyBuilder.parseInitializers(beginInitializers!,
           doFinishConstructor: isConst);
       bodyBuilder.performBacklogComputations(delayedActionPerformers);
diff --git a/pkg/front_end/testcases/super_parameters/issue48642.dart b/pkg/front_end/testcases/super_parameters/issue48642.dart
new file mode 100644
index 0000000..9ee576b
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48642.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Test {
+  Test.foo() {}
+  factory Test.bar() => new Test.foo();
+}
+
+class A1 {
+  A1({x, y});
+}
+
+class B1 extends A1 {
+  B1.foo({super.x}) : super(y: new Test.foo());
+  B1.bar({super.x}) : super(y: new Test.bar());
+}
+
+class A2 {
+  A2(x, {y});
+}
+
+class B2 extends A2 {
+  B2.foo(super.x) : super(y: new Test.foo());
+  B2.bar(super.x) : super(y: new Test.bar());
+}
+
+class A3 {
+  A3(x, {y});
+}
+
+class B3 extends A3 {
+  B3.foo({super.y}) : super(new Test.foo());
+  B3.bar({super.y}) : super(new Test.bar());
+}
+
+class A4 {
+  const A4({x, y});
+}
+
+class B4 extends A4 {
+  B4.foo({super.x}) : super(y: new Test.foo());
+  B4.bar({super.x}) : super(y: new Test.bar());
+}
+
+class A5 {
+  const A5(x, {y});
+}
+
+class B5 extends A5 {
+  B5.foo(super.x) : super(y: new Test.foo());
+  B5.bar(super.x) : super(y: new Test.bar());
+}
+
+class A6 {
+  const A6(x, {y});
+}
+
+class B6 extends A6 {
+  B6.foo({super.y}) : super(new Test.foo());
+  B6.bar({super.y}) : super(new Test.bar());
+}
+
+class A7 {
+  const A7({x, y});
+}
+
+class B7 extends A7 {
+  const B7.foo({super.x}) : super(y: new Test.foo()); // Error.
+  const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+}
+
+class A8 {
+  const A8(x, {y});
+}
+
+class B8 extends A8 {
+  const B8.foo(super.x) : super(y: new Test.foo()); // Error.
+  const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+}
+
+class A9 {
+  const A9(x, {y});
+}
+
+class B9 extends A9 {
+  const B9.foo({super.y}) : super(new Test.foo()); // Error.
+  const B9.bar({super.y}) : super(new Test.bar()); // Error.
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48642.dart.strong.expect b/pkg/front_end/testcases/super_parameters/issue48642.dart.strong.expect
new file mode 100644
index 0000000..61ae4bf
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48642.dart.strong.expect
@@ -0,0 +1,183 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:69:38: Error: New expression is not a constant expression.
+//   const B7.foo({super.x}) : super(y: new Test.foo()); // Error.
+//                                      ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:70:38: Error: New expression is not a constant expression.
+//   const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+//                                      ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:78:36: Error: New expression is not a constant expression.
+//   const B8.foo(super.x) : super(y: new Test.foo()); // Error.
+//                                    ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:79:36: Error: New expression is not a constant expression.
+//   const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+//                                    ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:87:35: Error: New expression is not a constant expression.
+//   const B9.foo({super.y}) : super(new Test.foo()); // Error.
+//                                   ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:88:35: Error: New expression is not a constant expression.
+//   const B9.bar({super.y}) : super(new Test.bar()); // Error.
+//                                   ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:70:42: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+//                                          ^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:79:40: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+//                                        ^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:88:39: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B9.bar({super.y}) : super(new Test.bar()); // Error.
+//                                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Test extends core::Object {
+  constructor foo() → self::Test
+    : super core::Object::•() {}
+  static factory bar() → self::Test
+    return new self::Test::foo();
+}
+class A1 extends core::Object {
+  constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A1
+    : super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor foo({dynamic x = #C1}) → self::B1
+    : super self::A1::•(y: new self::Test::foo(), x: x)
+    ;
+  constructor bar({dynamic x = #C1}) → self::B1
+    : super self::A1::•(y: self::Test::bar(), x: x)
+    ;
+}
+class A2 extends core::Object {
+  constructor •(dynamic x, {dynamic y = #C1}) → self::A2
+    : super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor foo(dynamic x) → self::B2
+    : super self::A2::•(x, y: new self::Test::foo())
+    ;
+  constructor bar(dynamic x) → self::B2
+    : super self::A2::•(x, y: self::Test::bar())
+    ;
+}
+class A3 extends core::Object {
+  constructor •(dynamic x, {dynamic y = #C1}) → self::A3
+    : super core::Object::•()
+    ;
+}
+class B3 extends self::A3 {
+  constructor foo({dynamic y = #C1}) → self::B3
+    : super self::A3::•(new self::Test::foo(), y: y)
+    ;
+  constructor bar({dynamic y = #C1}) → self::B3
+    : super self::A3::•(self::Test::bar(), y: y)
+    ;
+}
+class A4 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A4
+    : super core::Object::•()
+    ;
+}
+class B4 extends self::A4 {
+  constructor foo({dynamic x = #C1}) → self::B4
+    : super self::A4::•(y: new self::Test::foo(), x: x)
+    ;
+  constructor bar({dynamic x = #C1}) → self::B4
+    : super self::A4::•(y: self::Test::bar(), x: x)
+    ;
+}
+class A5 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A5
+    : super core::Object::•()
+    ;
+}
+class B5 extends self::A5 {
+  constructor foo(dynamic x) → self::B5
+    : super self::A5::•(x, y: new self::Test::foo())
+    ;
+  constructor bar(dynamic x) → self::B5
+    : super self::A5::•(x, y: self::Test::bar())
+    ;
+}
+class A6 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A6
+    : super core::Object::•()
+    ;
+}
+class B6 extends self::A6 {
+  constructor foo({dynamic y = #C1}) → self::B6
+    : super self::A6::•(new self::Test::foo(), y: y)
+    ;
+  constructor bar({dynamic y = #C1}) → self::B6
+    : super self::A6::•(self::Test::bar(), y: y)
+    ;
+}
+class A7 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A7
+    : super core::Object::•()
+    ;
+}
+class B7 extends self::A7 /*hasConstConstructor*/  {
+  const constructor foo({dynamic x = #C1}) → self::B7
+    : super self::A7::•(y: new self::Test::foo(), x: x)
+    ;
+  const constructor bar({dynamic x = #C1}) → self::B7
+    : super self::A7::•(y: invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:70:42: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+                                         ^", x: x)
+    ;
+}
+class A8 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A8
+    : super core::Object::•()
+    ;
+}
+class B8 extends self::A8 /*hasConstConstructor*/  {
+  const constructor foo(dynamic x) → self::B8
+    : super self::A8::•(x, y: new self::Test::foo())
+    ;
+  const constructor bar(dynamic x) → self::B8
+    : super self::A8::•(x, y: invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:79:40: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+                                       ^")
+    ;
+}
+class A9 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A9
+    : super core::Object::•()
+    ;
+}
+class B9 extends self::A9 /*hasConstConstructor*/  {
+  const constructor foo({dynamic y = #C1}) → self::B9
+    : super self::A9::•(new self::Test::foo(), y: y)
+    ;
+  const constructor bar({dynamic y = #C1}) → self::B9
+    : super self::A9::•(invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:88:39: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B9.bar({super.y}) : super(new Test.bar()); // Error.
+                                      ^", y: y)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48642.dart.strong.transformed.expect b/pkg/front_end/testcases/super_parameters/issue48642.dart.strong.transformed.expect
new file mode 100644
index 0000000..61ae4bf
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48642.dart.strong.transformed.expect
@@ -0,0 +1,183 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:69:38: Error: New expression is not a constant expression.
+//   const B7.foo({super.x}) : super(y: new Test.foo()); // Error.
+//                                      ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:70:38: Error: New expression is not a constant expression.
+//   const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+//                                      ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:78:36: Error: New expression is not a constant expression.
+//   const B8.foo(super.x) : super(y: new Test.foo()); // Error.
+//                                    ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:79:36: Error: New expression is not a constant expression.
+//   const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+//                                    ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:87:35: Error: New expression is not a constant expression.
+//   const B9.foo({super.y}) : super(new Test.foo()); // Error.
+//                                   ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:88:35: Error: New expression is not a constant expression.
+//   const B9.bar({super.y}) : super(new Test.bar()); // Error.
+//                                   ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:70:42: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+//                                          ^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:79:40: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+//                                        ^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:88:39: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B9.bar({super.y}) : super(new Test.bar()); // Error.
+//                                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Test extends core::Object {
+  constructor foo() → self::Test
+    : super core::Object::•() {}
+  static factory bar() → self::Test
+    return new self::Test::foo();
+}
+class A1 extends core::Object {
+  constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A1
+    : super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor foo({dynamic x = #C1}) → self::B1
+    : super self::A1::•(y: new self::Test::foo(), x: x)
+    ;
+  constructor bar({dynamic x = #C1}) → self::B1
+    : super self::A1::•(y: self::Test::bar(), x: x)
+    ;
+}
+class A2 extends core::Object {
+  constructor •(dynamic x, {dynamic y = #C1}) → self::A2
+    : super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor foo(dynamic x) → self::B2
+    : super self::A2::•(x, y: new self::Test::foo())
+    ;
+  constructor bar(dynamic x) → self::B2
+    : super self::A2::•(x, y: self::Test::bar())
+    ;
+}
+class A3 extends core::Object {
+  constructor •(dynamic x, {dynamic y = #C1}) → self::A3
+    : super core::Object::•()
+    ;
+}
+class B3 extends self::A3 {
+  constructor foo({dynamic y = #C1}) → self::B3
+    : super self::A3::•(new self::Test::foo(), y: y)
+    ;
+  constructor bar({dynamic y = #C1}) → self::B3
+    : super self::A3::•(self::Test::bar(), y: y)
+    ;
+}
+class A4 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A4
+    : super core::Object::•()
+    ;
+}
+class B4 extends self::A4 {
+  constructor foo({dynamic x = #C1}) → self::B4
+    : super self::A4::•(y: new self::Test::foo(), x: x)
+    ;
+  constructor bar({dynamic x = #C1}) → self::B4
+    : super self::A4::•(y: self::Test::bar(), x: x)
+    ;
+}
+class A5 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A5
+    : super core::Object::•()
+    ;
+}
+class B5 extends self::A5 {
+  constructor foo(dynamic x) → self::B5
+    : super self::A5::•(x, y: new self::Test::foo())
+    ;
+  constructor bar(dynamic x) → self::B5
+    : super self::A5::•(x, y: self::Test::bar())
+    ;
+}
+class A6 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A6
+    : super core::Object::•()
+    ;
+}
+class B6 extends self::A6 {
+  constructor foo({dynamic y = #C1}) → self::B6
+    : super self::A6::•(new self::Test::foo(), y: y)
+    ;
+  constructor bar({dynamic y = #C1}) → self::B6
+    : super self::A6::•(self::Test::bar(), y: y)
+    ;
+}
+class A7 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A7
+    : super core::Object::•()
+    ;
+}
+class B7 extends self::A7 /*hasConstConstructor*/  {
+  const constructor foo({dynamic x = #C1}) → self::B7
+    : super self::A7::•(y: new self::Test::foo(), x: x)
+    ;
+  const constructor bar({dynamic x = #C1}) → self::B7
+    : super self::A7::•(y: invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:70:42: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+                                         ^", x: x)
+    ;
+}
+class A8 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A8
+    : super core::Object::•()
+    ;
+}
+class B8 extends self::A8 /*hasConstConstructor*/  {
+  const constructor foo(dynamic x) → self::B8
+    : super self::A8::•(x, y: new self::Test::foo())
+    ;
+  const constructor bar(dynamic x) → self::B8
+    : super self::A8::•(x, y: invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:79:40: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+                                       ^")
+    ;
+}
+class A9 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A9
+    : super core::Object::•()
+    ;
+}
+class B9 extends self::A9 /*hasConstConstructor*/  {
+  const constructor foo({dynamic y = #C1}) → self::B9
+    : super self::A9::•(new self::Test::foo(), y: y)
+    ;
+  const constructor bar({dynamic y = #C1}) → self::B9
+    : super self::A9::•(invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:88:39: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B9.bar({super.y}) : super(new Test.bar()); // Error.
+                                      ^", y: y)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48642.dart.textual_outline.expect b/pkg/front_end/testcases/super_parameters/issue48642.dart.textual_outline.expect
new file mode 100644
index 0000000..3024153
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48642.dart.textual_outline.expect
@@ -0,0 +1,87 @@
+class Test {
+  Test.foo() {}
+  factory Test.bar() => new Test.foo();
+}
+
+class A1 {
+  A1({x, y});
+}
+
+class B1 extends A1 {
+  B1.foo({super.x}) : super(y: new Test.foo());
+  B1.bar({super.x}) : super(y: new Test.bar());
+}
+
+class A2 {
+  A2(x, {y});
+}
+
+class B2 extends A2 {
+  B2.foo(super.x) : super(y: new Test.foo());
+  B2.bar(super.x) : super(y: new Test.bar());
+}
+
+class A3 {
+  A3(x, {y});
+}
+
+class B3 extends A3 {
+  B3.foo({super.y}) : super(new Test.foo());
+  B3.bar({super.y}) : super(new Test.bar());
+}
+
+class A4 {
+  const A4({x, y});
+}
+
+class B4 extends A4 {
+  B4.foo({super.x}) : super(y: new Test.foo());
+  B4.bar({super.x}) : super(y: new Test.bar());
+}
+
+class A5 {
+  const A5(x, {y});
+}
+
+class B5 extends A5 {
+  B5.foo(super.x) : super(y: new Test.foo());
+  B5.bar(super.x) : super(y: new Test.bar());
+}
+
+class A6 {
+  const A6(x, {y});
+}
+
+class B6 extends A6 {
+  B6.foo({super.y}) : super(new Test.foo());
+  B6.bar({super.y}) : super(new Test.bar());
+}
+
+class A7 {
+  const A7({x, y});
+}
+
+class B7 extends A7 {
+  const B7.foo({super.x}) : super(y: new Test.foo());
+  const B7.bar({super.x}) : super(y: new Test.bar());
+}
+
+class A8 {
+  const A8(x, {y});
+}
+
+class B8 extends A8 {
+  const B8.foo(super.x) : super(y: new Test.foo());
+  const B8.bar(super.x) : super(y: new Test.bar());
+}
+
+class A9 {
+  const A9(x, {y});
+}
+
+class B9 extends A9 {
+  const B9.foo({super.y}) : super(new Test.foo());
+  const B9.bar({super.y}) : super(new Test.bar());
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48642.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/super_parameters/issue48642.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..74dd0fe
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48642.dart.textual_outline_modelled.expect
@@ -0,0 +1,87 @@
+class A1 {
+  A1({x, y});
+}
+
+class A2 {
+  A2(x, {y});
+}
+
+class A3 {
+  A3(x, {y});
+}
+
+class A4 {
+  const A4({x, y});
+}
+
+class A5 {
+  const A5(x, {y});
+}
+
+class A6 {
+  const A6(x, {y});
+}
+
+class A7 {
+  const A7({x, y});
+}
+
+class A8 {
+  const A8(x, {y});
+}
+
+class A9 {
+  const A9(x, {y});
+}
+
+class B1 extends A1 {
+  B1.bar({super.x}) : super(y: new Test.bar());
+  B1.foo({super.x}) : super(y: new Test.foo());
+}
+
+class B2 extends A2 {
+  B2.bar(super.x) : super(y: new Test.bar());
+  B2.foo(super.x) : super(y: new Test.foo());
+}
+
+class B3 extends A3 {
+  B3.bar({super.y}) : super(new Test.bar());
+  B3.foo({super.y}) : super(new Test.foo());
+}
+
+class B4 extends A4 {
+  B4.bar({super.x}) : super(y: new Test.bar());
+  B4.foo({super.x}) : super(y: new Test.foo());
+}
+
+class B5 extends A5 {
+  B5.bar(super.x) : super(y: new Test.bar());
+  B5.foo(super.x) : super(y: new Test.foo());
+}
+
+class B6 extends A6 {
+  B6.bar({super.y}) : super(new Test.bar());
+  B6.foo({super.y}) : super(new Test.foo());
+}
+
+class B7 extends A7 {
+  const B7.bar({super.x}) : super(y: new Test.bar());
+  const B7.foo({super.x}) : super(y: new Test.foo());
+}
+
+class B8 extends A8 {
+  const B8.bar(super.x) : super(y: new Test.bar());
+  const B8.foo(super.x) : super(y: new Test.foo());
+}
+
+class B9 extends A9 {
+  const B9.bar({super.y}) : super(new Test.bar());
+  const B9.foo({super.y}) : super(new Test.foo());
+}
+
+class Test {
+  Test.foo() {}
+  factory Test.bar() => new Test.foo();
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/super_parameters/issue48642.dart.weak.expect b/pkg/front_end/testcases/super_parameters/issue48642.dart.weak.expect
new file mode 100644
index 0000000..61ae4bf
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48642.dart.weak.expect
@@ -0,0 +1,183 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:69:38: Error: New expression is not a constant expression.
+//   const B7.foo({super.x}) : super(y: new Test.foo()); // Error.
+//                                      ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:70:38: Error: New expression is not a constant expression.
+//   const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+//                                      ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:78:36: Error: New expression is not a constant expression.
+//   const B8.foo(super.x) : super(y: new Test.foo()); // Error.
+//                                    ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:79:36: Error: New expression is not a constant expression.
+//   const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+//                                    ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:87:35: Error: New expression is not a constant expression.
+//   const B9.foo({super.y}) : super(new Test.foo()); // Error.
+//                                   ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:88:35: Error: New expression is not a constant expression.
+//   const B9.bar({super.y}) : super(new Test.bar()); // Error.
+//                                   ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:70:42: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+//                                          ^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:79:40: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+//                                        ^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:88:39: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B9.bar({super.y}) : super(new Test.bar()); // Error.
+//                                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Test extends core::Object {
+  constructor foo() → self::Test
+    : super core::Object::•() {}
+  static factory bar() → self::Test
+    return new self::Test::foo();
+}
+class A1 extends core::Object {
+  constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A1
+    : super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor foo({dynamic x = #C1}) → self::B1
+    : super self::A1::•(y: new self::Test::foo(), x: x)
+    ;
+  constructor bar({dynamic x = #C1}) → self::B1
+    : super self::A1::•(y: self::Test::bar(), x: x)
+    ;
+}
+class A2 extends core::Object {
+  constructor •(dynamic x, {dynamic y = #C1}) → self::A2
+    : super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor foo(dynamic x) → self::B2
+    : super self::A2::•(x, y: new self::Test::foo())
+    ;
+  constructor bar(dynamic x) → self::B2
+    : super self::A2::•(x, y: self::Test::bar())
+    ;
+}
+class A3 extends core::Object {
+  constructor •(dynamic x, {dynamic y = #C1}) → self::A3
+    : super core::Object::•()
+    ;
+}
+class B3 extends self::A3 {
+  constructor foo({dynamic y = #C1}) → self::B3
+    : super self::A3::•(new self::Test::foo(), y: y)
+    ;
+  constructor bar({dynamic y = #C1}) → self::B3
+    : super self::A3::•(self::Test::bar(), y: y)
+    ;
+}
+class A4 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A4
+    : super core::Object::•()
+    ;
+}
+class B4 extends self::A4 {
+  constructor foo({dynamic x = #C1}) → self::B4
+    : super self::A4::•(y: new self::Test::foo(), x: x)
+    ;
+  constructor bar({dynamic x = #C1}) → self::B4
+    : super self::A4::•(y: self::Test::bar(), x: x)
+    ;
+}
+class A5 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A5
+    : super core::Object::•()
+    ;
+}
+class B5 extends self::A5 {
+  constructor foo(dynamic x) → self::B5
+    : super self::A5::•(x, y: new self::Test::foo())
+    ;
+  constructor bar(dynamic x) → self::B5
+    : super self::A5::•(x, y: self::Test::bar())
+    ;
+}
+class A6 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A6
+    : super core::Object::•()
+    ;
+}
+class B6 extends self::A6 {
+  constructor foo({dynamic y = #C1}) → self::B6
+    : super self::A6::•(new self::Test::foo(), y: y)
+    ;
+  constructor bar({dynamic y = #C1}) → self::B6
+    : super self::A6::•(self::Test::bar(), y: y)
+    ;
+}
+class A7 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A7
+    : super core::Object::•()
+    ;
+}
+class B7 extends self::A7 /*hasConstConstructor*/  {
+  const constructor foo({dynamic x = #C1}) → self::B7
+    : super self::A7::•(y: new self::Test::foo(), x: x)
+    ;
+  const constructor bar({dynamic x = #C1}) → self::B7
+    : super self::A7::•(y: invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:70:42: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+                                         ^", x: x)
+    ;
+}
+class A8 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A8
+    : super core::Object::•()
+    ;
+}
+class B8 extends self::A8 /*hasConstConstructor*/  {
+  const constructor foo(dynamic x) → self::B8
+    : super self::A8::•(x, y: new self::Test::foo())
+    ;
+  const constructor bar(dynamic x) → self::B8
+    : super self::A8::•(x, y: invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:79:40: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+                                       ^")
+    ;
+}
+class A9 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A9
+    : super core::Object::•()
+    ;
+}
+class B9 extends self::A9 /*hasConstConstructor*/  {
+  const constructor foo({dynamic y = #C1}) → self::B9
+    : super self::A9::•(new self::Test::foo(), y: y)
+    ;
+  const constructor bar({dynamic y = #C1}) → self::B9
+    : super self::A9::•(invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:88:39: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B9.bar({super.y}) : super(new Test.bar()); // Error.
+                                      ^", y: y)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48642.dart.weak.modular.expect b/pkg/front_end/testcases/super_parameters/issue48642.dart.weak.modular.expect
new file mode 100644
index 0000000..61ae4bf
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48642.dart.weak.modular.expect
@@ -0,0 +1,183 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:69:38: Error: New expression is not a constant expression.
+//   const B7.foo({super.x}) : super(y: new Test.foo()); // Error.
+//                                      ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:70:38: Error: New expression is not a constant expression.
+//   const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+//                                      ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:78:36: Error: New expression is not a constant expression.
+//   const B8.foo(super.x) : super(y: new Test.foo()); // Error.
+//                                    ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:79:36: Error: New expression is not a constant expression.
+//   const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+//                                    ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:87:35: Error: New expression is not a constant expression.
+//   const B9.foo({super.y}) : super(new Test.foo()); // Error.
+//                                   ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:88:35: Error: New expression is not a constant expression.
+//   const B9.bar({super.y}) : super(new Test.bar()); // Error.
+//                                   ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:70:42: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+//                                          ^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:79:40: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+//                                        ^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:88:39: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B9.bar({super.y}) : super(new Test.bar()); // Error.
+//                                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Test extends core::Object {
+  constructor foo() → self::Test
+    : super core::Object::•() {}
+  static factory bar() → self::Test
+    return new self::Test::foo();
+}
+class A1 extends core::Object {
+  constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A1
+    : super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor foo({dynamic x = #C1}) → self::B1
+    : super self::A1::•(y: new self::Test::foo(), x: x)
+    ;
+  constructor bar({dynamic x = #C1}) → self::B1
+    : super self::A1::•(y: self::Test::bar(), x: x)
+    ;
+}
+class A2 extends core::Object {
+  constructor •(dynamic x, {dynamic y = #C1}) → self::A2
+    : super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor foo(dynamic x) → self::B2
+    : super self::A2::•(x, y: new self::Test::foo())
+    ;
+  constructor bar(dynamic x) → self::B2
+    : super self::A2::•(x, y: self::Test::bar())
+    ;
+}
+class A3 extends core::Object {
+  constructor •(dynamic x, {dynamic y = #C1}) → self::A3
+    : super core::Object::•()
+    ;
+}
+class B3 extends self::A3 {
+  constructor foo({dynamic y = #C1}) → self::B3
+    : super self::A3::•(new self::Test::foo(), y: y)
+    ;
+  constructor bar({dynamic y = #C1}) → self::B3
+    : super self::A3::•(self::Test::bar(), y: y)
+    ;
+}
+class A4 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A4
+    : super core::Object::•()
+    ;
+}
+class B4 extends self::A4 {
+  constructor foo({dynamic x = #C1}) → self::B4
+    : super self::A4::•(y: new self::Test::foo(), x: x)
+    ;
+  constructor bar({dynamic x = #C1}) → self::B4
+    : super self::A4::•(y: self::Test::bar(), x: x)
+    ;
+}
+class A5 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A5
+    : super core::Object::•()
+    ;
+}
+class B5 extends self::A5 {
+  constructor foo(dynamic x) → self::B5
+    : super self::A5::•(x, y: new self::Test::foo())
+    ;
+  constructor bar(dynamic x) → self::B5
+    : super self::A5::•(x, y: self::Test::bar())
+    ;
+}
+class A6 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A6
+    : super core::Object::•()
+    ;
+}
+class B6 extends self::A6 {
+  constructor foo({dynamic y = #C1}) → self::B6
+    : super self::A6::•(new self::Test::foo(), y: y)
+    ;
+  constructor bar({dynamic y = #C1}) → self::B6
+    : super self::A6::•(self::Test::bar(), y: y)
+    ;
+}
+class A7 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A7
+    : super core::Object::•()
+    ;
+}
+class B7 extends self::A7 /*hasConstConstructor*/  {
+  const constructor foo({dynamic x = #C1}) → self::B7
+    : super self::A7::•(y: new self::Test::foo(), x: x)
+    ;
+  const constructor bar({dynamic x = #C1}) → self::B7
+    : super self::A7::•(y: invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:70:42: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+                                         ^", x: x)
+    ;
+}
+class A8 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A8
+    : super core::Object::•()
+    ;
+}
+class B8 extends self::A8 /*hasConstConstructor*/  {
+  const constructor foo(dynamic x) → self::B8
+    : super self::A8::•(x, y: new self::Test::foo())
+    ;
+  const constructor bar(dynamic x) → self::B8
+    : super self::A8::•(x, y: invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:79:40: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+                                       ^")
+    ;
+}
+class A9 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A9
+    : super core::Object::•()
+    ;
+}
+class B9 extends self::A9 /*hasConstConstructor*/  {
+  const constructor foo({dynamic y = #C1}) → self::B9
+    : super self::A9::•(new self::Test::foo(), y: y)
+    ;
+  const constructor bar({dynamic y = #C1}) → self::B9
+    : super self::A9::•(invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:88:39: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B9.bar({super.y}) : super(new Test.bar()); // Error.
+                                      ^", y: y)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/pkg/front_end/testcases/super_parameters/issue48642.dart.weak.outline.expect b/pkg/front_end/testcases/super_parameters/issue48642.dart.weak.outline.expect
new file mode 100644
index 0000000..0c84a13
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48642.dart.weak.outline.expect
@@ -0,0 +1,165 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:69:38: Error: New expression is not a constant expression.
+//   const B7.foo({super.x}) : super(y: new Test.foo()); // Error.
+//                                      ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:70:38: Error: New expression is not a constant expression.
+//   const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+//                                      ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:78:36: Error: New expression is not a constant expression.
+//   const B8.foo(super.x) : super(y: new Test.foo()); // Error.
+//                                    ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:79:36: Error: New expression is not a constant expression.
+//   const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+//                                    ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:87:35: Error: New expression is not a constant expression.
+//   const B9.foo({super.y}) : super(new Test.foo()); // Error.
+//                                   ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:88:35: Error: New expression is not a constant expression.
+//   const B9.bar({super.y}) : super(new Test.bar()); // Error.
+//                                   ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:70:42: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+//                                          ^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:79:40: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+//                                        ^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:88:39: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B9.bar({super.y}) : super(new Test.bar()); // Error.
+//                                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Test extends core::Object {
+  constructor foo() → self::Test
+    ;
+  static factory bar() → self::Test
+    ;
+}
+class A1 extends core::Object {
+  constructor •({dynamic x, dynamic y}) → self::A1
+    ;
+}
+class B1 extends self::A1 {
+  constructor foo({dynamic x}) → self::B1
+    ;
+  constructor bar({dynamic x}) → self::B1
+    ;
+}
+class A2 extends core::Object {
+  constructor •(dynamic x, {dynamic y}) → self::A2
+    ;
+}
+class B2 extends self::A2 {
+  constructor foo(dynamic x) → self::B2
+    ;
+  constructor bar(dynamic x) → self::B2
+    ;
+}
+class A3 extends core::Object {
+  constructor •(dynamic x, {dynamic y}) → self::A3
+    ;
+}
+class B3 extends self::A3 {
+  constructor foo({dynamic y}) → self::B3
+    ;
+  constructor bar({dynamic y}) → self::B3
+    ;
+}
+class A4 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x, dynamic y}) → self::A4
+    : super core::Object::•()
+    ;
+}
+class B4 extends self::A4 {
+  constructor foo({dynamic x}) → self::B4
+    ;
+  constructor bar({dynamic x}) → self::B4
+    ;
+}
+class A5 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y}) → self::A5
+    : super core::Object::•()
+    ;
+}
+class B5 extends self::A5 {
+  constructor foo(dynamic x) → self::B5
+    ;
+  constructor bar(dynamic x) → self::B5
+    ;
+}
+class A6 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y}) → self::A6
+    : super core::Object::•()
+    ;
+}
+class B6 extends self::A6 {
+  constructor foo({dynamic y}) → self::B6
+    ;
+  constructor bar({dynamic y}) → self::B6
+    ;
+}
+class A7 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x, dynamic y}) → self::A7
+    : super core::Object::•()
+    ;
+}
+class B7 extends self::A7 /*hasConstConstructor*/  {
+  const constructor foo({dynamic x}) → self::B7
+    : super self::A7::•(y: new self::Test::foo(), x: x)
+    ;
+  const constructor bar({dynamic x}) → self::B7
+    : super self::A7::•(y: invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:70:42: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+                                         ^", x: x)
+    ;
+}
+class A8 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y}) → self::A8
+    : super core::Object::•()
+    ;
+}
+class B8 extends self::A8 /*hasConstConstructor*/  {
+  const constructor foo(dynamic x) → self::B8
+    : super self::A8::•(x, y: new self::Test::foo())
+    ;
+  const constructor bar(dynamic x) → self::B8
+    : super self::A8::•(x, y: invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:79:40: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+                                       ^")
+    ;
+}
+class A9 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y}) → self::A9
+    : super core::Object::•()
+    ;
+}
+class B9 extends self::A9 /*hasConstConstructor*/  {
+  const constructor foo({dynamic y}) → self::B9
+    : super self::A9::•(new self::Test::foo(), y: y)
+    ;
+  const constructor bar({dynamic y}) → self::B9
+    : super self::A9::•(invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:88:39: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B9.bar({super.y}) : super(new Test.bar()); // Error.
+                                      ^", y: y)
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/super_parameters/issue48642.dart.weak.transformed.expect b/pkg/front_end/testcases/super_parameters/issue48642.dart.weak.transformed.expect
new file mode 100644
index 0000000..61ae4bf
--- /dev/null
+++ b/pkg/front_end/testcases/super_parameters/issue48642.dart.weak.transformed.expect
@@ -0,0 +1,183 @@
+library /*isNonNullableByDefault*/;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:69:38: Error: New expression is not a constant expression.
+//   const B7.foo({super.x}) : super(y: new Test.foo()); // Error.
+//                                      ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:70:38: Error: New expression is not a constant expression.
+//   const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+//                                      ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:78:36: Error: New expression is not a constant expression.
+//   const B8.foo(super.x) : super(y: new Test.foo()); // Error.
+//                                    ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:79:36: Error: New expression is not a constant expression.
+//   const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+//                                    ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:87:35: Error: New expression is not a constant expression.
+//   const B9.foo({super.y}) : super(new Test.foo()); // Error.
+//                                   ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:88:35: Error: New expression is not a constant expression.
+//   const B9.bar({super.y}) : super(new Test.bar()); // Error.
+//                                   ^^^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:70:42: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+//                                          ^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:79:40: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+//                                        ^
+//
+// pkg/front_end/testcases/super_parameters/issue48642.dart:88:39: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+// Try using a constructor or factory that is 'const'.
+//   const B9.bar({super.y}) : super(new Test.bar()); // Error.
+//                                       ^
+//
+import self as self;
+import "dart:core" as core;
+
+class Test extends core::Object {
+  constructor foo() → self::Test
+    : super core::Object::•() {}
+  static factory bar() → self::Test
+    return new self::Test::foo();
+}
+class A1 extends core::Object {
+  constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A1
+    : super core::Object::•()
+    ;
+}
+class B1 extends self::A1 {
+  constructor foo({dynamic x = #C1}) → self::B1
+    : super self::A1::•(y: new self::Test::foo(), x: x)
+    ;
+  constructor bar({dynamic x = #C1}) → self::B1
+    : super self::A1::•(y: self::Test::bar(), x: x)
+    ;
+}
+class A2 extends core::Object {
+  constructor •(dynamic x, {dynamic y = #C1}) → self::A2
+    : super core::Object::•()
+    ;
+}
+class B2 extends self::A2 {
+  constructor foo(dynamic x) → self::B2
+    : super self::A2::•(x, y: new self::Test::foo())
+    ;
+  constructor bar(dynamic x) → self::B2
+    : super self::A2::•(x, y: self::Test::bar())
+    ;
+}
+class A3 extends core::Object {
+  constructor •(dynamic x, {dynamic y = #C1}) → self::A3
+    : super core::Object::•()
+    ;
+}
+class B3 extends self::A3 {
+  constructor foo({dynamic y = #C1}) → self::B3
+    : super self::A3::•(new self::Test::foo(), y: y)
+    ;
+  constructor bar({dynamic y = #C1}) → self::B3
+    : super self::A3::•(self::Test::bar(), y: y)
+    ;
+}
+class A4 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A4
+    : super core::Object::•()
+    ;
+}
+class B4 extends self::A4 {
+  constructor foo({dynamic x = #C1}) → self::B4
+    : super self::A4::•(y: new self::Test::foo(), x: x)
+    ;
+  constructor bar({dynamic x = #C1}) → self::B4
+    : super self::A4::•(y: self::Test::bar(), x: x)
+    ;
+}
+class A5 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A5
+    : super core::Object::•()
+    ;
+}
+class B5 extends self::A5 {
+  constructor foo(dynamic x) → self::B5
+    : super self::A5::•(x, y: new self::Test::foo())
+    ;
+  constructor bar(dynamic x) → self::B5
+    : super self::A5::•(x, y: self::Test::bar())
+    ;
+}
+class A6 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A6
+    : super core::Object::•()
+    ;
+}
+class B6 extends self::A6 {
+  constructor foo({dynamic y = #C1}) → self::B6
+    : super self::A6::•(new self::Test::foo(), y: y)
+    ;
+  constructor bar({dynamic y = #C1}) → self::B6
+    : super self::A6::•(self::Test::bar(), y: y)
+    ;
+}
+class A7 extends core::Object /*hasConstConstructor*/  {
+  const constructor •({dynamic x = #C1, dynamic y = #C1}) → self::A7
+    : super core::Object::•()
+    ;
+}
+class B7 extends self::A7 /*hasConstConstructor*/  {
+  const constructor foo({dynamic x = #C1}) → self::B7
+    : super self::A7::•(y: new self::Test::foo(), x: x)
+    ;
+  const constructor bar({dynamic x = #C1}) → self::B7
+    : super self::A7::•(y: invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:70:42: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B7.bar({super.x}) : super(y: new Test.bar()); // Error.
+                                         ^", x: x)
+    ;
+}
+class A8 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A8
+    : super core::Object::•()
+    ;
+}
+class B8 extends self::A8 /*hasConstConstructor*/  {
+  const constructor foo(dynamic x) → self::B8
+    : super self::A8::•(x, y: new self::Test::foo())
+    ;
+  const constructor bar(dynamic x) → self::B8
+    : super self::A8::•(x, y: invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:79:40: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B8.bar(super.x) : super(y: new Test.bar()); // Error.
+                                       ^")
+    ;
+}
+class A9 extends core::Object /*hasConstConstructor*/  {
+  const constructor •(dynamic x, {dynamic y = #C1}) → self::A9
+    : super core::Object::•()
+    ;
+}
+class B9 extends self::A9 /*hasConstConstructor*/  {
+  const constructor foo({dynamic y = #C1}) → self::B9
+    : super self::A9::•(new self::Test::foo(), y: y)
+    ;
+  const constructor bar({dynamic y = #C1}) → self::B9
+    : super self::A9::•(invalid-expression "pkg/front_end/testcases/super_parameters/issue48642.dart:88:39: Error: Cannot invoke a non-'const' factory where a const expression is expected.
+Try using a constructor or factory that is 'const'.
+  const B9.bar({super.y}) : super(new Test.bar()); // Error.
+                                      ^", y: y)
+    ;
+}
+static method main() → dynamic {}
+
+constants  {
+  #C1 = null
+}
diff --git a/runtime/docs/gc.md b/runtime/docs/gc.md
index 7c2fd9a..ac9696d 100644
--- a/runtime/docs/gc.md
+++ b/runtime/docs/gc.md
@@ -13,7 +13,7 @@
 Heap objects are always allocated in double-word increments. Objects in old-space are kept at double-word alignment (address % double-word == 0), and objects in new-space are kept offset from double-word alignment (address % double-word == word). This allows checking an object's age without comparing to a boundary address, avoiding restrictions on heap placement and avoiding loading the boundary from thread-local storage. Additionally, the scavenger can quickly skip over both immediates and old objects with a single branch.
 
 | Pointer    | Referent                                |
-| ---        | ---                                     |
+| ---------- | --------------------------------------- |
 | 0x00000002 | Small integer 1                         |
 | 0xFFFFFFFE | Small integer -1                        |
 | 0x00A00001 | Heap object at 0x00A00000, in old-space |
@@ -75,7 +75,7 @@
 
 ## Concurrent Marking
 
-To reduce the time the mutator is paused for old-space GCs, we allow the mutator to continue running during most of the marking work. 
+To reduce the time the mutator is paused for old-space GCs, we allow the mutator to continue running during most of the marking work.
 
 ### Barrier
 
@@ -204,3 +204,35 @@
 <instructions that cannot directly call Dart functions>
 StoreInstanceField(container, value, NoBarrier)
 ```
+
+## Finalizers
+
+The GC is aware of two types of objects for the purposes of running finalizers.
+
+1) `FinalizerEntry`
+2) `Finalizer` (`FinalizerBase`, `_FinalizerImpl`)
+
+A `FinalizerEntry` contains the `value`, the optional `detach` key, and the `token`, and a reference to the `finalizer`.
+An entry only holds on weakly to the value, detach key, and finalizer. (Similar to how `WeakReference` only holds on weakly to target).
+
+A `Finalizer` contains all entries, a list of entries of which the value is collected, and a reference to the isolate.
+
+When the value of an entry is GCed, the entry is added over to the collected list.
+If any entry is moved to the collected list, a message is sent that invokes the finalizer to call the callback on all entries in that list.
+
+When a finalizer is detached by the user, the entry token is set to the entry itself and is removed from the all entries set.
+This ensures that if the entry was already moved to the collected list, the finalizer is not executed.
+
+To speed up detaching, we use a weak map from detach keys to list of entries. This ensures entries can be GCed.
+
+Both the scavenger and marker can process finalizer entries in parallel.
+Parallel tasks use an atomic exchange on the head of the collected entries list, ensuring no entries get lost.
+Mutator threads are guaranteed to be stopped when processing entries.
+This ensures that we do not need barriers for moving entries into the finalizers collected list.
+Dart reads and replaces the collected entries list also with an atomic exchange, ensuring the GC doesn't run in between a load/store.
+
+When a finalizer gets posted a message to process finalized objects, it is being kept alive by the message.
+An alternative design would be to pre-allocate a `WeakReference` in the finalizer pointing to the finalizer, and send that itself.
+This would be at the cost of an extra object.
+
+If the finalizer object itself is GCed, the callback is not run for any of the attachments.
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 3d2a0f0..e2ef579 100644
--- a/runtime/lib/isolate.cc
+++ b/runtime/lib/isolate.cc
@@ -242,6 +242,8 @@
     break;
 
           MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary);
+          // TODO(http://dartbug.com/47777): Send and exit support: remove this.
+          MESSAGE_SNAPSHOT_ILLEGAL(Finalizer);
           MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference);
           MESSAGE_SNAPSHOT_ILLEGAL(Pointer);
           MESSAGE_SNAPSHOT_ILLEGAL(ReceivePort);
@@ -284,6 +286,7 @@
   return obj.ptr();
 }
 
+// TODO(http://dartbug.com/47777): Add support for Finalizers.
 DEFINE_NATIVE_ENTRY(Isolate_exit_, 0, 2) {
   GET_NATIVE_ARGUMENT(SendPort, port, arguments->NativeArgAt(0));
   if (!port.IsNull()) {
@@ -638,9 +641,10 @@
     // Make a copy of the state's isolate flags and hand it to the callback.
     Dart_IsolateFlags api_flags = *(state_->isolate_flags());
     api_flags.is_system_isolate = false;
-    Dart_Isolate isolate = (create_group_callback)(
-        state_->script_url(), name, nullptr, state_->package_config(),
-        &api_flags, parent_isolate_->init_callback_data(), &error);
+    Dart_Isolate isolate =
+        (create_group_callback)(state_->script_url(), name, nullptr,
+                                state_->package_config(), &api_flags,
+                                parent_isolate_->init_callback_data(), &error);
     parent_isolate_->DecrementSpawnCount();
     parent_isolate_ = nullptr;
 
diff --git a/runtime/tests/vm/dart/finalizer/finalizer_isolate_groups_run_gc_helper.dart b/runtime/tests/vm/dart/finalizer/finalizer_isolate_groups_run_gc_helper.dart
new file mode 100644
index 0000000..c0dfdeb
--- /dev/null
+++ b/runtime/tests/vm/dart/finalizer/finalizer_isolate_groups_run_gc_helper.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:isolate';
+
+import 'helpers.dart';
+
+int callbackCount = 0;
+
+void callback(Nonce token) {
+  callbackCount++;
+  print('$name: Running finalizer: token: $token');
+}
+
+final finalizer = Finalizer<Nonce>(callback);
+
+late String name;
+
+void main(List<String> arguments, SendPort port) async {
+  name = arguments[0];
+
+  final token = Nonce(42);
+  makeObjectWithFinalizer(finalizer, token);
+
+  final awaitBeforeShuttingDown = ReceivePort();
+  port.send(awaitBeforeShuttingDown.sendPort);
+  final message = await awaitBeforeShuttingDown.first;
+  print('$name: $message');
+
+  await Future.delayed(Duration(milliseconds: 1));
+  print('$name: Awaited to see if there were any callbacks.');
+
+  print('$name: Helper isolate exiting. num callbacks: $callbackCount.');
+  port.send(callbackCount);
+}
diff --git a/runtime/tests/vm/dart/finalizer/finalizer_isolate_groups_run_gc_test.dart b/runtime/tests/vm/dart/finalizer/finalizer_isolate_groups_run_gc_test.dart
new file mode 100644
index 0000000..ba5216f
--- /dev/null
+++ b/runtime/tests/vm/dart/finalizer/finalizer_isolate_groups_run_gc_test.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--use_compactor
+// VMOptions=--use_compactor --force_evacuation
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:async/async.dart';
+import 'package:expect/expect.dart';
+
+import 'helpers.dart';
+
+void main() async {
+  await testFinalizerInOtherIsolateGroupGCBeforeExit();
+  await testFinalizerInOtherIsolateGroupGCAfterExit();
+  await testFinalizerInOtherIsolateGroupNoGC();
+
+  print('$name: End of test, shutting down.');
+}
+
+const name = 'main';
+
+late bool hotReloadBot;
+
+Future<void> testFinalizerInOtherIsolateGroupGCBeforeExit() async {
+  final receivePort = ReceivePort();
+  final messagesQueue = StreamQueue(receivePort);
+
+  await Isolate.spawnUri(
+    Uri.parse('finalizer_isolate_groups_run_gc_helper.dart'),
+    ['helper 1'],
+    receivePort.sendPort,
+  );
+  final signalHelperIsolate = await messagesQueue.next as SendPort;
+
+  doGC(name: name);
+  await yieldToMessageLoop(name: name);
+
+  signalHelperIsolate.send('Done GCing.');
+
+  final helperCallbacks = await messagesQueue.next as int;
+  messagesQueue.cancel();
+  print('$name: Helper exited.');
+  // Different isolate group, so we don't expect a GC in this isolate to cause
+  // collected objects in the helper.
+  // Except for in --hot-reload-test-mode, then the GC is triggered.
+  hotReloadBot = helperCallbacks == 1;
+}
+
+Future<void> testFinalizerInOtherIsolateGroupGCAfterExit() async {
+  final receivePort = ReceivePort();
+  final messagesQueue = StreamQueue(receivePort);
+  await Isolate.spawnUri(
+    Uri.parse('finalizer_isolate_groups_run_gc_helper.dart'),
+    ['helper 2'],
+    receivePort.sendPort,
+  );
+
+  final signalHelperIsolate = await messagesQueue.next as SendPort;
+
+  signalHelperIsolate.send('Before GCing.');
+
+  final helperCallbacks = await messagesQueue.next as int;
+  messagesQueue.cancel();
+  print('$name: Helper exited.');
+  Expect.equals(hotReloadBot ? 1 : 0, helperCallbacks);
+
+  doGC(name: name);
+  await yieldToMessageLoop(name: name);
+}
+
+Future<void> testFinalizerInOtherIsolateGroupNoGC() async {
+  final receivePort = ReceivePort();
+  final messagesQueue = StreamQueue(receivePort);
+
+  await Isolate.spawnUri(
+    Uri.parse('finalizer_isolate_groups_run_gc_helper.dart'),
+    ['helper 3'],
+    receivePort.sendPort,
+  );
+  final signalHelperIsolate = await messagesQueue.next as SendPort;
+
+  signalHelperIsolate.send('Before quitting main isolate.');
+
+  final helperCallbacks = await messagesQueue.next as int;
+  messagesQueue.cancel();
+  print('$name: Helper exited.');
+  Expect.equals(hotReloadBot ? 1 : 0, helperCallbacks);
+}
diff --git a/runtime/tests/vm/dart/finalizer/finalizer_isolates_run_gc_test.dart b/runtime/tests/vm/dart/finalizer/finalizer_isolates_run_gc_test.dart
new file mode 100644
index 0000000..5750bf4
--- /dev/null
+++ b/runtime/tests/vm/dart/finalizer/finalizer_isolates_run_gc_test.dart
@@ -0,0 +1,103 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--use_compactor
+// VMOptions=--use_compactor --force_evacuation
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:expect/expect.dart';
+
+import 'helpers.dart';
+
+void main() async {
+  await testNormalExit();
+  await testSendAndExit();
+  await testSendAndExitFinalizer();
+  print('End of test, shutting down.');
+}
+
+final finalizerTokens = <Nonce>{};
+
+void callback(Nonce token) {
+  print('Running finalizer: token: $token');
+  finalizerTokens.add(token);
+}
+
+void runIsolateAttachFinalizer(Object? message) {
+  final finalizer = Finalizer<Nonce>(callback);
+  final value = Nonce(1001);
+  final token = Nonce(1002);
+  finalizer.attach(value, token);
+  final token9 = Nonce(9002);
+  makeObjectWithFinalizer(finalizer, token9);
+  if (message == null) {
+    print('Isolate done.');
+    return;
+  }
+  final list = message as List;
+  assert(list.length == 2);
+  final sendPort = list[0] as SendPort;
+  final tryToSendFinalizer = list[1] as bool;
+  if (tryToSendFinalizer) {
+    Expect.throws(() {
+      // TODO(http://dartbug.com/47777): Send and exit support.
+      print('Trying to send and exit finalizer.');
+      Isolate.exit(sendPort, [value, finalizer]);
+    });
+  }
+  print('Isolate sending and exit.');
+  Isolate.exit(sendPort, [value]);
+}
+
+Future testNormalExit() async {
+  final portExitMessage = ReceivePort();
+  await Isolate.spawn(
+    runIsolateAttachFinalizer,
+    null,
+    onExit: portExitMessage.sendPort,
+  );
+  await portExitMessage.first;
+
+  doGC();
+  await yieldToMessageLoop();
+
+  Expect.equals(0, finalizerTokens.length);
+}
+
+@pragma('vm:never-inline')
+Future<Finalizer?> testSendAndExitHelper(
+    {bool trySendFinalizer = false}) async {
+  final port = ReceivePort();
+  await Isolate.spawn(
+    runIsolateAttachFinalizer,
+    [port.sendPort, trySendFinalizer],
+  );
+  final message = await port.first as List;
+  print('Received message ($message).');
+  final value = message[0] as Nonce;
+  print('Received value ($value), but now forgetting about it.');
+
+  Expect.equals(1, message.length);
+  // TODO(http://dartbug.com/47777): Send and exit support.
+  return null;
+}
+
+Future testSendAndExit() async {
+  await testSendAndExitHelper(trySendFinalizer: false);
+
+  doGC();
+  await yieldToMessageLoop();
+
+  Expect.equals(0, finalizerTokens.length);
+}
+
+Future testSendAndExitFinalizer() async {
+  final finalizer = await testSendAndExitHelper(trySendFinalizer: true);
+
+  // TODO(http://dartbug.com/47777): Send and exit support.
+  Expect.isNull(finalizer);
+}
diff --git a/runtime/tests/vm/dart/finalizer/finalizer_nullable_run_gc_test.dart b/runtime/tests/vm/dart/finalizer/finalizer_nullable_run_gc_test.dart
new file mode 100644
index 0000000..8000a41
--- /dev/null
+++ b/runtime/tests/vm/dart/finalizer/finalizer_nullable_run_gc_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+import 'helpers.dart';
+
+void main() {
+  testFinalizer();
+}
+
+void testFinalizer() async {
+  final finalizerTokens = <Nonce?>{};
+  void callback(Nonce? token) {
+    print('Running finalizer: token: $token');
+    finalizerTokens.add(token);
+  }
+
+  final finalizer = Finalizer<Nonce?>(callback);
+
+  {
+    final detach = Nonce(2022);
+    final token = null;
+
+    makeObjectWithFinalizer(finalizer, token, detach: detach);
+
+    doGC();
+
+    // We haven't stopped running synchronous dart code yet.
+    Expect.isFalse(finalizerTokens.contains(token));
+
+    await Future.delayed(Duration(milliseconds: 1));
+
+    // Now we have.
+    Expect.isTrue(finalizerTokens.contains(token));
+
+    // Try detaching after finalizer ran.
+    finalizer.detach(detach);
+  }
+
+  print('End of test, shutting down.');
+}
diff --git a/runtime/tests/vm/dart/finalizer/finalizer_run_gc_test.dart b/runtime/tests/vm/dart/finalizer/finalizer_run_gc_test.dart
new file mode 100644
index 0000000..a278b5d
--- /dev/null
+++ b/runtime/tests/vm/dart/finalizer/finalizer_run_gc_test.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--use_compactor
+// VMOptions=--use_compactor --force_evacuation
+
+import 'package:expect/expect.dart';
+
+import 'helpers.dart';
+
+void main() {
+  testWrongArguments();
+  testFinalizer();
+}
+
+void testWrongArguments() {
+  void callback(Object token) {
+    throw 'This should never happen!';
+  }
+
+  final finalizer = Finalizer<Nonce>(callback);
+  final myFinalizable = Nonce(1000);
+  final token = Nonce(2000);
+  final detach = Nonce(3000);
+
+  Expect.throws(() {
+    finalizer.attach(myFinalizable, token, detach: 123);
+  });
+  Expect.throws(() {
+    finalizer.attach(123, token, detach: detach);
+  });
+}
+
+void testFinalizer() async {
+  final finalizerTokens = <Object>{};
+  void callback(Object token) {
+    print('Running finalizer: token: $token');
+    finalizerTokens.add(token);
+  }
+
+  final finalizer = Finalizer<Nonce>(callback);
+
+  {
+    final detach = Nonce(2022);
+    final token = Nonce(42);
+
+    makeObjectWithFinalizer(finalizer, token, detach: detach);
+
+    doGC();
+
+    // We haven't stopped running synchronous dart code yet.
+    Expect.isFalse(finalizerTokens.contains(token));
+
+    await Future.delayed(Duration(milliseconds: 1));
+
+    // Now we have.
+    Expect.isTrue(finalizerTokens.contains(token));
+
+    // Try detaching after finalizer ran.
+    finalizer.detach(detach);
+  }
+
+  {
+    final token = Nonce(1337);
+    final token2 = Nonce(1338);
+    final detachkey = Nonce(1984);
+    {
+      final value = Nonce(2);
+      final value2 = Nonce(2000000);
+      finalizer.attach(value, token, detach: detachkey);
+      finalizer.attach(value2, token2, detach: detachkey);
+      // Should detach 2 finalizers.
+      finalizer.detach(detachkey);
+      // Try detaching again, should do nothing.
+      finalizer.detach(detachkey);
+    }
+    doGC();
+    await yieldToMessageLoop();
+    Expect.isFalse(finalizerTokens.contains(token));
+    Expect.isFalse(finalizerTokens.contains(token2));
+  }
+
+  // Not running finalizer on shutdown.
+  final value = Nonce(3);
+  final token = Nonce(1337);
+  finalizer.attach(value, token);
+  print('End of test, shutting down.');
+}
diff --git a/runtime/tests/vm/dart/finalizer/finalizer_zone_run_gc_test.dart b/runtime/tests/vm/dart/finalizer/finalizer_zone_run_gc_test.dart
new file mode 100644
index 0000000..bcc6d9e1
--- /dev/null
+++ b/runtime/tests/vm/dart/finalizer/finalizer_zone_run_gc_test.dart
@@ -0,0 +1,73 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--use_compactor
+// VMOptions=--use_compactor --force_evacuation
+
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+
+import 'helpers.dart';
+
+void main() async {
+  await testFinalizerZone();
+  await testFinalizerException();
+}
+
+Future<void> testFinalizerZone() async {
+  Zone? expectedZone;
+  Zone? actualZone;
+
+  final finalizer = runZoned(() {
+    expectedZone = Zone.current;
+
+    void callback(Object token) {
+      actualZone = Zone.current;
+    }
+
+    return Finalizer<Nonce>(callback);
+  });
+
+  final detach = Nonce(2022);
+  final token = Nonce(42);
+
+  makeObjectWithFinalizer(finalizer, token, detach: detach);
+
+  doGC();
+
+  // We haven't stopped running synchronous dart code yet.
+  Expect.isNull(actualZone);
+
+  await yieldToMessageLoop();
+
+  // Now we have.
+  Expect.equals(expectedZone, actualZone);
+}
+
+Future<void> testFinalizerException() async {
+  Object? caughtError;
+
+  final finalizer = runZonedGuarded(() {
+    void callback(Object token) {
+      throw 'uncaught!';
+    }
+
+    return Finalizer<Nonce>(callback);
+  }, (Object error, StackTrace stack) {
+    caughtError = error;
+  })!;
+
+  final detach = Nonce(2022);
+  final token = Nonce(42);
+
+  makeObjectWithFinalizer(finalizer, token, detach: detach);
+
+  doGC();
+
+  Expect.isNull(caughtError);
+  await yieldToMessageLoop();
+  Expect.isNotNull(caughtError);
+}
diff --git a/runtime/tests/vm/dart/finalizer/helpers.dart b/runtime/tests/vm/dart/finalizer/helpers.dart
new file mode 100644
index 0000000..d776098
--- /dev/null
+++ b/runtime/tests/vm/dart/finalizer/helpers.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// ignore: import_internal_library, unused_import
+import 'dart:_internal';
+import 'dart:async';
+
+/// A user-defined class of which objects can be identified with a field value.
+class Nonce {
+  final int value;
+
+  Nonce(this.value);
+
+  String toString() => 'Nonce($value)';
+}
+
+/// Never inline to ensure `object` becomes unreachable.
+@pragma('vm:never-inline')
+void makeObjectWithFinalizer<T>(Finalizer<T> finalizer, T token,
+    {Object? detach}) {
+  final value = Nonce(1);
+  finalizer.attach(value, token, detach: detach);
+}
+
+/// Triggers garbage collection.
+// Defined in `dart:_internal`.
+// ignore: undefined_identifier
+void triggerGc() => VMInternalsForTesting.collectAllGarbage();
+
+void Function(String) _namedPrint(String? name) {
+  if (name != null) {
+    return (String value) => print('$name: $value');
+  }
+  return (String value) => print(value);
+}
+
+/// Does a GC and if [doAwait] awaits a future to enable running finalizers.
+///
+/// Also prints for debug purposes.
+///
+/// If provided, [name] prefixes the debug prints.
+void doGC({String? name}) {
+  final _print = _namedPrint(name);
+
+  _print('Do GC.');
+  triggerGc();
+  _print('GC done');
+}
+
+Future<void> yieldToMessageLoop({String? name}) async {
+  await Future.delayed(Duration(milliseconds: 1));
+  _namedPrint(name)('Await done.');
+  return null;
+}
diff --git a/runtime/tests/vm/dart/finalizer/weak_reference_run_gc_test.dart b/runtime/tests/vm/dart/finalizer/weak_reference_run_gc_test.dart
index 15b330d..da365b9 100644
--- a/runtime/tests/vm/dart/finalizer/weak_reference_run_gc_test.dart
+++ b/runtime/tests/vm/dart/finalizer/weak_reference_run_gc_test.dart
@@ -2,25 +2,16 @@
 // 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.
 
-// ignore: import_internal_library, unused_import
-import 'dart:_internal';
-
 import 'package:expect/expect.dart';
 
+import 'helpers.dart';
+
 void main() {
   testWeakReferenceNonExpandoKey();
   testWeakReferenceTypeArgument();
   testWeakReference();
 }
 
-class Nonce {
-  final int value;
-
-  Nonce(this.value);
-
-  String toString() => 'Nonce($value)';
-}
-
 void testWeakReferenceNonExpandoKey() {
   Expect.throwsArgumentError(() {
     WeakReference<String>("Hello world!");
@@ -55,7 +46,3 @@
 
   print('End of test, shutting down.');
 }
-
-// Defined in `dart:_internal`.
-// ignore: undefined_identifier
-void triggerGc() => VMInternalsForTesting.collectAllGarbage();
diff --git a/runtime/tests/vm/dart/isolates/fast_object_copy_test.dart b/runtime/tests/vm/dart/isolates/fast_object_copy_test.dart
index cd24fbc..d714c56 100644
--- a/runtime/tests/vm/dart/isolates/fast_object_copy_test.dart
+++ b/runtime/tests/vm/dart/isolates/fast_object_copy_test.dart
@@ -245,6 +245,7 @@
 
     await testWeakProperty();
     await testWeakReference();
+    await testFinalizer();
 
     await testForbiddenClosures();
   }
@@ -756,6 +757,14 @@
     }
   }
 
+  Future testFinalizer() async {
+    print('testFinalizer');
+
+    void callback(Object token) {}
+    final finalizer = Finalizer<Object>(callback);
+    Expect.throwsArgumentError(() => sendPort.send(finalizer));
+  }
+
   Future testForbiddenClosures() async {
     print('testForbiddenClosures');
     for (final closure in nonCopyableClosures) {
diff --git a/runtime/tests/vm/dart_2/finalizer/finalizer_isolate_groups_run_gc_helper.dart b/runtime/tests/vm/dart_2/finalizer/finalizer_isolate_groups_run_gc_helper.dart
new file mode 100644
index 0000000..58ff5bb
--- /dev/null
+++ b/runtime/tests/vm/dart_2/finalizer/finalizer_isolate_groups_run_gc_helper.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+import 'dart:isolate';
+
+import 'helpers.dart';
+
+int callbackCount = 0;
+
+void callback(Nonce token) {
+  callbackCount++;
+  print('$name: Running finalizer: token: $token');
+}
+
+final finalizer = Finalizer<Nonce>(callback);
+
+String name;
+
+void main(List<String> arguments, SendPort port) async {
+  name = arguments[0];
+
+  final token = Nonce(42);
+  makeObjectWithFinalizer(finalizer, token);
+
+  final awaitBeforeShuttingDown = ReceivePort();
+  port.send(awaitBeforeShuttingDown.sendPort);
+  final message = await awaitBeforeShuttingDown.first;
+  print('$name: $message');
+
+  await Future.delayed(Duration(milliseconds: 1));
+  print('$name: Awaited to see if there were any callbacks.');
+
+  print('$name: Helper isolate exiting. num callbacks: $callbackCount.');
+  port.send(callbackCount);
+}
diff --git a/runtime/tests/vm/dart_2/finalizer/finalizer_isolate_groups_run_gc_test.dart b/runtime/tests/vm/dart_2/finalizer/finalizer_isolate_groups_run_gc_test.dart
new file mode 100644
index 0000000..afd09bb
--- /dev/null
+++ b/runtime/tests/vm/dart_2/finalizer/finalizer_isolate_groups_run_gc_test.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--use_compactor
+// VMOptions=--use_compactor --force_evacuation
+
+// @dart = 2.9
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:async/async.dart';
+import 'package:expect/expect.dart';
+
+import 'helpers.dart';
+
+void main() async {
+  await testFinalizerInOtherIsolateGroupGCBeforeExit();
+  await testFinalizerInOtherIsolateGroupGCAfterExit();
+  await testFinalizerInOtherIsolateGroupNoGC();
+
+  print('$name: End of test, shutting down.');
+}
+
+const name = 'main';
+
+bool hotReloadBot;
+
+Future<void> testFinalizerInOtherIsolateGroupGCBeforeExit() async {
+  final receivePort = ReceivePort();
+  final messagesQueue = StreamQueue(receivePort);
+
+  await Isolate.spawnUri(
+    Uri.parse('finalizer_isolate_groups_run_gc_helper.dart'),
+    ['helper 1'],
+    receivePort.sendPort,
+  );
+  final signalHelperIsolate = await messagesQueue.next as SendPort;
+
+  doGC(name: name);
+  await yieldToMessageLoop(name: name);
+
+  signalHelperIsolate.send('Done GCing.');
+
+  final helperCallbacks = await messagesQueue.next as int;
+  messagesQueue.cancel();
+  print('$name: Helper exited.');
+  // Different isolate group, so we don't expect a GC in this isolate to cause
+  // collected objects in the helper.
+  // Except for in --hot-reload-test-mode, then the GC is triggered.
+  hotReloadBot = helperCallbacks == 1;
+}
+
+Future<void> testFinalizerInOtherIsolateGroupGCAfterExit() async {
+  final receivePort = ReceivePort();
+  final messagesQueue = StreamQueue(receivePort);
+  await Isolate.spawnUri(
+    Uri.parse('finalizer_isolate_groups_run_gc_helper.dart'),
+    ['helper 2'],
+    receivePort.sendPort,
+  );
+
+  final signalHelperIsolate = await messagesQueue.next as SendPort;
+
+  signalHelperIsolate.send('Before GCing.');
+
+  final helperCallbacks = await messagesQueue.next as int;
+  messagesQueue.cancel();
+  print('$name: Helper exited.');
+  Expect.equals(hotReloadBot ? 1 : 0, helperCallbacks);
+
+  doGC(name: name);
+  await yieldToMessageLoop(name: name);
+}
+
+Future<void> testFinalizerInOtherIsolateGroupNoGC() async {
+  final receivePort = ReceivePort();
+  final messagesQueue = StreamQueue(receivePort);
+
+  await Isolate.spawnUri(
+    Uri.parse('finalizer_isolate_groups_run_gc_helper.dart'),
+    ['helper 3'],
+    receivePort.sendPort,
+  );
+  final signalHelperIsolate = await messagesQueue.next as SendPort;
+
+  signalHelperIsolate.send('Before quitting main isolate.');
+
+  final helperCallbacks = await messagesQueue.next as int;
+  messagesQueue.cancel();
+  print('$name: Helper exited.');
+  Expect.equals(hotReloadBot ? 1 : 0, helperCallbacks);
+}
diff --git a/runtime/tests/vm/dart_2/finalizer/finalizer_isolates_run_gc_test.dart b/runtime/tests/vm/dart_2/finalizer/finalizer_isolates_run_gc_test.dart
new file mode 100644
index 0000000..7c2103d
--- /dev/null
+++ b/runtime/tests/vm/dart_2/finalizer/finalizer_isolates_run_gc_test.dart
@@ -0,0 +1,104 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--use_compactor
+// VMOptions=--use_compactor --force_evacuation
+
+// @dart = 2.9
+
+import 'dart:async';
+import 'dart:isolate';
+
+import 'package:expect/expect.dart';
+
+import 'helpers.dart';
+
+void main() async {
+  await testNormalExit();
+  await testSendAndExit();
+  await testSendAndExitFinalizer();
+  print('End of test, shutting down.');
+}
+
+final finalizerTokens = <Nonce>{};
+
+void callback(Nonce token) {
+  print('Running finalizer: token: $token');
+  finalizerTokens.add(token);
+}
+
+void runIsolateAttachFinalizer(Object message) {
+  final finalizer = Finalizer<Nonce>(callback);
+  final value = Nonce(1001);
+  final token = Nonce(1002);
+  finalizer.attach(value, token);
+  final token9 = Nonce(9002);
+  makeObjectWithFinalizer(finalizer, token9);
+  if (message == null) {
+    print('Isolate done.');
+    return;
+  }
+  final list = message as List;
+  assert(list.length == 2);
+  final sendPort = list[0] as SendPort;
+  final tryToSendFinalizer = list[1] as bool;
+  if (tryToSendFinalizer) {
+    Expect.throws(() {
+      // TODO(http://dartbug.com/47777): Send and exit support.
+      print('Trying to send and exit finalizer.');
+      Isolate.exit(sendPort, [value, finalizer]);
+    });
+  }
+  print('Isolate sending and exit.');
+  Isolate.exit(sendPort, [value]);
+}
+
+Future testNormalExit() async {
+  final portExitMessage = ReceivePort();
+  await Isolate.spawn(
+    runIsolateAttachFinalizer,
+    null,
+    onExit: portExitMessage.sendPort,
+  );
+  await portExitMessage.first;
+
+  doGC();
+  await yieldToMessageLoop();
+
+  Expect.equals(0, finalizerTokens.length);
+}
+
+@pragma('vm:never-inline')
+Future<Finalizer> testSendAndExitHelper({bool trySendFinalizer = false}) async {
+  final port = ReceivePort();
+  await Isolate.spawn(
+    runIsolateAttachFinalizer,
+    [port.sendPort, trySendFinalizer],
+  );
+  final message = await port.first as List;
+  print('Received message ($message).');
+  final value = message[0] as Nonce;
+  print('Received value ($value), but now forgetting about it.');
+
+  Expect.equals(1, message.length);
+  // TODO(http://dartbug.com/47777): Send and exit support.
+  return null;
+}
+
+Future testSendAndExit() async {
+  await testSendAndExitHelper(trySendFinalizer: false);
+
+  doGC();
+  await yieldToMessageLoop();
+
+  Expect.equals(0, finalizerTokens.length);
+}
+
+Future testSendAndExitFinalizer() async {
+  final finalizer = await testSendAndExitHelper(trySendFinalizer: true);
+
+  // TODO(http://dartbug.com/47777): Send and exit support.
+  Expect.isNull(finalizer);
+}
diff --git a/runtime/tests/vm/dart_2/finalizer/finalizer_nullable_run_gc_test.dart b/runtime/tests/vm/dart_2/finalizer/finalizer_nullable_run_gc_test.dart
new file mode 100644
index 0000000..b033c1b
--- /dev/null
+++ b/runtime/tests/vm/dart_2/finalizer/finalizer_nullable_run_gc_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+import 'helpers.dart';
+
+void main() {
+  testFinalizer();
+}
+
+void testFinalizer() async {
+  final finalizerTokens = <Nonce>{};
+  void callback(Nonce token) {
+    print('Running finalizer: token: $token');
+    finalizerTokens.add(token);
+  }
+
+  final finalizer = Finalizer<Nonce>(callback);
+
+  {
+    final detach = Nonce(2022);
+    final token = null;
+
+    makeObjectWithFinalizer(finalizer, token, detach: detach);
+
+    doGC();
+
+    // We haven't stopped running synchronous dart code yet.
+    Expect.isFalse(finalizerTokens.contains(token));
+
+    await Future.delayed(Duration(milliseconds: 1));
+
+    // Now we have.
+    Expect.isTrue(finalizerTokens.contains(token));
+
+    // Try detaching after finalizer ran.
+    finalizer.detach(detach);
+  }
+
+  print('End of test, shutting down.');
+}
diff --git a/runtime/tests/vm/dart_2/finalizer/finalizer_run_gc_test.dart b/runtime/tests/vm/dart_2/finalizer/finalizer_run_gc_test.dart
new file mode 100644
index 0000000..9c17461
--- /dev/null
+++ b/runtime/tests/vm/dart_2/finalizer/finalizer_run_gc_test.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--use_compactor
+// VMOptions=--use_compactor --force_evacuation
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+import 'helpers.dart';
+
+void main() {
+  testWrongArguments();
+  testFinalizer();
+}
+
+void testWrongArguments() {
+  void callback(Object token) {
+    throw 'This should never happen!';
+  }
+
+  final finalizer = Finalizer<Nonce>(callback);
+  final myFinalizable = Nonce(1000);
+  final token = Nonce(2000);
+  final detach = Nonce(3000);
+
+  Expect.throws(() {
+    finalizer.attach(myFinalizable, token, detach: 123);
+  });
+  Expect.throws(() {
+    finalizer.attach(123, token, detach: detach);
+  });
+}
+
+void testFinalizer() async {
+  final finalizerTokens = <Object>{};
+  void callback(Object token) {
+    print('Running finalizer: token: $token');
+    finalizerTokens.add(token);
+  }
+
+  final finalizer = Finalizer<Nonce>(callback);
+
+  {
+    final detach = Nonce(2022);
+    final token = Nonce(42);
+
+    makeObjectWithFinalizer(finalizer, token, detach: detach);
+
+    doGC();
+
+    // We haven't stopped running synchronous dart code yet.
+    Expect.isFalse(finalizerTokens.contains(token));
+
+    await Future.delayed(Duration(milliseconds: 1));
+
+    // Now we have.
+    Expect.isTrue(finalizerTokens.contains(token));
+
+    // Try detaching after finalizer ran.
+    finalizer.detach(detach);
+  }
+
+  {
+    final token = Nonce(1337);
+    final token2 = Nonce(1338);
+    final detachkey = Nonce(1984);
+    {
+      final value = Nonce(2);
+      final value2 = Nonce(2000000);
+      finalizer.attach(value, token, detach: detachkey);
+      finalizer.attach(value2, token2, detach: detachkey);
+      // Should detach 2 finalizers.
+      finalizer.detach(detachkey);
+      // Try detaching again, should do nothing.
+      finalizer.detach(detachkey);
+    }
+    doGC();
+    await yieldToMessageLoop();
+    Expect.isFalse(finalizerTokens.contains(token));
+    Expect.isFalse(finalizerTokens.contains(token2));
+  }
+
+  // Not running finalizer on shutdown.
+  final value = Nonce(3);
+  final token = Nonce(1337);
+  finalizer.attach(value, token);
+  print('End of test, shutting down.');
+}
diff --git a/runtime/tests/vm/dart_2/finalizer/finalizer_zone_run_gc_test.dart b/runtime/tests/vm/dart_2/finalizer/finalizer_zone_run_gc_test.dart
new file mode 100644
index 0000000..17646d1
--- /dev/null
+++ b/runtime/tests/vm/dart_2/finalizer/finalizer_zone_run_gc_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// VMOptions=
+// VMOptions=--use_compactor
+// VMOptions=--use_compactor --force_evacuation
+
+// @dart = 2.9
+
+import 'dart:async';
+
+import 'package:expect/expect.dart';
+
+import 'helpers.dart';
+
+void main() async {
+  await testFinalizerZone();
+  await testFinalizerException();
+}
+
+Future<void> testFinalizerZone() async {
+  Zone expectedZone;
+  Zone actualZone;
+
+  final finalizer = runZoned(() {
+    expectedZone = Zone.current;
+
+    void callback(Object token) {
+      actualZone = Zone.current;
+    }
+
+    return Finalizer<Nonce>(callback);
+  });
+
+  final detach = Nonce(2022);
+  final token = Nonce(42);
+
+  makeObjectWithFinalizer(finalizer, token, detach: detach);
+
+  doGC();
+
+  // We haven't stopped running synchronous dart code yet.
+  Expect.isNull(actualZone);
+
+  await yieldToMessageLoop();
+
+  // Now we have.
+  Expect.equals(expectedZone, actualZone);
+}
+
+Future<void> testFinalizerException() async {
+  Object caughtError;
+
+  final finalizer = runZonedGuarded(() {
+    void callback(Object token) {
+      throw 'uncaught!';
+    }
+
+    return Finalizer<Nonce>(callback);
+  }, (Object error, StackTrace stack) {
+    caughtError = error;
+  });
+
+  final detach = Nonce(2022);
+  final token = Nonce(42);
+
+  makeObjectWithFinalizer(finalizer, token, detach: detach);
+
+  doGC();
+
+  Expect.isNull(caughtError);
+  await yieldToMessageLoop();
+  Expect.isNotNull(caughtError);
+}
diff --git a/runtime/tests/vm/dart_2/finalizer/helpers.dart b/runtime/tests/vm/dart_2/finalizer/helpers.dart
new file mode 100644
index 0000000..a82646c
--- /dev/null
+++ b/runtime/tests/vm/dart_2/finalizer/helpers.dart
@@ -0,0 +1,57 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// @dart = 2.9
+
+// ignore: import_internal_library, unused_import
+import 'dart:_internal';
+import 'dart:async';
+
+/// A user-defined class of which objects can be identified with a field value.
+class Nonce {
+  final int value;
+
+  Nonce(this.value);
+
+  String toString() => 'Nonce($value)';
+}
+
+/// Never inline to ensure `value` becomes unreachable.
+@pragma('vm:never-inline')
+void makeObjectWithFinalizer<T>(Finalizer<T> finalizer, T token,
+    {Object detach}) {
+  final value = Nonce(1);
+  finalizer.attach(value, token, detach: detach);
+}
+
+/// Triggers garbage collection.
+// Defined in `dart:_internal`.
+// ignore: undefined_identifier
+void triggerGc() => VMInternalsForTesting.collectAllGarbage();
+
+void Function(String) _namedPrint(String name) {
+  if (name != null) {
+    return (String value) => print('$name: $value');
+  }
+  return (String value) => print(value);
+}
+
+/// Does a GC and if [doAwait] awaits a future to enable running finalizers.
+///
+/// Also prints for debug purposes.
+///
+/// If provided, [name] prefixes the debug prints.
+void doGC({String name}) {
+  final _print = _namedPrint(name);
+
+  _print('Do GC.');
+  triggerGc();
+  _print('GC done');
+}
+
+Future<void> yieldToMessageLoop({String name}) async {
+  await Future.delayed(Duration(milliseconds: 1));
+  _namedPrint(name)('Await done.');
+  return null;
+}
diff --git a/runtime/tests/vm/dart_2/finalizer/weak_reference_run_gc_test.dart b/runtime/tests/vm/dart_2/finalizer/weak_reference_run_gc_test.dart
index 8c7583d..708d540 100644
--- a/runtime/tests/vm/dart_2/finalizer/weak_reference_run_gc_test.dart
+++ b/runtime/tests/vm/dart_2/finalizer/weak_reference_run_gc_test.dart
@@ -4,25 +4,16 @@
 
 // @dart = 2.9
 
-// ignore: import_internal_library, unused_import
-import 'dart:_internal';
-
 import 'package:expect/expect.dart';
 
+import 'helpers.dart';
+
 void main() {
   testWeakReferenceNonExpandoKey();
   testWeakReferenceTypeArgument();
   testWeakReference();
 }
 
-class Nonce {
-  final int value;
-
-  Nonce(this.value);
-
-  String toString() => 'Nonce($value)';
-}
-
 void testWeakReferenceNonExpandoKey() {
   Expect.throwsArgumentError(() {
     WeakReference<String>("Hello world!");
@@ -57,7 +48,3 @@
 
   print('End of test, shutting down.');
 }
-
-// Defined in `dart:_internal`.
-// ignore: undefined_identifier
-void triggerGc() => VMInternalsForTesting.collectAllGarbage();
diff --git a/runtime/tests/vm/dart_2/isolates/fast_object_copy_test.dart b/runtime/tests/vm/dart_2/isolates/fast_object_copy_test.dart
index 1843f0c..91fd27d 100644
--- a/runtime/tests/vm/dart_2/isolates/fast_object_copy_test.dart
+++ b/runtime/tests/vm/dart_2/isolates/fast_object_copy_test.dart
@@ -247,6 +247,7 @@
 
     await testWeakProperty();
     await testWeakReference();
+    await testFinalizer();
 
     await testForbiddenClosures();
   }
@@ -758,6 +759,14 @@
     }
   }
 
+  Future testFinalizer() async {
+    print('testFinalizer');
+
+    void callback(Object token) {}
+    final finalizer = Finalizer<Object>(callback);
+    Expect.throwsArgumentError(() => sendPort.send(finalizer));
+  }
+
   Future testForbiddenClosures() async {
     print('testForbiddenClosures');
     for (final closure in nonCopyableClosures) {
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status
index 1f5066c..8feee00 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -108,6 +108,7 @@
 [ $compiler == dartkp ]
 dart/causal_stacks/async_throws_stack_no_causal_non_symbolic_test: SkipByDesign # --no-lazy... does nothing on precompiler.
 dart/causal_stacks/async_throws_stack_no_causal_test: SkipByDesign # --no-lazy... does nothing on precompiler.
+dart/finalizer/finalizer_isolate_groups_run_gc_test: SkipByDesign # Isolate.spawnUri is not supported in AOT.
 dart/redirection_type_shuffling_test: SkipByDesign # Uses dart:mirrors.
 dart/scavenger_abort_test: SkipSlow
 dart/v8_snapshot_profile_writer_test: Pass, Slow # Can be slow due to re-invoking the precompiler.
@@ -442,9 +443,11 @@
 # These Isolate tests that use spawnURI are hence skipped on purpose.
 [ $runtime == dart_precompiled || $runtime == vm && ($arch == simarm || $arch == simarm64 || $arch == simarm64c || $arch == simriscv32 || $arch == simriscv64) ]
 dart/data_uri_spawn_test: SkipByDesign # Isolate.spawnUri
+dart/finalizer/finalizer_isolate_groups_run_gc_test: SkipByDesign # uses spawnUri.
 dart/isolates/send_object_to_spawn_uri_isolate_test: SkipByDesign # uses spawnUri
 dart/issue32950_test: SkipByDesign # uses spawnUri.
 dart_2/data_uri_spawn_test: SkipByDesign # Isolate.spawnUri
+dart_2/finalizer/finalizer_isolate_groups_run_gc_test: SkipByDesign # uses spawnUri.
 dart_2/isolates/send_object_to_spawn_uri_isolate_test: SkipByDesign # uses spawnUri
 dart_2/issue32950_test: SkipByDesign # uses spawnUri.
 
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index dc432e3..e91180e 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -267,6 +267,10 @@
   ASSERT_EQUAL(WeakProperty::InstanceSize(), cls.host_instance_size());
   cls = object_store->weak_reference_class();
   ASSERT_EQUAL(WeakReference::InstanceSize(), cls.host_instance_size());
+  cls = object_store->finalizer_class();
+  ASSERT_EQUAL(Finalizer::InstanceSize(), cls.host_instance_size());
+  cls = object_store->finalizer_entry_class();
+  ASSERT_EQUAL(FinalizerEntry::InstanceSize(), cls.host_instance_size());
   cls = object_store->linked_hash_map_class();
   ASSERT_EQUAL(LinkedHashMap::InstanceSize(), cls.host_instance_size());
   cls = object_store->immutable_linked_hash_map_class();
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index 93e1979..501c3a8 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -68,6 +68,9 @@
   V(TypeArguments)                                                             \
   V(AbstractType)                                                              \
   V(Type)                                                                      \
+  V(FinalizerBase)                                                             \
+  V(Finalizer)                                                                 \
+  V(FinalizerEntry)                                                            \
   V(FunctionType)                                                              \
   V(TypeRef)                                                                   \
   V(TypeParameter)                                                             \
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index 4d28937..8d01fc7 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2797,6 +2797,16 @@
     case Slot::Kind::kClosure_function:
     case Slot::Kind::kClosure_function_type_arguments:
     case Slot::Kind::kClosure_instantiator_type_arguments:
+    case Slot::Kind::kFinalizer_callback:
+    case Slot::Kind::kFinalizer_type_arguments:
+    case Slot::Kind::kFinalizerBase_all_entries:
+    case Slot::Kind::kFinalizerBase_detachments:
+    case Slot::Kind::kFinalizerBase_entries_collected:
+    case Slot::Kind::kFinalizerEntry_detach:
+    case Slot::Kind::kFinalizerEntry_finalizer:
+    case Slot::Kind::kFinalizerEntry_next:
+    case Slot::Kind::kFinalizerEntry_token:
+    case Slot::Kind::kFinalizerEntry_value:
     case Slot::Kind::kFunction_data:
     case Slot::Kind::kFunction_signature:
     case Slot::Kind::kFunctionType_named_parameter_names:
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index 4a512f8..dfd04ac 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -227,6 +227,16 @@
     case Slot::Kind::kClosure_hash:
     case Slot::Kind::kCapturedVariable:
     case Slot::Kind::kDartField:
+    case Slot::Kind::kFinalizer_callback:
+    case Slot::Kind::kFinalizer_type_arguments:
+    case Slot::Kind::kFinalizerBase_all_entries:
+    case Slot::Kind::kFinalizerBase_detachments:
+    case Slot::Kind::kFinalizerBase_entries_collected:
+    case Slot::Kind::kFinalizerEntry_detach:
+    case Slot::Kind::kFinalizerEntry_finalizer:
+    case Slot::Kind::kFinalizerEntry_next:
+    case Slot::Kind::kFinalizerEntry_token:
+    case Slot::Kind::kFinalizerEntry_value:
     case Slot::Kind::kFunction_data:
     case Slot::Kind::kFunction_signature:
     case Slot::Kind::kFunctionType_named_parameter_names:
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index ab82fe2..995ce8cf 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -53,6 +53,15 @@
 //   that) or like a non-final field.
 #define NULLABLE_BOXED_NATIVE_SLOTS_LIST(V)                                    \
   V(Array, UntaggedArray, type_arguments, TypeArguments, FINAL)                \
+  V(Finalizer, UntaggedFinalizer, type_arguments, TypeArguments, FINAL)        \
+  V(FinalizerBase, UntaggedFinalizerBase, all_entries, LinkedHashSet, VAR)     \
+  V(FinalizerBase, UntaggedFinalizerBase, detachments, Dynamic, VAR)           \
+  V(FinalizerBase, UntaggedFinalizer, entries_collected, FinalizerEntry, VAR)  \
+  V(FinalizerEntry, UntaggedFinalizerEntry, value, Dynamic, VAR)               \
+  V(FinalizerEntry, UntaggedFinalizerEntry, detach, Dynamic, VAR)              \
+  V(FinalizerEntry, UntaggedFinalizerEntry, token, Dynamic, VAR)               \
+  V(FinalizerEntry, UntaggedFinalizerEntry, finalizer, FinalizerBase, VAR)     \
+  V(FinalizerEntry, UntaggedFinalizerEntry, next, FinalizerEntry, VAR)         \
   V(Function, UntaggedFunction, signature, FunctionType, FINAL)                \
   V(Context, UntaggedContext, parent, Context, FINAL)                          \
   V(Closure, UntaggedClosure, instantiator_type_arguments, TypeArguments,      \
@@ -91,6 +100,7 @@
   V(Closure, UntaggedClosure, function, Function, FINAL)                       \
   V(Closure, UntaggedClosure, context, Context, FINAL)                         \
   V(Closure, UntaggedClosure, hash, Context, VAR)                              \
+  V(Finalizer, UntaggedFinalizer, callback, Closure, FINAL)                    \
   V(Function, UntaggedFunction, data, Dynamic, FINAL)                          \
   V(FunctionType, UntaggedFunctionType, named_parameter_names, Array, FINAL)   \
   V(FunctionType, UntaggedFunctionType, parameter_types, Array, FINAL)         \
@@ -159,6 +169,7 @@
   AOT_ONLY_UNBOXED_NATIVE_SLOTS_LIST(V)                                        \
   V(ClosureData, UntaggedClosureData, default_type_arguments_kind, Uint8,      \
     FINAL)                                                                     \
+  V(FinalizerBase, UntaggedFinalizerBase, isolate, IntPtr, VAR)                \
   V(Function, UntaggedFunction, entry_point, Uword, FINAL)                     \
   V(Function, UntaggedFunction, kind_tag, Uint32, FINAL)                       \
   V(Function, UntaggedFunction, packed_fields, Uint32, FINAL)                  \
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 006ea70..9abd1fd 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -818,6 +818,13 @@
   V(ByteDataViewLength, TypedDataBase_length)                                  \
   V(ByteDataViewOffsetInBytes, TypedDataView_offset_in_bytes)                  \
   V(ByteDataViewTypedData, TypedDataView_typed_data)                           \
+  V(Finalizer_getCallback, Finalizer_callback)                                 \
+  V(FinalizerBase_getAllEntries, FinalizerBase_all_entries)                    \
+  V(FinalizerBase_getDetachments, FinalizerBase_detachments)                   \
+  V(FinalizerEntry_getDetach, FinalizerEntry_detach)                           \
+  V(FinalizerEntry_getNext, FinalizerEntry_next)                               \
+  V(FinalizerEntry_getToken, FinalizerEntry_token)                             \
+  V(FinalizerEntry_getValue, FinalizerEntry_value)                             \
   V(GrowableArrayLength, GrowableObjectArray_length)                           \
   V(ImmutableLinkedHashBase_getData, ImmutableLinkedHashBase_data)             \
   V(ImmutableLinkedHashBase_getIndex, ImmutableLinkedHashBase_index)           \
@@ -835,6 +842,14 @@
   V(WeakReference_getTarget, WeakReference_target)
 
 #define STORE_NATIVE_FIELD(V)                                                  \
+  V(Finalizer_setCallback, Finalizer_callback)                                 \
+  V(FinalizerBase_setAllEntries, FinalizerBase_all_entries)                    \
+  V(FinalizerBase_setDetachments, FinalizerBase_detachments)                   \
+  V(FinalizerEntry_setDetach, FinalizerEntry_detach)                           \
+  V(FinalizerEntry_setFinalizer, FinalizerEntry_finalizer)                     \
+  V(FinalizerEntry_setNext, FinalizerEntry_next)                               \
+  V(FinalizerEntry_setToken, FinalizerEntry_token)                             \
+  V(FinalizerEntry_setValue, FinalizerEntry_value)                             \
   V(LinkedHashBase_setData, LinkedHashBase_data)                               \
   V(LinkedHashBase_setIndex, LinkedHashBase_index)                             \
   V(WeakProperty_setKey, WeakProperty_key)                                     \
@@ -919,6 +934,10 @@
     case MethodRecognizer::kFfiAsExternalTypedDataFloat:
     case MethodRecognizer::kFfiAsExternalTypedDataDouble:
     case MethodRecognizer::kGetNativeField:
+    case MethodRecognizer::kFinalizerBase_exchangeEntriesCollectedWithNull:
+    case MethodRecognizer::kFinalizerBase_getIsolateFinalizers:
+    case MethodRecognizer::kFinalizerBase_setIsolate:
+    case MethodRecognizer::kFinalizerBase_setIsolateFinalizers:
     case MethodRecognizer::kObjectEquals:
     case MethodRecognizer::kStringBaseLength:
     case MethodRecognizer::kStringBaseIsEmpty:
@@ -1567,6 +1586,41 @@
       body += LoadLocal(parsed_function_->RawParameterVariable(0));
       body += MathUnary(MathUnaryInstr::kSqrt);
     } break;
+    case MethodRecognizer::kFinalizerBase_setIsolate:
+      ASSERT_EQUAL(function.NumParameters(), 1);
+      body += LoadLocal(parsed_function_->RawParameterVariable(0));
+      body += LoadIsolate();
+      body += ConvertUntaggedToUnboxed(kUnboxedIntPtr);
+      body += StoreNativeField(Slot::FinalizerBase_isolate());
+      body += NullConstant();
+      break;
+    case MethodRecognizer::kFinalizerBase_getIsolateFinalizers:
+      ASSERT_EQUAL(function.NumParameters(), 0);
+      body += LoadIsolate();
+      body += RawLoadField(compiler::target::Isolate::finalizers_offset());
+      break;
+    case MethodRecognizer::kFinalizerBase_setIsolateFinalizers:
+      ASSERT_EQUAL(function.NumParameters(), 1);
+      body += LoadIsolate();
+      body += LoadLocal(parsed_function_->RawParameterVariable(0));
+      body += RawStoreField(compiler::target::Isolate::finalizers_offset());
+      body += NullConstant();
+      break;
+    case MethodRecognizer::kFinalizerBase_exchangeEntriesCollectedWithNull:
+      ASSERT_EQUAL(function.NumParameters(), 1);
+      ASSERT(this->optimizing_);
+      // This relies on being force-optimized to do an 'atomic' exchange w.r.t.
+      // the GC.
+      // As an alternative design we could introduce an ExchangeNativeFieldInstr
+      // that uses the same machine code as std::atomic::exchange. Or we could
+      // use an FfiNative to do that in C.
+      body += LoadLocal(parsed_function_->RawParameterVariable(0));
+      // No GC from here til StoreNativeField.
+      body += LoadNativeField(Slot::FinalizerBase_entries_collected());
+      body += LoadLocal(parsed_function_->RawParameterVariable(0));
+      body += NullConstant();
+      body += StoreNativeField(Slot::FinalizerBase_entries_collected());
+      break;
 #define IL_BODY(method, slot)                                                  \
   case MethodRecognizer::k##method:                                            \
     ASSERT_EQUAL(function.NumParameters(), 1);                                 \
@@ -3974,6 +4028,19 @@
   return Fragment(unbox);
 }
 
+Fragment FlowGraphBuilder::LoadThread() {
+  LoadThreadInstr* instr = new (Z) LoadThreadInstr();
+  Push(instr);
+  return Fragment(instr);
+}
+
+Fragment FlowGraphBuilder::LoadIsolate() {
+  Fragment body;
+  body += LoadThread();
+  body += LoadUntagged(compiler::target::Thread::isolate_offset());
+  return body;
+}
+
 // TODO(http://dartbug.com/47487): Support unboxed output value.
 Fragment FlowGraphBuilder::BoolToInt() {
   // TODO(http://dartbug.com/36855) Build IfThenElseInstr, instead of letting
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index 03a18f6..2a92d6a 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -276,6 +276,12 @@
   // target representation.
   Fragment UnboxTruncate(Representation to);
 
+  // Loads the (untagged) thread address.
+  Fragment LoadThread();
+
+  // Loads the (untagged) isolate address.
+  Fragment LoadIsolate();
+
   // Converts a true to 1 and false to 0.
   Fragment BoolToInt();
 
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index e8a7016..1676f7c 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -110,6 +110,28 @@
   V(::, _sqrt, MathSqrt, 0x03183390)                                           \
   V(::, _exp, MathExp, 0x00f4ffd0)                                             \
   V(::, _log, MathLog, 0x09ae8462)                                             \
+  V(FinalizerBase, get:_allEntries, FinalizerBase_getAllEntries, 0xf03ff26b)   \
+  V(FinalizerBase, set:_allEntries, FinalizerBase_setAllEntries, 0x8f0920e8)   \
+  V(FinalizerBase, get:_detachments, FinalizerBase_getDetachments, 0x2f650f36) \
+  V(FinalizerBase, set:_detachments, FinalizerBase_setDetachments, 0x788f1df3) \
+  V(FinalizerBase, _exchangeEntriesCollectedWithNull,                          \
+    FinalizerBase_exchangeEntriesCollectedWithNull, 0x6c9124fb)                \
+  V(FinalizerBase, _setIsolate, FinalizerBase_setIsolate, 0xbcf7db91)          \
+  V(FinalizerBase, get:_isolateFinalizers, FinalizerBase_getIsolateFinalizers, \
+    0x70f53b2b)                                                                \
+  V(FinalizerBase, set:_isolateFinalizers, FinalizerBase_setIsolateFinalizers, \
+    0xb3e66928)                                                                \
+  V(_FinalizerImpl, get:_callback, Finalizer_getCallback, 0x6f3d56bc)          \
+  V(_FinalizerImpl, set:_callback, Finalizer_setCallback, 0xc6aa96f9)          \
+  V(FinalizerEntry, get:value, FinalizerEntry_getValue, 0xf5c9b9d7)            \
+  V(FinalizerEntry, set:value, FinalizerEntry_setValue, 0x5501cc54)            \
+  V(FinalizerEntry, get:detach, FinalizerEntry_getDetach, 0x171cd968)          \
+  V(FinalizerEntry, set:detach, FinalizerEntry_setDetach, 0x7654ebe5)          \
+  V(FinalizerEntry, set:finalizer, FinalizerEntry_setFinalizer, 0x15cfefe9)    \
+  V(FinalizerEntry, get:token, FinalizerEntry_getToken, 0x04915a72)            \
+  V(FinalizerEntry, set:token, FinalizerEntry_setToken, 0x63c96cef)            \
+  V(FinalizerEntry, get:next, FinalizerEntry_getNext, 0x7102d7a4)              \
+  V(FinalizerEntry, set:next, FinalizerEntry_setNext, 0xd0b2ee61)              \
   V(Float32x4, _Float32x4FromDoubles, Float32x4FromDoubles, 0x1845792b)        \
   V(Float32x4, Float32x4.zero, Float32x4Zero, 0xd3b64002)                      \
   V(Float32x4, _Float32x4Splat, Float32x4Splat, 0x13a552c3)                    \
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 7d7866b..2973168 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -443,6 +443,10 @@
       return WeakProperty::InstanceSize();
     case kWeakReferenceCid:
       return WeakReference::InstanceSize();
+    case kFinalizerCid:
+      return Finalizer::InstanceSize();
+    case kFinalizerEntryCid:
+      return FinalizerEntry::InstanceSize();
     case kByteBufferCid:
     case kByteDataViewCid:
     case kPointerCid:
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 5295836..2b2a7d3 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -1015,6 +1015,34 @@
   FINAL_CLASS();
 };
 
+class FinalizerBase : public AllStatic {
+ public:
+  static word all_entries_offset();
+  static word detachments_offset();
+  static word entries_collected_offset();
+  static word isolate_offset();
+  FINAL_CLASS();
+};
+
+class Finalizer : public AllStatic {
+ public:
+  static word type_arguments_offset();
+  static word callback_offset();
+  static word InstanceSize();
+  FINAL_CLASS();
+};
+
+class FinalizerEntry : public AllStatic {
+ public:
+  static word value_offset();
+  static word detach_offset();
+  static word token_offset();
+  static word next_offset();
+  static word finalizer_offset();
+  static word InstanceSize();
+  FINAL_CLASS();
+};
+
 class MirrorReference : public AllStatic {
  public:
   static word InstanceSize();
@@ -1212,6 +1240,7 @@
   static word current_tag_offset();
   static word user_tag_offset();
   static word ic_miss_code_offset();
+  static word finalizers_offset();
 #if !defined(PRODUCT)
   static word single_step_offset();
 #endif  // !defined(PRODUCT)
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 06ff2b0..e2c52c5 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -183,6 +183,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 24;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 28;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 40;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     20;
@@ -190,7 +191,7 @@
     IsolateGroup_shared_class_table_offset = 8;
 static constexpr dart::compiler::target::word
     IsolateGroup_cached_class_table_table_offset = 16;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 40;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 44;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 20;
 static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
 static constexpr dart::compiler::target::word
@@ -219,12 +220,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    160;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 116;
+    164;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 120;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    180;
+    184;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    104;
+    108;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -432,6 +433,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
 static constexpr dart::compiler::target::word Type_type_state_offset = 22;
 static constexpr dart::compiler::target::word Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    24;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 20;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    12;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    8;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 16;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 4;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 4;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 12;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    16;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 20;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 24;
@@ -514,6 +531,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     28;
 static constexpr dart::compiler::target::word Field_InstanceSize = 60;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 28;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 28;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 88;
@@ -750,6 +769,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 56;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 80;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 64;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     40;
@@ -757,7 +777,7 @@
     IsolateGroup_shared_class_table_offset = 16;
 static constexpr dart::compiler::target::word
     IsolateGroup_cached_class_table_table_offset = 32;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 80;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 40;
 static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
 static constexpr dart::compiler::target::word
@@ -786,12 +806,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    320;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
+    328;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 240;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    360;
+    368;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -1005,6 +1025,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 40;
 static constexpr dart::compiler::target::word Type_type_state_offset = 42;
 static constexpr dart::compiler::target::word Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    48;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 40;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    24;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    16;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 32;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 16;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 24;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    32;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 40;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 48;
@@ -1088,6 +1124,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     48;
 static constexpr dart::compiler::target::word Field_InstanceSize = 96;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 56;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 56;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 128;
@@ -1322,6 +1360,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 24;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 28;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 40;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     20;
@@ -1329,7 +1368,7 @@
     IsolateGroup_shared_class_table_offset = 8;
 static constexpr dart::compiler::target::word
     IsolateGroup_cached_class_table_table_offset = 16;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 40;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 44;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 20;
 static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
 static constexpr dart::compiler::target::word
@@ -1358,12 +1397,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    160;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 116;
+    164;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 120;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    180;
+    184;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    104;
+    108;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -1571,6 +1610,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
 static constexpr dart::compiler::target::word Type_type_state_offset = 22;
 static constexpr dart::compiler::target::word Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    24;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 20;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    12;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    8;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 16;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 4;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 4;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 12;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    16;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 20;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 24;
@@ -1650,6 +1705,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     28;
 static constexpr dart::compiler::target::word Field_InstanceSize = 60;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 28;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 28;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 88;
@@ -1886,6 +1943,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 56;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 80;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 64;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     40;
@@ -1893,7 +1951,7 @@
     IsolateGroup_shared_class_table_offset = 16;
 static constexpr dart::compiler::target::word
     IsolateGroup_cached_class_table_table_offset = 32;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 80;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 40;
 static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
 static constexpr dart::compiler::target::word
@@ -1922,12 +1980,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    320;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
+    328;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 240;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    360;
+    368;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -2141,6 +2199,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 40;
 static constexpr dart::compiler::target::word Type_type_state_offset = 42;
 static constexpr dart::compiler::target::word Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    48;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 40;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    24;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    16;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 32;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 16;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 24;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    32;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 40;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 48;
@@ -2225,6 +2299,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     48;
 static constexpr dart::compiler::target::word Field_InstanceSize = 96;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 56;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 56;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 128;
@@ -2459,6 +2535,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 56;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 80;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 64;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     40;
@@ -2466,7 +2543,7 @@
     IsolateGroup_shared_class_table_offset = 16;
 static constexpr dart::compiler::target::word
     IsolateGroup_cached_class_table_table_offset = 32;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 80;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 40;
 static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
 static constexpr dart::compiler::target::word
@@ -2495,12 +2572,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    320;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
+    328;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 240;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    360;
+    368;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -2714,6 +2791,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 32;
 static constexpr dart::compiler::target::word Type_type_state_offset = 34;
 static constexpr dart::compiler::target::word Type_nullability_offset = 35;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    36;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 32;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    20;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    16;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 24;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 12;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 16;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    20;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 24;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 36;
@@ -2797,6 +2890,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     32;
 static constexpr dart::compiler::target::word Field_InstanceSize = 64;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 40;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 32;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 96;
@@ -3031,6 +3126,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 56;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 80;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 64;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     40;
@@ -3038,7 +3134,7 @@
     IsolateGroup_shared_class_table_offset = 16;
 static constexpr dart::compiler::target::word
     IsolateGroup_cached_class_table_table_offset = 32;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 80;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 40;
 static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 16;
 static constexpr dart::compiler::target::word
@@ -3067,12 +3163,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    320;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
+    328;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 240;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    360;
+    368;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -3286,6 +3382,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 32;
 static constexpr dart::compiler::target::word Type_type_state_offset = 34;
 static constexpr dart::compiler::target::word Type_nullability_offset = 35;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    36;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 32;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    20;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    16;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 24;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 12;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 16;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    20;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 24;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 36;
@@ -3370,6 +3482,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     32;
 static constexpr dart::compiler::target::word Field_InstanceSize = 64;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 40;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 32;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 96;
@@ -3604,6 +3718,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 24;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 28;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 40;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 32;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     20;
@@ -3611,7 +3726,7 @@
     IsolateGroup_shared_class_table_offset = 8;
 static constexpr dart::compiler::target::word
     IsolateGroup_cached_class_table_table_offset = 16;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 40;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 44;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 20;
 static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 12;
 static constexpr dart::compiler::target::word
@@ -3640,12 +3755,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    160;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 116;
+    164;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 120;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    180;
+    184;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    104;
+    108;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -3853,6 +3968,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
 static constexpr dart::compiler::target::word Type_type_state_offset = 22;
 static constexpr dart::compiler::target::word Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    24;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 20;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    12;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    8;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 16;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 4;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 4;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 12;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    16;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 20;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 24;
@@ -3937,6 +4068,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     28;
 static constexpr dart::compiler::target::word Field_InstanceSize = 60;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 28;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 28;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 88;
@@ -4173,6 +4306,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 48;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 56;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 80;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 64;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     40;
@@ -4180,7 +4314,7 @@
     IsolateGroup_shared_class_table_offset = 16;
 static constexpr dart::compiler::target::word
     IsolateGroup_cached_class_table_table_offset = 32;
-static constexpr dart::compiler::target::word Isolate_single_step_offset = 80;
+static constexpr dart::compiler::target::word Isolate_single_step_offset = 88;
 static constexpr dart::compiler::target::word Isolate_user_tag_offset = 40;
 static constexpr dart::compiler::target::word LinkedHashBase_data_offset = 24;
 static constexpr dart::compiler::target::word
@@ -4209,12 +4343,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    320;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
+    328;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 240;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    360;
+    368;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -4428,6 +4562,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 40;
 static constexpr dart::compiler::target::word Type_type_state_offset = 42;
 static constexpr dart::compiler::target::word Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    48;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 40;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    24;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    16;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 32;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 16;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 24;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    32;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 40;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 48;
@@ -4512,6 +4662,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     48;
 static constexpr dart::compiler::target::word Field_InstanceSize = 96;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 56;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 56;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 128;
@@ -4743,6 +4895,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 36;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     20;
@@ -4778,12 +4931,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    160;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 116;
+    164;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 120;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    180;
+    184;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    104;
+    108;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -4991,6 +5144,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
 static constexpr dart::compiler::target::word Type_type_state_offset = 22;
 static constexpr dart::compiler::target::word Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    24;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 20;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    12;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    8;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 16;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 4;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 4;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 12;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    16;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 20;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 24;
@@ -5073,6 +5242,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     28;
 static constexpr dart::compiler::target::word Field_InstanceSize = 60;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 28;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 28;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 88;
@@ -5304,6 +5475,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 72;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     40;
@@ -5339,12 +5511,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    320;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
+    328;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 240;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    360;
+    368;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -5558,6 +5730,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 40;
 static constexpr dart::compiler::target::word Type_type_state_offset = 42;
 static constexpr dart::compiler::target::word Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    48;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 40;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    24;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    16;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 32;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 16;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 24;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    32;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 40;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 48;
@@ -5641,6 +5829,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     48;
 static constexpr dart::compiler::target::word Field_InstanceSize = 96;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 56;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 56;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 128;
@@ -5870,6 +6060,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 36;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     20;
@@ -5905,12 +6096,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    160;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 116;
+    164;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 120;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    180;
+    184;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    104;
+    108;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -6118,6 +6309,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
 static constexpr dart::compiler::target::word Type_type_state_offset = 22;
 static constexpr dart::compiler::target::word Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    24;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 20;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    12;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    8;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 16;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 4;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 4;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 12;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    16;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 20;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 24;
@@ -6197,6 +6404,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     28;
 static constexpr dart::compiler::target::word Field_InstanceSize = 60;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 28;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 28;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 88;
@@ -6428,6 +6637,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 72;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     40;
@@ -6463,12 +6673,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    320;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
+    328;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 240;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    360;
+    368;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -6682,6 +6892,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 40;
 static constexpr dart::compiler::target::word Type_type_state_offset = 42;
 static constexpr dart::compiler::target::word Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    48;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 40;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    24;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    16;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 32;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 16;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 24;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    32;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 40;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 48;
@@ -6766,6 +6992,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     48;
 static constexpr dart::compiler::target::word Field_InstanceSize = 96;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 56;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 56;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 128;
@@ -6995,6 +7223,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 72;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     40;
@@ -7030,12 +7259,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    320;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
+    328;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 240;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    360;
+    368;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -7249,6 +7478,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 32;
 static constexpr dart::compiler::target::word Type_type_state_offset = 34;
 static constexpr dart::compiler::target::word Type_nullability_offset = 35;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    36;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 32;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    20;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    16;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 24;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 12;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 16;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    20;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 24;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 36;
@@ -7332,6 +7577,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     32;
 static constexpr dart::compiler::target::word Field_InstanceSize = 64;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 40;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 32;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 96;
@@ -7561,6 +7808,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 72;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     40;
@@ -7596,12 +7844,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    320;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
+    328;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 240;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    360;
+    368;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -7815,6 +8063,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 32;
 static constexpr dart::compiler::target::word Type_type_state_offset = 34;
 static constexpr dart::compiler::target::word Type_nullability_offset = 35;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    36;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 32;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    20;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    16;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 24;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 12;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 16;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    20;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 24;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 36;
@@ -7899,6 +8163,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     32;
 static constexpr dart::compiler::target::word Field_InstanceSize = 64;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 40;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 32;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 96;
@@ -8128,6 +8394,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 20;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 24;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 36;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 28;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     20;
@@ -8163,12 +8430,12 @@
     12;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    160;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 116;
+    164;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 120;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    180;
+    184;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    104;
+    108;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 4;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
@@ -8376,6 +8643,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 20;
 static constexpr dart::compiler::target::word Type_type_state_offset = 22;
 static constexpr dart::compiler::target::word Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    24;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 20;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    12;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    8;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 16;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 4;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 4;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 12;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    16;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 20;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 24;
@@ -8460,6 +8743,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     28;
 static constexpr dart::compiler::target::word Field_InstanceSize = 60;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 28;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 28;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 88;
@@ -8691,6 +8976,7 @@
 static constexpr dart::compiler::target::word Int32x4_value_offset = 8;
 static constexpr dart::compiler::target::word Isolate_current_tag_offset = 40;
 static constexpr dart::compiler::target::word Isolate_default_tag_offset = 48;
+static constexpr dart::compiler::target::word Isolate_finalizers_offset = 72;
 static constexpr dart::compiler::target::word Isolate_ic_miss_code_offset = 56;
 static constexpr dart::compiler::target::word IsolateGroup_object_store_offset =
     40;
@@ -8726,12 +9012,12 @@
     24;
 static constexpr dart::compiler::target::word NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word ObjectStore_double_type_offset =
-    320;
-static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 232;
+    328;
+static constexpr dart::compiler::target::word ObjectStore_int_type_offset = 240;
 static constexpr dart::compiler::target::word ObjectStore_string_type_offset =
-    360;
+    368;
 static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
 static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
 static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
@@ -8945,6 +9231,22 @@
 static constexpr dart::compiler::target::word Type_type_class_id_offset = 40;
 static constexpr dart::compiler::target::word Type_type_state_offset = 42;
 static constexpr dart::compiler::target::word Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word Finalizer_type_arguments_offset =
+    48;
+static constexpr dart::compiler::target::word Finalizer_callback_offset = 40;
+static constexpr dart::compiler::target::word FinalizerBase_all_entries_offset =
+    24;
+static constexpr dart::compiler::target::word FinalizerBase_detachments_offset =
+    16;
+static constexpr dart::compiler::target::word
+    FinalizerBase_entries_collected_offset = 32;
+static constexpr dart::compiler::target::word FinalizerBase_isolate_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_value_offset = 8;
+static constexpr dart::compiler::target::word FinalizerEntry_detach_offset = 16;
+static constexpr dart::compiler::target::word FinalizerEntry_token_offset = 24;
+static constexpr dart::compiler::target::word FinalizerEntry_finalizer_offset =
+    32;
+static constexpr dart::compiler::target::word FinalizerEntry_next_offset = 40;
 static constexpr dart::compiler::target::word FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
     FunctionType_named_parameter_names_offset = 48;
@@ -9029,6 +9331,8 @@
 static constexpr dart::compiler::target::word FfiTrampolineData_InstanceSize =
     48;
 static constexpr dart::compiler::target::word Field_InstanceSize = 96;
+static constexpr dart::compiler::target::word Finalizer_InstanceSize = 56;
+static constexpr dart::compiler::target::word FinalizerEntry_InstanceSize = 56;
 static constexpr dart::compiler::target::word Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word Function_InstanceSize = 128;
@@ -9281,6 +9585,8 @@
     24;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     28;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    40;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     32;
 static constexpr dart::compiler::target::word
@@ -9290,7 +9596,7 @@
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_cached_class_table_table_offset = 16;
 static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
-    40;
+    44;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 20;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
     12;
@@ -9325,13 +9631,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 160;
+    AOT_ObjectStore_double_type_offset = 164;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    116;
+    120;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 180;
+    AOT_ObjectStore_string_type_offset = 184;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    104;
+    108;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 4;
@@ -9558,6 +9864,28 @@
     20;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 22;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 24;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    20;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 16;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    12;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 16;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    20;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 24;
@@ -9652,6 +9980,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 28;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 28;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    28;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 44;
@@ -9914,6 +10245,8 @@
     48;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     56;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    80;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     64;
 static constexpr dart::compiler::target::word
@@ -9923,7 +10256,7 @@
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
-    80;
+    88;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 40;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
     24;
@@ -9958,13 +10291,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 320;
+    AOT_ObjectStore_double_type_offset = 328;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 360;
+    AOT_ObjectStore_string_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
@@ -10192,6 +10525,28 @@
     40;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 42;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 48;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    40;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 32;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 32;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    40;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 48;
@@ -10288,6 +10643,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    56;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 80;
@@ -10553,6 +10911,8 @@
     48;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     56;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    80;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     64;
 static constexpr dart::compiler::target::word
@@ -10562,7 +10922,7 @@
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
-    80;
+    88;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 40;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
     24;
@@ -10597,13 +10957,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 320;
+    AOT_ObjectStore_double_type_offset = 328;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 360;
+    AOT_ObjectStore_string_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
@@ -10831,6 +11191,28 @@
     40;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 42;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 48;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    40;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 32;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 32;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    40;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 48;
@@ -10928,6 +11310,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    56;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 80;
@@ -11189,6 +11574,8 @@
     48;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     56;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    80;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     64;
 static constexpr dart::compiler::target::word
@@ -11198,7 +11585,7 @@
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
-    80;
+    88;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 40;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
     16;
@@ -11233,13 +11620,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 320;
+    AOT_ObjectStore_double_type_offset = 328;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 360;
+    AOT_ObjectStore_string_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
@@ -11467,6 +11854,28 @@
     32;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 34;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 35;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 36;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    32;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 24;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    12;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 20;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    24;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 36;
@@ -11563,6 +11972,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    32;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 56;
@@ -11824,6 +12236,8 @@
     48;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     56;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    80;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     64;
 static constexpr dart::compiler::target::word
@@ -11833,7 +12247,7 @@
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
-    80;
+    88;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 40;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
     16;
@@ -11868,13 +12282,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 320;
+    AOT_ObjectStore_double_type_offset = 328;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 360;
+    AOT_ObjectStore_string_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
@@ -12102,6 +12516,28 @@
     32;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 34;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 35;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 36;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    32;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 24;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    12;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 20;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    24;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 36;
@@ -12199,6 +12635,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    32;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 56;
@@ -12460,6 +12899,8 @@
     24;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     28;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    40;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     32;
 static constexpr dart::compiler::target::word
@@ -12469,7 +12910,7 @@
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_cached_class_table_table_offset = 16;
 static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
-    40;
+    44;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 20;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
     12;
@@ -12504,13 +12945,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 160;
+    AOT_ObjectStore_double_type_offset = 164;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    116;
+    120;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 180;
+    AOT_ObjectStore_string_type_offset = 184;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    104;
+    108;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 4;
@@ -12737,6 +13178,28 @@
     20;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 22;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 24;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    20;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 16;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    12;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 16;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    20;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 24;
@@ -12833,6 +13296,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 28;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 28;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    28;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 44;
@@ -13095,6 +13561,8 @@
     48;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     56;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    80;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     64;
 static constexpr dart::compiler::target::word
@@ -13104,7 +13572,7 @@
 static constexpr dart::compiler::target::word
     AOT_IsolateGroup_cached_class_table_table_offset = 32;
 static constexpr dart::compiler::target::word AOT_Isolate_single_step_offset =
-    80;
+    88;
 static constexpr dart::compiler::target::word AOT_Isolate_user_tag_offset = 40;
 static constexpr dart::compiler::target::word AOT_LinkedHashBase_data_offset =
     24;
@@ -13139,13 +13607,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 320;
+    AOT_ObjectStore_double_type_offset = 328;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 360;
+    AOT_ObjectStore_string_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
@@ -13373,6 +13841,28 @@
     40;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 42;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 48;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    40;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 32;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 32;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    40;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 48;
@@ -13470,6 +13960,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    56;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 80;
@@ -13728,6 +14221,8 @@
     20;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     24;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    36;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     28;
 static constexpr dart::compiler::target::word
@@ -13770,13 +14265,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 160;
+    AOT_ObjectStore_double_type_offset = 164;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    116;
+    120;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 180;
+    AOT_ObjectStore_string_type_offset = 184;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    104;
+    108;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 4;
@@ -14003,6 +14498,28 @@
     20;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 22;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 24;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    20;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 16;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    12;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 16;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    20;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 24;
@@ -14097,6 +14614,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 28;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 28;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    28;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 44;
@@ -14354,6 +14874,8 @@
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     48;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    72;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -14396,13 +14918,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 320;
+    AOT_ObjectStore_double_type_offset = 328;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 360;
+    AOT_ObjectStore_string_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
@@ -14630,6 +15152,28 @@
     40;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 42;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 48;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    40;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 32;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 32;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    40;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 48;
@@ -14726,6 +15270,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    56;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 80;
@@ -14986,6 +15533,8 @@
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     48;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    72;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -15028,13 +15577,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 320;
+    AOT_ObjectStore_double_type_offset = 328;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 360;
+    AOT_ObjectStore_string_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
@@ -15262,6 +15811,28 @@
     40;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 42;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 48;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    40;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 32;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 32;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    40;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 48;
@@ -15359,6 +15930,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    56;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 80;
@@ -15615,6 +16189,8 @@
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     48;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    72;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -15657,13 +16233,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 320;
+    AOT_ObjectStore_double_type_offset = 328;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 360;
+    AOT_ObjectStore_string_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
@@ -15891,6 +16467,28 @@
     32;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 34;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 35;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 36;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    32;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 24;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    12;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 20;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    24;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 36;
@@ -15987,6 +16585,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    32;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 56;
@@ -16243,6 +16844,8 @@
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     48;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    72;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -16285,13 +16888,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 320;
+    AOT_ObjectStore_double_type_offset = 328;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 360;
+    AOT_ObjectStore_string_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
@@ -16519,6 +17122,28 @@
     32;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 34;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 35;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 36;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    32;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 20;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 24;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    12;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 20;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    24;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 40;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 36;
@@ -16616,6 +17241,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 40;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    32;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 56;
@@ -16872,6 +17500,8 @@
     20;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     24;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    36;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     28;
 static constexpr dart::compiler::target::word
@@ -16914,13 +17544,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 160;
+    AOT_ObjectStore_double_type_offset = 164;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    116;
+    120;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 180;
+    AOT_ObjectStore_string_type_offset = 184;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    104;
+    108;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     12;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 4;
@@ -17147,6 +17777,28 @@
     20;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 22;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 23;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 24;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    20;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 12;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 8;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 16;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    4;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    12;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 16;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    20;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 28;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 24;
@@ -17243,6 +17895,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 28;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 48;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 28;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    28;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 44;
@@ -17500,6 +18155,8 @@
     40;
 static constexpr dart::compiler::target::word AOT_Isolate_default_tag_offset =
     48;
+static constexpr dart::compiler::target::word AOT_Isolate_finalizers_offset =
+    72;
 static constexpr dart::compiler::target::word AOT_Isolate_ic_miss_code_offset =
     56;
 static constexpr dart::compiler::target::word
@@ -17542,13 +18199,13 @@
 static constexpr dart::compiler::target::word
     AOT_NativeArguments_thread_offset = 0;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_double_type_offset = 320;
+    AOT_ObjectStore_double_type_offset = 328;
 static constexpr dart::compiler::target::word AOT_ObjectStore_int_type_offset =
-    232;
+    240;
 static constexpr dart::compiler::target::word
-    AOT_ObjectStore_string_type_offset = 360;
+    AOT_ObjectStore_string_type_offset = 368;
 static constexpr dart::compiler::target::word AOT_ObjectStore_type_type_offset =
-    208;
+    216;
 static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
     16;
 static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
@@ -17776,6 +18433,28 @@
     40;
 static constexpr dart::compiler::target::word AOT_Type_type_state_offset = 42;
 static constexpr dart::compiler::target::word AOT_Type_nullability_offset = 43;
+static constexpr dart::compiler::target::word
+    AOT_Finalizer_type_arguments_offset = 48;
+static constexpr dart::compiler::target::word AOT_Finalizer_callback_offset =
+    40;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_all_entries_offset = 24;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_detachments_offset = 16;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerBase_entries_collected_offset = 32;
+static constexpr dart::compiler::target::word AOT_FinalizerBase_isolate_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_value_offset =
+    8;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_detach_offset =
+    16;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_token_offset =
+    24;
+static constexpr dart::compiler::target::word
+    AOT_FinalizerEntry_finalizer_offset = 32;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_next_offset =
+    40;
 static constexpr dart::compiler::target::word AOT_FunctionType_hash_offset = 56;
 static constexpr dart::compiler::target::word
     AOT_FunctionType_named_parameter_names_offset = 48;
@@ -17873,6 +18552,9 @@
 static constexpr dart::compiler::target::word
     AOT_FfiTrampolineData_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_Field_InstanceSize = 80;
+static constexpr dart::compiler::target::word AOT_Finalizer_InstanceSize = 56;
+static constexpr dart::compiler::target::word AOT_FinalizerEntry_InstanceSize =
+    56;
 static constexpr dart::compiler::target::word AOT_Float32x4_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Float64x2_InstanceSize = 24;
 static constexpr dart::compiler::target::word AOT_Function_InstanceSize = 80;
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index 09f12cf..a2da836 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -149,6 +149,7 @@
   FIELD(Int32x4, value_offset)                                                 \
   FIELD(Isolate, current_tag_offset)                                           \
   FIELD(Isolate, default_tag_offset)                                           \
+  FIELD(Isolate, finalizers_offset)                                            \
   FIELD(Isolate, ic_miss_code_offset)                                          \
   FIELD(IsolateGroup, object_store_offset)                                     \
   FIELD(IsolateGroup, shared_class_table_offset)                               \
@@ -298,6 +299,17 @@
   FIELD(Type, type_class_id_offset)                                            \
   FIELD(Type, type_state_offset)                                               \
   FIELD(Type, nullability_offset)                                              \
+  FIELD(Finalizer, type_arguments_offset)                                      \
+  FIELD(Finalizer, callback_offset)                                            \
+  FIELD(FinalizerBase, all_entries_offset)                                     \
+  FIELD(FinalizerBase, detachments_offset)                                     \
+  FIELD(FinalizerBase, entries_collected_offset)                               \
+  FIELD(FinalizerBase, isolate_offset)                                         \
+  FIELD(FinalizerEntry, value_offset)                                          \
+  FIELD(FinalizerEntry, detach_offset)                                         \
+  FIELD(FinalizerEntry, token_offset)                                          \
+  FIELD(FinalizerEntry, finalizer_offset)                                      \
+  FIELD(FinalizerEntry, next_offset)                                           \
   FIELD(FunctionType, hash_offset)                                             \
   FIELD(FunctionType, named_parameter_names_offset)                            \
   FIELD(FunctionType, nullability_offset)                                      \
@@ -360,6 +372,8 @@
   SIZEOF(ExternalTypedData, InstanceSize, UntaggedExternalTypedData)           \
   SIZEOF(FfiTrampolineData, InstanceSize, UntaggedFfiTrampolineData)           \
   SIZEOF(Field, InstanceSize, UntaggedField)                                   \
+  SIZEOF(Finalizer, InstanceSize, UntaggedFinalizer)                           \
+  SIZEOF(FinalizerEntry, InstanceSize, UntaggedFinalizerEntry)                 \
   SIZEOF(Float32x4, InstanceSize, UntaggedFloat32x4)                           \
   SIZEOF(Float64x2, InstanceSize, UntaggedFloat64x2)                           \
   SIZEOF(Function, InstanceSize, UntaggedFunction)                             \
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index b2fd4b3..9042281 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -370,6 +370,7 @@
     Object::InitNullAndBool(vm_isolate_->group());
     vm_isolate_->isolate_group_->set_object_store(new ObjectStore());
     vm_isolate_->isolate_object_store()->Init();
+    vm_isolate_->finalizers_ = GrowableObjectArray::null();
     Object::Init(vm_isolate_->group());
     OffsetsTable::Init();
     ArgumentsDescriptor::Init();
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 46df59f..501568e 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -677,18 +677,14 @@
 }
 
 ObjectPtr DartLibraryCalls::LookupHandler(Dart_Port port_id) {
-  Thread* thread = Thread::Current();
-  Zone* zone = thread->zone();
+  Thread* const thread = Thread::Current();
+  Zone* const zone = thread->zone();
   const auto& function = Function::Handle(
       zone, thread->isolate_group()->object_store()->lookup_port_handler());
-  const int kNumArguments = 1;
   ASSERT(!function.IsNull());
   Array& args = Array::Handle(
       zone, thread->isolate()->isolate_object_store()->dart_args_1());
-  if (args.IsNull()) {
-    args = Array::New(kNumArguments);
-    thread->isolate()->isolate_object_store()->set_dart_args_1(args);
-  }
+  ASSERT(!args.IsNull());
   args.SetAt(0, Integer::Handle(zone, Integer::New(port_id)));
   const Object& result =
       Object::Handle(zone, DartEntry::InvokeFunction(function, args));
@@ -706,24 +702,7 @@
   return result.ptr();
 }
 
-ObjectPtr DartLibraryCalls::HandleMessage(Dart_Port port_id,
-                                          const Instance& message) {
-  auto thread = Thread::Current();
-  auto zone = thread->zone();
-  auto isolate = thread->isolate();
-  auto object_store = thread->isolate_group()->object_store();
-  const auto& function =
-      Function::Handle(zone, object_store->handle_message_function());
-  const int kNumArguments = 2;
-  ASSERT(!function.IsNull());
-  Array& args =
-      Array::Handle(zone, isolate->isolate_object_store()->dart_args_2());
-  if (args.IsNull()) {
-    args = Array::New(kNumArguments);
-    isolate->isolate_object_store()->set_dart_args_2(args);
-  }
-  args.SetAt(0, Integer::Handle(zone, Integer::New(port_id)));
-  args.SetAt(1, message);
+static void DebuggerSetResumeIfStepping(Isolate* isolate) {
 #if !defined(PRODUCT)
   if (isolate->debugger()->IsStepping()) {
     // If the isolate is being debugged and the debugger was stepping
@@ -732,6 +711,47 @@
     isolate->debugger()->SetResumeAction(Debugger::kStepInto);
   }
 #endif
+}
+
+ObjectPtr DartLibraryCalls::HandleMessage(Dart_Port port_id,
+                                          const Instance& message) {
+  auto* const thread = Thread::Current();
+  auto* const zone = thread->zone();
+  auto* const isolate = thread->isolate();
+  auto* const object_store = thread->isolate_group()->object_store();
+  const auto& function =
+      Function::Handle(zone, object_store->handle_message_function());
+  ASSERT(!function.IsNull());
+  Array& args =
+      Array::Handle(zone, isolate->isolate_object_store()->dart_args_2());
+  ASSERT(!args.IsNull());
+  args.SetAt(0, Integer::Handle(zone, Integer::New(port_id)));
+  args.SetAt(1, message);
+  DebuggerSetResumeIfStepping(isolate);
+  const Object& handler =
+      Object::Handle(zone, DartEntry::InvokeFunction(function, args));
+  return handler.ptr();
+}
+
+ObjectPtr DartLibraryCalls::HandleFinalizerMessage(
+    const FinalizerBase& finalizer) {
+  if (FLAG_trace_finalizers) {
+    THR_Print("Running finalizer %p callback on isolate %p\n",
+              finalizer.ptr()->untag(), finalizer.isolate());
+  }
+
+  auto* const thread = Thread::Current();
+  auto* const zone = thread->zone();
+  auto* const isolate = thread->isolate();
+  auto* const object_store = thread->isolate_group()->object_store();
+  const auto& function =
+      Function::Handle(zone, object_store->handle_finalizer_message_function());
+  ASSERT(!function.IsNull());
+  Array& args =
+      Array::Handle(zone, isolate->isolate_object_store()->dart_args_1());
+  ASSERT(!args.IsNull());
+  args.SetAt(0, finalizer);
+  DebuggerSetResumeIfStepping(isolate);
   const Object& handler =
       Object::Handle(zone, DartEntry::InvokeFunction(function, args));
   return handler.ptr();
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 4f650a8..c5cc2be 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -36,8 +36,8 @@
   intptr_t TypeArgsLen() const;  // 0 if no type argument vector is passed.
   intptr_t FirstArgIndex() const { return TypeArgsLen() > 0 ? 1 : 0; }
   intptr_t CountWithTypeArgs() const { return FirstArgIndex() + Count(); }
-  intptr_t Count() const;            // Excluding type arguments vector.
-  intptr_t Size() const;             // Excluding type arguments vector.
+  intptr_t Count() const;  // Excluding type arguments vector.
+  intptr_t Size() const;   // Excluding type arguments vector.
   intptr_t SizeWithTypeArgs() const { return FirstArgIndex() + Size(); }
   intptr_t PositionalCount() const;  // Excluding type arguments vector.
   intptr_t NamedCount() const { return Count() - PositionalCount(); }
@@ -292,10 +292,12 @@
   // handler for this port id.
   static ObjectPtr HandleMessage(Dart_Port port_id, const Instance& message);
 
+  // Invokes the finalizer to run its callbacks.
+  static ObjectPtr HandleFinalizerMessage(const FinalizerBase& finalizer);
+
   // Returns a list of open ReceivePorts.
   static ObjectPtr LookupOpenPorts();
 
-
   // Returns null on success, an ErrorPtr on failure.
   static ObjectPtr DrainMicrotaskQueue();
 
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index 1e77f74..68b49e4 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -202,6 +202,7 @@
     "Generate code for a generic CPU, unknown at compile time")                \
   D(trace_cha, bool, false, "Trace CHA operations")                            \
   R(trace_field_guards, false, bool, false, "Trace changes in field's cids.")  \
+  D(trace_finalizers, bool, false, "Traces finalizers.")                       \
   D(trace_ic, bool, false, "Trace IC handling")                                \
   D(trace_ic_miss_in_optimized, bool, false,                                   \
     "Trace IC miss in optimized code")                                         \
diff --git a/runtime/vm/heap/gc_shared.h b/runtime/vm/heap/gc_shared.h
index 1d2bf64..7e0cb2d 100644
--- a/runtime/vm/heap/gc_shared.h
+++ b/runtime/vm/heap/gc_shared.h
@@ -30,7 +30,8 @@
 // - variable name
 #define GC_LINKED_LIST(V)                                                      \
   V(WeakProperty, weak_properties)                                             \
-  V(WeakReference, weak_references)
+  V(WeakReference, weak_references)                                            \
+  V(FinalizerEntry, finalizer_entries)
 
 template <typename Type, typename PtrType>
 class GCLinkedList {
@@ -81,6 +82,115 @@
 #undef FOREACH
 };
 
+#ifdef DEBUG
+#define TRACE_FINALIZER(format, ...)                                           \
+  if (FLAG_trace_finalizers) {                                                 \
+    THR_Print("%s %p " format "\n", GCVisitorType::kName, visitor,             \
+              __VA_ARGS__);                                                    \
+  }
+#else
+#define TRACE_FINALIZER(format, ...)
+#endif
+
+// This function processes all finalizer entries discovered by a scavenger or
+// marker. If an entry is referencing an object that is going to die, such entry
+// is cleared and enqueued in the respective finalizer.
+//
+// Finalizer entries belonging to unreachable finalizer entries do not get
+// processed, so the callback will not be called for these finalizers.
+//
+// For more documentation see runtime/docs/gc.md.
+//
+// |GCVisitorType| is a concrete type implementing either marker or scavenger.
+// It is expected to provide |SetNullIfCollected| method for clearing fields
+// referring to dead objects and |kName| field which contains visitor name for
+// tracing output.
+template <typename GCVisitorType>
+void MournFinalized(GCVisitorType* visitor) {
+  FinalizerEntryPtr current_entry =
+      visitor->delayed_.finalizer_entries.Release();
+  while (current_entry != FinalizerEntry::null()) {
+    TRACE_FINALIZER("Processing Entry %p", current_entry->untag());
+    FinalizerEntryPtr next_entry =
+        current_entry->untag()->next_seen_by_gc_.Decompress(
+            current_entry->heap_base());
+    current_entry->untag()->next_seen_by_gc_ = FinalizerEntry::null();
+
+    uword heap_base = current_entry->heap_base();
+    const bool value_collected_this_gc = GCVisitorType::SetNullIfCollected(
+        heap_base, &current_entry->untag()->value_);
+    GCVisitorType::SetNullIfCollected(heap_base,
+                                      &current_entry->untag()->detach_);
+    GCVisitorType::SetNullIfCollected(heap_base,
+                                      &current_entry->untag()->finalizer_);
+
+    ObjectPtr token_object = current_entry->untag()->token();
+    // See sdk/lib/_internal/vm/lib/internal_patch.dart FinalizerBase.detach.
+    const bool is_detached = token_object == current_entry;
+
+    if (value_collected_this_gc && !is_detached) {
+      FinalizerBasePtr finalizer = current_entry->untag()->finalizer();
+
+      if (finalizer.IsRawNull()) {
+        TRACE_FINALIZER("Value collected entry %p finalizer null",
+                        current_entry->untag());
+
+        // Do nothing, the finalizer has been GCed.
+      } else if (finalizer.IsFinalizer()) {
+        TRACE_FINALIZER("Value collected entry %p finalizer %p",
+                        current_entry->untag(), finalizer->untag());
+
+        FinalizerPtr finalizer_dart = static_cast<FinalizerPtr>(finalizer);
+        // Move entry to entries collected and current head of that list as
+        // the next element. Using a atomic exchange satisfies concurrency
+        // between the parallel GC tasks.
+        // We rely on the fact that the mutator thread is not running to avoid
+        // races between GC and mutator modifying Finalizer.entries_collected.
+        //
+        // We only run in serial marker or in the finalize step in the marker,
+        // both are in safepoint.
+        // The main scavenger worker is at safepoint, the other scavenger
+        // workers are are not, but they bypass safepoint because the main
+        // worker is at a safepoint already.
+        ASSERT(Thread::Current()->IsAtSafepoint() ||
+               Thread::Current()->BypassSafepoints());
+
+        FinalizerEntryPtr previous_head =
+            finalizer_dart->untag()->exchange_entries_collected(current_entry);
+        current_entry->untag()->set_next(previous_head);
+        const bool first_entry = previous_head.IsRawNull();
+        // Schedule calling Dart finalizer.
+        if (first_entry) {
+          Isolate* isolate = finalizer->untag()->isolate_;
+          if (isolate == nullptr) {
+            TRACE_FINALIZER(
+                "Not scheduling finalizer %p callback on isolate null",
+                finalizer->untag());
+          } else {
+            TRACE_FINALIZER("Scheduling finalizer %p callback on isolate %p",
+                            finalizer->untag(), isolate);
+
+            PersistentHandle* handle =
+                isolate->group()->api_state()->AllocatePersistentHandle();
+            handle->set_ptr(finalizer);
+            MessageHandler* message_handler = isolate->message_handler();
+            message_handler->PostMessage(
+                Message::New(handle, Message::kNormalPriority),
+                /*before_events*/ false);
+          }
+        }
+      } else {
+        // TODO(http://dartbug.com/47777): Implement NativeFinalizer.
+        UNREACHABLE();
+      }
+    }
+
+    current_entry = next_entry;
+  }
+}
+
+#undef TRACE_FINALIZER
+
 }  // namespace dart
 
 #endif  // RUNTIME_VM_HEAP_GC_SHARED_H_
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index a797c39..63a150b 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -47,6 +47,10 @@
   int64_t marked_micros() const { return marked_micros_; }
   void AddMicros(int64_t micros) { marked_micros_ += micros; }
 
+#ifdef DEBUG
+  constexpr static const char* const kName = "Marker";
+#endif
+
   static bool IsMarked(ObjectPtr raw) {
     ASSERT(raw->IsHeapObject());
     ASSERT(raw->IsOldObject());
@@ -126,6 +130,9 @@
         } else if (class_id == kWeakReferenceCid) {
           WeakReferencePtr raw_weak = static_cast<WeakReferencePtr>(raw_obj);
           size = ProcessWeakReference(raw_weak);
+        } else if (class_id == kFinalizerEntryCid) {
+          FinalizerEntryPtr raw_weak = static_cast<FinalizerEntryPtr>(raw_obj);
+          size = ProcessFinalizerEntry(raw_weak);
         } else {
           size = raw_obj->untag()->VisitPointersNonvirtual(this);
         }
@@ -220,6 +227,17 @@
     return raw_weak->untag()->HeapSize();
   }
 
+  intptr_t ProcessFinalizerEntry(FinalizerEntryPtr raw_entry) {
+    ASSERT(IsMarked(raw_entry));
+    delayed_.finalizer_entries.Enqueue(raw_entry);
+    // Only visit token and next.
+    MarkObject(LoadCompressedPointerIgnoreRace(&raw_entry->untag()->token_)
+                   .Decompress(raw_entry->heap_base()));
+    MarkObject(LoadCompressedPointerIgnoreRace(&raw_entry->untag()->next_)
+                   .Decompress(raw_entry->heap_base()));
+    return raw_entry->untag()->HeapSize();
+  }
+
   void ProcessDeferredMarking() {
     ObjectPtr raw_obj;
     while ((raw_obj = deferred_work_list_.Pop()) != nullptr) {
@@ -254,6 +272,7 @@
   void FinalizeMarking() {
     work_list_.Finalize();
     deferred_work_list_.Finalize();
+    MournFinalized(this);
   }
 
   void MournWeakProperties() {
@@ -394,6 +413,9 @@
   uintptr_t marked_bytes_;
   int64_t marked_micros_;
 
+  template <typename GCVisitorType>
+  friend void MournFinalized(GCVisitorType* visitor);
+
   DISALLOW_IMPLICIT_CONSTRUCTORS(MarkingVisitorBase);
 };
 
@@ -703,6 +725,8 @@
       // Phase 3: Weak processing and statistics.
       visitor_->MournWeakProperties();
       visitor_->MournWeakReferences();
+      // Don't MournFinalized here, do it on main thread, so that we don't have
+      // to coordinate workers.
 
       marker_->IterateWeakRoots(thread);
       int64_t stop = OS::GetCurrentMonotonicMicros();
@@ -942,6 +966,7 @@
       visitor.FinalizeMarking();
       visitor.MournWeakProperties();
       visitor.MournWeakReferences();
+      MournFinalized(&visitor);
       IterateWeakRoots(thread);
       // All marking done; detach code, etc.
       int64_t stop = OS::GetCurrentMonotonicMicros();
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index 75b2519..1945296 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -138,6 +138,10 @@
         promoted_list_(promotion_stack) {}
   ~ScavengerVisitorBase() { ASSERT(delayed_.IsEmpty()); }
 
+#ifdef DEBUG
+  constexpr static const char* const kName = "Scavenger";
+#endif
+
   virtual void VisitTypedDataViewPointers(TypedDataViewPtr view,
                                           CompressedObjectPtr* first,
                                           CompressedObjectPtr* last) {
@@ -298,6 +302,7 @@
 
       MournWeakProperties();
       MournOrUpdateWeakReferences();
+      MournFinalized(this);
     }
     page_space_->ReleaseLock(freelist_);
     thread_ = nullptr;
@@ -536,6 +541,9 @@
   NewPage* tail_ = nullptr;  // Allocating from here.
   NewPage* scan_ = nullptr;  // Resolving from here.
 
+  template <typename GCVisitorType>
+  friend void MournFinalized(GCVisitorType* visitor);
+
   DISALLOW_COPY_AND_ASSIGN(ScavengerVisitorBase);
 };
 
@@ -1418,6 +1426,21 @@
         return raw_weak->untag()->HeapSize();
       }
     }
+  } else if (UNLIKELY(class_id == kFinalizerEntryCid)) {
+    FinalizerEntryPtr raw_entry = static_cast<FinalizerEntryPtr>(raw_obj);
+    ASSERT(IsNotForwarding(raw_entry));
+    delayed_.finalizer_entries.Enqueue(raw_entry);
+    // Only visit token and next.
+#if !defined(DART_COMPRESSED_POINTERS)
+    ScavengePointer(&raw_entry->untag()->token_);
+    ScavengePointer(&raw_entry->untag()->next_);
+#else
+    ScavengeCompressedPointer(raw_entry->heap_base(),
+                              &raw_entry->untag()->token_);
+    ScavengeCompressedPointer(raw_entry->heap_base(),
+                              &raw_entry->untag()->next_);
+#endif
+    return raw_entry->untag()->HeapSize();
   }
   return raw_obj->untag()->VisitPointersNonvirtual(this);
 }
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 59450e8..287aa91 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -1388,6 +1388,15 @@
         }
       }
     }
+  } else if (message->IsFinalizerInvocationRequest()) {
+    const Object& msg_handler = Object::Handle(
+        zone,
+        DartLibraryCalls::HandleFinalizerMessage(FinalizerBase::Cast(msg)));
+    if (msg_handler.IsError()) {
+      status = ProcessUnhandledException(Error::Cast(msg_handler));
+    } else {
+      // The handler closure which was used to successfully handle the message.
+    }
   } else if (message->dest_port() == Message::kIllegalPort) {
     // Check whether this is a delayed OOB message which needed handling as
     // part of the regular message dispatch. All other messages are dropped on
@@ -1686,6 +1695,7 @@
       default_tag_(UserTag::null()),
       ic_miss_code_(Code::null()),
       field_table_(new FieldTable(/*isolate=*/this)),
+      finalizers_(GrowableObjectArray::null()),
       isolate_group_(isolate_group),
       isolate_object_store_(new IsolateObjectStore()),
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -2465,6 +2475,34 @@
     }
   }
 
+  // Set live finalizers isolate to null, before deleting the message handler.
+  // TODO(http://dartbug.com/47777): How to detect if the isolate field was ever
+  // initialized beyond RAW_NULL?
+  const auto& finalizers =
+      GrowableObjectArray::Handle(stack_zone.GetZone(), finalizers_);
+  if (!finalizers.IsNull()) {
+    const intptr_t num_finalizers = finalizers.Length();
+    auto& weak_reference = WeakReference::Handle(stack_zone.GetZone());
+    auto& finalizer = FinalizerBase::Handle(stack_zone.GetZone());
+    for (int i = 0; i < num_finalizers; i++) {
+      weak_reference ^= finalizers.At(i);
+      finalizer ^= weak_reference.target();
+      if (!finalizer.IsNull()) {
+        if (finalizer.isolate() == this) {
+          if (FLAG_trace_finalizers) {
+            THR_Print("Isolate %p Setting finalizer %p isolate to null\n", this,
+                      finalizer.ptr()->untag());
+          }
+          // Finalizer was not sent to another isolate with send and exit.
+          finalizer.set_isolate(nullptr);
+        } else {
+          // TODO(http://dartbug.com/47777): Send and exit support.
+          UNREACHABLE();
+        }
+      }
+    }
+  }
+
   // Close all the ports owned by this isolate.
   PortMap::ClosePorts(message_handler());
 
@@ -2571,7 +2609,6 @@
           "--check-reloaded is enabled.\n");
     }
   }
-
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
   // Then, proceed with low-level teardown.
@@ -2721,6 +2758,7 @@
   visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&ic_miss_code_));
   visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&tag_table_));
   visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&sticky_error_));
+  visitor->VisitPointer(reinterpret_cast<ObjectPtr*>(&finalizers_));
 #if !defined(PRODUCT)
   visitor->VisitPointer(
       reinterpret_cast<ObjectPtr*>(&pending_service_extension_calls_));
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index e714838..bd1e9fb 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -1065,6 +1065,10 @@
   void set_init_callback_data(void* value) { init_callback_data_ = value; }
   void* init_callback_data() const { return init_callback_data_; }
 
+  static intptr_t finalizers_offset() {
+    return OFFSET_OF(Isolate, finalizers_);
+  }
+
 #if !defined(DART_PRECOMPILED_RUNTIME)
   NativeCallbackTrampolines* native_callback_trampolines() {
     return &native_callback_trampolines_;
@@ -1540,6 +1544,9 @@
   UserTagPtr default_tag_;
   CodePtr ic_miss_code_;
   FieldTable* field_table_ = nullptr;
+  // Used to clear out `UntaggedFinalizerBase::isolate_` pointers on isolate
+  // shutdown to prevent usage of dangling pointers.
+  GrowableObjectArrayPtr finalizers_;
   bool single_step_ = false;
   bool is_system_isolate_ = false;
   // End accessed from generated code.
@@ -1651,7 +1658,7 @@
   Dart_EnvironmentCallback environment_callback_ = nullptr;
   Random random_;
   Simulator* simulator_ = nullptr;
-  Mutex mutex_;                            // Protects compiler stats.
+  Mutex mutex_;  // Protects compiler stats.
   MessageHandler* message_handler_ = nullptr;
   intptr_t defer_finalization_count_ = 0;
   DeoptContext* deopt_context_ = nullptr;
@@ -1727,7 +1734,7 @@
   friend class ServiceIsolate;
   friend class Thread;
   friend class Timeline;
-  friend class IsolateGroup;   // reload_context_
+  friend class IsolateGroup;  // reload_context_
 
   DISALLOW_COPY_AND_ASSIGN(Isolate);
 };
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 0b1eb10..f5e8986 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1300,7 +1300,8 @@
     }
     if (!Api::IsFfiEnabled() &&
         target_library.url() == Symbols::DartFfi().ptr() &&
-        library->url() != Symbols::DartCore().ptr()) {
+        library->url() != Symbols::DartCore().ptr() &&
+        library->url() != Symbols::DartInternal().ptr()) {
       H.ReportError(
           "import of dart:ffi is not supported in the current Dart runtime");
     }
diff --git a/runtime/vm/message.cc b/runtime/vm/message.cc
index 0f2d2e4..d9d0680 100644
--- a/runtime/vm/message.cc
+++ b/runtime/vm/message.cc
@@ -45,12 +45,20 @@
   ASSERT(IsPersistentHandle());
 }
 
+Message::Message(PersistentHandle* handle, Priority priority)
+    : dest_port_(ILLEGAL_PORT),
+      payload_(handle),
+      snapshot_length_(kFinalizerSnapshotLen),
+      priority_(priority) {
+  ASSERT(IsFinalizerInvocationRequest());
+}
+
 Message::~Message() {
   if (IsSnapshot()) {
     free(payload_.snapshot_);
   }
   delete finalizable_data_;
-  if (IsPersistentHandle()) {
+  if (IsPersistentHandle() || IsFinalizerInvocationRequest()) {
     auto isolate_group = IsolateGroup::Current();
     isolate_group->api_state()->FreePersistentHandle(
         payload_.persistent_handle_);
diff --git a/runtime/vm/message.h b/runtime/vm/message.h
index 4c82bdf..46064a9 100644
--- a/runtime/vm/message.h
+++ b/runtime/vm/message.h
@@ -62,8 +62,13 @@
   // the VM heap. This is indicated by setting the len_ field to 0.
   Message(Dart_Port dest_port, ObjectPtr raw_obj, Priority priority);
 
+  // A message sent from SendPort.send or SendPort.sendAndExit where sender and
+  // receiver are in the same isolate group.
   Message(Dart_Port dest_port, PersistentHandle* handle, Priority priority);
 
+  // A message sent from GC to run a finalizer.
+  Message(PersistentHandle* handle, Priority priority);
+
   ~Message();
 
   template <typename... Args>
@@ -94,7 +99,7 @@
     return payload_.raw_obj_;
   }
   PersistentHandle* persistent_handle() const {
-    ASSERT(IsPersistentHandle());
+    ASSERT(IsPersistentHandle() || IsFinalizerInvocationRequest());
     return payload_.persistent_handle_;
   }
   Priority priority() const { return priority_; }
@@ -103,7 +108,9 @@
   // of at the top of the message loop. Control messages from dart:isolate or
   // vm-service requests.
   bool IsOOB() const { return priority_ == Message::kOOBPriority; }
-  bool IsSnapshot() const { return !IsRaw() && !IsPersistentHandle(); }
+  bool IsSnapshot() const {
+    return !IsRaw() && !IsPersistentHandle() && !IsFinalizerInvocationRequest();
+  }
   // A message whose object is an immortal object from the vm-isolate's heap.
   bool IsRaw() const { return snapshot_length_ == 0; }
   // A message sent from SendPort.send or SendPort.sendAndExit where sender and
@@ -111,6 +118,10 @@
   bool IsPersistentHandle() const {
     return snapshot_length_ == kPersistentHandleSnapshotLen;
   }
+  // A message sent from GC to run a finalizer.
+  bool IsFinalizerInvocationRequest() const {
+    return snapshot_length_ == kFinalizerSnapshotLen;
+  }
 
   void DropFinalizers() {
     if (finalizable_data_ != nullptr) {
@@ -124,6 +135,7 @@
 
  private:
   static intptr_t const kPersistentHandleSnapshotLen = -1;
+  static intptr_t const kFinalizerSnapshotLen = -2;
 
   friend class MessageQueue;
 
diff --git a/runtime/vm/message_handler.h b/runtime/vm/message_handler.h
index 715641b..228c745 100644
--- a/runtime/vm/message_handler.h
+++ b/runtime/vm/message_handler.h
@@ -211,6 +211,8 @@
   Thread* thread() const { return Thread::Current(); }
 
  private:
+  template <typename GCVisitorType>
+  friend void MournFinalized(GCVisitorType* visitor);
   friend class PortMap;
   friend class MessageHandlerTestPeer;
   friend class MessageHandlerTask;
diff --git a/runtime/vm/message_snapshot.cc b/runtime/vm/message_snapshot.cc
index cc40ebb..b0d5250 100644
--- a/runtime/vm/message_snapshot.cc
+++ b/runtime/vm/message_snapshot.cc
@@ -26,7 +26,6 @@
 
 namespace dart {
 
-
 static Dart_CObject cobj_sentinel = {Dart_CObject_kUnsupported, {false}};
 static Dart_CObject cobj_transition_sentinel = {Dart_CObject_kUnsupported,
                                                 {false}};
@@ -46,8 +45,12 @@
   }
 
   static Dart_CObject* cobj_null() { return &getInstance().cobj_null_; }
-  static Dart_CObject* cobj_empty_array() { return &getInstance().cobj_empty_array_; }
-  static Dart_CObject* cobj_zero_array() { return &getInstance().cobj_zero_array_; }
+  static Dart_CObject* cobj_empty_array() {
+    return &getInstance().cobj_empty_array_;
+  }
+  static Dart_CObject* cobj_zero_array() {
+    return &getInstance().cobj_zero_array_;
+  }
 
  private:
   PredefinedCObjects() {
@@ -3938,6 +3941,11 @@
 ObjectPtr ReadMessage(Thread* thread, Message* message) {
   if (message->IsRaw()) {
     return message->raw_obj();
+  } else if (message->IsFinalizerInvocationRequest()) {
+    PersistentHandle* handle = message->persistent_handle();
+    Object& msg_obj = Object::Handle(thread->zone(), handle->ptr());
+    ASSERT(msg_obj.IsFinalizer());
+    return msg_obj.ptr();
   } else if (message->IsPersistentHandle()) {
     return ReadObjectGraphCopyMessage(thread, message->persistent_handle());
   } else {
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 7b71456..a81a147 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -118,7 +118,7 @@
 
 cpp_vtable Object::builtin_vtables_[kNumPredefinedCids] = {};
 
-// These are initialized to a value that will force a illegal memory access if
+// These are initialized to a value that will force an illegal memory access if
 // they are being used.
 #if defined(RAW_NULL)
 #error RAW_NULL should not be defined.
@@ -2344,6 +2344,15 @@
     pending_classes.Add(cls);
     RegisterClass(cls, Symbols::FfiDynamicLibrary(), lib);
 
+    cls = Class::New<Finalizer, RTN::Finalizer>(isolate_group);
+    cls.set_type_arguments_field_offset(
+        Finalizer::type_arguments_offset(),
+        RTN::Finalizer::type_arguments_offset());
+    cls.set_num_type_arguments_unsafe(1);
+    object_store->set_finalizer_class(cls);
+    pending_classes.Add(cls);
+    RegisterPrivateClass(cls, Symbols::_FinalizerImpl(), core_lib);
+
     // Pre-register the internal library so we can place the vm class
     // FinalizerEntry there rather than the core library.
     lib = Library::LookupLibrary(thread, Symbols::DartInternal());
@@ -2356,6 +2365,11 @@
     ASSERT(!lib.IsNull());
     ASSERT(lib.ptr() == Library::InternalLibrary());
 
+    cls = Class::New<FinalizerEntry, RTN::FinalizerEntry>(isolate_group);
+    object_store->set_finalizer_entry_class(cls);
+    pending_classes.Add(cls);
+    RegisterClass(cls, Symbols::FinalizerEntry(), lib);
+
     // Finish the initialization by compiling the bootstrap scripts containing
     // the base interfaces and the implementation of the internal classes.
     const Error& error = Error::Handle(
@@ -2523,6 +2537,10 @@
     object_store->set_weak_property_class(cls);
     cls = Class::New<WeakReference, RTN::WeakReference>(isolate_group);
     object_store->set_weak_reference_class(cls);
+    cls = Class::New<Finalizer, RTN::Finalizer>(isolate_group);
+    object_store->set_finalizer_class(cls);
+    cls = Class::New<FinalizerEntry, RTN::FinalizerEntry>(isolate_group);
+    object_store->set_finalizer_entry_class(cls);
 
     cls = Class::New<MirrorReference, RTN::MirrorReference>(isolate_group);
     cls = Class::New<UserTag, RTN::UserTag>(isolate_group);
@@ -11250,8 +11268,7 @@
   FieldGuardUpdater(const Field* field, const Object& value);
 
   bool IsUpdateNeeded() {
-    return does_guarded_cid_need_update_ ||
-           does_is_nullable_need_update_ ||
+    return does_guarded_cid_need_update_ || does_is_nullable_need_update_ ||
            does_list_length_and_offset_need_update_ ||
            does_static_type_exactness_state_need_update_;
   }
@@ -11274,7 +11291,8 @@
   }
 
   intptr_t guarded_list_length() { return list_length_; }
-  void set_guarded_list_length_and_offset(intptr_t list_length,
+  void set_guarded_list_length_and_offset(
+      intptr_t list_length,
       intptr_t list_length_in_object_offset) {
     list_length_ = list_length;
     list_length_in_object_offset_ = list_length_in_object_offset;
@@ -11678,15 +11696,15 @@
   return;
 }
 
-FieldGuardUpdater::FieldGuardUpdater(const Field* field, const Object& value):
-    field_(field),
-    value_(value),
-    guarded_cid_(field->guarded_cid()),
-    is_nullable_(field->is_nullable()),
-    list_length_(field->guarded_list_length()),
-    list_length_in_object_offset_(
-        field->guarded_list_length_in_object_offset()),
-    static_type_exactness_state_(field->static_type_exactness_state()) {
+FieldGuardUpdater::FieldGuardUpdater(const Field* field, const Object& value)
+    : field_(field),
+      value_(value),
+      guarded_cid_(field->guarded_cid()),
+      is_nullable_(field->is_nullable()),
+      list_length_(field->guarded_list_length()),
+      list_length_in_object_offset_(
+          field->guarded_list_length_in_object_offset()),
+      static_type_exactness_state_(field->static_type_exactness_state()) {
   ReviewGuards();
   ReviewExactnessState();
 }
@@ -26012,14 +26030,50 @@
                        space, WeakReference::ContainsCompressedPointers());
   return static_cast<WeakReferencePtr>(raw);
 }
-
 const char* WeakReference::ToCString() const {
   TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
   String& type_args_name = String::Handle(type_args.UserVisibleName());
-  return OS::SCreate(Thread::Current()->zone(), "WeakReference%s",
+  return OS::SCreate(Thread::Current()->zone(), "_WeakReference%s",
                      type_args_name.ToCString());
 }
 
+const char* FinalizerBase::ToCString() const {
+  return "FinalizerBase";
+}
+
+FinalizerPtr Finalizer::New(Heap::Space space) {
+  ASSERT(IsolateGroup::Current()->object_store()->finalizer_class() !=
+         Class::null());
+  ObjectPtr raw =
+      Object::Allocate(Finalizer::kClassId, Finalizer::InstanceSize(), space,
+                       Finalizer::ContainsCompressedPointers());
+  return static_cast<FinalizerPtr>(raw);
+}
+
+const char* Finalizer::ToCString() const {
+  TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
+  String& type_args_name = String::Handle(type_args.UserVisibleName());
+  return OS::SCreate(Thread::Current()->zone(), "_FinalizerImpl%s",
+                     type_args_name.ToCString());
+}
+
+FinalizerEntryPtr FinalizerEntry::New(Heap::Space space) {
+  ASSERT(IsolateGroup::Current()->object_store()->finalizer_entry_class() !=
+         Class::null());
+  ObjectPtr raw =
+      Object::Allocate(FinalizerEntry::kClassId, FinalizerEntry::InstanceSize(),
+                       space, FinalizerEntry::ContainsCompressedPointers());
+  return static_cast<FinalizerEntryPtr>(raw);
+}
+
+void FinalizerEntry::set_finalizer(const FinalizerBase& value) const {
+  untag()->set_finalizer(value.ptr());
+}
+
+const char* FinalizerEntry::ToCString() const {
+  return "FinalizerEntry";
+}
+
 AbstractTypePtr MirrorReference::GetAbstractTypeReferent() const {
   ASSERT(Object::Handle(referent()).IsAbstractType());
   return AbstractType::Cast(Object::Handle(referent())).ptr();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 607d88d..34b5b78 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -3188,7 +3188,29 @@
   bool ForceOptimize() const {
     return IsFfiFromAddress() || IsFfiGetAddress() || IsFfiLoad() ||
            IsFfiStore() || IsFfiTrampoline() || IsFfiAsExternalTypedData() ||
-           IsTypedDataViewFactory() || IsUtf8Scan() || IsGetNativeField();
+           IsTypedDataViewFactory() || IsUtf8Scan() || IsGetNativeField() ||
+           IsFinalizerForceOptimized();
+  }
+
+  bool IsFinalizerForceOptimized() const {
+    // Either because of unboxed/untagged data, or because we don't want the GC
+    // to trigger in between.
+    switch (recognized_kind()) {
+      case MethodRecognizer::kFinalizerBase_getIsolateFinalizers:
+      case MethodRecognizer::kFinalizerBase_setIsolate:
+      case MethodRecognizer::kFinalizerBase_setIsolateFinalizers:
+        // Unboxed/untagged representation not supported in unoptimized.
+        return true;
+      case MethodRecognizer::kFinalizerBase_exchangeEntriesCollectedWithNull:
+        // Prevent the GC from running so that the operation is atomic from
+        // a GC point of view. Always double check implementation in
+        // kernel_to_il.cc that no GC can happen in between the relevant IL
+        // instructions.
+        // TODO(https://dartbug.com/48527): Support inlining.
+        return true;
+      default:
+        return false;
+    }
   }
 
   bool CanBeInlined() const;
@@ -12021,15 +12043,109 @@
     return RoundedAllocationSize(sizeof(UntaggedWeakReference));
   }
 
-  static void Clear(WeakReferencePtr raw_weak) {
-    ASSERT(raw_weak->untag()->next_seen_by_gc_ ==
-           CompressedWeakReferencePtr(WeakReference::null()));
-    // This action is performed by the GC. No barrier.
-    raw_weak->untag()->target_ = Object::null();
+ private:
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(WeakReference, Instance);
+  friend class Class;
+};
+
+class FinalizerEntry : public Instance {
+ public:
+  ObjectPtr value() const { return untag()->value(); }
+  void set_value(const Object& value) const { untag()->set_value(value.ptr()); }
+  static intptr_t value_offset() {
+    return OFFSET_OF(UntaggedFinalizerEntry, value_);
+  }
+
+  ObjectPtr detach() const { return untag()->detach(); }
+  void set_detach(const Object& value) const {
+    untag()->set_detach(value.ptr());
+  }
+  static intptr_t detach_offset() {
+    return OFFSET_OF(UntaggedFinalizerEntry, detach_);
+  }
+
+  ObjectPtr token() const { return untag()->token(); }
+  void set_token(const Object& value) const { untag()->set_token(value.ptr()); }
+  static intptr_t token_offset() {
+    return OFFSET_OF(UntaggedFinalizerEntry, token_);
+  }
+
+  FinalizerBasePtr finalizer() const { return untag()->finalizer(); }
+  void set_finalizer(const FinalizerBase& value) const;
+  static intptr_t finalizer_offset() {
+    return OFFSET_OF(UntaggedFinalizerEntry, finalizer_);
+  }
+
+  FinalizerEntryPtr next() const { return untag()->next(); }
+  void set_next(const FinalizerEntry& value) const {
+    untag()->set_next(value.ptr());
+  }
+  static intptr_t next_offset() {
+    return OFFSET_OF(UntaggedFinalizerEntry, next_);
+  }
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(UntaggedFinalizerEntry));
+  }
+
+  static FinalizerEntryPtr New(Heap::Space space = Heap::kNew);
+
+ private:
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(FinalizerEntry, Instance);
+  friend class Class;
+};
+
+class FinalizerBase : public Instance {
+ public:
+  static intptr_t isolate_offset() {
+    return OFFSET_OF(UntaggedFinalizerBase, isolate_);
+  }
+  Isolate* isolate() const { return untag()->isolate_; }
+  void set_isolate(Isolate* value) const { untag()->isolate_ = value; }
+
+  static intptr_t detachments_offset() {
+    return OFFSET_OF(UntaggedFinalizerBase, detachments_);
+  }
+
+  LinkedHashSetPtr all_entries() const { return untag()->all_entries(); }
+  static intptr_t all_entries_offset() {
+    return OFFSET_OF(UntaggedFinalizerBase, all_entries_);
+  }
+
+  FinalizerEntryPtr entries_collected() const {
+    return untag()->entries_collected();
+  }
+  void set_entries_collected(const FinalizerEntry& value) const {
+    untag()->set_entries_collected(value.ptr());
+  }
+  static intptr_t entries_collected_offset() {
+    return OFFSET_OF(UntaggedFinalizer, entries_collected_);
   }
 
  private:
-  FINAL_HEAP_OBJECT_IMPLEMENTATION(WeakReference, Instance);
+  HEAP_OBJECT_IMPLEMENTATION(FinalizerBase, Instance);
+  friend class Class;
+};
+
+class Finalizer : public FinalizerBase {
+ public:
+  static intptr_t type_arguments_offset() {
+    return OFFSET_OF(UntaggedFinalizer, type_arguments_);
+  }
+
+  ObjectPtr callback() const { return untag()->callback(); }
+  static intptr_t callback_offset() {
+    return OFFSET_OF(UntaggedFinalizer, callback_);
+  }
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(UntaggedFinalizer));
+  }
+
+  static FinalizerPtr New(Heap::Space space = Heap::kNew);
+
+ private:
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(Finalizer, FinalizerBase);
   friend class Class;
 };
 
diff --git a/runtime/vm/object_graph_copy.cc b/runtime/vm/object_graph_copy.cc
index 0998320..ede344d 100644
--- a/runtime/vm/object_graph_copy.cc
+++ b/runtime/vm/object_graph_copy.cc
@@ -35,6 +35,9 @@
   V(ExceptionHandlers)                                                         \
   V(FfiTrampolineData)                                                         \
   V(Field)                                                                     \
+  V(Finalizer)                                                                 \
+  V(FinalizerBase)                                                             \
+  V(FinalizerEntry)                                                            \
   V(Function)                                                                  \
   V(FunctionType)                                                              \
   V(FutureOr)                                                                  \
@@ -600,6 +603,7 @@
       // those are the only non-abstract classes (so we avoid checking more cids
       // here that cannot happen in reality)
       HANDLE_ILLEGAL_CASE(DynamicLibrary)
+      HANDLE_ILLEGAL_CASE(Finalizer)
       HANDLE_ILLEGAL_CASE(MirrorReference)
       HANDLE_ILLEGAL_CASE(Pointer)
       HANDLE_ILLEGAL_CASE(ReceivePort)
@@ -1815,7 +1819,7 @@
         // We force the GC to compact, which is more likely to discover
         // untracked pointers (and other issues, like incorrect class table).
         thread_->heap()->CollectAllGarbage(GCReason::kDebugging,
-                                           /*compact=*/ true);
+                                           /*compact=*/true);
       }
 
       // Fast copy failed due to
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 210f508..59245d6 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -1700,6 +1700,29 @@
   jsobj.AddProperty("target", target_handle);
 }
 
+void FinalizerBase::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  UNREACHABLE();
+}
+
+void Finalizer::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  JSONObject jsobj(stream);
+  PrintSharedInstanceJSON(&jsobj, ref);
+  jsobj.AddProperty("kind", "Finalizer");
+  jsobj.AddServiceId(*this);
+  if (ref) {
+    return;
+  }
+
+  const Object& finalizer_callback = Object::Handle(callback());
+  jsobj.AddProperty("callback", finalizer_callback);
+
+  // Not exposing entries.
+}
+
+void FinalizerEntry::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  UNREACHABLE();
+}
+
 void MirrorReference::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   PrintSharedInstanceJSON(&jsobj, ref);
diff --git a/runtime/vm/object_store.cc b/runtime/vm/object_store.cc
index 23f9b4d..bdbc4a1 100644
--- a/runtime/vm/object_store.cc
+++ b/runtime/vm/object_store.cc
@@ -78,6 +78,8 @@
   resume_capabilities_ = GrowableObjectArray::New();
   exit_listeners_ = GrowableObjectArray::New();
   error_listeners_ = GrowableObjectArray::New();
+  dart_args_1_ = Array::New(1);
+  dart_args_2_ = Array::New(2);
 
   // Allocate pre-allocated unhandled exception object initialized with the
   // pre-allocated OutOfMemoryError.
@@ -467,7 +469,24 @@
   auto* const thread = Thread::Current();
   SafepointWriteRwLocker locker(thread,
                                 thread->isolate_group()->program_lock());
-  // TODO(http://dartbug.com/47777): Implement finalizers.
+  if (handle_finalizer_message_function_.load() == Function::null()) {
+    auto* const zone = thread->zone();
+    auto& cls = Class::Handle(zone);
+    auto& function = Function::Handle(zone);
+    auto& error = Error::Handle(zone);
+
+    const auto& ffi_lib = Library::Handle(zone, Library::FfiLibrary());
+    ASSERT(!ffi_lib.IsNull());
+
+    cls = finalizer_class();
+    ASSERT(!cls.IsNull());
+    error = cls.EnsureIsFinalized(thread);
+    ASSERT(error.IsNull());
+    function =
+        cls.LookupFunctionAllowPrivate(Symbols::_handleFinalizerMessage());
+    ASSERT(!function.IsNull());
+    handle_finalizer_message_function_.store(function.ptr());
+  }
 }
 
 void ObjectStore::LazyInitIsolateMembers() {
@@ -512,13 +531,14 @@
     auto* const zone = thread->zone();
     auto& cls = Class::Handle(zone);
     auto& field = Field::Handle(zone);
+    auto& error = Error::Handle(zone);
 
     const auto& internal_lib =
         Library::Handle(zone, Library::InternalLibrary());
     cls = internal_lib.LookupClass(Symbols::Symbol());
     ASSERT(!cls.IsNull());
-    const auto& error = cls.EnsureIsFinalized(thread);
-    ASSERT(error == Error::null());
+    error = cls.EnsureIsFinalized(thread);
+    ASSERT(error.IsNull());
     symbol_class_.store(cls.ptr());
 
     field = cls.LookupInstanceFieldAllowPrivate(Symbols::_name());
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index f86b8c5..26bce63 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -55,6 +55,7 @@
   LAZY_CORE(Function, _object_to_string_function)                              \
   LAZY_INTERNAL(Class, symbol_class)                                           \
   LAZY_INTERNAL(Field, symbol_name_field)                                      \
+  LAZY_FFI(Function, handle_finalizer_message_function)                        \
   LAZY_ASYNC(Type, non_nullable_future_rare_type)                              \
   LAZY_ASYNC(Type, non_nullable_future_never_type)                             \
   LAZY_ASYNC(Type, nullable_future_null_type)                                  \
@@ -126,6 +127,9 @@
   RW(Class, expando_class)                                                     \
   RW(Class, weak_property_class)                                               \
   RW(Class, weak_reference_class)                                              \
+  RW(Class, finalizer_class)                                                   \
+  RW(Class, finalizer_entry_class)                                             \
+  RW(Class, finalizer_native_class)                                            \
   ARW_AR(Array, symbol_table)                                                  \
   RW(Array, canonical_types)                                                   \
   RW(Array, canonical_function_types)                                          \
@@ -315,8 +319,8 @@
   RW(UnhandledException, preallocated_unhandled_exception)                     \
   RW(StackTrace, preallocated_stack_trace)                                     \
   RW(UnwindError, preallocated_unwind_error)                                   \
-  RW(Array, dart_args_1)                                                       \
-  RW(Array, dart_args_2)                                                       \
+  R_(Array, dart_args_1)                                                       \
+  R_(Array, dart_args_2)                                                       \
   R_(GrowableObjectArray, resume_capabilities)                                 \
   R_(GrowableObjectArray, exit_listeners)                                      \
   R_(GrowableObjectArray, error_listeners)
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 237ffb0..8a647cb 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 #include <limits>
+#include <memory>
 
 #include "include/dart_api.h"
 
@@ -16,12 +17,15 @@
 #include "vm/code_descriptors.h"
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/compiler/compiler_state.h"
+#include "vm/compiler/runtime_api.h"
 #include "vm/dart_api_impl.h"
 #include "vm/dart_entry.h"
 #include "vm/debugger.h"
 #include "vm/debugger_api_impl_test.h"
+#include "vm/flags.h"
 #include "vm/isolate.h"
 #include "vm/malloc_hooks.h"
+#include "vm/message_handler.h"
 #include "vm/object.h"
 #include "vm/object_store.h"
 #include "vm/resolver.h"
@@ -4005,6 +4009,1037 @@
   WeakReference_Preserve_ReachableThroughWeakProperty(thread, Heap::kOld);
 }
 
+static int NumEntries(const FinalizerEntry& entry, intptr_t acc = 0) {
+  if (entry.IsNull()) {
+    return acc;
+  }
+  return NumEntries(FinalizerEntry::Handle(entry.next()), acc + 1);
+}
+
+static void Finalizer_PreserveOne(Thread* thread,
+                                  Heap::Space space,
+                                  bool with_detach) {
+#ifdef DEBUG
+  SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
+#endif
+
+  MessageHandler* handler = thread->isolate()->message_handler();
+  {
+    MessageHandler::AcquiredQueues aq(handler);
+    EXPECT_EQ(0, aq.queue()->Length());
+  }
+
+  const auto& finalizer = Finalizer::Handle(Finalizer::New(space));
+  finalizer.set_isolate(thread->isolate());
+  const auto& entry = FinalizerEntry::Handle(FinalizerEntry::New(space));
+  entry.set_finalizer(finalizer);
+  const auto& value = String::Handle(OneByteString::New("value", space));
+  entry.set_value(value);
+  auto& detach = Object::Handle();
+  if (with_detach) {
+    detach = OneByteString::New("detach", space);
+  } else {
+    detach = Object::null();
+  }
+  entry.set_detach(detach);
+  const auto& token = String::Handle(OneByteString::New("token", space));
+  entry.set_token(token);
+
+  if (space == Heap::kNew) {
+    GCTestHelper::CollectNewSpace();
+  } else {
+    GCTestHelper::CollectAllGarbage();
+  }
+
+  // Nothing in the entry should have been collected.
+  EXPECT_NE(Object::null(), entry.value());
+  EXPECT((entry.detach() == Object::null()) ^ with_detach);
+  EXPECT_NE(Object::null(), entry.token());
+
+  // The entry should not have moved to the collected list.
+  EXPECT_EQ(0,
+            NumEntries(FinalizerEntry::Handle(finalizer.entries_collected())));
+
+  // We should have no messages.
+  {
+    // Acquire ownership of message handler queues.
+    MessageHandler::AcquiredQueues aq(handler);
+    EXPECT_EQ(0, aq.queue()->Length());
+  }
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_PreserveNoDetachOne_NewSpace) {
+  Finalizer_PreserveOne(thread, Heap::kNew, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_PreserveNoDetachOne_OldSpace) {
+  Finalizer_PreserveOne(thread, Heap::kOld, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_PreserveWithDetachOne_NewSpace) {
+  Finalizer_PreserveOne(thread, Heap::kNew, true);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_PreserveWithDetachOne_OldSpace) {
+  Finalizer_PreserveOne(thread, Heap::kOld, true);
+}
+
+static void Finalizer_ClearDetachOne(Thread* thread, Heap::Space space) {
+#ifdef DEBUG
+  SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
+#endif
+
+  MessageHandler* handler = thread->isolate()->message_handler();
+  {
+    MessageHandler::AcquiredQueues aq(handler);
+    EXPECT_EQ(0, aq.queue()->Length());
+  }
+
+  const auto& finalizer = Finalizer::Handle(Finalizer::New(space));
+  finalizer.set_isolate(thread->isolate());
+  const auto& entry = FinalizerEntry::Handle(FinalizerEntry::New(space));
+  entry.set_finalizer(finalizer);
+  const auto& value = String::Handle(OneByteString::New("value", space));
+  entry.set_value(value);
+  const auto& token = String::Handle(OneByteString::New("token", space));
+  entry.set_token(token);
+
+  {
+    HANDLESCOPE(thread);
+    const auto& detach = String::Handle(OneByteString::New("detach", space));
+    entry.set_detach(detach);
+  }
+
+  if (space == Heap::kNew) {
+    GCTestHelper::CollectNewSpace();
+  } else {
+    GCTestHelper::CollectAllGarbage();
+  }
+
+  // Detach should have been collected.
+  EXPECT_NE(Object::null(), entry.value());
+  EXPECT_EQ(Object::null(), entry.detach());
+  EXPECT_NE(Object::null(), entry.token());
+
+  // The entry should not have moved to the collected list.
+  EXPECT_EQ(0,
+            NumEntries(FinalizerEntry::Handle(finalizer.entries_collected())));
+
+  // We should have no messages.
+  {
+    // Acquire ownership of message handler queues.
+    MessageHandler::AcquiredQueues aq(handler);
+    EXPECT_EQ(0, aq.queue()->Length());
+  }
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearDetachOne_NewSpace) {
+  Finalizer_ClearDetachOne(thread, Heap::kNew);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearDetachOne_OldSpace) {
+  Finalizer_ClearDetachOne(thread, Heap::kOld);
+}
+
+static void Finalizer_ClearValueOne(Thread* thread,
+                                    Heap::Space space,
+                                    bool null_token) {
+#ifdef DEBUG
+  SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
+#endif
+
+  MessageHandler* handler = thread->isolate()->message_handler();
+  {
+    MessageHandler::AcquiredQueues aq(handler);
+    EXPECT_EQ(0, aq.queue()->Length());
+  }
+
+  const auto& finalizer = Finalizer::Handle(Finalizer::New(space));
+  finalizer.set_isolate(thread->isolate());
+  const auto& entry = FinalizerEntry::Handle(FinalizerEntry::New(space));
+  entry.set_finalizer(finalizer);
+  const auto& detach = String::Handle(OneByteString::New("detach", space));
+  auto& token = Object::Handle();
+  if (null_token) {
+    // Null is a valid token in Dart finalizers.
+    token = Object::null();
+  } else {
+    token = OneByteString::New("token", space);
+  }
+  entry.set_token(token);
+  entry.set_detach(detach);
+
+  {
+    HANDLESCOPE(thread);
+    const auto& value = String::Handle(OneByteString::New("value", space));
+    entry.set_value(value);
+  }
+
+  if (space == Heap::kNew) {
+    GCTestHelper::CollectNewSpace();
+  } else {
+    GCTestHelper::CollectAllGarbage();
+  }
+
+  // Value should have been collected.
+  EXPECT_EQ(Object::null(), entry.value());
+  EXPECT_NE(Object::null(), entry.detach());
+
+  // The entry should have moved to the collected list.
+  EXPECT_EQ(1,
+            NumEntries(FinalizerEntry::Handle(finalizer.entries_collected())));
+
+  // We should have 1 message.
+  {
+    // Acquire ownership of message handler queues.
+    MessageHandler::AcquiredQueues aq(handler);
+    EXPECT_EQ(1, aq.queue()->Length());
+  }
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearValueOne_NewSpace) {
+  Finalizer_ClearValueOne(thread, Heap::kNew, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearValueOne_OldSpace) {
+  Finalizer_ClearValueOne(thread, Heap::kOld, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearValueNullTokenOne_NewSpace) {
+  Finalizer_ClearValueOne(thread, Heap::kNew, true);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearValueNullTokenOne_OldSpace) {
+  Finalizer_ClearValueOne(thread, Heap::kOld, true);
+}
+
+static void Finalizer_DetachOne(Thread* thread,
+                                Heap::Space space,
+                                bool clear_value) {
+#ifdef DEBUG
+  SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
+#endif
+
+  MessageHandler* handler = thread->isolate()->message_handler();
+  {
+    MessageHandler::AcquiredQueues aq(handler);
+    EXPECT_EQ(0, aq.queue()->Length());
+  }
+
+  const auto& finalizer = Finalizer::Handle(Finalizer::New(space));
+  finalizer.set_isolate(thread->isolate());
+  const auto& entry = FinalizerEntry::Handle(FinalizerEntry::New(space));
+  entry.set_finalizer(finalizer);
+  const auto& detach = String::Handle(OneByteString::New("detach", space));
+  entry.set_detach(detach);
+
+  // Simulate calling detach, setting the token of the entry to the entry.
+  entry.set_token(entry);
+
+  auto& value = String::Handle();
+  {
+    HANDLESCOPE(thread);
+
+    const auto& object = String::Handle(OneByteString::New("value", space));
+    entry.set_value(object);
+    if (!clear_value) {
+      value = object.ptr();
+    }
+  }
+
+  if (space == Heap::kNew) {
+    GCTestHelper::CollectNewSpace();
+  } else {
+    GCTestHelper::CollectAllGarbage();
+  }
+
+  EXPECT((entry.value() == Object::null()) ^ !clear_value);
+  EXPECT_NE(Object::null(), entry.detach());
+  EXPECT_EQ(entry.ptr(), entry.token());
+
+  // The entry should have been removed entirely
+  EXPECT_EQ(0,
+            NumEntries(FinalizerEntry::Handle(finalizer.entries_collected())));
+
+  // We should have no message.
+  {
+    // Acquire ownership of message handler queues.
+    MessageHandler::AcquiredQueues aq(handler);
+    EXPECT_EQ(0, aq.queue()->Length());
+  }
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_DetachOne_NewSpace) {
+  Finalizer_DetachOne(thread, Heap::kNew, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_DetachOne_OldSpace) {
+  Finalizer_DetachOne(thread, Heap::kOld, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_DetachAndClearValueOne_NewSpace) {
+  Finalizer_DetachOne(thread, Heap::kNew, true);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_DetachAndClearValueOne_OldSpace) {
+  Finalizer_DetachOne(thread, Heap::kOld, true);
+}
+
+static void Finalizer_GcFinalizer(Thread* thread, Heap::Space space) {
+#ifdef DEBUG
+  SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
+#endif
+
+  MessageHandler* handler = thread->isolate()->message_handler();
+  {
+    MessageHandler::AcquiredQueues aq(handler);
+    EXPECT_EQ(0, aq.queue()->Length());
+  }
+
+  const auto& detach = String::Handle(OneByteString::New("detach", space));
+  const auto& token = String::Handle(OneByteString::New("token", space));
+
+  {
+    HANDLESCOPE(thread);
+    const auto& finalizer = Finalizer::Handle(Finalizer::New(space));
+    finalizer.set_isolate(thread->isolate());
+    const auto& entry = FinalizerEntry::Handle(FinalizerEntry::New(space));
+    entry.set_finalizer(finalizer);
+    entry.set_detach(detach);
+    entry.set_token(token);
+    const auto& value = String::Handle(OneByteString::New("value", space));
+    entry.set_value(value);
+  }
+
+  if (space == Heap::kNew) {
+    GCTestHelper::CollectNewSpace();
+  } else {
+    GCTestHelper::CollectAllGarbage();
+  }
+
+  // We should have no message, the Finalizer itself has been GCed.
+  {
+    // Acquire ownership of message handler queues.
+    MessageHandler::AcquiredQueues aq(handler);
+    EXPECT_EQ(0, aq.queue()->Length());
+  }
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_GcFinalizer_NewSpace) {
+  Finalizer_GcFinalizer(thread, Heap::kNew);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_GcFinalizer_OldSpace) {
+  Finalizer_GcFinalizer(thread, Heap::kOld);
+}
+
+static void Finalizer_TwoEntriesCrossGen(
+    Thread* thread,
+    Heap::Space* spaces,
+    bool collect_old_space,
+    bool collect_new_space,
+    bool evacuate_new_space_and_collect_old_space,
+    bool clear_value_1,
+    bool clear_value_2,
+    bool clear_detach_1,
+    bool clear_detach_2) {
+#ifdef DEBUG
+  SetFlagScope<bool> sfs(&FLAG_trace_finalizers, true);
+#endif
+
+  MessageHandler* handler = thread->isolate()->message_handler();
+  // We're reusing the isolate in a loop, so there are messages from previous
+  // runs of this test.
+  intptr_t queue_length_start = 0;
+  {
+    MessageHandler::AcquiredQueues aq(handler);
+    queue_length_start = aq.queue()->Length();
+  }
+
+  const auto& finalizer = Finalizer::Handle(Finalizer::New(spaces[0]));
+  finalizer.set_isolate(thread->isolate());
+  const auto& entry1 = FinalizerEntry::Handle(FinalizerEntry::New(spaces[1]));
+  entry1.set_finalizer(finalizer);
+  const auto& entry2 = FinalizerEntry::Handle(FinalizerEntry::New(spaces[2]));
+  entry2.set_finalizer(finalizer);
+
+  auto& value1 = String::Handle();
+  auto& detach1 = String::Handle();
+  const auto& token1 = String::Handle(OneByteString::New("token1", spaces[3]));
+  entry1.set_token(token1);
+
+  auto& value2 = String::Handle();
+  auto& detach2 = String::Handle();
+  const auto& token2 = String::Handle(OneByteString::New("token2", spaces[4]));
+  entry2.set_token(token2);
+  entry2.set_detach(detach2);
+
+  {
+    HANDLESCOPE(thread);
+    auto& object = String::Handle();
+
+    object ^= OneByteString::New("value1", spaces[5]);
+    entry1.set_value(object);
+    if (!clear_value_1) {
+      value1 = object.ptr();
+    }
+
+    object ^= OneByteString::New("detach", spaces[6]);
+    entry1.set_detach(object);
+    if (!clear_detach_1) {
+      detach1 = object.ptr();
+    }
+
+    object ^= OneByteString::New("value2", spaces[7]);
+    entry2.set_value(object);
+    if (!clear_value_2) {
+      value2 = object.ptr();
+    }
+
+    object ^= OneByteString::New("detach", spaces[8]);
+    entry2.set_detach(object);
+    if (!clear_detach_2) {
+      detach2 = object.ptr();
+    }
+  }
+
+  if (collect_old_space) {
+    GCTestHelper::CollectOldSpace();
+  }
+  if (collect_new_space) {
+    GCTestHelper::CollectNewSpace();
+  }
+  if (evacuate_new_space_and_collect_old_space) {
+    GCTestHelper::CollectAllGarbage();
+  }
+
+  EXPECT((entry1.value() == Object::null()) ^ !clear_value_1);
+  EXPECT((entry2.value() == Object::null()) ^ !clear_value_2);
+  EXPECT((entry1.detach() == Object::null()) ^ !clear_detach_1);
+  EXPECT((entry2.detach() == Object::null()) ^ !clear_detach_2);
+  EXPECT_NE(Object::null(), entry1.token());
+  EXPECT_NE(Object::null(), entry2.token());
+
+  const intptr_t expect_num_cleared =
+      (clear_value_1 ? 1 : 0) + (clear_value_2 ? 1 : 0);
+  EXPECT_EQ(expect_num_cleared,
+            NumEntries(FinalizerEntry::Handle(finalizer.entries_collected())));
+
+  const intptr_t expect_num_messages = expect_num_cleared == 0 ? 0 : 1;
+  {
+    // Acquire ownership of message handler queues.
+    MessageHandler::AcquiredQueues aq(handler);
+    EXPECT_EQ(expect_num_messages + queue_length_start, aq.queue()->Length());
+  }
+}
+
+const intptr_t kFinalizerTwoEntriesNumObjects = 9;
+
+static void Finalizer_TwoEntries(Thread* thread,
+                                 Heap::Space space,
+                                 bool clear_value_1,
+                                 bool clear_value_2,
+                                 bool clear_detach_1,
+                                 bool clear_detach_2) {
+  const bool collect_old_space = true;
+  const bool collect_new_space = space == Heap::kNew;
+  const bool evacuate_new_space_and_collect_old_space = !collect_new_space;
+
+  Heap::Space spaces[kFinalizerTwoEntriesNumObjects];
+  for (intptr_t i = 0; i < kFinalizerTwoEntriesNumObjects; i++) {
+    spaces[i] = space;
+  }
+  Finalizer_TwoEntriesCrossGen(
+      thread, spaces, collect_old_space, collect_new_space,
+      evacuate_new_space_and_collect_old_space, clear_value_1, clear_value_2,
+      clear_detach_1, clear_detach_2);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearValueTwo_NewSpace) {
+  Finalizer_TwoEntries(thread, Heap::kNew, true, true, false, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearValueTwo_OldSpace) {
+  Finalizer_TwoEntries(thread, Heap::kOld, true, true, false, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearFirstValue_NewSpace) {
+  Finalizer_TwoEntries(thread, Heap::kNew, true, false, false, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearFirstValue_OldSpace) {
+  Finalizer_TwoEntries(thread, Heap::kOld, true, false, false, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearSecondValue_NewSpace) {
+  Finalizer_TwoEntries(thread, Heap::kNew, false, true, false, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearSecondValue_OldSpace) {
+  Finalizer_TwoEntries(thread, Heap::kOld, false, true, false, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_PreserveTwo_NewSpace) {
+  Finalizer_TwoEntries(thread, Heap::kNew, false, false, false, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_PreserveTwo_OldSpace) {
+  Finalizer_TwoEntries(thread, Heap::kOld, false, false, false, false);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearDetachTwo_NewSpace) {
+  Finalizer_TwoEntries(thread, Heap::kNew, false, false, true, true);
+}
+
+ISOLATE_UNIT_TEST_CASE(Finalizer_ClearDetachTwo_OldSpace) {
+  Finalizer_TwoEntries(thread, Heap::kOld, false, false, true, true);
+}
+
+static void Finalizer_TwoEntriesCrossGen(Thread* thread, intptr_t test_i) {
+  ASSERT(test_i < (1 << kFinalizerTwoEntriesNumObjects));
+  Heap::Space spaces[kFinalizerTwoEntriesNumObjects];
+  for (intptr_t i = 0; i < kFinalizerTwoEntriesNumObjects; i++) {
+    spaces[i] = ((test_i >> i) & 0x1) == 0x1 ? Heap::kOld : Heap::kNew;
+  }
+  // Either collect or evacuate new space.
+  for (const bool collect_new_space : {false, true}) {
+    // Always run old space collection first.
+    const bool collect_old_space = true;
+    // Always run old space collection after new space.
+    const bool evacuate_new_space_and_collect_old_space = true;
+    for (intptr_t test_j = 0; test_j < 16; test_j++) {
+      const bool clear_value_1 = (test_j >> 0 & 0x1) == 0x1;
+      const bool clear_value_2 = (test_j >> 1 & 0x1) == 0x1;
+      const bool clear_detach_1 = (test_j >> 2 & 0x1) == 0x1;
+      const bool clear_detach_2 = (test_j >> 3 & 0x1) == 0x1;
+      Finalizer_TwoEntriesCrossGen(
+          thread, spaces, collect_old_space, collect_new_space,
+          evacuate_new_space_and_collect_old_space, clear_value_1,
+          clear_value_2, clear_detach_1, clear_detach_2);
+    }
+  }
+}
+#define FINALIZER_CROSS_GEN_TEST_CASE(n)                                       \
+  ISOLATE_UNIT_TEST_CASE(Finalizer_CrossGen_##n) {                             \
+    Finalizer_TwoEntriesCrossGen(thread, n);                                   \
+  }
+
+#define REPEAT_512(V)                                                          \
+  V(0)                                                                         \
+  V(1)                                                                         \
+  V(2)                                                                         \
+  V(3)                                                                         \
+  V(4)                                                                         \
+  V(5)                                                                         \
+  V(6)                                                                         \
+  V(7)                                                                         \
+  V(8)                                                                         \
+  V(9)                                                                         \
+  V(10)                                                                        \
+  V(11)                                                                        \
+  V(12)                                                                        \
+  V(13)                                                                        \
+  V(14)                                                                        \
+  V(15)                                                                        \
+  V(16)                                                                        \
+  V(17)                                                                        \
+  V(18)                                                                        \
+  V(19)                                                                        \
+  V(20)                                                                        \
+  V(21)                                                                        \
+  V(22)                                                                        \
+  V(23)                                                                        \
+  V(24)                                                                        \
+  V(25)                                                                        \
+  V(26)                                                                        \
+  V(27)                                                                        \
+  V(28)                                                                        \
+  V(29)                                                                        \
+  V(30)                                                                        \
+  V(31)                                                                        \
+  V(32)                                                                        \
+  V(33)                                                                        \
+  V(34)                                                                        \
+  V(35)                                                                        \
+  V(36)                                                                        \
+  V(37)                                                                        \
+  V(38)                                                                        \
+  V(39)                                                                        \
+  V(40)                                                                        \
+  V(41)                                                                        \
+  V(42)                                                                        \
+  V(43)                                                                        \
+  V(44)                                                                        \
+  V(45)                                                                        \
+  V(46)                                                                        \
+  V(47)                                                                        \
+  V(48)                                                                        \
+  V(49)                                                                        \
+  V(50)                                                                        \
+  V(51)                                                                        \
+  V(52)                                                                        \
+  V(53)                                                                        \
+  V(54)                                                                        \
+  V(55)                                                                        \
+  V(56)                                                                        \
+  V(57)                                                                        \
+  V(58)                                                                        \
+  V(59)                                                                        \
+  V(60)                                                                        \
+  V(61)                                                                        \
+  V(62)                                                                        \
+  V(63)                                                                        \
+  V(64)                                                                        \
+  V(65)                                                                        \
+  V(66)                                                                        \
+  V(67)                                                                        \
+  V(68)                                                                        \
+  V(69)                                                                        \
+  V(70)                                                                        \
+  V(71)                                                                        \
+  V(72)                                                                        \
+  V(73)                                                                        \
+  V(74)                                                                        \
+  V(75)                                                                        \
+  V(76)                                                                        \
+  V(77)                                                                        \
+  V(78)                                                                        \
+  V(79)                                                                        \
+  V(80)                                                                        \
+  V(81)                                                                        \
+  V(82)                                                                        \
+  V(83)                                                                        \
+  V(84)                                                                        \
+  V(85)                                                                        \
+  V(86)                                                                        \
+  V(87)                                                                        \
+  V(88)                                                                        \
+  V(89)                                                                        \
+  V(90)                                                                        \
+  V(91)                                                                        \
+  V(92)                                                                        \
+  V(93)                                                                        \
+  V(94)                                                                        \
+  V(95)                                                                        \
+  V(96)                                                                        \
+  V(97)                                                                        \
+  V(98)                                                                        \
+  V(99)                                                                        \
+  V(100)                                                                       \
+  V(101)                                                                       \
+  V(102)                                                                       \
+  V(103)                                                                       \
+  V(104)                                                                       \
+  V(105)                                                                       \
+  V(106)                                                                       \
+  V(107)                                                                       \
+  V(108)                                                                       \
+  V(109)                                                                       \
+  V(110)                                                                       \
+  V(111)                                                                       \
+  V(112)                                                                       \
+  V(113)                                                                       \
+  V(114)                                                                       \
+  V(115)                                                                       \
+  V(116)                                                                       \
+  V(117)                                                                       \
+  V(118)                                                                       \
+  V(119)                                                                       \
+  V(120)                                                                       \
+  V(121)                                                                       \
+  V(122)                                                                       \
+  V(123)                                                                       \
+  V(124)                                                                       \
+  V(125)                                                                       \
+  V(126)                                                                       \
+  V(127)                                                                       \
+  V(128)                                                                       \
+  V(129)                                                                       \
+  V(130)                                                                       \
+  V(131)                                                                       \
+  V(132)                                                                       \
+  V(133)                                                                       \
+  V(134)                                                                       \
+  V(135)                                                                       \
+  V(136)                                                                       \
+  V(137)                                                                       \
+  V(138)                                                                       \
+  V(139)                                                                       \
+  V(140)                                                                       \
+  V(141)                                                                       \
+  V(142)                                                                       \
+  V(143)                                                                       \
+  V(144)                                                                       \
+  V(145)                                                                       \
+  V(146)                                                                       \
+  V(147)                                                                       \
+  V(148)                                                                       \
+  V(149)                                                                       \
+  V(150)                                                                       \
+  V(151)                                                                       \
+  V(152)                                                                       \
+  V(153)                                                                       \
+  V(154)                                                                       \
+  V(155)                                                                       \
+  V(156)                                                                       \
+  V(157)                                                                       \
+  V(158)                                                                       \
+  V(159)                                                                       \
+  V(160)                                                                       \
+  V(161)                                                                       \
+  V(162)                                                                       \
+  V(163)                                                                       \
+  V(164)                                                                       \
+  V(165)                                                                       \
+  V(166)                                                                       \
+  V(167)                                                                       \
+  V(168)                                                                       \
+  V(169)                                                                       \
+  V(170)                                                                       \
+  V(171)                                                                       \
+  V(172)                                                                       \
+  V(173)                                                                       \
+  V(174)                                                                       \
+  V(175)                                                                       \
+  V(176)                                                                       \
+  V(177)                                                                       \
+  V(178)                                                                       \
+  V(179)                                                                       \
+  V(180)                                                                       \
+  V(181)                                                                       \
+  V(182)                                                                       \
+  V(183)                                                                       \
+  V(184)                                                                       \
+  V(185)                                                                       \
+  V(186)                                                                       \
+  V(187)                                                                       \
+  V(188)                                                                       \
+  V(189)                                                                       \
+  V(190)                                                                       \
+  V(191)                                                                       \
+  V(192)                                                                       \
+  V(193)                                                                       \
+  V(194)                                                                       \
+  V(195)                                                                       \
+  V(196)                                                                       \
+  V(197)                                                                       \
+  V(198)                                                                       \
+  V(199)                                                                       \
+  V(200)                                                                       \
+  V(201)                                                                       \
+  V(202)                                                                       \
+  V(203)                                                                       \
+  V(204)                                                                       \
+  V(205)                                                                       \
+  V(206)                                                                       \
+  V(207)                                                                       \
+  V(208)                                                                       \
+  V(209)                                                                       \
+  V(210)                                                                       \
+  V(211)                                                                       \
+  V(212)                                                                       \
+  V(213)                                                                       \
+  V(214)                                                                       \
+  V(215)                                                                       \
+  V(216)                                                                       \
+  V(217)                                                                       \
+  V(218)                                                                       \
+  V(219)                                                                       \
+  V(220)                                                                       \
+  V(221)                                                                       \
+  V(222)                                                                       \
+  V(223)                                                                       \
+  V(224)                                                                       \
+  V(225)                                                                       \
+  V(226)                                                                       \
+  V(227)                                                                       \
+  V(228)                                                                       \
+  V(229)                                                                       \
+  V(230)                                                                       \
+  V(231)                                                                       \
+  V(232)                                                                       \
+  V(233)                                                                       \
+  V(234)                                                                       \
+  V(235)                                                                       \
+  V(236)                                                                       \
+  V(237)                                                                       \
+  V(238)                                                                       \
+  V(239)                                                                       \
+  V(240)                                                                       \
+  V(241)                                                                       \
+  V(242)                                                                       \
+  V(243)                                                                       \
+  V(244)                                                                       \
+  V(245)                                                                       \
+  V(246)                                                                       \
+  V(247)                                                                       \
+  V(248)                                                                       \
+  V(249)                                                                       \
+  V(250)                                                                       \
+  V(251)                                                                       \
+  V(252)                                                                       \
+  V(253)                                                                       \
+  V(254)                                                                       \
+  V(255)                                                                       \
+  V(256)                                                                       \
+  V(257)                                                                       \
+  V(258)                                                                       \
+  V(259)                                                                       \
+  V(260)                                                                       \
+  V(261)                                                                       \
+  V(262)                                                                       \
+  V(263)                                                                       \
+  V(264)                                                                       \
+  V(265)                                                                       \
+  V(266)                                                                       \
+  V(267)                                                                       \
+  V(268)                                                                       \
+  V(269)                                                                       \
+  V(270)                                                                       \
+  V(271)                                                                       \
+  V(272)                                                                       \
+  V(273)                                                                       \
+  V(274)                                                                       \
+  V(275)                                                                       \
+  V(276)                                                                       \
+  V(277)                                                                       \
+  V(278)                                                                       \
+  V(279)                                                                       \
+  V(280)                                                                       \
+  V(281)                                                                       \
+  V(282)                                                                       \
+  V(283)                                                                       \
+  V(284)                                                                       \
+  V(285)                                                                       \
+  V(286)                                                                       \
+  V(287)                                                                       \
+  V(288)                                                                       \
+  V(289)                                                                       \
+  V(290)                                                                       \
+  V(291)                                                                       \
+  V(292)                                                                       \
+  V(293)                                                                       \
+  V(294)                                                                       \
+  V(295)                                                                       \
+  V(296)                                                                       \
+  V(297)                                                                       \
+  V(298)                                                                       \
+  V(299)                                                                       \
+  V(300)                                                                       \
+  V(301)                                                                       \
+  V(302)                                                                       \
+  V(303)                                                                       \
+  V(304)                                                                       \
+  V(305)                                                                       \
+  V(306)                                                                       \
+  V(307)                                                                       \
+  V(308)                                                                       \
+  V(309)                                                                       \
+  V(310)                                                                       \
+  V(311)                                                                       \
+  V(312)                                                                       \
+  V(313)                                                                       \
+  V(314)                                                                       \
+  V(315)                                                                       \
+  V(316)                                                                       \
+  V(317)                                                                       \
+  V(318)                                                                       \
+  V(319)                                                                       \
+  V(320)                                                                       \
+  V(321)                                                                       \
+  V(322)                                                                       \
+  V(323)                                                                       \
+  V(324)                                                                       \
+  V(325)                                                                       \
+  V(326)                                                                       \
+  V(327)                                                                       \
+  V(328)                                                                       \
+  V(329)                                                                       \
+  V(330)                                                                       \
+  V(331)                                                                       \
+  V(332)                                                                       \
+  V(333)                                                                       \
+  V(334)                                                                       \
+  V(335)                                                                       \
+  V(336)                                                                       \
+  V(337)                                                                       \
+  V(338)                                                                       \
+  V(339)                                                                       \
+  V(340)                                                                       \
+  V(341)                                                                       \
+  V(342)                                                                       \
+  V(343)                                                                       \
+  V(344)                                                                       \
+  V(345)                                                                       \
+  V(346)                                                                       \
+  V(347)                                                                       \
+  V(348)                                                                       \
+  V(349)                                                                       \
+  V(350)                                                                       \
+  V(351)                                                                       \
+  V(352)                                                                       \
+  V(353)                                                                       \
+  V(354)                                                                       \
+  V(355)                                                                       \
+  V(356)                                                                       \
+  V(357)                                                                       \
+  V(358)                                                                       \
+  V(359)                                                                       \
+  V(360)                                                                       \
+  V(361)                                                                       \
+  V(362)                                                                       \
+  V(363)                                                                       \
+  V(364)                                                                       \
+  V(365)                                                                       \
+  V(366)                                                                       \
+  V(367)                                                                       \
+  V(368)                                                                       \
+  V(369)                                                                       \
+  V(370)                                                                       \
+  V(371)                                                                       \
+  V(372)                                                                       \
+  V(373)                                                                       \
+  V(374)                                                                       \
+  V(375)                                                                       \
+  V(376)                                                                       \
+  V(377)                                                                       \
+  V(378)                                                                       \
+  V(379)                                                                       \
+  V(380)                                                                       \
+  V(381)                                                                       \
+  V(382)                                                                       \
+  V(383)                                                                       \
+  V(384)                                                                       \
+  V(385)                                                                       \
+  V(386)                                                                       \
+  V(387)                                                                       \
+  V(388)                                                                       \
+  V(389)                                                                       \
+  V(390)                                                                       \
+  V(391)                                                                       \
+  V(392)                                                                       \
+  V(393)                                                                       \
+  V(394)                                                                       \
+  V(395)                                                                       \
+  V(396)                                                                       \
+  V(397)                                                                       \
+  V(398)                                                                       \
+  V(399)                                                                       \
+  V(400)                                                                       \
+  V(401)                                                                       \
+  V(402)                                                                       \
+  V(403)                                                                       \
+  V(404)                                                                       \
+  V(405)                                                                       \
+  V(406)                                                                       \
+  V(407)                                                                       \
+  V(408)                                                                       \
+  V(409)                                                                       \
+  V(410)                                                                       \
+  V(411)                                                                       \
+  V(412)                                                                       \
+  V(413)                                                                       \
+  V(414)                                                                       \
+  V(415)                                                                       \
+  V(416)                                                                       \
+  V(417)                                                                       \
+  V(418)                                                                       \
+  V(419)                                                                       \
+  V(420)                                                                       \
+  V(421)                                                                       \
+  V(422)                                                                       \
+  V(423)                                                                       \
+  V(424)                                                                       \
+  V(425)                                                                       \
+  V(426)                                                                       \
+  V(427)                                                                       \
+  V(428)                                                                       \
+  V(429)                                                                       \
+  V(430)                                                                       \
+  V(431)                                                                       \
+  V(432)                                                                       \
+  V(433)                                                                       \
+  V(434)                                                                       \
+  V(435)                                                                       \
+  V(436)                                                                       \
+  V(437)                                                                       \
+  V(438)                                                                       \
+  V(439)                                                                       \
+  V(440)                                                                       \
+  V(441)                                                                       \
+  V(442)                                                                       \
+  V(443)                                                                       \
+  V(444)                                                                       \
+  V(445)                                                                       \
+  V(446)                                                                       \
+  V(447)                                                                       \
+  V(448)                                                                       \
+  V(449)                                                                       \
+  V(450)                                                                       \
+  V(451)                                                                       \
+  V(452)                                                                       \
+  V(453)                                                                       \
+  V(454)                                                                       \
+  V(455)                                                                       \
+  V(456)                                                                       \
+  V(457)                                                                       \
+  V(458)                                                                       \
+  V(459)                                                                       \
+  V(460)                                                                       \
+  V(461)                                                                       \
+  V(462)                                                                       \
+  V(463)                                                                       \
+  V(464)                                                                       \
+  V(465)                                                                       \
+  V(466)                                                                       \
+  V(467)                                                                       \
+  V(468)                                                                       \
+  V(469)                                                                       \
+  V(470)                                                                       \
+  V(471)                                                                       \
+  V(472)                                                                       \
+  V(473)                                                                       \
+  V(474)                                                                       \
+  V(475)                                                                       \
+  V(476)                                                                       \
+  V(477)                                                                       \
+  V(478)                                                                       \
+  V(479)                                                                       \
+  V(480)                                                                       \
+  V(481)                                                                       \
+  V(482)                                                                       \
+  V(483)                                                                       \
+  V(484)                                                                       \
+  V(485)                                                                       \
+  V(486)                                                                       \
+  V(487)                                                                       \
+  V(488)                                                                       \
+  V(489)                                                                       \
+  V(490)                                                                       \
+  V(491)                                                                       \
+  V(492)                                                                       \
+  V(493)                                                                       \
+  V(494)                                                                       \
+  V(495)                                                                       \
+  V(496)                                                                       \
+  V(497)                                                                       \
+  V(498)                                                                       \
+  V(499)                                                                       \
+  V(500)                                                                       \
+  V(501)                                                                       \
+  V(502)                                                                       \
+  V(503)                                                                       \
+  V(504)                                                                       \
+  V(505)                                                                       \
+  V(506)                                                                       \
+  V(507)                                                                       \
+  V(508)                                                                       \
+  V(509)                                                                       \
+  V(510)                                                                       \
+  V(511)
+
+REPEAT_512(FINALIZER_CROSS_GEN_TEST_CASE)
+
 ISOLATE_UNIT_TEST_CASE(MirrorReference) {
   const MirrorReference& reference =
       MirrorReference::Handle(MirrorReference::New(Object::Handle()));
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index eb83d68..82e1bf8 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -552,6 +552,8 @@
 COMPRESSED_VISITOR(RegExp)
 COMPRESSED_VISITOR(WeakProperty)
 COMPRESSED_VISITOR(WeakReference)
+COMPRESSED_VISITOR(Finalizer)
+COMPRESSED_VISITOR(FinalizerEntry)
 COMPRESSED_VISITOR(MirrorReference)
 COMPRESSED_VISITOR(UserTag)
 REGULAR_VISITOR(SubtypeTestCache)
@@ -594,6 +596,7 @@
 UNREACHABLE_VISITOR(CallSiteData)
 UNREACHABLE_VISITOR(TypedDataBase)
 UNREACHABLE_VISITOR(Error)
+UNREACHABLE_VISITOR(FinalizerBase)
 UNREACHABLE_VISITOR(Number)
 UNREACHABLE_VISITOR(Integer)
 UNREACHABLE_VISITOR(String)
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 1ba2094..c21d64a 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -623,6 +623,20 @@
     }
   }
 
+  template <typename type,
+            typename compressed_type,
+            std::memory_order order = std::memory_order_relaxed>
+  type ExchangeCompressedPointer(compressed_type const* addr, type value) {
+    compressed_type previous_value =
+        reinterpret_cast<std::atomic<compressed_type>*>(
+            const_cast<compressed_type*>(addr))
+            ->exchange(static_cast<compressed_type>(value), order);
+    if (value.IsHeapObject()) {
+      CheckHeapPointerStore(value, Thread::Current());
+    }
+    return static_cast<type>(previous_value.Decompress(heap_base()));
+  }
+
   template <std::memory_order order = std::memory_order_relaxed>
   SmiPtr LoadSmi(SmiPtr const* addr) const {
     return reinterpret_cast<std::atomic<SmiPtr>*>(const_cast<SmiPtr*>(addr))
@@ -3321,6 +3335,92 @@
   friend class SlowObjectCopy;  // For OFFSET_OF
 };
 
+class UntaggedFinalizerBase : public UntaggedInstance {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(FinalizerBase);
+
+  // The isolate this finalizer belongs to. Updated on sent and exit and set
+  // to null on isolate shutdown. See Isolate::finalizers_.
+  Isolate* isolate_;
+
+  COMPRESSED_POINTER_FIELD(ObjectPtr, detachments)
+  VISIT_FROM(detachments)
+  COMPRESSED_POINTER_FIELD(LinkedHashSetPtr, all_entries)
+  COMPRESSED_POINTER_FIELD(FinalizerEntryPtr, entries_collected)
+
+// With compressed pointers, the first field in a subclass is at offset 28.
+// If the fields would be public, the first field in a subclass is at offset 32.
+// On Windows, it is always at offset 32, no matter public/private.
+// This makes it 32 for all OSes.
+// We can't use ALIGN8 on the first fields of the subclasses because they use
+// the COMPRESSED_POINTER_FIELD macro to define it.
+#ifdef DART_COMPRESSED_POINTERS
+  uint32_t align_next_field;
+#endif
+
+  template <typename GCVisitorType>
+  friend void MournFinalized(GCVisitorType* visitor);
+  friend class GCMarker;
+  template <bool>
+  friend class MarkingVisitorBase;
+  friend class Scavenger;
+  template <bool>
+  friend class ScavengerVisitorBase;
+};
+
+class UntaggedFinalizer : public UntaggedFinalizerBase {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(Finalizer);
+
+  COMPRESSED_POINTER_FIELD(ClosurePtr, callback)
+  COMPRESSED_POINTER_FIELD(TypeArgumentsPtr, type_arguments)
+  VISIT_TO(type_arguments)
+
+  template <std::memory_order order = std::memory_order_relaxed>
+  FinalizerEntryPtr exchange_entries_collected(FinalizerEntryPtr value) {
+    return ExchangeCompressedPointer<FinalizerEntryPtr,
+                                     CompressedFinalizerEntryPtr, order>(
+        &entries_collected_, value);
+  }
+
+  template <typename GCVisitorType>
+  friend void MournFinalized(GCVisitorType* visitor);
+  friend class GCMarker;
+  template <bool>
+  friend class MarkingVisitorBase;
+  friend class Scavenger;
+  template <bool>
+  friend class ScavengerVisitorBase;
+};
+
+class UntaggedFinalizerEntry : public UntaggedInstance {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(FinalizerEntry);
+
+  COMPRESSED_POINTER_FIELD(ObjectPtr, value)  // Weak reference.
+  VISIT_FROM(value)
+  COMPRESSED_POINTER_FIELD(ObjectPtr, detach)  // Weak reference.
+  COMPRESSED_POINTER_FIELD(ObjectPtr, token)
+  COMPRESSED_POINTER_FIELD(FinalizerBasePtr, finalizer)  // Weak reference.
+  // Used for the linked list in Finalizer::entries_collected_. That cannot be
+  // an ordinary list because we need to add elements during a GC so we cannot
+  // modify the heap.
+  COMPRESSED_POINTER_FIELD(FinalizerEntryPtr, next)
+  VISIT_TO(next)
+
+  // Linked list is chaining all pending. Not visited by pointer visitors.
+  // Only populated during the GC, otherwise null.
+  COMPRESSED_POINTER_FIELD(FinalizerEntryPtr, next_seen_by_gc)
+
+  template <typename Type, typename PtrType>
+  friend class GCLinkedList;
+  template <typename GCVisitorType>
+  friend void MournFinalized(GCVisitorType* visitor);
+  friend class GCMarker;
+  template <bool>
+  friend class MarkingVisitorBase;
+  friend class Scavenger;
+  template <bool>
+  friend class ScavengerVisitorBase;
+};
+
 // MirrorReferences are used by mirrors to hold reflectees that are VM
 // internal objects, such as libraries, classes, functions or types.
 class UntaggedMirrorReference : public UntaggedInstance {
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 7784041..7953a1f 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -137,6 +137,8 @@
   V(FfiVoid, "Void")                                                           \
   V(FfiHandle, "Handle")                                                       \
   V(Field, "Field")                                                            \
+  V(FinalizerBase, "FinalizerBase")                                            \
+  V(FinalizerEntry, "FinalizerEntry")                                          \
   V(FinallyRetVal, ":finally_ret_val")                                         \
   V(FirstArg, "x")                                                             \
   V(Float32List, "Float32List")                                                \
@@ -308,6 +310,7 @@
   V(_ExternalUint64Array, "_ExternalUint64Array")                              \
   V(_ExternalUint8Array, "_ExternalUint8Array")                                \
   V(_ExternalUint8ClampedArray, "_ExternalUint8ClampedArray")                  \
+  V(_FinalizerImpl, "_FinalizerImpl")                                          \
   V(_Float32ArrayFactory, "Float32List.")                                      \
   V(_Float32ArrayView, "_Float32ArrayView")                                    \
   V(_Float32List, "_Float32List")                                              \
@@ -407,6 +410,7 @@
   V(_ensureScheduleImmediate, "_ensureScheduleImmediate")                      \
   V(_future, "_future")                                                        \
   V(_handleMessage, "_handleMessage")                                          \
+  V(_handleFinalizerMessage, "_handleFinalizerMessage")                        \
   V(_instanceOf, "_instanceOf")                                                \
   V(_listGetAt, "_listGetAt")                                                  \
   V(_listLength, "_listLength")                                                \
diff --git a/runtime/vm/tagged_pointer.h b/runtime/vm/tagged_pointer.h
index 0f53fe7..5a0b99f 100644
--- a/runtime/vm/tagged_pointer.h
+++ b/runtime/vm/tagged_pointer.h
@@ -413,6 +413,9 @@
 DEFINE_TAGGED_POINTER(RegExp, Instance)
 DEFINE_TAGGED_POINTER(WeakProperty, Instance)
 DEFINE_TAGGED_POINTER(WeakReference, Instance)
+DEFINE_TAGGED_POINTER(FinalizerBase, Instance)
+DEFINE_TAGGED_POINTER(Finalizer, Instance)
+DEFINE_TAGGED_POINTER(FinalizerEntry, Instance)
 DEFINE_TAGGED_POINTER(MirrorReference, Instance)
 DEFINE_TAGGED_POINTER(UserTag, Instance)
 DEFINE_TAGGED_POINTER(FutureOr, Instance)
diff --git a/runtime/vm/type_testing_stubs.cc b/runtime/vm/type_testing_stubs.cc
index c4dc3d3..7ff72b1 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -570,9 +570,10 @@
 }
 
 // Builds a cid range check for the concrete subclasses and implementors of
-// type. Assumes cid to check is already in TTSInternalRegs::kScratchReg. Falls
-// through or jumps to check_succeeded if the range contains the cid, else
-// jumps to check_failed.
+// type. Falls through or jumps to check_succeeded if the range contains the
+// cid, else jumps to check_failed.
+//
+// Clobbers class_id_reg.
 void TypeTestingStubGenerator::BuildOptimizedSubtypeRangeCheck(
     compiler::Assembler* assembler,
     const CidRangeVector& ranges,
@@ -591,12 +592,9 @@
         const Type& type,
         const Class& type_class) {
   ASSERT(hi->CanUseGenericSubtypeRangeCheckFor(type));
-  compiler::Label check_failed;
+  compiler::Label check_failed, load_succeeded;
   // a) First we perform subtype cid-range checks and load the instance type
   // arguments based on which check succeeded.
-  __ LoadClassIdMayBeSmi(TTSInternalRegs::kScratchReg,
-                         TypeTestABI::kInstanceReg);
-  compiler::Label load_succeeded;
   if (BuildLoadInstanceTypeArguments(assembler, hi, type, type_class,
                                      TTSInternalRegs::kScratchReg,
                                      TTSInternalRegs::kInstanceTypeArgumentsReg,
@@ -879,6 +877,7 @@
     const intptr_t tav_offset =
         compiler::target::Class::TypeArgumentsFieldOffset(type_class);
     compiler::Label is_subtype;
+    __ LoadClassIdMayBeSmi(class_id_reg, TypeTestABI::kInstanceReg);
     BuildOptimizedSubtypeRangeCheck(assembler, ranges, class_id_reg,
                                     &is_subtype, load_failed);
     __ Bind(&is_subtype);
@@ -902,6 +901,7 @@
     compiler::Label is_subtype, keep_looking;
     compiler::Label* check_failed =
         type_argument_checks.is_empty() ? load_failed : &keep_looking;
+    __ LoadClassIdMayBeSmi(class_id_reg, TypeTestABI::kInstanceReg);
     BuildOptimizedSubtypeRangeCheck(assembler, cid_checks_only, class_id_reg,
                                     &is_subtype, check_failed);
     __ Bind(&is_subtype);
@@ -929,6 +929,7 @@
       // and avoid emitting a jump to load_succeeded.
       compiler::Label* check_failed =
           i < vectors.length() - 1 ? &keep_looking : load_failed;
+      __ LoadClassIdMayBeSmi(class_id_reg, TypeTestABI::kInstanceReg);
       BuildOptimizedSubtypeRangeCheck(assembler, *vector, class_id_reg,
                                       &load_tav, check_failed);
       __ Bind(&load_tav);
diff --git a/runtime/vm/type_testing_stubs_test.cc b/runtime/vm/type_testing_stubs_test.cc
index 3c68eb8..c897d45 100644
--- a/runtime/vm/type_testing_stubs_test.cc
+++ b/runtime/vm/type_testing_stubs_test.cc
@@ -2264,6 +2264,92 @@
 }
 #endif  // !defined(PRODUCT)
 
+// This test checks for a failure due to not reloading the class id between
+// different uses of GenerateCidRangeChecks when loading the instance type
+// arguments vector in a TTS for an implemented class. GenerateCidRangeChecks
+// might clobber the register that holds the class ID to check, hence the need
+// to reload.
+//
+// To ensure that the register is clobbered on all architectures, we set things
+// up by generating the following classes:
+// * B<X>, an generic abstract class which is implemented by the others.
+// * I, implements B<String>, has a single int field x, and is
+//   used to create the checked instance.
+// * G<Y>, which implements B<Y> and has no fields (so its TAV field
+//   offset will correspond to that of the offset of x in I).
+// * C and D, consecutively defined non-generic classes which both implement
+//   B<int>.
+// * U0 - UN, unrelated concrete classes as needed for cid alignment.
+//
+// We'll carefully set things up so that the following equation between their
+// class ids holds:
+//
+//   G =  I - C.
+//
+// Thus, when we create a TTS for B<int> and check it against an instance V
+// of I. The cid for I will be loaded into a register R, and then two
+// check blocks will be generated:
+//
+//   * A check for the cid range [C-D], hich has the side effect of
+//     subtracting the cid of C from the contents of R (here, the cid of I).
+//
+//   * A check that R contains the cid for G.
+//
+// Thus, if the cid of I is not reloaded into R before the second check, and
+// the equation earlier holds,we'll get a false positive that V is an instance
+// of G, so the code will then try to load the instance type arguments from V
+// as if it was an instance of G. This means the contents of x will be loaded
+// and attempted to be used as a TypeArgumentsPtr, which will cause a crash
+// during the checks that the instantiation of Y is int.
+ISOLATE_UNIT_TEST_CASE(TTS_Regress_CidRangeChecks) {
+  // Bump this appropriately if the EXPECT_EQ below fails.
+  const intptr_t kNumUnrelated = 1183;
+  TextBuffer buffer(1024);
+  buffer.AddString(R"(
+      abstract class B<X> {}
+      class G<Y> implements B<Y> {}
+      class C implements B<int> {}
+      class D implements B<int> {}
+)");
+  for (intptr_t i = 0; i < kNumUnrelated; i++) {
+    buffer.Printf(R"(
+      class U%)" Pd R"( {}
+)",
+                  i);
+  }
+  buffer.AddString(R"(
+      class I implements B<String> {
+        final x = 1;
+      }
+
+      createI() => I();
+)");
+
+  const auto& root_library = Library::Handle(LoadTestScript(buffer.buffer()));
+  const auto& class_b = Class::Handle(GetClass(root_library, "B"));
+  const auto& class_g = Class::Handle(GetClass(root_library, "G"));
+  const auto& class_c = Class::Handle(GetClass(root_library, "C"));
+  const auto& class_i = Class::Handle(GetClass(root_library, "I"));
+  const auto& obj_i = Object::Handle(Invoke(root_library, "createI"));
+  {
+    SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
+    ClassFinalizer::FinalizeClass(class_g);
+  }
+
+  EXPECT_EQ(class_g.id(), class_i.id() - class_c.id());
+
+  const auto& tav_null = Object::null_type_arguments();
+  auto& tav_int = TypeArguments::Handle(TypeArguments::New(1));
+  tav_int.SetTypeAt(0, Type::Handle(Type::IntType()));
+  CanonicalizeTAV(&tav_int);
+
+  auto& type_b_int = Type::Handle(Type::New(class_b, tav_int));
+  FinalizeAndCanonicalize(&type_b_int);
+
+  TTSTestState state(thread, type_b_int);
+  state.InvokeEagerlySpecializedStub(Failure({obj_i, tav_null, tav_null}));
+}
+
 }  // namespace dart
 
 #endif  // !defined(TARGET_ARCH_IA32)
diff --git a/sdk/lib/_internal/vm/lib/core_patch.dart b/sdk/lib/_internal/vm/lib/core_patch.dart
index 78b3bab..79ff4aa 100644
--- a/sdk/lib/_internal/vm/lib/core_patch.dart
+++ b/sdk/lib/_internal/vm/lib/core_patch.dart
@@ -13,10 +13,14 @@
     show
         allocateOneByteString,
         allocateTwoByteString,
+        checkValidWeakTarget,
         ClassID,
         CodeUnits,
         copyRangeFromUint8ListToOneByteString,
         EfficientLengthIterable,
+        FinalizerBase,
+        FinalizerBaseMembers,
+        FinalizerEntry,
         FixedLengthListBase,
         IterableElementError,
         ListIterator,
@@ -28,11 +32,12 @@
         makeFixedListUnmodifiable,
         makeListFixedLength,
         patch,
+        reachabilityFence,
         unsafeCast,
         writeIntoOneByteString,
         writeIntoTwoByteString;
 
-import "dart:async" show Completer, DeferredLoadException, Future, Timer;
+import "dart:async" show Completer, DeferredLoadException, Future, Timer, Zone;
 
 import "dart:collection"
     show
@@ -49,9 +54,9 @@
 
 import "dart:convert" show ascii, Encoding, json, latin1, utf8;
 
-import "dart:ffi" show Pointer, Struct, Union;
+import "dart:ffi" show Pointer, Struct, Union, NativePort;
 
-import "dart:isolate" show Isolate;
+import "dart:isolate" show Isolate, RawReceivePort;
 
 import "dart:typed_data"
     show Endian, Uint8List, Int64List, Uint16List, Uint32List;
diff --git a/sdk/lib/_internal/vm/lib/expando_patch.dart b/sdk/lib/_internal/vm/lib/expando_patch.dart
index cf34b7f..fd5bd93 100644
--- a/sdk/lib/_internal/vm/lib/expando_patch.dart
+++ b/sdk/lib/_internal/vm/lib/expando_patch.dart
@@ -28,7 +28,8 @@
 
   @patch
   T? operator [](Object object) {
-    _checkType(object);
+    // TODO(http://dartbug.com/48634): Rename to `key`.
+    checkValidWeakTarget(object, 'object');
 
     var mask = _size - 1;
     var idx = object._identityHashCode & mask;
@@ -50,7 +51,8 @@
 
   @patch
   void operator []=(Object object, T? value) {
-    _checkType(object);
+    // TODO(http://dartbug.com/48634): Rename to `key`.
+    checkValidWeakTarget(object, 'object');
 
     var mask = _size - 1;
     var idx = object._identityHashCode & mask;
@@ -147,19 +149,6 @@
     }
   }
 
-  static _checkType(object) {
-    if ((object == null) ||
-        (object is bool) ||
-        (object is num) ||
-        (object is String) ||
-        (object is Pointer) ||
-        (object is Struct) ||
-        (object is Union)) {
-      throw new ArgumentError.value(object,
-          "Expandos are not allowed on strings, numbers, booleans, null, Pointers, Structs or Unions.");
-    }
-  }
-
   int get _size => _data.length;
   int get _limit => (3 * (_size ~/ 4));
 
@@ -170,14 +159,14 @@
 @patch
 class WeakReference<T extends Object> {
   @patch
-  factory WeakReference(T object) = _WeakReferenceImpl<T>;
+  factory WeakReference(T target) = _WeakReferenceImpl<T>;
 }
 
 @pragma("vm:entry-point")
 class _WeakReferenceImpl<T extends Object> implements WeakReference<T> {
-  _WeakReferenceImpl(T object) {
-    Expando._checkType(object);
-    _target = object;
+  _WeakReferenceImpl(T target) {
+    checkValidWeakTarget(target, 'target');
+    _target = target;
   }
 
   @pragma("vm:recognized", "other")
@@ -190,11 +179,3 @@
   @pragma("vm:external-name", "WeakReference_setTarget")
   external set _target(T? value);
 }
-
-@patch
-class Finalizer<T> {
-  @patch
-  factory Finalizer(void Function(T) object) {
-    throw UnimplementedError("Finalizer");
-  }
-}
diff --git a/sdk/lib/_internal/vm/lib/finalizer_patch.dart b/sdk/lib/_internal/vm/lib/finalizer_patch.dart
index aec537b..a9db853 100644
--- a/sdk/lib/_internal/vm/lib/finalizer_patch.dart
+++ b/sdk/lib/_internal/vm/lib/finalizer_patch.dart
@@ -4,5 +4,83 @@
 
 // part of "core_patch.dart";
 
-// This is a placeholder file which will shortly contain a Finalizer
-// implementation.
+@patch
+@pragma("vm:entry-point")
+abstract class Finalizer<T> {
+  @patch
+  factory Finalizer(void Function(T) callback) = _FinalizerImpl<T>;
+}
+
+@pragma("vm:entry-point")
+class _FinalizerImpl<T> extends FinalizerBase implements Finalizer<T> {
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external void Function(T) get _callback;
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external set _callback(void Function(T) value);
+
+  /// Constructs a finalizer.
+  ///
+  /// This is fine as a non-atomic operation, because the GC only looks at
+  /// finalizer instances when it process their entries. By preventing inlining
+  /// we ensure the the finalizer to have been fully initialized by the time
+  /// any [attach] on it is called.
+  ///
+  /// Alternatively, we could make it a recognized method and add a reachability
+  /// fence on the relevant members.
+  @pragma('vm:never-inline')
+  _FinalizerImpl(void Function(T) callback) {
+    allEntries = <FinalizerEntry>{};
+    _callback = Zone.current.bindUnaryCallbackGuarded(callback);
+    setIsolate();
+    isolateRegisterFinalizer();
+  }
+
+  void attach(Object value, T token, {Object? detach}) {
+    checkValidWeakTarget(value, 'value');
+    if (detach != null) {
+      checkValidWeakTarget(detach, 'detach');
+    }
+
+    // Initializing the entry in a non-atomic way should be fine.
+    // The only interesting step in the GC is when value is collected.
+    // If the entry gets processed before initializing value, it will be null,
+    // and this is fine. We will not consider it as being collected that GC.
+    final entry = FinalizerEntry()
+      ..value = value
+      ..token = token
+      ..detach = detach
+      ..finalizer = this;
+    allEntries.add(entry);
+    // Ensure value stays reachable until after having initialized the entry.
+    // This ensures the token and finalizer are set.
+    reachabilityFence(value);
+
+    if (detach != null) {
+      (detachments[detach] ??= <FinalizerEntry>{}).add(entry);
+    }
+  }
+
+  void _runFinalizers() {
+    FinalizerEntry? entry = exchangeEntriesCollectedWithNull();
+    while (entry != null) {
+      final token = entry.token;
+      // Check token for identical, detach might have been called.
+      if (!identical(token, entry)) {
+        _callback(unsafeCast<T>(token));
+      }
+      allEntries.remove(entry);
+      final detach = entry.detach;
+      if (detach != null) {
+        detachments[detach]?.remove(entry);
+      }
+      entry = entry.next;
+    }
+  }
+
+  @pragma("vm:entry-point", "call")
+  static _handleFinalizerMessage(_FinalizerImpl finalizer) {
+    finalizer._runFinalizers();
+  }
+}
diff --git a/sdk/lib/_internal/vm/lib/internal_patch.dart b/sdk/lib/_internal/vm/lib/internal_patch.dart
index 4c0fa92..547835c 100644
--- a/sdk/lib/_internal/vm/lib/internal_patch.dart
+++ b/sdk/lib/_internal/vm/lib/internal_patch.dart
@@ -9,7 +9,7 @@
 
 import "dart:async" show Timer;
 import "dart:core" hide Symbol;
-
+import "dart:ffi" show Pointer, Struct, Union;
 import "dart:isolate" show SendPort;
 import "dart:typed_data" show Int32List, Uint8List;
 
@@ -209,3 +209,225 @@
     throw new LateError.localADI(localName);
   }
 }
+
+void checkValidWeakTarget(object, name) {
+  if ((object == null) ||
+      (object is bool) ||
+      (object is num) ||
+      (object is String) ||
+      (object is Pointer) ||
+      (object is Struct) ||
+      (object is Union)) {
+    throw new ArgumentError.value(object, name,
+        "Cannot be a string, number, boolean, null, Pointer, Struct or Union");
+  }
+}
+
+@pragma("vm:entry-point")
+class FinalizerBase {
+  /// The list of finalizers of this isolate.
+  ///
+  /// Reuses [WeakReference] so that we don't have to implement yet another
+  /// mechanism to hold on weakly to things.
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external static List<WeakReference<FinalizerBase>>? get _isolateFinalizers;
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external static set _isolateFinalizers(
+      List<WeakReference<FinalizerBase>>? value);
+
+  static int _isolateFinalizersPurgeCollectedAt = 1;
+
+  /// Amortizes the cost for purging nulled out entries.
+  ///
+  /// Similar to how Expandos purge their nulled out entries on a rehash when
+  /// resizing.
+  static void _isolateFinalizersEnsureCapacity() {
+    _isolateFinalizers ??= <WeakReference<FinalizerBase>>[];
+    if (_isolateFinalizers!.length < _isolateFinalizersPurgeCollectedAt) {
+      return;
+    }
+    // retainWhere does a single traversal.
+    _isolateFinalizers!.retainWhere((weak) => weak.target != null);
+    // We might have dropped most finalizers, trigger next resize at 2x.
+    _isolateFinalizersPurgeCollectedAt = _isolateFinalizers!.length * 2;
+  }
+
+  /// Registers this [FinalizerBase] to the isolate.
+  ///
+  /// This is used to prevent sending messages from the GC to the isolate after
+  /// isolate shutdown.
+  void _isolateRegisterFinalizer() {
+    _isolateFinalizersEnsureCapacity();
+    _isolateFinalizers!.add(WeakReference(this));
+  }
+
+  /// The isolate this [FinalizerBase] belongs to.
+  ///
+  /// This is used to send finalizer messages to `_handleFinalizerMessage`
+  /// without a Dart_Port.
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external _setIsolate();
+
+  /// All active attachments.
+  ///
+  /// This keeps the [FinalizerEntry]s belonging to this finalizer alive. If an
+  /// entry gets collected, the finalizer is not run when the
+  /// [FinalizerEntry.value] is collected.
+  ///
+  /// TODO(http://dartbug.com/47777): For native finalizers, what data structure
+  /// can we use that we can modify in the VM. So that we don't have to send a
+  /// message to Dart to clean up entries for which the GC has run.
+  ///
+  /// Requirements for data structure:
+  /// 1. Keeps entries reachable. Entries that are collected will never run
+  ///    the GC.
+  /// 2. Atomic insert in Dart on `attach`. GC should not run in between.
+  /// 3. Atomic remove in Dart on `detach`. multiple GC tasks run in parallel.
+  /// 4. Atomic remove in C++ on value being collected. Multiple GC tasks run in
+  ///    parallel.
+  ///
+  /// For Dart finalizers we execute the remove in Dart, much simpler.
+  @pragma("vm:recognized", "other")
+  @pragma('vm:prefer-inline')
+  external Set<FinalizerEntry> get _allEntries;
+  @pragma("vm:recognized", "other")
+  @pragma('vm:prefer-inline')
+  external set _allEntries(Set<FinalizerEntry> entries);
+
+  /// Entries of which the value has been collected.
+  ///
+  /// This is a linked list, with [FinalizerEntry.next].
+  ///
+  /// Atomic exchange: The GC cannot run between reading the value and storing
+  /// `null`. Atomicity guaranteed by force optimizing the function.
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external FinalizerEntry? _exchangeEntriesCollectedWithNull();
+
+  /// A weak map from `detach` keys to [FinalizerEntry]s.
+  ///
+  /// Using the [FinalizerEntry.detach] keys as keys in an [Expando] ensures
+  /// they can be GCed.
+  ///
+  /// [FinalizerEntry]s do not get GCed themselves when their
+  /// [FinalizerEntry.detach] is unreachable, in contrast to `WeakProperty`s
+  /// which are GCed themselves when their `key` is no longer reachable.
+  /// To prevent [FinalizerEntry]s staying around in [_detachments] forever,
+  /// we reuse `WeakProperty`s.
+  /// To avoid code duplication, we do not inline the code but use an [Expando]
+  /// here instead.
+  ///
+  /// We cannot eagerly purge entries from the map (in the Expando) when GCed.
+  /// The map is indexed on detach, and doesn't enable finding the entries
+  /// based on their identity.
+  /// Instead we rely on the WeakProperty being nulled out (assuming the
+  /// `detach` key gets GCed) and then reused.
+  @pragma("vm:recognized", "other")
+  @pragma('vm:prefer-inline')
+  external Expando<Set<FinalizerEntry>>? get _detachments;
+  @pragma("vm:recognized", "other")
+  @pragma('vm:prefer-inline')
+  external set _detachments(Expando<Set<FinalizerEntry>>? value);
+
+  void detach(Object detach) {
+    final entries = detachments[detach];
+    if (entries != null) {
+      for (final entry in entries) {
+        entry.token = entry;
+        _allEntries.remove(entry);
+      }
+      detachments[detach] = null;
+    }
+  }
+}
+
+// Extension so that the members can be accessed from other libs.
+extension FinalizerBaseMembers on FinalizerBase {
+  /// See documentation on [_allEntries].
+  @pragma('vm:prefer-inline')
+  Set<FinalizerEntry> get allEntries => _allEntries;
+  @pragma('vm:prefer-inline')
+  set allEntries(Set<FinalizerEntry> value) => _allEntries = value;
+
+  /// See documentation on [_exchangeEntriesCollectedWithNull].
+  FinalizerEntry? exchangeEntriesCollectedWithNull() =>
+      _exchangeEntriesCollectedWithNull();
+
+  /// See documentation on [_detachments].
+  @pragma('vm:prefer-inline')
+  Expando<Set<FinalizerEntry>> get detachments {
+    _detachments ??= Expando<Set<FinalizerEntry>>();
+    return unsafeCast<Expando<Set<FinalizerEntry>>>(_detachments);
+  }
+
+  /// See documentation on [_isolateRegisterFinalizer].
+  isolateRegisterFinalizer() => _isolateRegisterFinalizer();
+
+  /// See documentation on [_setIsolate].
+  setIsolate() => _setIsolate();
+}
+
+/// Contains the informatation of an active [Finalizer.attach].
+///
+/// It holds on to the [value], optional [detach], and [token]. In addition, it
+/// also keeps a reference the [finalizer] it belings to and a [next] field for
+/// when being used in a linked list.
+///
+/// This is being kept alive by [FinalizerBase._allEntries] until either (1)
+/// [Finalizer.detach] detaches it, or (2) [value] is collected and the
+/// `callback` has been invoked.
+///
+/// Note that the GC itself uses an extra hidden field `next_seen_by_gc` to keep a
+/// linked list of pending entries while running the GC.
+@pragma("vm:entry-point")
+class FinalizerEntry {
+  /// The [value] the [FinalizerBase] is attached to.
+  ///
+  /// Set to `null` by GC when unreachable.
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external Object? get value;
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external set value(Object? value);
+
+  /// The [detach] object can be passed to [FinalizerBase] to detach
+  /// the finalizer.
+  ///
+  /// Set to `null` by GC when unreachable.
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external Object? get detach;
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external set detach(Object? value);
+
+  /// The [token] is passed to [FinalizerBase] when the finalizer is run.
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external Object? get token;
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external set token(Object? value);
+
+  /// The [finalizer] this [FinalizerEntry] belongs to.
+  ///
+  /// Set to `null` by GC when unreachable.
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external set finalizer(FinalizerBase? finalizer);
+
+  /// The [next] entry in a linked list.
+  ///
+  /// Used in for the linked list starting from
+  /// [FinalizerBase._exchangeEntriesCollectedWithNull].
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external FinalizerEntry? get next;
+  @pragma("vm:recognized", "other")
+  @pragma("vm:prefer-inline")
+  external set next(FinalizerEntry? value);
+}
diff --git a/sdk/lib/core/weak.dart b/sdk/lib/core/weak.dart
index 01ef31c..3c8f968 100644
--- a/sdk/lib/core/weak.dart
+++ b/sdk/lib/core/weak.dart
@@ -207,15 +207,15 @@
   /// with different, or the same, finalization token.
   void attach(Object value, T finalizationToken, {Object? detach});
 
-  /// Detaches the finalizer from values attached with [detachToken].
+  /// Detaches this finalizer from values attached with [detach].
   ///
   /// Each attachment between this finalizer and a value,
-  /// which was created by calling [attach] with the [detachToken] object as
+  /// which was created by calling [attach] with the [detach] object as
   /// `detach` argument, is removed.
   ///
   /// If the finalizer was attached multiple times to the same value
   /// with different detachment keys,
-  /// only those attachments which used [detachToken] are removed.
+  /// only those attachments which used [detach] are removed.
   ///
   /// After detaching, an attachment won't cause any callbacks to happen
   /// if the object become inaccessible.
@@ -242,5 +242,5 @@
   ///   }
   /// }
   /// ```
-  void detach(Object detachToken);
+  void detach(Object detach);
 }
diff --git a/sdk/lib/isolate/isolate.dart b/sdk/lib/isolate/isolate.dart
index 96ef3e5..6b2b940 100644
--- a/sdk/lib/isolate/isolate.dart
+++ b/sdk/lib/isolate/isolate.dart
@@ -723,6 +723,7 @@
   ///     therefore not be sent.
   ///   - [ReceivePort]
   ///   - [DynamicLibrary]
+  ///   - [Finalizer]
   ///   - [Pointer]
   ///   - [UserTag]
   ///   - `MirrorReference`
diff --git a/tools/VERSION b/tools/VERSION
index 36bc97b..4113a05 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 17
 PATCH 0
-PRERELEASE 239
+PRERELEASE 240
 PRERELEASE_PATCH 0
\ No newline at end of file