Version 2.13.0-147.0.dev

Merge commit '26f0eba03b72eae65460413f5556599aa6370549' into 'dev'
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 5e82e3b..17573ee 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -513,16 +513,25 @@
   }
 
   /// Computes the appropriate set of context messages to report along with an
-  /// error that may have occurred because [receiver] was not type promoted.
+  /// error that may have occurred because [expression] was not type promoted.
+  ///
+  /// If [expression] is `null`, it means the expression that was not type
+  /// promoted was an implicit `this`.
+  ///
+  /// [errorEntity] is the entity whose location will be associated with the
+  /// error.  This is needed for test instrumentation.
+  ///
+  /// [whyNotPromoted] should be the non-promotion details returned by the flow
+  /// analysis engine.
   List<DiagnosticMessage> computeWhyNotPromotedMessages(
-      Expression? receiver,
+      Expression? expression,
       SyntacticEntity errorEntity,
       Map<DartType, NonPromotionReason>? whyNotPromoted) {
     List<DiagnosticMessage> messages = [];
     if (whyNotPromoted != null) {
       for (var entry in whyNotPromoted.entries) {
         var whyNotPromotedVisitor = _WhyNotPromotedVisitor(
-            source, receiver, errorEntity, flowAnalysis!.dataForTesting);
+            source, expression, errorEntity, flowAnalysis!.dataForTesting);
         if (typeSystem.isPotentiallyNullable(entry.key)) continue;
         var message = entry.value.accept(whyNotPromotedVisitor);
         if (message != null) {
@@ -3353,7 +3362,9 @@
             PromotableElement, DartType> {
   final Source source;
 
-  final Expression? _receiver;
+  /// The expression that was not promoted, or `null` if the thing that was not
+  /// promoted was an implicit `this`.
+  final Expression? _expression;
 
   final SyntacticEntity _errorEntity;
 
@@ -3364,7 +3375,7 @@
   DartType? propertyType;
 
   _WhyNotPromotedVisitor(
-      this.source, this._receiver, this._errorEntity, this._dataForTesting);
+      this.source, this._expression, this._errorEntity, this._dataForTesting);
 
   @override
   DiagnosticMessage? visitDemoteViaExplicitWrite(
@@ -3410,16 +3421,17 @@
   @override
   DiagnosticMessage? visitPropertyNotPromoted(
       PropertyNotPromoted<DartType> reason) {
-    var receiver = _receiver;
+    var expression = _expression;
     Element? receiverElement;
-    if (receiver is SimpleIdentifier) {
-      receiverElement = receiver.staticElement;
-    } else if (receiver is PropertyAccess) {
-      receiverElement = receiver.propertyName.staticElement;
-    } else if (receiver is PrefixedIdentifier) {
-      receiverElement = receiver.identifier.staticElement;
+    if (expression is SimpleIdentifier) {
+      receiverElement = expression.staticElement;
+    } else if (expression is PropertyAccess) {
+      receiverElement = expression.propertyName.staticElement;
+    } else if (expression is PrefixedIdentifier) {
+      receiverElement = expression.identifier.staticElement;
     } else {
-      assert(false, 'Unrecognized receiver: ${receiver.runtimeType}');
+      assert(false,
+          'Unrecognized property access expression: ${expression.runtimeType}');
     }
     if (receiverElement is PropertyAccessorElement) {
       propertyReference = receiverElement;
@@ -3427,7 +3439,7 @@
       return _contextMessageForProperty(receiverElement, reason.propertyName);
     } else {
       assert(receiverElement == null,
-          'Unrecognized receiver element: ${receiverElement.runtimeType}');
+          'Unrecognized property element: ${receiverElement.runtimeType}');
       return null;
     }
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 93add07..21443af 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -5950,11 +5950,17 @@
     // Peek to leave type parameters on top of stack.
     List<TypeVariableBuilder> typeVariables = peek();
 
+    List<TypeBuilder> unboundTypes = [];
+    List<TypeVariableBuilder> unboundTypeVariables = [];
     List<TypeBuilder> calculatedBounds = calculateBounds(
         typeVariables,
         libraryBuilder.loader.target.dynamicType,
         libraryBuilder.loader.target.nullType,
-        libraryBuilder.loader.target.objectClassBuilder);
+        libraryBuilder.loader.target.objectClassBuilder,
+        unboundTypes: unboundTypes,
+        unboundTypeVariables: unboundTypeVariables);
+    assert(unboundTypes.isEmpty,
+        "Found a type not bound to a declaration in BodyBuilder.");
     for (int i = 0; i < typeVariables.length; ++i) {
       typeVariables[i].defaultType = calculatedBounds[i];
       typeVariables[i].defaultType.resolveIn(scope, typeVariables[i].charOffset,
@@ -5964,6 +5970,12 @@
           libraryBuilder.loader.target.objectClassBuilder,
           libraryBuilder.loader.target.dynamicType);
     }
+    for (int i = 0; i < unboundTypeVariables.length; ++i) {
+      unboundTypeVariables[i].finish(
+          libraryBuilder,
+          libraryBuilder.loader.target.objectClassBuilder,
+          libraryBuilder.loader.target.dynamicType);
+    }
     TypeVariableBuilder.finishNullabilities(
         libraryBuilder, libraryBuilder.pendingNullabilities);
     libraryBuilder.pendingNullabilities.clear();
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
index 80f2dcb..57f8b57 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -378,7 +378,12 @@
 /// (https://github.com/dart-lang/sdk/blob/master/docs/language/informal/instantiate-to-bound.md)
 /// of the algorithm for details.
 List<TypeBuilder> calculateBounds(List<TypeVariableBuilder> variables,
-    TypeBuilder dynamicType, TypeBuilder bottomType, ClassBuilder objectClass) {
+    TypeBuilder dynamicType, TypeBuilder bottomType, ClassBuilder objectClass,
+    {List<TypeBuilder> unboundTypes,
+    List<TypeVariableBuilder> unboundTypeVariables}) {
+  assert(unboundTypes != null);
+  assert(unboundTypeVariables != null);
+
   List<TypeBuilder> bounds =
       new List<TypeBuilder>.filled(variables.length, null);
 
@@ -399,8 +404,12 @@
     }
     for (int variableIndex in component) {
       TypeVariableBuilder variable = variables[variableIndex];
-      bounds[variableIndex] = substituteRange(bounds[variableIndex],
-          dynamicSubstitution, nullSubstitution, null, null,
+      bounds[variableIndex] = substituteRange(
+          bounds[variableIndex],
+          dynamicSubstitution,
+          nullSubstitution,
+          unboundTypes,
+          unboundTypeVariables,
           variance: variable.variance);
     }
   }
@@ -414,8 +423,8 @@
     nullSubstitution[variables[i]] = bottomType;
     for (int j = 0; j < variables.length; j++) {
       TypeVariableBuilder variable = variables[j];
-      bounds[j] = substituteRange(
-          bounds[j], substitution, nullSubstitution, null, null,
+      bounds[j] = substituteRange(bounds[j], substitution, nullSubstitution,
+          unboundTypes, unboundTypeVariables,
           variance: variable.variance);
     }
   }
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index e409ff0..bb2c869 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -2937,11 +2937,20 @@
         }
 
         if (!haveErroneousBounds) {
+          List<TypeBuilder> unboundTypes = [];
+          List<TypeVariableBuilder> unboundTypeVariables = [];
           List<TypeBuilder> calculatedBounds = calculateBounds(
               variables,
               dynamicType,
               isNonNullableByDefault ? bottomType : nullType,
-              objectClass);
+              objectClass,
+              unboundTypes: unboundTypes,
+              unboundTypeVariables: unboundTypeVariables);
+          for (TypeBuilder unboundType in unboundTypes) {
+            currentTypeParameterScopeBuilder
+                .addType(new UnresolvedType(unboundType, -1, null));
+          }
+          boundlessTypeVariables.addAll(unboundTypeVariables);
           for (int i = 0; i < variables.length; ++i) {
             variables[i].defaultType = calculatedBounds[i];
           }
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart
new file mode 100644
index 0000000..70b0804
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart
@@ -0,0 +1,7 @@
+// Copyright (c) 2021, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+foo<X extends Function<Y extends X>()>() {}
+
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.strong.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.strong.expect
new file mode 100644
index 0000000..52d8793
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.strong.expect
@@ -0,0 +1,5 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method foo<X extends <Y extends self::foo::X = dynamic>() → dynamic = <Y extends dynamic = dynamic>() → dynamic>() → dynamic {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.strong.transformed.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.strong.transformed.expect
new file mode 100644
index 0000000..52d8793
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.strong.transformed.expect
@@ -0,0 +1,5 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method foo<X extends <Y extends self::foo::X = dynamic>() → dynamic = <Y extends dynamic = dynamic>() → dynamic>() → dynamic {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.textual_outline.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.textual_outline.expect
new file mode 100644
index 0000000..e6c43cd
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.textual_outline.expect
@@ -0,0 +1,2 @@
+foo<X extends Function<Y extends X>()>() {}
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.textual_outline_modelled.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.textual_outline_modelled.expect
new file mode 100644
index 0000000..e6c43cd
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.textual_outline_modelled.expect
@@ -0,0 +1,2 @@
+foo<X extends Function<Y extends X>()>() {}
+main() {}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.expect
new file mode 100644
index 0000000..52d8793
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.expect
@@ -0,0 +1,5 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method foo<X extends <Y extends self::foo::X = dynamic>() → dynamic = <Y extends dynamic = dynamic>() → dynamic>() → dynamic {}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.outline.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.outline.expect
new file mode 100644
index 0000000..3b0732a
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.outline.expect
@@ -0,0 +1,7 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method foo<X extends <Y extends self::foo::X = dynamic>() → dynamic = <Y extends dynamic = dynamic>() → dynamic>() → dynamic
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.transformed.expect b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.transformed.expect
new file mode 100644
index 0000000..52d8793
--- /dev/null
+++ b/pkg/front_end/testcases/generic_metadata/type_parameters_in_default_types.dart.weak.transformed.expect
@@ -0,0 +1,5 @@
+library /*isNonNullableByDefault*/;
+import self as self;
+
+static method foo<X extends <Y extends self::foo::X = dynamic>() → dynamic = <Y extends dynamic = dynamic>() → dynamic>() → dynamic {}
+static method main() → dynamic {}
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.cc b/runtime/vm/compiler/assembler/assembler_ia32.cc
index c845d8a..b33e519 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2409,6 +2409,15 @@
   call(FieldAddress(CODE_REG, target::Code::entry_point_offset(entry_kind)));
 }
 
+void Assembler::CallVmStub(const Code& target) {
+  const Object& target_as_object = CastHandle<Object, Code>(target);
+  ASSERT(target::CanEmbedAsRawPointerInGeneratedCode(target_as_object));
+  call(Address::Absolute(
+      target::ToRawPointer(target_as_object) +
+      target::Code::entry_point_offset(CodeEntryKind::kNormal) -
+      kHeapObjectTag));
+}
+
 void Assembler::CallToRuntime() {
   call(Address(THR, target::Thread::call_to_runtime_entry_point_offset()));
 }
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index 82b9745..ed03442 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -770,6 +770,9 @@
             bool movable_target = false,
             CodeEntryKind entry_kind = CodeEntryKind::kNormal);
   void CallToRuntime();
+  // Will not clobber any registers and can therefore be called with 5 live
+  // registers.
+  void CallVmStub(const Code& code);
 
   void Call(Address target) { call(target); }
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index 09110ef..b5e050d 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -540,7 +540,11 @@
 }
 
 void FlowGraphCompiler::EmitCallToStub(const Code& stub) {
-  __ Call(stub);
+  if (stub.InVMIsolateHeap()) {
+    __ CallVmStub(stub);
+  } else {
+    __ Call(stub);
+  }
   AddStubCallTarget(stub);
 }
 
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 8aa57f7..af6199b 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -5406,20 +5406,30 @@
 }
 
 void AssertSubtypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-#if defined(TARGET_ARCH_IA32)
-  __ PushRegister(AssertSubtypeABI::kInstantiatorTypeArgumentsReg);
-  __ PushRegister(AssertSubtypeABI::kFunctionTypeArgumentsReg);
-  __ PushRegister(AssertSubtypeABI::kSubTypeReg);
-  __ PushRegister(AssertSubtypeABI::kSuperTypeReg);
-  __ PushRegister(AssertSubtypeABI::kDstNameReg);
-  compiler->GenerateRuntimeCall(source(), deopt_id(), kSubtypeCheckRuntimeEntry,
-                                5, locs());
-
-  __ Drop(5);
-#else
   compiler->GenerateStubCall(source(), StubCode::AssertSubtype(),
                              UntaggedPcDescriptors::kOther, locs());
-#endif
+}
+
+LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
+                                                           bool opt) const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* locs = new (zone)
+      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
+  locs->set_in(0, Location::RegisterLocation(
+                      InstantiateTypeABI::kInstantiatorTypeArgumentsReg));
+  locs->set_in(1, Location::RegisterLocation(
+                      InstantiateTypeABI::kFunctionTypeArgumentsReg));
+  locs->set_out(0,
+                Location::RegisterLocation(InstantiateTypeABI::kResultTypeReg));
+  return locs;
+}
+
+void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  __ LoadObject(InstantiateTypeABI::kTypeReg, type());
+  compiler->GenerateStubCall(source(), StubCode::InstantiateType(),
+                             UntaggedPcDescriptors::kOther, locs(), deopt_id(),
+                             env());
 }
 
 LocationSummary* DeoptimizeInstr::MakeLocationSummary(Zone* zone,
@@ -6515,6 +6525,8 @@
 }
 
 void EnterHandleScopeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(kEnterHandleScopeRuntimeEntry.is_leaf());
