[vm/concurrency] Make clustered snapshot serializer independent of current isolate

Issue https://github.com/dart-lang/sdk/issues/36097

TEST=Mainly refactoring, stress tests for --enable-isolate-groups with JIT will come in the future.

Change-Id: Iebb2fb8bd144cb9abd21916856a04f49f85541c0
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/183680
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 897e24a..1849a38 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -59,9 +59,10 @@
     GrowableArray<CodePtr>* code_objects,
     GrowableArray<ImageWriterCommand>* image_writer_commands) {
   auto thread = Thread::Current();
-  auto isolate = is_vm ? Dart::vm_isolate() : thread->isolate();
+  auto isolate_group =
+      is_vm ? Dart::vm_isolate()->group() : thread->isolate_group();
 
-  WritableCodePages writable_code_pages(thread, isolate);
+  WritableCodePages writable_code_pages(thread, isolate_group);
   CodeRelocator::Relocate(thread, code_objects, image_writer_commands, is_vm);
 }
 
@@ -146,8 +147,7 @@
     Serializer* s,
     intptr_t class_id) {
   const auto unboxed_fields_bitmap_host =
-      s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
-          class_id);
+      s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(class_id);
 
   UnboxedFieldBitmap unboxed_fields_bitmap;
   if (unboxed_fields_bitmap_host.IsEmpty() ||
@@ -358,7 +358,7 @@
       }
     }
 
