Version 2.16.0-65.0.dev

Merge commit 'db9d61f3af61310dde776ece95cf37108c64912d' into 'dev'
diff --git a/DEPS b/DEPS
index 580a590..135c437 100644
--- a/DEPS
+++ b/DEPS
@@ -140,7 +140,7 @@
   "pool_rev": "7abe634002a1ba8a0928eded086062f1307ccfae",
   "process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
   "protobuf_rev": "c1eb6cb51af39ccbaa1a8e19349546586a5c8e31",
-  "pub_rev": "96404e0749864c9fbf8b12e1d424e8078809e00a",
+  "pub_rev": "b9edfa5e288ea3d1a57d1db054ef844ae7b27d99",
   "pub_semver_rev": "a43ad72fb6b7869607581b5fedcb186d1e74276a",
   "root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
   "rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
diff --git a/runtime/vm/compiler/backend/flow_graph.cc b/runtime/vm/compiler/backend/flow_graph.cc
index 6decb04..1dbf213 100644
--- a/runtime/vm/compiler/backend/flow_graph.cc
+++ b/runtime/vm/compiler/backend/flow_graph.cc
@@ -132,20 +132,6 @@
   }
 }
 
-Representation FlowGraph::UnboxedFieldRepresentationOf(const Field& field) {
-  switch (field.UnboxedFieldCid()) {
-    case kDoubleCid:
-      return kUnboxedDouble;
-    case kFloat32x4Cid:
-      return kUnboxedFloat32x4;
-    case kFloat64x2Cid:
-      return kUnboxedFloat64x2;
-    default:
-      RELEASE_ASSERT(field.is_non_nullable_integer());
-      return kUnboxedInt64;
-  }
-}
-
 void FlowGraph::ReplaceCurrentInstruction(ForwardInstructionIterator* iterator,
                                           Instruction* current,
                                           Instruction* replacement) {
diff --git a/runtime/vm/compiler/backend/flow_graph.h b/runtime/vm/compiler/backend/flow_graph.h
index 815b361..2c82c13 100644
--- a/runtime/vm/compiler/backend/flow_graph.h
+++ b/runtime/vm/compiler/backend/flow_graph.h
@@ -157,8 +157,6 @@
 
   static Representation ReturnRepresentationOf(const Function& function);
 
-  static Representation UnboxedFieldRepresentationOf(const Field& field);
-
   // The number of variables (or boxes) inside the functions frame - meaning
   // below the frame pointer.  This does not include the expression stack.
   intptr_t num_stack_locals() const {
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 47bcbbbef..e31b958 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -203,30 +203,6 @@
   ArchSpecificInitialization();
 }
 
-bool FlowGraphCompiler::IsUnboxedField(const Field& field) {
-  // The `field.is_non_nullable_integer()` is set in the kernel loader and can
-  // only be set if we consume a AOT kernel (annotated with inferred types).
-  ASSERT(!field.is_non_nullable_integer() || FLAG_precompiled_mode);
-  const bool valid_class =
-      ((SupportsUnboxedDoubles() && (field.guarded_cid() == kDoubleCid)) ||
-       (SupportsUnboxedSimd128() && (field.guarded_cid() == kFloat32x4Cid)) ||
-       (SupportsUnboxedSimd128() && (field.guarded_cid() == kFloat64x2Cid)) ||
-       field.is_non_nullable_integer());
-  return field.is_unboxing_candidate() && !field.is_nullable() && valid_class;
-}
-
-bool FlowGraphCompiler::IsPotentialUnboxedField(const Field& field) {
-  if (FLAG_precompiled_mode) {
-    // kernel_loader.cc:ReadInferredType sets the guarded cid for fields based
-    // on inferred types from TFA (if available). The guarded cid is therefore
-    // proven to be correct.
-    return IsUnboxedField(field);
-  }
-  return field.is_unboxing_candidate() &&
-         (FlowGraphCompiler::IsUnboxedField(field) ||
-          (field.guarded_cid() == kIllegalCid));
-}
-
 void FlowGraphCompiler::InitCompiler() {
   compressed_stackmaps_builder_ =
       new (zone()) CompressedStackMapsBuilder(zone());
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 5d9b0ad..e195a18 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -465,9 +465,6 @@
   static bool SupportsHardwareDivision();
   static bool CanConvertInt64ToDouble();
 
-  static bool IsUnboxedField(const Field& field);
-  static bool IsPotentialUnboxedField(const Field& field);
-
   // Accessors.
   compiler::Assembler* assembler() const { return assembler_; }
   const ParsedFunction& parsed_function() const { return parsed_function_; }
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index e901f3b..4ca03ed 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -894,17 +894,17 @@
 
 bool LoadFieldInstr::IsUnboxedDartFieldLoad() const {
   return slot().representation() == kTagged && slot().IsDartField() &&
-         FlowGraphCompiler::IsUnboxedField(slot().field());
+         slot().IsUnboxed();
 }
 
 bool LoadFieldInstr::IsPotentialUnboxedDartFieldLoad() const {
   return slot().representation() == kTagged && slot().IsDartField() &&
-         FlowGraphCompiler::IsPotentialUnboxedField(slot().field());
+         slot().IsPotentialUnboxed();
 }
 
 Representation LoadFieldInstr::representation() const {
   if (IsUnboxedDartFieldLoad() && CompilerState::Current().is_optimizing()) {
-    return FlowGraph::UnboxedFieldRepresentationOf(slot().field());
+    return slot().UnboxedRepresentation();
   }
   return slot().representation();
 }
@@ -963,12 +963,12 @@
 
 bool StoreInstanceFieldInstr::IsUnboxedDartFieldStore() const {
   return slot().representation() == kTagged && slot().IsDartField() &&
-         FlowGraphCompiler::IsUnboxedField(slot().field());
+         slot().IsUnboxed();
 }
 
 bool StoreInstanceFieldInstr::IsPotentialUnboxedDartFieldStore() const {
   return slot().representation() == kTagged && slot().IsDartField() &&
-         FlowGraphCompiler::IsPotentialUnboxedField(slot().field());
+         slot().IsPotentialUnboxed();
 }
 
 Representation StoreInstanceFieldInstr::RequiredInputRepresentation(
@@ -979,7 +979,7 @@
     return kTagged;
   }
   if (IsUnboxedDartFieldStore() && CompilerState::Current().is_optimizing()) {
-    return FlowGraph::UnboxedFieldRepresentationOf(slot().field());
+    return slot().UnboxedRepresentation();
   }
   return slot().representation();
 }
@@ -6181,7 +6181,7 @@
 }
 
 bool Utf8ScanInstr::IsScanFlagsUnboxed() const {
-  return FlowGraphCompiler::IsUnboxedField(scan_flags_field_.field());
+  return scan_flags_field_.IsUnboxed();
 }
 
 InvokeMathCFunctionInstr::InvokeMathCFunctionInstr(
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index b4b9920..75afb9a 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -331,6 +331,58 @@
   return SlotCache::Instance(thread).Canonicalize(slot);
 }
 