+
   if (kind_ == Kind::kGetTopHandleScope) {
     __ LoadMemoryValue(CallingConventions::kReturnReg, THR,
                        compiler::target::Thread::api_top_scope_offset());
@@ -6541,6 +6553,8 @@
 }
 
 void ExitHandleScopeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(kEnterHandleScopeRuntimeEntry.is_leaf());
+
   Location arg_loc = FirstArgumentLocation();
   __ EnterCFrame(arg_loc.IsRegister() ? 0 : compiler::target::kWordSize);
   NoTemporaryAllocator no_temp;
@@ -6578,6 +6592,8 @@
 }
 
 void AllocateHandleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(kEnterHandleScopeRuntimeEntry.is_leaf());
+
   Location arg_loc = FirstArgumentLocation();
   __ EnterCFrame(arg_loc.IsRegister() ? 0 : compiler::target::kWordSize);
   if (arg_loc.IsStackSlot()) {
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 3cf8ffc..5d39a46 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -364,7 +364,7 @@
     // The instruction is guaranteed to not trigger GC on a non-exceptional
     // path. If the conditions depend on parameters of the instruction, do not
     // use this attribute but overload CanTriggerGC() instead.
-    kNoGC = 1
+    kNoGC = 1,
   };
 };
 
@@ -392,7 +392,7 @@
   M(NativeReturn, kNoGC)                                                       \
   M(Throw, kNoGC)                                                              \
   M(ReThrow, kNoGC)                                                            \