-    auto shared_class_table = d->isolate()->group()->shared_class_table();
+    auto shared_class_table = d->isolate_group()->shared_class_table();
     for (intptr_t id = start_index_; id < stop_index_; id++) {
       ClassPtr cls = static_cast<ClassPtr>(d->Ref(id));
       Deserializer::InitializeHeader(cls, kClassCid, Class::InstanceSize());
@@ -498,7 +498,7 @@
   }
 
   void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+    if (is_canonical && (d->isolate_group() != Dart::vm_isolate()->group())) {
       CanonicalTypeArgumentsSet table(
           d->zone(),
           d->isolate_group()->object_store()->canonical_type_arguments());
@@ -2367,7 +2367,7 @@
 
   void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
     if (is_canonical && IsStringClassId(cid_) &&
-        (d->isolate() != Dart::vm_isolate())) {
+        (d->isolate_group() != Dart::vm_isolate()->group())) {
       CanonicalStringSet table(
           d->zone(), d->isolate_group()->object_store()->symbol_table());
       String& str = String::Handle(d->zone());
@@ -3165,8 +3165,7 @@
     const intptr_t next_field_offset = host_next_field_offset_in_words_
                                        << kWordSizeLog2;
     const auto unboxed_fields_bitmap =
-        s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
-            cid_);
+        s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(cid_);
     intptr_t offset = Instance::NextFieldOffset();
     while (offset < next_field_offset) {
       // Skips unboxed fields
@@ -3203,8 +3202,7 @@
     const intptr_t count = objects_.length();
     s->WriteUnsigned64(CalculateTargetUnboxedFieldsBitmap(s, cid_).Value());
     const auto unboxed_fields_bitmap =
-        s->isolate()->group()->shared_class_table()->GetUnboxedFieldsMapAt(
-            cid_);
+        s->isolate_group()->shared_class_table()->GetUnboxedFieldsMapAt(cid_);
 
     for (intptr_t i = 0; i < count; i++) {
       InstancePtr instance = objects_[i];
@@ -3458,7 +3456,7 @@
   }
 
   void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+    if (is_canonical && (d->isolate_group() != Dart::vm_isolate()->group())) {
       CanonicalTypeSet table(
           d->zone(), d->isolate_group()->object_store()->canonical_types());
       Type& type = Type::Handle(d->zone());
@@ -3578,7 +3576,7 @@
   }
 
   void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+    if (is_canonical && (d->isolate_group() != Dart::vm_isolate()->group())) {
       CanonicalFunctionTypeSet table(
           d->zone(),
           d->isolate_group()->object_store()->canonical_function_types());
@@ -3785,7 +3783,7 @@
   }
 
   void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+    if (is_canonical && (d->isolate_group() != Dart::vm_isolate()->group())) {
       CanonicalTypeParameterSet table(
           d->zone(),
           d->isolate_group()->object_store()->canonical_type_parameters());
@@ -3955,7 +3953,7 @@
   void ReadFill(Deserializer* d, bool is_canonical) {}
 
   void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+    if (is_canonical && (d->isolate_group() != Dart::vm_isolate()->group())) {
       const Class& mint_cls = Class::Handle(
           d->zone(), IsolateGroup::Current()->object_store()->mint_class());
       mint_cls.set_constants(Object::null_array());
@@ -4843,7 +4841,7 @@
   }
 
   void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+    if (is_canonical && (d->isolate_group() != Dart::vm_isolate()->group())) {
       CanonicalStringSet table(
           d->zone(), d->isolate_group()->object_store()->symbol_table());
       String& str = String::Handle(d->zone());
@@ -4940,7 +4938,7 @@
   }
 
   void PostLoad(Deserializer* d, const Array& refs, bool is_canonical) {
-    if (is_canonical && (d->isolate() != Dart::vm_isolate())) {
+    if (is_canonical && (d->isolate_group() != Dart::vm_isolate()->group())) {
       CanonicalStringSet table(
           d->zone(), d->isolate_group()->object_store()->symbol_table());
       String& str = String::Handle(d->zone());
@@ -5274,7 +5272,6 @@
   }
 
   void PostLoad(Deserializer* d, const Array& refs) {
-    auto isolate = d->thread()->isolate();
     auto isolate_group = d->thread()->isolate_group();
     isolate_group->class_table()->CopySizesFromClassObjects();
     d->heap()->old_space()->EvaluateAfterLoading();
@@ -5286,7 +5283,6 @@
       unit ^= units.At(LoadingUnit::kRootId);
       unit.set_base_objects(refs);
     }
-    isolate->isolate_object_store()->PreallocateObjects();
 
     // Setup native resolver for bootstrap impl.
     Bootstrap::SetupNativeResolver();
@@ -5392,7 +5388,7 @@
 
     // Reinitialize the dispatch table by rereading the table's serialization
     // in the root snapshot.
-    IsolateGroup* group = d->thread()->isolate()->group();
+    IsolateGroup* group = d->thread()->isolate_group();
     if (group->dispatch_table_snapshot() != nullptr) {
       ReadStream stream(group->dispatch_table_snapshot(),
                         group->dispatch_table_snapshot_size());
@@ -6005,7 +6001,7 @@
   WriteBytes(reinterpret_cast<const uint8_t*>(expected_version), version_len);
 
   const char* expected_features =
-      Dart::FeaturesString(Isolate::Current(), is_vm_snapshot, kind_);
+      Dart::FeaturesString(IsolateGroup::Current(), is_vm_snapshot, kind_);
   ASSERT(expected_features != NULL);
   const intptr_t features_len = strlen(expected_features);
   WriteBytes(reinterpret_cast<const uint8_t*>(expected_features),
@@ -6522,7 +6518,6 @@
   // object, from which we can get the reference ID for any code object.
   const intptr_t first_code_id = stream->ReadUnsigned();
 
-  auto const I = isolate();
   auto const IG = isolate_group();
   auto code = IG->object_store()->dispatch_table_null_error_stub();
   ASSERT(code != Code::null());
@@ -6560,11 +6555,11 @@
   }
   ASSERT(repeat_count == 0);
 
-  I->group()->set_dispatch_table(table);
+  IG->set_dispatch_table(table);
   intptr_t table_snapshot_size =
       stream->AddressOfCurrentPosition() - table_snapshot_start;
-  I->group()->set_dispatch_table_snapshot(table_snapshot_start);
-  I->group()->set_dispatch_table_snapshot_size(table_snapshot_size);
+  IG->set_dispatch_table_snapshot(table_snapshot_start);
+  IG->set_dispatch_table_snapshot_size(table_snapshot_size);
 #endif
 }
 
@@ -6575,11 +6570,12 @@
   return ApiError::null();
 }
 
-char* SnapshotHeaderReader::VerifyVersionAndFeatures(Isolate* isolate,
-                                                     intptr_t* offset) {
+char* SnapshotHeaderReader::VerifyVersionAndFeatures(
+    IsolateGroup* isolate_group,
+    intptr_t* offset) {
   char* error = VerifyVersion();
   if (error == nullptr) {
-    error = VerifyFeatures(isolate);
+    error = VerifyFeatures(isolate_group);
   }
   if (error == nullptr) {
     *offset = stream_.Position();
@@ -6622,9 +6618,9 @@
   return nullptr;
 }
 
-char* SnapshotHeaderReader::VerifyFeatures(Isolate* isolate) {
+char* SnapshotHeaderReader::VerifyFeatures(IsolateGroup* isolate_group) {
   const char* expected_features =
-      Dart::FeaturesString(isolate, (isolate == NULL), kind_);
+      Dart::FeaturesString(isolate_group, (isolate_group == NULL), kind_);
   ASSERT(expected_features != NULL);
   const intptr_t expected_len = strlen(expected_features);
 
@@ -6912,10 +6908,10 @@
   roots->PostLoad(this, refs);
 
 #if defined(DEBUG)
-  Isolate* isolate = thread()->isolate();
-  isolate->ValidateClassTable();
-  if (isolate != Dart::vm_isolate()) {
-    isolate->group()->heap()->Verify();
+  auto isolate_group = thread()->isolate_group();
+  isolate_group->ValidateClassTable();
+  if (isolate_group != Dart::vm_isolate()->group()) {
+    isolate_group->heap()->Verify();
   }
 #endif
 
@@ -6956,13 +6952,13 @@
       clustered_isolate_size_(0),
       mapped_data_size_(0),
       mapped_text_size_(0) {
-  ASSERT(isolate() != NULL);
+  ASSERT(isolate_group() != NULL);
   ASSERT(heap() != NULL);
   ObjectStore* object_store = isolate_group()->object_store();
   ASSERT(object_store != NULL);
 
 #if defined(DEBUG)
-  isolate()->ValidateClassTable();
+  isolate_group()->ValidateClassTable();
   isolate_group()->ValidateConstants();
 #endif  // DEBUG
 
@@ -7289,8 +7285,8 @@
   SnapshotHeaderReader header_reader(kind_, buffer_, size_);
 
   intptr_t offset = 0;
-  char* error =
-      header_reader.VerifyVersionAndFeatures(/*isolate=*/NULL, &offset);
+  char* error = header_reader.VerifyVersionAndFeatures(
+      /*isolate_group=*/nullptr, &offset);
   if (error != nullptr) {
     return ConvertToApiError(error);
   }
@@ -7305,11 +7301,11 @@
 
   if (Snapshot::IncludesCode(kind_)) {
     ASSERT(data_image_ != NULL);
-    thread_->isolate()->SetupImagePage(data_image_,
-                                       /* is_executable */ false);
+    thread_->isolate_group()->SetupImagePage(data_image_,
+                                             /* is_executable */ false);
     ASSERT(instructions_image_ != NULL);
-    thread_->isolate()->SetupImagePage(instructions_image_,
-                                       /* is_executable */ true);
+    thread_->isolate_group()->SetupImagePage(instructions_image_,
+                                             /* is_executable */ true);
   }
 
   VMDeserializationRoots roots;
@@ -7331,7 +7327,7 @@
   SnapshotHeaderReader header_reader(kind_, buffer_, size_);
   intptr_t offset = 0;
   char* error =
-      header_reader.VerifyVersionAndFeatures(thread_->isolate(), &offset);
+      header_reader.VerifyVersionAndFeatures(thread_->isolate_group(), &offset);
   if (error != nullptr) {
     return ConvertToApiError(error);
   }
@@ -7346,11 +7342,11 @@
 
   if (Snapshot::IncludesCode(kind_)) {
     ASSERT(data_image_ != NULL);
-    thread_->isolate()->SetupImagePage(data_image_,
-                                       /* is_executable */ false);
+    thread_->isolate_group()->SetupImagePage(data_image_,
+                                             /* is_executable */ false);
     ASSERT(instructions_image_ != NULL);
-    thread_->isolate()->SetupImagePage(instructions_image_,
-                                       /* is_executable */ true);
+    thread_->isolate_group()->SetupImagePage(instructions_image_,
+                                             /* is_executable */ true);
   }
 
   ProgramDeserializationRoots roots(thread_->isolate_group()->object_store());
@@ -7366,7 +7362,7 @@
   SnapshotHeaderReader header_reader(kind_, buffer_, size_);
   intptr_t offset = 0;
   char* error =
-      header_reader.VerifyVersionAndFeatures(thread_->isolate(), &offset);
+      header_reader.VerifyVersionAndFeatures(thread_->isolate_group(), &offset);
   if (error != nullptr) {
     return ConvertToApiError(error);
   }
@@ -7392,11 +7388,11 @@
 
   if (Snapshot::IncludesCode(kind_)) {
     ASSERT(data_image_ != NULL);
-    thread_->isolate()->SetupImagePage(data_image_,
-                                       /* is_executable */ false);
+    thread_->isolate_group()->SetupImagePage(data_image_,
+                                             /* is_executable */ false);
     ASSERT(instructions_image_ != NULL);
-    thread_->isolate()->SetupImagePage(instructions_image_,
-                                       /* is_executable */ true);
+    thread_->isolate_group()->SetupImagePage(instructions_image_,
+                                             /* is_executable */ true);
   }
 
   UnitDeserializationRoots roots(unit);
diff --git a/runtime/vm/clustered_snapshot.h b/runtime/vm/clustered_snapshot.h
index fcd5d90..c4bd073 100644
--- a/runtime/vm/clustered_snapshot.h
+++ b/runtime/vm/clustered_snapshot.h
@@ -537,12 +537,12 @@
   // Returns null on success and a malloc()ed error on failure.
   // The [offset] will be the next position in the snapshot stream after the
   // features.
-  char* VerifyVersionAndFeatures(Isolate* isolate, intptr_t* offset);
+  char* VerifyVersionAndFeatures(IsolateGroup* isolate_group, intptr_t* offset);
 
  private:
   char* VerifyVersion();
   char* ReadFeatures(const char** features, intptr_t* features_length);
-  char* VerifyFeatures(Isolate* isolate);
+  char* VerifyFeatures(IsolateGroup* isolate_group);
   char* BuildError(const char* message);
 
   Snapshot::Kind kind_;
@@ -685,7 +685,6 @@
 
   Thread* thread() const { return thread_; }
   Zone* zone() const { return thread_->zone(); }
-  Isolate* isolate() const { return thread_->isolate(); }
   IsolateGroup* isolate_group() const { return thread_->isolate_group(); }
   Heap* heap() const { return isolate_group()->heap(); }
 
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index c1259f2..51a197c 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -879,9 +879,6 @@
   HandleScope handle_scope(T);
   bool was_child_cloned_into_existing_isolate = false;
   if (source_isolate_group != nullptr) {
-    I->isolate_object_store()->Init();
-    I->isolate_object_store()->PreallocateObjects();
-
     // If a static field gets registered in [IsolateGroup::RegisterStaticField]:
     //
     //   * before this block it will ignore this isolate. The [Clone] of the
@@ -938,16 +935,16 @@
 
   I->set_ic_miss_code(StubCode::SwitchableCallMiss());
 
-  if ((snapshot_data == NULL) || (kernel_buffer != NULL)) {
-    Error& error = Error::Handle();
+  Error& error = Error::Handle();
+  if (snapshot_data == nullptr || kernel_buffer != nullptr) {
     error ^= IG->object_store()->PreallocateObjects();
     if (!error.IsNull()) {
       return error.ptr();
     }
-    error ^= I->isolate_object_store()->PreallocateObjects();
-    if (!error.IsNull()) {
-      return error.ptr();
-    }
+  }
+  error ^= I->isolate_object_store()->PreallocateObjects();
+  if (!error.IsNull()) {
+    return error.ptr();
   }
 
   if (!was_child_cloned_into_existing_isolate) {
@@ -983,11 +980,9 @@
   return Error::null();
 }
 
-const char* Dart::FeaturesString(Isolate* isolate,
+const char* Dart::FeaturesString(IsolateGroup* isolate_group,
                                  bool is_vm_isolate,
                                  Snapshot::Kind kind) {
-  auto isolate_group = isolate != nullptr ? isolate->group() : nullptr;
-
   TextBuffer buffer(64);
 
 // Different fields are included for DEBUG/RELEASE/PRODUCT.
diff --git a/runtime/vm/dart.h b/runtime/vm/dart.h
index b7406c1..fa95787 100644
--- a/runtime/vm/dart.h
+++ b/runtime/vm/dart.h
@@ -101,7 +101,7 @@
   static uword AllocateReadOnlyHandle();
   static bool IsReadOnlyHandle(uword address);
 
-  static const char* FeaturesString(Isolate* isolate,
+  static const char* FeaturesString(IsolateGroup* isolate_group,
                                     bool is_vm_snapshot,
                                     Snapshot::Kind kind);
   static Snapshot::Kind vm_snapshot_kind() { return vm_snapshot_kind_; }
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index 9757a28..2422e51 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -1210,13 +1210,14 @@
   }
 }
 
-WritableCodePages::WritableCodePages(Thread* thread, Isolate* isolate)
-    : StackResource(thread), isolate_(isolate) {
-  isolate_->group()->heap()->WriteProtectCode(false);
+WritableCodePages::WritableCodePages(Thread* thread,
+                                     IsolateGroup* isolate_group)
+    : StackResource(thread), isolate_group_(isolate_group) {
+  isolate_group_->heap()->WriteProtectCode(false);
 }
 
 WritableCodePages::~WritableCodePages() {
-  isolate_->group()->heap()->WriteProtectCode(true);
+  isolate_group_->heap()->WriteProtectCode(true);
 }
 
 }  // namespace dart
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index ac1f0ff..6ec7705 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -484,11 +484,11 @@
 
 class WritableCodePages : StackResource {
  public:
-  explicit WritableCodePages(Thread* thread, Isolate* isolate);
+  WritableCodePages(Thread* thread, IsolateGroup* isolate_group);
   ~WritableCodePages();
 
  private:
-  Isolate* isolate_;
+  IsolateGroup* isolate_group_;
 };
 
 #if defined(TESTING)
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 3799f2c..5b8ffb7 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -905,8 +905,8 @@
 }
 
 #if defined(DEBUG)
-void Isolate::ValidateClassTable() {
-  group()->class_table()->Validate();
+void IsolateGroup::ValidateClassTable() {
+  class_table()->Validate();
 }
 #endif  // DEBUG
 
@@ -1918,10 +1918,11 @@
   return Api::UnwrapHandle(api_result);
 }
 
-void Isolate::SetupImagePage(const uint8_t* image_buffer, bool is_executable) {
+void IsolateGroup::SetupImagePage(const uint8_t* image_buffer,
+                                  bool is_executable) {
   Image image(image_buffer);
-  group()->heap()->SetupImagePage(image.object_start(), image.object_size(),
-                                  is_executable);
+  heap()->SetupImagePage(image.object_start(), image.object_size(),
+                         is_executable);
 }
 
 void Isolate::ScheduleInterrupts(uword interrupt_bits) {
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 1ec4245..b73263d 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -344,6 +344,7 @@
   void RehashConstants();
 #if defined(DEBUG)
   void ValidateConstants();
+  void ValidateClassTable();
 #endif
 
   IsolateGroupSource* source() const { return source_.get(); }
@@ -384,6 +385,7 @@
   SafepointHandler* safepoint_handler() { return safepoint_handler_.get(); }
 
   void CreateHeap(bool is_vm_isolate, bool is_service_or_kernel_isolate);
+  void SetupImagePage(const uint8_t* snapshot_buffer, bool is_executable);
   void Shutdown();
 
 #define ISOLATE_METRIC_ACCESSOR(type, variable, name, unit)                    \
@@ -979,9 +981,6 @@
 
   // Register a newly introduced class.
   void RegisterClass(const Class& cls);
-#if defined(DEBUG)
-  void ValidateClassTable();
-#endif
 
   ThreadRegistry* thread_registry() const { return group()->thread_registry(); }
 
@@ -1100,8 +1099,6 @@
   }
   ObjectPtr CallDeferredLoadHandler(intptr_t id);
 
-  void SetupImagePage(const uint8_t* snapshot_buffer, bool is_executable);
-
   void ScheduleInterrupts(uword interrupt_bits);
 
   const char* MakeRunnable();
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 5202079..f90b098 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -710,7 +710,8 @@
   return NULL;
 }
 
-ApiErrorPtr SnapshotReader::VerifyVersionAndFeatures(Isolate* isolate) {
+ApiErrorPtr SnapshotReader::VerifyVersionAndFeatures(
+    IsolateGroup* isolate_group) {
   // If the version string doesn't match, return an error.
   // Note: New things are allocated only if we're going to return an error.
 
@@ -747,7 +748,8 @@
   }
   Advance(version_len);
 
-  const char* expected_features = Dart::FeaturesString(isolate, false, kind_);
+  const char* expected_features =
+      Dart::FeaturesString(isolate_group, false, kind_);
   ASSERT(expected_features != NULL);
   const intptr_t expected_len = strlen(expected_features);
 
@@ -1566,7 +1568,7 @@
   WriteBytes(reinterpret_cast<const uint8_t*>(expected_version), version_len);
 
   const char* expected_features =
-      Dart::FeaturesString(Isolate::Current(), false, kind_);
+      Dart::FeaturesString(IsolateGroup::Current(), false, kind_);
   ASSERT(expected_features != NULL);
   const intptr_t features_len = strlen(expected_features);
   WriteBytes(reinterpret_cast<const uint8_t*>(expected_features),
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index d526847..8ad3cb1 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -289,7 +289,7 @@
   Object* GetBackRef(intptr_t id);
 
   // Read version number of snapshot and verify.
-  ApiErrorPtr VerifyVersionAndFeatures(Isolate* isolate);
+  ApiErrorPtr VerifyVersionAndFeatures(IsolateGroup* isolate_group);
 
   ObjectPtr NewInteger(int64_t value);