Version 2.14.0-89.0.dev

Merge commit 'f53af0d445c8f73562274bcea9e0bec394a1f6a0' into 'dev'
diff --git a/pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect b/pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect
index cad4e7a..cdeb1e9 100644
--- a/pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/general/ffi_sample.dart.weak.transformed.expect
@@ -30,18 +30,20 @@
   abstract member-signature method toString() → core::String*; -> core::Object::toString
   abstract member-signature method noSuchMethod(core::Invocation* invocation) → dynamic; -> core::Object::noSuchMethod
   abstract member-signature get runtimeType() → core::Type*; -> core::Object::runtimeType
+  @#C11
   get x() → core::double*
-    return ffi::_loadDouble(this.{ffi::_Compound::_typedDataBase}, (#C12).{core::List::[]}(ffi::_abi()));
+    return ffi::_loadDouble(this.{ffi::_Compound::_typedDataBase}, (#C13).{core::List::[]}(ffi::_abi()));
   set x(core::double* #v) → void
-    return ffi::_storeDouble(this.{ffi::_Compound::_typedDataBase}, (#C12).{core::List::[]}(ffi::_abi()), #v);
+    return ffi::_storeDouble(this.{ffi::_Compound::_typedDataBase}, (#C13).{core::List::[]}(ffi::_abi()), #v);
+  @#C11
   get y() → core::double*
-    return ffi::_loadDouble(this.{ffi::_Compound::_typedDataBase}, (#C14).{core::List::[]}(ffi::_abi()));
+    return ffi::_loadDouble(this.{ffi::_Compound::_typedDataBase}, (#C15).{core::List::[]}(ffi::_abi()));
   set y(core::double* #v) → void
-    return ffi::_storeDouble(this.{ffi::_Compound::_typedDataBase}, (#C14).{core::List::[]}(ffi::_abi()), #v);
+    return ffi::_storeDouble(this.{ffi::_Compound::_typedDataBase}, (#C15).{core::List::[]}(ffi::_abi()), #v);
   get next() → ffi::Pointer<self::Coordinate*>*
-    return ffi::_fromAddress<self::Coordinate*>(ffi::_loadIntPtr(this.{ffi::_Compound::_typedDataBase}, (#C16).{core::List::[]}(ffi::_abi())));
+    return ffi::_fromAddress<self::Coordinate*>(ffi::_loadIntPtr(this.{ffi::_Compound::_typedDataBase}, (#C17).{core::List::[]}(ffi::_abi())));
   set next(ffi::Pointer<self::Coordinate*>* #v) → void
-    return ffi::_storeIntPtr(this.{ffi::_Compound::_typedDataBase}, (#C16).{core::List::[]}(ffi::_abi()), #v.{ffi::Pointer::address});
+    return ffi::_storeIntPtr(this.{ffi::_Compound::_typedDataBase}, (#C17).{core::List::[]}(ffi::_abi()), #v.{ffi::Pointer::address});
 }
 static method main() → dynamic {}
 
@@ -56,12 +58,13 @@
   #C8 = 24
   #C9 = 20
   #C10 = <core::int*>[#C8, #C9, #C8]
-  #C11 = 0
-  #C12 = <core::int*>[#C11, #C11, #C11]
-  #C13 = 8
-  #C14 = <core::int*>[#C13, #C13, #C13]
-  #C15 = 16
-  #C16 = <core::int*>[#C15, #C15, #C15]
+  #C11 = ffi::Double {}
+  #C12 = 0
+  #C13 = <core::int*>[#C12, #C12, #C12]
+  #C14 = 8
+  #C15 = <core::int*>[#C14, #C14, #C14]
+  #C16 = 16
+  #C17 = <core::int*>[#C16, #C16, #C16]
 }
 
 
diff --git a/pkg/front_end/testcases/incremental.status b/pkg/front_end/testcases/incremental.status
index 57a86f3..afed71c 100644
--- a/pkg/front_end/testcases/incremental.status
+++ b/pkg/front_end/testcases/incremental.status
@@ -6,7 +6,3 @@
 
 # http://dartbug.com/41812#issuecomment-684825703
 strongmode_mixins_2: Crash
-
-# http://dartbug.com/45899
-crash_05: Crash
-crash_06: Crash
diff --git a/pkg/front_end/testcases/incremental/crash_05.yaml b/pkg/front_end/testcases/incremental/crash_05.yaml
index 405d4f2..58d324b 100644
--- a/pkg/front_end/testcases/incremental/crash_05.yaml
+++ b/pkg/front_end/testcases/incremental/crash_05.yaml
@@ -30,4 +30,4 @@
     invalidate:
       - main.dart
     expectedLibraryCount: 2
-    expectsRebuildBodiesOnly: true
\ No newline at end of file
+    expectsRebuildBodiesOnly: false
diff --git a/pkg/front_end/testcases/incremental/crash_05.yaml.world.2.expect b/pkg/front_end/testcases/incremental/crash_05.yaml.world.2.expect
new file mode 100644
index 0000000..7b59748
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/crash_05.yaml.world.2.expect
@@ -0,0 +1,62 @@
+main = <No Member>;
+library from "org-dartlang-test:///lib.dart" as lib {
+
+  import "dart:ffi";
+
+  @#C6
+  class Y extends dart.ffi::Struct {
+    static final field dart.core::int* #sizeOf = (#C8).{dart.core::List::[]}(dart.ffi::_abi())/*isLegacy*/;
+    synthetic constructor •() → lib::Y
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → lib::Y
+      : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+      ;
+    @#C9
+    get yy() → dart.core::int
+      return dart.ffi::_loadUint32(this.{dart.ffi::_Compound::_typedDataBase}, (#C11).{dart.core::List::[]}(dart.ffi::_abi()));
+    @#C9
+    set yy(dart.core::int #externalFieldValue) → void
+      return dart.ffi::_storeUint32(this.{dart.ffi::_Compound::_typedDataBase}, (#C11).{dart.core::List::[]}(dart.ffi::_abi()), #externalFieldValue);
+  }
+}
+library from "org-dartlang-test:///main.dart" as main {
+
+  import "dart:ffi";
+  import "org-dartlang-test:///lib.dart";
+
+  @#C15
+  class X extends dart.ffi::Struct {
+    static final field dart.core::int* #sizeOf = (#C8).{dart.core::List::[]}(dart.ffi::_abi())/*isLegacy*/;
+    synthetic constructor •() → main::X
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → main::X
+      : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+      ;
+    get xx() → lib::Y
+      return new lib::Y::#fromTypedDataBase( block {
+        dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase};
+        dart.core::int #offset = (#C11).{dart.core::List::[]}(dart.ffi::_abi());
+      } =>#typedDataBase is dart.ffi::Pointer<dynamic> ?{dart.core::Object} dart.ffi::_fromAddress<lib::Y>(#typedDataBase.{dart.ffi::Pointer::address}.{dart.core::num::+}(#offset)) : let dart.typed_data::TypedData #typedData = dart._internal::unsafeCast<dart.typed_data::TypedData>(#typedDataBase) in #typedData.{dart.typed_data::TypedData::buffer}.{dart.typed_data::ByteBuffer::asUint8List}(#typedData.{dart.typed_data::TypedData::offsetInBytes}.{dart.core::num::+}(#offset), (#C8).{dart.core::List::[]}(dart.ffi::_abi())));
+    set xx(lib::Y #externalFieldValue) → void
+      return dart.ffi::_memCopy(this.{dart.ffi::_Compound::_typedDataBase}, (#C11).{dart.core::List::[]}(dart.ffi::_abi()), #externalFieldValue.{dart.ffi::_Compound::_typedDataBase}, #C10, (#C8).{dart.core::List::[]}(dart.ffi::_abi()));
+  }
+}
+constants  {
+  #C1 = "vm:ffi:struct-fields"
+  #C2 = TypeLiteralConstant(dart.ffi::Uint32)
+  #C3 = <dart.core::Type>[#C2]
+  #C4 = null
+  #C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C3, packing:#C4}
+  #C6 = dart.core::pragma {name:#C1, options:#C5}
+  #C7 = 4
+  #C8 = <dart.core::int*>[#C7, #C7, #C7]
+  #C9 = dart.ffi::Uint32 {}
+  #C10 = 0
+  #C11 = <dart.core::int*>[#C10, #C10, #C10]
+  #C12 = TypeLiteralConstant(lib::Y)
+  #C13 = <dart.core::Type>[#C12]
+  #C14 = dart.ffi::_FfiStructLayout {fieldTypes:#C13, packing:#C4}
+  #C15 = dart.core::pragma {name:#C1, options:#C14}
+}
diff --git a/pkg/front_end/testcases/incremental/crash_06.yaml b/pkg/front_end/testcases/incremental/crash_06.yaml
index 932a44d..1c46cb0 100644
--- a/pkg/front_end/testcases/incremental/crash_06.yaml
+++ b/pkg/front_end/testcases/incremental/crash_06.yaml
@@ -7,6 +7,7 @@
 type: newworld
 worlds:
   - entry: structs.dart
+    errors: true
     experiments: non-nullable
     sources:
       structs.dart: |
@@ -20,11 +21,12 @@
     expectedLibraryCount: 1
 
   - entry: structs.dart
+    errors: true
     experiments: non-nullable
     worldType: updated
     expectInitializeFromDill: false
     invalidate:
       - structs.dart
     expectedLibraryCount: 1
-    expectsRebuildBodiesOnly: true
+    expectsRebuildBodiesOnly: false
 
diff --git a/pkg/front_end/testcases/incremental/crash_06.yaml.world.1.expect b/pkg/front_end/testcases/incremental/crash_06.yaml.world.1.expect
new file mode 100644
index 0000000..2e6d138
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/crash_06.yaml.world.1.expect
@@ -0,0 +1,62 @@
+main = <No Member>;
+//
+// Problems in component:
+//
+// org-dartlang-test:///structs.dart:6:14: Error: Field 'zz' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs and Unions cannot have regular Dart fields.
+//   external Z zz;
+//              ^
+//
+library from "org-dartlang-test:///structs.dart" as str {
+//
+// Problems in library:
+//
+// org-dartlang-test:///structs.dart:6:12: Error: 'Z' isn't a type.
+//   external Z zz;
+//            ^
+//
+// org-dartlang-test:///structs.dart:6:12: Error: Type 'Z' not found.
+//   external Z zz;
+//            ^
+//
+
+  import "dart:ffi";
+
+  @#C6
+  class A extends dart.ffi::Struct {
+    static final field dart.core::int* #sizeOf = (#C8).{dart.core::List::[]}(dart.ffi::_abi())/*isLegacy*/;
+    synthetic constructor •() → str::A
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → str::A
+      : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+      ;
+    get yy() → str::Y
+      return new str::Y::#fromTypedDataBase( block {
+        dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase};
+        dart.core::int #offset = (#C8).{dart.core::List::[]}(dart.ffi::_abi());
+      } =>#typedDataBase is dart.ffi::Pointer<dynamic> ?{dart.core::Object} dart.ffi::_fromAddress<str::Y>(#typedDataBase.{dart.ffi::Pointer::address}.{dart.core::num::+}(#offset)) : let dart.typed_data::TypedData #typedData = dart._internal::unsafeCast<dart.typed_data::TypedData>(#typedDataBase) in #typedData.{dart.typed_data::TypedData::buffer}.{dart.typed_data::ByteBuffer::asUint8List}(#typedData.{dart.typed_data::TypedData::offsetInBytes}.{dart.core::num::+}(#offset), (#C8).{dart.core::List::[]}(dart.ffi::_abi())));
+    set yy(str::Y #externalFieldValue) → void
+      return dart.ffi::_memCopy(this.{dart.ffi::_Compound::_typedDataBase}, (#C8).{dart.core::List::[]}(dart.ffi::_abi()), #externalFieldValue.{dart.ffi::_Compound::_typedDataBase}, #C7, (#C8).{dart.core::List::[]}(dart.ffi::_abi()));
+  }
+  class Y extends dart.ffi::Struct {
+    static final field dart.core::int* #sizeOf = (#C8).{dart.core::List::[]}(dart.ffi::_abi())/*isLegacy*/;
+    synthetic constructor •() → str::Y
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → str::Y
+      : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+      ;
+    external get zz() → invalid-type;
+    external set zz(invalid-type #externalFieldValue) → void;
+  }
+}
+constants  {
+  #C1 = "vm:ffi:struct-fields"
+  #C2 = TypeLiteralConstant(str::Y)
+  #C3 = <dart.core::Type>[#C2]
+  #C4 = null
+  #C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C3, packing:#C4}
+  #C6 = dart.core::pragma {name:#C1, options:#C5}
+  #C7 = 0
+  #C8 = <dart.core::int*>[#C7, #C7, #C7]
+}
diff --git a/pkg/front_end/testcases/incremental/crash_06.yaml.world.2.expect b/pkg/front_end/testcases/incremental/crash_06.yaml.world.2.expect
new file mode 100644
index 0000000..2e6d138
--- /dev/null
+++ b/pkg/front_end/testcases/incremental/crash_06.yaml.world.2.expect
@@ -0,0 +1,62 @@
+main = <No Member>;
+//
+// Problems in component:
+//
+// org-dartlang-test:///structs.dart:6:14: Error: Field 'zz' requires exactly one annotation to declare its native type, which cannot be Void. dart:ffi Structs and Unions cannot have regular Dart fields.
+//   external Z zz;
+//              ^
+//
+library from "org-dartlang-test:///structs.dart" as str {
+//
+// Problems in library:
+//
+// org-dartlang-test:///structs.dart:6:12: Error: 'Z' isn't a type.
+//   external Z zz;
+//            ^
+//
+// org-dartlang-test:///structs.dart:6:12: Error: Type 'Z' not found.
+//   external Z zz;
+//            ^
+//
+
+  import "dart:ffi";
+
+  @#C6
+  class A extends dart.ffi::Struct {
+    static final field dart.core::int* #sizeOf = (#C8).{dart.core::List::[]}(dart.ffi::_abi())/*isLegacy*/;
+    synthetic constructor •() → str::A
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → str::A
+      : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+      ;
+    get yy() → str::Y
+      return new str::Y::#fromTypedDataBase( block {
+        dart.core::Object #typedDataBase = this.{dart.ffi::_Compound::_typedDataBase};
+        dart.core::int #offset = (#C8).{dart.core::List::[]}(dart.ffi::_abi());
+      } =>#typedDataBase is dart.ffi::Pointer<dynamic> ?{dart.core::Object} dart.ffi::_fromAddress<str::Y>(#typedDataBase.{dart.ffi::Pointer::address}.{dart.core::num::+}(#offset)) : let dart.typed_data::TypedData #typedData = dart._internal::unsafeCast<dart.typed_data::TypedData>(#typedDataBase) in #typedData.{dart.typed_data::TypedData::buffer}.{dart.typed_data::ByteBuffer::asUint8List}(#typedData.{dart.typed_data::TypedData::offsetInBytes}.{dart.core::num::+}(#offset), (#C8).{dart.core::List::[]}(dart.ffi::_abi())));
+    set yy(str::Y #externalFieldValue) → void
+      return dart.ffi::_memCopy(this.{dart.ffi::_Compound::_typedDataBase}, (#C8).{dart.core::List::[]}(dart.ffi::_abi()), #externalFieldValue.{dart.ffi::_Compound::_typedDataBase}, #C7, (#C8).{dart.core::List::[]}(dart.ffi::_abi()));
+  }
+  class Y extends dart.ffi::Struct {
+    static final field dart.core::int* #sizeOf = (#C8).{dart.core::List::[]}(dart.ffi::_abi())/*isLegacy*/;
+    synthetic constructor •() → str::Y
+      : super dart.ffi::Struct::•()
+      ;
+    constructor #fromTypedDataBase(dart.core::Object #typedDataBase) → str::Y
+      : super dart.ffi::Struct::_fromTypedDataBase(#typedDataBase)
+      ;
+    external get zz() → invalid-type;
+    external set zz(invalid-type #externalFieldValue) → void;
+  }
+}
+constants  {
+  #C1 = "vm:ffi:struct-fields"
+  #C2 = TypeLiteralConstant(str::Y)
+  #C3 = <dart.core::Type>[#C2]
+  #C4 = null
+  #C5 = dart.ffi::_FfiStructLayout {fieldTypes:#C3, packing:#C4}
+  #C6 = dart.core::pragma {name:#C1, options:#C5}
+  #C7 = 0
+  #C8 = <dart.core::int*>[#C7, #C7, #C7]
+}
diff --git a/pkg/front_end/testcases/incremental/ffi_01.yaml.world.1.expect b/pkg/front_end/testcases/incremental/ffi_01.yaml.world.1.expect
index e983eec..481fe3f 100644
--- a/pkg/front_end/testcases/incremental/ffi_01.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/ffi_01.yaml.world.1.expect
@@ -23,18 +23,20 @@
     abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
     abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+    @#C11
     get x() → dart.core::double*
-      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()));
+      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()));
     set x(dart.core::double* #v) → void
-      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+    @#C11
     get y() → dart.core::double*
-      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()));
+      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()));
     set y(dart.core::double* #v) → void
-      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v);
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
-      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C16).{dart.core::List::[]}(dart.ffi::_abi())));
+      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C17).{dart.core::List::[]}(dart.ffi::_abi())));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C16).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
+      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
   }
 }
 library from "org-dartlang-test:///main.dart" as main {
@@ -59,10 +61,11 @@
   #C8 = 24
   #C9 = 20
   #C10 = <dart.core::int*>[#C8, #C9, #C8]
-  #C11 = 0
-  #C12 = <dart.core::int*>[#C11, #C11, #C11]
-  #C13 = 8
-  #C14 = <dart.core::int*>[#C13, #C13, #C13]
-  #C15 = 16
-  #C16 = <dart.core::int*>[#C15, #C15, #C15]
+  #C11 = dart.ffi::Double {}
+  #C12 = 0
+  #C13 = <dart.core::int*>[#C12, #C12, #C12]
+  #C14 = 8
+  #C15 = <dart.core::int*>[#C14, #C14, #C14]
+  #C16 = 16
+  #C17 = <dart.core::int*>[#C16, #C16, #C16]
 }
diff --git a/pkg/front_end/testcases/incremental/ffi_01.yaml.world.2.expect b/pkg/front_end/testcases/incremental/ffi_01.yaml.world.2.expect
index f61ae87..751d0a9 100644
--- a/pkg/front_end/testcases/incremental/ffi_01.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/ffi_01.yaml.world.2.expect
@@ -23,18 +23,20 @@
     abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
     abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+    @#C11
     get x() → dart.core::double*
-      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()));
+      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()));
     set x(dart.core::double* #v) → void
-      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+    @#C11
     get y() → dart.core::double*
-      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()));
+      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()));
     set y(dart.core::double* #v) → void
-      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v);
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
-      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C16).{dart.core::List::[]}(dart.ffi::_abi())));
+      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C17).{dart.core::List::[]}(dart.ffi::_abi())));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C16).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
+      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
   }
 }
 library from "org-dartlang-test:///main.dart" as main {
@@ -63,10 +65,11 @@
   #C8 = 24
   #C9 = 20
   #C10 = <dart.core::int*>[#C8, #C9, #C8]
-  #C11 = 0
-  #C12 = <dart.core::int*>[#C11, #C11, #C11]
-  #C13 = 8
-  #C14 = <dart.core::int*>[#C13, #C13, #C13]
-  #C15 = 16
-  #C16 = <dart.core::int*>[#C15, #C15, #C15]
+  #C11 = dart.ffi::Double {}
+  #C12 = 0
+  #C13 = <dart.core::int*>[#C12, #C12, #C12]
+  #C14 = 8
+  #C15 = <dart.core::int*>[#C14, #C14, #C14]
+  #C16 = 16
+  #C17 = <dart.core::int*>[#C16, #C16, #C16]
 }
diff --git a/pkg/front_end/testcases/incremental/ffi_02.yaml.world.1.expect b/pkg/front_end/testcases/incremental/ffi_02.yaml.world.1.expect
index 1979d4a..deb8a44 100644
--- a/pkg/front_end/testcases/incremental/ffi_02.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/ffi_02.yaml.world.1.expect
@@ -23,18 +23,20 @@
     abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
     abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+    @#C11
     get x() → dart.core::double*
-      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()));
+      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()));
     set x(dart.core::double* #v) → void
-      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+    @#C11
     get y() → dart.core::double*
-      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()));
+      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()));
     set y(dart.core::double* #v) → void
-      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v);
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
-      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C16).{dart.core::List::[]}(dart.ffi::_abi())));
+      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C17).{dart.core::List::[]}(dart.ffi::_abi())));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C16).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
+      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
   }
 }
 library from "org-dartlang-test:///main.dart" as main {
@@ -60,10 +62,11 @@
   #C8 = 24
   #C9 = 20
   #C10 = <dart.core::int*>[#C8, #C9, #C8]
-  #C11 = 0
-  #C12 = <dart.core::int*>[#C11, #C11, #C11]
-  #C13 = 8
-  #C14 = <dart.core::int*>[#C13, #C13, #C13]
-  #C15 = 16
-  #C16 = <dart.core::int*>[#C15, #C15, #C15]
+  #C11 = dart.ffi::Double {}
+  #C12 = 0
+  #C13 = <dart.core::int*>[#C12, #C12, #C12]
+  #C14 = 8
+  #C15 = <dart.core::int*>[#C14, #C14, #C14]
+  #C16 = 16
+  #C17 = <dart.core::int*>[#C16, #C16, #C16]
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.1.expect b/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.1.expect
index e983eec..481fe3f 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.1.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.1.expect
@@ -23,18 +23,20 @@
     abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
     abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+    @#C11
     get x() → dart.core::double*
-      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()));
+      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()));
     set x(dart.core::double* #v) → void
-      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+    @#C11
     get y() → dart.core::double*
-      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()));
+      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()));
     set y(dart.core::double* #v) → void
-      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v);
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
-      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C16).{dart.core::List::[]}(dart.ffi::_abi())));
+      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C17).{dart.core::List::[]}(dart.ffi::_abi())));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C16).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
+      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
   }
 }
 library from "org-dartlang-test:///main.dart" as main {
@@ -59,10 +61,11 @@
   #C8 = 24
   #C9 = 20
   #C10 = <dart.core::int*>[#C8, #C9, #C8]
-  #C11 = 0
-  #C12 = <dart.core::int*>[#C11, #C11, #C11]
-  #C13 = 8
-  #C14 = <dart.core::int*>[#C13, #C13, #C13]
-  #C15 = 16
-  #C16 = <dart.core::int*>[#C15, #C15, #C15]
+  #C11 = dart.ffi::Double {}
+  #C12 = 0
+  #C13 = <dart.core::int*>[#C12, #C12, #C12]
+  #C14 = 8
+  #C15 = <dart.core::int*>[#C14, #C14, #C14]
+  #C16 = 16
+  #C17 = <dart.core::int*>[#C16, #C16, #C16]
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.2.expect b/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.2.expect
index aae1c15..aeab1b0 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.2.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.2.expect
@@ -23,18 +23,20 @@
     abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
     abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+    @#C11
     get x() → dart.core::double*
-      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()));
+      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()));
     set x(dart.core::double* #v) → void
-      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+    @#C11
     get y() → dart.core::double*
-      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()));
+      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()));
     set y(dart.core::double* #v) → void
-      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v);
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
-      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C16).{dart.core::List::[]}(dart.ffi::_abi())));
+      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C17).{dart.core::List::[]}(dart.ffi::_abi())));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C16).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
+      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
   }
 }
 library from "org-dartlang-test:///main.dart" as main {
@@ -60,10 +62,11 @@
   #C8 = 24
   #C9 = 20
   #C10 = <dart.core::int*>[#C8, #C9, #C8]
-  #C11 = 0
-  #C12 = <dart.core::int*>[#C11, #C11, #C11]
-  #C13 = 8
-  #C14 = <dart.core::int*>[#C13, #C13, #C13]
-  #C15 = 16
-  #C16 = <dart.core::int*>[#C15, #C15, #C15]
+  #C11 = dart.ffi::Double {}
+  #C12 = 0
+  #C13 = <dart.core::int*>[#C12, #C12, #C12]
+  #C14 = 8
+  #C15 = <dart.core::int*>[#C14, #C14, #C14]
+  #C16 = 16
+  #C17 = <dart.core::int*>[#C16, #C16, #C16]
 }