-  M(Stop, _)                                                                   \
+  M(Stop, kNoGC)                                                               \
   M(Goto, kNoGC)                                                               \
   M(IndirectGoto, kNoGC)                                                       \
   M(Branch, kNoGC)                                                             \
@@ -402,10 +402,10 @@
   M(SpecialParameter, kNoGC)                                                   \
   M(ClosureCall, _)                                                            \
   M(FfiCall, _)                                                                \
-  M(EnterHandleScope, _)                                                       \
-  M(ExitHandleScope, _)                                                        \
-  M(AllocateHandle, _)                                                         \
-  M(RawStoreField, _)                                                          \
+  M(EnterHandleScope, kNoGC)                                                   \
+  M(ExitHandleScope, kNoGC)                                                    \
+  M(AllocateHandle, kNoGC)                                                     \
+  M(RawStoreField, kNoGC)                                                      \
   M(InstanceCall, _)                                                           \
   M(PolymorphicInstanceCall, _)                                                \
   M(DispatchTableCall, _)                                                      \
@@ -470,19 +470,19 @@
   M(Unbox, kNoGC)                                                              \
   M(BoxInt64, _)                                                               \
   M(UnboxInt64, kNoGC)                                                         \
-  M(CaseInsensitiveCompare, _)                                                 \
+  M(CaseInsensitiveCompare, kNoGC)                                             \
   M(BinaryInt64Op, kNoGC)                                                      \
   M(ShiftInt64Op, kNoGC)                                                       \
   M(SpeculativeShiftInt64Op, kNoGC)                                            \
   M(UnaryInt64Op, kNoGC)                                                       \
   M(CheckArrayBound, kNoGC)                                                    \
   M(GenericCheckBound, kNoGC)                                                  \
