VarHandle: add StaticFieldVarHandle class

Add StaticFieldVarHandle class to keep a live reference to the
declaring class for the target field of VarHandle's targeting static
fields.

Bug: 191980149
Test: art/test.py --host -r -g
Change-Id: I3a1cada6591d146b8f9fc9066105e3b617290185
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f3f7afd..0563f38 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -969,6 +969,11 @@
   CHECK(class_root != nullptr);
   SetClassRoot(ClassRoot::kJavaLangInvokeFieldVarHandle, class_root);
 
+  // Create java.lang.invoke.StaticFieldVarHandle.class root
+  class_root = FindSystemClass(self, "Ljava/lang/invoke/StaticFieldVarHandle;");
+  CHECK(class_root != nullptr);
+  SetClassRoot(ClassRoot::kJavaLangInvokeStaticFieldVarHandle, class_root);
+
   // Create java.lang.invoke.ArrayElementVarHandle.class root
   class_root = FindSystemClass(self, "Ljava/lang/invoke/ArrayElementVarHandle;");
   CHECK(class_root != nullptr);
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 5dc194f..691fcf1 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -815,6 +815,13 @@
   }
 };
 
+struct StaticFieldVarHandleOffsets : public CheckOffsets<mirror::StaticFieldVarHandle> {
+  StaticFieldVarHandleOffsets() : CheckOffsets<mirror::StaticFieldVarHandle>(
+      false, "Ljava/lang/invoke/StaticFieldVarHandle;") {
+    addOffset(OFFSETOF_MEMBER(mirror::StaticFieldVarHandle, declaring_class_), "declaringClass");
+  }
+};
+
 struct ArrayElementVarHandleOffsets : public CheckOffsets<mirror::ArrayElementVarHandle> {
   ArrayElementVarHandleOffsets() : CheckOffsets<mirror::ArrayElementVarHandle>(
       false, "Ljava/lang/invoke/ArrayElementVarHandle;") {
diff --git a/runtime/class_root.h b/runtime/class_root.h
index 85e074c..baa2128 100644
--- a/runtime/class_root.h
+++ b/runtime/class_root.h
@@ -50,6 +50,7 @@
 template<typename T> class PrimitiveArray;
 class Reference;
 class StackTraceElement;
+class StaticFieldVarHandle;
 class String;
 class Throwable;
 class VarHandle;
@@ -78,6 +79,7 @@
   M(kJavaLangInvokeMethodType,              "Ljava/lang/invoke/MethodType;",              mirror::MethodType)                             \
   M(kJavaLangInvokeVarHandle,               "Ljava/lang/invoke/VarHandle;",               mirror::VarHandle)                              \
   M(kJavaLangInvokeFieldVarHandle,          "Ljava/lang/invoke/FieldVarHandle;",          mirror::FieldVarHandle)                         \
+  M(kJavaLangInvokeStaticFieldVarHandle,    "Ljava/lang/invoke/StaticFieldVarHandle;",    mirror::StaticFieldVarHandle)                   \
   M(kJavaLangInvokeArrayElementVarHandle,   "Ljava/lang/invoke/ArrayElementVarHandle;",   mirror::ArrayElementVarHandle)                  \
   M(kJavaLangInvokeByteArrayViewVarHandle,  "Ljava/lang/invoke/ByteArrayViewVarHandle;",  mirror::ByteArrayViewVarHandle)                 \
   M(kJavaLangInvokeByteBufferViewVarHandle, "Ljava/lang/invoke/ByteBufferViewVarHandle;", mirror::ByteBufferViewVarHandle)                \
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 4676ded..21e9c31 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -4507,6 +4507,8 @@
       down_cast<mirror::Field*>(ref)->VisitTarget(visit);
     } else if (art::GetClassRoot<art::mirror::MethodHandle>()->IsAssignableFrom(klass)) {
       down_cast<mirror::MethodHandle*>(ref)->VisitTarget(visit);
+    } else if (art::GetClassRoot<art::mirror::StaticFieldVarHandle>()->IsAssignableFrom(klass)) {
+      down_cast<mirror::StaticFieldVarHandle*>(ref)->VisitTarget(visit);
     } else if (art::GetClassRoot<art::mirror::FieldVarHandle>()->IsAssignableFrom(klass)) {
       down_cast<mirror::FieldVarHandle*>(ref)->VisitTarget(visit);
     } else if (art::GetClassRoot<art::mirror::DexCache>()->IsAssignableFrom(klass)) {
diff --git a/runtime/mirror/object_reference.h b/runtime/mirror/object_reference.h
index adeb29c..386244d 100644
--- a/runtime/mirror/object_reference.h
+++ b/runtime/mirror/object_reference.h
@@ -58,6 +58,7 @@
     vis("Ljava/lang/invoke/ByteBufferViewVarHandle;") \
     vis("Ljava/lang/invoke/CallSite;")                \
     vis("Ljava/lang/invoke/FieldVarHandle;")          \
+    vis("Ljava/lang/invoke/StaticFieldVarHandle;")    \
     vis("Ljava/lang/invoke/MethodHandle;")            \
     vis("Ljava/lang/invoke/MethodHandleImpl;")        \
     vis("Ljava/lang/invoke/MethodHandles$Lookup;")    \
diff --git a/runtime/mirror/var_handle.cc b/runtime/mirror/var_handle.cc
index 7970c62..c071e23 100644
--- a/runtime/mirror/var_handle.cc
+++ b/runtime/mirror/var_handle.cc
@@ -1454,16 +1454,19 @@
   ObjPtr<ObjectArray<Class>> class_roots = Runtime::Current()->GetClassLinker()->GetClassRoots();
   ObjPtr<Class> klass = GetClass();
   if (klass == GetClassRoot<FieldVarHandle>(class_roots)) {
-    auto vh = reinterpret_cast<FieldVarHandle*>(this);
+    auto vh = ObjPtr<FieldVarHandle>::DownCast(this);
+    return vh->Access(access_mode, shadow_frame, operands, result);
+  } else if (klass == GetClassRoot<StaticFieldVarHandle>(class_roots)) {
+    auto vh = ObjPtr<StaticFieldVarHandle>::DownCast(this);
     return vh->Access(access_mode, shadow_frame, operands, result);
   } else if (klass == GetClassRoot<ArrayElementVarHandle>(class_roots)) {
-    auto vh = reinterpret_cast<ArrayElementVarHandle*>(this);
+    auto vh = ObjPtr<ArrayElementVarHandle>::DownCast(this);
     return vh->Access(access_mode, shadow_frame, operands, result);
   } else if (klass == GetClassRoot<ByteArrayViewVarHandle>(class_roots)) {
-    auto vh = reinterpret_cast<ByteArrayViewVarHandle*>(this);
+    auto vh = ObjPtr<ByteArrayViewVarHandle>::DownCast(this);
     return vh->Access(access_mode, shadow_frame, operands, result);
   } else if (klass == GetClassRoot<ByteBufferViewVarHandle>(class_roots)) {
-    auto vh = reinterpret_cast<ByteBufferViewVarHandle*>(this);
+    auto vh = ObjPtr<ByteBufferViewVarHandle>::DownCast(this);
     return vh->Access(access_mode, shadow_frame, operands, result);
   } else {
     LOG(FATAL) << "Unknown varhandle kind";
@@ -2004,6 +2007,16 @@
   }
 }
 
+void StaticFieldVarHandle::VisitTarget(ReflectiveValueVisitor* v) {
+  ArtField* orig = GetField();
+  ArtField* new_value =
+      v->VisitField(orig, HeapReflectiveSourceInfo(kSourceJavaLangInvokeFieldVarHandle, this));
+  if (orig != new_value) {
+    SetField64</*kTransactionActive*/ false>(ArtFieldOffset(),
+                                             reinterpret_cast<uintptr_t>(new_value));
+    SetFieldObject<false>(DeclaringClassOffset(), new_value->GetDeclaringClass());
+  }
+}
 
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/var_handle.h b/runtime/mirror/var_handle.h
index fd225e0..3747b3e 100644
--- a/runtime/mirror/var_handle.h
+++ b/runtime/mirror/var_handle.h
@@ -32,6 +32,7 @@
 
 struct VarHandleOffsets;
 struct FieldVarHandleOffsets;
+struct StaticFieldVarHandleOffsets;
 struct ArrayElementVarHandleOffsets;
 struct ByteArrayViewVarHandleOffsets;
 struct ByteBufferViewVarHandleOffsets;
@@ -235,6 +236,26 @@
   DISALLOW_IMPLICIT_CONSTRUCTORS(FieldVarHandle);
 };
 