diff --git a/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.3.expect b/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.3.expect
index dcd9515..1c8bfde 100644
--- a/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.3.expect
+++ b/pkg/front_end/testcases/incremental/no_outline_change_35.yaml.world.3.expect
@@ -24,18 +24,20 @@
     abstract member-signature method toString() → dart.core::String*; -> dart.core::Object::toString
     abstract member-signature method noSuchMethod(dart.core::Invocation* invocation) → dynamic; -> dart.core::Object::noSuchMethod
     abstract member-signature get runtimeType() → dart.core::Type*; -> dart.core::Object::runtimeType
+    @#C11
     get x() → dart.core::double*
-      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()));
+      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()));
     set x(dart.core::double* #v) → void
-      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C12).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C13).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+    @#C11
     get y() → dart.core::double*
-      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()));
+      return dart.ffi::_loadDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()));
     set y(dart.core::double* #v) → void
-      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C14).{dart.core::List::[]}(dart.ffi::_abi()), #v);
+      return dart.ffi::_storeDouble(this.{dart.ffi::_Compound::_typedDataBase}, (#C15).{dart.core::List::[]}(dart.ffi::_abi()), #v);
     get next() → dart.ffi::Pointer<lib::Coordinate*>*
-      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C16).{dart.core::List::[]}(dart.ffi::_abi())));
+      return dart.ffi::_fromAddress<lib::Coordinate*>(dart.ffi::_loadIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C17).{dart.core::List::[]}(dart.ffi::_abi())));
     set next(dart.ffi::Pointer<lib::Coordinate*>* #v) → void
-      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C16).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
+      return dart.ffi::_storeIntPtr(this.{dart.ffi::_Compound::_typedDataBase}, (#C17).{dart.core::List::[]}(dart.ffi::_abi()), #v.{dart.ffi::Pointer::address});
   }
 }
 library from "org-dartlang-test:///main.dart" as main {
@@ -61,10 +63,11 @@
   #C8 = 24
   #C9 = 20
   #C10 = <dart.core::int*>[#C8, #C9, #C8]
-  #C11 = 0
-  #C12 = <dart.core::int*>[#C11, #C11, #C11]
-  #C13 = 8
-  #C14 = <dart.core::int*>[#C13, #C13, #C13]
-  #C15 = 16
-  #C16 = <dart.core::int*>[#C15, #C15, #C15]
+  #C11 = dart.ffi::Double {}
+  #C12 = 0
+  #C13 = <dart.core::int*>[#C12, #C12, #C12]
+  #C14 = 8
+  #C15 = <dart.core::int*>[#C14, #C14, #C14]
+  #C16 = 16
+  #C17 = <dart.core::int*>[#C16, #C16, #C16]
 }
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
index b7ef1d7..e69b8a1 100644
--- a/pkg/vm/lib/transformations/ffi_definitions.dart
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -103,9 +103,9 @@
 
   // Data structures for topological navigation.
   Map<Class, IndexedClass> indexedCompoundClasses = {};