-  M(Constraint, _)                                                             \
+  M(Constraint, kNoGC)                                                         \
   M(StringToCharCode, kNoGC)                                                   \
   M(OneByteStringFromCharCode, kNoGC)                                          \
   M(StringInterpolate, _)                                                      \
   M(Utf8Scan, kNoGC)                                                           \
-  M(InvokeMathCFunction, _)                                                    \
+  M(InvokeMathCFunction, kNoGC)                                                \
   M(TruncDivMod, kNoGC)                                                        \
   /*We could be more precise about when these 2 instructions can trigger GC.*/ \
   M(GuardFieldClass, _)                                                        \
@@ -501,9 +501,9 @@
   M(UnboxUint32, kNoGC)                                                        \
   M(BoxInt32, _)                                                               \
   M(UnboxInt32, kNoGC)                                                         \
-  M(BoxUint8, _)                                                               \
+  M(BoxUint8, kNoGC)                                                           \
   M(IntConverter, _)                                                           \
-  M(BitCast, _)                                                                \
+  M(BitCast, kNoGC)                                                            \
   M(Deoptimize, kNoGC)                                                         \
   M(SimdOp, kNoGC)
 
@@ -5814,7 +5814,10 @@
 // }
 //
 // under these assumptions:
-// - The start and end inputs are within the bounds of bytes and in smi range.
+// - The difference between start and end must be less than 2^30, since the
+//   resulting length can be twice the input length (and the result has to be in
+//   Smi range). This is guaranteed by `_Utf8Decoder.chunkSize` which is set to
+//   `65536`.
 // - The decoder._scanFlags field is unboxed or contains a smi.
 // - The first 128 entries of the table have the value 1.
 class Utf8ScanInstr : public TemplateDefinition<5, NoThrow> {
@@ -5848,6 +5851,7 @@
   virtual bool HasUnknownSideEffects() const { return true; }
   virtual bool ComputeCanDeoptimize() const { return false; }
   virtual intptr_t DeoptimizationTarget() const { return DeoptId::kNone; }
+  virtual void InferRange(RangeAnalysis* analysis, Range* range);
 
   virtual SpeculativeMode SpeculativeModeOfInput(intptr_t index) const {
     return kNotSpeculative;
@@ -6893,6 +6897,8 @@
 
   virtual Definition* Canonicalize(FlowGraph* flow_graph);
 
+  virtual bool CanTriggerGC() const { return !ValueFitsSmi(); }
+
   DEFINE_INSTRUCTION_TYPE_CHECK(BoxInteger)
 
  private:
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index f14f74c..42c547a 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -3451,42 +3451,6 @@
   __ Bind(&done);
 }
 
-LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
-                                                           bool opt) const {
-  const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* locs = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(
-                      InstantiationABI::kInstantiatorTypeArgumentsReg));
-  locs->set_in(1, Location::RegisterLocation(
-                      InstantiationABI::kFunctionTypeArgumentsReg));
-  locs->set_out(0,
-                Location::RegisterLocation(InstantiationABI::kResultTypeReg));
-  return locs;
-}
-
-void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register instantiator_type_args_reg = locs()->in(0).reg();
-  const Register function_type_args_reg = locs()->in(1).reg();
-  const Register result_reg = locs()->out(0).reg();
-
-  // 'instantiator_type_args_reg' is a TypeArguments object (or null).
-  // 'function_type_args_reg' is a TypeArguments object (or null).
-  // A runtime call to instantiate the type is required.
-  __ PushObject(Object::null_object());  // Make room for the result.
-  __ PushObject(type());
-  static_assert(InstantiationABI::kFunctionTypeArgumentsReg <
-                    InstantiationABI::kInstantiatorTypeArgumentsReg,
-                "Should be ordered to push arguments with one instruction");
-  __ PushList((1 << instantiator_type_args_reg) |
-              (1 << function_type_args_reg));
-  compiler->GenerateRuntimeCall(source(), deopt_id(),
-                                kInstantiateTypeRuntimeEntry, 3, locs());
-  __ Drop(3);          // Drop 2 type vectors, and uninstantiated type.
-  __ Pop(result_reg);  // Pop instantiated type.
-}
-
 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -6094,6 +6058,8 @@
 }
 
 void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(TargetFunction().is_leaf());