+class MANAGED StaticFieldVarHandle : public FieldVarHandle {
+ public:
+  MIRROR_CLASS("Ljava/lang/invoke/StaticFieldVarHandle;");
+
+  // Used for updating var-handles to obsolete fields.
+  void VisitTarget(ReflectiveValueVisitor* v) REQUIRES(Locks::mutator_lock_);
+
+  static MemberOffset DeclaringClassOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(StaticFieldVarHandle, declaring_class_));
+  }
+
+ private:
+  HeapReference<mirror::Class> declaring_class_;
+
+  friend class VarHandleTest;  // for var_handle_test.
+  friend struct art::StaticFieldVarHandleOffsets;  // for verifying offset information
+  DISALLOW_IMPLICIT_CONSTRUCTORS(StaticFieldVarHandle);
+};
+
+
 // Represents a VarHandle providing accessors to an array.
 // The corresponding managed class in libart java.lang.invoke.ArrayElementVarHandle.
 class MANAGED ArrayElementVarHandle : public VarHandle {
diff --git a/runtime/oat.h b/runtime/oat.h
index ab45b84..99268c0 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -32,8 +32,8 @@
 class PACKED(4) OatHeader {
  public:
   static constexpr std::array<uint8_t, 4> kOatMagic { { 'o', 'a', 't', '\n' } };
-  // Last oat version changed reason: Apex versions in key/value store.
-  static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '9', '5', '\0' } };
+  // Last oat version changed reason: StaticFieldVarHandle introduction.
+  static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '9', '6', '\0' } };
 
   static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
   static constexpr const char* kDebuggableKey = "debuggable";
