[vm/concurrency] Remove usage of current isolate field state from compiler

As part of making the compiler independent of the current isolate (since
JITed code will be shared across all isolate) we make the compiler not
depend on global field state, with one exception: we preserve an existing
optimization that utilizes knowledge whether a global final field was
already initialized (if --enable-isolate-groups is turned off) - we do
so by asking the isolate group for it's own isolate member.

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

TEST=Refactoring of existing code.

Change-Id: I2f08d854af6102e05e5a1df8d5b66b514d6f3ce4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/182540
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Alexander Aprelev <aam@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index 427c0b9..df2b9df 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -854,8 +854,8 @@
   if (!FLAG_fields_may_be_reset) {
     const Field& field = instr->field();
     ASSERT(field.is_static());
-    if (field.is_final() && instr->IsFieldInitialized()) {
-      Instance& obj = Instance::Handle(Z, field.StaticValue());
+    auto& obj = Instance::Handle(Z);
+    if (field.is_final() && instr->IsFieldInitialized(&obj)) {
       if (obj.IsSmi() || (obj.IsOld() && obj.IsCanonical())) {
         SetValue(instr, obj);
         return;
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index f7cae12..b90b712 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1135,10 +1135,32 @@
   return field().ptr() == other->AsLoadStaticField()->field().ptr();
 }
 
-bool LoadStaticFieldInstr::IsFieldInitialized() const {
+bool LoadStaticFieldInstr::IsFieldInitialized(Instance* field_value) const {
+  if (FLAG_fields_may_be_reset) {
+    return false;
+  }
+
+  // Since new isolates will be spawned, the JITed code cannot depend on whether
+  // global field was initialized when running with --enable-isolate-groups.
+  if (IsolateGroup::AreIsolateGroupsEnabled()) return false;
+
   const Field& field = this->field();
-  return (field.StaticValue() != Object::sentinel().ptr()) &&
-         (field.StaticValue() != Object::transition_sentinel().ptr());
+  Isolate* only_isolate = IsolateGroup::Current()->FirstIsolate();
+  if (only_isolate == nullptr) {
+    // This can happen if background compiler executes this code but the mutator
+    // is being shutdown and the isolate was already unregistered from the group
+    // (and is trying to stop this BG compiler).
+    if (field_value != nullptr) {
+      *field_value = Object::sentinel().ptr();
+    }
+    return false;
+  }
+  if (field_value == nullptr) {
+    field_value = &Instance::Handle();
+  }
+  *field_value = only_isolate->field_table()->At(field.field_id());
+  return (field_value->ptr() != Object::sentinel().ptr()) &&
+         (field_value->ptr() != Object::transition_sentinel().ptr());
 }
 
 Definition* LoadStaticFieldInstr::Canonicalize(FlowGraph* flow_graph) {
@@ -1146,8 +1168,7 @@
   // make it safe to omit code that checks if the field needs initialization
   // because the field will be reset so it starts uninitialized in the process
   // running the precompiled code. We must be prepared to reinitialize fields.
-  if (calls_initializer() && !FLAG_fields_may_be_reset &&
-      IsFieldInitialized()) {
+  if (calls_initializer() && IsFieldInitialized()) {
     set_calls_initializer(false);
   }
   return this;
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 345f9b2..f27870d 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -5543,7 +5543,7 @@
   virtual CompileType ComputeType() const;
 
   const Field& field() const { return field_; }
-  bool IsFieldInitialized() const;
+  bool IsFieldInitialized(Instance* 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/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 3ae21f6..5f224b06 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -1446,9 +1446,9 @@
   AbstractType* abstract_type = &AbstractType::ZoneHandle(field.type());
   TraceStrongModeType(this, *abstract_type);
   ASSERT(field.is_static());
-  const bool is_initialized = IsFieldInitialized() && !FLAG_fields_may_be_reset;
+  auto& obj = Instance::Handle();
+  const bool is_initialized = IsFieldInitialized(&obj);
   if (field.is_final() && is_initialized) {
-    const Instance& obj = Instance::Handle(field.StaticValue());
     if (!obj.IsNull()) {
       is_nullable = CompileType::kNonNullable;
       cid = obj.GetClassId();
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 9856b71..1bb096e 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -70,20 +70,6 @@
                            B->last_used_block_id_, prologue_info);
 }
 
-void StreamingFlowGraphBuilder::EvaluateConstFieldValue(const Field& field) {
-  ASSERT(field.is_const() && field.IsUninitialized());
-
-  FieldHelper field_helper(this);
-  field_helper.ReadUntilExcluding(FieldHelper::kInitializer);
-  Tag initializer_tag = ReadTag();  // read first part of initializer.
-
-  ASSERT(initializer_tag == kSomething);
-
-  Instance& value =
-      Instance::Handle(Z, constant_reader_.ReadConstantExpression());
-  field.SetStaticValue(value);
-}
-
 void StreamingFlowGraphBuilder::SetupDefaultParameterValues() {
   intptr_t optional_parameter_count =
       parsed_function()->function().NumOptionalParameters();
@@ -1024,10 +1010,6 @@
     case UntaggedFunction::kImplicitGetter:
     case UntaggedFunction::kImplicitStaticGetter:
     case UntaggedFunction::kImplicitSetter: {
-      const Field& field = Field::Handle(Z, function.accessor_field());
-      if (field.is_const() && field.IsUninitialized()) {
-        EvaluateConstFieldValue(field);
-      }
       return B->BuildGraphOfFieldAccessor(function);
     }
     case UntaggedFunction::kFieldInitializer:
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index f469fc4..7f133f7 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -59,7 +59,6 @@
 
   void ParseKernelASTFunction();
   void ReadForwardingStubTarget(const Function& function);
-  void EvaluateConstFieldValue(const Field& field);
   void SetupDefaultParameterValues();
 
   FlowGraph* BuildGraphOfFieldInitializer();