Version 2.10.0-68.0.dev

Merge commit '771fcaf63288f7f346aad8fb48604f0971b1c88c' into 'dev'
diff --git a/DEPS b/DEPS
index 98aeca7..6a63c4a 100644
--- a/DEPS
+++ b/DEPS
@@ -44,7 +44,7 @@
   # co19 is a cipd package. Use update.sh in tests/co19[_2] to update these
   # hashes. It requires access to the dart-build-access group, which EngProd
   # has.
-  "co19_rev": "741384c83190cdaa648bf77aefcf4b6c0ec75988",
+  "co19_rev": "826fba7da0ec78f93989b5104e91e46a3ecc52d0",
   "co19_2_rev": "e48b3090826cf40b8037648f19d211e8eab1b4b6",
 
   # The internal benchmarks to use. See go/dart-benchmarks-internal
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
index 12d346c..386dd91 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/forwarding_listener.dart
@@ -13,11 +13,6 @@
   ForwardingListener([this.listener]);
 
   @override
-  set suppressParseErrors(bool value) {
-    listener?.suppressParseErrors = value;
-  }
-
-  @override
   Uri get uri => listener?.uri;
 
   @override
@@ -463,11 +458,6 @@
   }
 
   @override
-  void discardTypeReplacedWithCommentTypeAssign() {
-    listener?.discardTypeReplacedWithCommentTypeAssign();
-  }
-
-  @override
   void endArguments(int count, Token beginToken, Token endToken) {
     listener?.endArguments(count, beginToken, endToken);
   }
diff --git a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
index 735b41c..0d57f76 100644
--- a/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/parser/listener.dart
@@ -44,8 +44,6 @@
 
   void logEvent(String name) {}
 
-  set suppressParseErrors(bool value) {}
-
   void beginArguments(Token token) {}
 
   void endArguments(int count, Token beginToken, Token endToken) {
@@ -1630,11 +1628,6 @@
     logEvent("Script");
   }
 
-  /// A type has been just parsed, and the parser noticed that the next token
-  /// has a type substitution comment /*=T*. So, the type that has been just
-  /// parsed should be discarded, and a new type should be parsed instead.
-  void discardTypeReplacedWithCommentTypeAssign() {}
-
   /// A single comment reference has been found
   /// where [referenceSource] is the text between the `[` and `]`
   /// and [referenceOffset] is the character offset in the token stream.
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index e0ed8b3..4fd12b4 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -487,11 +487,6 @@
     // printEvent('AstBuilder: $name');
   }
 
-  @override
-  void discardTypeReplacedWithCommentTypeAssign() {
-    pop();
-  }
-
   void doDotExpression(Token dot) {
     Expression identifierOrInvoke = pop();
     Expression receiver = pop();
diff --git a/pkg/front_end/test/parser_test_listener.dart b/pkg/front_end/test/parser_test_listener.dart
index cfccc6a..d9e3e7e 100644
--- a/pkg/front_end/test/parser_test_listener.dart
+++ b/pkg/front_end/test/parser_test_listener.dart
@@ -58,10 +58,6 @@
     doPrint('logEvent(' '$name)');
   }
 
-  set suppressParseErrors(bool value) {
-    doPrint('suppressParseErrors(' '$value)');
-  }
-
   void beginArguments(Token token) {
     seen(token);
     doPrint('beginArguments(' '$token)');
@@ -2150,10 +2146,6 @@
     doPrint('handleScript(' '$token)');
   }
 