+
   // Call the function.
   __ CallRuntime(TargetFunction(), TargetFunction().argument_count());
 }
@@ -6577,6 +6543,8 @@
 }
 
 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(TargetFunction().is_leaf());
+
   if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
     InvokeDoublePow(compiler, this);
     return;
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index ce2a0a9..48514db 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -3019,38 +3019,6 @@
   __ Bind(&done);
 }
 
-LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
-                                                           bool opt) const {
-  const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* locs = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(
-                      InstantiationABI::kInstantiatorTypeArgumentsReg));
-  locs->set_in(1, Location::RegisterLocation(
-                      InstantiationABI::kFunctionTypeArgumentsReg));
-  locs->set_out(0,
-                Location::RegisterLocation(InstantiationABI::kResultTypeReg));
-  return locs;
-}
-
-void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Register instantiator_type_args_reg = locs()->in(0).reg();
-  const Register function_type_args_reg = locs()->in(1).reg();
-  const Register result_reg = locs()->out(0).reg();
-
-  // 'instantiator_type_args_reg' is a TypeArguments object (or null).
-  // 'function_type_args_reg' is a TypeArguments object (or null).
-  // A runtime call to instantiate the type is required.
-  __ LoadObject(TMP, type());
-  __ PushPair(TMP, NULL_REG);
-  __ PushPair(function_type_args_reg, instantiator_type_args_reg);
-  compiler->GenerateRuntimeCall(source(), deopt_id(),
-                                kInstantiateTypeRuntimeEntry, 3, locs());
-  __ Drop(3);          // Drop 2 type vectors, and uninstantiated type.
-  __ Pop(result_reg);  // Pop instantiated type.
-}
-
 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -5139,6 +5107,8 @@
 }
 
 void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(TargetFunction().is_leaf());
