Version 2.13.0-193.0.dev
Merge commit '76ed8441b9e5e259bdf07cc929cd303974b5e466' into 'dev'
diff --git a/pkg/front_end/testcases/dart2js/late_fields.dart b/pkg/front_end/testcases/dart2js/late_fields.dart
new file mode 100644
index 0000000..ea3012b
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2021, 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.
+
+void main() {
+ testUninitializedNonFinalInstanceField();
+ testUninitializedFinalInstanceField();
+ testInitializedNonFinalInstanceField();
+ testInitializedFinalInstanceField();
+}
+
+class C {
+ late int a;
+ late final int b;
+ late int c = -1;
+ late final int d = -1;
+}
+
+var c = C();
+
+void testUninitializedNonFinalInstanceField() {
+ print(c.a);
+ c.a = 42;
+ print(c.a);
+}
+
+void testUninitializedFinalInstanceField() {
+ print(c.b);
+ c.b = 42;
+ print(c.b);
+}
+
+void testInitializedNonFinalInstanceField() {
+ print(c.c);
+ c.c = 42;
+ print(c.c);
+}
+
+void testInitializedFinalInstanceField() {
+ print(c.d);
+}
diff --git a/pkg/front_end/testcases/dart2js/late_fields.dart.strong.expect b/pkg/front_end/testcases/dart2js/late_fields.dart.strong.expect
new file mode 100644
index 0000000..cf590d6
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields.dart.strong.expect
@@ -0,0 +1,56 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+ field core::int? _#C#a = null;
+ field core::int? _#C#b = null;
+ field core::int? _#C#c = null;
+ field core::int? _#C#d = null;
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ get a() → core::int
+ return let final core::int? #t1 = this.{self::C::_#C#a} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("a") : #t1{core::int};
+ set a(core::int #t2) → void
+ this.{self::C::_#C#a} = #t2;
+ get b() → core::int
+ return let final core::int? #t3 = this.{self::C::_#C#b} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("b") : #t3{core::int};
+ set b(core::int #t4) → void
+ if(this.{self::C::_#C#b} == null)
+ this.{self::C::_#C#b} = #t4;
+ else
+ throw new _in::LateError::fieldAI("b");
+ get c() → core::int
+ return let final core::int? #t5 = this.{self::C::_#C#c} in #t5 == null ?{core::int} this.{self::C::_#C#c} = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+ set c(core::int #t6) → void
+ this.{self::C::_#C#c} = #t6;
+ get d() → core::int
+ return let final core::int? #t7 = this.{self::C::_#C#d} in #t7 == null ?{core::int} let final core::int #t8 = 1.{core::int::unary-}(){() → core::int} in this.{self::C::_#C#d} == null ?{core::int} this.{self::C::_#C#d} = #t8 : throw new _in::LateError::fieldADI("d") : #t7{core::int};
+}
+static field self::C c = new self::C::•();
+static method main() → void {
+ self::testUninitializedNonFinalInstanceField();
+ self::testUninitializedFinalInstanceField();
+ self::testInitializedNonFinalInstanceField();
+ self::testInitializedFinalInstanceField();
+}
+static method testUninitializedNonFinalInstanceField() → void {
+ core::print(self::c.{self::C::a}{core::int});
+ self::c.{self::C::a} = 42;
+ core::print(self::c.{self::C::a}{core::int});
+}
+static method testUninitializedFinalInstanceField() → void {
+ core::print(self::c.{self::C::b}{core::int});
+ self::c.{self::C::b} = 42;
+ core::print(self::c.{self::C::b}{core::int});
+}
+static method testInitializedNonFinalInstanceField() → void {
+ core::print(self::c.{self::C::c}{core::int});
+ self::c.{self::C::c} = 42;
+ core::print(self::c.{self::C::c}{core::int});
+}
+static method testInitializedFinalInstanceField() → void {
+ core::print(self::c.{self::C::d}{core::int});
+}
diff --git a/pkg/front_end/testcases/dart2js/late_fields.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/late_fields.dart.strong.transformed.expect
new file mode 100644
index 0000000..9b256e1
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields.dart.strong.transformed.expect
@@ -0,0 +1,63 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+ field core::int? _#C#a = null;
+ field core::int? _#C#b = null;
+ field core::int? _#C#c = null;
+ field core::int? _#C#d = null;
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ get a() → core::int
+ return let final core::int? #t1 = this.{self::C::_#C#a} in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("a") : #t1{core::int};
+ set a(core::int #t2) → void
+ this.{self::C::_#C#a} = #t2;
+ get b() → core::int
+ return let final core::int? #t3 = this.{self::C::_#C#b} in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("b") : #t3{core::int};
+ set b(core::int #t4) → void
+ if(this.{self::C::_#C#b} == null)
+ this.{self::C::_#C#b} = #t4;
+ else
+ throw new _in::LateError::fieldAI("b");
+ get c() → core::int
+ return let final core::int? #t5 = this.{self::C::_#C#c} in #t5 == null ?{core::int} this.{self::C::_#C#c} = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+ set c(core::int #t6) → void
+ this.{self::C::_#C#c} = #t6;
+ get d() → core::int
+ return let final core::int? #t7 = this.{self::C::_#C#d} in #t7 == null ?{core::int} let final core::int #t8 = 1.{core::int::unary-}(){() → core::int} in this.{self::C::_#C#d} == null ?{core::int} this.{self::C::_#C#d} = #t8 : throw new _in::LateError::fieldADI("d") : #t7{core::int};
+}
+static field self::C c = new self::C::•();
+static method main() → void {
+ self::testUninitializedNonFinalInstanceField();
+ self::testUninitializedFinalInstanceField();
+ self::testInitializedNonFinalInstanceField();
+ self::testInitializedFinalInstanceField();
+}
+static method testUninitializedNonFinalInstanceField() → void {
+ core::print(self::c.{self::C::a}{core::int});
+ self::c.{self::C::a} = 42;
+ core::print(self::c.{self::C::a}{core::int});
+}
+static method testUninitializedFinalInstanceField() → void {
+ core::print(self::c.{self::C::b}{core::int});
+ self::c.{self::C::b} = 42;
+ core::print(self::c.{self::C::b}{core::int});
+}
+static method testInitializedNonFinalInstanceField() → void {
+ core::print(self::c.{self::C::c}{core::int});
+ self::c.{self::C::c} = 42;
+ core::print(self::c.{self::C::c}{core::int});
+}
+static method testInitializedFinalInstanceField() → void {
+ core::print(self::c.{self::C::d}{core::int});
+}
+
+
+Extra constant evaluation status:
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_fields.dart:15:16 -> DoubleConstant(-1.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_fields.dart:16:22 -> DoubleConstant(-1.0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_fields.dart:16:18 -> DoubleConstant(-1.0)
+Extra constant evaluation: evaluated: 92, effectively constant: 3
diff --git a/pkg/front_end/testcases/dart2js/late_fields.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/late_fields.dart.textual_outline.expect
new file mode 100644
index 0000000..7f4885f
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields.dart.textual_outline.expect
@@ -0,0 +1,14 @@
+void main() {}
+
+class C {
+ late int a;
+ late final int b;
+ late int c = -1;
+ late final int d = -1;
+}
+
+var c = C();
+void testUninitializedNonFinalInstanceField() {}
+void testUninitializedFinalInstanceField() {}
+void testInitializedNonFinalInstanceField() {}
+void testInitializedFinalInstanceField() {}
diff --git a/pkg/front_end/testcases/dart2js/late_fields.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/late_fields.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..79b904b
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields.dart.textual_outline_modelled.expect
@@ -0,0 +1,24 @@
+class C {
+ ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+ int a;
+ ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+ final int b;
+ ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+ int c = -1;
+ ---- unknown chunk starts ----
+late
+---- unknown chunk ends ----
+ final int d = -1;
+}
+var c = C();
+void main() {}
+void testInitializedFinalInstanceField() {}
+void testInitializedNonFinalInstanceField() {}
+void testUninitializedFinalInstanceField() {}
+void testUninitializedNonFinalInstanceField() {}
diff --git a/pkg/front_end/testcases/dart2js/late_fields.dart.weak.expect b/pkg/front_end/testcases/dart2js/late_fields.dart.weak.expect
new file mode 100644
index 0000000..9b589dc
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields.dart.weak.expect
@@ -0,0 +1,56 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+ field core::int? _#C#a = _in::createSentinel<core::int>();
+ field core::int? _#C#b = _in::createSentinel<core::int>();
+ field core::int? _#C#c = _in::createSentinel<core::int>();
+ field core::int? _#C#d = _in::createSentinel<core::int>();
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ get a() → core::int
+ return let final core::int? #t1 = this.{self::C::_#C#a} in _in::isSentinel(#t1) ?{core::int} throw new _in::LateError::fieldNI("a") : #t1{core::int};
+ set a(core::int #t2) → void
+ this.{self::C::_#C#a} = #t2;
+ get b() → core::int
+ return let final core::int? #t3 = this.{self::C::_#C#b} in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::fieldNI("b") : #t3{core::int};
+ set b(core::int #t4) → void
+ if(_in::isSentinel(this.{self::C::_#C#b}))
+ this.{self::C::_#C#b} = #t4;
+ else
+ throw new _in::LateError::fieldAI("b");
+ get c() → core::int
+ return let final core::int? #t5 = this.{self::C::_#C#c} in _in::isSentinel(#t5) ?{core::int} this.{self::C::_#C#c} = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+ set c(core::int #t6) → void
+ this.{self::C::_#C#c} = #t6;
+ get d() → core::int
+ return let final core::int #t7 = this.{self::C::_#C#d} in _in::isSentinel(#t7) ?{core::int} let final core::int #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(this.{self::C::_#C#d}) ?{core::int} this.{self::C::_#C#d} = #t8 : throw new _in::LateError::fieldADI("d") : #t7;
+}
+static field self::C c = new self::C::•();
+static method main() → void {
+ self::testUninitializedNonFinalInstanceField();
+ self::testUninitializedFinalInstanceField();
+ self::testInitializedNonFinalInstanceField();
+ self::testInitializedFinalInstanceField();
+}
+static method testUninitializedNonFinalInstanceField() → void {
+ core::print(self::c.{self::C::a}{core::int});
+ self::c.{self::C::a} = 42;
+ core::print(self::c.{self::C::a}{core::int});
+}
+static method testUninitializedFinalInstanceField() → void {
+ core::print(self::c.{self::C::b}{core::int});
+ self::c.{self::C::b} = 42;
+ core::print(self::c.{self::C::b}{core::int});
+}
+static method testInitializedNonFinalInstanceField() → void {
+ core::print(self::c.{self::C::c}{core::int});
+ self::c.{self::C::c} = 42;
+ core::print(self::c.{self::C::c}{core::int});
+}
+static method testInitializedFinalInstanceField() → void {
+ core::print(self::c.{self::C::d}{core::int});
+}
diff --git a/pkg/front_end/testcases/dart2js/late_fields.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/late_fields.dart.weak.outline.expect
new file mode 100644
index 0000000..09228574
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields.dart.weak.outline.expect
@@ -0,0 +1,30 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class C extends core::Object {
+ field core::int? _#C#a;
+ field core::int? _#C#b;
+ field core::int? _#C#c;
+ field core::int? _#C#d;
+ synthetic constructor •() → self::C
+ ;
+ get a() → core::int;
+ set a(core::int #t1) → void;
+ get b() → core::int;
+ set b(core::int #t2) → void;
+ get c() → core::int;
+ set c(core::int #t3) → void;
+ get d() → core::int;
+}
+static field self::C c;
+static method main() → void
+ ;
+static method testUninitializedNonFinalInstanceField() → void
+ ;
+static method testUninitializedFinalInstanceField() → void
+ ;
+static method testInitializedNonFinalInstanceField() → void
+ ;
+static method testInitializedFinalInstanceField() → void
+ ;
diff --git a/pkg/front_end/testcases/dart2js/late_fields.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/late_fields.dart.weak.transformed.expect
new file mode 100644
index 0000000..46bb69b
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_fields.dart.weak.transformed.expect
@@ -0,0 +1,63 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class C extends core::Object {
+ field core::int? _#C#a = _in::createSentinel<core::int>();
+ field core::int? _#C#b = _in::createSentinel<core::int>();
+ field core::int? _#C#c = _in::createSentinel<core::int>();
+ field core::int? _#C#d = _in::createSentinel<core::int>();
+ synthetic constructor •() → self::C
+ : super core::Object::•()
+ ;
+ get a() → core::int
+ return let final core::int? #t1 = this.{self::C::_#C#a} in _in::isSentinel(#t1) ?{core::int} throw new _in::LateError::fieldNI("a") : #t1{core::int};
+ set a(core::int #t2) → void
+ this.{self::C::_#C#a} = #t2;
+ get b() → core::int
+ return let final core::int? #t3 = this.{self::C::_#C#b} in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::fieldNI("b") : #t3{core::int};
+ set b(core::int #t4) → void
+ if(_in::isSentinel(this.{self::C::_#C#b}))
+ this.{self::C::_#C#b} = #t4;
+ else
+ throw new _in::LateError::fieldAI("b");
+ get c() → core::int
+ return let final core::int? #t5 = this.{self::C::_#C#c} in _in::isSentinel(#t5) ?{core::int} this.{self::C::_#C#c} = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+ set c(core::int #t6) → void
+ this.{self::C::_#C#c} = #t6;
+ get d() → core::int
+ return let final core::int #t7 = this.{self::C::_#C#d} in _in::isSentinel(#t7) ?{core::int} let final core::int #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(this.{self::C::_#C#d}) ?{core::int} this.{self::C::_#C#d} = #t8 : throw new _in::LateError::fieldADI("d") : #t7;
+}
+static field self::C c = new self::C::•();
+static method main() → void {
+ self::testUninitializedNonFinalInstanceField();
+ self::testUninitializedFinalInstanceField();
+ self::testInitializedNonFinalInstanceField();
+ self::testInitializedFinalInstanceField();
+}
+static method testUninitializedNonFinalInstanceField() → void {
+ core::print(self::c.{self::C::a}{core::int});
+ self::c.{self::C::a} = 42;
+ core::print(self::c.{self::C::a}{core::int});
+}
+static method testUninitializedFinalInstanceField() → void {
+ core::print(self::c.{self::C::b}{core::int});
+ self::c.{self::C::b} = 42;
+ core::print(self::c.{self::C::b}{core::int});
+}
+static method testInitializedNonFinalInstanceField() → void {
+ core::print(self::c.{self::C::c}{core::int});
+ self::c.{self::C::c} = 42;
+ core::print(self::c.{self::C::c}{core::int});
+}
+static method testInitializedFinalInstanceField() → void {
+ core::print(self::c.{self::C::d}{core::int});
+}
+
+
+Extra constant evaluation status:
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_fields.dart:15:16 -> DoubleConstant(-1.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_fields.dart:16:22 -> DoubleConstant(-1.0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_fields.dart:16:18 -> DoubleConstant(-1.0)
+Extra constant evaluation: evaluated: 96, effectively constant: 3
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart b/pkg/front_end/testcases/dart2js/late_locals.dart
new file mode 100644
index 0000000..8065042
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2021, 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.
+
+void main() {
+ testNullableUninitializedNonFinalLocal();
+ testNonNullableUninitializedNonFinalLocal();
+ testNullableUninitializedFinalLocal();
+ testNonNullableUninitializedFinalLocal();
+ testNullableInitializedNonFinalLocal();
+ testNonNullableInitializedNonFinalLocal();
+ testNullableInitializedFinalLocal();
+ testNonNullableInitializedFinalLocal();
+}
+
+void testNullableUninitializedNonFinalLocal() {
+ late int? x;
+ x = 42;
+ print(x);
+}
+
+void testNonNullableUninitializedNonFinalLocal() {
+ late int x;
+ x = 42;
+ print(x);
+}
+
+void testNullableUninitializedFinalLocal() {
+ late final int? x;
+ x = 42;
+ print(x);
+}
+
+void testNonNullableUninitializedFinalLocal() {
+ late final int x;
+ x = 42;
+ print(x);
+}
+
+void testNullableInitializedNonFinalLocal() {
+ late int? x = -1;
+ print(x);
+ x = 42;
+ print(x);
+
+ late int? y = null;
+ print(y);
+ y = 42;
+ print(y);
+}
+
+void testNonNullableInitializedNonFinalLocal() {
+ late int x = -1;
+ print(x);
+ x = 42;
+ print(x);
+}
+
+void testNullableInitializedFinalLocal() {
+ late final int? x = -1;
+ print(x);
+
+ late final int? y = null;
+ print(y);
+}
+
+void testNonNullableInitializedFinalLocal() {
+ late final int x = -1;
+ print(x);
+}
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.strong.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.strong.expect
new file mode 100644
index 0000000..fe43261
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.strong.expect
@@ -0,0 +1,101 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method main() → void {
+ self::testNullableUninitializedNonFinalLocal();
+ self::testNonNullableUninitializedNonFinalLocal();
+ self::testNullableUninitializedFinalLocal();
+ self::testNonNullableUninitializedFinalLocal();
+ self::testNullableInitializedNonFinalLocal();
+ self::testNonNullableInitializedNonFinalLocal();
+ self::testNullableInitializedFinalLocal();
+ self::testNonNullableInitializedFinalLocal();
+}
+static method testNullableUninitializedNonFinalLocal() → void {
+ lowered core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
+ function #x#set(core::int? #t2) → dynamic
+ return #x = #t2;
+ #x#set(42){(core::int?) → dynamic};
+ core::print(#x#get(){() → core::int?});
+}
+static method testNonNullableUninitializedNonFinalLocal() → void {
+ lowered core::int? #x;
+ function #x#get() → core::int
+ return let final core::int? #t3 = #x in #t3 == null ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
+ function #x#set(core::int #t4) → dynamic
+ return #x = #t4;
+ #x#set(42){(core::int) → dynamic};
+ core::print(#x#get(){() → core::int});
+}
+static method testNullableUninitializedFinalLocal() → void {
+ lowered final core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
+ function #x#set(core::int? #t6) → dynamic
+ if(_in::isSentinel(#x))
+ return #x = #t6;
+ else
+ throw new _in::LateError::localAI("x");
+ #x#set(42){(core::int?) → dynamic};
+ core::print(#x#get(){() → core::int?});
+}
+static method testNonNullableUninitializedFinalLocal() → void {
+ lowered final core::int? #x;
+ function #x#get() → core::int
+ return let final core::int? #t7 = #x in #t7 == null ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
+ function #x#set(core::int #t8) → dynamic
+ if(#x == null)
+ return #x = #t8;
+ else
+ throw new _in::LateError::localAI("x");
+ #x#set(42){(core::int) → dynamic};
+ core::print(#x#get(){() → core::int});
+}
+static method testNullableInitializedNonFinalLocal() → void {
+ lowered core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
+ function #x#set(core::int? #t10) → dynamic
+ return #x = #t10;
+ core::print(#x#get(){() → core::int?});
+ #x#set(42){(core::int?) → dynamic};
+ core::print(#x#get(){() → core::int?});
+ lowered core::int? #y = _in::createSentinel<core::int?>();
+ function #y#get() → core::int?
+ return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
+ function #y#set(core::int? #t12) → dynamic
+ return #y = #t12;
+ core::print(#y#get(){() → core::int?});
+ #y#set(42){(core::int?) → dynamic};
+ core::print(#y#get(){() → core::int?});
+}
+static method testNonNullableInitializedNonFinalLocal() → void {
+ lowered core::int? #x;
+ function #x#get() → core::int
+ return let final core::int? #t13 = #x in #t13 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
+ function #x#set(core::int #t14) → dynamic
+ return #x = #t14;
+ core::print(#x#get(){() → core::int});
+ #x#set(42){(core::int) → dynamic};
+ core::print(#x#get(){() → core::int});
+}
+static method testNullableInitializedFinalLocal() → void {
+ lowered final core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
+ core::print(#x#get(){() → core::int?});
+ lowered final core::int? #y = _in::createSentinel<core::int?>();
+ function #y#get() → core::int?
+ return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
+ core::print(#y#get(){() → core::int?});
+}
+static method testNonNullableInitializedFinalLocal() → void {
+ lowered final core::int? #x;
+ function #x#get() → core::int
+ return let final core::int? #t19 = #x in #t19 == null ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19{core::int};
+ core::print(#x#get(){() → core::int});
+}
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.strong.transformed.expect
new file mode 100644
index 0000000..ac86677
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.strong.transformed.expect
@@ -0,0 +1,112 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method main() → void {
+ self::testNullableUninitializedNonFinalLocal();
+ self::testNonNullableUninitializedNonFinalLocal();
+ self::testNullableUninitializedFinalLocal();
+ self::testNonNullableUninitializedFinalLocal();
+ self::testNullableInitializedNonFinalLocal();
+ self::testNonNullableInitializedNonFinalLocal();
+ self::testNullableInitializedFinalLocal();
+ self::testNonNullableInitializedFinalLocal();
+}
+static method testNullableUninitializedNonFinalLocal() → void {
+ lowered core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
+ function #x#set(core::int? #t2) → dynamic
+ return #x = #t2;
+ #x#set(42){(core::int?) → dynamic};
+ core::print(#x#get(){() → core::int?});
+}
+static method testNonNullableUninitializedNonFinalLocal() → void {
+ lowered core::int? #x;
+ function #x#get() → core::int
+ return let final core::int? #t3 = #x in #t3 == null ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
+ function #x#set(core::int #t4) → dynamic
+ return #x = #t4;
+ #x#set(42){(core::int) → dynamic};
+ core::print(#x#get(){() → core::int});
+}
+static method testNullableUninitializedFinalLocal() → void {
+ lowered final core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
+ function #x#set(core::int? #t6) → dynamic
+ if(_in::isSentinel(#x))
+ return #x = #t6;
+ else
+ throw new _in::LateError::localAI("x");
+ #x#set(42){(core::int?) → dynamic};
+ core::print(#x#get(){() → core::int?});
+}
+static method testNonNullableUninitializedFinalLocal() → void {
+ lowered final core::int? #x;
+ function #x#get() → core::int
+ return let final core::int? #t7 = #x in #t7 == null ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
+ function #x#set(core::int #t8) → dynamic
+ if(#x == null)
+ return #x = #t8;
+ else
+ throw new _in::LateError::localAI("x");
+ #x#set(42){(core::int) → dynamic};
+ core::print(#x#get(){() → core::int});
+}
+static method testNullableInitializedNonFinalLocal() → void {
+ lowered core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
+ function #x#set(core::int? #t10) → dynamic
+ return #x = #t10;
+ core::print(#x#get(){() → core::int?});
+ #x#set(42){(core::int?) → dynamic};
+ core::print(#x#get(){() → core::int?});
+ lowered core::int? #y = _in::createSentinel<core::int?>();
+ function #y#get() → core::int?
+ return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
+ function #y#set(core::int? #t12) → dynamic
+ return #y = #t12;
+ core::print(#y#get(){() → core::int?});
+ #y#set(42){(core::int?) → dynamic};
+ core::print(#y#get(){() → core::int?});
+}
+static method testNonNullableInitializedNonFinalLocal() → void {
+ lowered core::int? #x;
+ function #x#get() → core::int
+ return let final core::int? #t13 = #x in #t13 == null ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
+ function #x#set(core::int #t14) → dynamic
+ return #x = #t14;
+ core::print(#x#get(){() → core::int});
+ #x#set(42){(core::int) → dynamic};
+ core::print(#x#get(){() → core::int});
+}
+static method testNullableInitializedFinalLocal() → void {
+ lowered final core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
+ core::print(#x#get(){() → core::int?});
+ lowered final core::int? #y = _in::createSentinel<core::int?>();
+ function #y#get() → core::int?
+ return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
+ core::print(#y#get(){() → core::int?});
+}
+static method testNonNullableInitializedFinalLocal() → void {
+ lowered final core::int? #x;
+ function #x#get() → core::int
+ return let final core::int? #t19 = #x in #t19 == null ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in #x == null ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19{core::int};
+ core::print(#x#get(){() → core::int});
+}
+
+
+Extra constant evaluation status:
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:41:17 -> DoubleConstant(-1.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:53:16 -> DoubleConstant(-1.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:60:23 -> DoubleConstant(-1.0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:60:19 -> DoubleConstant(-1.0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:63:19 -> NullConstant(null)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:68:22 -> DoubleConstant(-1.0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:68:18 -> DoubleConstant(-1.0)
+Extra constant evaluation: evaluated: 168, effectively constant: 7
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.textual_outline.expect
new file mode 100644
index 0000000..c13d4ba
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.textual_outline.expect
@@ -0,0 +1,9 @@
+void main() {}
+void testNullableUninitializedNonFinalLocal() {}
+void testNonNullableUninitializedNonFinalLocal() {}
+void testNullableUninitializedFinalLocal() {}
+void testNonNullableUninitializedFinalLocal() {}
+void testNullableInitializedNonFinalLocal() {}
+void testNonNullableInitializedNonFinalLocal() {}
+void testNullableInitializedFinalLocal() {}
+void testNonNullableInitializedFinalLocal() {}
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..6760814
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.textual_outline_modelled.expect
@@ -0,0 +1,9 @@
+void main() {}
+void testNonNullableInitializedFinalLocal() {}
+void testNonNullableInitializedNonFinalLocal() {}
+void testNonNullableUninitializedFinalLocal() {}
+void testNonNullableUninitializedNonFinalLocal() {}
+void testNullableInitializedFinalLocal() {}
+void testNullableInitializedNonFinalLocal() {}
+void testNullableUninitializedFinalLocal() {}
+void testNullableUninitializedNonFinalLocal() {}
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.weak.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.expect
new file mode 100644
index 0000000..26979f0
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.expect
@@ -0,0 +1,101 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method main() → void {
+ self::testNullableUninitializedNonFinalLocal();
+ self::testNonNullableUninitializedNonFinalLocal();
+ self::testNullableUninitializedFinalLocal();
+ self::testNonNullableUninitializedFinalLocal();
+ self::testNullableInitializedNonFinalLocal();
+ self::testNonNullableInitializedNonFinalLocal();
+ self::testNullableInitializedFinalLocal();
+ self::testNonNullableInitializedFinalLocal();
+}
+static method testNullableUninitializedNonFinalLocal() → void {
+ lowered core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
+ function #x#set(core::int? #t2) → dynamic
+ return #x = #t2;
+ #x#set(42){(core::int?) → dynamic};
+ core::print(#x#get(){() → core::int?});
+}
+static method testNonNullableUninitializedNonFinalLocal() → void {
+ lowered core::int? #x = _in::createSentinel<core::int>();
+ function #x#get() → core::int
+ return let final core::int? #t3 = #x in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
+ function #x#set(core::int #t4) → dynamic
+ return #x = #t4;
+ #x#set(42){(core::int) → dynamic};
+ core::print(#x#get(){() → core::int});
+}
+static method testNullableUninitializedFinalLocal() → void {
+ lowered final core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
+ function #x#set(core::int? #t6) → dynamic
+ if(_in::isSentinel(#x))
+ return #x = #t6;
+ else
+ throw new _in::LateError::localAI("x");
+ #x#set(42){(core::int?) → dynamic};
+ core::print(#x#get(){() → core::int?});
+}
+static method testNonNullableUninitializedFinalLocal() → void {
+ lowered final core::int? #x = _in::createSentinel<core::int>();
+ function #x#get() → core::int
+ return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
+ function #x#set(core::int #t8) → dynamic
+ if(_in::isSentinel(#x))
+ return #x = #t8;
+ else
+ throw new _in::LateError::localAI("x");
+ #x#set(42){(core::int) → dynamic};
+ core::print(#x#get(){() → core::int});
+}
+static method testNullableInitializedNonFinalLocal() → void {
+ lowered core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
+ function #x#set(core::int? #t10) → dynamic
+ return #x = #t10;
+ core::print(#x#get(){() → core::int?});
+ #x#set(42){(core::int?) → dynamic};
+ core::print(#x#get(){() → core::int?});
+ lowered core::int? #y = _in::createSentinel<core::int?>();
+ function #y#get() → core::int?
+ return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
+ function #y#set(core::int? #t12) → dynamic
+ return #y = #t12;
+ core::print(#y#get(){() → core::int?});
+ #y#set(42){(core::int?) → dynamic};
+ core::print(#y#get(){() → core::int?});
+}
+static method testNonNullableInitializedNonFinalLocal() → void {
+ lowered core::int? #x = _in::createSentinel<core::int>();
+ function #x#get() → core::int
+ return let final core::int? #t13 = #x in _in::isSentinel(#t13) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
+ function #x#set(core::int #t14) → dynamic
+ return #x = #t14;
+ core::print(#x#get(){() → core::int});
+ #x#set(42){(core::int) → dynamic};
+ core::print(#x#get(){() → core::int});
+}
+static method testNullableInitializedFinalLocal() → void {
+ lowered final core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
+ core::print(#x#get(){() → core::int?});
+ lowered final core::int? #y = _in::createSentinel<core::int?>();
+ function #y#get() → core::int?
+ return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
+ core::print(#y#get(){() → core::int?});
+}
+static method testNonNullableInitializedFinalLocal() → void {
+ lowered final core::int? #x = _in::createSentinel<core::int>();
+ function #x#get() → core::int
+ return let final core::int #t19 = #x in _in::isSentinel(#t19) ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19;
+ core::print(#x#get(){() → core::int});
+}
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.outline.expect
new file mode 100644
index 0000000..99217cb
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.outline.expect
@@ -0,0 +1,21 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method main() → void
+ ;
+static method testNullableUninitializedNonFinalLocal() → void
+ ;
+static method testNonNullableUninitializedNonFinalLocal() → void
+ ;
+static method testNullableUninitializedFinalLocal() → void
+ ;
+static method testNonNullableUninitializedFinalLocal() → void
+ ;
+static method testNullableInitializedNonFinalLocal() → void
+ ;
+static method testNonNullableInitializedNonFinalLocal() → void
+ ;
+static method testNullableInitializedFinalLocal() → void
+ ;
+static method testNonNullableInitializedFinalLocal() → void
+ ;
diff --git a/pkg/front_end/testcases/dart2js/late_locals.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.transformed.expect
new file mode 100644
index 0000000..640d4d4
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_locals.dart.weak.transformed.expect
@@ -0,0 +1,112 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+static method main() → void {
+ self::testNullableUninitializedNonFinalLocal();
+ self::testNonNullableUninitializedNonFinalLocal();
+ self::testNullableUninitializedFinalLocal();
+ self::testNonNullableUninitializedFinalLocal();
+ self::testNullableInitializedNonFinalLocal();
+ self::testNonNullableInitializedNonFinalLocal();
+ self::testNullableInitializedFinalLocal();
+ self::testNonNullableInitializedFinalLocal();
+}
+static method testNullableUninitializedNonFinalLocal() → void {
+ lowered core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t1 = #x in _in::isSentinel(#t1) ?{core::int?} throw new _in::LateError::localNI("x") : #t1{core::int?};
+ function #x#set(core::int? #t2) → dynamic
+ return #x = #t2;
+ #x#set(42){(core::int?) → dynamic};
+ core::print(#x#get(){() → core::int?});
+}
+static method testNonNullableUninitializedNonFinalLocal() → void {
+ lowered core::int? #x = _in::createSentinel<core::int>();
+ function #x#get() → core::int
+ return let final core::int? #t3 = #x in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::localNI("x") : #t3{core::int};
+ function #x#set(core::int #t4) → dynamic
+ return #x = #t4;
+ #x#set(42){(core::int) → dynamic};
+ core::print(#x#get(){() → core::int});
+}
+static method testNullableUninitializedFinalLocal() → void {
+ lowered final core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t5 = #x in _in::isSentinel(#t5) ?{core::int?} throw new _in::LateError::localNI("x") : #t5{core::int?};
+ function #x#set(core::int? #t6) → dynamic
+ if(_in::isSentinel(#x))
+ return #x = #t6;
+ else
+ throw new _in::LateError::localAI("x");
+ #x#set(42){(core::int?) → dynamic};
+ core::print(#x#get(){() → core::int?});
+}
+static method testNonNullableUninitializedFinalLocal() → void {
+ lowered final core::int? #x = _in::createSentinel<core::int>();
+ function #x#get() → core::int
+ return let final core::int? #t7 = #x in _in::isSentinel(#t7) ?{core::int} throw new _in::LateError::localNI("x") : #t7{core::int};
+ function #x#set(core::int #t8) → dynamic
+ if(_in::isSentinel(#x))
+ return #x = #t8;
+ else
+ throw new _in::LateError::localAI("x");
+ #x#set(42){(core::int) → dynamic};
+ core::print(#x#get(){() → core::int});
+}
+static method testNullableInitializedNonFinalLocal() → void {
+ lowered core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t9 = #x in _in::isSentinel(#t9) ?{core::int?} #x = 1.{core::int::unary-}(){() → core::int} : #t9{core::int?};
+ function #x#set(core::int? #t10) → dynamic
+ return #x = #t10;
+ core::print(#x#get(){() → core::int?});
+ #x#set(42){(core::int?) → dynamic};
+ core::print(#x#get(){() → core::int?});
+ lowered core::int? #y = _in::createSentinel<core::int?>();
+ function #y#get() → core::int?
+ return let final core::int? #t11 = #y in _in::isSentinel(#t11) ?{core::int?} #y = null : #t11{core::int?};
+ function #y#set(core::int? #t12) → dynamic
+ return #y = #t12;
+ core::print(#y#get(){() → core::int?});
+ #y#set(42){(core::int?) → dynamic};
+ core::print(#y#get(){() → core::int?});
+}
+static method testNonNullableInitializedNonFinalLocal() → void {
+ lowered core::int? #x = _in::createSentinel<core::int>();
+ function #x#get() → core::int
+ return let final core::int? #t13 = #x in _in::isSentinel(#t13) ?{core::int} #x = 1.{core::int::unary-}(){() → core::int} : #t13{core::int};
+ function #x#set(core::int #t14) → dynamic
+ return #x = #t14;
+ core::print(#x#get(){() → core::int});
+ #x#set(42){(core::int) → dynamic};
+ core::print(#x#get(){() → core::int});
+}
+static method testNullableInitializedFinalLocal() → void {
+ lowered final core::int? #x = _in::createSentinel<core::int?>();
+ function #x#get() → core::int?
+ return let final core::int? #t15 = #x in _in::isSentinel(#t15) ?{core::int?} let final core::int? #t16 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int?} #x = #t16 : throw new _in::LateError::localADI("x") : #t15;
+ core::print(#x#get(){() → core::int?});
+ lowered final core::int? #y = _in::createSentinel<core::int?>();
+ function #y#get() → core::int?
+ return let final core::int? #t17 = #y in _in::isSentinel(#t17) ?{core::int?} let final core::int? #t18 = null in _in::isSentinel(#y) ?{core::int?} #y = #t18 : throw new _in::LateError::localADI("y") : #t17;
+ core::print(#y#get(){() → core::int?});
+}
+static method testNonNullableInitializedFinalLocal() → void {
+ lowered final core::int? #x = _in::createSentinel<core::int>();
+ function #x#get() → core::int
+ return let final core::int #t19 = #x in _in::isSentinel(#t19) ?{core::int} let final core::int #t20 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(#x) ?{core::int} #x = #t20 : throw new _in::LateError::localADI("x") : #t19;
+ core::print(#x#get(){() → core::int});
+}
+
+
+Extra constant evaluation status:
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:41:17 -> DoubleConstant(-1.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:53:16 -> DoubleConstant(-1.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:60:23 -> DoubleConstant(-1.0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:60:19 -> DoubleConstant(-1.0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:63:19 -> NullConstant(null)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_locals.dart:68:22 -> DoubleConstant(-1.0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_locals.dart:68:18 -> DoubleConstant(-1.0)
+Extra constant evaluation: evaluated: 172, effectively constant: 7
diff --git a/pkg/front_end/testcases/dart2js/late_statics.dart b/pkg/front_end/testcases/dart2js/late_statics.dart
new file mode 100644
index 0000000..1030ef4
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_statics.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2021, 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.
+
+void main() {
+ testUninitializedNonFinalStaticField();
+ testUninitializedFinalStaticField();
+ testInitializedNonFinalStaticField();
+ testInitializedFinalStaticField();
+}
+
+class Statics {
+ static late int a;
+ static late final int b;
+ static late int c = -1;
+ static late final int d = -1;
+}
+
+void testUninitializedNonFinalStaticField() {
+ print(Statics.a);
+ Statics.a = 42;
+ print(Statics.a);
+}
+
+void testUninitializedFinalStaticField() {
+ print(Statics.b);
+ Statics.b = 42;
+ print(Statics.b);
+}
+
+void testInitializedNonFinalStaticField() {
+ print(Statics.c);
+ Statics.c = 42;
+ print(Statics.c);
+}
+
+void testInitializedFinalStaticField() {
+ print(Statics.d);
+}
diff --git a/pkg/front_end/testcases/dart2js/late_statics.dart.strong.expect b/pkg/front_end/testcases/dart2js/late_statics.dart.strong.expect
new file mode 100644
index 0000000..f41ebf9
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_statics.dart.strong.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Statics extends core::Object {
+ static field core::int? _#a = null;
+ static field core::int? _#b = null;
+ static field core::int? _#c = null;
+ static field core::int? _#d = null;
+ synthetic constructor •() → self::Statics
+ : super core::Object::•()
+ ;
+ static get a() → core::int
+ return let final core::int? #t1 = self::Statics::_#a in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("a") : #t1{core::int};
+ static set a(core::int #t2) → void
+ self::Statics::_#a = #t2;
+ static get b() → core::int
+ return let final core::int? #t3 = self::Statics::_#b in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("b") : #t3{core::int};
+ static set b(core::int #t4) → void
+ if(self::Statics::_#b == null)
+ self::Statics::_#b = #t4;
+ else
+ throw new _in::LateError::fieldAI("b");
+ static get c() → core::int
+ return let final core::int? #t5 = self::Statics::_#c in #t5 == null ?{core::int} self::Statics::_#c = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+ static set c(core::int #t6) → void
+ self::Statics::_#c = #t6;
+ static get d() → core::int
+ return let final core::int? #t7 = self::Statics::_#d in #t7 == null ?{core::int} let final core::int #t8 = 1.{core::int::unary-}(){() → core::int} in self::Statics::_#d == null ?{core::int} self::Statics::_#d = #t8 : throw new _in::LateError::fieldADI("d") : #t7{core::int};
+}
+static method main() → void {
+ self::testUninitializedNonFinalStaticField();
+ self::testUninitializedFinalStaticField();
+ self::testInitializedNonFinalStaticField();
+ self::testInitializedFinalStaticField();
+}
+static method testUninitializedNonFinalStaticField() → void {
+ core::print(self::Statics::a);
+ self::Statics::a = 42;
+ core::print(self::Statics::a);
+}
+static method testUninitializedFinalStaticField() → void {
+ core::print(self::Statics::b);
+ self::Statics::b = 42;
+ core::print(self::Statics::b);
+}
+static method testInitializedNonFinalStaticField() → void {
+ core::print(self::Statics::c);
+ self::Statics::c = 42;
+ core::print(self::Statics::c);
+}
+static method testInitializedFinalStaticField() → void {
+ core::print(self::Statics::d);
+}
diff --git a/pkg/front_end/testcases/dart2js/late_statics.dart.strong.transformed.expect b/pkg/front_end/testcases/dart2js/late_statics.dart.strong.transformed.expect
new file mode 100644
index 0000000..1a4e13b
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_statics.dart.strong.transformed.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Statics extends core::Object {
+ static field core::int? _#a = null;
+ static field core::int? _#b = null;
+ static field core::int? _#c = null;
+ static field core::int? _#d = null;
+ synthetic constructor •() → self::Statics
+ : super core::Object::•()
+ ;
+ static get a() → core::int
+ return let final core::int? #t1 = self::Statics::_#a in #t1 == null ?{core::int} throw new _in::LateError::fieldNI("a") : #t1{core::int};
+ static set a(core::int #t2) → void
+ self::Statics::_#a = #t2;
+ static get b() → core::int
+ return let final core::int? #t3 = self::Statics::_#b in #t3 == null ?{core::int} throw new _in::LateError::fieldNI("b") : #t3{core::int};
+ static set b(core::int #t4) → void
+ if(self::Statics::_#b == null)
+ self::Statics::_#b = #t4;
+ else
+ throw new _in::LateError::fieldAI("b");
+ static get c() → core::int
+ return let final core::int? #t5 = self::Statics::_#c in #t5 == null ?{core::int} self::Statics::_#c = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+ static set c(core::int #t6) → void
+ self::Statics::_#c = #t6;
+ static get d() → core::int
+ return let final core::int? #t7 = self::Statics::_#d in #t7 == null ?{core::int} let final core::int #t8 = 1.{core::int::unary-}(){() → core::int} in self::Statics::_#d == null ?{core::int} self::Statics::_#d = #t8 : throw new _in::LateError::fieldADI("d") : #t7{core::int};
+}
+static method main() → void {
+ self::testUninitializedNonFinalStaticField();
+ self::testUninitializedFinalStaticField();
+ self::testInitializedNonFinalStaticField();
+ self::testInitializedFinalStaticField();
+}
+static method testUninitializedNonFinalStaticField() → void {
+ core::print(self::Statics::a);
+ self::Statics::a = 42;
+ core::print(self::Statics::a);
+}
+static method testUninitializedFinalStaticField() → void {
+ core::print(self::Statics::b);
+ self::Statics::b = 42;
+ core::print(self::Statics::b);
+}
+static method testInitializedNonFinalStaticField() → void {
+ core::print(self::Statics::c);
+ self::Statics::c = 42;
+ core::print(self::Statics::c);
+}
+static method testInitializedFinalStaticField() → void {
+ core::print(self::Statics::d);
+}
+
+
+Extra constant evaluation status:
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_statics.dart:15:23 -> DoubleConstant(-1.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_statics.dart:16:29 -> DoubleConstant(-1.0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_statics.dart:16:25 -> DoubleConstant(-1.0)
+Extra constant evaluation: evaluated: 70, effectively constant: 3
diff --git a/pkg/front_end/testcases/dart2js/late_statics.dart.textual_outline.expect b/pkg/front_end/testcases/dart2js/late_statics.dart.textual_outline.expect
new file mode 100644
index 0000000..c9f0b3d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_statics.dart.textual_outline.expect
@@ -0,0 +1,15 @@
+void main() {}
+class Statics {
+ static late int ;
+ a;
+ static late ;
+ final int b;
+ static late int ;
+ c = -1;
+ static late ;
+ final int d = -1;
+}
+void testUninitializedNonFinalStaticField() {}
+void testUninitializedFinalStaticField() {}
+void testInitializedNonFinalStaticField() {}
+void testInitializedFinalStaticField() {}
diff --git a/pkg/front_end/testcases/dart2js/late_statics.dart.weak.expect b/pkg/front_end/testcases/dart2js/late_statics.dart.weak.expect
new file mode 100644
index 0000000..fb7425e
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_statics.dart.weak.expect
@@ -0,0 +1,55 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Statics extends core::Object {
+ static field core::int? _#a = _in::createSentinel<core::int>();
+ static field core::int? _#b = _in::createSentinel<core::int>();
+ static field core::int? _#c = _in::createSentinel<core::int>();
+ static field core::int? _#d = _in::createSentinel<core::int>();
+ synthetic constructor •() → self::Statics
+ : super core::Object::•()
+ ;
+ static get a() → core::int
+ return let final core::int? #t1 = self::Statics::_#a in _in::isSentinel(#t1) ?{core::int} throw new _in::LateError::fieldNI("a") : #t1{core::int};
+ static set a(core::int #t2) → void
+ self::Statics::_#a = #t2;
+ static get b() → core::int
+ return let final core::int? #t3 = self::Statics::_#b in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::fieldNI("b") : #t3{core::int};
+ static set b(core::int #t4) → void
+ if(_in::isSentinel(self::Statics::_#b))
+ self::Statics::_#b = #t4;
+ else
+ throw new _in::LateError::fieldAI("b");
+ static get c() → core::int
+ return let final core::int? #t5 = self::Statics::_#c in _in::isSentinel(#t5) ?{core::int} self::Statics::_#c = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+ static set c(core::int #t6) → void
+ self::Statics::_#c = #t6;
+ static get d() → core::int
+ return let final core::int #t7 = self::Statics::_#d in _in::isSentinel(#t7) ?{core::int} let final core::int #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(self::Statics::_#d) ?{core::int} self::Statics::_#d = #t8 : throw new _in::LateError::fieldADI("d") : #t7;
+}
+static method main() → void {
+ self::testUninitializedNonFinalStaticField();
+ self::testUninitializedFinalStaticField();
+ self::testInitializedNonFinalStaticField();
+ self::testInitializedFinalStaticField();
+}
+static method testUninitializedNonFinalStaticField() → void {
+ core::print(self::Statics::a);
+ self::Statics::a = 42;
+ core::print(self::Statics::a);
+}
+static method testUninitializedFinalStaticField() → void {
+ core::print(self::Statics::b);
+ self::Statics::b = 42;
+ core::print(self::Statics::b);
+}
+static method testInitializedNonFinalStaticField() → void {
+ core::print(self::Statics::c);
+ self::Statics::c = 42;
+ core::print(self::Statics::c);
+}
+static method testInitializedFinalStaticField() → void {
+ core::print(self::Statics::d);
+}
diff --git a/pkg/front_end/testcases/dart2js/late_statics.dart.weak.outline.expect b/pkg/front_end/testcases/dart2js/late_statics.dart.weak.outline.expect
new file mode 100644
index 0000000..7f9136d
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_statics.dart.weak.outline.expect
@@ -0,0 +1,29 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+
+class Statics extends core::Object {
+ static field core::int? _#a;
+ static field core::int? _#b;
+ static field core::int? _#c;
+ static field core::int? _#d;
+ synthetic constructor •() → self::Statics
+ ;
+ static get a() → core::int;
+ static set a(core::int #t1) → void;
+ static get b() → core::int;
+ static set b(core::int #t2) → void;
+ static get c() → core::int;
+ static set c(core::int #t3) → void;
+ static get d() → core::int;
+}
+static method main() → void
+ ;
+static method testUninitializedNonFinalStaticField() → void
+ ;
+static method testUninitializedFinalStaticField() → void
+ ;
+static method testInitializedNonFinalStaticField() → void
+ ;
+static method testInitializedFinalStaticField() → void
+ ;
diff --git a/pkg/front_end/testcases/dart2js/late_statics.dart.weak.transformed.expect b/pkg/front_end/testcases/dart2js/late_statics.dart.weak.transformed.expect
new file mode 100644
index 0000000..68a4534
--- /dev/null
+++ b/pkg/front_end/testcases/dart2js/late_statics.dart.weak.transformed.expect
@@ -0,0 +1,62 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+import "dart:core" as core;
+import "dart:_internal" as _in;
+
+class Statics extends core::Object {
+ static field core::int? _#a = _in::createSentinel<core::int>();
+ static field core::int? _#b = _in::createSentinel<core::int>();
+ static field core::int? _#c = _in::createSentinel<core::int>();
+ static field core::int? _#d = _in::createSentinel<core::int>();
+ synthetic constructor •() → self::Statics
+ : super core::Object::•()
+ ;
+ static get a() → core::int
+ return let final core::int? #t1 = self::Statics::_#a in _in::isSentinel(#t1) ?{core::int} throw new _in::LateError::fieldNI("a") : #t1{core::int};
+ static set a(core::int #t2) → void
+ self::Statics::_#a = #t2;
+ static get b() → core::int
+ return let final core::int? #t3 = self::Statics::_#b in _in::isSentinel(#t3) ?{core::int} throw new _in::LateError::fieldNI("b") : #t3{core::int};
+ static set b(core::int #t4) → void
+ if(_in::isSentinel(self::Statics::_#b))
+ self::Statics::_#b = #t4;
+ else
+ throw new _in::LateError::fieldAI("b");
+ static get c() → core::int
+ return let final core::int? #t5 = self::Statics::_#c in _in::isSentinel(#t5) ?{core::int} self::Statics::_#c = 1.{core::int::unary-}(){() → core::int} : #t5{core::int};
+ static set c(core::int #t6) → void
+ self::Statics::_#c = #t6;
+ static get d() → core::int
+ return let final core::int #t7 = self::Statics::_#d in _in::isSentinel(#t7) ?{core::int} let final core::int #t8 = 1.{core::int::unary-}(){() → core::int} in _in::isSentinel(self::Statics::_#d) ?{core::int} self::Statics::_#d = #t8 : throw new _in::LateError::fieldADI("d") : #t7;
+}
+static method main() → void {
+ self::testUninitializedNonFinalStaticField();
+ self::testUninitializedFinalStaticField();
+ self::testInitializedNonFinalStaticField();
+ self::testInitializedFinalStaticField();
+}
+static method testUninitializedNonFinalStaticField() → void {
+ core::print(self::Statics::a);
+ self::Statics::a = 42;
+ core::print(self::Statics::a);
+}
+static method testUninitializedFinalStaticField() → void {
+ core::print(self::Statics::b);
+ self::Statics::b = 42;
+ core::print(self::Statics::b);
+}
+static method testInitializedNonFinalStaticField() → void {
+ core::print(self::Statics::c);
+ self::Statics::c = 42;
+ core::print(self::Statics::c);
+}
+static method testInitializedFinalStaticField() → void {
+ core::print(self::Statics::d);
+}
+
+
+Extra constant evaluation status:
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_statics.dart:15:23 -> DoubleConstant(-1.0)
+Evaluated: InstanceInvocation @ org-dartlang-testcase:///late_statics.dart:16:29 -> DoubleConstant(-1.0)
+Evaluated: VariableGet @ org-dartlang-testcase:///late_statics.dart:16:25 -> DoubleConstant(-1.0)
+Extra constant evaluation: evaluated: 74, effectively constant: 3
diff --git a/runtime/bin/builtin_impl_sources.gni b/runtime/bin/builtin_impl_sources.gni
index 1045fdc..d1f7d95 100644
--- a/runtime/bin/builtin_impl_sources.gni
+++ b/runtime/bin/builtin_impl_sources.gni
@@ -62,6 +62,7 @@
"thread_macos.h",
"thread_win.cc",
"thread_win.h",
+ "utils.cc",
"utils.h",
"utils_android.cc",
"utils_fuchsia.cc",
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index 9730817..ed0c781 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -89,6 +89,7 @@
V(Namespace_GetDefault, 0) \
V(Namespace_GetPointer, 1) \
V(NetworkInterface_ListSupported, 0) \
+ V(OSError_inProgressErrorCode, 0) \
V(Platform_NumberOfProcessors, 0) \
V(Platform_OperatingSystem, 0) \
V(Platform_OperatingSystemVersion, 0) \
diff --git a/runtime/bin/utils.cc b/runtime/bin/utils.cc
new file mode 100644
index 0000000..3182185
--- /dev/null
+++ b/runtime/bin/utils.cc
@@ -0,0 +1,25 @@
+// Copyright (c) 2021, 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.
+
+#include "bin/utils.h"
+
+#include <errno.h> // NOLINT
+
+#include "bin/builtin.h"
+#include "bin/dartutils.h"
+
+#include "include/dart_api.h"
+
+#include "platform/globals.h"
+#include "platform/utils.h"
+
+namespace dart {
+namespace bin {
+
+void FUNCTION_NAME(OSError_inProgressErrorCode)(Dart_NativeArguments args) {
+ Dart_SetIntegerReturnValue(args, EINPROGRESS);
+}
+
+} // namespace bin
+} // namespace dart
diff --git a/runtime/observatory/lib/src/elements/class_instances.dart b/runtime/observatory/lib/src/elements/class_instances.dart
index abf90cc..8d12e21 100644
--- a/runtime/observatory/lib/src/elements/class_instances.dart
+++ b/runtime/observatory/lib/src/elements/class_instances.dart
@@ -6,6 +6,7 @@
import 'dart:async';
import 'package:observatory/models.dart' as M;
import 'package:observatory/src/elements/class_ref.dart';
+import 'package:observatory/src/elements/helpers/any_ref.dart';
import 'package:observatory/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory/src/elements/helpers/custom_element.dart';
import 'package:observatory/src/elements/inbound_references.dart';
@@ -25,6 +26,12 @@
late M.ReachableSizeRepository _reachableSizes;
late M.StronglyReachableInstancesRepository _stronglyReachableInstances;
late M.ObjectRepository _objects;
+ M.Guarded<M.InstanceRef>? _allInstances = null;
+ bool _loadingAllInstances = false;
+ M.Guarded<M.InstanceRef>? _allSubclassInstances = null;
+ bool _loadingAllSubclassInstances = false;
+ M.Guarded<M.InstanceRef>? _allImplementorInstances = null;
+ bool _loadingAllImplementorInstances = false;
M.Guarded<M.Instance>? _retainedSize = null;
bool _loadingRetainedBytes = false;
M.Guarded<M.Instance>? _reachableSize = null;
@@ -108,6 +115,41 @@
],
new DivElement()
..classes = ['memberItem']
+ ..children = <Element>[
+ new DivElement()
+ ..classes = ['memberName']
+ ..text = 'all direct instances'
+ ..title = 'All instances whose class is exactly this class',
+ new DivElement()
+ ..classes = ['memberValue']
+ ..children = _createAllInstances()
+ ],
+ new DivElement()
+ ..classes = ['memberItem']
+ ..children = <Element>[
+ new DivElement()
+ ..classes = ['memberName']
+ ..text = 'all instances of subclasses'
+ ..title =
+ 'All instances whose class is a subclass of this class',
+ new DivElement()
+ ..classes = ['memberValue']
+ ..children = _createAllSubclassInstances()
+ ],
+ new DivElement()
+ ..classes = ['memberItem']
+ ..children = <Element>[
+ new DivElement()
+ ..classes = ['memberName']
+ ..text = 'all instances of implementors'
+ ..title =
+ 'All instances whose class implements the implicit interface of this class',
+ new DivElement()
+ ..classes = ['memberValue']
+ ..children = _createAllImplementorInstances()
+ ],
+ new DivElement()
+ ..classes = ['memberItem']
..title = 'Space reachable from this object, '
'excluding class references'
..children = <Element>[
@@ -134,6 +176,96 @@
];
}
+ List<Element> _createAllInstances() {
+ final content = <Element>[];
+ if (_allInstances != null) {
+ if (_allInstances!.isSentinel) {
+ content.add(new SentinelValueElement(_allInstances!.asSentinel!,
+ queue: _r.queue)
+ .element);
+ } else {
+ content.add(anyRef(_isolate, _allInstances!.asValue!, _objects));
+ }
+ } else {
+ content.add(new SpanElement()..text = '...');
+ }
+ final button = new ButtonElement()
+ ..classes = ['reachable_size']
+ ..disabled = _loadingAllInstances
+ ..text = '↺';
+ button.onClick.listen((_) async {
+ button.disabled = true;
+ _loadingAllInstances = true;
+ _allInstances =
+ await _stronglyReachableInstances.getAsArray(_isolate, _cls);
+ _loadingAllInstances = false;
+ _r.dirty();
+ });
+ content.add(button);
+ return content;
+ }
+
+ List<Element> _createAllSubclassInstances() {
+ final content = <Element>[];
+ if (_allSubclassInstances != null) {
+ if (_allSubclassInstances!.isSentinel) {
+ content.add(new SentinelValueElement(_allSubclassInstances!.asSentinel!,
+ queue: _r.queue)
+ .element);
+ } else {
+ content
+ .add(anyRef(_isolate, _allSubclassInstances!.asValue!, _objects));
+ }
+ } else {
+ content.add(new SpanElement()..text = '...');
+ }
+ final button = new ButtonElement()
+ ..classes = ['reachable_size']
+ ..disabled = _loadingAllSubclassInstances
+ ..text = '↺';
+ button.onClick.listen((_) async {
+ button.disabled = true;
+ _loadingAllSubclassInstances = true;
+ _allSubclassInstances = await _stronglyReachableInstances
+ .getAsArray(_isolate, _cls, includeSubclasses: true);
+ _loadingAllSubclassInstances = false;
+ _r.dirty();
+ });
+ content.add(button);
+ return content;
+ }
+
+ List<Element> _createAllImplementorInstances() {
+ final content = <Element>[];
+ if (_allImplementorInstances != null) {
+ if (_allImplementorInstances!.isSentinel) {
+ content.add(new SentinelValueElement(
+ _allImplementorInstances!.asSentinel!,
+ queue: _r.queue)
+ .element);
+ } else {
+ content.add(
+ anyRef(_isolate, _allImplementorInstances!.asValue!, _objects));
+ }
+ } else {
+ content.add(new SpanElement()..text = '...');
+ }
+ final button = new ButtonElement()
+ ..classes = ['reachable_size']
+ ..disabled = _loadingAllImplementorInstances
+ ..text = '↺';
+ button.onClick.listen((_) async {
+ button.disabled = true;
+ _loadingAllImplementorInstances = true;
+ _allImplementorInstances = await _stronglyReachableInstances
+ .getAsArray(_isolate, _cls, includeImplementors: true);
+ _loadingAllImplementorInstances = false;
+ _r.dirty();
+ });
+ content.add(button);
+ return content;
+ }
+
List<Element> _createReachableSizeValue() {
final content = <Element>[];
if (_reachableSize != null) {
@@ -157,6 +289,7 @@
button.disabled = true;
_loadingReachableBytes = true;
_reachableSize = await _reachableSizes.get(_isolate, _cls.id!);
+ _loadingReachableBytes = false;
_r.dirty();
});
content.add(button);
@@ -186,6 +319,7 @@
button.disabled = true;
_loadingRetainedBytes = true;
_retainedSize = await _retainedSizes.get(_isolate, _cls.id!);
+ _loadingRetainedBytes = false;
_r.dirty();
});
content.add(button);
diff --git a/runtime/observatory/lib/src/models/repositories/strongly_reachable_instances.dart b/runtime/observatory/lib/src/models/repositories/strongly_reachable_instances.dart
index c0449f8..195948a 100644
--- a/runtime/observatory/lib/src/models/repositories/strongly_reachable_instances.dart
+++ b/runtime/observatory/lib/src/models/repositories/strongly_reachable_instances.dart
@@ -6,4 +6,6 @@
abstract class StronglyReachableInstancesRepository {
Future<InstanceSet> get(IsolateRef isolate, ClassRef cls, {int limit: 100});
+ Future<Guarded<InstanceRef>> getAsArray(IsolateRef isolate, ClassRef cls,
+ {bool includeSubclasses: false, includeImplementors: false});
}
diff --git a/runtime/observatory/lib/src/repositories/strongly_reachable_instances.dart b/runtime/observatory/lib/src/repositories/strongly_reachable_instances.dart
index a015928..f4ed736 100644
--- a/runtime/observatory/lib/src/repositories/strongly_reachable_instances.dart
+++ b/runtime/observatory/lib/src/repositories/strongly_reachable_instances.dart
@@ -15,4 +15,18 @@
assert(limit != null);
return (await isolate.getInstances(cls, limit)) as S.InstanceSet;
}
+
+ Future<M.Guarded<M.InstanceRef>> getAsArray(M.IsolateRef i, M.ClassRef c,
+ {bool includeSubclasses: false, includeImplementors: false}) async {
+ S.Isolate isolate = i as S.Isolate;
+ S.Class cls = c as S.Class;
+ assert(isolate != null);
+ assert(cls != null);
+ final response = await isolate.invokeRpc('_getInstancesAsArray', {
+ 'objectId': cls.id,
+ 'includeSubclasses': includeSubclasses,
+ 'includeImplementors': includeImplementors
+ });
+ return new S.Guarded<S.Instance>(response);
+ }
}
diff --git a/runtime/observatory/tests/service/get_instances_as_array_rpc_test.dart b/runtime/observatory/tests/service/get_instances_as_array_rpc_test.dart
new file mode 100644
index 0000000..1981ec9c
--- /dev/null
+++ b/runtime/observatory/tests/service/get_instances_as_array_rpc_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2020, 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:observatory/service_io.dart";
+import "package:test/test.dart";
+
+import "test_helper.dart";
+
+@pragma("vm:entry-point")
+class Class {}
+
+@pragma("vm:entry-point")
+class Subclass extends Class {}
+
+@pragma("vm:entry-point")
+class Implementor implements Class {}
+
+@pragma("vm:entry-point")
+var aClass;
+@pragma("vm:entry-point")
+var aSubclass;
+@pragma("vm:entry-point")
+var anImplementor;
+
+@pragma("vm:entry-point")
+allocate() {
+ aClass = new Class();
+ aSubclass = new Subclass();
+ anImplementor = new Implementor();
+}
+
+var tests = <IsolateTest>[
+ (Isolate isolate) async {
+ invoke(String selector) async {
+ Map params = {
+ "targetId": isolate.rootLibrary.id,
+ "selector": selector,
+ "argumentIds": <String>[],
+ };
+ return await isolate.invokeRpcNoUpgrade("invoke", params);
+ }
+
+ Future<int> instanceCount(String className,
+ {bool includeSubclasses: false,
+ bool includeImplementors: false}) async {
+ Map params = {
+ "objectId": isolate.rootLibrary.classes
+ .singleWhere((cls) => cls.name == className)
+ .id,
+ "includeSubclasses": includeSubclasses,
+ "includeImplementors": includeImplementors,
+ };
+ var result =
+ await isolate.invokeRpcNoUpgrade("_getInstancesAsArray", params);
+ expect(result["type"], equals("@Instance"));
+ expect(result["kind"], equals("List"));
+ return result["length"] as int;
+ }
+
+ await isolate.rootLibrary.load();
+
+ expect(await instanceCount("Class"), equals(0));
+ expect(await instanceCount("Class", includeSubclasses: true), equals(0));
+ expect(await instanceCount("Class", includeImplementors: true), equals(0));
+
+ await invoke("allocate");
+
+ expect(await instanceCount("Class"), equals(1));
+ expect(await instanceCount("Class", includeSubclasses: true), equals(2));
+ expect(await instanceCount("Class", includeImplementors: true), equals(3));
+ },
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/observatory_2/lib/src/elements/class_instances.dart b/runtime/observatory_2/lib/src/elements/class_instances.dart
index bc3e101..7197780 100644
--- a/runtime/observatory_2/lib/src/elements/class_instances.dart
+++ b/runtime/observatory_2/lib/src/elements/class_instances.dart
@@ -6,6 +6,7 @@
import 'dart:async';
import 'package:observatory_2/models.dart' as M;
import 'package:observatory_2/src/elements/class_ref.dart';
+import 'package:observatory_2/src/elements/helpers/any_ref.dart';
import 'package:observatory_2/src/elements/helpers/rendering_scheduler.dart';
import 'package:observatory_2/src/elements/helpers/custom_element.dart';
import 'package:observatory_2/src/elements/inbound_references.dart';
@@ -25,6 +26,12 @@
M.ReachableSizeRepository _reachableSizes;
M.StronglyReachableInstancesRepository _stronglyReachableInstances;
M.ObjectRepository _objects;
+ M.Guarded<M.InstanceRef> _allInstances = null;
+ bool _loadingAllInstances = false;
+ M.Guarded<M.InstanceRef> _allSubclassInstances = null;
+ bool _loadingAllSubclassInstances = false;
+ M.Guarded<M.InstanceRef> _allImplementorInstances = null;
+ bool _loadingAllImplementorInstances = false;
M.Guarded<M.Instance> _retainedSize = null;
bool _loadingRetainedBytes = false;
M.Guarded<M.Instance> _reachableSize = null;
@@ -108,6 +115,41 @@
],
new DivElement()
..classes = ['memberItem']
+ ..children = <Element>[
+ new DivElement()
+ ..classes = ['memberName']
+ ..text = 'all direct instances'
+ ..title = 'All instances whose class is exactly this class',
+ new DivElement()
+ ..classes = ['memberValue']
+ ..children = _createAllInstances()
+ ],
+ new DivElement()
+ ..classes = ['memberItem']
+ ..children = <Element>[
+ new DivElement()
+ ..classes = ['memberName']
+ ..text = 'all instances of subclasses'
+ ..title =
+ 'All instances whose class is a subclass of this class',
+ new DivElement()
+ ..classes = ['memberValue']
+ ..children = _createAllSubclassInstances()
+ ],
+ new DivElement()
+ ..classes = ['memberItem']
+ ..children = <Element>[
+ new DivElement()
+ ..classes = ['memberName']
+ ..text = 'all instances of implementors'
+ ..title =
+ 'All instances whose class implements the implicit interface of this class',
+ new DivElement()
+ ..classes = ['memberValue']
+ ..children = _createAllImplementorInstances()
+ ],
+ new DivElement()
+ ..classes = ['memberItem']
..title = 'Space reachable from this object, '
'excluding class references'
..children = <Element>[
@@ -134,6 +176,95 @@
];
}
+ List<Element> _createAllInstances() {
+ final content = <Element>[];
+ if (_allInstances != null) {
+ if (_allInstances.isSentinel) {
+ content.add(
+ new SentinelValueElement(_allInstances.asSentinel, queue: _r.queue)
+ .element);
+ } else {
+ content.add(anyRef(_isolate, _allInstances.asValue, _objects));
+ }
+ } else {
+ content.add(new SpanElement()..text = '...');
+ }
+ final button = new ButtonElement()
+ ..classes = ['reachable_size']
+ ..disabled = _loadingAllInstances
+ ..text = '↺';
+ button.onClick.listen((_) async {
+ button.disabled = true;
+ _loadingAllInstances = true;
+ _allInstances =
+ await _stronglyReachableInstances.getAsArray(_isolate, _cls);
+ _loadingAllInstances = false;
+ _r.dirty();
+ });
+ content.add(button);
+ return content;
+ }
+
+ List<Element> _createAllSubclassInstances() {
+ final content = <Element>[];
+ if (_allSubclassInstances != null) {
+ if (_allSubclassInstances.isSentinel) {
+ content.add(new SentinelValueElement(_allSubclassInstances.asSentinel,
+ queue: _r.queue)
+ .element);
+ } else {
+ content.add(anyRef(_isolate, _allSubclassInstances.asValue, _objects));
+ }
+ } else {
+ content.add(new SpanElement()..text = '...');
+ }
+ final button = new ButtonElement()
+ ..classes = ['reachable_size']
+ ..disabled = _loadingAllSubclassInstances
+ ..text = '↺';
+ button.onClick.listen((_) async {
+ button.disabled = true;
+ _loadingAllSubclassInstances = true;
+ _allSubclassInstances = await _stronglyReachableInstances
+ .getAsArray(_isolate, _cls, includeSubclasses: true);
+ _loadingAllSubclassInstances = false;
+ _r.dirty();
+ });
+ content.add(button);
+ return content;
+ }
+
+ List<Element> _createAllImplementorInstances() {
+ final content = <Element>[];
+ if (_allImplementorInstances != null) {
+ if (_allImplementorInstances.isSentinel) {
+ content.add(new SentinelValueElement(
+ _allImplementorInstances.asSentinel,
+ queue: _r.queue)
+ .element);
+ } else {
+ content
+ .add(anyRef(_isolate, _allImplementorInstances.asValue, _objects));
+ }
+ } else {
+ content.add(new SpanElement()..text = '...');
+ }
+ final button = new ButtonElement()
+ ..classes = ['reachable_size']
+ ..disabled = _loadingAllImplementorInstances
+ ..text = '↺';
+ button.onClick.listen((_) async {
+ button.disabled = true;
+ _loadingAllImplementorInstances = true;
+ _allImplementorInstances = await _stronglyReachableInstances
+ .getAsArray(_isolate, _cls, includeImplementors: true);
+ _loadingAllImplementorInstances = false;
+ _r.dirty();
+ });
+ content.add(button);
+ return content;
+ }
+
List<Element> _createReachableSizeValue() {
final content = <Element>[];
if (_reachableSize != null) {
diff --git a/runtime/observatory_2/lib/src/models/repositories/strongly_reachable_instances.dart b/runtime/observatory_2/lib/src/models/repositories/strongly_reachable_instances.dart
index c0449f8..195948a 100644
--- a/runtime/observatory_2/lib/src/models/repositories/strongly_reachable_instances.dart
+++ b/runtime/observatory_2/lib/src/models/repositories/strongly_reachable_instances.dart
@@ -6,4 +6,6 @@
abstract class StronglyReachableInstancesRepository {
Future<InstanceSet> get(IsolateRef isolate, ClassRef cls, {int limit: 100});
+ Future<Guarded<InstanceRef>> getAsArray(IsolateRef isolate, ClassRef cls,
+ {bool includeSubclasses: false, includeImplementors: false});
}
diff --git a/runtime/observatory_2/lib/src/repositories/strongly_reachable_instances.dart b/runtime/observatory_2/lib/src/repositories/strongly_reachable_instances.dart
index a015928..8083ea7 100644
--- a/runtime/observatory_2/lib/src/repositories/strongly_reachable_instances.dart
+++ b/runtime/observatory_2/lib/src/repositories/strongly_reachable_instances.dart
@@ -15,4 +15,18 @@
assert(limit != null);
return (await isolate.getInstances(cls, limit)) as S.InstanceSet;
}
+
+ Future<M.Guarded<M.InstanceRef>> getAsArray(M.IsolateRef i, M.ClassRef c,
+ {bool includeSubclasses: false, includeImplementors: false}) async {
+ S.Isolate isolate = i as S.Isolate;
+ S.Class cls = c as S.Class;
+ assert(isolate != null);
+ assert(cls != null);
+ final response = await isolate.invokeRpc('_getInstancesAsArray', {
+ 'objectId': cls.id,
+ 'includeSubclasses': includeSubclasses == true,
+ 'includeImplementors': includeImplementors == true,
+ });
+ return new S.Guarded<S.Instance>(response);
+ }
}
diff --git a/runtime/observatory_2/tests/service_2/get_instances_as_array_rpc_test.dart b/runtime/observatory_2/tests/service_2/get_instances_as_array_rpc_test.dart
new file mode 100644
index 0000000..f87d897
--- /dev/null
+++ b/runtime/observatory_2/tests/service_2/get_instances_as_array_rpc_test.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2020, 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:observatory_2/service_io.dart";
+import "package:test/test.dart";
+
+import "test_helper.dart";
+
+class Class {}
+
+class Subclass extends Class {}
+
+class Implementor implements Class {}
+
+@pragma("vm:entry-point")
+var aClass;
+@pragma("vm:entry-point")
+var aSubclass;
+@pragma("vm:entry-point")
+var anImplementor;
+
+@pragma("vm:entry-point")
+allocate() {
+ aClass = new Class();
+ aSubclass = new Subclass();
+ anImplementor = new Implementor();
+}
+
+var tests = <IsolateTest>[
+ (Isolate isolate) async {
+ invoke(String selector) async {
+ Map params = {
+ "targetId": isolate.rootLibrary.id,
+ "selector": selector,
+ "argumentIds": <String>[],
+ };
+ return await isolate.invokeRpcNoUpgrade("invoke", params);
+ }
+
+ Future<int> instanceCount(String className,
+ {bool includeSubclasses: false,
+ bool includeImplementors: false}) async {
+ Map params = {
+ "objectId": isolate.rootLibrary.classes
+ .singleWhere((cls) => cls.name == className)
+ .id,
+ "includeSubclasses": includeSubclasses,
+ "includeImplementors": includeImplementors,
+ };
+ var result =
+ await isolate.invokeRpcNoUpgrade("_getInstancesAsArray", params);
+ expect(result["type"], equals("@Instance"));
+ expect(result["kind"], equals("List"));
+ return result["length"] as int;
+ }
+
+ await isolate.rootLibrary.load();
+
+ expect(await instanceCount("Class"), equals(0));
+ expect(await instanceCount("Class", includeSubclasses: true), equals(0));
+ expect(await instanceCount("Class", includeImplementors: true), equals(0));
+
+ await invoke("allocate");
+
+ expect(await instanceCount("Class"), equals(1));
+ expect(await instanceCount("Class", includeSubclasses: true), equals(2));
+ expect(await instanceCount("Class", includeImplementors: true), equals(3));
+ },
+];
+
+main(args) async => runIsolateTests(args, tests);
diff --git a/runtime/runtime_args.gni b/runtime/runtime_args.gni
index 7e4e9b4..ae564be 100644
--- a/runtime/runtime_args.gni
+++ b/runtime/runtime_args.gni
@@ -75,9 +75,6 @@
# Whether libdart should export the symbols of the Dart API.
dart_lib_export_symbols = true
- # Whether package:wasm should be enabled.
- dart_enable_wasm = false
-
# Whether to use compressed pointers.
dart_use_compressed_pointers = false
}
diff --git a/runtime/tests/vm/dart/isolate_send_regex_test.dart b/runtime/tests/vm/dart/isolate_send_regex_test.dart
new file mode 100644
index 0000000..cac6d09
--- /dev/null
+++ b/runtime/tests/vm/dart/isolate_send_regex_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2021, 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 'package:expect/expect.dart';
+
+f(List args) {
+ final sendPort = args[0] as SendPort;
+ final re = args[1] as RegExp;
+ Expect.stringEquals("RegExp: pattern=abc flags=", re.toString());
+ sendPort.send(true);
+}
+
+main() async {
+ final rpError = RawReceivePort((e) {
+ Expect.fail('Spawned isolated failed with $e');
+ });
+ {
+ // Test sending of initialized RegExp
+ final rp = ReceivePort();
+ final re = RegExp('abc');
+ print(re.hasMatch('kukabcdef'));
+ await Isolate.spawn(f, <dynamic>[rp.sendPort, re],
+ onError: rpError.sendPort);
+ Expect.isTrue(await rp.first);
+ }
+ {
+ // Test send of uninitialized RegExp(num_groups is null)
+ final rp = ReceivePort();
+ final re = RegExp('abc');
+ await Isolate.spawn(f, <dynamic>[rp.sendPort, re],
+ onError: rpError.sendPort);
+ Expect.isTrue(await rp.first);
+ }
+ rpError.close();
+}
diff --git a/runtime/tests/vm/dart_2/isolate_send_regex_test.dart b/runtime/tests/vm/dart_2/isolate_send_regex_test.dart
new file mode 100644
index 0000000..cac6d09
--- /dev/null
+++ b/runtime/tests/vm/dart_2/isolate_send_regex_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2021, 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 'package:expect/expect.dart';
+
+f(List args) {
+ final sendPort = args[0] as SendPort;
+ final re = args[1] as RegExp;
+ Expect.stringEquals("RegExp: pattern=abc flags=", re.toString());
+ sendPort.send(true);
+}
+
+main() async {
+ final rpError = RawReceivePort((e) {
+ Expect.fail('Spawned isolated failed with $e');
+ });
+ {
+ // Test sending of initialized RegExp
+ final rp = ReceivePort();
+ final re = RegExp('abc');
+ print(re.hasMatch('kukabcdef'));
+ await Isolate.spawn(f, <dynamic>[rp.sendPort, re],
+ onError: rpError.sendPort);
+ Expect.isTrue(await rp.first);
+ }
+ {
+ // Test send of uninitialized RegExp(num_groups is null)
+ final rp = ReceivePort();
+ final re = RegExp('abc');
+ await Isolate.spawn(f, <dynamic>[rp.sendPort, re],
+ onError: rpError.sendPort);
+ Expect.isTrue(await rp.first);
+ }
+ rpError.close();
+}
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index 9f23820..3f0d49f 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -125,6 +125,20 @@
trace_allocation_table_.load()[cid] = trace ? 1 : 0;
}
bool TraceAllocationFor(intptr_t cid);
+ void SetCollectInstancesFor(intptr_t cid, bool trace) {
+ ASSERT(cid > 0);
+ ASSERT(cid < top_);
+ if (trace) {
+ trace_allocation_table_.load()[cid] |= 2;
+ } else {
+ trace_allocation_table_.load()[cid] &= ~2;
+ }
+ }
+ bool CollectInstancesFor(intptr_t cid) {
+ ASSERT(cid > 0);
+ ASSERT(cid < top_);
+ return (trace_allocation_table_.load()[cid] & 2) != 0;
+ }
#endif // !defined(PRODUCT)
void CopyBeforeHotReload(intptr_t** copy, intptr_t* copy_num_cids) {
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index e84949f..6b87632 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -2395,10 +2395,6 @@
while (it.HasNext()) {
cls = it.GetNextClass();
- // The subclasses/implementors array is only needed for CHA.
- cls.ClearDirectSubclasses();
- cls.ClearDirectImplementors();
-
bool retain = false;
members = cls.fields();
if (members.Length() > 0) {
@@ -2549,6 +2545,12 @@
void Precompiler::DropClasses() {
Class& cls = Class::Handle(Z);
Array& constants = Array::Handle(Z);
+ GrowableObjectArray& implementors = GrowableObjectArray::Handle(Z);
+ GrowableObjectArray& retained_implementors = GrowableObjectArray::Handle(Z);
+ Class& implementor = Class::Handle(Z);
+ GrowableObjectArray& subclasses = GrowableObjectArray::Handle(Z);
+ GrowableObjectArray& retained_subclasses = GrowableObjectArray::Handle(Z);
+ Class& subclass = Class::Handle(Z);
// We are about to remove classes from the class table. For this to be safe,
// there must be no instances of these classes on the heap, not even
@@ -2558,6 +2560,7 @@
IG->heap()->CollectAllGarbage();
IG->heap()->WaitForSweeperTasks(T);
+ SafepointWriteRwLocker ml(T, IG->program_lock());
ClassTable* class_table = IG->class_table();
intptr_t num_cids = class_table->NumCids();
@@ -2576,6 +2579,30 @@
cls = class_table->At(cid);
ASSERT(!cls.IsNull());
+ implementors = cls.direct_implementors();
+ if (!implementors.IsNull()) {
+ retained_implementors = GrowableObjectArray::New();
+ for (intptr_t i = 0; i < implementors.Length(); i++) {
+ implementor ^= implementors.At(i);
+ if (classes_to_retain_.HasKey(&implementor)) {
+ retained_implementors.Add(implementor);
+ }
+ }
+ cls.set_direct_implementors(retained_implementors);
+ }
+
+ subclasses = cls.direct_subclasses();
+ if (!subclasses.IsNull()) {
+ retained_subclasses = GrowableObjectArray::New();
+ for (intptr_t i = 0; i < subclasses.Length(); i++) {
+ subclass ^= subclasses.At(i);
+ if (classes_to_retain_.HasKey(&subclass)) {
+ retained_subclasses.Add(subclass);
+ }
+ }
+ cls.set_direct_subclasses(retained_subclasses);
+ }
+
if (cls.IsTopLevel()) {
// Top-level classes are referenced directly from their library. They
// will only be removed as a consequence of an entire library being
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index 56e7709..7c16944 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -338,7 +338,28 @@
}
CompileType Slot::ComputeCompileType() const {
- return CompileType::CreateNullable(is_nullable(), nullable_cid());
+ // If we unboxed the slot, we may know a more precise type.
+ switch (representation()) {
+ case kUnboxedInt64:
+ if (nullable_cid() == kDynamicCid) {
+ return CompileType::Int();
+ }
+ // Might be an CID like nullable_cid == kSmiCid.
+ break;
+ case kUnboxedDouble:
+ return CompileType::FromCid(kDoubleCid);
+ case kUnboxedInt32x4:
+ return CompileType::FromCid(kInt32x4Cid);
+ case kUnboxedFloat32x4:
+ return CompileType::FromCid(kFloat32x4Cid);
+ case kUnboxedFloat64x2:
+ return CompileType::FromCid(kFloat64x2Cid);
+ default:
+ break;
+ }
+
+ return CompileType(is_nullable(), nullable_cid(),
+ nullable_cid() == kDynamicCid ? static_type_ : nullptr);
}
const AbstractType& Slot::static_type() const {
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 164e8bb..6175f11 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1505,21 +1505,9 @@
}
CompileType LoadFieldInstr::ComputeType() const {
- const AbstractType& field_type = slot().static_type();
- CompileType compile_type_cid = slot().ComputeCompileType();
- if (field_type.ptr() == AbstractType::null()) {
- return compile_type_cid;
- }
-
- const AbstractType* abstract_type = &field_type;
- TraceStrongModeType(this, *abstract_type);
-
- if (compile_type_cid.ToNullableCid() != kDynamicCid) {
- abstract_type = nullptr;
- }
-
- return CompileType(compile_type_cid.is_nullable(),
- compile_type_cid.ToNullableCid(), abstract_type);
+ CompileType type = slot().ComputeCompileType();
+ TraceStrongModeType(this, &type);
+ return type;
}
CompileType LoadCodeUnitsInstr::ComputeType() const {
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index a5bd97f..f5cc809 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -2560,20 +2560,20 @@
// Clear the direct subclasses for all classes.
Class& cls = Class::Handle();
- GrowableObjectArray& subclasses = GrowableObjectArray::Handle();
+ const GrowableObjectArray& null_list = GrowableObjectArray::Handle();
for (intptr_t i = 1; i < num_cids; i++) {
if (class_table->HasValidClassAt(i)) {
cls = class_table->At(i);
if (!cls.is_declaration_loaded()) {
continue; // Can't have any subclasses or implementors yet.
}
- subclasses = cls.direct_subclasses();
- if (!subclasses.IsNull()) {
- cls.ClearDirectSubclasses();
+ // Testing for null to prevent attempting to write to read-only classes
+ // in the VM isolate.
+ if (cls.direct_subclasses() != GrowableObjectArray::null()) {
+ cls.set_direct_subclasses(null_list);
}
- subclasses = cls.direct_implementors();
- if (!subclasses.IsNull()) {
- cls.ClearDirectImplementors();
+ if (cls.direct_implementors() != GrowableObjectArray::null()) {
+ cls.set_direct_implementors(null_list);
}
}
}
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index bbe41e4..2c14854 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -5080,9 +5080,10 @@
direct_implementors.Add(implementor, Heap::kOld);
}
-void Class::ClearDirectImplementors() const {
+void Class::set_direct_implementors(
+ const GrowableObjectArray& implementors) const {
ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
- untag()->set_direct_implementors(GrowableObjectArray::null());
+ untag()->set_direct_implementors(implementors.ptr());
}
void Class::AddDirectSubclass(const Class& subclass) const {
@@ -5106,9 +5107,9 @@
direct_subclasses.Add(subclass, Heap::kOld);
}
-void Class::ClearDirectSubclasses() const {
+void Class::set_direct_subclasses(const GrowableObjectArray& subclasses) const {
ASSERT(IsolateGroup::Current()->program_lock()->IsCurrentThreadWriter());
- untag()->set_direct_subclasses(GrowableObjectArray::null());
+ untag()->set_direct_subclasses(subclasses.ptr());
}
ArrayPtr Class::constants() const {
@@ -25164,6 +25165,10 @@
untag()->set_num_bracket_expressions(value);
}
+void RegExp::set_num_bracket_expressions(const Smi& value) const {
+ untag()->set_num_bracket_expressions(value.ptr());
+}
+
void RegExp::set_num_bracket_expressions(intptr_t value) const {
untag()->set_num_bracket_expressions(Smi::New(value));
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 259e3df..2a7efb4 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1197,8 +1197,11 @@
IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
return untag()->direct_implementors();
}
+ GrowableObjectArrayPtr direct_implementors_unsafe() const {
+ return untag()->direct_implementors();
+ }
+ void set_direct_implementors(const GrowableObjectArray& implementors) const;
void AddDirectImplementor(const Class& subclass, bool is_mixin) const;
- void ClearDirectImplementors() const;
// Returns the list of classes having this class as direct superclass.
GrowableObjectArrayPtr direct_subclasses() const {
@@ -1209,8 +1212,8 @@
GrowableObjectArrayPtr direct_subclasses_unsafe() const {
return untag()->direct_subclasses();
}
+ void set_direct_subclasses(const GrowableObjectArray& subclasses) const;
void AddDirectSubclass(const Class& subclass) const;
- void ClearDirectSubclasses() const;
// Check if this class represents the class of null.
bool IsNullClass() const { return id() == kNullCid; }
@@ -11042,6 +11045,7 @@
const TypedData& bytecode) const;
void set_num_bracket_expressions(SmiPtr value) const;
+ void set_num_bracket_expressions(const Smi& value) const;
void set_num_bracket_expressions(intptr_t value) const;
void set_capture_name_map(const Array& array) const;
void set_is_global() const {
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 5776c38..f8e344b 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -934,7 +934,9 @@
CompressedObjectPtr* to_snapshot(Snapshot::Kind kind) {
switch (kind) {
case Snapshot::kFullAOT:
+#if defined(PRODUCT)
return reinterpret_cast<CompressedObjectPtr*>(&allocation_stub_);
+#endif
case Snapshot::kFull:
case Snapshot::kFullCore:
return reinterpret_cast<CompressedObjectPtr*>(&direct_subclasses_);
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index f1470e1..c6c8955 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -1713,7 +1713,8 @@
reader->AddBackRef(object_id, ®ex, kIsDeserialized);
// Read and Set all the other fields.
- regex.set_num_bracket_expressions(reader->ReadAsSmi());
+ *reader->SmiHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
+ regex.set_num_bracket_expressions(*reader->SmiHandle());
*reader->ArrayHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
regex.set_capture_name_map(*reader->ArrayHandle());
@@ -1750,7 +1751,8 @@
writer->WriteTags(writer->GetObjectTags(this));
// Write out all the other fields.
- writer->Write<ObjectPtr>(num_bracket_expressions_);
+ writer->WriteObjectImpl(num_bracket_expressions_, kAsInlinedObject);
+ writer->WriteObjectImpl(capture_name_map_, kAsInlinedObject);
writer->WriteObjectImpl(pattern_, kAsInlinedObject);
writer->Write<int32_t>(num_one_byte_registers_);
writer->Write<int32_t>(num_two_byte_registers_);
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index ee7a7ec..5da2074 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -3079,23 +3079,72 @@
return true;
}
+static void MarkClasses(const Class& root,
+ bool include_subclasses,
+ bool include_implementors) {
+ Thread* thread = Thread::Current();
+ HANDLESCOPE(thread);
+ SharedClassTable* table = thread->isolate()->group()->shared_class_table();
+ GrowableArray<const Class*> worklist;
+ table->SetCollectInstancesFor(root.id(), true);
+ worklist.Add(&root);
+ GrowableObjectArray& subclasses = GrowableObjectArray::Handle();
+ GrowableObjectArray& implementors = GrowableObjectArray::Handle();
+ while (!worklist.is_empty()) {
+ const Class& cls = *worklist.RemoveLast();
+ // All subclasses are implementors, but they are not included in
+ // `direct_implementors`.
+ if (include_subclasses || include_implementors) {
+ subclasses = cls.direct_subclasses_unsafe();
+ if (!subclasses.IsNull()) {
+ for (intptr_t j = 0; j < subclasses.Length(); j++) {
+ Class& subclass = Class::Handle();
+ subclass ^= subclasses.At(j);
+ if (!table->CollectInstancesFor(subclass.id())) {
+ table->SetCollectInstancesFor(subclass.id(), true);
+ worklist.Add(&subclass);
+ }
+ }
+ }
+ }
+ if (include_implementors) {
+ implementors = cls.direct_implementors_unsafe();
+ if (!implementors.IsNull()) {
+ for (intptr_t j = 0; j < implementors.Length(); j++) {
+ Class& implementor = Class::Handle();
+ implementor ^= implementors.At(j);
+ if (!table->CollectInstancesFor(implementor.id())) {
+ table->SetCollectInstancesFor(implementor.id(), true);
+ worklist.Add(&implementor);
+ }
+ }
+ }
+ }
+ }
+}
+
+static void UnmarkClasses() {
+ SharedClassTable* table = IsolateGroup::Current()->shared_class_table();
+ for (intptr_t i = 1; i < table->NumCids(); i++) {
+ table->SetCollectInstancesFor(i, false);
+ }
+}
+
class GetInstancesVisitor : public ObjectGraph::Visitor {
public:
- GetInstancesVisitor(const Class& cls,
- ZoneGrowableHandlePtrArray<Object>* storage,
+ GetInstancesVisitor(ZoneGrowableHandlePtrArray<Object>* storage,
intptr_t limit)
- : cls_(cls), storage_(storage), limit_(limit), count_(0) {}
+ : table_(IsolateGroup::Current()->shared_class_table()),
+ storage_(storage),
+ limit_(limit),
+ count_(0) {}
virtual Direction VisitObject(ObjectGraph::StackIterator* it) {
ObjectPtr raw_obj = it->Get();
if (raw_obj->IsPseudoObject()) {
return kProceed;
}
- Thread* thread = Thread::Current();
- REUSABLE_OBJECT_HANDLESCOPE(thread);
- Object& obj = thread->ObjectHandle();
- obj = raw_obj;
- if (obj.GetClassId() == cls_.id()) {
+ if (table_->CollectInstancesFor(raw_obj->GetClassId())) {
if (count_ < limit_) {
storage_->Add(Object::Handle(raw_obj));
}
@@ -3107,7 +3156,7 @@
intptr_t count() const { return count_; }
private:
- const Class& cls_;
+ SharedClassTable* const table_;
ZoneGrowableHandlePtrArray<Object>* storage_;
const intptr_t limit_;
intptr_t count_;
@@ -3147,11 +3196,13 @@
HANDLESCOPE(thread);
ZoneGrowableHandlePtrArray<Object> storage(thread->zone(), limit);
- GetInstancesVisitor visitor(cls, &storage, limit);
+ GetInstancesVisitor visitor(&storage, limit);
{
ObjectGraph graph(thread);
HeapIterationScope iteration_scope(Thread::Current(), true);
+ MarkClasses(cls, false, false);
graph.IterateObjects(&visitor);
+ UnmarkClasses();
}
intptr_t count = visitor.count();
JSONObject jsobj(js);
@@ -3166,6 +3217,55 @@
return true;
}
+static const MethodParameter* get_instances_as_array_params[] = {
+ RUNNABLE_ISOLATE_PARAMETER,
+ NULL,
+};
+
+static bool GetInstancesAsArray(Thread* thread, JSONStream* js) {
+ const char* object_id = js->LookupParam("objectId");
+ if (object_id == NULL) {
+ PrintMissingParamError(js, "objectId");
+ return true;
+ }
+
+ bool include_subclasses =
+ BoolParameter::Parse(js->LookupParam("includeSubclasses"), false);
+ bool include_implementors =
+ BoolParameter::Parse(js->LookupParam("includeImplementors"), false);
+
+ const Object& obj = Object::Handle(LookupHeapObject(thread, object_id, NULL));
+ if (obj.ptr() == Object::sentinel().ptr() || !obj.IsClass()) {
+ PrintInvalidParamError(js, "objectId");
+ return true;
+ }
+ const Class& cls = Class::Cast(obj);
+
+ // Ensure the array and handles created below are promptly destroyed.
+ Array& instances = Array::Handle();
+ {
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
+
+ ZoneGrowableHandlePtrArray<Object> storage(thread->zone(), 1024);
+ GetInstancesVisitor visitor(&storage, kSmiMax);
+ {
+ ObjectGraph graph(thread);
+ HeapIterationScope iteration_scope(Thread::Current(), true);
+ MarkClasses(cls, include_subclasses, include_implementors);
+ graph.IterateObjects(&visitor);
+ UnmarkClasses();
+ }
+ intptr_t count = visitor.count();
+ instances = Array::New(count);
+ for (intptr_t i = 0; i < count; i++) {
+ instances.SetAt(i, storage.At(i));
+ }
+ }
+ instances.PrintJSON(js, /* as_ref */ true);
+ return true;
+}
+
static const MethodParameter* get_ports_params[] = {
RUNNABLE_ISOLATE_PARAMETER,
NULL,
@@ -5116,6 +5216,8 @@
get_inbound_references_params },
{ "getInstances", GetInstances,
get_instances_params },
+ { "_getInstancesAsArray", GetInstancesAsArray,
+ get_instances_as_array_params },
{ "getPorts", GetPorts,
get_ports_params },
{ "getIsolate", GetIsolate,
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index c700063..4d9a35f 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -301,6 +301,7 @@
typed_data_(TypedData::Handle(zone_)),
typed_data_view_(TypedDataView::Handle(zone_)),
function_(Function::Handle(zone_)),
+ smi_(Smi::Handle(zone_)),
error_(UnhandledException::Handle(zone_)),
set_class_(Class::ZoneHandle(
zone_,
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 174a88f..ba3f9a9 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -285,6 +285,7 @@
TypedData* TypedDataHandle() { return &typed_data_; }
TypedDataView* TypedDataViewHandle() { return &typed_data_view_; }
Function* FunctionHandle() { return &function_; }
+ Smi* SmiHandle() { return &smi_; }
Snapshot::Kind kind() const { return kind_; }
// Reads an object.
@@ -379,6 +380,7 @@
TypedData& typed_data_; // Temporary typed data handle.
TypedDataView& typed_data_view_; // Temporary typed data view handle.
Function& function_; // Temporary function handle.
+ Smi& smi_; // Temporary Smi handle.
UnhandledException& error_; // Error handle.
const Class& set_class_; // The LinkedHashSet class.
intptr_t max_vm_isolate_object_id_;
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index aad3f5a..15a1abf 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -507,29 +507,6 @@
outputs = [ "$root_out_dir/dart-sdk/lib/_internal/{{source_file_part}}" ]
}
-copy("copy_wasmer") {
- visibility = [ ":create_common_sdk" ]
- deps = [
- ":copy_libraries",
- "../third_party/wasmer:wasmer_wrap",
- ]
- if (is_win) {
- prefix = ""
- suffix = "dll"
- } else if (is_mac) {
- prefix = "lib"
- suffix = "dylib"
- } else {
- # TODO(dartbug.com/37882): Support Fuchsia.
- prefix = "lib"
- suffix = "so"
- }
- sources = [ "$root_out_dir/${prefix}wasmer_wrap.$suffix" ]
- outputs = [
- "$root_out_dir/dart-sdk/bin/third_party/wasmer/${prefix}wasmer.$suffix",
- ]
-}
-
# This rule copies dill files to lib/_internal.
copy("copy_vm_dill_files") {
visibility = [ ":create_common_sdk" ]
@@ -850,14 +827,6 @@
if (is_win) {
public_deps += [ ":copy_7zip" ]
}
-
- # CIPD only has versions of the Rust compiler for linux and mac x64 hosts.
- # We also disallow cross-compialtion (it may be possible in future, but it
- # isn't ready yet).
- if (host_cpu == "x64" && (host_os == "linux" || host_os == "mac") &&
- host_cpu == current_cpu && host_os == current_os && dart_enable_wasm) {
- public_deps += [ ":copy_wasmer" ]
- }
}
# Parts specific to the platform SDK.
diff --git a/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart b/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
index 041dfd5..d0e0ba2 100644
--- a/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
+++ b/sdk/lib/_internal/js_dev_runtime/patch/io_patch.dart
@@ -220,6 +220,14 @@
}
@patch
+class OSError {
+ @patch
+ static int inProgressErrorCode() {
+ throw new UnsupportedError("OSError.inProgressErrorCode");
+ }
+}
+
+@patch
class _IOCrypto {
@patch
static Uint8List getRandomBytes(int count) {
diff --git a/sdk/lib/_internal/js_runtime/lib/io_patch.dart b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
index 77a2530..fb7052f 100644
--- a/sdk/lib/_internal/js_runtime/lib/io_patch.dart
+++ b/sdk/lib/_internal/js_runtime/lib/io_patch.dart
@@ -228,6 +228,14 @@
}
@patch
+class OSError {
+ @patch
+ static int inProgressErrorCode() {
+ throw new UnsupportedError("OSError.inProgressErrorCode");
+ }
+}
+
+@patch
class _Platform {
@patch
static int _numberOfProcessors() {
diff --git a/sdk/lib/_internal/vm/bin/common_patch.dart b/sdk/lib/_internal/vm/bin/common_patch.dart
index f788ec7..45e8ac1 100644
--- a/sdk/lib/_internal/vm/bin/common_patch.dart
+++ b/sdk/lib/_internal/vm/bin/common_patch.dart
@@ -63,6 +63,12 @@
}
@patch
+class OSError {
+ @patch
+ static int inProgressErrorCode() native "OSError_inProgressErrorCode";
+}
+
+@patch
class _IOCrypto {
@patch
static Uint8List getRandomBytes(int count) native "Crypto_GetRandomBytes";
diff --git a/sdk/lib/_internal/vm/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
index 62d56d5..a20a0bb 100644
--- a/sdk/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/socket_patch.dart
@@ -802,9 +802,17 @@
try {
socket.port;
} catch (e) {
- error ??= createError(e, "Connection failed", address, port);
- connectNext(); // Try again after failure to connect.
- return;
+ if (e is OSError && e.errorCode == OSError.inProgressErrorCode()) {
+ // Ignore the error, proceed with waiting for a socket to become open.
+ // In non-blocking mode connect might not be established away, socket
+ // have to be waited for.
+ // EINPROGRESS error is ignored during |connect| call in native code,
+ // it has be ignored here during |port| query here.
+ } else {
+ error ??= createError(e, "Connection failed", address, port);
+ connectNext(); // Try again after failure to connect.
+ return;
+ }
}
// Try again if no response (failure or success) within a duration.
@@ -1146,7 +1154,11 @@
if (localAddress.type == InternetAddressType.unix) return 0;
if (localPort != 0) return localPort;
if (isClosing || isClosed) throw const SocketException.closed();
- return localPort = nativeGetPort();
+ var result = nativeGetPort();
+ if (result is OSError) {
+ throw result;
+ }
+ return localPort = result;
}
int get remotePort {
@@ -1530,7 +1542,7 @@
nativeCreateBindDatagram(Uint8List addr, int port, bool reuseAddress,
bool reusePort, int ttl) native "Socket_CreateBindDatagram";
bool nativeAccept(_NativeSocket socket) native "ServerSocket_Accept";
- int nativeGetPort() native "Socket_GetPort";
+ dynamic nativeGetPort() native "Socket_GetPort";
List nativeGetRemotePeer() native "Socket_GetRemotePeer";
int nativeGetSocketId() native "Socket_GetSocketId";
OSError nativeGetError() native "Socket_GetError";
diff --git a/sdk/lib/io/common.dart b/sdk/lib/io/common.dart
index 252d602..a2d4d73 100644
--- a/sdk/lib/io/common.dart
+++ b/sdk/lib/io/common.dart
@@ -48,6 +48,9 @@
/// Constant used to indicate that no OS error code is available.
static const int noErrorCode = -1;
+ /// Returns error code that corresponds to EINPROGRESS OS error.
+ external static int inProgressErrorCode();
+
/// Error message supplied by the operating system. This will be empty if no
/// message is associated with the error.
final String message;
diff --git a/tests/language/vm/regress_45524_test.dart b/tests/language/vm/regress_45524_test.dart
new file mode 100644
index 0000000..9df16c8
--- /dev/null
+++ b/tests/language/vm/regress_45524_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2021, 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";
+
+// Reduced from:
+// The Dart Project Fuzz Tester (1.89).
+// Program generated as:
+// dart dartfuzz.dart --seed 3959760722 --no-fp --no-ffi --flat
+
+bool var17 = bool.fromEnvironment('2y');
+
+class X0 {
+ num fld0_2 = 9223372036854775807;
+}
+
+extension XE0 on X0 {
+ bool foo0_Extension0() {
+ if (-12 >= -(((var17 ? -92 : fld0_2)))) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+main() {
+ Expect.equals(true, X0().foo0_Extension0());
+}
diff --git a/tests/language_2/vm/regress_45524_test.dart b/tests/language_2/vm/regress_45524_test.dart
new file mode 100644
index 0000000..3f33adb
--- /dev/null
+++ b/tests/language_2/vm/regress_45524_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2021, 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";
+
+// Reduced from:
+// The Dart Project Fuzz Tester (1.89).
+// Program generated as:
+// dart dartfuzz.dart --seed 3959760722 --no-fp --no-ffi --flat
+// @dart=2.7
+
+bool var17 = bool.fromEnvironment('2y');
+
+class X0 {
+ num fld0_2 = 9223372036854775807;
+}
+
+extension XE0 on X0 {
+ bool foo0_Extension0() {
+ if (-12 >= -(((var17 ? -92 : fld0_2)))) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
+
+main() {
+ Expect.equals(true, X0().foo0_Extension0());
+}
diff --git a/third_party/wasmer/.gitignore b/third_party/wasmer/.gitignore
deleted file mode 100644
index 86a9394..0000000
--- a/third_party/wasmer/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-!*
-Cargo.lock
diff --git a/third_party/wasmer/BUILD.gn b/third_party/wasmer/BUILD.gn
deleted file mode 100644
index 0f65bf7..0000000
--- a/third_party/wasmer/BUILD.gn
+++ /dev/null
@@ -1,24 +0,0 @@
-import("../../build/rust/rust.gni")
-
-shared_library("wasmer_wrap") {
- sources = [
- "../../runtime/include/dart_api_dl.c",
- "finalizers.cc",
- ]
- deps = [
- ":wasmer_lib",
- "../../runtime/bin:dart",
- ]
- include_dirs = [ "../../runtime" ]
- defines = [ "DART_SHARED_LIB" ]
- if (is_linux) {
- libs = [ "rt" ]
- }
-
- # Force linking of all wasmer symbols.
- ldflags = [ "-Wl,--no-as-needed" ]
-}
-
-rust_library("wasmer_lib") {
- lib_name = "wasmer"
-}
diff --git a/third_party/wasmer/Cargo.toml b/third_party/wasmer/Cargo.toml
deleted file mode 100644
index a476549..0000000
--- a/third_party/wasmer/Cargo.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-[package]
-name = "wasmer"
-version = "1.0.0-alpha5"
-
-[lib]
-name = "wasmer"
-crate-type = ["staticlib"]
-path = "wasmer.rs"
-
-[dependencies.wasmer-c-api]
-version = "1.0.0-alpha5"
-default-features = false
-features = ["jit", "cranelift", "wasi"]
diff --git a/third_party/wasmer/LICENSE b/third_party/wasmer/LICENSE
deleted file mode 100644
index 62bb543..0000000
--- a/third_party/wasmer/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2019-present Wasmer, Inc. and its affiliates.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/third_party/wasmer/finalizers.cc b/third_party/wasmer/finalizers.cc
deleted file mode 100644
index 85d5286..0000000
--- a/third_party/wasmer/finalizers.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2020, 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.
-
-#include "include/dart_api.h"
-#include "include/dart_api_dl.h"
-
-#define FINALIZER(type) \
- extern "C" void wasm_##type##_delete(void*); \
- extern "C" void wasm_##type##_finalizer(void*, void* native_object) { \
- wasm_##type##_delete(native_object); \
- } \
- DART_EXPORT void set_finalizer_for_##type(Dart_Handle dart_object, \
- void* native_object) { \
- Dart_NewFinalizableHandle_DL(dart_object, native_object, 0, \
- wasm_##type##_finalizer); \
- }
-
-FINALIZER(engine);
-FINALIZER(store);
-FINALIZER(module);
-FINALIZER(instance);
-FINALIZER(trap);
-FINALIZER(memorytype);
-FINALIZER(memory);
-FINALIZER(func);
diff --git a/third_party/wasmer/wasmer.rs b/third_party/wasmer/wasmer.rs
deleted file mode 100644
index c4bd6e5..0000000
--- a/third_party/wasmer/wasmer.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub extern crate wasmer_c_api;
diff --git a/tools/VERSION b/tools/VERSION
index 873a2c8..48d6604 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 192
+PRERELEASE 193
PRERELEASE_PATCH 0
\ No newline at end of file