-  void discardTypeReplacedWithCommentTypeAssign() {
-    doPrint('discardTypeReplacedWithCommentTypeAssign()');
-  }
-
   void handleCommentReferenceText(String referenceSource, int referenceOffset) {
     doPrint(
         'handleCommentReferenceText(' '$referenceSource, ' '$referenceOffset)');
diff --git a/pkg/native_stack_traces/bin/decode.dart b/pkg/native_stack_traces/bin/decode.dart
index 22a5e7e..2458e16 100644
--- a/pkg/native_stack_traces/bin/decode.dart
+++ b/pkg/native_stack_traces/bin/decode.dart
@@ -57,7 +57,7 @@
       help: 'Print usage information for this or a particular subcommand');
 
 final String _mainUsage = '''
-Usage: convert_stack_traces <command> [options] ...
+Usage: decode <command> [options] ...
 
 Commands:
 ${_argParser.commands.keys.join("\n")}
@@ -66,15 +66,15 @@
 ${_argParser.usage}''';
 
 final String _helpUsage = '''
-Usage: convert_stack_traces help [<command>]
+Usage: decode help [<command>]
 
-Returns usage for the convert_stack_traces utility or a particular command.
+Returns usage for the decode utility or a particular command.
 
 Commands:
 ${_argParser.commands.keys.join("\n")}''';
 
 final String _translateUsage = '''
-Usage: convert_stack_traces translate [options]
+Usage: decode translate [options]
 
 The translate command takes text that includes non-symbolic stack traces
 generated by the VM when executing a snapshot compiled with the
@@ -89,7 +89,7 @@
 ${_translateParser.usage}''';
 
 final String _findUsage = '''
-Usage: convert_stack_traces find [options] <PC> ...
+Usage: decode find [options] <PC> ...
 
 The find command looks up program counter (PC) addresses, either given as
 arguments on the command line or via the -l/--location option. For each
diff --git a/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart b/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
index bf1f858..2c69ae0 100644
--- a/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
+++ b/pkg/vm/lib/transformations/type_flow/table_selector_assigner.dart
@@ -146,4 +146,7 @@
       methodSelector.tornOff = true;
     }
   }
+
+  /// A (conservative) number which is bigger than all selector IDs.
+  int get selectorIdRange => metadata.selectors.length;
 }
diff --git a/pkg/vm/lib/transformations/type_flow/transformer.dart b/pkg/vm/lib/transformations/type_flow/transformer.dart
index 798233b..71e556b 100644
--- a/pkg/vm/lib/transformations/type_flow/transformer.dart
+++ b/pkg/vm/lib/transformations/type_flow/transformer.dart
@@ -96,9 +96,8 @@
 
   final tableSelectorAssigner = new TableSelectorAssigner(component);
 
-  final unboxingInfo = new UnboxingInfoManager(typeFlowAnalysis);
-
-  _makePartition(component, typeFlowAnalysis, unboxingInfo);
+  final unboxingInfo = new UnboxingInfoManager(typeFlowAnalysis)
+    ..analyzeComponent(component, typeFlowAnalysis, tableSelectorAssigner);
 
   new AnnotateKernel(component, typeFlowAnalysis, treeShaker.fieldMorpher,
           tableSelectorAssigner, unboxingInfo)
@@ -499,86 +498,6 @@
   }
 }
 
-// Partition the methods in order to idenfity parameters and return values
-// that are unboxing candidates
-void _makePartition(Component component, TypeFlowAnalysis typeFlowAnalysis,
-    UnboxingInfoManager unboxingInfo) {
-  // Traverses all the members and creates the partition graph.
-  // Currently unboxed parameters and return value are not supported for
-  // closures, therefore they do not exist in this graph
-  for (bool registering in const [true, false]) {
-    for (Library library in component.libraries) {
-      for (Class cls in library.classes) {
-        for (Member member in cls.members) {
-          if (registering) {
-            unboxingInfo.registerMember(member);
-          } else {
-            unboxingInfo.linkWithSuperClasses(member);
-          }
-        }
-      }
-      if (registering) {
-        for (Member member in library.members) {
-          unboxingInfo.registerMember(member);
-        }
-      }
-    }
-  }
-  unboxingInfo.finishGraph();
-
-  for (Library library in component.libraries) {
-    for (Class cls in library.classes) {
-      for (Member member in cls.members) {
-        _updateUnboxingInfoOfMember(member, typeFlowAnalysis, unboxingInfo);
-      }
-    }
-    for (Member member in library.members) {
-      _updateUnboxingInfoOfMember(member, typeFlowAnalysis, unboxingInfo);
-    }
-  }
-}
-
-void _updateUnboxingInfoOfMember(Member member,
-    TypeFlowAnalysis typeFlowAnalysis, UnboxingInfoManager unboxingInfo) {
-  if (typeFlowAnalysis.isMemberUsed(member)) {
-    if (member is Procedure || member is Constructor) {
-      final Args<Type> argTypes = typeFlowAnalysis.argumentTypes(member);
-      assertx(argTypes != null);
-
-      final int firstParamIndex =
-          numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
-
-      final positionalParams = member.function.positionalParameters;
-      assertx(argTypes.positionalCount ==
-          firstParamIndex + positionalParams.length);
-
-      for (int i = 0; i < positionalParams.length; i++) {
-        final inferredType = argTypes.values[firstParamIndex + i];
-        unboxingInfo.applyToArg(member, i, inferredType);
-      }
-
-      final names = argTypes.names;
-      for (int i = 0; i < names.length; i++) {
-        final inferredType =
-            argTypes.values[firstParamIndex + positionalParams.length + i];
-        unboxingInfo.applyToArg(
-            member, positionalParams.length + i, inferredType);
-      }
-
-      final Type resultType = typeFlowAnalysis.getSummary(member).resultType;
-      unboxingInfo.applyToReturn(member, resultType);
-    } else if (member is Field) {
-      final fieldValue = typeFlowAnalysis.getFieldValue(member).value;
-      if (member.hasSetter) {
-        unboxingInfo.applyToArg(member, 0, fieldValue);
-      }
-      unboxingInfo.applyToReturn(member, fieldValue);
-    } else {
-      assertx(false);
-    }
-  }
-}
-
 /// Tree shaking based on results of type flow analysis (TFA).
 ///
 /// TFA provides information about allocated classes and reachable member
diff --git a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
index 33e1899..0e9dad1 100644
--- a/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
+++ b/pkg/vm/lib/transformations/type_flow/unboxing_info.dart
@@ -5,96 +5,167 @@
 import 'package:kernel/ast.dart';
 import 'package:kernel/core_types.dart';
 import 'package:kernel/external_name.dart' show getExternalName;
+import 'package:vm/metadata/procedure_attributes.dart';
 import 'package:vm/transformations/type_flow/analysis.dart';
+import 'package:vm/transformations/type_flow/calls.dart';
 import 'package:vm/transformations/type_flow/native_code.dart';
+import 'package:vm/transformations/type_flow/table_selector_assigner.dart';
 import 'package:vm/transformations/type_flow/types.dart';
 
 import '../../metadata/unboxing_info.dart';
 import 'utils.dart';
 
 class UnboxingInfoManager {
-  final List<UnboxingInfoMetadata> _allUnboxingInfo = [];
-  final Map<Member, int> _memberIds = {};
-  final List<int> _partitionIds = [];
-  final List<int> _partitionRank = [];
-  final Set<Member> _mustBox = {};
+  final Map<Member, UnboxingInfoMetadata> _memberInfo = {};
 
   final TypeHierarchy _typeHierarchy;
   final CoreTypes _coreTypes;
   final NativeCodeOracle _nativeCodeOracle;
-  bool _finishedGraph;
 
   UnboxingInfoManager(TypeFlowAnalysis typeFlowAnalysis)
       : _typeHierarchy = typeFlowAnalysis.hierarchyCache,
         _coreTypes = typeFlowAnalysis.environment.coreTypes,
-        _nativeCodeOracle = typeFlowAnalysis.nativeCodeOracle,
-        _finishedGraph = false;
-
-  void registerMember(Member member) {
-    member = _validMemberOrNull(member);
-    if (member == null) return;
-    _addMember(member);
-  }
+        _nativeCodeOracle = typeFlowAnalysis.nativeCodeOracle;
 
   UnboxingInfoMetadata getUnboxingInfoOfMember(Member member) {
-    assertx(_finishedGraph);
-    member = _validMemberOrNull(member);
-    if ((member == null || (!_memberIds.containsKey(member)))) {
-      return null;
+    final UnboxingInfoMetadata info = _memberInfo[member];
+    if (member is Procedure && member.isGetter) {
+      // Remove placeholder parameter info slot for setters that the getter is
+      // grouped with.
+      return UnboxingInfoMetadata(0)..returnInfo = info.returnInfo;
     }
-    final partitionId = _memberIds[member];
-    return _allUnboxingInfo[partitionId];
+    return info;
   }
 
-  void linkWithSuperClasses(Member member) {
-    member = _validMemberOrNull(member);
-    if (member == null) return;
-    _linkRecursive(member, member.enclosingClass);
-  }
+  void analyzeComponent(Component component, TypeFlowAnalysis typeFlowAnalysis,
+      TableSelectorAssigner tableSelectorAssigner) {
+    const kInvalidSelectorId = ProcedureAttributesMetadata.kInvalidSelectorId;
 
-  void finishGraph() {
-    assertx(!_finishedGraph);
-    final oldToNewId = {};
-    final newUnboxingInfo = <UnboxingInfoMetadata>[];
-    for (int i = 0; i < _allUnboxingInfo.length; i++) {
-      if (_find(i) == i) {
-        final newId = oldToNewId.length;
-        oldToNewId[i] = newId;
-        newUnboxingInfo.add(_allUnboxingInfo[i]);
+    // Unboxing info for instance members is grouped by selector ID, such that
+    // the unboxing decisions match up for all members that can be called from
+    // the same call site.
+
+    // Unify the selector IDs for the getter and setter of every (writable)
+    // field, such that it can be grouped with both getters and setters.
+    // In the unified unboxing info, the return info represents the getters, and
+    // the parameter info represents the setters.
+    final selectorUnionFind = UnionFind(tableSelectorAssigner.selectorIdRange);
+    for (Library library in component.libraries) {
+      for (Class cls in library.classes) {
+        for (Field field in cls.fields) {
+          if (field.isInstanceMember && field.hasSetter) {
+            final getterId = tableSelectorAssigner.getterSelectorId(field);
+            final setterId =
+                tableSelectorAssigner.methodOrSetterSelectorId(field);
+            assertx(getterId != kInvalidSelectorId);
+            assertx(setterId != kInvalidSelectorId);
+            selectorUnionFind.union(getterId, setterId);
+          }
+        }
       }
     }
-    for (final key in _memberIds.keys) {
-      final newId = oldToNewId[_partitionIds[_memberIds[key]]];
-      assertx(newId != null);
-      _memberIds[key] = newId;
-    }
-    _allUnboxingInfo.clear();
-    _allUnboxingInfo.insertAll(0, newUnboxingInfo);
-    _memberIds.forEach((member, id) {
-      if (_mustBox.contains(member)) {
-        _allUnboxingInfo[id].returnInfo = UnboxingInfoMetadata.kBoxed;
-        _allUnboxingInfo[id].unboxedArgsInfo.clear();
+
+    // Map members to unboxing info.
+    final Map<int, UnboxingInfoMetadata> selectorIdToInfo = {};
+
+    void addMember(Member member) {
+      if (!(member is Procedure || member is Constructor || member is Field)) {
+        return;
       }
-    });
-    _partitionIds.clear();
-    _partitionRank.clear();
-    _finishedGraph = true;
+      // Give getters one parameter info slot to hold the unboxing info for the
+      // setters that the getter is grouped with.
+      final int paramCount = member is Field
+          ? (member.hasSetter ? 1 : 0)
+          : member is Procedure && member.isGetter
+              ? 1
+              : member.function.requiredParameterCount;
+      UnboxingInfoMetadata info;
+      if (member.isInstanceMember) {
+        int selectorId =
+            member is Field || member is Procedure && member.isGetter
+                ? tableSelectorAssigner.getterSelectorId(member)
+                : tableSelectorAssigner.methodOrSetterSelectorId(member);
+        assertx(selectorId != kInvalidSelectorId);
+        selectorId = selectorUnionFind.find(selectorId);
+        info = selectorIdToInfo[selectorId];
+        if (info == null) {
+          info = UnboxingInfoMetadata(paramCount);
+          selectorIdToInfo[selectorId] = info;
+        } else {
+          if (paramCount < info.unboxedArgsInfo.length) {
+            info.unboxedArgsInfo.length = paramCount;
+          }
+        }
+      } else {
+        info = UnboxingInfoMetadata(paramCount);
+      }
+      _memberInfo[member] = info;
+      _updateUnboxingInfoOfMember(member, typeFlowAnalysis);
+    }
+
+    for (Library library in component.libraries) {
+      for (Class cls in library.classes) {
+        for (Member member in cls.members) {
+          addMember(member);
+        }
+      }
+      for (Member member in library.members) {
+        addMember(member);
+      }
+    }
   }
 
-  void applyToArg(Member member, int argPos, Type type) {
-    assertx(_finishedGraph);
-    member = _validMemberOrNull(member);
-    if (member == null) return;
-    assertx(_memberIds.containsKey(member));
-    final partitionId = _memberIds[member];
+  void _updateUnboxingInfoOfMember(
+      Member member, TypeFlowAnalysis typeFlowAnalysis) {
+    if (typeFlowAnalysis.isMemberUsed(member)) {
+      final UnboxingInfoMetadata unboxingInfo = _memberInfo[member];
+      if (_cannotUnbox(member)) {
+        unboxingInfo.unboxedArgsInfo.length = 0;
+        unboxingInfo.returnInfo = UnboxingInfoMetadata.kBoxed;
+        return;
+      }
+      if (member is Procedure || member is Constructor) {
+        final Args<Type> argTypes = typeFlowAnalysis.argumentTypes(member);
+        assertx(argTypes != null);
 
-    if (argPos < 0 ||
-        _allUnboxingInfo[partitionId].unboxedArgsInfo.length <= argPos) {
+        final int firstParamIndex =
+            numTypeParams(member) + (hasReceiverArg(member) ? 1 : 0);
+
+        final positionalParams = member.function.positionalParameters;
+        assertx(argTypes.positionalCount ==
+            firstParamIndex + positionalParams.length);
+
+        for (int i = 0; i < positionalParams.length; i++) {
+          final inferredType = argTypes.values[firstParamIndex + i];
+          _applyToArg(unboxingInfo, i, inferredType);
+        }
+
+        final names = argTypes.names;
+        for (int i = 0; i < names.length; i++) {
+          final inferredType =
+              argTypes.values[firstParamIndex + positionalParams.length + i];
+          _applyToArg(unboxingInfo, positionalParams.length + i, inferredType);
+        }
+
+        final Type resultType = typeFlowAnalysis.getSummary(member).resultType;
+        _applyToReturn(unboxingInfo, resultType);
+      } else if (member is Field) {
+        final fieldValue = typeFlowAnalysis.getFieldValue(member).value;
+        if (member.hasSetter) {
+          _applyToArg(unboxingInfo, 0, fieldValue);
+        }
+        _applyToReturn(unboxingInfo, fieldValue);
+      } else {
+        assertx(false);
+      }
+    }
+  }
+
+  void _applyToArg(UnboxingInfoMetadata unboxingInfo, int argPos, Type type) {
+    if (argPos < 0 || unboxingInfo.unboxedArgsInfo.length <= argPos) {
       return;
     }
 
-    final unboxingInfo = _allUnboxingInfo[partitionId];
-
     if (type is NullableType ||
         (!type.isSubtypeOf(_typeHierarchy, _coreTypes.intClass) &&
             !type.isSubtypeOf(_typeHierarchy, _coreTypes.doubleClass))) {
@@ -107,14 +178,7 @@
     }
   }
 
-  void applyToReturn(Member member, Type type) {
-    assertx(_finishedGraph);
-    member = _validMemberOrNull(member);
-    if (member == null) return;
-    assertx(_memberIds.containsKey(member));
-    final partitionId = _memberIds[member];
-    final unboxingInfo = _allUnboxingInfo[partitionId];
-
+  void _applyToReturn(UnboxingInfoMetadata unboxingInfo, Type type) {
     if (type is NullableType ||
         (!type.isSubtypeOf(_typeHierarchy, _coreTypes.intClass) &&
             !type.isSubtypeOf(_typeHierarchy, _coreTypes.doubleClass))) {
@@ -127,82 +191,18 @@
     }
   }
 
-  void _linkRecursive(Member member, Class cls) {
-    for (final superType in cls.supers) {
-      final superClass = superType.classNode;
-      bool linked = false;
-      superClass.members.forEach((Member superMember) {
-        if (member.isInstanceMember) {
-          if (member.name == superMember.name) {
-            _linkMembers(member, superMember);
-            linked = true;
-          }
-        }
-      });
-      if (!linked) {
-        _linkRecursive(member, superClass);
-      }
-    }
-  }
-
-  void _linkMembers(Member member1, Member member2) {
-    member1 = _validMemberOrNull(member1);
-    member2 = _validMemberOrNull(member2);
-    if (member1 == null ||
-        member2 == null ||
-        _isConstructorOrStatic(member1) ||
-        _isConstructorOrStatic(member2)) {
-      return;
-    }
-    _union(_getMemberId(member1), _getMemberId(member2));
-  }
-
-  Member _validMemberOrNull(Member member) {
-    if (member == null ||
-        (member is! Procedure && member is! Constructor && member is! Field)) {
-      return null;
-    }
-    return member;
-  }
-
-  bool _isConstructorOrStatic(Member member) {
-    return ((member is Constructor) ||
-        ((member is Procedure) && member.isStatic));
-  }
-
-  void _addMember(Member member) {
-    assertx(!_finishedGraph);
-
-    if (_cannotUnbox(member)) {
-      _mustBox.add(member);
-    }
-
-    final int memberId = _allUnboxingInfo.length;
-    assertx(memberId == _partitionIds.length);
-    assertx(_partitionIds.length == _partitionRank.length);
-    final int argsLen = member is Field
-        ? (member.hasSetter ? 1 : 0)
-        : member.function.requiredParameterCount;
-    _memberIds[member] = memberId;
-    _allUnboxingInfo.add(UnboxingInfoMetadata(argsLen));
-    _partitionIds.add(memberId);
-    _partitionRank.add(1);
-  }
-
   bool _cannotUnbox(Member member) {
     // Methods that do not need dynamic invocation forwarders can not have
     // unboxed parameters and return because dynamic calls always use boxed
     // values.
     // Similarly C->Dart calls (entrypoints) and Dart->C calls (natives) need to
     // have boxed parameters and return values.
-    return (_isNative(member) ||
+    return _isNative(member) ||
         _nativeCodeOracle.isMemberReferencedFromNativeCode(member) ||
-        _isEnclosingClassSubtypeOfNum(member));
+        _isEnclosingClassSubtypeOfNum(member);
   }
 
-  bool _isNative(Member member) {
-    return (getExternalName(member) != null);
-  }
+  bool _isNative(Member member) => getExternalName(member) != null;
 
   // TODO(dartbug.com/33549): Calls to these methods could be replaced by
   // CheckedSmiOpInstr, so in order to allow the parameters and return
@@ -213,48 +213,4 @@
         ConeType(_typeHierarchy.getTFClass(member.enclosingClass))
             .isSubtypeOf(_typeHierarchy, _coreTypes.numClass));
   }
-
-  int _getMemberId(Member member) {
-    return _memberIds[member];
-  }
-
-  int _find(int memberId) {
-    assertx(!_finishedGraph);
-    if (memberId == _partitionIds[memberId]) {
-      return memberId;
-    }
-    final partitionId = _find(_partitionIds[memberId]);
-    _allUnboxingInfo[memberId] = null;
-    _partitionIds[memberId] = partitionId;
-    return partitionId;
-  }
-
-  void _union(int memberId1, int memberId2) {
-    assertx(!_finishedGraph);
-    final partitionId1 = _find(memberId1);
-    final partitionId2 = _find(memberId2);
-
-    if (partitionId1 == partitionId2) {
-      return;
-    }
-
-    int from, to;
-    if (_partitionRank[partitionId1] < _partitionRank[partitionId2]) {
-      from = partitionId1;
-      to = partitionId2;
-    } else {
-      from = partitionId2;
-      to = partitionId1;
-    }
-    final fromArgsInfo = _allUnboxingInfo[from].unboxedArgsInfo;
-    final toArgsInfo = _allUnboxingInfo[to].unboxedArgsInfo;
-    if (fromArgsInfo.length < toArgsInfo.length) {
-      toArgsInfo.length = fromArgsInfo.length;
-    }
-    _allUnboxingInfo[from] = null;
-    _partitionIds[from] = to;
-    if (_partitionRank[from] == _partitionRank[to]) {
-      _partitionRank[to]++;
-    }
-  }
 }
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart
new file mode 100644
index 0000000..65d7485
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart
@@ -0,0 +1,34 @@
+// 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 'dart:math';
+
+import 'package:expect/expect.dart';
+
+final bool alwaysFalse = int.parse('1') == 2;
+
+class A {
+  @pragma("vm:never-inline")
+  void foo(/* boxed */ int x) => Expect.isTrue(x.isOdd);
+}
+
+class B {
+  @pragma("vm:never-inline")
+  void foo(/* unboxed */ int x) => Expect.isTrue(x.isOdd);
+}
+
+class C extends A implements B {}
+
+main() {
+  final Random r = Random();
+  if (alwaysFalse) {
+    A().foo(r.nextInt(10));
+    B().foo(r.nextInt(10));
+    A().foo(null);
+  }
+  final List<B> l = [B(), C()];
+  for (B b in l) {
+    b.foo(13);
+  }
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect
new file mode 100644
index 0000000..5df0c21
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_1_test.dart.expect
@@ -0,0 +1,49 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+import "dart:math" as math;
+
+import "dart:math";
+import "package:expect/expect.dart";
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  @#C3
+  method foo([@vm.inferred-type.metadata=int?] core::int* x) → void
+    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd??] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd});
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  @#C3
+  method foo([@vm.inferred-type.metadata=int] core::int* x) → void
+    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd});
+}
+class C extends self::A implements self::B {
+  synthetic constructor •() → self::C*
+    : super self::A::•()
+    ;
+}
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* alwaysFalse = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(2);
+static method main() → dynamic {
+  final math::Random* r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
+  if([@vm.inferred-type.metadata=dart.core::bool?] self::alwaysFalse) {
+    [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10));
+    [@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::foo}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10));
+    [@vm.direct-call.metadata=#lib::A.foo] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::foo}(null);
+  }
+  final core::List<self::B*>* l = <self::B*>[new self::B::•(), new self::C::•()];
+  {
+    core::Iterator<self::B*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B*>] l.{core::Iterable::iterator};
+    for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      self::B* b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current};
+      {
+        b.{self::B::foo}(13);
+      }
+    }
+  }
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart
new file mode 100644
index 0000000..824ac78
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart
@@ -0,0 +1,34 @@
+// 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 'dart:math';
+
+import 'package:expect/expect.dart';
+
+final bool alwaysFalse = int.parse('1') == 2;
+
+class A {
+  @pragma("vm:never-inline")
+  void bar(/* unboxed */ int x) => Expect.isTrue(x.isOdd);
+}
+
+class B {
+  @pragma("vm:never-inline")
+  void bar(/* boxed */ int x) => Expect.isTrue(x.isOdd);
+}
+
+class C extends A implements B {}
+
+main() {
+  final Random r = Random();
+  if (alwaysFalse) {
+    A().bar(r.nextInt(10));
+    B().bar(r.nextInt(10));
+    B().bar(null);
+  }
+  final List<B> l = [B(), C()];
+  for (B b in l) {
+    b.bar(13);
+  }
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect
new file mode 100644
index 0000000..11a9912
--- /dev/null
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/regress_42418_2_test.dart.expect
@@ -0,0 +1,49 @@
+library #lib;
+import self as self;
+import "dart:core" as core;
+import "package:expect/expect.dart" as exp;
+import "dart:math" as math;
+
+import "dart:math";
+import "package:expect/expect.dart";
+
+class A extends core::Object {
+  synthetic constructor •() → self::A*
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  @#C3
+  method bar([@vm.inferred-type.metadata=int] core::int* x) → void
+    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd});
+}
+class B extends core::Object {
+  synthetic constructor •() → self::B*
+    : super core::Object::•()
+    ;
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2]  @#C3
+  method bar([@vm.inferred-type.metadata=int?] core::int* x) → void
+    return [@vm.inferred-type.metadata=dart.core::Null? (value: null)] exp::Expect::isTrue([@vm.direct-call.metadata=dart.core::_IntegerImplementation.isOdd??] [@vm.inferred-type.metadata=dart.core::bool] x.{core::int::isOdd});
+}
+class C extends self::A implements self::B {
+  synthetic constructor •() → self::C*
+    : super self::A::•()
+    ;
+}
+[@vm.inferred-type.metadata=dart.core::bool?]static final field core::bool* alwaysFalse = [@vm.direct-call.metadata=dart.core::_IntegerImplementation.==] [@vm.inferred-type.metadata=dart.core::bool (skip check)] [@vm.inferred-type.metadata=int] core::int::parse("1").{core::num::==}(2);
+static method main() → dynamic {
+  final math::Random* r = [@vm.inferred-type.metadata=dart.math::_Random] math::Random::•();
+  if([@vm.inferred-type.metadata=dart.core::bool?] self::alwaysFalse) {
+    [@vm.direct-call.metadata=#lib::A.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::A::•().{self::A::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10));
+    [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}([@vm.direct-call.metadata=dart.math::_Random.nextInt] [@vm.inferred-type.metadata=int (skip check)] r.{math::Random::nextInt}(10));
+    [@vm.direct-call.metadata=#lib::B.bar] [@vm.inferred-type.metadata=!? (skip check)] new self::B::•().{self::B::bar}(null);
+  }
+  final core::List<self::B*>* l = <self::B*>[new self::B::•(), new self::C::•()];
+  {
+    core::Iterator<self::B*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B*>] l.{core::Iterable::iterator};
+    for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
+      self::B* b = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current};
+      {
+        b.{self::B::bar}(13);
+      }
+    }
+  }
+}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
index 408a9b7..be40648 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/unboxed_getters.dart.expect
@@ -56,7 +56,7 @@
 [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i]  abstract get value() → core::int*;
 }
 class UBIA extends core::Object implements self::UBI {
-[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:5] [@vm.unboxing-info.metadata=()->i]  field core::int* value;
+[@vm.inferred-type.metadata=int] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:5] [@vm.unboxing-info.metadata=(i)->i]  field core::int* value;
 [@vm.unboxing-info.metadata=(i)->b]  constructor •([@vm.inferred-type.metadata=int] core::int* value) → self::UBIA*
     : self::UBIA::value = value, super core::Object::•()
     ;
diff --git a/runtime/docs/dwarf_stack_traces.md b/runtime/docs/dwarf_stack_traces.md
index 0c80515..afddbc7 100644
--- a/runtime/docs/dwarf_stack_traces.md
+++ b/runtime/docs/dwarf_stack_traces.md
@@ -136,8 +136,8 @@
 
 ### Using the stack trace converter tool
 
-A simple way to translate DWARF stack traces is to use the tool
-`pkg/vm/bin/convert_stack_traces.dart`. The tool has one required
+A simple way to translate DWARF stack traces is to use the tool `decode`
+from the package [native_stack_traces](https://pub.dev/packages/native_stack_traces). The tool has one required
 argument `-e`, which takes the name of the file containing DWARF
 debugging information as an input. This can either be an
 unstripped ELF snapshot or a file generated by `--save-debugging-info=<...>`.
@@ -147,7 +147,7 @@
 
 ```bash
 # Using the unstripped ELF snapshot and piping all output to the tool's stdin.
-$ out/ReleaseX64/dart_precompiled_runtime dwarf_snapshot.so |& out/ReleaseX64/dart pkg/vm/bin/convert_stack_traces.dart -e dwarf_snapshot.so
+$ out/ReleaseX64/dart_precompiled_runtime dwarf_snapshot.so |& out/ReleaseX64/dart pkg/native_stack_traces/bin/decode.dart -e dwarf_snapshot.so
 Unhandled exception:
 Throw of null.
 Warning: This VM has been configured to produce stack traces that violate the Dart standard.
@@ -161,7 +161,7 @@
 #4	_RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174)
 
 # Using the separately saved debugging information and piping all output to the tool's stdin.
-$ out/ReleaseX64/dart_precompiled_runtime dwarf_snapshot.so |& out/ReleaseX64/dart pkg/vm/bin/convert_stack_traces.dart -e debug.data
+$ out/ReleaseX64/dart_precompiled_runtime dwarf_snapshot.so |& out/ReleaseX64/dart pkg/native_stack_traces/bin/decode.dart -e debug.data
 Unhandled exception:
 Throw of null.
 Warning: This VM has been configured to produce stack traces that violate the Dart standard.
@@ -178,7 +178,7 @@
 $ out/ReleaseX64/dart_precompiled_runtime dwarf_snapshot.so >output.txt 2>&1
 
 # Reading the input to convert from the file "output.txt" instead of stdin.
-$ out/ReleaseX64/dart pkg/vm/bin/convert_stack_traces.dart -e debug.data -i output.txt
+$ out/ReleaseX64/dart pkg/native_stack_traces/bin/decode.dart -e debug.data -i output.txt
 Unhandled exception:
 Throw of null.
 Warning: This VM has been configured to produce stack traces that violate the Dart standard.
@@ -192,7 +192,7 @@
 #4	_RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:174)
 
 # Output the converted input to the file "converted.txt" instead of stdout.
-$ out/ReleaseX64/dart pkg/vm/bin/convert_stack_traces.dart -e debug.data -i output.txt -o converted.txt
+$ out/ReleaseX64/dart pkg/native_stack_traces/bin/decode.dart -e debug.data -i output.txt -o converted.txt
 
 $ cat converted.txt
 Unhandled exception:
@@ -248,7 +248,7 @@
 
 To convert a stream of lines that may include DWARF stack traces, use
 the stack transformer `DwarfStackTraceDecoder`. Its constructor takes a `Dwarf`
-object, and the transformer, like `convert_stack_traces.dart`, only changes
+object, and the transformer, like `decode.dart` from the package [native_stack_traces](https://pub.dev/packages/native_stack_traces), only changes
 lines that correspond to stack trace frames.
 
 > **Note**: The stack transformer assumes that lines are not combined or broken
diff --git a/runtime/tests/vm/dart/regress_42418_1_test.dart b/runtime/tests/vm/dart/regress_42418_1_test.dart
new file mode 100644
index 0000000..add07b4
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_42418_1_test.dart
@@ -0,0 +1,34 @@
+// 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 'dart:math';
+
+import 'package:expect/expect.dart';
+
+final bool alwaysFalse = int.parse('1') == 2;
+
+class A {
+  @pragma("vm:never-inline")
+  void foo(/* boxed */ int? x) => Expect.isTrue(x!.isOdd);
+}
+
+class B {
+  @pragma("vm:never-inline")
+  void foo(/* unboxed */ int? x) => Expect.isTrue(x!.isOdd);
+}
+
+class C extends A implements B {}
+
+main() {
+  final Random r = Random();
+  if (alwaysFalse) {
+    A().foo(r.nextInt(10));
+    B().foo(r.nextInt(10));
+    A().foo(null);
+  }
+  final List<B> l = [B(), C()];
+  for (B b in l) {
+    b.foo(13);
+  }
+}
diff --git a/runtime/tests/vm/dart/regress_42418_2_test.dart b/runtime/tests/vm/dart/regress_42418_2_test.dart
new file mode 100644
index 0000000..01bede8
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_42418_2_test.dart
@@ -0,0 +1,34 @@
+// 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 'dart:math';
+
+import 'package:expect/expect.dart';
+
+final bool alwaysFalse = int.parse('1') == 2;
+
+class A {
+  @pragma("vm:never-inline")
+  void bar(/* unboxed */ int? x) => Expect.isTrue(x!.isOdd);
+}
+
+class B {
+  @pragma("vm:never-inline")
+  void bar(/* boxed */ int? x) => Expect.isTrue(x!.isOdd);
+}
+
+class C extends A implements B {}
+
+main() {
+  final Random r = Random();
+  if (alwaysFalse) {
+    A().bar(r.nextInt(10));
+    B().bar(r.nextInt(10));
+    B().bar(null);
+  }
+  final List<B> l = [B(), C()];
+  for (B b in l) {
+    b.bar(13);
+  }
+}
diff --git a/runtime/tests/vm/dart_2/regress_42418_1_test.dart b/runtime/tests/vm/dart_2/regress_42418_1_test.dart
new file mode 100644
index 0000000..65d7485
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_42418_1_test.dart
@@ -0,0 +1,34 @@
+// 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 'dart:math';
+
+import 'package:expect/expect.dart';
+
+final bool alwaysFalse = int.parse('1') == 2;
+
+class A {
+  @pragma("vm:never-inline")
+  void foo(/* boxed */ int x) => Expect.isTrue(x.isOdd);
+}
+
+class B {
+  @pragma("vm:never-inline")
+  void foo(/* unboxed */ int x) => Expect.isTrue(x.isOdd);
+}
+
+class C extends A implements B {}
+
+main() {
+  final Random r = Random();
+  if (alwaysFalse) {
+    A().foo(r.nextInt(10));
+    B().foo(r.nextInt(10));
+    A().foo(null);
+  }
+  final List<B> l = [B(), C()];
+  for (B b in l) {
+    b.foo(13);
+  }
+}
diff --git a/runtime/tests/vm/dart_2/regress_42418_2_test.dart b/runtime/tests/vm/dart_2/regress_42418_2_test.dart
new file mode 100644
index 0000000..824ac78
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_42418_2_test.dart
@@ -0,0 +1,34 @@
+// 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 'dart:math';
+
+import 'package:expect/expect.dart';
+
+final bool alwaysFalse = int.parse('1') == 2;
+
+class A {
+  @pragma("vm:never-inline")
+  void bar(/* unboxed */ int x) => Expect.isTrue(x.isOdd);
+}
+
+class B {
+  @pragma("vm:never-inline")
+  void bar(/* boxed */ int x) => Expect.isTrue(x.isOdd);
+}
+
+class C extends A implements B {}
+
+main() {
+  final Random r = Random();
+  if (alwaysFalse) {
+    A().bar(r.nextInt(10));
+    B().bar(r.nextInt(10));
+    B().bar(null);
+  }
+  final List<B> l = [B(), C()];
+  for (B b in l) {
+    b.bar(13);
+  }
+}
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index a992ff3..fd3f576 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -2277,7 +2277,7 @@
     setter.set_accessor_field(field);
     setter.set_is_extension_member(field.is_extension_member());
     H.SetupFieldAccessorFunction(klass, setter, field_type);
-    T.SetupUnboxingInfoMetadataForFieldAccessors(getter,
+    T.SetupUnboxingInfoMetadataForFieldAccessors(setter,
                                                  library_kernel_offset_);
   }
 }
diff --git a/tools/VERSION b/tools/VERSION
index da8eb4b..29d04b0 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 10
 PATCH 0
-PRERELEASE 67
+PRERELEASE 68
 PRERELEASE_PATCH 0
\ No newline at end of file