+
   // Call the function.
   __ CallRuntime(TargetFunction(), TargetFunction().argument_count());
 }
@@ -5603,6 +5573,8 @@
 }
 
 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(TargetFunction().is_leaf());
+
   if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
     InvokeDoublePow(compiler, this);
     return;
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 900c929..c32a520 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -2772,39 +2772,6 @@
   __ Bind(&done);
 }
 
-LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
-                                                           bool opt) const {
-  const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* locs = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(
-                      InstantiationABI::kInstantiatorTypeArgumentsReg));
-  locs->set_in(1, Location::RegisterLocation(
-                      InstantiationABI::kFunctionTypeArgumentsReg));
-  locs->set_out(0,
-                Location::RegisterLocation(InstantiationABI::kResultTypeReg));
-  return locs;
-}
-
-void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register instantiator_type_args_reg = locs()->in(0).reg();
-  Register function_type_args_reg = locs()->in(1).reg();
-  Register result_reg = locs()->out(0).reg();
-
-  // 'instantiator_type_args_reg' is a TypeArguments object (or null).
-  // 'function_type_args_reg' is a TypeArguments object (or null).
-  // A runtime call to instantiate the type is required.
-  __ PushObject(Object::null_object());  // Make room for the result.
-  __ PushObject(type());
-  __ pushl(instantiator_type_args_reg);  // Push instantiator type arguments.
-  __ pushl(function_type_args_reg);      // Push function type arguments.
-  compiler->GenerateRuntimeCall(source(), deopt_id(),
-                                kInstantiateTypeRuntimeEntry, 3, locs());
-  __ Drop(3);           // Drop 2 type vectors, and uninstantiated type.
-  __ popl(result_reg);  // Pop instantiated type.
-}
-
 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -5034,6 +5001,8 @@
 }
 
 void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(TargetFunction().is_leaf());