+FieldGuardState::FieldGuardState(const Field& field)
+    : state_(GuardedCidBits::encode(field.guarded_cid()) |
+             IsNonNullableIntegerBit::encode(field.is_non_nullable_integer()) |
+             IsUnboxingCandidateBit::encode(field.is_unboxing_candidate()) |
+             IsNullableBit::encode(field.is_nullable())) {}
+
+bool FieldGuardState::IsUnboxed() const {
+  ASSERT(!is_non_nullable_integer() || FLAG_precompiled_mode);
+  const bool valid_class = ((FlowGraphCompiler::SupportsUnboxedDoubles() &&
+                             (guarded_cid() == kDoubleCid)) ||
+                            (FlowGraphCompiler::SupportsUnboxedSimd128() &&
+                             (guarded_cid() == kFloat32x4Cid)) ||
+                            (FlowGraphCompiler::SupportsUnboxedSimd128() &&
+                             (guarded_cid() == kFloat64x2Cid)) ||
+                            is_non_nullable_integer());
+  return is_unboxing_candidate() && !is_nullable() && valid_class;
+}
+
+bool FieldGuardState::IsPotentialUnboxed() const {
+  if (FLAG_precompiled_mode) {
+    // kernel_loader.cc:ReadInferredType sets the guarded cid for fields based
+    // on inferred types from TFA (if available). The guarded cid is therefore
+    // proven to be correct.
+    return IsUnboxed();
+  }
+
+  return is_unboxing_candidate() &&
+         (IsUnboxed() || (guarded_cid() == kIllegalCid));
+}
+
+bool Slot::IsUnboxed() const {
+  return field_guard_state().IsUnboxed();
+}
+
+bool Slot::IsPotentialUnboxed() const {
+  return field_guard_state().IsPotentialUnboxed();
+}
+
+Representation Slot::UnboxedRepresentation() const {
+  switch (field_guard_state().guarded_cid()) {
+    case kDoubleCid:
+      return kUnboxedDouble;
+    case kFloat32x4Cid:
+      return kUnboxedFloat32x4;
+    case kFloat64x2Cid:
+      return kUnboxedFloat64x2;
+    default:
+      RELEASE_ASSERT(field_guard_state().is_non_nullable_integer());
+      return kUnboxedInt64;
+  }
+}
+
 const Slot& Slot::Get(const Field& field,
                       const ParsedFunction* parsed_function) {
   Thread* thread = Thread::Current();
@@ -354,16 +406,18 @@
     is_nullable = false;
   }
 