diff --git a/test/1981-structural-redef-private-method-handles/expected-stdout.txt b/test/1981-structural-redef-private-method-handles/expected-stdout.txt
index 0c0ac6e..33d0833 100644
--- a/test/1981-structural-redef-private-method-handles/expected-stdout.txt
+++ b/test/1981-structural-redef-private-method-handles/expected-stdout.txt
@@ -1,20 +1,20 @@
 Initial: class art.Test1981$Transform[FOO: value of <FOO FIELD>, BAR: value of <BAR FIELD>]
 Reading field FOO using (ID: 0) MethodHandle()Object = (ID: 1) value of <FOO FIELD>
-Reading field FOO using (ID: 2) java.lang.invoke.FieldVarHandle()->java.lang.Object = (ID: 1) value of <FOO FIELD>
+Reading field FOO using (ID: 2) java.lang.invoke.StaticFieldVarHandle()->java.lang.Object = (ID: 1) value of <FOO FIELD>
 Reading field BAR using (ID: 3) MethodHandle()Object = (ID: 4) value of <BAR FIELD>
-Reading field BAR using (ID: 5) java.lang.invoke.FieldVarHandle()->java.lang.Object = (ID: 4) value of <BAR FIELD>
+Reading field BAR using (ID: 5) java.lang.invoke.StaticFieldVarHandle()->java.lang.Object = (ID: 4) value of <BAR FIELD>
 Redefining Transform class
 Post redefinition : class art.Test1981$Transform[FOO: value of <FOO FIELD>, BAR: value of <BAR FIELD>, BAZ: null]
 Reading field FOO using (ID: 0) MethodHandle()Object = (ID: 1) value of <FOO FIELD>
-Reading field FOO using (ID: 2) java.lang.invoke.FieldVarHandle()->java.lang.Object = (ID: 1) value of <FOO FIELD>
+Reading field FOO using (ID: 2) java.lang.invoke.StaticFieldVarHandle()->java.lang.Object = (ID: 1) value of <FOO FIELD>
 Reading field BAR using (ID: 3) MethodHandle()Object = (ID: 4) value of <BAR FIELD>