+
   // Save ESP. EDI is chosen because it is callee saved so we do not need to
   // back it up before calling into the runtime.
   static const Register kSavedSPReg = EDI;
@@ -5541,6 +5510,8 @@
 }
 
 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(TargetFunction().is_leaf());
+
   if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
     InvokeDoublePow(compiler, this);
     return;
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index 379ba84..085daca 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -3108,39 +3108,6 @@
   __ Bind(&done);
 }
 
-LocationSummary* InstantiateTypeInstr::MakeLocationSummary(Zone* zone,
-                                                           bool opt) const {
-  const intptr_t kNumInputs = 2;
-  const intptr_t kNumTemps = 0;
-  LocationSummary* locs = new (zone)
-      LocationSummary(zone, kNumInputs, kNumTemps, LocationSummary::kCall);
-  locs->set_in(0, Location::RegisterLocation(
-                      InstantiationABI::kInstantiatorTypeArgumentsReg));
-  locs->set_in(1, Location::RegisterLocation(
-                      InstantiationABI::kFunctionTypeArgumentsReg));
-  locs->set_out(0,
-                Location::RegisterLocation(InstantiationABI::kResultTypeReg));
-  return locs;
-}
-
-void InstantiateTypeInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  Register instantiator_type_args_reg = locs()->in(0).reg();
-  Register function_type_args_reg = locs()->in(1).reg();
-  Register result_reg = locs()->out(0).reg();
-
-  // 'instantiator_type_args_reg' is a TypeArguments object (or null).
-  // 'function_type_args_reg' is a TypeArguments object (or null).
-  // A runtime call to instantiate the type is required.
-  __ PushObject(Object::null_object());  // Make room for the result.
-  __ PushObject(type());
-  __ pushq(instantiator_type_args_reg);  // Push instantiator type arguments.
-  __ pushq(function_type_args_reg);      // Push function type arguments.
-  compiler->GenerateRuntimeCall(source(), deopt_id(),
-                                kInstantiateTypeRuntimeEntry, 3, locs());
-  __ Drop(3);           // Drop 2 type vectors, and uninstantiated type.
-  __ popq(result_reg);  // Pop instantiated type.
-}
-
 LocationSummary* InstantiateTypeArgumentsInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
@@ -5479,6 +5446,8 @@
 }
 
 void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(TargetFunction().is_leaf());
+
   // Save RSP. R13 is chosen because it is callee saved so we do not need to
   // back it up before calling into the runtime.
   static const Register kSavedSPReg = R13;
@@ -5966,6 +5935,8 @@
 }
 
 void InvokeMathCFunctionInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  ASSERT(TargetFunction().is_leaf());
+
   if (recognized_kind() == MethodRecognizer::kMathDoublePow) {
     InvokeDoublePow(compiler, this);
     return;
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index e39dff8..51aa420 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2914,6 +2914,12 @@
   }
 }
 