-  Map<Class, Set<Class>> compoundClassDependencies = {};
-  Map<Class, bool> fieldsValid = {};
-  Map<Class, CompoundNativeTypeCfe> compoundCache = {};
+  Set<Class> transformCompounds = {};
+  Set<Class> transformCompoundsInvalid = {};
+  Map<Class, NativeTypeCfe> compoundCache = {};
 
   ChangedStructureNotifier changedStructureNotifier;
 
@@ -121,9 +121,53 @@
       : super(index, coreTypes, hierarchy, diagnosticReporter,
             referenceFromIndex) {}
 
+  /// Finds all compound class dependencies.
+  ///
+  /// Works both for transformed and non-transformed compound classes.
+  Set<Class> _compoundClassDependencies(Class node) {
+    final dependencies = <Class>{};
+    final membersWithAnnotations =
+        _compoundFieldMembers(node, includeSetters: false);
+    for (final Member f in membersWithAnnotations) {
+      final type = _compoundMemberType(f);
+      if (isCompoundSubtype(type)) {
+        final clazz = (type as InterfaceType).classNode;
+        dependencies.add(clazz);
+      } else if (isArrayType(type)) {
+        final sizeAnnotations = _getArraySizeAnnotations(f);
+        if (sizeAnnotations.length == 1) {
+          final singleElementType = arraySingleElementType(type);
+          if (isCompoundSubtype(singleElementType)) {
+            final clazz = (singleElementType as InterfaceType).classNode;
+            dependencies.add(clazz);
+          }
+        }
+      }
+    }
+    return dependencies;
+  }
+
+  /// Creates a dependency graph containing all compounds being compiled
+  /// in this compilation, and their transitive dependencies.
+  CompoundDependencyGraph<Class> _compoundDependencyGraph() {
+    Map<Class, Set<Class>> compoundClassDependencies = {};
+    final toProcess = [...transformCompounds, ...transformCompoundsInvalid];
+
+    while (toProcess.isNotEmpty) {
+      final clazz = toProcess.removeLast();
+      if (!compoundClassDependencies.containsKey(clazz)) {
+        final dependencies = _compoundClassDependencies(clazz);
+        compoundClassDependencies[clazz] = dependencies;
+        toProcess.addAll(dependencies);
+      }
+    }
+
+    return CompoundDependencyGraph(compoundClassDependencies);
+  }
+
   void manualVisitInTopologicalOrder() {
-    final connectedComponents = computeStrongComponents(
-        CompoundDependencyGraph(compoundClassDependencies));
+    final dependencyGraph = _compoundDependencyGraph();
+    final connectedComponents = computeStrongComponents(dependencyGraph);
 
     connectedComponents.forEach((List<Class> component) {
       bool report = false;
@@ -132,8 +176,7 @@
         report = true;
       }
       if (component.length == 1) {
-        if (compoundClassDependencies[component.single]
-            .contains(component.single)) {
+        if (dependencyGraph.map[component.single].contains(component.single)) {
           // Direct cycle.
           report = true;
         }
@@ -146,10 +189,31 @@
               e.fileOffset,
               e.name.length,
               e.fileUri);
+          compoundCache[e] = InvalidNativeTypeCfe("Cyclic members.");
+          if (transformCompoundsInvalid.contains(e) ||
+              transformCompounds.contains(e)) {
+            final indexedClass = indexedCompoundClasses[e];
+            _addSizeOfField(e, indexedClass);
+          }
         });
       } else {
         // Only visit the ones without cycles.
-        visitClassInTopologicalOrder(component.single);
+        final clazz = component.single;
+        final compoundData = _findFields(clazz);
+        final compoundType = compoundData.compoundType;
+        compoundCache[clazz] = compoundType;
+        final indexedClass = indexedCompoundClasses[clazz];
+        if (transformCompounds.contains(clazz) &&
+            compoundType is! InvalidNativeTypeCfe) {
+          // Only visit if it has not been transformed yet, and its fields
+          // are valid.
+
+          _replaceFields(clazz, indexedClass, compoundData);
+          _addSizeOfField(clazz, indexedClass, compoundType.size);
+          changedStructureNotifier?.registerClassMemberChange(clazz);
+        } else if (transformCompoundsInvalid.contains(clazz)) {
+          _addSizeOfField(clazz, indexedClass);
+        }
       }
     });
   }
