[vm/kernel] Recognize desugared mixin applications in dart:mirrors

Kernel mixin transformation desugars mixin applications into normal
classes. Mixed-in type is pulled into interfaces list.
However, dart:mirrors needs to know the original mixed-in type of
a mixin application.

This change solves this problem by propagating a 'isTransformedMixinApplication'
attribute of a class through kernel AST, kernel binary and VM objects
into dart:mirrors implementation.

Fixes: https://github.com/dart-lang/sdk/issues/33240
Change-Id: I98ca69294e1ad445402a5ca91d90c30447aabcb2
Reviewed-on: https://dart-review.googlesource.com/56721
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Siva Annamalai <asiva@google.com>
Reviewed-by: Kevin Millikin <kmillikin@google.com>
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index ac82f5f..822d245 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -1281,7 +1281,7 @@
         if (_kernel.mixedInType != null) {
           _kernelMixins.add(_kernel.mixedInType);
         }
-        while (supertype.classNode.isSyntheticMixinImplementation) {
+        while (supertype.classNode.isAnonymousMixin) {
           var superNode = supertype.classNode;
           var substitute = kernel.Substitution.fromSupertype(supertype);
 
@@ -1855,7 +1855,7 @@
   List<ClassElement> get types {
     if (_kernelContext != null) {
       _types ??= _kernelContext.kernelUnit.classes
-          .where((k) => !k.isEnum && !k.isSyntheticMixinImplementation)
+          .where((k) => !k.isEnum && !k.isAnonymousMixin)
           .map((k) => new ClassElementImpl.forKernel(this, k))
           .toList(growable: false);
     }
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index c9b9d93..dde76e85 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -297,7 +297,7 @@
   ClassEnvImpl.internal(this.cls, this._constructorMap, this._memberMap,
       this._setterMap, this._members);
 
-  bool get isUnnamedMixinApplication => cls.isSyntheticMixinImplementation;
+  bool get isUnnamedMixinApplication => cls.isAnonymousMixin;
 
   /// Copied from 'package:kernel/transformations/mixin_full_resolution.dart'.
   ir.Constructor _buildForwardingConstructor(
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index b296f10..a8478d6 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -522,7 +522,7 @@
 
   JS.Statement _emitClassDeclaration(Class c) {
     // Mixins are unrolled in _defineClass.
-    if (c.isSyntheticMixinImplementation) return null;
+    if (c.isAnonymousMixin) return null;
 
     // If this class is annotated with `@JS`, then there is nothing to emit.
     if (findAnnotation(c, isPublicJSAnnotation) != null) return null;
@@ -820,7 +820,7 @@
   /// Defines all constructors for this class as ES5 constructors.
   List<JS.Statement> _defineConstructors(Class c, JS.Expression className) {
     var body = <JS.Statement>[];
-    if (c.isSyntheticMixinImplementation || isMixinAliasClass(c)) {
+    if (c.isAnonymousMixin || isMixinAliasClass(c)) {
       // We already handled this when we defined the class.
       return body;
     }
diff --git a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
index dc11518..44a8f0f 100644
--- a/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
+++ b/pkg/dev_compiler/lib/src/kernel/kernel_helpers.dart
@@ -227,7 +227,7 @@
   if (mixedInClass != null) mixins.add(mixedInClass);
 
   var sc = c.superclass;
-  for (; sc.isSyntheticMixinImplementation; sc = sc.superclass) {
+  for (; sc.isAnonymousMixin; sc = sc.superclass) {
     mixins.add(sc.mixedInClass);
   }
   return sc;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 81b4f1f..c25088e 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -449,8 +449,7 @@
         // TODO(ahe, kmillikin): Should always be true?
         // pkg/analyzer/test/src/summary/resynthesize_kernel_test.dart can't
         // handle that :(
-        application.cls.isSyntheticMixinImplementation =
-            !isNamedMixinApplication;
+        application.cls.isAnonymousMixin = !isNamedMixinApplication;
         addBuilder(fullname, application, charOffset);
         supertype =
             addNamedType(fullname, applicationTypeArguments, charOffset);
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 5b02dc9..7507777 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -664,7 +664,7 @@
     TypeEnvironment env = new TypeEnvironment(coreTypes, hierarchy,
         strongMode: target.strongMode);
 
-    if (cls.isSyntheticMixinImplementation) return;
+    if (cls.isAnonymousMixin) return;
 
     if (env.isSubtypeOf(a.asInterfaceType, b.asInterfaceType)) return;
     addProblem(
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 58c6532..361dd77 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -1634,7 +1634,7 @@
       Supertype baseType, Supertype mixinSupertype) {
     if (mixinSupertype.typeArguments.isEmpty) {
       // The supertype constraint isn't generic; it doesn't constrain anything.
-    } else if (mixinSupertype.classNode.isSyntheticMixinImplementation) {
+    } else if (mixinSupertype.classNode.isAnonymousMixin) {
       // We had a mixin M<X0, ..., Xn> with a superclass constraint of the form
       // S0 with M0 where S0 and M0 each possibly have type arguments.  That has
       // been compiled a named mixin application class of the form
diff --git a/pkg/front_end/test/incremental_utils.dart b/pkg/front_end/test/incremental_utils.dart
index c8480bf..ef4626a 100644
--- a/pkg/front_end/test/incremental_utils.dart
+++ b/pkg/front_end/test/incremental_utils.dart
@@ -33,7 +33,7 @@
   int empty = 0;
   for (Library lib in component.libraries) {
     for (Class c in lib.classes) {
-      if (c.isSyntheticMixinImplementation) {
+      if (c.isAnonymousMixin) {
         for (Procedure p in c.procedures) {
           if (p.function.body is EmptyStatement) {
             empty++;
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 13b28bf..d94fb18 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -131,7 +131,7 @@
 
 type ComponentFile {
   UInt32 magic = 0x90ABCDEF;
-  UInt32 formatVersion = 6;
+  UInt32 formatVersion = 7;
   Library[] libraries;
   UriSource sourceMap;
   List<CanonicalName> canonicalNames;
@@ -286,11 +286,14 @@
   UriReference fileUri;
   FileOffset fileOffset;
   FileOffset fileEndOffset;
-  Byte flags (isAbstract, isEnum, xx); // Where xx is index into ClassLevel
+  Byte flags (levelBit0, levelBit1, isAbstract, isEnum, isAnonymousMixin,
+              isEliminatedMixin); // Where level is index into ClassLevel
   StringReference name;
   List<Expression> annotations;
   List<TypeParameter> typeParameters;
   Option<DartType> superClass;
+  // For transformed mixin application classes (isEliminatedMixin),
+  // original mixedInType is pulled into the end of implementedClasses.
   Option<DartType> mixedInType;
   List<DartType> implementedClasses;
   List<Field> fields;
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index afe96c6..f7367b9 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -696,10 +696,28 @@
   /// applications.
   @coq
   String name;
-  bool isAbstract;
+
+  // Must match serialized bit positions.
+  static const int LevelMask = 0x3; // Bits 0 and 1.
+  static const int FlagAbstract = 1 << 2;
+  static const int FlagEnum = 1 << 3;
+  static const int FlagAnonymousMixin = 1 << 4;
+  static const int FlagEliminatedMixin = 1 << 5;
+
+  int flags = 0;
+
+  bool get isAbstract => flags & FlagAbstract != 0;
+
+  void set isAbstract(bool value) {
+    flags = value ? (flags | FlagAbstract) : (flags & ~FlagAbstract);
+  }
 
   /// Whether this class is an enum.
-  bool isEnum = false;
+  bool get isEnum => flags & FlagEnum != 0;
+
+  void set isEnum(bool value) {
+    flags = value ? (flags | FlagEnum) : (flags & ~FlagEnum);
+  }
 
   /// Whether this class is a synthetic implementation created for each
   /// mixed-in class. For example the following code:
@@ -714,7 +732,22 @@
   /// abstract class A&B&C&D extends A&B&C mixedIn D {}
   /// class Z extends A&B&C&D {}
   /// All X&Y classes are marked as synthetic.
-  bool isSyntheticMixinImplementation;
+  bool get isAnonymousMixin => flags & FlagAnonymousMixin != 0;
+
+  void set isAnonymousMixin(bool value) {
+    flags =
+        value ? (flags | FlagAnonymousMixin) : (flags & ~FlagAnonymousMixin);
+  }
+
+  /// Whether this class was transformed from a mixin application.
+  /// In such case, its mixed-in type was pulled into the end of implemented
+  /// types list.
+  bool get isEliminatedMixin => flags & FlagEliminatedMixin != 0;
+
+  void set isEliminatedMixin(bool value) {
+    flags =
+        value ? (flags | FlagEliminatedMixin) : (flags & ~FlagEliminatedMixin);
+  }
 
   /// The URI of the source file this class was loaded from.
   Uri fileUri;
@@ -750,8 +783,8 @@
 
   Class(
       {this.name,
-      this.isAbstract: false,
-      this.isSyntheticMixinImplementation: false,
+      bool isAbstract: false,
+      bool isAnonymousMixin: false,
       this.supertype,
       this.mixedInType,
       List<TypeParameter> typeParameters,
@@ -775,6 +808,8 @@
     setParents(this.procedures, this);
     setParents(this.fields, this);
     setParents(this.redirectingFactoryConstructors, this);
+    this.isAbstract = isAbstract;
+    this.isAnonymousMixin = isAnonymousMixin;
   }
 
   void computeCanonicalNames() {
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index b75a3a3..5e01828 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -847,10 +847,8 @@
     node.fileOffset = readOffset();
     node.fileEndOffset = readOffset();
     int flags = readByte();
-    node.isAbstract = flags & 0x1 != 0;
-    node.isEnum = flags & 0x2 != 0;
-    node.isSyntheticMixinImplementation = flags & 0x4 != 0;
-    int levelIndex = (flags >> 3) & 0x3;
+    node.flags = flags & ~Class.LevelMask;
+    int levelIndex = flags & Class.LevelMask;
     var level = ClassLevel.values[levelIndex + 1];
     if (level.index >= node.level.index) {
       node.level = level;
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 156d80b..ed89e92 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -725,25 +725,18 @@
     }
   }
 
-  int _encodeClassFlags(bool isAbstract, bool isEnum,
-      bool isSyntheticMixinImplementation, ClassLevel level) {
-    int abstractFlag = isAbstract ? 1 : 0;
-    int isEnumFlag = isEnum ? 2 : 0;
-    int isSyntheticMixinImplementationFlag =
-        isSyntheticMixinImplementation ? 4 : 0;
-    int levelFlags = (level.index - 1) << 3;
-    return abstractFlag |
-        isEnumFlag |
-        isSyntheticMixinImplementationFlag |
-        levelFlags;
+  int _encodeClassFlags(int flags, ClassLevel level) {
+    assert((flags & Class.LevelMask) == 0);
+    final levelIndex = level.index - 1;
+    assert((levelIndex & Class.LevelMask) == levelIndex);
+    return flags | levelIndex;
   }
 
   @override
   void visitClass(Class node) {
     classOffsets.add(getBufferOffset());
 
-    int flags = _encodeClassFlags(node.isAbstract, node.isEnum,
-        node.isSyntheticMixinImplementation, node.level);
+    int flags = _encodeClassFlags(node.flags, node.level);
     if (node.canonicalName == null) {
       throw 'Missing canonical name for $node';
     }
diff --git a/pkg/kernel/lib/binary/tag.dart b/pkg/kernel/lib/binary/tag.dart
index 1d016af..9bb574b0 100644
--- a/pkg/kernel/lib/binary/tag.dart
+++ b/pkg/kernel/lib/binary/tag.dart
@@ -135,7 +135,7 @@
   /// Internal version of kernel binary format.
   /// Bump it when making incompatible changes in kernel binaries.
   /// Keep in sync with runtime/vm/kernel_binary.h, pkg/kernel/binary.md.
-  static const int BinaryFormatVersion = 6;
+  static const int BinaryFormatVersion = 7;
 }
 
 abstract class ConstantTag {
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 3a9a036..ab527e5 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -23,7 +23,7 @@
       {HandleAmbiguousSupertypes onAmbiguousSupertypes,
       MixinInferrer mixinInferrer}) {
     onAmbiguousSupertypes ??= (Class cls, Supertype a, Supertype b) {
-      if (!cls.isSyntheticMixinImplementation) {
+      if (!cls.isAnonymousMixin) {
         // See https://github.com/dart-lang/sdk/issues/32091
         throw "$cls can't implement both $a and $b";
       }
diff --git a/pkg/kernel/lib/transformations/mixin_full_resolution.dart b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
index a2f392620..d546fe4 100644
--- a/pkg/kernel/lib/transformations/mixin_full_resolution.dart
+++ b/pkg/kernel/lib/transformations/mixin_full_resolution.dart
@@ -232,11 +232,15 @@
       }
     }
 
-    // This class implements the mixin type.
+    // This class implements the mixin type. Also, backends rely on the fact
+    // that eliminated mixin is appended into the end of interfaces list.
     class_.implementedTypes.add(class_.mixedInType);
 
     // This class is now a normal class.
     class_.mixedInType = null;
+
+    // Leave breadcrumbs for backends (e.g. for dart:mirrors implementation).
+    class_.isEliminatedMixin = true;
   }
 
   Constructor buildForwardingConstructor(
diff --git a/pkg/vm/lib/transformations/mixin_deduplication.dart b/pkg/vm/lib/transformations/mixin_deduplication.dart
index 2daf9a0..68ade75 100644
--- a/pkg/vm/lib/transformations/mixin_deduplication.dart
+++ b/pkg/vm/lib/transformations/mixin_deduplication.dart
@@ -79,7 +79,7 @@
       _transformSupertype(c);
     }
 
-    if (!c.isSyntheticMixinImplementation) {
+    if (!c.isAnonymousMixin) {
       return c;
     }
 
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 3524eef..1651cfa 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -313,7 +313,7 @@
     return CreateTypedefMirror(cls, type, is_declaration, owner_mirror);
   }
 
-  const Array& args = Array::Handle(Array::New(9));
+  const Array& args = Array::Handle(Array::New(10));
   args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
   args.SetAt(1, type);
   // Note that the VM does not consider mixin application aliases to be mixin
@@ -328,8 +328,9 @@
   args.SetAt(4, Bool::Get(cls.is_abstract()));
   args.SetAt(5, Bool::Get(cls.IsGeneric()));
   args.SetAt(6, Bool::Get(cls.is_mixin_app_alias()));
-  args.SetAt(7, cls.NumTypeParameters() == 0 ? Bool::False() : is_declaration);
-  args.SetAt(8, Bool::Get(cls.is_enum_class()));
+  args.SetAt(7, Bool::Get(cls.is_transformed_mixin_application()));
+  args.SetAt(8, cls.NumTypeParameters() == 0 ? Bool::False() : is_declaration);
+  args.SetAt(9, Bool::Get(cls.is_enum_class()));
   return CreateMirror(Symbols::_LocalClassMirror(), args);
 }
 
@@ -993,7 +994,13 @@
   PROPAGATE_IF_MALFORMED(type);
   ASSERT(type.IsFinalized());
   const Class& cls = Class::Handle(type.type_class());
-  const AbstractType& mixin_type = AbstractType::Handle(cls.mixin());
+  AbstractType& mixin_type = AbstractType::Handle();
+  if (cls.is_transformed_mixin_application()) {
+    const Array& interfaces = Array::Handle(cls.interfaces());
+    mixin_type ^= interfaces.At(interfaces.Length() - 1);
+  } else {
+    mixin_type = cls.mixin();
+  }
   ASSERT(mixin_type.IsNull() || mixin_type.IsFinalized());
   return mixin_type.raw();
 }
@@ -1005,7 +1012,13 @@
   PROPAGATE_IF_MALFORMED(type);
   ASSERT(type.IsFinalized());
   const Class& cls = Class::Handle(type.type_class());
-  const AbstractType& mixin_type = AbstractType::Handle(cls.mixin());
+  AbstractType& mixin_type = AbstractType::Handle();
+  if (cls.is_transformed_mixin_application()) {
+    const Array& interfaces = Array::Handle(cls.interfaces());
+    mixin_type ^= interfaces.At(interfaces.Length() - 1);
+  } else {
+    mixin_type = cls.mixin();
+  }
   if (mixin_type.IsNull()) {
     return mixin_type.raw();
   }
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 5c42dc4..eb0becb 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -356,7 +356,16 @@
   DeclarationMirror _owner;
   final bool isAbstract;
   final bool _isGeneric;
+
+  // Only used for Dart 1 named mixin applications.
+  // TODO(alexmarkov): Clean up after Dart 1 is gone.
   final bool _isMixinAlias;
+
+  // Since Dart 2, mixins are erased by kernel transformation.
+  // Resulting classes have this flag set, and mixed-in type is pulled into
+  // the end of interfaces list.
+  final bool _isTransformedMixinApplication;
+
   final bool _isGenericDeclaration;
   final bool isEnum;
   Type _instantiator;
@@ -369,6 +378,7 @@
       this.isAbstract,
       this._isGeneric,
       this._isMixinAlias,
+      this._isTransformedMixinApplication,
       this._isGenericDeclaration,
       this.isEnum)
       : this._simpleName = _s(simpleName),
@@ -443,6 +453,9 @@
       var interfaceTypes = isOriginalDeclaration
           ? _nativeInterfaces(_reflectedType)
           : _nativeInterfacesInstantiated(_reflectedType);
+      if (_isTransformedMixinApplication) {
+        interfaceTypes = interfaceTypes.sublist(0, interfaceTypes.length - 1);
+      }
       var interfaceMirrors = new List<ClassMirror>();
       for (var interfaceType in interfaceTypes) {
         interfaceMirrors.add(reflectType(interfaceType));
@@ -570,6 +583,7 @@
         new UnmodifiableMapView<Symbol, DeclarationMirror>(decls);
   }
 
+  // Note: returns correct result only for Dart 1 anonymous mixin applications.
   bool get _isAnonymousMixinApplication {
     if (_isMixinAlias) return false; // Named mixin application.
     if (mixin == this) return false; // Not a mixin application.
@@ -579,7 +593,7 @@
   List<TypeVariableMirror> _typeVariables;
   List<TypeVariableMirror> get typeVariables {
     if (_typeVariables == null) {
-      if (_isAnonymousMixinApplication) {
+      if (!_isTransformedMixinApplication && _isAnonymousMixinApplication) {
         return _typeVariables = const <TypeVariableMirror>[];
       }
       _typeVariables = new List<TypeVariableMirror>();
@@ -600,7 +614,8 @@
   List<TypeMirror> _typeArguments;
   List<TypeMirror> get typeArguments {
     if (_typeArguments == null) {
-      if (_isGenericDeclaration || _isAnonymousMixinApplication) {
+      if (_isGenericDeclaration ||
+          (!_isTransformedMixinApplication && _isAnonymousMixinApplication)) {
         _typeArguments = const <TypeMirror>[];
       } else {
         _typeArguments = new UnmodifiableListView<TypeMirror>(
@@ -734,7 +749,7 @@
   final _functionReflectee;
   _LocalFunctionTypeMirror(reflectee, this._functionReflectee, reflectedType)
       : super(reflectee, reflectedType, null, null, false, false, false, false,
-            false);
+            false, false);
 
   bool get _isAnonymousMixinApplication => false;
 
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index c83ac76..859d443 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -431,8 +431,10 @@
   };
 
   enum Flag {
-    kIsAbstract = 1,
-    kIsEnumClass = 2,
+    kIsAbstract = 1 << 2,
+    kIsEnumClass = 1 << 3,
+    kIsAnonymousMixin = 1 << 4,
+    kIsEliminatedMixin = 1 << 5,
   };
 
   explicit ClassHelper(KernelReaderHelper* helper)
@@ -447,9 +449,13 @@
   void SetNext(Field field) { next_read_ = field; }
   void SetJustRead(Field field) { next_read_ = field + 1; }
 
-  bool is_abstract() { return flags_ & Flag::kIsAbstract; }
+  bool is_abstract() const { return flags_ & Flag::kIsAbstract; }
 
-  bool is_enum_class() { return flags_ & Flag::kIsEnumClass; }
+  bool is_enum_class() const { return flags_ & Flag::kIsEnumClass; }
+
+  bool is_transformed_mixin_application() const {
+    return flags_ & Flag::kIsEliminatedMixin;
+  }
 
   NameIndex canonical_name_;
   TokenPosition position_;
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index ba05ff0..70a967b 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -20,7 +20,7 @@
 // package:kernel/binary.md.
 
 static const uint32_t kMagicProgramFile = 0x90ABCDEFu;
-static const uint32_t kBinaryFormatVersion = 6;
+static const uint32_t kBinaryFormatVersion = 7;
 
 // Keep in sync with package:kernel/lib/binary/tag.dart
 #define KERNEL_TAG_LIST(V)                                                     \
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index 607c1e9..e7f45d2 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -967,6 +967,10 @@
   klass->set_interfaces(interfaces);
 
   if (class_helper->is_abstract()) klass->set_is_abstract();
+
+  if (class_helper->is_transformed_mixin_application()) {
+    klass->set_is_transformed_mixin_application();
+  }
 }
 
 // Workaround for http://dartbug.com/32087: currently Kernel front-end
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index de61db2..d379d22 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -3792,6 +3792,11 @@
   set_state_bits(MixinTypeAppliedBit::update(true, raw_ptr()->state_bits_));
 }
 
+void Class::set_is_transformed_mixin_application() const {
+  set_state_bits(
+      TransformedMixinApplicationBit::update(true, raw_ptr()->state_bits_));
+}
+
 void Class::set_is_fields_marked_nullable() const {
   set_state_bits(FieldsMarkedNullableBit::update(true, raw_ptr()->state_bits_));
 }
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 1d8dc12..ee04799 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -1311,6 +1311,17 @@
   }
   void set_is_mixin_type_applied() const;
 
+  // Tests if this is a mixin application class which was desugared
+  // to a normal class by kernel mixin transformation
+  // (pkg/kernel/lib/transformations/mixin_full_resolution.dart).
+  //
+  // In such case, its mixed-in type was pulled into the end of
+  // interfaces list.
+  bool is_transformed_mixin_application() const {
+    return TransformedMixinApplicationBit::decode(raw_ptr()->state_bits_);
+  }
+  void set_is_transformed_mixin_application() const;
+
   bool is_fields_marked_nullable() const {
     return FieldsMarkedNullableBit::decode(raw_ptr()->state_bits_);
   }
@@ -1470,6 +1481,7 @@
     kFieldsMarkedNullableBit = 11,
     kCycleFreeBit = 12,
     kEnumBit = 13,
+    kTransformedMixinApplicationBit = 14,
     kIsAllocatedBit = 15,
   };
   class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
@@ -1494,6 +1506,8 @@
       : public BitField<uint16_t, bool, kFieldsMarkedNullableBit, 1> {};
   class CycleFreeBit : public BitField<uint16_t, bool, kCycleFreeBit, 1> {};
   class EnumBit : public BitField<uint16_t, bool, kEnumBit, 1> {};
+  class TransformedMixinApplicationBit
+      : public BitField<uint16_t, bool, kTransformedMixinApplicationBit, 1> {};
   class IsAllocatedBit : public BitField<uint16_t, bool, kIsAllocatedBit, 1> {};
 
   void set_name(const String& value) const;
diff --git a/tests/lib_2/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index 63aa705..da72614 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -133,12 +133,9 @@
 mirrors/generic_f_bounded_mixin_application_test: RuntimeError
 mirrors/generic_function_typedef_test: RuntimeError
 mirrors/generic_interface_test/01: RuntimeError
-mirrors/generic_interface_test/none: RuntimeError
 mirrors/generic_mixin_applications_test: RuntimeError
-mirrors/generic_mixin_test: RuntimeError
 mirrors/hot_get_field_test: RuntimeError
 mirrors/hot_set_field_test: RuntimeError
-mirrors/intercepted_object_test: RuntimeError # Issue 31402 (Invocation arguments)
 mirrors/invocation_fuzz_test: RuntimeError, Crash
 mirrors/invoke_private_test: RuntimeError
 mirrors/invoke_private_wrong_library_test: RuntimeError
@@ -171,8 +168,6 @@
 mirrors/mirrors_used_typedef_declaration_test/none: RuntimeError
 mirrors/mixin_application_test: RuntimeError # Issue 31402 (Invocation arguments)
 mirrors/mixin_members_test: CompileTimeError # Issue 31402 (Invocation arguments)
-mirrors/mixin_simple_test: RuntimeError
-mirrors/mixin_test: RuntimeError
 mirrors/native_class_test: SkipByDesign # Imports dart:html
 mirrors/operator_test: CompileTimeError # Issue 31402 (Invocation arguments)
 mirrors/other_declarations_location_test: RuntimeError