+void Utf8ScanInstr::InferRange(RangeAnalysis* analysis, Range* range) {
+  // The input bytes given to the Utf8Scan instruction are in non-negative Smi
+  // range and so is the resulting computed length.
+  *range = Range(RangeBoundary::FromConstant(0), RangeBoundary::MaxSmi());
+}
+
 void IfThenElseInstr::InferRange(RangeAnalysis* analysis, Range* range) {
   const intptr_t min = Utils::Minimum(if_true_, if_false_);
   const intptr_t max = Utils::Maximum(if_true_, if_false_);
diff --git a/runtime/vm/compiler/stub_code_compiler.cc b/runtime/vm/compiler/stub_code_compiler.cc
index 3478028..76492e7 100644
--- a/runtime/vm/compiler/stub_code_compiler.cc
+++ b/runtime/vm/compiler/stub_code_compiler.cc
@@ -204,6 +204,19 @@
 #endif
 }
 
+void StubCodeCompiler::GenerateInstantiateTypeStub(Assembler* assembler) {
+  __ EnterStubFrame();
+  __ PushObject(Object::null_object());
+  __ PushRegister(InstantiateTypeABI::kTypeReg);
+  __ PushRegister(InstantiateTypeABI::kInstantiatorTypeArgumentsReg);
+  __ PushRegister(InstantiateTypeABI::kFunctionTypeArgumentsReg);
+  __ CallRuntime(kInstantiateTypeRuntimeEntry, /*argument_count=*/3);
+  __ Drop(3);
+  __ PopRegister(InstantiateTypeABI::kResultTypeReg);
+  __ LeaveStubFrame();
+  __ Ret();
+}
+
 void StubCodeCompiler::GenerateInstanceOfStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ PushObject(NullObject());  // Make room for the result.
diff --git a/runtime/vm/constants.h b/runtime/vm/constants.h
index 01d9d08..00e3f9b 100644
--- a/runtime/vm/constants.h
+++ b/runtime/vm/constants.h
@@ -19,6 +19,20 @@
 
 namespace dart {
 
+// An architecture independent ABI for the InstantiateType stub.
+//
+// We re-use registers from another ABI to avoid duplicating this ABI across 4
+// architectures.
+struct InstantiateTypeABI {
+  static const Register kTypeReg =
+      InstantiationABI::kUninstantiatedTypeArgumentsReg;
+  static const Register kInstantiatorTypeArgumentsReg =
+      InstantiationABI::kInstantiatorTypeArgumentsReg;
+  static const Register kFunctionTypeArgumentsReg =
+      InstantiationABI::kFunctionTypeArgumentsReg;
+  static const Register kResultTypeReg = InstantiationABI::kResultTypeReg;
+};
+
 class RegisterNames {
  public:
   static const char* RegisterName(Register reg) {
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
index ea8d907..d1a200f 100644
--- a/runtime/vm/stub_code_list.h
+++ b/runtime/vm/stub_code_list.h
@@ -126,6 +126,7 @@
   V(ReThrow)                                                                   \
   V(AssertBoolean)                                                             \
   V(InstanceOf)                                                                \
+  V(InstantiateType)                                                           \
   V(InstantiateTypeArguments)                                                  \
   V(InstantiateTypeArgumentsMayShareInstantiatorTA)                            \
   V(InstantiateTypeArgumentsMayShareFunctionTA)                                \
diff --git a/sdk/lib/_internal/vm/lib/convert_patch.dart b/sdk/lib/_internal/vm/lib/convert_patch.dart
index 851c554..22bf67c 100644
--- a/sdk/lib/_internal/vm/lib/convert_patch.dart
+++ b/sdk/lib/_internal/vm/lib/convert_patch.dart
@@ -1675,7 +1675,11 @@
       "QQQQQQQQQQQQQQQQRRRRRbbbbbbbbbbb" // E0-FF
       ;
 
-  /// Max chunk to scan at a time. Avoids staying away from safepoints too long.
+  /// Max chunk to scan at a time.
+  ///
+  /// Avoids staying away from safepoints too long.
+  /// The Utf8ScanInstr relies on this being small enough to ensure the
+  /// decoded length stays within Smi range.
   static const int scanChunkSize = 65536;
 
   /// Reset the decoder to a state where it is ready to decode a new string but
diff --git a/tools/VERSION b/tools/VERSION
index 41bc8a4..a5bbf8d 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 13
 PATCH 0
-PRERELEASE 146
+PRERELEASE 147
 PRERELEASE_PATCH 0
\ No newline at end of file