@@ -166,12 +230,19 @@
     return node;
   }
 
-  @override
-  visitClass(Class node) {
+  bool _isUserCompound(Class node) {
     if (!hierarchy.isSubclassOf(node, compoundClass) ||
         node == compoundClass ||
         node == structClass ||
         node == unionClass) {
+      return false;
+    }
+    return true;
+  }
+
+  @override
+  visitClass(Class node) {
+    if (!_isUserCompound(node)) {
       return node;
     }
 
@@ -181,20 +252,17 @@
     _checkConstructors(node, indexedClass);
     indexedCompoundClasses[node] = indexedClass;
 
-    fieldsValid[node] = _checkFieldAnnotations(node, packing);
+    final fieldsValid = _checkFieldAnnotations(node, packing);
+    if (fieldsValid) {
+      // Only do the transformation if the compound is valid.
+      transformCompounds.add(node);
+    } else {
+      transformCompoundsInvalid.add(node);
+    }
 
     return node;
   }
 
-  void visitClassInTopologicalOrder(Class node) {
-    final indexedClass = indexedCompoundClasses[node];
-    if (fieldsValid[node]) {
-      final compoundSize = _replaceFields(node, indexedClass);
-      _replaceSizeOfMethod(node, compoundSize, indexedClass);
-      changedStructureNotifier?.registerClassMemberChange(node);
-    }
-  }
-
   /// Returns packing if any.
   int _checkCompoundClass(Class node) {
     if (node.typeParameters.length > 0) {
@@ -237,25 +305,39 @@
     return null;
   }
 
-  /// Returns members of [node] that correspond to compound fields.
+  /// Returns members of [node] that possibly correspond to compound fields.
   ///
   /// Note that getters and setters that originate from an external field have
   /// the same `fileOffset`, we always returns getters first.
-  List<Member> _compoundFieldMembers(Class node) {
-    final externalGetterSetters = [...node.procedures]
-      ..retainWhere((p) => p.isExternal && (p.isGetter || p.isSetter));
-    final compoundMembers = [...node.fields, ...externalGetterSetters]
-      ..sort((m1, m2) {
+  ///
+  /// This works for both transformed and non-transformed structs.
+  List<Member> _compoundFieldMembers(Class node,
+      {bool possiblyAlreadyTransformed = true, bool includeSetters = true}) {
+    final getterSetters = node.procedures.where((p) {
+      if (!possiblyAlreadyTransformed && !p.isExternal) {
+        // If a struct has not been transformed yet, we have the guarantee
+        // that getters and setters corresponding to native fields are external.
+        return false;
+      }
+      if (p.isSetter && includeSetters) {
+        return true;
+      }
+      return p.isGetter;
+    });
+    final compoundMembers = [...node.fields, ...getterSetters]..sort((m1, m2) {
         if (m1.fileOffset == m2.fileOffset) {
           // Getter and setter have same offset, getter comes first.
-          return (m1 as Procedure).isGetter ? -1 : 1;
+          if (m1 is Procedure) {
+            return m1.isGetter ? -1 : 1;
+          }
+          // Generated fields with fileOffset identical to class, fallthrough.
         }
         return m1.fileOffset - m2.fileOffset;
       });
     return compoundMembers;
   }
 
-  DartType _compoundFieldMemberType(Member member) {
+  DartType _compoundMemberType(Member member) {
     if (member is Field) {
       return member.type;
     }
@@ -268,9 +350,8 @@
 
   bool _checkFieldAnnotations(Class node, int packing) {
     bool success = true;
-    compoundClassDependencies[node] = {};
-    final membersWithAnnotations = _compoundFieldMembers(node)
-      ..retainWhere((m) => (m is Field) || (m is Procedure && m.isGetter));
+    final membersWithAnnotations = _compoundFieldMembers(node,
+        possiblyAlreadyTransformed: false, includeSetters: false);
     for (final Member f in membersWithAnnotations) {
       if (f is Field) {
         if (f.initializer is! NullLiteral) {
@@ -284,7 +365,7 @@
         }
       }
       final nativeTypeAnnos = _getNativeTypeAnnotations(f).toList();
-      final type = _compoundFieldMemberType(f);
+      final type = _compoundMemberType(f);
       if (type is NullType) {
         diagnosticReporter.report(
             templateFfiFieldNull.withArguments(f.name.text),
@@ -307,7 +388,6 @@
         }
         if (isCompoundSubtype(type)) {
           final clazz = (type as InterfaceType).classNode;
-          compoundClassDependencies[node].add(clazz);
           _checkPacking(node, packing, clazz, f);
         } else if (isArrayType(type)) {
           final sizeAnnotations = _getArraySizeAnnotations(f);
@@ -315,7 +395,6 @@
             final singleElementType = arraySingleElementType(type);
             if (isCompoundSubtype(singleElementType)) {
               final clazz = (singleElementType as InterfaceType).classNode;
-              compoundClassDependencies[node].add(clazz);
               _checkPacking(node, packing, clazz, f);
             }
             final dimensions = sizeAnnotations.single;
@@ -462,20 +541,16 @@
     node.addConstructor(ctor);
   }
 
-  /// Computes the field offsets (for all ABIs) in the compound and replaces
-  /// the fields with getters and setters using these offsets.
-  ///
-  /// Returns the total size of the compound (for all ABIs).
-  Map<Abi, int> _replaceFields(Class node, IndexedClass indexedClass) {
+  CompoundData _findFields(Class node) {
     final types = <NativeTypeCfe>[];
     final fields = <int, Field>{};
     final getters = <int, Procedure>{};
     final setters = <int, Procedure>{};
-
     int i = 0;
     for (final Member m in _compoundFieldMembers(node)) {
-      final dartType = _compoundFieldMemberType(m);
+      final dartType = _compoundMemberType(m);
 
+      // Nullable.
       NativeTypeCfe type;
       if (isArrayType(dartType)) {
         final sizeAnnotations = _getArraySizeAnnotations(m).toList();
@@ -508,7 +583,8 @@
       }
       if (m is Procedure && m.isSetter) {
         final index = i - 1; // The corresponding getter's index.
-        if (getters.containsKey(index)) {
+        final getter = getters[index];
+        if (getter != null && getter.name == m.name) {
           setters[i - 1] = m;
         }
       }
@@ -518,8 +594,35 @@
     final packing =
         (!packingAnnotations.isEmpty) ? packingAnnotations.first : null;
 
-    _annoteCompoundWithFields(node, types, packing);
-    if (types.isEmpty) {
+    final compoundType = () {
+      if (types.whereType<InvalidNativeTypeCfe>().isNotEmpty) {
+        return InvalidNativeTypeCfe("Nested member invalid.");
+      }
+      if (node.superclass == structClass) {
+        return StructNativeTypeCfe(node, types, packing: packing);
+      }
+      return UnionNativeTypeCfe(node, types);
+    }();
+
+    List<CompoundField> fieldsFound = [];
+    for (int j = 0; j < i; j++) {
+      fieldsFound
+          .add(CompoundField(types[j], fields[j], getters[j], setters[j]));
+    }
+    return CompoundData(fieldsFound, packing, compoundType);
+  }
+
+  /// Computes the field offsets (for all ABIs) in the compound and replaces
+  /// the fields with getters and setters using these offsets.
+  ///
+  /// Returns the total size of the compound (for all ABIs).
+  void _replaceFields(
+      Class node, IndexedClass indexedClass, CompoundData compoundData) {
+    final compoundType = compoundData.compoundType as CompoundNativeTypeCfe;
+    final compoundLayout = compoundType.layout;
+
+    _annoteCompoundWithFields(node, compoundType.members, compoundData.packing);
+    if (compoundType.members.isEmpty) {
       diagnosticReporter.report(
           templateFfiEmptyStruct.withArguments(node.superclass.name, node.name),
           node.fileOffset,
@@ -527,53 +630,46 @@
           node.location.file);
     }
 
-    final compoundType = node.superclass == structClass
-        ? StructNativeTypeCfe(node, types, packing: packing)
-        : UnionNativeTypeCfe(node, types);
-    compoundCache[node] = compoundType;
-    final compoundLayout = compoundType.layout;
+    final unalignedAccess = compoundData.packing != null;
 
-    final unalignedAccess = packing != null;
-    for (final i in fields.keys) {
+    int i = 0;
+    for (final compoundField in compoundData.compoundFields) {
+      NativeTypeCfe type = compoundField.type;
+      Field field = compoundField.field;
+      Procedure getter = compoundField.getter;
+      Procedure setter = compoundField.setter;
+
       final fieldOffsets = compoundLayout
           .map((Abi abi, CompoundLayout v) => MapEntry(abi, v.offsets[i]));
-      final methods = _generateMethodsForField(
-          fields[i], types[i], fieldOffsets, unalignedAccess, indexedClass);
-      methods.forEach((p) => node.addProcedure(p));
-    }
 
-    for (final Field f in fields.values) {
-      node.fields.remove(f);
-    }
+      if (field != null) {
+        _generateMethodsForField(
+            node, field, type, fieldOffsets, unalignedAccess, indexedClass);
+      }
 
-    for (final i in getters.keys) {
-      final fieldOffsets = compoundLayout
-          .map((Abi abi, CompoundLayout v) => MapEntry(abi, v.offsets[i]));
-      Procedure getter = getters[i];
-      getter.function.body = types[i].generateGetterStatement(
-          getter.function.returnType,
-          getter.fileOffset,
-          fieldOffsets,
-          unalignedAccess,
-          this);
-      getter.isExternal = false;
-    }
+      if (getter != null) {
+        getter.function.body = type.generateGetterStatement(
+            getter.function.returnType,
+            getter.fileOffset,
+            fieldOffsets,
+            unalignedAccess,
+            this);
+        getter.isExternal = false;
+      }
 
-    for (final i in setters.keys) {
-      final fieldOffsets = compoundLayout
-          .map((Abi abi, CompoundLayout v) => MapEntry(abi, v.offsets[i]));
-      Procedure setter = setters[i];
-      setter.function.body = types[i].generateSetterStatement(
-          setter.function.positionalParameters.single.type,
-          setter.fileOffset,
-          fieldOffsets,
-          unalignedAccess,
-          setter.function.positionalParameters.single,
-          this);
-      setter.isExternal = false;
-    }
+      if (setter != null) {
+        setter.function.body = type.generateSetterStatement(
+            setter.function.positionalParameters.single.type,
+            setter.fileOffset,
+            fieldOffsets,
+            unalignedAccess,
+            setter.function.positionalParameters.single,
+            this);
+        setter.isExternal = false;
+      }
 
-    return compoundLayout.map((k, v) => MapEntry(k, v.size));
+      i++;
+    }
   }
 
   // packing is `int?`.
@@ -596,7 +692,7 @@
         InterfaceType(pragmaClass, Nullability.nonNullable, [])));
   }
 
-  List<Procedure> _generateMethodsForField(Field field, NativeTypeCfe type,
+  void _generateMethodsForField(Class node, Field field, NativeTypeCfe type,
       Map<Abi, int> offsets, bool unalignedAccess, IndexedClass indexedClass) {
     // TODO(johnniwinther): Avoid passing [indexedClass]. When compiling
     // incrementally, [field] should already carry the references from
@@ -612,9 +708,10 @@
         FunctionNode(getterStatement, returnType: field.type),
         fileUri: field.fileUri, reference: getterReference)
       ..fileOffset = field.fileOffset
-      ..isNonNullableByDefault = field.isNonNullableByDefault;
+      ..isNonNullableByDefault = field.isNonNullableByDefault
+      ..annotations = field.annotations;
+    node.addProcedure(getter);
 
-    Procedure setter = null;
     if (!field.isFinal) {
       Reference setterReference =
           indexedClass?.lookupSetterReference(field.name) ??
@@ -626,7 +723,7 @@
             ..fileOffset = field.fileOffset;
       final setterStatement = type.generateSetterStatement(field.type,
           field.fileOffset, offsets, unalignedAccess, argument, this);
-      setter = Procedure(
+      final setter = Procedure(
           field.name,
           ProcedureKind.Setter,
           FunctionNode(setterStatement,
@@ -635,15 +732,22 @@
           reference: setterReference)
         ..fileOffset = field.fileOffset
         ..isNonNullableByDefault = field.isNonNullableByDefault;
+      node.addProcedure(setter);
     }
 
-    return [getter, if (setter != null) setter];
+    node.fields.remove(field);
   }
 
   /// Sample output:
-  /// int #sizeOf => [24,24,16][_abi()];
-  void _replaceSizeOfMethod(
-      Class compound, Map<Abi, int> sizes, IndexedClass indexedClass) {
+  /// final int #sizeOf = [24,24,16][_abi()];
+  ///
+  /// If sizes are not supplied still emits a field so that the use site
+  /// transformer can still rewrite to it.
+  void _addSizeOfField(Class compound, IndexedClass indexedClass,
+      [Map<Abi, int> sizes = null]) {
+    if (sizes == null) {
+      sizes = Map.fromEntries(Abi.values.map((abi) => MapEntry(abi, 0)));
+    }
     var name = Name("#sizeOf");
     var getterReference = indexedClass?.lookupGetterReference(name);
     final Field sizeOf = Field.immutable(name,
@@ -725,6 +829,32 @@
   }
 }
 
+class CompoundData {
+  final List<CompoundField> compoundFields;
+
+  // Nullable.
+  final int packing;
+
+  final NativeTypeCfe compoundType;
+
+  CompoundData(this.compoundFields, this.packing, this.compoundType);
+}
+
+class CompoundField {
+  final NativeTypeCfe type;
+
+  // Nullable.
+  final Field field;
+
+  // Nullable.
+  final Procedure getter;
+
+  // Nullable.
+  final Procedure setter;
+
+  CompoundField(this.type, this.field, this.getter, this.setter);
+}
+
 /// The layout of a `Struct` or `Union` in one [Abi].
 class CompoundLayout {
   /// Size of the entire struct or union.
@@ -748,7 +878,7 @@
 abstract class NativeTypeCfe {
   factory NativeTypeCfe(FfiTransformer transformer, DartType dartType,
       {List<int> arrayDimensions,
-      Map<Class, CompoundNativeTypeCfe> compoundCache = const {}}) {
+      Map<Class, NativeTypeCfe> compoundCache = const {}}) {
     if (transformer.isPrimitiveType(dartType)) {
       final clazz = (dartType as InterfaceType).classNode;
       final nativeType = transformer.getType(clazz);
@@ -772,6 +902,9 @@
       final elementType = transformer.arraySingleElementType(dartType);
       final elementCfeType =
           NativeTypeCfe(transformer, elementType, compoundCache: compoundCache);
+      if (elementCfeType is InvalidNativeTypeCfe) {
+        return elementCfeType;
+      }
       return ArrayNativeTypeCfe.multi(elementCfeType, arrayDimensions);
     }
     throw "Invalid type $dartType";
@@ -810,6 +943,40 @@
       FfiTransformer transformer);
 }
 
+class InvalidNativeTypeCfe implements NativeTypeCfe {
+  final String reason;
+
+  InvalidNativeTypeCfe(this.reason);
+
+  @override
+  Map<Abi, int> get alignment => throw reason;
+
+  @override
+  Constant generateConstant(FfiTransformer transformer) => throw reason;
+
+  @override
+  ReturnStatement generateGetterStatement(
+          DartType dartType,
+          int fileOffset,
+          Map<Abi, int> offsets,
+          bool unalignedAccess,
+          FfiTransformer transformer) =>
+      throw reason;
+
+  @override
+  ReturnStatement generateSetterStatement(
+          DartType dartType,
+          int fileOffset,
+          Map<Abi, int> offsets,
+          bool unalignedAccess,
+          VariableDeclaration argument,
+          FfiTransformer transformer) =>
+      throw reason;
+
+  @override
+  Map<Abi, int> get size => throw reason;
+}
+
 class PrimitiveNativeTypeCfe implements NativeTypeCfe {
   final NativeType nativeType;
 
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
index 860c2d2..8f9b4a3 100644
--- a/pkg/vm/lib/transformations/ffi_use_sites.dart
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -388,7 +388,8 @@
     final NativeType nt = getType(nativeClass);
     if (nt == null) {
       // User-defined compounds.
-      Field sizeOfField = nativeClass.fields.single;
+      Field sizeOfField = nativeClass.fields
+          .firstWhere((field) => field.name == Name('#sizeOf'));
       return StaticGet(sizeOfField);
     }
     final int size = nativeTypeSizes[nt.index];
@@ -505,8 +506,8 @@
         PropertyGet(NullCheck(node.arguments.positional[0]),
             arrayTypedDataBaseField.name, arrayTypedDataBaseField),
         MethodInvocation(node.arguments.positional[1], numMultiplication.name,
-            Arguments([StaticGet(clazz.fields.single)]), numMultiplication),
-        StaticGet(clazz.fields.single),
+            Arguments([_inlineSizeOf(dartType)]), numMultiplication),
+        _inlineSizeOf(dartType),
         dartType,
         node.fileOffset);
 
diff --git a/tools/VERSION b/tools/VERSION
index f349f1c..6ae49c3 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 88
+PRERELEASE 89
 PRERELEASE_PATCH 0
\ No newline at end of file