+  FieldGuardState field_guard_state(field);
+
   bool used_guarded_state = false;
-  if (field.guarded_cid() != kIllegalCid &&
-      field.guarded_cid() != kDynamicCid) {
+  if (field_guard_state.guarded_cid() != kIllegalCid &&
+      field_guard_state.guarded_cid() != kDynamicCid) {
     // Use guarded state if it is more precise then what we already have.
     if (nullable_cid == kDynamicCid) {
-      nullable_cid = field.guarded_cid();
+      nullable_cid = field_guard_state.guarded_cid();
       used_guarded_state = true;
     }
 
-    if (is_nullable && !field.is_nullable()) {
+    if (is_nullable && !field_guard_state.is_nullable()) {
       is_nullable = false;
       used_guarded_state = true;
     }
@@ -377,10 +431,10 @@
     used_guarded_state = false;
   }
 
-  if (field.is_non_nullable_integer()) {
+  if (field_guard_state.is_non_nullable_integer()) {
     ASSERT(FLAG_precompiled_mode);
     is_nullable = false;
-    if (FlowGraphCompiler::IsUnboxedField(field)) {
+    if (field_guard_state.IsUnboxed()) {
       rep = kUnboxedInt64;
     }
   }
@@ -397,7 +451,7 @@
           IsSentinelVisibleBit::encode(field.is_late() && field.is_final() &&
                                        !field.has_initializer()),
       nullable_cid, compiler::target::Field::OffsetOf(field), &field, &type,
-      rep));
+      rep, field_guard_state));
 
   // If properties of this slot were based on the guarded state make sure
   // to add the field to the list of guarded fields. Note that during background
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index a31e9a9..88c1dd8 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -166,6 +166,35 @@
   NONNULLABLE_BOXED_NATIVE_SLOTS_LIST(V)                                       \
   UNBOXED_NATIVE_SLOTS_LIST(V)
 
+class FieldGuardState {
+ public:
+  FieldGuardState() : state_(0) {}
+  explicit FieldGuardState(const Field& field);
+
+  intptr_t guarded_cid() const { return GuardedCidBits::decode(state_); }
+  bool is_non_nullable_integer() const {
+    return IsNonNullableIntegerBit::decode(state_);
+  }
+  bool is_unboxing_candidate() const {
+    return IsUnboxingCandidateBit::decode(state_);
+  }
+  bool is_nullable() const { return IsNullableBit::decode(state_); }
+
+  bool IsUnboxed() const;
+  bool IsPotentialUnboxed() const;
+
+ private:
+  using GuardedCidBits = BitField<int32_t, ClassIdTagType, 0, 16>;
+  using IsNonNullableIntegerBit =
+      BitField<int32_t, bool, GuardedCidBits::kNextBit, 1>;
+  using IsUnboxingCandidateBit =
+      BitField<int32_t, bool, IsNonNullableIntegerBit::kNextBit, 1>;
+  using IsNullableBit =
+      BitField<int32_t, bool, IsUnboxingCandidateBit::kNextBit, 1>;
+
+  const int32_t state_;
+};
+
 // Slot is an abstraction that describes an readable (and possibly writeable)
 // location within an object.
 //
@@ -298,6 +327,10 @@
     return kind() == Kind::kCapturedVariable || kind() == Kind::kContext_parent;
   }
 
+  bool IsUnboxed() const;
+  bool IsPotentialUnboxed() const;
+  Representation UnboxedRepresentation() const;
+
  private:
   friend class FlowGraphDeserializer;  // For GetNativeSlot.
 
@@ -307,12 +340,14 @@
        intptr_t offset_in_bytes,
        const void* data,
        const AbstractType* static_type,
-       Representation representation)
+       Representation representation,
+       const FieldGuardState& field_guard_state = FieldGuardState())
       : kind_(kind),
         flags_(bits),
         cid_(cid),
         offset_in_bytes_(offset_in_bytes),
         representation_(representation),
+        field_guard_state_(field_guard_state),
         data_(data),
         static_type_(static_type) {}
 
@@ -323,7 +358,8 @@
              other.offset_in_bytes_,
              other.data_,
              other.static_type_,
-             other.representation_) {}
+             other.representation_,
+             other.field_guard_state_) {}
 
   using IsImmutableBit = BitField<int8_t, bool, 0, 1>;
   using IsNullableBit = BitField<int8_t, bool, IsImmutableBit::kNextBit, 1>;
