Version 2.14.0-204.0.dev

Merge commit '00d6b8972a63f92ec590e4e0d1f4b045071f26e7' into 'dev'
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index bfa05f5..2fbc03f 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -42,6 +42,7 @@
   V(ExceptionHandlers)                                                         \
   V(Context)                                                                   \
   V(ContextScope)                                                              \
+  V(Sentinel)                                                                  \
   V(SingleTargetCache)                                                         \
   V(UnlinkedCall)                                                              \
   V(MonomorphicSmiableCall)                                                    \
@@ -217,8 +218,6 @@
   kNumPredefinedCids,
 };
 
-constexpr ClassId kSentinelCid = kNeverCid;
-
 // Keep these in sync with the cid numbering above.
 const int kTypedDataCidRemainderInternal = 0;
 const int kTypedDataCidRemainderView = 1;
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 243f69a..fd75159 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -570,11 +570,7 @@
   void WriteCanonicalSetLayout(Serializer* s) {
     if (represents_canonical_set_) {
       s->WriteUnsigned(table_length_);
-      if (kAllCanonicalObjectsAreIncludedIntoSet) {
-        ASSERT(objects_.length() == gaps_.length());
-      } else {
-        s->WriteUnsigned(objects_.length() - gaps_.length());
-      }
+      s->WriteUnsigned(objects_.length() - gaps_.length());
       for (auto gap : gaps_) {
         s->WriteUnsigned(gap);
       }
@@ -608,8 +604,7 @@
     }
 
     const auto table_length = d->ReadUnsigned();
-    first_element_ =
-        kAllCanonicalObjectsAreIncludedIntoSet ? 0 : d->ReadUnsigned();
+    first_element_ = d->ReadUnsigned();
     const intptr_t count = stop_index_ - (start_index_ + first_element_);
     auto table = StartDeserialization(d, table_length, count);
     for (intptr_t i = start_index_ + first_element_; i < stop_index_; i++) {
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 215bca5..8a0978b 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -757,7 +757,7 @@
   // No IC data checks. Try resolve target using the propagated cid.
   const intptr_t receiver_cid =
       instr->ArgumentValueAt(receiver_idx)->Type()->ToCid();
-  if (receiver_cid != kDynamicCid) {
+  if (receiver_cid != kDynamicCid && receiver_cid != kSentinelCid) {
     const Class& receiver_class =
         Class::Handle(Z, isolate_group()->class_table()->At(receiver_cid));
     const Function& function =
@@ -781,7 +781,7 @@
         const intptr_t cid = class_ids[i];
         // Skip sentinel cid. It may appear in the unreachable code after
         // inlining a method which doesn't return.
-        if (cid == kNeverCid) continue;
+        if (cid == kSentinelCid) continue;
         const Class& cls =
             Class::Handle(Z, isolate_group()->class_table()->At(cid));
         const Function& target =
@@ -1051,7 +1051,7 @@
   const intptr_t receiver_idx = call->type_args_len() > 0 ? 1 : 0;
   const intptr_t receiver_cid =
       call->ArgumentValueAt(receiver_idx)->Type()->ToCid();
-  if (receiver_cid != kDynamicCid) {
+  if (receiver_cid != kDynamicCid && receiver_cid != kSentinelCid) {
     const Class& receiver_class =
         Class::Handle(Z, isolate_group()->class_table()->At(receiver_cid));
     const Function& function =
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 62d0044..5e299f0 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -2277,6 +2277,7 @@
   auto& members = Array::Handle(Z);
   auto& constants = Array::Handle(Z);
   auto& retained_constants = GrowableObjectArray::Handle(Z);
+  auto& obj = Object::Handle(Z);
   auto& constant = Instance::Handle(Z);
 
   SafepointWriteRwLocker ml(T, T->isolate_group()->program_lock());
@@ -2308,7 +2309,12 @@
       retained_constants = GrowableObjectArray::New();
       if (!constants.IsNull()) {
         for (intptr_t j = 0; j < constants.Length(); j++) {
-          constant ^= constants.At(j);
+          obj = constants.At(j);
+          if ((obj.ptr() == HashTableBase::UnusedMarker().ptr()) ||
+              (obj.ptr() == HashTableBase::DeletedMarker().ptr())) {
+            continue;
+          }
+          constant ^= obj.ptr();
           bool retain = consts_to_retain_.HasKey(&constant);
           if (retain) {
             retained_constants.Add(constant);
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 529eda6..88d1f2f 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -602,11 +602,7 @@
       const intptr_t right_cid = instr->right()->Type()->ToCid();
       // If exact classes (cids) are known and they differ, the result
       // of strict compare can be computed.
-      // The only exception is comparison with special sentinel value
-      // (used for lazy initialization) which can be compared to a
-      // value of any type. Sentinel value has kNeverCid.
       if ((left_cid != kDynamicCid) && (right_cid != kDynamicCid) &&
-          (left_cid != kNeverCid) && (right_cid != kNeverCid) &&
           (left_cid != right_cid)) {
         const bool result = (instr->kind() != Token::kEQ_STRICT);
         SetValue(instr, Bool::Get(result));
@@ -852,7 +848,7 @@
   if (!FLAG_fields_may_be_reset) {
     const Field& field = instr->field();
     ASSERT(field.is_static());
-    auto& obj = Instance::Handle(Z);
+    auto& obj = Object::Handle(Z);
     if (field.is_final() && instr->IsFieldInitialized(&obj)) {
       if (obj.IsSmi() || (obj.IsOld() && obj.IsCanonical())) {
         SetValue(instr, obj);
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index aad4fe7..b65dc1a 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1149,7 +1149,7 @@
   return field().ptr() == other.AsLoadStaticField()->field().ptr();
 }
 
-bool LoadStaticFieldInstr::IsFieldInitialized(Instance* field_value) const {
+bool LoadStaticFieldInstr::IsFieldInitialized(Object* field_value) const {
   if (FLAG_fields_may_be_reset) {
     return false;
   }
@@ -1170,7 +1170,7 @@
     return false;
   }
   if (field_value == nullptr) {
-    field_value = &Instance::Handle();
+    field_value = &Object::Handle();
   }
   *field_value = only_isolate->field_table()->At(field.field_id());
   return (field_value->ptr() != Object::sentinel().ptr()) &&
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index e14e142..91fe069 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -5561,7 +5561,7 @@
   virtual CompileType ComputeType() const;
 
   const Field& field() const { return field_; }
-  bool IsFieldInitialized(Instance* field_value = nullptr) const;
+  bool IsFieldInitialized(Object* field_value = nullptr) const;
 
   bool calls_initializer() const { return calls_initializer_; }
   void set_calls_initializer(bool value) { calls_initializer_ = value; }
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index d576993..3163f63 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -3669,7 +3669,7 @@
     FlowGraphInliner::ExactnessInfo* exactness) {
   COMPILER_TIMINGS_TIMER_SCOPE(flow_graph->thread(), InlineRecognizedMethod);
 
-  if (receiver_cid == kNeverCid) {
+  if (receiver_cid == kSentinelCid) {
     // Receiver was defined in dead code and was replaced by the sentinel.
     // Original receiver cid is lost, so don't try to inline recognized
     // methods.
diff --git a/runtime/vm/compiler/backend/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 8ff2339..c396f37 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -739,8 +739,8 @@
       cid_ = kNullCid;
     }
     // Same for sentinel.
-    if ((type_ != NULL) && type_->IsNeverType()) {
-      cid_ = kNeverCid;
+    if ((type_ != NULL) && type_->IsSentinelType()) {
+      cid_ = kSentinelCid;
     }
   }
 
@@ -761,8 +761,8 @@
       cid_ = kDynamicCid;
     } else if (type_->IsNullType()) {
       cid_ = kNullCid;
-    } else if (type_->IsNeverType()) {
-      cid_ = kNeverCid;
+    } else if (type_->IsSentinelType()) {
+      cid_ = kSentinelCid;
     } else if (type_->IsFunctionType() || type_->IsDartFunctionType()) {
       cid_ = kClosureCid;
     } else if (type_->type_class_id() != kIllegalCid) {
@@ -1514,7 +1514,7 @@
   AbstractType* abstract_type = &AbstractType::ZoneHandle(field.type());
   TraceStrongModeType(this, *abstract_type);
   ASSERT(field.is_static());
-  auto& obj = Instance::Handle();
+  auto& obj = Object::Handle();
   const bool is_initialized = IsFieldInitialized(&obj);
   if (field.is_final() && is_initialized) {
     if (!obj.IsNull()) {
diff --git a/runtime/vm/compiler/backend/type_propagator_test.cc b/runtime/vm/compiler/backend/type_propagator_test.cc
index 4cb966e..87d459a 100644
--- a/runtime/vm/compiler/backend/type_propagator_test.cc
+++ b/runtime/vm/compiler/backend/type_propagator_test.cc
@@ -191,7 +191,7 @@
   {
     SafepointWriteRwLocker locker(thread,
                                   thread->isolate_group()->program_lock());
-    thread->isolate_group()->RegisterStaticField(field, Instance::Handle());
+    thread->isolate_group()->RegisterStaticField(field, Object::Handle());
   }
 
   FlowGraphBuilderHelper H;
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index e33e569..4a737b1 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -140,8 +140,13 @@
   }
 
   if (all_cids_known) {
+    const intptr_t receiver_cid = class_ids[0];
+    if (receiver_cid == kSentinelCid) {
+      // Unreachable call.
+      return false;
+    }
     const Class& receiver_class =
-        Class::Handle(Z, IG->class_table()->At(class_ids[0]));
+        Class::Handle(Z, IG->class_table()->At(receiver_cid));
     if (!receiver_class.is_finalized()) {
       // Do not eagerly finalize classes. ResolveDynamicForReceiverClass can
       // cause class finalization, since callee's receiver class may not be
diff --git a/runtime/vm/compiler/frontend/constant_reader.cc b/runtime/vm/compiler/frontend/constant_reader.cc
index d85926f..a9bd54f 100644
--- a/runtime/vm/compiler/frontend/constant_reader.cc
+++ b/runtime/vm/compiler/frontend/constant_reader.cc
@@ -21,7 +21,7 @@
       translation_helper_(helper->translation_helper_),
       active_class_(active_class),
       script_(helper->script()),
-      result_(Instance::Handle(zone_)) {}
+      result_(Object::Handle(zone_)) {}
 
 InstancePtr ConstantReader::ReadConstantInitializer() {
   Tag tag = helper_->ReadTag();  // read tag.
@@ -33,7 +33,7 @@
                     "Not a constant expression: unexpected kernel tag %s (%d)",
                     Reader::TagName(tag), tag);
   }
-  return result_.ptr();
+  return Instance::RawCast(result_.ptr());
 }
 
 InstancePtr ConstantReader::ReadConstantExpression() {
@@ -58,7 +58,7 @@
                     "Not a constant expression: unexpected kernel tag %s (%d)",
                     Reader::TagName(tag), tag);
   }
-  return result_.ptr();
+  return Instance::RawCast(result_.ptr());
 }
 
 ObjectPtr ConstantReader::ReadAnnotations() {
@@ -89,7 +89,7 @@
         H.thread()->isolate_group()->kernel_constants_mutex());
     const auto& constants_array = Array::Handle(Z, H.info().constants());
     ASSERT(constant_index < constants_array.Length());
-    result_ ^= constants_array.At(constant_index);
+    result_ = constants_array.At(constant_index);
   }
 
   // On miss, evaluate, and insert value.
@@ -102,7 +102,7 @@
     ASSERT(constant_index < constants_array.Length());
     constants_array.SetAt(constant_index, result_);
   }
-  return result_.ptr();
+  return Instance::RawCast(result_.ptr());
 }
 
 bool ConstantReader::IsInstanceConstant(intptr_t constant_index,
diff --git a/runtime/vm/compiler/frontend/constant_reader.h b/runtime/vm/compiler/frontend/constant_reader.h
index b4e52c4..733a463 100644
--- a/runtime/vm/compiler/frontend/constant_reader.h
+++ b/runtime/vm/compiler/frontend/constant_reader.h
@@ -47,7 +47,7 @@
   TranslationHelper& translation_helper_;
   ActiveClass* active_class_;
   const Script& script_;
-  Instance& result_;
+  Object& result_;
 
   DISALLOW_COPY_AND_ASSIGN(ConstantReader);
 };
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 8aa7359..ecca290 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -1141,6 +1141,10 @@
   return -kWordSize;
 }
 
+word Sentinel::NextFieldOffset() {
+  return -kWordSize;
+}
+
 word UnlinkedCall::NextFieldOffset() {
   return -kWordSize;
 }
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 32cbeee..7b746fe 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -890,6 +890,12 @@
   static word NextFieldOffset();
 };
 
+class Sentinel : public AllStatic {
+ public:
+  static word InstanceSize();
+  static word NextFieldOffset();
+};
+
 class UnlinkedCall : public AllStatic {
  public:
   static word InstanceSize();
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 56e8f0e..e3d2c5d 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -529,6 +529,7 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
 static constexpr dart::compiler::target::word Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 4;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     16;
 static constexpr dart::compiler::target::word StackTrace_InstanceSize = 20;
@@ -1074,6 +1075,7 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word Script_InstanceSize = 80;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
 static constexpr dart::compiler::target::word StackTrace_InstanceSize = 40;
@@ -1609,6 +1611,7 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
 static constexpr dart::compiler::target::word Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 4;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     16;
 static constexpr dart::compiler::target::word StackTrace_InstanceSize = 20;
@@ -2155,6 +2158,7 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word Script_InstanceSize = 80;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
 static constexpr dart::compiler::target::word StackTrace_InstanceSize = 40;
@@ -2699,6 +2703,7 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 80;
 static constexpr dart::compiler::target::word Script_InstanceSize = 56;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
 static constexpr dart::compiler::target::word StackTrace_InstanceSize = 24;
@@ -3244,6 +3249,7 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 80;
 static constexpr dart::compiler::target::word Script_InstanceSize = 56;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
 static constexpr dart::compiler::target::word StackTrace_InstanceSize = 24;
@@ -3778,6 +3784,7 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
 static constexpr dart::compiler::target::word Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 4;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     16;
 static constexpr dart::compiler::target::word StackTrace_InstanceSize = 20;
@@ -4317,6 +4324,7 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word Script_InstanceSize = 80;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
 static constexpr dart::compiler::target::word StackTrace_InstanceSize = 40;
@@ -4846,6 +4854,7 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 60;
 static constexpr dart::compiler::target::word Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 4;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     16;
 static constexpr dart::compiler::target::word StackTrace_InstanceSize = 20;
@@ -5386,6 +5395,7 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word Script_InstanceSize = 80;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
 static constexpr dart::compiler::target::word StackTrace_InstanceSize = 40;
@@ -5924,6 +5934,7 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 80;
 static constexpr dart::compiler::target::word Script_InstanceSize = 56;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
 static constexpr dart::compiler::target::word StackTrace_InstanceSize = 24;
@@ -6463,6 +6474,7 @@
 static constexpr dart::compiler::target::word RegExp_InstanceSize = 80;
 static constexpr dart::compiler::target::word Script_InstanceSize = 56;
 static constexpr dart::compiler::target::word SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word SingleTargetCache_InstanceSize =
     32;
 static constexpr dart::compiler::target::word StackTrace_InstanceSize = 24;
@@ -7064,6 +7076,7 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 60;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 4;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 20;
@@ -7671,6 +7684,7 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 72;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 40;
@@ -8282,6 +8296,7 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 72;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 40;
@@ -8889,6 +8904,7 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 24;
@@ -9497,6 +9513,7 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 24;
@@ -10095,6 +10112,7 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 60;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 40;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 4;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 16;
 static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 20;
@@ -10695,6 +10713,7 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 72;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 40;
@@ -11299,6 +11318,7 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 120;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 72;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 40;
@@ -11899,6 +11919,7 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 24;
@@ -12500,6 +12521,7 @@
 static constexpr dart::compiler::target::word AOT_RegExp_InstanceSize = 80;
 static constexpr dart::compiler::target::word AOT_Script_InstanceSize = 48;
 static constexpr dart::compiler::target::word AOT_SendPort_InstanceSize = 24;
+static constexpr dart::compiler::target::word AOT_Sentinel_InstanceSize = 8;
 static constexpr dart::compiler::target::word
     AOT_SingleTargetCache_InstanceSize = 32;
 static constexpr dart::compiler::target::word AOT_StackTrace_InstanceSize = 24;
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index 08f4fe7..43df0cb 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -379,6 +379,7 @@
   SIZEOF(RegExp, InstanceSize, UntaggedRegExp)                                 \
   SIZEOF(Script, InstanceSize, UntaggedScript)                                 \
   SIZEOF(SendPort, InstanceSize, UntaggedSendPort)                             \
+  SIZEOF(Sentinel, InstanceSize, UntaggedSentinel)                             \
   SIZEOF(SingleTargetCache, InstanceSize, UntaggedSingleTargetCache)           \
   SIZEOF(StackTrace, InstanceSize, UntaggedStackTrace)                         \
   SIZEOF(String, InstanceSize, UntaggedString)                                 \
diff --git a/runtime/vm/field_table.cc b/runtime/vm/field_table.cc
index bd20207..6809ff4 100644
--- a/runtime/vm/field_table.cc
+++ b/runtime/vm/field_table.cc
@@ -49,7 +49,7 @@
 }
 
 intptr_t FieldTable::FieldOffsetFor(intptr_t field_id) {
-  return field_id * sizeof(InstancePtr);  // NOLINT
+  return field_id * sizeof(ObjectPtr);  // NOLINT
 }
 
 bool FieldTable::Register(const Field& field, intptr_t expected_field_id) {
@@ -88,7 +88,7 @@
   free_head_ = field_id;
 }
 
-void FieldTable::SetAt(intptr_t index, InstancePtr raw_instance) {
+void FieldTable::SetAt(intptr_t index, ObjectPtr raw_instance) {
   ASSERT(index < capacity_);
   table_[index] = raw_instance;
 }
@@ -99,7 +99,7 @@
     Grow(new_capacity);
   }
 
-  ASSERT(table_[index] == InstancePtr());
+  ASSERT(table_[index] == ObjectPtr());
   if (index >= top_) {
     top_ = index + 1;
   }
@@ -109,14 +109,14 @@
   ASSERT(new_capacity > capacity_);
 
   auto old_table = table_;
-  auto new_table = static_cast<InstancePtr*>(
-      malloc(new_capacity * sizeof(InstancePtr)));  // NOLINT
+  auto new_table = static_cast<ObjectPtr*>(
+      malloc(new_capacity * sizeof(ObjectPtr)));  // NOLINT
   intptr_t i;
   for (i = 0; i < top_; i++) {
     new_table[i] = old_table[i];
   }
   for (; i < new_capacity; i++) {
-    new_table[i] = InstancePtr();
+    new_table[i] = ObjectPtr();
   }
   capacity_ = new_capacity;
   old_tables_->Add(old_table);
@@ -134,9 +134,9 @@
       IsolateGroup::Current()->program_lock()->IsCurrentThreadReader());
 
   FieldTable* clone = new FieldTable(for_isolate);
-  auto new_table = static_cast<InstancePtr*>(
-      malloc(capacity_ * sizeof(InstancePtr)));  // NOLINT
-  memmove(new_table, table_, capacity_ * sizeof(InstancePtr));
+  auto new_table =
+      static_cast<ObjectPtr*>(malloc(capacity_ * sizeof(ObjectPtr)));  // NOLINT
+  memmove(new_table, table_, capacity_ * sizeof(ObjectPtr));
   ASSERT(clone->table_ == nullptr);
   clone->table_ = new_table;
   clone->capacity_ = capacity_;
@@ -153,8 +153,7 @@
 
   ASSERT(visitor != NULL);
   visitor->set_gc_root_type("static fields table");
-  visitor->VisitPointers(reinterpret_cast<ObjectPtr*>(&table_[0]),
-                         reinterpret_cast<ObjectPtr*>(&table_[top_ - 1]));
+  visitor->VisitPointers(&table_[0], &table_[top_ - 1]);
   visitor->clear_gc_root_type();
 }
 
diff --git a/runtime/vm/field_table.h b/runtime/vm/field_table.h
index 8b2f473..84b3b5e 100644
--- a/runtime/vm/field_table.h
+++ b/runtime/vm/field_table.h
@@ -27,7 +27,7 @@
         capacity_(0),
         free_head_(-1),
         table_(nullptr),
-        old_tables_(new MallocGrowableArray<InstancePtr*>()),
+        old_tables_(new MallocGrowableArray<ObjectPtr*>()),
         isolate_(isolate),
         is_ready_to_use_(isolate == nullptr) {}
 
@@ -39,7 +39,7 @@
   intptr_t NumFieldIds() const { return top_; }
   intptr_t Capacity() const { return capacity_; }
 
-  InstancePtr* table() { return table_; }
+  ObjectPtr* table() { return table_; }
 
   void FreeOldTables();
 
@@ -58,11 +58,11 @@
   // to an existing static field value.
   void Free(intptr_t index);
 
-  InstancePtr At(intptr_t index) const {
+  ObjectPtr At(intptr_t index) const {
     ASSERT(IsValidIndex(index));
     return table_[index];
   }
-  void SetAt(intptr_t index, InstancePtr raw_instance);
+  void SetAt(intptr_t index, ObjectPtr raw_instance);
 
   FieldTable* Clone(Isolate* for_isolate);
 
@@ -86,10 +86,10 @@
   // element, last element contains -1.
   intptr_t free_head_;
 
-  InstancePtr* table_;
+  ObjectPtr* table_;
   // When table_ grows and have to reallocated, keep the old one here
   // so it will get freed when its are no longer in use.
-  MallocGrowableArray<InstancePtr*>* old_tables_;
+  MallocGrowableArray<ObjectPtr*>* old_tables_;
 
   // If non-NULL, it will specify the isolate this field table belongs to.
   // Growing the field table will keep the cached field table on the isolate's
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 183dabc..234a43a 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -910,7 +910,7 @@
 #endif  // DEBUG
 
 void IsolateGroup::RegisterStaticField(const Field& field,
-                                       const Instance& initial_value) {
+                                       const Object& initial_value) {
   ASSERT(program_lock()->IsCurrentThreadWriter());
 
   ASSERT(field.is_static());
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index fd19306..69dc7bc 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -786,7 +786,7 @@
   MutatorThreadPool* thread_pool() { return thread_pool_.get(); }
 
   void RegisterClass(const Class& cls);
-  void RegisterStaticField(const Field& field, const Instance& initial_value);
+  void RegisterStaticField(const Field& field, const Object& initial_value);
   void FreeStaticField(const Field& field);
 
   static bool AreIsolateGroupsEnabled() {
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 2402951..5be85a1 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -2110,7 +2110,8 @@
       : cls_(Class::Handle(zone)),
         cls_fields_(Array::Handle(zone)),
         entry_(Object::Handle(zone)),
-        value_(Instance::Handle(zone)),
+        value_(Object::Handle(zone)),
+        instance_(Instance::Handle(zone)),
         type_(AbstractType::Handle(zone)),
         cache_(SubtypeTestCache::Handle(zone)),
         entries_(Array::Handle(zone)),
@@ -2186,7 +2187,7 @@
     if (field.needs_load_guard()) {
       return;  // Already guarding.
     }
-    value_ ^= instance.GetField(field);
+    value_ = instance.GetField(field);
     if (value_.ptr() == Object::sentinel().ptr()) {
       if (field.is_late()) {
         // Late fields already have lazy initialization logic.
@@ -2202,8 +2203,9 @@
 
   DART_FORCE_INLINE
   void CheckValueType(bool null_safety,
-                      const Instance& value,
+                      const Object& value,
                       const Field& field) {
+    ASSERT(!value.IsSentinel());
     if (!null_safety && value.IsNull()) {
       return;
     }
@@ -2225,7 +2227,7 @@
     } else {
       instance_cid_or_signature_ = Smi::New(cid);
       if (cls_.NumTypeArguments() > 0) {
-        instance_type_arguments_ = value_.GetTypeArguments();
+        instance_type_arguments_ = Instance::Cast(value).GetTypeArguments();
       } else {
         instance_type_arguments_ = TypeArguments::null();
       }
@@ -2270,8 +2272,9 @@
     }
 
     if (!cache_hit) {
-      if (!value.IsAssignableTo(type_, instantiator_type_arguments_,
-                                function_type_arguments_)) {
+      instance_ ^= value.ptr();
+      if (!instance_.IsAssignableTo(type_, instantiator_type_arguments_,
+                                    function_type_arguments_)) {
         ASSERT(!FLAG_identity_reload);
         field.set_needs_load_guard(true);
       } else {
@@ -2287,7 +2290,8 @@
   Class& cls_;
   Array& cls_fields_;
   Object& entry_;
-  Instance& value_;
+  Object& value_;
+  Instance& instance_;
   AbstractType& type_;
   SubtypeTestCache& cache_;
   Array& entries_;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index c9f1b29..7e59984 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -213,7 +213,7 @@
       external_name_field_(Field::Handle(Z)),
       potential_natives_(GrowableObjectArray::Handle(Z)),
       potential_pragma_functions_(GrowableObjectArray::Handle(Z)),
-      static_field_value_(Instance::Handle(Z)),
+      static_field_value_(Object::Handle(Z)),
       pragma_class_(Class::Handle(Z)),
       name_index_handle_(Smi::Handle(Z)),
       expression_evaluation_library_(Library::Handle(Z)) {
@@ -483,7 +483,7 @@
       external_name_field_(Field::Handle(Z)),
       potential_natives_(GrowableObjectArray::Handle(Z)),
       potential_pragma_functions_(GrowableObjectArray::Handle(Z)),
-      static_field_value_(Instance::Handle(Z)),
+      static_field_value_(Object::Handle(Z)),
       pragma_class_(Class::Handle(Z)),
       name_index_handle_(Smi::Handle(Z)),
       expression_evaluation_library_(Library::Handle(Z)) {
@@ -1628,7 +1628,7 @@
                      /* is_reflectable = */ false,
                      /* is_late = */ false, klass, Object::dynamic_type(),
                      TokenPosition::kNoSource, TokenPosition::kNoSource);
-      IG->RegisterStaticField(deleted_enum_sentinel, Instance::Handle());
+      IG->RegisterStaticField(deleted_enum_sentinel, Object::Handle());
       fields_.Add(&deleted_enum_sentinel);
     }
 
@@ -2159,9 +2159,9 @@
   return script.ptr();
 }
 
-InstancePtr KernelLoader::GenerateFieldAccessors(const Class& klass,
-                                                 const Field& field,
-                                                 FieldHelper* field_helper) {
+ObjectPtr KernelLoader::GenerateFieldAccessors(const Class& klass,
+                                               const Field& field,
+                                               FieldHelper* field_helper) {
   const Tag tag = helper_.PeekTag();
   const bool has_initializer = (tag == kSomething);
 
@@ -2255,8 +2255,7 @@
   }
 
   // If static, we do need a getter that evaluates the initializer if necessary.
-  return field_helper->IsStatic() ? Instance::sentinel().ptr()
-                                  : Instance::null();
+  return field_helper->IsStatic() ? Object::sentinel().ptr() : Object::null();
 }
 
 LibraryPtr KernelLoader::LookupLibraryOrNull(NameIndex library) {
diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h
index 91d28c2..cd3dbcb 100644
--- a/runtime/vm/kernel_loader.h
+++ b/runtime/vm/kernel_loader.h
@@ -320,9 +320,9 @@
   }
 
   // Returns the initial field value for a static function (if applicable).
-  InstancePtr GenerateFieldAccessors(const Class& klass,
-                                     const Field& field,
-                                     FieldHelper* field_helper);
+  ObjectPtr GenerateFieldAccessors(const Class& klass,
+                                   const Field& field,
+                                   FieldHelper* field_helper);
   bool FieldNeedsSetter(FieldHelper* field_helper);
 
   void LoadLibraryImportsAndExports(Library* library,
@@ -403,7 +403,7 @@
   Field& external_name_field_;
   GrowableObjectArray& potential_natives_;
   GrowableObjectArray& potential_pragma_functions_;
-  Instance& static_field_value_;
+  Object& static_field_value_;
 
   Class& pragma_class_;
 
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index e153091..fae5e39b 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -167,6 +167,7 @@
 ClassPtr Object::exception_handlers_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::context_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::context_scope_class_ = static_cast<ClassPtr>(RAW_NULL);
+ClassPtr Object::sentinel_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::singletargetcache_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::unlinkedcall_class_ = static_cast<ClassPtr>(RAW_NULL);
 ClassPtr Object::monomorphicsmiablecall_class_ =
@@ -770,25 +771,20 @@
   cls.set_is_declaration_loaded();
   cls.set_is_type_finalized();
 
+  // Allocate and initialize Sentinel class.
+  cls = Class::New<Sentinel, RTN::Sentinel>(isolate_group);
+  sentinel_class_ = cls.ptr();
+
   // Allocate and initialize the sentinel values.
   {
-    *sentinel_ ^=
-        Object::Allocate(kNeverCid, Instance::InstanceSize(), Heap::kOld,
-                         Instance::ContainsCompressedPointers());
-
-    *transition_sentinel_ ^=
-        Object::Allocate(kNeverCid, Instance::InstanceSize(), Heap::kOld,
-                         Instance::ContainsCompressedPointers());
+    *sentinel_ ^= Sentinel::New();
+    *transition_sentinel_ ^= Sentinel::New();
   }
 
   // Allocate and initialize optimizing compiler constants.
   {
-    *unknown_constant_ ^=
-        Object::Allocate(kNeverCid, Instance::InstanceSize(), Heap::kOld,
-                         Instance::ContainsCompressedPointers());
-    *non_constant_ ^=
-        Object::Allocate(kNeverCid, Instance::InstanceSize(), Heap::kOld,
-                         Instance::ContainsCompressedPointers());
+    *unknown_constant_ ^= Sentinel::New();
+    *non_constant_ ^= Sentinel::New();
   }
 
   // Allocate the remaining VM internal classes.
@@ -1201,13 +1197,13 @@
   ASSERT(!empty_exception_handlers_->IsSmi());
   ASSERT(empty_exception_handlers_->IsExceptionHandlers());
   ASSERT(!sentinel_->IsSmi());
-  ASSERT(sentinel_->IsInstance());
+  ASSERT(sentinel_->IsSentinel());
   ASSERT(!transition_sentinel_->IsSmi());
-  ASSERT(transition_sentinel_->IsInstance());
+  ASSERT(transition_sentinel_->IsSentinel());
   ASSERT(!unknown_constant_->IsSmi());
-  ASSERT(unknown_constant_->IsInstance());
+  ASSERT(unknown_constant_->IsSentinel());
   ASSERT(!non_constant_->IsSmi());
-  ASSERT(non_constant_->IsInstance());
+  ASSERT(non_constant_->IsSentinel());
   ASSERT(!bool_true_->IsSmi());
   ASSERT(bool_true_->IsBool());
   ASSERT(!bool_false_->IsSmi());
@@ -1379,6 +1375,7 @@
   SET_CLASS_NAME(exception_handlers, ExceptionHandlers);
   SET_CLASS_NAME(context, Context);
   SET_CLASS_NAME(context_scope, ContextScope);
+  SET_CLASS_NAME(sentinel, Sentinel);
   SET_CLASS_NAME(singletargetcache, SingleTargetCache);
   SET_CLASS_NAME(unlinkedcall, UnlinkedCall);
   SET_CLASS_NAME(monomorphicsmiablecall, MonomorphicSmiableCall);
@@ -4951,6 +4948,8 @@
       return Symbols::Context().ToCString();
     case kContextScopeCid:
       return Symbols::ContextScope().ToCString();
+    case kSentinelCid:
+      return Symbols::Sentinel().ToCString();
     case kSingleTargetCacheCid:
       return Symbols::SingleTargetCache().ToCString();
     case kICDataCid:
@@ -10828,7 +10827,7 @@
   if (!closure_field.IsNull()) {
     ASSERT(closure_field.is_static());
     const Instance& closure =
-        Instance::Handle(zone, closure_field.StaticValue());
+        Instance::Handle(zone, Instance::RawCast(closure_field.StaticValue()));
     ASSERT(!closure.IsNull());
     ASSERT(closure.IsClosure());
     return closure.ptr();
@@ -10924,7 +10923,7 @@
 bool Field::IsUninitialized() const {
   Thread* thread = Thread::Current();
   const FieldTable* field_table = thread->isolate()->field_table();
-  const InstancePtr raw_value = field_table->At(field_id());
+  const ObjectPtr raw_value = field_table->At(field_id());
   ASSERT(raw_value != Object::transition_sentinel().ptr());
   return raw_value == Object::sentinel().ptr();
 }
@@ -11287,9 +11286,10 @@
   return false;  // Not found.
 }
 
-void Field::SetStaticValue(const Instance& value) const {
+void Field::SetStaticValue(const Object& value) const {
   auto thread = Thread::Current();
   ASSERT(thread->IsMutatorThread());
+  ASSERT(value.IsNull() || value.IsSentinel() || value.IsInstance());
 
   ASSERT(is_static());  // Valid only for static dart fields.
   const intptr_t id = field_id();
@@ -17706,6 +17706,25 @@
   return prev_cstr;
 }
 
+SentinelPtr Sentinel::New() {
+  return static_cast<SentinelPtr>(
+      Object::Allocate(Sentinel::kClassId, Sentinel::InstanceSize(), Heap::kOld,
+                       Sentinel::ContainsCompressedPointers()));
+}
+
+const char* Sentinel::ToCString() const {
+  if (ptr() == Object::sentinel().ptr()) {
+    return "sentinel";
+  } else if (ptr() == Object::transition_sentinel().ptr()) {
+    return "transition_sentinel";
+  } else if (ptr() == Object::unknown_constant().ptr()) {
+    return "unknown_constant";
+  } else if (ptr() == Object::non_constant().ptr()) {
+    return "non_constant";
+  }
+  return "Sentinel(unknown)";
+}
+
 ArrayPtr MegamorphicCache::buckets() const {
   return untag()->buckets();
 }
@@ -18808,13 +18827,15 @@
   if (hash != 0) {
     return hash;
   }
-  const Class& cls = Class::Handle(clazz());
+  Zone* zone = thread->zone();
+  const Class& cls = Class::Handle(zone, clazz());
   NoSafepointScope no_safepoint(thread);
   const intptr_t instance_size = SizeFromClass();
   ASSERT(instance_size != 0);
   hash = instance_size / kWordSize;
   uword this_addr = reinterpret_cast<uword>(this->untag());
-  Instance& member = Instance::Handle();
+  Object& obj = Object::Handle(zone);
+  Instance& instance = Instance::Handle(zone);
 
   const auto unboxed_fields_bitmap =
       thread->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(
@@ -18833,8 +18854,13 @@
                              *reinterpret_cast<uint32_t*>(this_addr + offset));
       }
     } else {
-      member ^= *reinterpret_cast<ObjectPtr*>(this_addr + offset);
-      hash = CombineHashes(hash, member.CanonicalizeHash());
+      obj = *reinterpret_cast<ObjectPtr*>(this_addr + offset);
+      if (obj.IsSentinel()) {
+        hash = CombineHashes(hash, 11);
+      } else {
+        instance ^= obj.ptr();
+        hash = CombineHashes(hash, instance.CanonicalizeHash());
+      }
     }
   }
   hash = FinalizeHash(hash, String::kHashBits);
@@ -19476,14 +19502,6 @@
 const char* Instance::ToCString() const {
   if (IsNull()) {
     return "null";
-  } else if (ptr() == Object::sentinel().ptr()) {
-    return "sentinel";
-  } else if (ptr() == Object::transition_sentinel().ptr()) {
-    return "transition_sentinel";
-  } else if (ptr() == Object::unknown_constant().ptr()) {
-    return "unknown_constant";
-  } else if (ptr() == Object::non_constant().ptr()) {
-    return "non_constant";
   } else if (Thread::Current()->no_safepoint_scope_depth() > 0) {
     // Can occur when running disassembler.
     return "Instance";
@@ -19943,6 +19961,10 @@
   return type_class_id() == kNeverCid;
 }
 
+bool AbstractType::IsSentinelType() const {
+  return type_class_id() == kSentinelCid;
+}
+
 bool AbstractType::IsTopTypeForInstanceOf() const {
   const classid_t cid = type_class_id();
   if (cid == kDynamicCid || cid == kVoidCid) {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 105f60c..898c813 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -453,10 +453,10 @@
   V(ExceptionHandlers, empty_exception_handlers)                               \
   V(Array, extractor_parameter_types)                                          \
   V(Array, extractor_parameter_names)                                          \
-  V(Instance, sentinel)                                                        \
-  V(Instance, transition_sentinel)                                             \
-  V(Instance, unknown_constant)                                                \
-  V(Instance, non_constant)                                                    \
+  V(Sentinel, sentinel)                                                        \
+  V(Sentinel, transition_sentinel)                                             \
+  V(Sentinel, unknown_constant)                                                \
+  V(Sentinel, non_constant)                                                    \
   V(Bool, bool_true)                                                           \
   V(Bool, bool_false)                                                          \
   V(Smi, smi_illegal_cid)                                                      \
@@ -521,6 +521,7 @@
   static ClassPtr deopt_info_class() { return deopt_info_class_; }
   static ClassPtr context_class() { return context_class_; }
   static ClassPtr context_scope_class() { return context_scope_class_; }
+  static ClassPtr sentinel_class() { return sentinel_class_; }
   static ClassPtr api_error_class() { return api_error_class_; }
   static ClassPtr language_error_class() { return language_error_class_; }
   static ClassPtr unhandled_exception_class() {
@@ -830,6 +831,7 @@
   static ClassPtr deopt_info_class_;            // Class of DeoptInfo.
   static ClassPtr context_class_;            // Class of the Context vm object.
   static ClassPtr context_scope_class_;      // Class of ContextScope vm object.
+  static ClassPtr sentinel_class_;           // Class of Sentinel vm object.
   static ClassPtr singletargetcache_class_;  // Class of SingleTargetCache.
   static ClassPtr unlinkedcall_class_;       // Class of UnlinkedCall.
   static ClassPtr
@@ -4024,8 +4026,8 @@
   void SetStaticConstFieldValue(const Instance& value,
                                 bool assert_initializing_store = true) const;
 
-  inline InstancePtr StaticValue() const;
-  void SetStaticValue(const Instance& value) const;
+  inline ObjectPtr StaticValue() const;
+  void SetStaticValue(const Object& value) const;
 
   inline intptr_t field_id() const;
   inline void set_field_id(intptr_t field_id) const;
@@ -6870,6 +6872,29 @@
   friend class Object;
 };
 
+// Class of special sentinel values:
+// - Object::sentinel() is a value that cannot be produced by Dart code.
+// It can be used to mark special values, for example to distinguish
+// "uninitialized" fields.
+// - Object::transition_sentinel() is a value marking that we are transitioning
+// from sentinel, e.g., computing a field value. Used to detect circular
+// initialization of static fields.
+// - Object::unknown_constant() and Object::non_constant() are optimizing
+// compiler's constant propagation constants.
+class Sentinel : public Object {
+ public:
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(UntaggedSentinel));
+  }
+
+  static SentinelPtr New();
+
+ private:
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(Sentinel, Object);
+  friend class Class;
+  friend class Object;
+};
+
 class MegamorphicCache : public CallSiteData {
  public:
   static const intptr_t kInitialCapacity = 16;
@@ -8011,6 +8036,9 @@
   // Check if this type represents the 'Never' type.
   bool IsNeverType() const;
 
+  // Check if this type represents the 'Sentinel' type.
+  bool IsSentinelType() const;
+
   // Check if this type represents the 'Object' type.
   bool IsObjectType() const { return type_class_id() == kInstanceCid; }
 
@@ -11638,7 +11666,7 @@
 #endif  //  !defined(DART_PRECOMPILED_RUNTIME)
 }
 
-InstancePtr Field::StaticValue() const {
+ObjectPtr Field::StaticValue() const {
   ASSERT(is_static());  // Valid only for static dart fields.
   return Isolate::Current()->field_table()->At(field_id());
 }
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 9ee1b59..99b66cd 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -1312,6 +1312,7 @@
     case kLinkedHashMapCid:
     case kMintCid:
     case kNeverCid:
+    case kSentinelCid:
     case kNullCid:
     case kObjectPoolCid:
     case kOneByteStringCid:
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index 1c23fa8..3f91520 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -403,7 +403,7 @@
     return;
   }
   if (is_static()) {
-    const Instance& valueObj = Instance::Handle(StaticValue());
+    const Object& valueObj = Object::Handle(StaticValue());
     jsobj.AddProperty("staticValue", valueObj);
   }
 
@@ -932,6 +932,25 @@
   Object::PrintJSONImpl(stream, ref);
 }
 
+void Sentinel::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  // Handle certain special sentinel values.
+  if (ptr() == Object::sentinel().ptr()) {
+    JSONObject jsobj(stream);
+    jsobj.AddProperty("type", "Sentinel");
+    jsobj.AddProperty("kind", "NotInitialized");
+    jsobj.AddProperty("valueAsString", "<not initialized>");
+    return;
+  } else if (ptr() == Object::transition_sentinel().ptr()) {
+    JSONObject jsobj(stream);
+    jsobj.AddProperty("type", "Sentinel");
+    jsobj.AddProperty("kind", "BeingInitialized");
+    jsobj.AddProperty("valueAsString", "<being initialized>");
+    return;
+  }
+
+  Object::PrintJSONImpl(stream, ref);
+}
+
 void MegamorphicCache::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   AddCommonObjectProperties(&jsobj, "Object", ref);
@@ -1075,19 +1094,6 @@
 void Instance::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
 
-  // Handle certain special instance values.
-  if (ptr() == Object::sentinel().ptr()) {
-    jsobj.AddProperty("type", "Sentinel");
-    jsobj.AddProperty("kind", "NotInitialized");
-    jsobj.AddProperty("valueAsString", "<not initialized>");
-    return;
-  } else if (ptr() == Object::transition_sentinel().ptr()) {
-    jsobj.AddProperty("type", "Sentinel");
-    jsobj.AddProperty("kind", "BeingInitialized");
-    jsobj.AddProperty("valueAsString", "<being initialized>");
-    return;
-  }
-
   PrintSharedInstanceJSON(&jsobj, ref);
   // TODO(regis): Wouldn't it be simpler to provide a Closure::PrintJSONImpl()?
   if (IsClosure()) {
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index 7afae88..de6a837 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -3035,7 +3035,7 @@
   {
     SafepointWriteRwLocker locker(thread,
                                   thread->isolate_group()->program_lock());
-    thread->isolate_group()->RegisterStaticField(field, Instance::sentinel());
+    thread->isolate_group()->RegisterStaticField(field, Object::sentinel());
   }
   return field.ptr();
 }
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index 410779e..5340a96 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -584,6 +584,7 @@
     TypedData::ElementSizeInBytes(raw_obj->GetClassId()) *
         Smi::Value(raw_obj->untag()->length()))
 VARIABLE_COMPRESSED_VISITOR(ContextScope, raw_obj->untag()->num_variables_)
+NULL_VISITOR(Sentinel)
 VARIABLE_VISITOR(InstructionsTable, raw_obj->untag()->length_)
 NULL_VISITOR(Mint)
 NULL_VISITOR(Double)
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 9dafa28..b9f09a5 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -2364,6 +2364,11 @@
   friend class SnapshotReader;
 };
 
+class UntaggedSentinel : public UntaggedObject {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(Sentinel);
+  VISIT_NOTHING();
+};
+
 class UntaggedSingleTargetCache : public UntaggedObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(SingleTargetCache);
   POINTER_FIELD(CodePtr, target)
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index a533e45..3ca81e8 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -600,6 +600,7 @@
 MESSAGE_SNAPSHOT_UNREACHABLE(PatchClass);
 MESSAGE_SNAPSHOT_UNREACHABLE(PcDescriptors);
 MESSAGE_SNAPSHOT_UNREACHABLE(Script);
+MESSAGE_SNAPSHOT_UNREACHABLE(Sentinel);
 MESSAGE_SNAPSHOT_UNREACHABLE(SingleTargetCache);
 MESSAGE_SNAPSHOT_UNREACHABLE(String);
 MESSAGE_SNAPSHOT_UNREACHABLE(SubtypeTestCache);
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index df247e6..533119d 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -227,6 +227,7 @@
   V(SavedTryContextVar, ":saved_try_context_var")                              \
   V(Script, "Script")                                                          \
   V(SecondArg, "y")                                                            \
+  V(Sentinel, "Sentinel")                                                      \
   V(Set, "set")                                                                \
   V(SetterPrefix, "set:")                                                      \
   V(SingleTargetCache, "SingleTargetCache")                                    \
diff --git a/runtime/vm/tagged_pointer.h b/runtime/vm/tagged_pointer.h
index 790050c..765af22 100644
--- a/runtime/vm/tagged_pointer.h
+++ b/runtime/vm/tagged_pointer.h
@@ -339,6 +339,7 @@
 DEFINE_TAGGED_POINTER(ExceptionHandlers, Object)
 DEFINE_TAGGED_POINTER(Context, Object)
 DEFINE_TAGGED_POINTER(ContextScope, Object)
+DEFINE_TAGGED_POINTER(Sentinel, Object)
 DEFINE_TAGGED_POINTER(SingleTargetCache, Object)
 DEFINE_TAGGED_POINTER(UnlinkedCall, Object)
 DEFINE_TAGGED_POINTER(MonomorphicSmiableCall, Object)
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index f0cb6c1..a9ff835 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -1043,7 +1043,7 @@
   // is important for code size (although code size on X64 is not a priority).
   uword saved_stack_limit_;
   uword stack_overflow_flags_;
-  InstancePtr* field_table_values_;
+  ObjectPtr* field_table_values_;
   Heap* heap_;
   uword volatile top_exit_frame_info_;
   StoreBufferBlock* store_buffer_block_;
@@ -1133,7 +1133,7 @@
   intptr_t ffi_marshalled_arguments_size_ = 0;
   uint64_t* ffi_marshalled_arguments_;
 
-  InstancePtr* field_table_values() const { return field_table_values_; }
+  ObjectPtr* field_table_values() const { return field_table_values_; }
 
 // Reusable handles support.
 #define REUSABLE_HANDLE_FIELDS(object) object* object##_handle_;
diff --git a/tools/VERSION b/tools/VERSION
index 875ad99..7c86e03 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 14
 PATCH 0
-PRERELEASE 203
+PRERELEASE 204
 PRERELEASE_PATCH 0
\ No newline at end of file