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, ¤t_entry->untag()->value_);
+ GCVisitorType::SetNullIfCollected(heap_base,
+ ¤t_entry->untag()->detach_);
+ GCVisitorType::SetNullIfCollected(heap_base,
+ ¤t_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