@@ -342,6 +378,10 @@
   static AcqRelAtomic<Slot*> native_fields_;
   static const Slot& GetNativeSlot(Kind kind);
 
+  const FieldGuardState& field_guard_state() const {
+    return field_guard_state_;
+  }
+
   const Kind kind_;
   const int8_t flags_;        // is_immutable, is_nullable
   const ClassIdTagType cid_;  // Concrete cid of a value or kDynamicCid.
@@ -349,6 +389,8 @@
   const intptr_t offset_in_bytes_;
   const Representation representation_;
 
+  const FieldGuardState field_guard_state_;
+
   // Kind dependent data:
   //   - name as a Dart String object for local variables;
   //   - name as a C string for native slots;
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index 85ed2b5..a0da87b 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -1050,7 +1050,8 @@
   // [Intrinsifier::CanIntrinsifyFieldAccessor])
   auto zone = flow_graph->zone();
   const auto& function = flow_graph->function();
-  ASSERT(Intrinsifier::CanIntrinsifyFieldAccessor(function));
+  ASSERT(
+      Intrinsifier::CanIntrinsifyFieldAccessor(flow_graph->parsed_function()));
 
   auto& field = Field::Handle(zone, function.accessor_field());
   if (CompilerState::Current().should_clone_fields()) {
@@ -1072,12 +1073,10 @@
 
   // We only support cases where we do not have to create a box (whose
   // allocation could fail).
-  ASSERT(function.HasUnboxedReturnValue() ||
-         !FlowGraphCompiler::IsUnboxedField(field));
+  ASSERT(function.HasUnboxedReturnValue() || !slot.IsUnboxed());
 
   // We might need to unbox the field value before returning.
-  if (function.HasUnboxedReturnValue() &&
-      !FlowGraphCompiler::IsUnboxedField(field)) {
+  if (function.HasUnboxedReturnValue() && !slot.IsUnboxed()) {
     ASSERT(FLAG_precompiled_mode);
     field_value = builder.AddUnboxInstr(
         FlowGraph::ReturnRepresentationOf(flow_graph->function()),
@@ -1093,21 +1092,19 @@
   // [Intrinsifier::CanIntrinsifyFieldAccessor])
   auto zone = flow_graph->zone();
   const auto& function = flow_graph->function();
-  ASSERT(Intrinsifier::CanIntrinsifyFieldAccessor(function));
+  ASSERT(
+      Intrinsifier::CanIntrinsifyFieldAccessor(flow_graph->parsed_function()));
 
   auto& field = Field::Handle(zone, function.accessor_field());
   if (CompilerState::Current().should_clone_fields()) {
     field = field.CloneFromOriginal();
   }
   ASSERT(field.is_instance() && !field.is_final());
-  ASSERT(!function.HasUnboxedParameters() ||
-         FlowGraphCompiler::IsUnboxedField(field));
-
   const auto& slot = Slot::Get(field, &flow_graph->parsed_function());
+  ASSERT(!function.HasUnboxedParameters() || slot.IsUnboxed());
 
-  const auto barrier_mode = FlowGraphCompiler::IsUnboxedField(field)
-                                ? kNoStoreBarrier
-                                : kEmitStoreBarrier;
+  const auto barrier_mode =
+      slot.IsUnboxed() ? kNoStoreBarrier : kEmitStoreBarrier;
 
   flow_graph->CreateCommonConstants();
   GraphEntryInstr* graph_entry = flow_graph->graph_entry();
@@ -1118,14 +1115,13 @@
   auto value = builder.AddParameter(1, /*with_frame=*/false);
   VerifyParameterIsBoxed(&builder, 0);
 
-  if (!function.HasUnboxedParameters() &&
-      FlowGraphCompiler::IsUnboxedField(field)) {
+  if (!function.HasUnboxedParameters() && slot.IsUnboxed()) {
     // We do not support storing to possibly guarded fields in JIT in graph
     // intrinsics.
     ASSERT(FLAG_precompiled_mode);
-    value = builder.AddUnboxInstr(
-        FlowGraph::UnboxedFieldRepresentationOf(field), new Value(value),
-        /*is_checked=*/true);
+    value =
+        builder.AddUnboxInstr(slot.UnboxedRepresentation(), new Value(value),
+                              /*is_checked=*/true);
   }
 
   builder.AddInstruction(new (zone) StoreInstanceFieldInstr(
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index f343f73..4ba80d9f 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -25,7 +25,9 @@
 
 namespace compiler {
 
-bool Intrinsifier::CanIntrinsify(const Function& function) {
+bool Intrinsifier::CanIntrinsify(const ParsedFunction& parsed_function) {
+  const Function& function = parsed_function.function();
+
   if (FLAG_trace_intrinsifier) {
     THR_Print("CanIntrinsify %s ->", function.ToQualifiedCString());
   }
@@ -45,7 +47,8 @@
     }
     return false;
   }
-  if (!function.is_intrinsic() && !CanIntrinsifyFieldAccessor(function)) {
+  if (!function.is_intrinsic() &&
+      !CanIntrinsifyFieldAccessor(parsed_function)) {
     if (FLAG_trace_intrinsifier) {
       THR_Print("No, not intrinsic function.\n");
     }
@@ -73,7 +76,10 @@
   return true;
 }
 
-bool Intrinsifier::CanIntrinsifyFieldAccessor(const Function& function) {
+bool Intrinsifier::CanIntrinsifyFieldAccessor(
+    const ParsedFunction& parsed_function) {
+  const Function& function = parsed_function.function();
+
   const bool is_getter = function.IsImplicitGetterFunction();
   const bool is_setter = function.IsImplicitSetterFunction();
   if (!is_getter && !is_setter) return false;
@@ -97,11 +103,13 @@
   // We only graph intrinsify implicit instance getters/setter for now.
   if (!field.is_instance()) return false;
 
+  const auto& slot = Slot::Get(field, &parsed_function);
+
   if (is_getter) {
     // We don't support complex getter cases.
     if (field.is_late() || field.needs_load_guard()) return false;
 
-    if (FlowGraphCompiler::IsPotentialUnboxedField(field)) {
+    if (slot.IsPotentialUnboxed()) {
       if (function.HasUnboxedReturnValue()) {
         // In AOT mode: Unboxed fields contain the unboxed value and can be
         // returned in unboxed form.
@@ -136,7 +144,7 @@
     // avoid the need for boxing (which we cannot do in the intrinsic).
     if (function.HasUnboxedParameters()) {
       ASSERT(FLAG_precompiled_mode);
-      if (!FlowGraphCompiler::IsUnboxedField(field)) {
+      if (!slot.IsUnboxed()) {
         return false;
       }
     }
@@ -253,8 +261,7 @@
 // Returns true if fall-through code can be omitted.
 bool Intrinsifier::Intrinsify(const ParsedFunction& parsed_function,
                               FlowGraphCompiler* compiler) {
-  const Function& function = parsed_function.function();
-  if (!CanIntrinsify(function)) {
+  if (!CanIntrinsify(parsed_function)) {
     return false;
   }
 
@@ -262,6 +269,7 @@
     return compiler->intrinsic_slow_path_label()->IsUnused();
   }
 
+  const Function& function = parsed_function.function();
 #if !defined(HASH_IN_OBJECT_HEADER)
   // These two are more complicated on 32 bit platforms, where the
   // identity hash is not stored in the header of the object.  We
diff --git a/runtime/vm/compiler/intrinsifier.h b/runtime/vm/compiler/intrinsifier.h
index 835f73f..681b606 100644
--- a/runtime/vm/compiler/intrinsifier.h
+++ b/runtime/vm/compiler/intrinsifier.h
@@ -35,8 +35,8 @@
 
  private:
   friend class GraphIntrinsifier;  // For CanIntrinsifyFieldAccessor.
-  static bool CanIntrinsify(const Function& function);
-  static bool CanIntrinsifyFieldAccessor(const Function& function);
+  static bool CanIntrinsify(const ParsedFunction& parsed_function);
+  static bool CanIntrinsifyFieldAccessor(const ParsedFunction& parsed_function);
 };
 
 }  // namespace compiler
diff --git a/sdk/lib/_internal/vm/bin/socket_patch.dart b/sdk/lib/_internal/vm/bin/socket_patch.dart
index 8ce0776..8812068 100644
--- a/sdk/lib/_internal/vm/bin/socket_patch.dart
+++ b/sdk/lib/_internal/vm/bin/socket_patch.dart
@@ -1396,7 +1396,8 @@
 
         if (i == errorEvent) {
           if (!isClosing) {
-            reportError(nativeGetError(), null, "");
+            final err = nativeGetError();
+            reportError(err, null, err.message);
           }
         } else if (!isClosed) {
           // If the connection is closed right after it's accepted, there's a
diff --git a/tools/VERSION b/tools/VERSION
index 536a2a3..d0ff84a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 16
 PATCH 0
-PRERELEASE 64
+PRERELEASE 65
 PRERELEASE_PATCH 0
\ No newline at end of file