diff options
| -rw-r--r-- | runtime/class_linker.cc | 5 | ||||
| -rw-r--r-- | runtime/class_linker_test.cc | 7 | ||||
| -rw-r--r-- | runtime/class_root.h | 2 | ||||
| -rw-r--r-- | runtime/gc/heap.cc | 2 | ||||
| -rw-r--r-- | runtime/mirror/object_reference.h | 1 | ||||
| -rw-r--r-- | runtime/mirror/var_handle.cc | 21 | ||||
| -rw-r--r-- | runtime/mirror/var_handle.h | 21 | ||||
| -rw-r--r-- | runtime/oat.h | 4 | ||||
| -rw-r--r-- | test/1981-structural-redef-private-method-handles/expected-stdout.txt | 24 |
9 files changed, 69 insertions, 18 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index f3f7afdc3e..0563f3830b 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -969,6 +969,11 @@ bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b 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 5dc194f3ee..691fcf1293 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -815,6 +815,13 @@ struct FieldVarHandleOffsets : public CheckOffsets<mirror::FieldVarHandle> { } }; +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 85e074cc47..baa21286a8 100644 --- a/runtime/class_root.h +++ b/runtime/class_root.h @@ -50,6 +50,7 @@ class Proxy; template<typename T> class PrimitiveArray; class Reference; class StackTraceElement; +class StaticFieldVarHandle; class String; class Throwable; class VarHandle; @@ -78,6 +79,7 @@ class VarHandle; 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 4676deda61..21e9c31f0a 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -4507,6 +4507,8 @@ void Heap::VisitReflectiveTargets(ReflectiveValueVisitor *visit) { 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 adeb29c5d6..386244d643 100644 --- a/runtime/mirror/object_reference.h +++ b/runtime/mirror/object_reference.h @@ -58,6 +58,7 @@ constexpr bool IsMirroredDescriptor(std::string_view desc) { 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 7970c621d7..c071e23fd0 100644 --- a/runtime/mirror/var_handle.cc +++ b/runtime/mirror/var_handle.cc @@ -1454,16 +1454,19 @@ bool VarHandle::Access(AccessMode access_mode, 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 FieldVarHandle::VisitTarget(ReflectiveValueVisitor* v) { } } +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 fd225e0724..3747b3edbd 100644 --- a/runtime/mirror/var_handle.h +++ b/runtime/mirror/var_handle.h @@ -32,6 +32,7 @@ enum class Intrinsics; struct VarHandleOffsets; struct FieldVarHandleOffsets; +struct StaticFieldVarHandleOffsets; struct ArrayElementVarHandleOffsets; struct ByteArrayViewVarHandleOffsets; struct ByteBufferViewVarHandleOffsets; @@ -235,6 +236,26 @@ class MANAGED FieldVarHandle : public VarHandle { 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 ab45b84888..99268c0bca 100644 --- a/runtime/oat.h +++ b/runtime/oat.h @@ -32,8 +32,8 @@ class InstructionSetFeatures; 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 0c0ac6e9c0..33d0833f62 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 @@ Post set with old varhandle: class art.Test1981$Transform[FOO: new_value object, 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> |