-Reading field BAR using (ID: 5) java.lang.invoke.FieldVarHandle()->java.lang.Object = (ID: 4) value of <BAR FIELD>
+Reading field BAR using (ID: 5) java.lang.invoke.StaticFieldVarHandle()->java.lang.Object = (ID: 4) value of <BAR FIELD>
 Reading new field BAZ using (ID: 6) MethodHandle()Object = (ID: 7) <NULL>
-Reading new field BAZ using (ID: 8) java.lang.invoke.FieldVarHandle()->java.lang.Object = (ID: 7) <NULL>
+Reading new field BAZ using (ID: 8) java.lang.invoke.StaticFieldVarHandle()->java.lang.Object = (ID: 7) <NULL>
 Reading new field FOO using (ID: 9) MethodHandle()Object = (ID: 1) value of <FOO FIELD>
-Reading new field FOO using (ID: 10) java.lang.invoke.FieldVarHandle()->java.lang.Object = (ID: 1) value of <FOO FIELD>
+Reading new field FOO using (ID: 10) java.lang.invoke.StaticFieldVarHandle()->java.lang.Object = (ID: 1) value of <FOO FIELD>
 Reading new field BAR using (ID: 11) MethodHandle()Object = (ID: 4) value of <BAR FIELD>
-Reading new field BAR using (ID: 12) java.lang.invoke.FieldVarHandle()->java.lang.Object = (ID: 4) value of <BAR FIELD>
+Reading new field BAR using (ID: 12) java.lang.invoke.StaticFieldVarHandle()->java.lang.Object = (ID: 4) value of <BAR FIELD>
 Setting BAZ to (ID: 13) foo with new mh.
 Post set with new mh: class art.Test1981$Transform[FOO: value of <FOO FIELD>, BAR: value of <BAR FIELD>, BAZ: foo]
 Setting FOO to (ID: 14) class art.Test1981$Transform with old mh.
@@ -26,12 +26,12 @@
 Using mh to call new private method.
 Post reinit with mh: class art.Test1981$Transform[FOO: new_value object, BAR: value of <BAR FIELD>, BAZ: 42]
 Reading field FOO using (ID: 0) MethodHandle()Object = (ID: 15) new_value object
-Reading field FOO using (ID: 2) java.lang.invoke.FieldVarHandle()->java.lang.Object = (ID: 15) new_value object
+Reading field FOO using (ID: 2) java.lang.invoke.StaticFieldVarHandle()->java.lang.Object = (ID: 15) new_value object
 Reading field BAR using (ID: 3) MethodHandle()Object = (ID: 4) value of <BAR FIELD>
-Reading field BAR using (ID: 5) java.lang.invoke.FieldVarHandle()->java.lang.Object = (ID: 4) value of <BAR FIELD>
+Reading field BAR using (ID: 5) java.lang.invoke.StaticFieldVarHandle()->java.lang.Object = (ID: 4) value of <BAR FIELD>
 Reading new field BAZ using (ID: 6) MethodHandle()Object = (ID: 16) 42
-Reading new field BAZ using (ID: 8) java.lang.invoke.FieldVarHandle()->java.lang.Object = (ID: 16) 42
+Reading new field BAZ using (ID: 8) java.lang.invoke.StaticFieldVarHandle()->java.lang.Object = (ID: 16) 42
 Reading new field FOO using (ID: 9) MethodHandle()Object = (ID: 15) new_value object
-Reading new field FOO using (ID: 10) java.lang.invoke.FieldVarHandle()->java.lang.Object = (ID: 15) new_value object
+Reading new field FOO using (ID: 10) java.lang.invoke.StaticFieldVarHandle()->java.lang.Object = (ID: 15) new_value object
 Reading new field BAR using (ID: 11) MethodHandle()Object = (ID: 4) value of <BAR FIELD>
-Reading new field BAR using (ID: 12) java.lang.invoke.FieldVarHandle()->java.lang.Object = (ID: 4) value of <BAR FIELD>
+Reading new field BAR using (ID: 12) java.lang.invoke.StaticFieldVarHandle()->java.lang.Object = (ID: 4) value of <BAR FIELD>