diff options
author | 2019-10-04 08:38:11 +0000 | |
---|---|---|
committer | 2019-10-04 08:38:38 +0000 | |
commit | 712fa800b2b78e527d36c88dc369bf4b723587ea (patch) | |
tree | ccc4573a3c6bef136ef6da022350ebb5c17a1892 | |
parent | f70dfec27cae2625c199f1b8ecf1ef1f23580a45 (diff) |
Revert "Walk internal ArtField/ArtMethod pointers"
This reverts commit c84fc3a742b160ce51cbf01c2e5f971ccc0a2c6c.
Bug: 134162467
Reason for revert: Test fails on debuggable.
Change-Id: I240d58fafcc7434749947330b64c67d65b9b7a1e
38 files changed, 103 insertions, 1288 deletions
diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc index 3f205eb6f4..77acd562d1 100644 --- a/openjdkjvmti/events.cc +++ b/openjdkjvmti/events.cc @@ -64,8 +64,6 @@ #include "mirror/object-inl.h" #include "monitor-inl.h" #include "nativehelper/scoped_local_ref.h" -#include "reflective_handle.h" -#include "reflective_handle_scope-inl.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" #include "scoped_thread_state_change.h" @@ -802,14 +800,11 @@ class JvmtiMethodTraceListener final : public art::instrumentation::Instrumentat // Call-back for when we read from a field. void FieldRead(art::Thread* self, art::Handle<art::mirror::Object> this_object, - art::ArtMethod* method_p, + art::ArtMethod* method, uint32_t dex_pc, - art::ArtField* field_p) + art::ArtField* field) REQUIRES_SHARED(art::Locks::mutator_lock_) override { if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kFieldAccess)) { - art::StackReflectiveHandleScope<1, 1> rhs(self); - art::ReflectiveHandle<art::ArtField> field(rhs.NewHandle(field_p)); - art::ReflectiveHandle<art::ArtMethod> method(rhs.NewHandle(method_p)); art::JNIEnvExt* jnienv = self->GetJniEnv(); // DCHECK(!self->IsExceptionPending()); ScopedLocalRef<jobject> this_ref(jnienv, AddLocalRef<jobject>(jnienv, this_object.Get())); @@ -829,16 +824,13 @@ class JvmtiMethodTraceListener final : public art::instrumentation::Instrumentat void FieldWritten(art::Thread* self, art::Handle<art::mirror::Object> this_object, - art::ArtMethod* method_p, + art::ArtMethod* method, uint32_t dex_pc, - art::ArtField* field_p, + art::ArtField* field, art::Handle<art::mirror::Object> new_val) REQUIRES_SHARED(art::Locks::mutator_lock_) override { if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kFieldModification)) { art::JNIEnvExt* jnienv = self->GetJniEnv(); - art::StackReflectiveHandleScope<1, 1> rhs(self); - art::ReflectiveHandle<art::ArtField> field(rhs.NewHandle(field_p)); - art::ReflectiveHandle<art::ArtMethod> method(rhs.NewHandle(method_p)); // DCHECK(!self->IsExceptionPending()); ScopedLocalRef<jobject> this_ref(jnienv, AddLocalRef<jobject>(jnienv, this_object.Get())); ScopedLocalRef<jobject> fklass(jnienv, @@ -864,16 +856,13 @@ class JvmtiMethodTraceListener final : public art::instrumentation::Instrumentat // Call-back for when we write into a field. void FieldWritten(art::Thread* self, art::Handle<art::mirror::Object> this_object, - art::ArtMethod* method_p, + art::ArtMethod* method, uint32_t dex_pc, - art::ArtField* field_p, + art::ArtField* field, const art::JValue& field_value) REQUIRES_SHARED(art::Locks::mutator_lock_) override { if (event_handler_->IsEventEnabledAnywhere(ArtJvmtiEvent::kFieldModification)) { art::JNIEnvExt* jnienv = self->GetJniEnv(); - art::StackReflectiveHandleScope<1, 1> rhs(self); - art::ReflectiveHandle<art::ArtField> field(rhs.NewHandle(field_p)); - art::ReflectiveHandle<art::ArtMethod> method(rhs.NewHandle(method_p)); DCHECK(!self->IsExceptionPending()); ScopedLocalRef<jobject> this_ref(jnienv, AddLocalRef<jobject>(jnienv, this_object.Get())); ScopedLocalRef<jobject> fklass(jnienv, diff --git a/runtime/Android.bp b/runtime/Android.bp index cfa16f87dc..81e1ecfc87 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -189,7 +189,6 @@ libart_cc_defaults { "read_barrier.cc", "reference_table.cc", "reflection.cc", - "reflective_handle_scope.cc", "reflective_value_visitor.cc", "runtime.cc", "runtime_callbacks.cc", diff --git a/runtime/common_dex_operations.h b/runtime/common_dex_operations.h index 882e3ce4c7..2f86fbcca6 100644 --- a/runtime/common_dex_operations.h +++ b/runtime/common_dex_operations.h @@ -35,8 +35,6 @@ #include "mirror/class.h" #include "mirror/object.h" #include "obj_ptr-inl.h" -#include "reflective_handle.h" -#include "reflective_handle_scope.h" #include "runtime.h" #include "stack.h" #include "thread.h" @@ -102,10 +100,8 @@ static ALWAYS_INLINE bool DoFieldGetCommon(Thread* self, instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); if (UNLIKELY(instrumentation->HasFieldReadListeners())) { StackHandleScope<1> hs(self); - StackArtFieldHandleScope<1> rhs(self); // Wrap in handle wrapper in case the listener does thread suspension. HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj)); - ReflectiveHandleWrapper<ArtField> fh(rhs.NewReflectiveHandleWrapper(&field)); ObjPtr<mirror::Object> this_object; if (!field->IsStatic()) { this_object = obj; @@ -163,10 +159,8 @@ ALWAYS_INLINE bool DoFieldPutCommon(Thread* self, instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation(); if (UNLIKELY(instrumentation->HasFieldWriteListeners())) { StackHandleScope<2> hs(self); - StackArtFieldHandleScope<1> rhs(self); // Save this and return value (if needed) in case the instrumentation causes a suspend. HandleWrapperObjPtr<mirror::Object> h(hs.NewHandleWrapper(&obj)); - ReflectiveHandleWrapper<ArtField> fh(rhs.NewReflectiveHandleWrapper(&field)); ObjPtr<mirror::Object> this_object = field->IsStatic() ? nullptr : obj; mirror::Object* fake_root = nullptr; HandleWrapper<mirror::Object> ret(hs.NewHandleWrapper<mirror::Object>( @@ -216,10 +210,8 @@ ALWAYS_INLINE bool DoFieldPutCommon(Thread* self, ObjPtr<mirror::Class> field_class; { StackHandleScope<2> hs(self); - StackArtFieldHandleScope<1> rhs(self); HandleWrapperObjPtr<mirror::Object> h_reg(hs.NewHandleWrapper(®)); HandleWrapperObjPtr<mirror::Object> h_obj(hs.NewHandleWrapper(&obj)); - ReflectiveHandleWrapper<ArtField> fh(rhs.NewReflectiveHandleWrapper(&field)); field_class = field->ResolveType(); } // ArtField::ResolveType() may fail as evidenced with a dexing bug (b/78788577). diff --git a/runtime/debugger.cc b/runtime/debugger.cc index b28868fb7b..4cc3583496 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -71,8 +71,6 @@ #include "oat_file.h" #include "obj_ptr-inl.h" #include "reflection.h" -#include "reflective_handle.h" -#include "reflective_handle_scope-inl.h" #include "runtime-inl.h" #include "scoped_thread_state_change-inl.h" #include "stack.h" @@ -4058,19 +4056,18 @@ void Dbg::ExecuteMethodWithoutPendingException(ScopedObjectAccess& soa, DebugInv soa.Self()->AssertNoPendingException(); // Translate the method through the vtable, unless the debugger wants to suppress it. - StackArtMethodHandleScope<2> rhs(soa.Self()); - MutableReflectiveHandle<ArtMethod> m(rhs.NewHandle(pReq->method)); + ArtMethod* m = pReq->method; PointerSize image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize(); if ((pReq->options & JDWP::INVOKE_NONVIRTUAL) == 0 && pReq->receiver.Read() != nullptr) { - MutableReflectiveHandle<ArtMethod> actual_method(rhs.NewHandle( - pReq->klass.Read()->FindVirtualMethodForVirtualOrInterface(m.Get(), image_pointer_size))); - if (actual_method.Get() != m.Get()) { - VLOG(jdwp) << "ExecuteMethod translated " << m->PrettyMethod() - << " to " << actual_method->PrettyMethod(); + ArtMethod* actual_method = + pReq->klass.Read()->FindVirtualMethodForVirtualOrInterface(m, image_pointer_size); + if (actual_method != m) { + VLOG(jdwp) << "ExecuteMethod translated " << ArtMethod::PrettyMethod(m) + << " to " << ArtMethod::PrettyMethod(actual_method); m = actual_method; } } - VLOG(jdwp) << "ExecuteMethod " << m->PrettyMethod() + VLOG(jdwp) << "ExecuteMethod " << ArtMethod::PrettyMethod(m) << " receiver=" << pReq->receiver.Read() << " arg_count=" << pReq->arg_count; CHECK(m != nullptr); diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h index fe12a7c379..255607937e 100644 --- a/runtime/entrypoints/entrypoint_utils-inl.h +++ b/runtime/entrypoints/entrypoint_utils-inl.h @@ -39,7 +39,6 @@ #include "mirror/object-inl.h" #include "mirror/throwable.h" #include "nth_caller_visitor.h" -#include "reflective_handle_scope-inl.h" #include "runtime.h" #include "stack_map.h" #include "thread.h" @@ -382,11 +381,9 @@ inline ArtField* FindFieldFromCode(uint32_t field_idx, return resolved_field; } else { StackHandleScope<1> hs(self); - StackArtFieldHandleScope<1> rhs(self); - ReflectiveHandle<ArtField> resolved_field_handle(rhs.NewHandle(resolved_field)); if (LIKELY(class_linker->EnsureInitialized(self, hs.NewHandle(fields_class), true, true))) { // Otherwise let's ensure the class is initialized before resolving the field. - return resolved_field_handle.Get(); + return resolved_field; } DCHECK(self->IsExceptionPending()); // Throw exception and unwind return nullptr; // Failure. diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc index 5235f65224..5b4275cbad 100644 --- a/runtime/entrypoints_order_test.cc +++ b/runtime/entrypoints_order_test.cc @@ -136,13 +136,10 @@ class EntrypointsOrderTest : public CommonRuntimeTest { EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, flip_function, method_verifier, sizeof(void*)); EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, method_verifier, thread_local_mark_stack, sizeof(void*)); EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, thread_local_mark_stack, async_exception, sizeof(void*)); - EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, async_exception, top_reflective_handle_scope, - sizeof(void*)); // The first field after tlsPtr_ is forced to a 16 byte alignment so it might have some space. auto offset_tlsptr_end = OFFSETOF_MEMBER(Thread, tlsPtr_) + sizeof(decltype(reinterpret_cast<Thread*>(16)->tlsPtr_)); - CHECKED(offset_tlsptr_end - OFFSETOF_MEMBER(Thread, tlsPtr_.top_reflective_handle_scope) == - sizeof(void*), + CHECKED(offset_tlsptr_end - OFFSETOF_MEMBER(Thread, tlsPtr_.async_exception) == sizeof(void*), "async_exception last field"); } diff --git a/runtime/jni/jni_id_manager.cc b/runtime/jni/jni_id_manager.cc index 8190ac2ad3..2553fdf993 100644 --- a/runtime/jni/jni_id_manager.cc +++ b/runtime/jni/jni_id_manager.cc @@ -16,10 +16,6 @@ #include "jni_id_manager.h" -#include <algorithm> -#include <cstdint> -#include <type_traits> - #include "android-base/macros.h" #include "art_field-inl.h" #include "art_method-inl.h" @@ -38,11 +34,12 @@ #include "mirror/class_ext-inl.h" #include "mirror/object-inl.h" #include "obj_ptr-inl.h" -#include "reflective_handle_scope-inl.h" -#include "reflective_handle_scope.h" #include "reflective_value_visitor.h" #include "thread-inl.h" #include "thread.h" +#include <algorithm> +#include <cstdint> +#include <type_traits> namespace art { namespace jni { @@ -63,63 +60,65 @@ static constexpr uintptr_t IndexToId(size_t index) { } template <typename ArtType> -ObjPtr<mirror::PointerArray> GetIds(ObjPtr<mirror::Class> k, ArtType* t) - REQUIRES_SHARED(Locks::mutator_lock_) { - if constexpr (std::is_same_v<ArtType, ArtField>) { - return t->IsStatic() ? k->GetStaticFieldIds() : k->GetInstanceFieldIds(); - } else { - return k->GetMethodIds(); - } -} - -// Forces the appropriate id array to be present if possible. Returns true if allocation was -// attempted but failed. -template <typename ArtType> -bool EnsureIdsArray(Thread* self, ObjPtr<mirror::Class> k, ArtType* t) +ObjPtr<mirror::PointerArray> GetOrCreateIds(Thread* self, + ObjPtr<mirror::Class> k, + ArtType* t, + /*out*/bool* allocation_failure) REQUIRES_SHARED(Locks::mutator_lock_); template <> -bool EnsureIdsArray(Thread* self, ObjPtr<mirror::Class> k, ArtField* field) { +ObjPtr<mirror::PointerArray> GetOrCreateIds(Thread* self, + ObjPtr<mirror::Class> k, + ArtField* field, + /*out*/bool* allocation_failure) { ScopedExceptionStorage ses(self); StackHandleScope<1> hs(self); Handle<mirror::Class> h_k(hs.NewHandle(k)); + ObjPtr<mirror::PointerArray> res; if (Locks::mutator_lock_->IsExclusiveHeld(self)) { - return false; + res = field->IsStatic() ? h_k->GetStaticFieldIds() : h_k->GetInstanceFieldIds(); } else { - // NB This modifies the class to allocate the ClassExt and the ids array. - field->IsStatic() ? mirror::Class::GetOrCreateStaticFieldIds(h_k) - : mirror::Class::GetOrCreateInstanceFieldIds(h_k); + res = field->IsStatic() ? mirror::Class::GetOrCreateStaticFieldIds(h_k) + : mirror::Class::GetOrCreateInstanceFieldIds(h_k); } if (self->IsExceptionPending()) { self->AssertPendingOOMException(); ses.SuppressOldException("Failed to allocate maps for jmethodIDs. "); - return true; + *allocation_failure = true; + } else { + *allocation_failure = false; } - return false; + return res; } template <> -bool EnsureIdsArray(Thread* self, ObjPtr<mirror::Class> k, ArtMethod* method) { +ObjPtr<mirror::PointerArray> GetOrCreateIds(Thread* self, + ObjPtr<mirror::Class> k, + ArtMethod* method, + /*out*/bool* allocation_failure) { if (method->IsObsolete()) { if (kTraceIds) { LOG(INFO) << "jmethodID for Obsolete method " << method->PrettyMethod() << " requested!"; } // No ids array for obsolete methods. Just do a linear scan. - return false; + *allocation_failure = false; + return nullptr; } StackHandleScope<1> hs(self); Handle<mirror::Class> h_k(hs.NewHandle(k)); + ObjPtr<mirror::PointerArray> res; if (Locks::mutator_lock_->IsExclusiveHeld(self) || !Locks::mutator_lock_->IsSharedHeld(self)) { - return false; + res = h_k->GetMethodIds(); } else { - // NB This modifies the class to allocate the ClassExt and the ids array. - mirror::Class::GetOrCreateMethodIds(h_k); + res = mirror::Class::GetOrCreateMethodIds(h_k); } if (self->IsExceptionPending()) { self->AssertPendingOOMException(); - return true; + *allocation_failure = true; + } else { + *allocation_failure = false; } - return false; + return res; } template <typename ArtType> @@ -136,49 +135,33 @@ size_t GetIdOffset(ObjPtr<mirror::Class> k, ArtMethod* method, PointerSize point // Calls the relevant PrettyMethod/PrettyField on the input. template <typename ArtType> -std::string PrettyGeneric(ArtType t) REQUIRES_SHARED(Locks::mutator_lock_); -template <> -std::string PrettyGeneric(ArtMethod* f) { - return f->PrettyMethod(); -} -template <> -std::string PrettyGeneric(ReflectiveHandle<ArtMethod> f) { +std::string PrettyGeneric(ArtType* t) REQUIRES_SHARED(Locks::mutator_lock_); +template <> std::string PrettyGeneric(ArtMethod* f) { return f->PrettyMethod(); } -template <> -std::string PrettyGeneric(ArtField* f) { - return f->PrettyField(); -} -template <> -std::string PrettyGeneric(ReflectiveHandle<ArtField> f) { +template <> std::string PrettyGeneric(ArtField* f) { return f->PrettyField(); } // Checks if the field or method is obsolete. -template <typename ArtType> -bool IsObsolete(ReflectiveHandle<ArtType> t) REQUIRES_SHARED(Locks::mutator_lock_); -template <> -bool IsObsolete(ReflectiveHandle<ArtField> t ATTRIBUTE_UNUSED) { +template <typename ArtType> bool IsObsolete(ArtType* t) REQUIRES_SHARED(Locks::mutator_lock_); +template <> bool IsObsolete(ArtField* t ATTRIBUTE_UNUSED) { return false; } -template <> -bool IsObsolete(ReflectiveHandle<ArtMethod> t) { +template <> bool IsObsolete(ArtMethod* t) { return t->IsObsolete(); } // Get the canonical (non-copied) version of the field or method. Only relevant for methods. -template <typename ArtType> -ArtType* Canonicalize(ReflectiveHandle<ArtType> t) REQUIRES_SHARED(Locks::mutator_lock_); -template <> -ArtField* Canonicalize(ReflectiveHandle<ArtField> t) { - return t.Get(); +template <typename ArtType> ArtType* Canonicalize(ArtType* t) REQUIRES_SHARED(Locks::mutator_lock_); +template <> ArtField* Canonicalize(ArtField* t) { + return t; } -template <> -ArtMethod* Canonicalize(ReflectiveHandle<ArtMethod> t) { +template <> ArtMethod* Canonicalize(ArtMethod* t) { if (UNLIKELY(t->IsCopied())) { - return t->GetCanonicalMethod(); + t = t->GetCanonicalMethod(); } - return t.Get(); + return t; } }; // namespace @@ -186,8 +169,7 @@ ArtMethod* Canonicalize(ReflectiveHandle<ArtMethod> t) { // We increment the id by 2 each time to allow us to use the LSB as a flag that the ID is an index // and not a pointer. This gives us 2**31 unique methods that can be addressed on 32-bit art, which // should be more than enough. -template <> -uintptr_t JniIdManager::GetNextId<ArtField>(JniIdType type, ReflectiveHandle<ArtField> f) { +template <> uintptr_t JniIdManager::GetNextId<ArtField>(JniIdType type, ArtField* f) { if (LIKELY(type == JniIdType::kIndices)) { uintptr_t res = next_field_id_; next_field_id_ += 2; @@ -195,12 +177,11 @@ uintptr_t JniIdManager::GetNextId<ArtField>(JniIdType type, ReflectiveHandle<Art return res; } else { DCHECK_EQ(type, JniIdType::kSwapablePointer); - return reinterpret_cast<uintptr_t>(f.Get()); + return reinterpret_cast<uintptr_t>(f); } } -template <> -uintptr_t JniIdManager::GetNextId<ArtMethod>(JniIdType type, ReflectiveHandle<ArtMethod> m) { +template <> uintptr_t JniIdManager::GetNextId<ArtMethod>(JniIdType type, ArtMethod* m) { if (LIKELY(type == JniIdType::kIndices)) { uintptr_t res = next_method_id_; next_method_id_ += 2; @@ -208,26 +189,21 @@ uintptr_t JniIdManager::GetNextId<ArtMethod>(JniIdType type, ReflectiveHandle<Ar return res; } else { DCHECK_EQ(type, JniIdType::kSwapablePointer); - return reinterpret_cast<uintptr_t>(m.Get()); + return reinterpret_cast<uintptr_t>(m); } } -template <> -std::vector<ArtField*>& JniIdManager::GetGenericMap<ArtField>() { +template <> std::vector<ArtField*>& JniIdManager::GetGenericMap<ArtField>() { return field_id_map_; } -template <> -std::vector<ArtMethod*>& JniIdManager::GetGenericMap<ArtMethod>() { +template <> std::vector<ArtMethod*>& JniIdManager::GetGenericMap<ArtMethod>() { return method_id_map_; } -template <> -size_t JniIdManager::GetLinearSearchStartId<ArtField>( - ReflectiveHandle<ArtField> t ATTRIBUTE_UNUSED) { +template <> size_t JniIdManager::GetLinearSearchStartId<ArtField>(ArtField* t ATTRIBUTE_UNUSED) { return deferred_allocation_field_id_start_; } -template <> -size_t JniIdManager::GetLinearSearchStartId<ArtMethod>(ReflectiveHandle<ArtMethod> m) { +template <> size_t JniIdManager::GetLinearSearchStartId<ArtMethod>(ArtMethod* m) { if (m->IsObsolete()) { return 1; } else { @@ -236,24 +212,20 @@ size_t JniIdManager::GetLinearSearchStartId<ArtMethod>(ReflectiveHandle<ArtMetho } // TODO need to fix races in here with visitors -template <typename ArtType> -uintptr_t JniIdManager::EncodeGenericId(ReflectiveHandle<ArtType> t) { - static_assert(std::is_same_v<ArtType, ArtField> || std::is_same_v<ArtType, ArtMethod>, - "Expected ArtField or ArtMethod"); +template <typename ArtType> uintptr_t JniIdManager::EncodeGenericId(ArtType* t) { Runtime* runtime = Runtime::Current(); JniIdType id_type = runtime->GetJniIdType(); if (id_type == JniIdType::kPointer || t == nullptr) { - return reinterpret_cast<uintptr_t>(t.Get()); + return reinterpret_cast<uintptr_t>(t); } Thread* self = Thread::Current(); ScopedExceptionStorage ses(self); + t = Canonicalize(t); ObjPtr<mirror::Class> klass = t->GetDeclaringClass(); DCHECK(!klass.IsNull()) << "Null declaring class " << PrettyGeneric(t); - size_t off = GetIdOffset(klass, Canonicalize(t), kRuntimePointerSize); - // Here is the earliest point we can suspend. - bool allocation_failure = EnsureIdsArray(self, klass, t.Get()); - klass = t->GetDeclaringClass(); - ObjPtr<mirror::PointerArray> ids(GetIds(klass, t.Get())); + size_t off = GetIdOffset(klass, t, kRuntimePointerSize); + bool allocation_failure = false; + ObjPtr<mirror::PointerArray> ids(GetOrCreateIds(self, klass, t, &allocation_failure)); if (allocation_failure) { self->AssertPendingOOMException(); ses.SuppressOldException("OOM exception while trying to allocate JNI ids."); @@ -268,20 +240,8 @@ uintptr_t JniIdManager::EncodeGenericId(ReflectiveHandle<ArtType> t) { return cur_id; } WriterMutexLock mu(self, *Locks::jni_id_lock_); - ScopedAssertNoThreadSuspension sants("EncodeJniId critical section."); // Check the ids array for a racing id. - constexpr std::pair<size_t, size_t> counts { - std::is_same_v<ArtType, ArtField> ? 1 : 0, - std::is_same_v<ArtType, ArtField> ? 0 : 1, - }; - StackReflectiveHandleScope<counts.first, counts.second> hs(self); - t = hs.NewHandle(Canonicalize(t)); if (!ids.IsNull()) { - // It's possible we got suspended and structurally redefined during the EnsureIdsArray. We need - // to get the information again. - ids = GetIds(klass, t.Get()); - off = GetIdOffset(klass, Canonicalize(t), kRuntimePointerSize); - CHECK(!ids.IsNull()); cur_id = ids->GetElementPtrSize<uintptr_t>(off, kRuntimePointerSize); if (cur_id != 0) { // We were racing some other thread and lost. @@ -299,18 +259,17 @@ uintptr_t JniIdManager::EncodeGenericId(ReflectiveHandle<ArtType> t) { size_t search_start_index = IdToIndex(GetLinearSearchStartId(t)); size_t index = std::count_if(vec.cbegin() + search_start_index, vec.cend(), - [&found, &self, t](const ArtType* candidate) { - Locks::mutator_lock_->AssertSharedHeld(self); - found = found || candidate == t.Get(); + [&found, t](const ArtType* candidate) { + found = found || candidate == t; return !found; }) + search_start_index; if (found) { // We were either racing some other thread and lost or this thread was asked to encode the // same method multiple times while holding the mutator lock. - DCHECK_EQ(vec[index], t.Get()) - << "Expected: " << PrettyGeneric(vec[index]) << " got " << PrettyGeneric(t) - << " at index " << index << " (id: " << IndexToId(index) << ")."; + DCHECK_EQ(vec[index], t) << "Expected: " << PrettyGeneric(vec[index]) << " got " + << PrettyGeneric(t) << " at index " << index + << " (id: " << IndexToId(index) << ")."; return IndexToId(index); } } @@ -321,10 +280,10 @@ uintptr_t JniIdManager::EncodeGenericId(ReflectiveHandle<ArtType> t) { std::vector<ArtType*>& vec = GetGenericMap<ArtType>(); vec.reserve(cur_index + 1); vec.resize(std::max(vec.size(), cur_index + 1), nullptr); - vec[cur_index] = t.Get(); + vec[cur_index] = t; } else { DCHECK_EQ(cur_id % 2, 0u); - DCHECK_EQ(cur_id, reinterpret_cast<uintptr_t>(t.Get())); + DCHECK_EQ(cur_id, reinterpret_cast<uintptr_t>(t)); } if (ids.IsNull()) { if (kIsDebugBuild && !IsObsolete(t)) { @@ -339,24 +298,13 @@ uintptr_t JniIdManager::EncodeGenericId(ReflectiveHandle<ArtType> t) { } jfieldID JniIdManager::EncodeFieldId(ArtField* field) { - StackArtFieldHandleScope<1> rhs(Thread::Current()); - return EncodeFieldId(rhs.NewHandle(field)); -} - -jfieldID JniIdManager::EncodeFieldId(ReflectiveHandle<ArtField> field) { auto* res = reinterpret_cast<jfieldID>(EncodeGenericId(field)); if (kTraceIds && field != nullptr) { LOG(INFO) << "Returning " << res << " for field " << field->PrettyField(); } return res; } - jmethodID JniIdManager::EncodeMethodId(ArtMethod* method) { - StackArtMethodHandleScope<1> rhs(Thread::Current()); - return EncodeMethodId(rhs.NewHandle(method)); -} - -jmethodID JniIdManager::EncodeMethodId(ReflectiveHandle<ArtMethod> method) { auto* res = reinterpret_cast<jmethodID>(EncodeGenericId(method)); if (kTraceIds && method != nullptr) { LOG(INFO) << "Returning " << res << " for method " << method->PrettyMethod(); @@ -497,70 +445,17 @@ void JniIdManager::StartDefer() { } } -class JniIdDeferStackReflectiveScope : public BaseReflectiveHandleScope { - public: - JniIdDeferStackReflectiveScope() REQUIRES_SHARED(art::Locks::mutator_lock_) - : BaseReflectiveHandleScope(), methods_(), fields_() { - PushScope(Thread::Current()); - } - - void Initialize(const std::vector<ArtMethod*>& methods, const std::vector<ArtField*>& fields) - REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Roles::uninterruptible_) { - methods_ = methods; - fields_ = fields; - } - - ~JniIdDeferStackReflectiveScope() REQUIRES_SHARED(Locks::mutator_lock_) { - PopScope(); - } - - void VisitTargets(ReflectiveValueVisitor* visitor) override - REQUIRES_SHARED(Locks::mutator_lock_) { - for (auto it = methods_.begin(); it != methods_.end(); ++it) { - if (*it == nullptr) { - continue; - } - *it = visitor->VisitMethod(*it, ReflectiveHandleScopeSourceInfo(this)); - } - for (auto it = fields_.begin(); it != fields_.end(); ++it) { - if (*it == nullptr) { - continue; - } - *it = visitor->VisitField(*it, ReflectiveHandleScopeSourceInfo(this)); - } - } - - ArtField** GetFieldPtr(size_t idx) REQUIRES_SHARED(Locks::mutator_lock_) { - return &fields_[idx]; - } - - ArtMethod** GetMethodPtr(size_t idx) REQUIRES_SHARED(Locks::mutator_lock_) { - return &methods_[idx]; - } - - size_t NumFields() const { - return fields_.size(); - } - size_t NumMethods() const { - return methods_.size(); - } - - private: - std::vector<ArtMethod*> methods_; - std::vector<ArtField*> fields_; -}; - void JniIdManager::EndDefer() { // Fixup the method->id map. Thread* self = Thread::Current(); - auto set_id = [&](auto** t, uintptr_t id) REQUIRES_SHARED(Locks::mutator_lock_) { + auto set_id = [&](auto* t, uintptr_t id) REQUIRES_SHARED(Locks::mutator_lock_) { if (t == nullptr) { return; } - bool alloc_failure = EnsureIdsArray(self, (*t)->GetDeclaringClass(), *t); - ObjPtr<mirror::Class> klass((*t)->GetDeclaringClass()); - size_t off = GetIdOffset(klass, (*t), kRuntimePointerSize); - ObjPtr<mirror::PointerArray> ids = GetIds(klass, (*t)); + ObjPtr<mirror::Class> klass(t->GetDeclaringClass()); + size_t off = GetIdOffset(klass, t, kRuntimePointerSize); + bool alloc_failure = false; + ObjPtr<mirror::PointerArray> ids = GetOrCreateIds(self, klass, t, &alloc_failure); CHECK(!alloc_failure) << "Could not allocate jni ids array!"; if (ids.IsNull()) { return; @@ -587,24 +482,25 @@ void JniIdManager::EndDefer() { // ids when it finishes. Locks::mutator_lock_->AssertNotExclusiveHeld(self); Locks::mutator_lock_->AssertSharedHeld(self); - JniIdDeferStackReflectiveScope jidsrs; + std::vector<ArtMethod*> method_id_copy; + std::vector<ArtField*> field_id_copy; uintptr_t method_start_id; uintptr_t field_start_id; { ReaderMutexLock mu(self, *Locks::jni_id_lock_); - ScopedAssertNoThreadSuspension sants(__FUNCTION__); - jidsrs.Initialize(method_id_map_, field_id_map_); + method_id_copy = method_id_map_; + field_id_copy = field_id_map_; method_start_id = deferred_allocation_method_id_start_; field_start_id = deferred_allocation_field_id_start_; } - for (size_t index = kIsDebugBuild ? 0 : IdToIndex(method_start_id); index < jidsrs.NumMethods(); + for (size_t index = kIsDebugBuild ? 0 : IdToIndex(method_start_id); index < method_id_copy.size(); ++index) { - set_id(jidsrs.GetMethodPtr(index), IndexToId(index)); + set_id(method_id_copy[index], IndexToId(index)); } - for (size_t index = kIsDebugBuild ? 0 : IdToIndex(field_start_id); index < jidsrs.NumFields(); + for (size_t index = kIsDebugBuild ? 0 : IdToIndex(field_start_id); index < field_id_copy.size(); ++index) { - set_id(jidsrs.GetFieldPtr(index), IndexToId(index)); + set_id(field_id_copy[index], IndexToId(index)); } WriterMutexLock mu(self, *Locks::jni_id_lock_); DCHECK_GE(deferred_allocation_refcount_, 1u); diff --git a/runtime/jni/jni_id_manager.h b/runtime/jni/jni_id_manager.h index 1cfcefb858..6b43534d18 100644 --- a/runtime/jni/jni_id_manager.h +++ b/runtime/jni/jni_id_manager.h @@ -17,9 +17,8 @@ #ifndef ART_RUNTIME_JNI_JNI_ID_MANAGER_H_ #define ART_RUNTIME_JNI_JNI_ID_MANAGER_H_ -#include <jni.h> - #include <atomic> +#include <jni.h> #include <vector> #include "art_field.h" @@ -29,8 +28,6 @@ #include "reflective_value_visitor.h" namespace art { -template<typename RT> class ReflectiveHandle; - namespace jni { class ScopedEnableSuspendAllJniIdQueries; @@ -45,12 +42,8 @@ class JniIdManager { ArtMethod* DecodeMethodId(jmethodID method) REQUIRES(!Locks::jni_id_lock_); ArtField* DecodeFieldId(jfieldID field) REQUIRES(!Locks::jni_id_lock_); - jmethodID EncodeMethodId(ReflectiveHandle<ArtMethod> method) REQUIRES(!Locks::jni_id_lock_) - REQUIRES_SHARED(Locks::mutator_lock_); jmethodID EncodeMethodId(ArtMethod* method) REQUIRES(!Locks::jni_id_lock_) REQUIRES_SHARED(Locks::mutator_lock_); - jfieldID EncodeFieldId(ReflectiveHandle<ArtField> field) REQUIRES(!Locks::jni_id_lock_) - REQUIRES_SHARED(Locks::mutator_lock_); jfieldID EncodeFieldId(ArtField* field) REQUIRES(!Locks::jni_id_lock_) REQUIRES_SHARED(Locks::mutator_lock_); @@ -59,20 +52,15 @@ class JniIdManager { private: template <typename ArtType> - uintptr_t EncodeGenericId(ReflectiveHandle<ArtType> t) REQUIRES(!Locks::jni_id_lock_) + uintptr_t EncodeGenericId(ArtType* t) REQUIRES(!Locks::jni_id_lock_) REQUIRES_SHARED(Locks::mutator_lock_); template <typename ArtType> ArtType* DecodeGenericId(uintptr_t input) REQUIRES(!Locks::jni_id_lock_); - template <typename ArtType> std::vector<ArtType*>& GetGenericMap() - REQUIRES(Locks::jni_id_lock_); + template <typename ArtType> std::vector<ArtType*>& GetGenericMap() REQUIRES(Locks::jni_id_lock_); template <typename ArtType> - uintptr_t GetNextId(JniIdType id, ReflectiveHandle<ArtType> t) - REQUIRES_SHARED(Locks::mutator_lock_) - REQUIRES(Locks::jni_id_lock_); + uintptr_t GetNextId(JniIdType id, ArtType* t) REQUIRES(Locks::jni_id_lock_); template <typename ArtType> - size_t GetLinearSearchStartId(ReflectiveHandle<ArtType> t) - REQUIRES(Locks::jni_id_lock_) - REQUIRES_SHARED(Locks::mutator_lock_); + size_t GetLinearSearchStartId(ArtType* t) REQUIRES(Locks::jni_id_lock_); void StartDefer() REQUIRES(!Locks::jni_id_lock_) REQUIRES_SHARED(Locks::mutator_lock_); void EndDefer() REQUIRES(!Locks::jni_id_lock_) REQUIRES_SHARED(Locks::mutator_lock_); diff --git a/runtime/jni/jni_internal.h b/runtime/jni/jni_internal.h index 1616ee5263..da1792231b 100644 --- a/runtime/jni/jni_internal.h +++ b/runtime/jni/jni_internal.h @@ -22,10 +22,7 @@ #include "base/locks.h" #include "base/macros.h" -#include "reflective_handle.h" -#include "reflective_handle_scope.h" #include "runtime.h" -#include "thread.h" namespace art { @@ -90,16 +87,6 @@ static inline ArtField* DecodeArtField(jfieldID fid) { } template <bool kEnableIndexIds = true> -ALWAYS_INLINE static inline jfieldID EncodeArtField(ReflectiveHandle<ArtField> field) - REQUIRES_SHARED(Locks::mutator_lock_) { - if (kEnableIndexIds && Runtime::Current()->GetJniIdType() != JniIdType::kPointer) { - return Runtime::Current()->GetJniIdManager()->EncodeFieldId(field); - } else { - return reinterpret_cast<jfieldID>(field.Get()); - } -} - -template <bool kEnableIndexIds = true> ALWAYS_INLINE static inline jfieldID EncodeArtField(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_) { if (kEnableIndexIds && Runtime::Current()->GetJniIdType() != JniIdType::kPointer) { @@ -111,17 +98,6 @@ static inline jfieldID EncodeArtField(ArtField* field) REQUIRES_SHARED(Locks::mu template <bool kEnableIndexIds = true> ALWAYS_INLINE -static inline jmethodID EncodeArtMethod(ReflectiveHandle<ArtMethod> art_method) - REQUIRES_SHARED(Locks::mutator_lock_) { - if (kEnableIndexIds && Runtime::Current()->GetJniIdType() != JniIdType::kPointer) { - return Runtime::Current()->GetJniIdManager()->EncodeMethodId(art_method); - } else { - return reinterpret_cast<jmethodID>(art_method.Get()); - } -} - -template <bool kEnableIndexIds = true> -ALWAYS_INLINE static inline jmethodID EncodeArtMethod(ArtMethod* art_method) REQUIRES_SHARED(Locks::mutator_lock_) { if (kEnableIndexIds && Runtime::Current()->GetJniIdType() != JniIdType::kPointer) { diff --git a/runtime/reflective_handle.h b/runtime/reflective_handle.h deleted file mode 100644 index 014d976025..0000000000 --- a/runtime/reflective_handle.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_RUNTIME_REFLECTIVE_HANDLE_H_ -#define ART_RUNTIME_REFLECTIVE_HANDLE_H_ - -#include "base/value_object.h" -#include "reflective_reference.h" - -namespace art { - -// This is a holder similar to Handle<T> that is used to hold reflective references to ArtField and -// ArtMethod structures. A reflective reference is one that must be updated if the underlying class -// or instances are replaced due to structural redefinition or some other process. In general these -// don't need to be used. It's only when it's important that a reference to a field not become -// obsolete and it needs to be held over a suspend point that this should be used. -template <typename T> -class ReflectiveHandle : public ValueObject { - public: - static_assert(std::is_same_v<T, ArtField> || std::is_same_v<T, ArtMethod>, - "Expected ArtField or ArtMethod"); - - ReflectiveHandle() : reference_(nullptr) {} - - ALWAYS_INLINE ReflectiveHandle(const ReflectiveHandle<T>& handle) = default; - ALWAYS_INLINE ReflectiveHandle<T>& operator=(const ReflectiveHandle<T>& handle) = default; - - ALWAYS_INLINE explicit ReflectiveHandle(ReflectiveReference<T>* reference) - : reference_(reference) {} - - ALWAYS_INLINE T& operator*() const REQUIRES_SHARED(Locks::mutator_lock_) { - return *Get(); - } - - ALWAYS_INLINE T* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) { - return Get(); - } - - ALWAYS_INLINE T* Get() const REQUIRES_SHARED(Locks::mutator_lock_) { - return reference_->Ptr(); - } - - ALWAYS_INLINE bool IsNull() const { - // It's safe to null-check it without a read barrier. - return reference_->IsNull(); - } - - ALWAYS_INLINE bool operator!=(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) { - return !IsNull(); - } - - ALWAYS_INLINE bool operator==(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) { - return IsNull(); - } - - protected: - ReflectiveReference<T>* reference_; - - private: - friend class BaseReflectiveHandleScope; - template <size_t kNumFieldReferences, size_t kNumMethodReferences> - friend class StackReflectiveHandleScope; -}; - -// Handles that support assignment. -template <typename T> -class MutableReflectiveHandle : public ReflectiveHandle<T> { - public: - MutableReflectiveHandle() {} - - ALWAYS_INLINE MutableReflectiveHandle(const MutableReflectiveHandle<T>& handle) - REQUIRES_SHARED(Locks::mutator_lock_) = default; - - ALWAYS_INLINE MutableReflectiveHandle<T>& operator=(const MutableReflectiveHandle<T>& handle) - REQUIRES_SHARED(Locks::mutator_lock_) = default; - - ALWAYS_INLINE explicit MutableReflectiveHandle(ReflectiveReference<T>* reference) - REQUIRES_SHARED(Locks::mutator_lock_) - : ReflectiveHandle<T>(reference) {} - - ALWAYS_INLINE T* Assign(T* reference) REQUIRES_SHARED(Locks::mutator_lock_) { - ReflectiveReference<T>* ref = ReflectiveHandle<T>::reference_; - T* old = ref->Ptr(); - ref->Assign(reference); - return old; - } - - private: - friend class BaseReflectiveHandleScope; - template <size_t kNumFieldReferences, size_t kNumMethodReferences> - friend class StackReflectiveHandleScope; -}; - -template<typename T> -class ReflectiveHandleWrapper : public MutableReflectiveHandle<T> { - public: - ReflectiveHandleWrapper(T** obj, const MutableReflectiveHandle<T>& handle) - : MutableReflectiveHandle<T>(handle), obj_(obj) { - } - - ReflectiveHandleWrapper(const ReflectiveHandleWrapper&) = default; - - ~ReflectiveHandleWrapper() { - *obj_ = MutableReflectiveHandle<T>::Get(); - } - - private: - T** const obj_; -}; - -} // namespace art - -#endif // ART_RUNTIME_REFLECTIVE_HANDLE_H_ diff --git a/runtime/reflective_handle_scope-inl.h b/runtime/reflective_handle_scope-inl.h deleted file mode 100644 index 64ea9f921a..0000000000 --- a/runtime/reflective_handle_scope-inl.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_INL_H_ -#define ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_INL_H_ - -#include "android-base/thread_annotations.h" -#include "base/mutex.h" -#include "reflective_handle.h" -#include "reflective_handle_scope.h" -#include "thread-current-inl.h" - -namespace art { - -template <size_t kNumFields, size_t kNumMethods> -StackReflectiveHandleScope<kNumFields, kNumMethods>::StackReflectiveHandleScope(Thread* self) : field_pos_(0), method_pos_(0) { - DCHECK_EQ(self, Thread::Current()); - PushScope(self); -} - -template <size_t kNumFields, size_t kNumMethods> -void StackReflectiveHandleScope<kNumFields, kNumMethods>::VisitTargets( - ReflectiveValueVisitor* visitor) { - Thread* self = Thread::Current(); - DCHECK(GetThread() == self || - Locks::mutator_lock_->IsExclusiveHeld(self)) - << *GetThread() << " on thread " << *self; - auto visit_one = [&](auto& rv) NO_THREAD_SAFETY_ANALYSIS { - Locks::mutator_lock_->AssertSharedHeld(self); - if (!rv.IsNull()) { - rv.Assign((*visitor)(rv.Ptr(), ReflectiveHandleScopeSourceInfo(this))); - } - }; - std::for_each(fields_.begin(), fields_.begin() + field_pos_, visit_one); - std::for_each(methods_.begin(), methods_.begin() + method_pos_, visit_one); -} - -template <size_t kNumFields, size_t kNumMethods> -StackReflectiveHandleScope<kNumFields, kNumMethods>::~StackReflectiveHandleScope() { - PopScope(); -} - -void BaseReflectiveHandleScope::PushScope(Thread* self) { - DCHECK_EQ(self, Thread::Current()); - self_ = self; - link_ = self_->GetTopReflectiveHandleScope(); - self_->PushReflectiveHandleScope(this); -} - -void BaseReflectiveHandleScope::PopScope() { - auto* prev = self_->PopReflectiveHandleScope(); - CHECK_EQ(prev, this); - link_ = nullptr; -} - -} // namespace art - -#endif // ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_INL_H_ diff --git a/runtime/reflective_handle_scope.cc b/runtime/reflective_handle_scope.cc deleted file mode 100644 index 2c3ae5e6c5..0000000000 --- a/runtime/reflective_handle_scope.cc +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "reflective_handle_scope.h" - -#include <ostream> - -#include "thread.h" - -namespace art { - - -void BaseReflectiveHandleScope::Describe(std::ostream& os) const { - os << "[BaseReflectiveHandleScope self_=" << *self_ << ", link_=" << link_ << "]"; -} - -std::ostream& operator<<(std::ostream& os, const BaseReflectiveHandleScope& brhs) { - brhs.Describe(os); - return os; -} - -} // namespace art diff --git a/runtime/reflective_handle_scope.h b/runtime/reflective_handle_scope.h deleted file mode 100644 index 46cff8bce7..0000000000 --- a/runtime/reflective_handle_scope.h +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_H_ -#define ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_H_ - -#include <android-base/logging.h> - -#include <array> -#include <compare> -#include <functional> -#include <stack> - -#include "android-base/macros.h" -#include "base/enums.h" -#include "base/globals.h" -#include "base/locks.h" -#include "base/macros.h" -#include "base/value_object.h" -#include "reflective_handle.h" -#include "reflective_reference.h" -#include "reflective_value_visitor.h" - -namespace art { - -class ArtField; -class ArtMethod; -class BaseReflectiveHandleScope; -class Thread; - -// This is a holder similar to StackHandleScope that is used to hold reflective references to -// ArtField and ArtMethod structures. A reflective reference is one that must be updated if the -// underlying class or instances are replaced due to structural redefinition or some other process. -// In general these don't need to be used. It's only when it's important that a reference to a field -// not become obsolete and it needs to be held over a suspend point that this should be used. This -// takes care of the book-keeping to allow the runtime to visit and update ReflectiveHandles when -// structural redefinition occurs. -class BaseReflectiveHandleScope { - public: - template <typename Visitor> - ALWAYS_INLINE void VisitTargets(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_) { - FunctionReflectiveValueVisitor v(&visitor); - VisitTargets(&v); - } - - ALWAYS_INLINE virtual ~BaseReflectiveHandleScope() { - DCHECK(link_ == nullptr); - } - - virtual void VisitTargets(ReflectiveValueVisitor* visitor) - REQUIRES_SHARED(Locks::mutator_lock_) = 0; - - BaseReflectiveHandleScope* GetLink() { - return link_; - } - - Thread* GetThread() { - return self_; - } - - void Describe(std::ostream& os) const; - - protected: - ALWAYS_INLINE BaseReflectiveHandleScope() : self_(nullptr), link_(nullptr) {} - - ALWAYS_INLINE inline void PushScope(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_); - ALWAYS_INLINE inline void PopScope() REQUIRES_SHARED(Locks::mutator_lock_); - - // Thread this node is rooted in. - Thread* self_; - // Next node in the handle-scope linked list. Root is held by Thread. - BaseReflectiveHandleScope* link_; - - private: - DISALLOW_COPY_AND_ASSIGN(BaseReflectiveHandleScope); -}; -std::ostream& operator<<(std::ostream& os, const BaseReflectiveHandleScope& brhs); - -template <size_t kNumFields, size_t kNumMethods> -class StackReflectiveHandleScope : public BaseReflectiveHandleScope { - private: - static constexpr bool kHasFields = kNumFields > 0; - static constexpr bool kHasMethods = kNumMethods > 0; - - public: - ALWAYS_INLINE explicit StackReflectiveHandleScope(Thread* self) - REQUIRES_SHARED(Locks::mutator_lock_); - ALWAYS_INLINE ~StackReflectiveHandleScope() REQUIRES_SHARED(Locks::mutator_lock_); - - void VisitTargets(ReflectiveValueVisitor* visitor) override REQUIRES_SHARED(Locks::mutator_lock_); - - template <typename T, - typename = typename std::enable_if_t<(kHasFields && std::is_same_v<T, ArtField>) || - (kHasMethods && std::is_same_v<T, ArtMethod>)>> - ALWAYS_INLINE MutableReflectiveHandle<T> NewHandle(T* t) REQUIRES_SHARED(Locks::mutator_lock_) { - if constexpr (std::is_same_v<T, ArtField>) { - return NewFieldHandle(t); - } else { - static_assert(std::is_same_v<T, ArtMethod>, "Expected ArtField or ArtMethod"); - return NewMethodHandle(t); - } - } - template<typename T> - ALWAYS_INLINE ReflectiveHandleWrapper<T> NewReflectiveHandleWrapper(T** t) - REQUIRES_SHARED(art::Locks::mutator_lock_) { - return ReflectiveHandleWrapper<T>(t, NewHandle(*t)); - } - - ALWAYS_INLINE MutableReflectiveHandle<ArtField> NewFieldHandle(ArtField* f) - REQUIRES_SHARED(art::Locks::mutator_lock_) { - static_assert(kHasFields, "No fields"); - DCHECK_LT(field_pos_, kNumFields); - MutableReflectiveHandle<ArtField> fh(GetMutableFieldHandle(field_pos_++)); - fh.Assign(f); - return fh; - } - ALWAYS_INLINE ReflectiveHandleWrapper<ArtField> NewReflectiveFieldHandleWrapper(ArtField** f) - REQUIRES_SHARED(art::Locks::mutator_lock_) { - return ReflectiveHandleWrapper<ArtField>(f, NewMethodHandle(*f)); - } - - ALWAYS_INLINE ArtField* GetField(size_t i) { - static_assert(kHasFields, "No fields"); - return GetFieldReference(i)->Ptr(); - } - ALWAYS_INLINE ReflectiveHandle<ArtField> GetFieldHandle(size_t i) { - static_assert(kHasFields, "No fields"); - return ReflectiveHandle<ArtField>(GetFieldReference(i)); - } - ALWAYS_INLINE MutableReflectiveHandle<ArtField> GetMutableFieldHandle(size_t i) { - static_assert(kHasFields, "No fields"); - return MutableReflectiveHandle<ArtField>(GetFieldReference(i)); - } - - ALWAYS_INLINE MutableReflectiveHandle<ArtMethod> NewMethodHandle(ArtMethod* m) - REQUIRES_SHARED(art::Locks::mutator_lock_) { - static_assert(kHasMethods, "No methods"); - DCHECK_LT(method_pos_, kNumMethods); - MutableReflectiveHandle<ArtMethod> mh(GetMutableMethodHandle(method_pos_++)); - mh.Assign(m); - return mh; - } - ALWAYS_INLINE ReflectiveHandleWrapper<ArtMethod> NewReflectiveMethodHandleWrapper(ArtMethod** m) - REQUIRES_SHARED(art::Locks::mutator_lock_) { - return ReflectiveHandleWrapper<ArtMethod>(m, NewMethodHandle(*m)); - } - - ALWAYS_INLINE ArtMethod* GetMethod(size_t i) { - static_assert(kHasMethods, "No methods"); - return GetMethodReference(i)->Ptr(); - } - ALWAYS_INLINE ReflectiveHandle<ArtMethod> GetMethodHandle(size_t i) { - static_assert(kHasMethods, "No methods"); - return ReflectiveHandle<ArtMethod>(GetMethodReference(i)); - } - ALWAYS_INLINE MutableReflectiveHandle<ArtMethod> GetMutableMethodHandle(size_t i) { - static_assert(kHasMethods, "No methods"); - return MutableReflectiveHandle<ArtMethod>(GetMethodReference(i)); - } - - size_t RemainingFieldSlots() const { - return kNumFields - field_pos_; - } - - size_t RemainingMethodSlots() const { - return kNumMethods - method_pos_; - } - - private: - ReflectiveReference<ArtMethod>* GetMethodReference(size_t i) { - DCHECK_LT(i, method_pos_); - return &methods_[i]; - } - - ReflectiveReference<ArtField>* GetFieldReference(size_t i) { - DCHECK_LT(i, field_pos_); - return &fields_[i]; - } - - size_t field_pos_; - size_t method_pos_; - std::array<ReflectiveReference<ArtField>, kNumFields> fields_; - std::array<ReflectiveReference<ArtMethod>, kNumMethods> methods_; -}; - -template <size_t kNumMethods> -using StackArtMethodHandleScope = StackReflectiveHandleScope</*kNumFields=*/0, kNumMethods>; - -template <size_t kNumFields> -using StackArtFieldHandleScope = StackReflectiveHandleScope<kNumFields, /*kNumMethods=*/0>; - -} // namespace art - -#endif // ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_H_ diff --git a/runtime/reflective_reference.h b/runtime/reflective_reference.h deleted file mode 100644 index f57c0301bc..0000000000 --- a/runtime/reflective_reference.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ART_RUNTIME_REFLECTIVE_REFERENCE_H_ -#define ART_RUNTIME_REFLECTIVE_REFERENCE_H_ - -#include "android-base/macros.h" -#include "base/macros.h" -#include "mirror/object_reference.h" - -namespace art { - -class ArtField; -class ArtMethod; -// A reference to a ArtField or ArtMethod. -template <class ReflectiveType> -class ReflectiveReference { - public: - static_assert(std::is_same_v<ReflectiveType, ArtMethod> || - std::is_same_v<ReflectiveType, ArtField>, - "Uknown type!"); - ReflectiveReference() : val_(nullptr) {} - explicit ReflectiveReference(ReflectiveType* r) : val_(r) {} - ReflectiveReference<ReflectiveType>& operator=(const ReflectiveReference<ReflectiveType>& t) = - default; - - ReflectiveType* Ptr() { - return val_; - } - - void Assign(ReflectiveType* r) { - val_ = r; - } - - bool IsNull() const { - return val_ == nullptr; - } - - bool operator==(const ReflectiveReference<ReflectiveType>& rr) const { - return val_ == rr.val_; - } - bool operator!=(const ReflectiveReference<ReflectiveType>& rr) const { - return !operator==(rr); - } - bool operator==(std::nullptr_t) const { - return IsNull(); - } - bool operator!=(std::nullptr_t) const { - return !IsNull(); - } - - private: - ReflectiveType* val_; -}; - -} // namespace art - -#endif // ART_RUNTIME_REFLECTIVE_REFERENCE_H_ diff --git a/runtime/reflective_value_visitor.cc b/runtime/reflective_value_visitor.cc index 5a288d38be..69fd51ff6e 100644 --- a/runtime/reflective_value_visitor.cc +++ b/runtime/reflective_value_visitor.cc @@ -42,13 +42,4 @@ void JniIdReflectiveSourceInfo<jmethodID>::Describe(std::ostream& os) const { os << " jmethodID=" << reinterpret_cast<uintptr_t>(id_); } -void ReflectiveHandleScopeSourceInfo::Describe(std::ostream& os) const { - ReflectionSourceInfo::Describe(os); - os << " source= (" << source_ << ") "; - if (source_ == nullptr) { - os << "nullptr"; - } else { - os << *source_; - } -} } // namespace art diff --git a/runtime/reflective_value_visitor.h b/runtime/reflective_value_visitor.h index 0b09a0bf8a..8823fcba9c 100644 --- a/runtime/reflective_value_visitor.h +++ b/runtime/reflective_value_visitor.h @@ -124,7 +124,10 @@ class ReflectiveHandleScopeSourceInfo : public ReflectionSourceInfo { explicit ReflectiveHandleScopeSourceInfo(BaseReflectiveHandleScope* source) : ReflectionSourceInfo(kSourceThreadHandleScope), source_(source) {} - void Describe(std::ostream& os) const override; + void Describe(std::ostream& os) const override { + ReflectionSourceInfo::Describe(os); + os << " source=" << source_; + } private: BaseReflectiveHandleScope* source_; diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 0c9aeceb15..8f68b55a26 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -2198,7 +2198,6 @@ void Runtime::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) { } void Runtime::VisitReflectiveTargets(ReflectiveValueVisitor *visitor) { - thread_list_->VisitReflectiveTargets(visitor); heap_->VisitReflectiveTargets(visitor); jni_id_manager_->VisitReflectiveTargets(visitor); callbacks_->VisitReflectiveTargets(visitor); diff --git a/runtime/thread.cc b/runtime/thread.cc index 3aacfcb8dd..088f997855 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -98,7 +98,6 @@ #include "quick_exception_handler.h" #include "read_barrier-inl.h" #include "reflection.h" -#include "reflective_handle_scope-inl.h" #include "runtime-inl.h" #include "runtime.h" #include "runtime_callbacks.h" @@ -3958,14 +3957,6 @@ class RootCallbackVisitor { const uint32_t tid_; }; -void Thread::VisitReflectiveTargets(ReflectiveValueVisitor* visitor) { - for (BaseReflectiveHandleScope* brhs = GetTopReflectiveHandleScope(); - brhs != nullptr; - brhs = brhs->GetLink()) { - brhs->VisitTargets(visitor); - } -} - template <bool kPrecise> void Thread::VisitRoots(RootVisitor* visitor) { const pid_t thread_id = GetThreadId(); diff --git a/runtime/thread.h b/runtime/thread.h index 16ca2aa4f6..22c9d06da5 100644 --- a/runtime/thread.h +++ b/runtime/thread.h @@ -40,7 +40,6 @@ #include "managed_stack.h" #include "offsets.h" #include "read_barrier_config.h" -#include "reflective_handle_scope.h" #include "runtime_globals.h" #include "runtime_stats.h" #include "thread_state.h" @@ -636,9 +635,6 @@ class Thread { void VisitRoots(RootVisitor* visitor, VisitRootFlags flags) REQUIRES_SHARED(Locks::mutator_lock_); - void VisitReflectiveTargets(ReflectiveValueVisitor* visitor) - REQUIRES(Locks::mutator_lock_); - void VerifyStack() REQUIRES_SHARED(Locks::mutator_lock_) { if (kVerifyStack) { VerifyStackImpl(); @@ -896,23 +892,6 @@ class Thread { top_handle_scope)); } - BaseReflectiveHandleScope* GetTopReflectiveHandleScope() { - return tlsPtr_.top_reflective_handle_scope; - } - - void PushReflectiveHandleScope(BaseReflectiveHandleScope* scope) { - DCHECK_EQ(scope->GetLink(), tlsPtr_.top_reflective_handle_scope); - DCHECK_EQ(scope->GetThread(), this); - tlsPtr_.top_reflective_handle_scope = scope; - } - - BaseReflectiveHandleScope* PopReflectiveHandleScope() { - BaseReflectiveHandleScope* handle_scope = tlsPtr_.top_reflective_handle_scope; - DCHECK(handle_scope != nullptr); - tlsPtr_.top_reflective_handle_scope = tlsPtr_.top_reflective_handle_scope->GetLink(); - return handle_scope; - } - DebugInvokeReq* GetInvokeReq() const { return tlsPtr_.debug_invoke_req; } @@ -1660,7 +1639,7 @@ class Thread { thread_local_objects(0), mterp_current_ibase(nullptr), thread_local_alloc_stack_top(nullptr), thread_local_alloc_stack_end(nullptr), flip_function(nullptr), method_verifier(nullptr), thread_local_mark_stack(nullptr), - async_exception(nullptr), top_reflective_handle_scope(nullptr) { + async_exception(nullptr) { std::fill(held_mutexes, held_mutexes + kLockLevelCount, nullptr); } @@ -1818,9 +1797,6 @@ class Thread { // The pending async-exception or null. mirror::Throwable* async_exception; - - // Top of the linked-list for reflective-handle scopes or null if none. - BaseReflectiveHandleScope* top_reflective_handle_scope; } tlsPtr_; // Small thread-local cache to be used from the interpreter. diff --git a/runtime/thread_list.cc b/runtime/thread_list.cc index 4e8f468346..28bc184595 100644 --- a/runtime/thread_list.cc +++ b/runtime/thread_list.cc @@ -1542,13 +1542,6 @@ void ThreadList::VisitRoots(RootVisitor* visitor, VisitRootFlags flags) const { } } -void ThreadList::VisitReflectiveTargets(ReflectiveValueVisitor *visitor) const { - MutexLock mu(Thread::Current(), *Locks::thread_list_lock_); - for (const auto& thread : list_) { - thread->VisitReflectiveTargets(visitor); - } -} - uint32_t ThreadList::AllocThreadId(Thread* self) { MutexLock mu(self, *Locks::allocated_thread_ids_lock_); for (size_t i = 0; i < allocated_ids_.size(); ++i) { diff --git a/runtime/thread_list.h b/runtime/thread_list.h index dad896eb5a..b5b4450498 100644 --- a/runtime/thread_list.h +++ b/runtime/thread_list.h @@ -22,7 +22,6 @@ #include "base/mutex.h" #include "base/value_object.h" #include "jni.h" -#include "reflective_handle_scope.h" #include "suspend_reason.h" #include <bitset> @@ -174,8 +173,6 @@ class ThreadList { REQUIRES(!Locks::thread_list_lock_, !Locks::thread_suspend_count_lock_) REQUIRES_SHARED(Locks::mutator_lock_); - void VisitReflectiveTargets(ReflectiveValueVisitor* visitor) const REQUIRES(Locks::mutator_lock_); - // Return a copy of the thread list. std::list<Thread*> GetList() REQUIRES(Locks::thread_list_lock_) { return list_; diff --git a/test/1985-structural-redefine-stack-scope/expected.txt b/test/1985-structural-redefine-stack-scope/expected.txt deleted file mode 100644 index 6a5618ebc6..0000000000 --- a/test/1985-structural-redefine-stack-scope/expected.txt +++ /dev/null @@ -1 +0,0 @@ -JNI_OnLoad called diff --git a/test/1985-structural-redefine-stack-scope/info.txt b/test/1985-structural-redefine-stack-scope/info.txt deleted file mode 100644 index a108013047..0000000000 --- a/test/1985-structural-redefine-stack-scope/info.txt +++ /dev/null @@ -1 +0,0 @@ -Tests StackReflectiveHandleScope. diff --git a/test/1985-structural-redefine-stack-scope/run b/test/1985-structural-redefine-stack-scope/run deleted file mode 100755 index a36de16ea6..0000000000 --- a/test/1985-structural-redefine-stack-scope/run +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# -# Copyright 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Ask for stack traces to be dumped to a file rather than to stdout. -./default-run "$@" --jvmti --android-runtime-option -Xopaque-jni-ids:true diff --git a/test/1985-structural-redefine-stack-scope/src/Main.java b/test/1985-structural-redefine-stack-scope/src/Main.java deleted file mode 100644 index cb86c3d2ec..0000000000 --- a/test/1985-structural-redefine-stack-scope/src/Main.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import art.Redefinition; -import java.lang.invoke.*; -import java.lang.reflect.Field; -import java.util.Base64; - -public class Main { - public static final class Transform { - static { - } - - public static Object foo = null; - } - - /** - * Base64 encoded dex bytes for: - * public static final class Transform { - * static {} - * public static Object bar = null; - * public static Object foo = null; - * } - */ - public static final byte[] DEX_BYTES = - Base64.getDecoder() - .decode( - "ZGV4CjAzNQCjkRjcSr1RJO8FnnCjHV/8h6keJP/+P3WQAwAAcAAAAHhWNBIAAAAAAAAAANgCAAAQ" - + "AAAAcAAAAAYAAACwAAAAAQAAAMgAAAACAAAA1AAAAAMAAADkAAAAAQAAAPwAAAB0AgAAHAEAAFwB" - + "AABmAQAAbgEAAIABAACIAQAArAEAAMwBAADgAQAA6wEAAPYBAAD5AQAABgIAAAsCAAAQAgAAFgIA" - + "AB0CAAACAAAAAwAAAAQAAAAFAAAABgAAAAkAAAAJAAAABQAAAAAAAAAAAAQACwAAAAAABAAMAAAA" - + "AAAAAAAAAAAAAAAAAQAAAAQAAAABAAAAAAAAABEAAAAEAAAAAAAAAAcAAADIAgAApAIAAAAAAAAB" - + "AAAAAAAAAFABAAAGAAAAEgBpAAAAaQABAA4AAQABAAEAAABVAQAABAAAAHAQAgAAAA4ABwAOPAAF" - + "AA4AAAAACDxjbGluaXQ+AAY8aW5pdD4AEExNYWluJFRyYW5zZm9ybTsABkxNYWluOwAiTGRhbHZp" - + "ay9hbm5vdGF0aW9uL0VuY2xvc2luZ0NsYXNzOwAeTGRhbHZpay9hbm5vdGF0aW9uL0lubmVyQ2xh" - + "c3M7ABJMamF2YS9sYW5nL09iamVjdDsACU1haW4uamF2YQAJVHJhbnNmb3JtAAFWAAthY2Nlc3NG" - + "bGFncwADYmFyAANmb28ABG5hbWUABXZhbHVlAHZ+fkQ4eyJjb21waWxhdGlvbi1tb2RlIjoiZGVi" - + "dWciLCJtaW4tYXBpIjoxLCJzaGEtMSI6IjI4YmNlZjUwYWM4NTk3Y2YyMmU4OTJiMWJjM2EzYjky" - + "Yjc0ZTcwZTkiLCJ2ZXJzaW9uIjoiMS42LjMyLWRldiJ9AAICAQ4YAQIDAgoEGQ0XCAIAAgAACQEJ" - + "AIiABJwCAYGABLgCAAAAAAIAAACVAgAAmwIAALwCAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAAA" - + "AAAAAQAAABAAAABwAAAAAgAAAAYAAACwAAAAAwAAAAEAAADIAAAABAAAAAIAAADUAAAABQAAAAMA" - + "AADkAAAABgAAAAEAAAD8AAAAASAAAAIAAAAcAQAAAyAAAAIAAABQAQAAAiAAABAAAABcAQAABCAA" - + "AAIAAACVAgAAACAAAAEAAACkAgAAAxAAAAIAAAC4AgAABiAAAAEAAADIAgAAABAAAAEAAADYAgAA"); - - public static void assertEquals(Object a, Object b) { - if (a != b) { - throw new Error("Expected " + b + ", got " + a); - } - } - - public static void main(String[] args) throws Exception, Throwable { - System.loadLibrary(args[0]); - Field f = Transform.class.getDeclaredField("foo"); - Transform.foo = "THIS IS A FOO VALUE"; - assertEquals(f.get(null), Transform.foo); - MethodHandle j = - NativeFieldScopeCheck( - f, - () -> { - Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES); - }); - assertEquals(j.invokeExact(), Transform.foo); - } - - // Hold the field as a ArtField, run the 'test' function, turn the ArtField into a MethodHandle - // directly and return that. - public static native MethodHandle NativeFieldScopeCheck(Field in, Runnable test); -} diff --git a/test/1985-structural-redefine-stack-scope/src/art/Redefinition.java b/test/1985-structural-redefine-stack-scope/src/art/Redefinition.java deleted file mode 120000 index 81eaf31bbb..0000000000 --- a/test/1985-structural-redefine-stack-scope/src/art/Redefinition.java +++ /dev/null @@ -1 +0,0 @@ -../../../jvmti-common/Redefinition.java
\ No newline at end of file diff --git a/test/1985-structural-redefine-stack-scope/stack_scope.cc b/test/1985-structural-redefine-stack-scope/stack_scope.cc deleted file mode 100644 index 5c5215bac0..0000000000 --- a/test/1985-structural-redefine-stack-scope/stack_scope.cc +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <cstdio> -#include <memory> -#include <mutex> -#include <string> -#include <vector> - -#include "class_linker.h" -#include "class_root.h" -#include "jni.h" -#include "jni/jni_internal.h" -#include "mirror/class.h" -#include "mirror/method_handle_impl.h" -#include "mirror/object-inl.h" -#include "mirror/object_array-alloc-inl.h" -#include "reflection.h" -#include "reflective_handle.h" -#include "reflective_handle_scope-inl.h" -#include "runtime.h" -#include "scoped_thread_state_change-inl.h" -#include "thread-inl.h" - -namespace art { -namespace Test1985StructuralRedefineStackScope { - -extern "C" JNICALL jobject JNIEXPORT Java_Main_NativeFieldScopeCheck(JNIEnv* env, - jclass, - jobject field, - jobject runnable) { - jfieldID fid = env->FromReflectedField(field); - jclass runnable_klass = env->FindClass("java/lang/Runnable"); - jmethodID run = env->GetMethodID(runnable_klass, "run", "()V"); - ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<4> hs(soa.Self()); - StackArtFieldHandleScope<1> fhs(soa.Self()); - StackArtFieldHandleScope<1> bhs(soa.Self()); - ReflectiveHandle<ArtField> rf(fhs.NewHandle(jni::DecodeArtField(fid))); - ReflectiveHandle<ArtField> bf(bhs.NewHandle(jni::DecodeArtField(fid))); - ArtField* pre_ptr = rf.Get(); - { - ScopedThreadSuspension sts(soa.Self(), ThreadState::kNative); - // Upcall to perform redefinition. - env->CallVoidMethod(runnable, run); - } - Handle<mirror::ObjectArray<mirror::Class>> mt_arr( - hs.NewHandle(mirror::ObjectArray<mirror::Class>::Alloc( - soa.Self(), - Runtime::Current()->GetClassLinker()->FindArrayClass(soa.Self(), - GetClassRoot<mirror::Class>()), - 0))); - Handle<mirror::MethodType> mt(hs.NewHandle(mirror::MethodType::Create( - soa.Self(), hs.NewHandle(GetClassRoot<mirror::Object>()), mt_arr))); - Handle<mirror::MethodHandleImpl> mhi(hs.NewHandle( - mirror::MethodHandleImpl::Create(soa.Self(), - reinterpret_cast<uintptr_t>(rf.Get()), - (rf->IsStatic() ? mirror::MethodHandle::Kind::kStaticGet - : mirror::MethodHandle::Kind::kInstanceGet), - mt))); - CHECK_EQ(rf.Get(), bf.Get()) << "rf: " << rf->PrettyField() << " bf: " << bf->PrettyField(); - // TODO Modify this to work for when run doesn't cause a change. - CHECK_NE(pre_ptr, rf.Get()) << "pre_ptr: " << pre_ptr->PrettyField() - << " rf: " << rf->PrettyField(); - CHECK_EQ(fid, jni::EncodeArtField(rf)); - return soa.AddLocalReference<jobject>(mhi.Get()); -} - -} // namespace Test1985StructuralRedefineStackScope -} // namespace art diff --git a/test/1986-structural-redefine-multi-thread-stack-scope/expected.txt b/test/1986-structural-redefine-multi-thread-stack-scope/expected.txt deleted file mode 100644 index 6a5618ebc6..0000000000 --- a/test/1986-structural-redefine-multi-thread-stack-scope/expected.txt +++ /dev/null @@ -1 +0,0 @@ -JNI_OnLoad called diff --git a/test/1986-structural-redefine-multi-thread-stack-scope/info.txt b/test/1986-structural-redefine-multi-thread-stack-scope/info.txt deleted file mode 100644 index 184bd7202e..0000000000 --- a/test/1986-structural-redefine-multi-thread-stack-scope/info.txt +++ /dev/null @@ -1 +0,0 @@ -Tests StackReflectiveHandleScope works when there are several all in different threads. diff --git a/test/1986-structural-redefine-multi-thread-stack-scope/run b/test/1986-structural-redefine-multi-thread-stack-scope/run deleted file mode 100755 index a36de16ea6..0000000000 --- a/test/1986-structural-redefine-multi-thread-stack-scope/run +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# -# Copyright 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Ask for stack traces to be dumped to a file rather than to stdout. -./default-run "$@" --jvmti --android-runtime-option -Xopaque-jni-ids:true diff --git a/test/1986-structural-redefine-multi-thread-stack-scope/src/Main.java b/test/1986-structural-redefine-multi-thread-stack-scope/src/Main.java deleted file mode 100644 index 23b1656b65..0000000000 --- a/test/1986-structural-redefine-multi-thread-stack-scope/src/Main.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import art.Redefinition; -import java.lang.invoke.*; -import java.lang.reflect.Field; -import java.util.Base64; -import java.util.concurrent.CountDownLatch; - -public class Main { - public static final class Transform { - static { - } - - public static Object foo = null; - } - - /** - * Base64 encoded dex bytes for: - * - * public static final class Transform { - * static {} - * public static Object bar = null; - * public static Object foo = null; - * } - */ - public static final byte[] DEX_BYTES = - Base64.getDecoder() - .decode( - "ZGV4CjAzNQCjkRjcSr1RJO8FnnCjHV/8h6keJP/+P3WQAwAAcAAAAHhWNBIAAAAAAAAAANgCAAAQ" - + "AAAAcAAAAAYAAACwAAAAAQAAAMgAAAACAAAA1AAAAAMAAADkAAAAAQAAAPwAAAB0AgAAHAEAAFwB" - + "AABmAQAAbgEAAIABAACIAQAArAEAAMwBAADgAQAA6wEAAPYBAAD5AQAABgIAAAsCAAAQAgAAFgIA" - + "AB0CAAACAAAAAwAAAAQAAAAFAAAABgAAAAkAAAAJAAAABQAAAAAAAAAAAAQACwAAAAAABAAMAAAA" - + "AAAAAAAAAAAAAAAAAQAAAAQAAAABAAAAAAAAABEAAAAEAAAAAAAAAAcAAADIAgAApAIAAAAAAAAB" - + "AAAAAAAAAFABAAAGAAAAEgBpAAAAaQABAA4AAQABAAEAAABVAQAABAAAAHAQAgAAAA4ABwAOPAAF" - + "AA4AAAAACDxjbGluaXQ+AAY8aW5pdD4AEExNYWluJFRyYW5zZm9ybTsABkxNYWluOwAiTGRhbHZp" - + "ay9hbm5vdGF0aW9uL0VuY2xvc2luZ0NsYXNzOwAeTGRhbHZpay9hbm5vdGF0aW9uL0lubmVyQ2xh" - + "c3M7ABJMamF2YS9sYW5nL09iamVjdDsACU1haW4uamF2YQAJVHJhbnNmb3JtAAFWAAthY2Nlc3NG" - + "bGFncwADYmFyAANmb28ABG5hbWUABXZhbHVlAHZ+fkQ4eyJjb21waWxhdGlvbi1tb2RlIjoiZGVi" - + "dWciLCJtaW4tYXBpIjoxLCJzaGEtMSI6IjI4YmNlZjUwYWM4NTk3Y2YyMmU4OTJiMWJjM2EzYjky" - + "Yjc0ZTcwZTkiLCJ2ZXJzaW9uIjoiMS42LjMyLWRldiJ9AAICAQ4YAQIDAgoEGQ0XCAIAAgAACQEJ" - + "AIiABJwCAYGABLgCAAAAAAIAAACVAgAAmwIAALwCAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAAA" - + "AAAAAQAAABAAAABwAAAAAgAAAAYAAACwAAAAAwAAAAEAAADIAAAABAAAAAIAAADUAAAABQAAAAMA" - + "AADkAAAABgAAAAEAAAD8AAAAASAAAAIAAAAcAQAAAyAAAAIAAABQAQAAAiAAABAAAABcAQAABCAA" - + "AAIAAACVAgAAACAAAAEAAACkAgAAAxAAAAIAAAC4AgAABiAAAAEAAADIAgAAABAAAAEAAADYAgAA"); - - public static void assertEquals(Object a, Object b) { - if (a != b) { - throw new Error("Expected " + b + ", got " + a); - } - } - - public static void assertAllEquals(Object[] a, Object b) { - boolean failed = false; - String msg = ""; - for (int i = 0; i < a.length; i++) { - if (a[i] != b) { - failed = true; - msg += "Expected " + b + ", got a[" + i + "] (" + a[i] + "), "; - } - } - if (failed) { - throw new Error(msg); - } - } - - public static void main(String[] args) throws Exception, Throwable { - System.loadLibrary(args[0]); - Field f = Transform.class.getDeclaredField("foo"); - Transform.foo = "THIS IS A FOO VALUE"; - assertEquals(f.get(null), Transform.foo); - final int num_threads = 10; - Object[] results = new Object[num_threads]; - Thread[] threads = new Thread[num_threads]; - CountDownLatch start_latch = new CountDownLatch(num_threads); - CountDownLatch continue_latch = new CountDownLatch(1); - for (int i = 0; i < num_threads; i++) { - final int id = i; - threads[id] = - new Thread( - () -> { - try { - MethodHandle mh = - NativeFieldScopeCheck( - f, - () -> { - try { - start_latch.countDown(); - continue_latch.await(); - } catch (Exception e) { - throw new Error("failed!", e); - } - }); - results[id] = mh.invokeExact(); - } catch (Throwable t) { - throw new Error("Failed", t); - } - }, - "Target thread " + id); - threads[id].start(); - } - start_latch.await(); - Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES); - continue_latch.countDown(); - for (Thread t : threads) { - t.join(); - } - assertAllEquals(results, Transform.foo); - } - - // Hold the field as a ArtField, run the 'test' function, turn the ArtField into a MethodHandle - // directly and return that. - public static native MethodHandle NativeFieldScopeCheck(Field in, Runnable test); -} diff --git a/test/1986-structural-redefine-multi-thread-stack-scope/src/art/Redefinition.java b/test/1986-structural-redefine-multi-thread-stack-scope/src/art/Redefinition.java deleted file mode 120000 index 81eaf31bbb..0000000000 --- a/test/1986-structural-redefine-multi-thread-stack-scope/src/art/Redefinition.java +++ /dev/null @@ -1 +0,0 @@ -../../../jvmti-common/Redefinition.java
\ No newline at end of file diff --git a/test/1987-structural-redefine-recurisive-stack-scope/expected.txt b/test/1987-structural-redefine-recurisive-stack-scope/expected.txt deleted file mode 100644 index 288bed82b3..0000000000 --- a/test/1987-structural-redefine-recurisive-stack-scope/expected.txt +++ /dev/null @@ -1,12 +0,0 @@ -JNI_OnLoad called -Foo value is THIS IS A FOO VALUE -Result at depth 0: THIS IS A FOO VALUE -Result at depth 1: THIS IS A FOO VALUE -Result at depth 2: THIS IS A FOO VALUE -Result at depth 3: THIS IS A FOO VALUE -Result at depth 4: THIS IS A FOO VALUE -Result at depth 5: THIS IS A FOO VALUE -Result at depth 6: THIS IS A FOO VALUE -Result at depth 7: THIS IS A FOO VALUE -Result at depth 8: THIS IS A FOO VALUE -Result at depth 9: THIS IS A FOO VALUE diff --git a/test/1987-structural-redefine-recurisive-stack-scope/info.txt b/test/1987-structural-redefine-recurisive-stack-scope/info.txt deleted file mode 100644 index f841897268..0000000000 --- a/test/1987-structural-redefine-recurisive-stack-scope/info.txt +++ /dev/null @@ -1 +0,0 @@ -Tests StackReflectiveHandleScope works when there are several all in different recursive frames. diff --git a/test/1987-structural-redefine-recurisive-stack-scope/run b/test/1987-structural-redefine-recurisive-stack-scope/run deleted file mode 100755 index a36de16ea6..0000000000 --- a/test/1987-structural-redefine-recurisive-stack-scope/run +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -# -# Copyright 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Ask for stack traces to be dumped to a file rather than to stdout. -./default-run "$@" --jvmti --android-runtime-option -Xopaque-jni-ids:true diff --git a/test/1987-structural-redefine-recurisive-stack-scope/src/Main.java b/test/1987-structural-redefine-recurisive-stack-scope/src/Main.java deleted file mode 100644 index 2c53057916..0000000000 --- a/test/1987-structural-redefine-recurisive-stack-scope/src/Main.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import art.Redefinition; -import java.lang.invoke.*; -import java.lang.reflect.Field; -import java.util.Base64; - -public class Main { - public static final class Transform { - static { - } - - public static Object foo = null; - } - - /* Base64 encoded dex bytes for: - * - * public static final class Transform { - * static {} - * public static Object bar = null; - * public static Object foo = null; - * } - */ - public static final byte[] DEX_BYTES = - Base64.getDecoder() - .decode( - "ZGV4CjAzNQCjkRjcSr1RJO8FnnCjHV/8h6keJP/+P3WQAwAAcAAAAHhWNBIAAAAAAAAAANgCAAAQ" - + "AAAAcAAAAAYAAACwAAAAAQAAAMgAAAACAAAA1AAAAAMAAADkAAAAAQAAAPwAAAB0AgAAHAEAAFwB" - + "AABmAQAAbgEAAIABAACIAQAArAEAAMwBAADgAQAA6wEAAPYBAAD5AQAABgIAAAsCAAAQAgAAFgIA" - + "AB0CAAACAAAAAwAAAAQAAAAFAAAABgAAAAkAAAAJAAAABQAAAAAAAAAAAAQACwAAAAAABAAMAAAA" - + "AAAAAAAAAAAAAAAAAQAAAAQAAAABAAAAAAAAABEAAAAEAAAAAAAAAAcAAADIAgAApAIAAAAAAAAB" - + "AAAAAAAAAFABAAAGAAAAEgBpAAAAaQABAA4AAQABAAEAAABVAQAABAAAAHAQAgAAAA4ABwAOPAAF" - + "AA4AAAAACDxjbGluaXQ+AAY8aW5pdD4AEExNYWluJFRyYW5zZm9ybTsABkxNYWluOwAiTGRhbHZp" - + "ay9hbm5vdGF0aW9uL0VuY2xvc2luZ0NsYXNzOwAeTGRhbHZpay9hbm5vdGF0aW9uL0lubmVyQ2xh" - + "c3M7ABJMamF2YS9sYW5nL09iamVjdDsACU1haW4uamF2YQAJVHJhbnNmb3JtAAFWAAthY2Nlc3NG" - + "bGFncwADYmFyAANmb28ABG5hbWUABXZhbHVlAHZ+fkQ4eyJjb21waWxhdGlvbi1tb2RlIjoiZGVi" - + "dWciLCJtaW4tYXBpIjoxLCJzaGEtMSI6IjI4YmNlZjUwYWM4NTk3Y2YyMmU4OTJiMWJjM2EzYjky" - + "Yjc0ZTcwZTkiLCJ2ZXJzaW9uIjoiMS42LjMyLWRldiJ9AAICAQ4YAQIDAgoEGQ0XCAIAAgAACQEJ" - + "AIiABJwCAYGABLgCAAAAAAIAAACVAgAAmwIAALwCAAAAAAAAAAAAAAAAAAAPAAAAAAAAAAEAAAAA" - + "AAAAAQAAABAAAABwAAAAAgAAAAYAAACwAAAAAwAAAAEAAADIAAAABAAAAAIAAADUAAAABQAAAAMA" - + "AADkAAAABgAAAAEAAAD8AAAAASAAAAIAAAAcAQAAAyAAAAIAAABQAQAAAiAAABAAAABcAQAABCAA" - + "AAIAAACVAgAAACAAAAEAAACkAgAAAxAAAAIAAAC4AgAABiAAAAEAAADIAgAAABAAAAEAAADYAgAA"); - - public static void main(String[] args) throws Exception, Throwable { - System.loadLibrary(args[0]); - Field f = Transform.class.getDeclaredField("foo"); - Transform.foo = "THIS IS A FOO VALUE"; - System.out.println("Foo value is " + f.get(null)); - final int max_depth = 10; - Object[] results = new Object[max_depth]; - Runnable res = - () -> { - Redefinition.doCommonStructuralClassRedefinition(Transform.class, DEX_BYTES); - }; - for (int i = 0; i < max_depth; i++) { - final Runnable next = res; - final int id = i; - res = - () -> { - try { - results[id] = NativeFieldScopeCheck(f, next).invokeExact(); - } catch (Throwable t) { - throw new Error("Failed!", t); - } - }; - } - res.run(); - for (int i = 0; i < max_depth; i++) { - System.out.println("Result at depth " + i + ": " + results[i]); - } - } - - // Hold the field as a ArtField, run the 'test' function, turn the ArtField into a MethodHandle - // directly and return that. - public static native MethodHandle NativeFieldScopeCheck(Field in, Runnable test); -} diff --git a/test/1987-structural-redefine-recurisive-stack-scope/src/art/Redefinition.java b/test/1987-structural-redefine-recurisive-stack-scope/src/art/Redefinition.java deleted file mode 120000 index 81eaf31bbb..0000000000 --- a/test/1987-structural-redefine-recurisive-stack-scope/src/art/Redefinition.java +++ /dev/null @@ -1 +0,0 @@ -../../../jvmti-common/Redefinition.java
\ No newline at end of file diff --git a/test/Android.bp b/test/Android.bp index ac83a5dc15..66a08e92d0 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -518,7 +518,6 @@ cc_defaults { "1002-notify-startup/startup_interface.cc", "1947-breakpoint-redefine-deopt/check_deopt.cc", "1972-jni-id-swap-indices/jni_id.cc", - "1985-structural-redefine-stack-scope/stack_scope.cc", "common/runtime_state.cc", "common/stack_inspect.cc", ], |