diff options
author | 2019-06-27 07:54:48 +0000 | |
---|---|---|
committer | 2019-06-27 08:16:04 +0000 | |
commit | b476a29a2cda22b86fc1d96e4cc65ce36fb878af (patch) | |
tree | 039eaee2edf5495275088d1c467e522977c6bcd6 | |
parent | 3b2905366c6ee1eaba2d6477078e505e377343ec (diff) |
Revert "Support using opaque JNI ids"
This reverts commit 21d5994583c679cd5d8573b5d35dbd659bdca2c7.
Bug: 134162467
Reason for revert: Breaks debuggable
Change-Id: I9510a6ac208d392ff25ee196a1a519fecd151445
-rw-r--r-- | openjdkjvmti/ti_heap.cc | 6 | ||||
-rw-r--r-- | openjdkjvmti/ti_method.cc | 3 | ||||
-rw-r--r-- | runtime/Android.bp | 2 | ||||
-rw-r--r-- | runtime/base/locks.cc | 6 | ||||
-rw-r--r-- | runtime/base/locks.h | 7 | ||||
-rw-r--r-- | runtime/class_linker_test.cc | 3 | ||||
-rw-r--r-- | runtime/jni/jni_env_ext.h | 2 | ||||
-rw-r--r-- | runtime/jni/jni_id_manager.cc | 418 | ||||
-rw-r--r-- | runtime/jni/jni_id_manager.h | 89 | ||||
-rw-r--r-- | runtime/jni/jni_internal.cc | 524 | ||||
-rw-r--r-- | runtime/jni/jni_internal.h | 51 | ||||
-rw-r--r-- | runtime/jni_id_type.h | 38 | ||||
-rw-r--r-- | runtime/mirror/class.cc | 126 | ||||
-rw-r--r-- | runtime/mirror/class.h | 17 | ||||
-rw-r--r-- | runtime/mirror/class_ext-inl.h | 69 | ||||
-rw-r--r-- | runtime/mirror/class_ext.h | 46 | ||||
-rw-r--r-- | runtime/parsed_options.cc | 5 | ||||
-rw-r--r-- | runtime/runtime.cc | 11 | ||||
-rw-r--r-- | runtime/runtime.h | 16 | ||||
-rw-r--r-- | runtime/runtime_options.def | 1 | ||||
-rw-r--r-- | runtime/thread.cc | 10 | ||||
-rw-r--r-- | runtime/thread.h | 3 | ||||
-rwxr-xr-x | test/testrunner/testrunner.py | 4 |
23 files changed, 270 insertions, 1187 deletions
diff --git a/openjdkjvmti/ti_heap.cc b/openjdkjvmti/ti_heap.cc index 898363a269..3d99ed8fe6 100644 --- a/openjdkjvmti/ti_heap.cc +++ b/openjdkjvmti/ti_heap.cc @@ -21,15 +21,12 @@ #include "base/macros.h" #include "base/mutex.h" #include "class_linker.h" -#include "class_root.h" #include "dex/primitive.h" #include "gc/heap-visit-objects-inl.h" #include "gc/heap.h" #include "gc_root-inl.h" -#include "handle_scope.h" #include "java_frame_root_info.h" #include "jni/jni_env_ext.h" -#include "jni/jni_id_manager.h" #include "jni/jni_internal.h" #include "jvmti_weak_table-inl.h" #include "mirror/class.h" @@ -39,11 +36,9 @@ #include "object_tagging.h" #include "runtime.h" #include "scoped_thread_state_change-inl.h" -#include "scoped_thread_state_change.h" #include "stack.h" #include "thread-inl.h" #include "thread_list.h" -#include "well_known_classes.h" namespace openjdkjvmti { @@ -1383,7 +1378,6 @@ jvmtiError HeapUtil::FollowReferences(jvmtiEnv* env, } { art::ScopedObjectAccess soa(self); // Now we know we have the shared lock. - art::jni::ScopedEnableSuspendAllJniIdQueries sjni; // make sure we can get JNI ids. art::ScopedThreadSuspension sts(self, art::kWaitingForVisitObjects); art::ScopedSuspendAll ssa("FollowReferences"); diff --git a/openjdkjvmti/ti_method.cc b/openjdkjvmti/ti_method.cc index defcd54082..d8ee981063 100644 --- a/openjdkjvmti/ti_method.cc +++ b/openjdkjvmti/ti_method.cc @@ -93,13 +93,12 @@ struct TiMethodCallback : public art::MethodCallback { ScopedLocalRef<jthread> thread_jni( jnienv, PhaseUtil::IsLivePhase() ? jnienv->AddLocalReference<jthread>(thread->GetPeer()) : nullptr); - jmethodID method_id = art::jni::EncodeArtMethod(method); art::ScopedThreadSuspension sts(thread, art::ThreadState::kNative); event_handler->DispatchEvent<ArtJvmtiEvent::kNativeMethodBind>( thread, static_cast<JNIEnv*>(jnienv), thread_jni.get(), - method_id, + art::jni::EncodeArtMethod(method), const_cast<void*>(cur_method), new_method); } diff --git a/runtime/Android.bp b/runtime/Android.bp index db4ef0277b..6b691fd0fd 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -121,7 +121,6 @@ libart_cc_defaults { "jni/check_jni.cc", "jni/java_vm_ext.cc", "jni/jni_env_ext.cc", - "jni/jni_id_manager.cc", "jni/jni_internal.cc", "linear_alloc.cc", "managed_stack.cc", @@ -480,7 +479,6 @@ gensrcs { "jdwp_provider.h", "jdwp/jdwp.h", "jdwp/jdwp_constants.h", - "jni_id_type.h", "lock_word.h", "oat.h", "object_callbacks.h", diff --git a/runtime/base/locks.cc b/runtime/base/locks.cc index 7404d0d4fc..1cec44c27e 100644 --- a/runtime/base/locks.cc +++ b/runtime/base/locks.cc @@ -76,7 +76,6 @@ ReaderWriterMutex* Locks::jni_globals_lock_ = nullptr; Mutex* Locks::jni_weak_globals_lock_ = nullptr; ReaderWriterMutex* Locks::dex_lock_ = nullptr; Mutex* Locks::native_debug_interface_lock_ = nullptr; -ReaderWriterMutex* Locks::jni_id_lock_ = nullptr; std::vector<BaseMutex*> Locks::expected_mutexes_on_weak_ref_access_; Atomic<const BaseMutex*> Locks::expected_mutexes_on_weak_ref_access_guard_; @@ -158,7 +157,6 @@ void Locks::Init() { DCHECK(user_code_suspension_lock_ != nullptr); DCHECK(dex_lock_ != nullptr); DCHECK(native_debug_interface_lock_ != nullptr); - DCHECK(jni_id_lock_ != nullptr); DCHECK(runtime_thread_pool_lock_ != nullptr); } else { // Create global locks in level order from highest lock level to lowest. @@ -319,10 +317,6 @@ void Locks::Init() { DCHECK(native_debug_interface_lock_ == nullptr); native_debug_interface_lock_ = new Mutex("Native debug interface lock", current_lock_level); - UPDATE_CURRENT_LOCK_LEVEL(kJniIdLock); - DCHECK(jni_id_lock_ == nullptr); - jni_id_lock_ = new ReaderWriterMutex("JNI id map lock", current_lock_level); - UPDATE_CURRENT_LOCK_LEVEL(kAbortLock); DCHECK(abort_lock_ == nullptr); abort_lock_ = new Mutex("abort lock", current_lock_level, true); diff --git a/runtime/base/locks.h b/runtime/base/locks.h index 4b85df0ea6..77e304debd 100644 --- a/runtime/base/locks.h +++ b/runtime/base/locks.h @@ -45,7 +45,6 @@ enum LockLevel : uint8_t { kUnexpectedSignalLock, kThreadSuspendCountLock, kAbortLock, - kJniIdLock, kNativeDebugInterfaceLock, kSignalHandlingLock, // A generic lock level for mutexs that should not allow any additional mutexes to be gained after @@ -354,12 +353,8 @@ class Locks { // Guards the magic global variables used by native tools (e.g. libunwind). static Mutex* native_debug_interface_lock_ ACQUIRED_AFTER(unexpected_signal_lock_); - // Guards the data structures responsible for keeping track of the JNI - // jmethodID/jfieldID <-> ArtMethod/ArtField mapping when using index-ids. - static ReaderWriterMutex* jni_id_lock_ ACQUIRED_AFTER(native_debug_interface_lock_); - // Have an exclusive logging thread. - static Mutex* logging_lock_ ACQUIRED_AFTER(jni_id_lock_); + static Mutex* logging_lock_ ACQUIRED_AFTER(native_debug_interface_lock_); // List of mutexes that we expect a thread may hold when accessing weak refs. This is used to // avoid a deadlock in the empty checkpoint while weak ref access is disabled (b/34964016). If we diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc index 0ffbc4a56d..2a7cbaa991 100644 --- a/runtime/class_linker_test.cc +++ b/runtime/class_linker_test.cc @@ -610,8 +610,6 @@ struct ClassOffsets : public CheckOffsets<mirror::Class> { struct ClassExtOffsets : public CheckOffsets<mirror::ClassExt> { ClassExtOffsets() : CheckOffsets<mirror::ClassExt>(false, "Ldalvik/system/ClassExt;") { - addOffset(OFFSETOF_MEMBER(mirror::ClassExt, instance_jfield_ids_), "instanceJfieldIDs"); - addOffset(OFFSETOF_MEMBER(mirror::ClassExt, jmethod_ids_), "jmethodIDs"); addOffset(OFFSETOF_MEMBER(mirror::ClassExt, obsolete_dex_caches_), "obsoleteDexCaches"); addOffset(OFFSETOF_MEMBER(mirror::ClassExt, obsolete_methods_), "obsoleteMethods"); addOffset(OFFSETOF_MEMBER(mirror::ClassExt, original_dex_file_), "originalDexFile"); @@ -619,7 +617,6 @@ struct ClassExtOffsets : public CheckOffsets<mirror::ClassExt> { "preRedefineClassDefIndex"); addOffset(OFFSETOF_MEMBER(mirror::ClassExt, pre_redefine_dex_file_ptr_), "preRedefineDexFilePtr"); - addOffset(OFFSETOF_MEMBER(mirror::ClassExt, static_jfield_ids_), "staticJfieldIDs"); addOffset(OFFSETOF_MEMBER(mirror::ClassExt, verify_error_), "verifyError"); } }; diff --git a/runtime/jni/jni_env_ext.h b/runtime/jni/jni_env_ext.h index 924ff514e0..61de07424f 100644 --- a/runtime/jni/jni_env_ext.h +++ b/runtime/jni/jni_env_ext.h @@ -199,7 +199,7 @@ class JNIEnvExt : public JNIEnv { // If we are a JNI env for a daemon thread with a deleted runtime. bool runtime_deleted_; - template<bool kEnableIndexIds> friend class JNI; + friend class JNI; friend class ScopedJniEnvLocalRefState; friend class Thread; ART_FRIEND_TEST(JniInternalTest, JNIEnvExtOffsets); diff --git a/runtime/jni/jni_id_manager.cc b/runtime/jni/jni_id_manager.cc deleted file mode 100644 index 16f4d5f6d5..0000000000 --- a/runtime/jni/jni_id_manager.cc +++ /dev/null @@ -1,418 +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 "jni_id_manager.h" - -#include "android-base/macros.h" -#include "art_field-inl.h" -#include "art_method-inl.h" -#include "base/enums.h" -#include "base/globals.h" -#include "base/locks.h" -#include "base/mutex.h" -#include "gc/allocation_listener.h" -#include "gc/heap.h" -#include "jni/jni_internal.h" -#include "mirror/array-inl.h" -#include "mirror/class-inl.h" -#include "mirror/class.h" -#include "mirror/class_ext.h" -#include "mirror/object-inl.h" -#include "obj_ptr-inl.h" -#include "thread-inl.h" -#include "thread.h" -#include <algorithm> -#include <cstdint> -#include <type_traits> - -namespace art { -namespace jni { - -constexpr bool kTraceIds = false; - -// TODO This whole thing could be done lock & wait free (since we never remove anything from the -// ids list). It's not clear this would be worthwile though. - -namespace { - -static constexpr size_t IdToIndex(uintptr_t id) { - return id >> 1; -} - -static constexpr uintptr_t IndexToId(size_t index) { - return (index << 1) + 1; -} - -template <typename ArtType> -ObjPtr<mirror::PointerArray> GetOrCreateIds(Thread* self, - ObjPtr<mirror::Class> k, - ArtType* t, - /*out*/bool* allocation_failure) - REQUIRES_SHARED(Locks::mutator_lock_); - -template <> -ObjPtr<mirror::PointerArray> GetOrCreateIds(Thread* self, - ObjPtr<mirror::Class> k, - ArtField* field, - /*out*/bool* allocation_failure) { - ScopedExceptionStorage ses(self); - ObjPtr<mirror::PointerArray> res; - if (Locks::mutator_lock_->IsExclusiveHeld(self)) { - res = field->IsStatic() ? k->GetStaticFieldIds() : k->GetInstanceFieldIds(); - } else { - res = field->IsStatic() ? k->GetOrCreateStaticFieldIds() : k->GetOrCreateInstanceFieldIds(); - } - if (self->IsExceptionPending()) { - self->AssertPendingOOMException(); - ses.SuppressOldException("Failed to allocate maps for jmethodIDs. "); - *allocation_failure = true; - } else { - *allocation_failure = false; - } - return res; -} - -template <> -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. - *allocation_failure = false; - return nullptr; - } - ObjPtr<mirror::PointerArray> res; - if (Locks::mutator_lock_->IsExclusiveHeld(self) || !Locks::mutator_lock_->IsSharedHeld(self)) { - res = k->GetMethodIds(); - } else { - res = k->GetOrCreateMethodIds(); - } - if (self->IsExceptionPending()) { - self->AssertPendingOOMException(); - *allocation_failure = true; - } else { - *allocation_failure = false; - } - return res; -} - -template <typename ArtType> -size_t GetIdOffset(ObjPtr<mirror::Class> k, ArtType* t, PointerSize pointer_size) - REQUIRES_SHARED(Locks::mutator_lock_); -template <> -size_t GetIdOffset(ObjPtr<mirror::Class> k, ArtField* f, PointerSize ptr_size ATTRIBUTE_UNUSED) { - return f->IsStatic() ? k->GetStaticFieldIdOffset(f) : k->GetInstanceFieldIdOffset(f); -} -template <> -size_t GetIdOffset(ObjPtr<mirror::Class> k, ArtMethod* method, PointerSize pointer_size) { - return method->IsObsolete() ? -1 : k->GetMethodIdOffset(method, pointer_size); -} - -// 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(ArtField* f) { - return f->PrettyField(); -} - -// Checks if the field or method is obsolete. -template <typename ArtType> bool IsObsolete(ArtType* t) REQUIRES_SHARED(Locks::mutator_lock_); -template <> bool IsObsolete(ArtField* t ATTRIBUTE_UNUSED) { - return false; -} -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(ArtType* t) REQUIRES_SHARED(Locks::mutator_lock_); -template <> ArtField* Canonicalize(ArtField* t) { - return t; -} -template <> ArtMethod* Canonicalize(ArtMethod* t) { - if (UNLIKELY(t->IsCopied())) { - t = t->GetCanonicalMethod(); - } - return t; -} - -}; // namespace - -// 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>() { - uintptr_t res = next_field_id_; - next_field_id_ += 2; - CHECK_GT(next_field_id_, res) << "jfieldID Overflow"; - return res; -} - -template <> uintptr_t JniIdManager::GetNextId<ArtMethod>() { - uintptr_t res = next_method_id_; - next_method_id_ += 2; - CHECK_GT(next_method_id_, res) << "jmethodID Overflow"; - return res; -} -template <> std::vector<ArtField*>& JniIdManager::GetGenericMap<ArtField>() { - return field_id_map_; -} - -template <> std::vector<ArtMethod*>& JniIdManager::GetGenericMap<ArtMethod>() { - return method_id_map_; -} -template <> size_t JniIdManager::GetLinearSearchStartId<ArtField>(ArtField* t ATTRIBUTE_UNUSED) { - return deferred_allocation_field_id_start_; -} - -template <> size_t JniIdManager::GetLinearSearchStartId<ArtMethod>(ArtMethod* m) { - if (m->IsObsolete()) { - return 1; - } else { - return deferred_allocation_method_id_start_; - } -} - -template <typename ArtType> uintptr_t JniIdManager::EncodeGenericId(ArtType* t) { - if (!Runtime::Current()->JniIdsAreIndices() || t == nullptr) { - 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, 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."); - return 0u; - } - uintptr_t cur_id = 0; - if (!ids.IsNull()) { - DCHECK_GT(ids->GetLength(), static_cast<int32_t>(off)) << " is " << PrettyGeneric(t); - cur_id = ids->GetElementPtrSize<uintptr_t>(off, kRuntimePointerSize); - } - if (cur_id != 0) { - return cur_id; - } - WriterMutexLock mu(self, *Locks::jni_id_lock_); - // Check the ids array for a racing id. - if (!ids.IsNull()) { - cur_id = ids->GetElementPtrSize<uintptr_t>(off, kRuntimePointerSize); - if (cur_id != 0) { - // We were racing some other thread and lost. - return cur_id; - } - } else { - // We cannot allocate anything here or don't have an ids array (we might be an obsolete method). - DCHECK(IsObsolete(t) || deferred_allocation_refcount_ > 0u) - << "deferred_allocation_refcount_: " << deferred_allocation_refcount_ - << " t: " << PrettyGeneric(t); - // Check to see if we raced and lost to another thread. - const std::vector<ArtType*>& vec = GetGenericMap<ArtType>(); - bool found = false; - // simple count-while. - size_t search_start_index = IdToIndex(GetLinearSearchStartId(t)); - size_t index = std::count_if(vec.cbegin() + search_start_index, - vec.cend(), - [&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) << "Expected: " << PrettyGeneric(vec[index]) << " got " - << PrettyGeneric(t) << " at index " << index - << " (id: " << IndexToId(index) << ")."; - return IndexToId(index); - } - } - cur_id = GetNextId<ArtType>(); - size_t cur_index = IdToIndex(cur_id); - 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; - if (ids.IsNull()) { - if (kIsDebugBuild && !IsObsolete(t)) { - CHECK_NE(deferred_allocation_refcount_, 0u) - << "Failed to allocate ids array despite not being forbidden from doing so!"; - Locks::mutator_lock_->AssertExclusiveHeld(self); - } - } else { - ids->SetElementPtrSize(off, reinterpret_cast<void*>(cur_id), kRuntimePointerSize); - } - return cur_id; -} - -jfieldID JniIdManager::EncodeFieldId(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) { - auto* res = reinterpret_cast<jmethodID>(EncodeGenericId(method)); - if (kTraceIds && method != nullptr) { - LOG(INFO) << "Returning " << res << " for method " << method->PrettyMethod(); - } - return res; -} - -template <typename ArtType> ArtType* JniIdManager::DecodeGenericId(uintptr_t t) { - if (Runtime::Current()->JniIdsAreIndices() && (t % 2) == 1) { - ReaderMutexLock mu(Thread::Current(), *Locks::jni_id_lock_); - size_t index = IdToIndex(t); - DCHECK_GT(GetGenericMap<ArtType>().size(), index); - return GetGenericMap<ArtType>().at(index); - } else { - DCHECK_EQ((t % 2), 0u) << "id: " << t; - return reinterpret_cast<ArtType*>(t); - } -} - -ArtMethod* JniIdManager::DecodeMethodId(jmethodID method) { - return DecodeGenericId<ArtMethod>(reinterpret_cast<uintptr_t>(method)); -} - -ArtField* JniIdManager::DecodeFieldId(jfieldID field) { - return DecodeGenericId<ArtField>(reinterpret_cast<uintptr_t>(field)); -} - -// This whole defer system is an annoying requirement to allow us to generate IDs during heap-walks -// such as those required for instrumentation tooling. -// -// The defer system works with the normal id-assignment routine to ensure that all the class-ext -// data structures are eventually created and filled in. Basically how it works is the id-assignment -// function will check to see if it has a strong mutator-lock. If it does not then it will try to -// allocate the class-ext data structures normally and fail if it is unable to do so. In the case -// where mutator-lock is being held exclusive no attempt to allocate will be made and the thread -// will CHECK that allocations are being deferred (or that the method is obsolete, in which case -// there is no class-ext to store the method->id map in). -// -// Once the thread is done holding the exclusive mutator-lock it will go back and fill-in the -// class-ext data of all the methods that were added. We do this without the exclusive mutator-lock -// on a copy of the maps before we decrement the deferred refcount. This ensures that any other -// threads running at the same time know they need to perform a linear scan of the id-map. Since we -// don't have the mutator-lock anymore other threads can allocate the class-ext data, meaning our -// copy is fine. The only way additional methods could end up on the id-maps after our copy without -// having class-ext data is if another thread picked up the exclusive mutator-lock and added another -// defer, in which case that thread would fix-up the remaining ids. In this way we maintain eventual -// consistency between the class-ext method/field->id maps and the JniIdManager id->method/field -// maps. -// -// TODO It is possible that another thread to gain the mutator-lock and allocate new ids without -// calling StartDefer. This is basically a race that we should try to catch but doing so is -// rather difficult and since this defer system is only used in very rare circumstances unlikely to -// be worth the trouble. -void JniIdManager::StartDefer() { - Thread* self = Thread::Current(); - WriterMutexLock mu(self, *Locks::jni_id_lock_); - if (deferred_allocation_refcount_++ == 0) { - deferred_allocation_field_id_start_ = next_field_id_; - deferred_allocation_method_id_start_ = next_method_id_; - } -} - -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_) { - if (t == nullptr) { - return; - } - 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; - } - if (kIsDebugBuild) { - uintptr_t old_id = ids->GetElementPtrSize<uintptr_t, kRuntimePointerSize>(off); - if (old_id != 0) { - DCHECK_EQ(old_id, id); - } - } - ids->SetElementPtrSize(off, reinterpret_cast<void*>(id), kRuntimePointerSize); - }; - // To ensure eventual consistency this depends on the fact that the method_id_map_ and - // field_id_map_ are the ultimate source of truth and no id is ever reused to be valid. It also - // relies on all threads always getting calling StartDefer if they are going to be allocating jni - // ids while suspended. If a thread tries to do so while it doesn't have a scope we could miss - // ids. - // TODO We should use roles or something to verify that this requirement is not broken. - // - // If another thread comes along and adds more methods to the list after - // copying either (1) the id-maps are already present for the method and everything is fine, (2) - // the thread is not suspended and so can create the ext-data and id lists or, (3) the thread also - // suspended everything and incremented the deferred_allocation_refcount_ so it will fix up new - // ids when it finishes. - Locks::mutator_lock_->AssertNotExclusiveHeld(self); - Locks::mutator_lock_->AssertSharedHeld(self); - 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_); - 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 < method_id_copy.size(); - ++index) { - set_id(method_id_copy[index], IndexToId(index)); - } - for (size_t index = kIsDebugBuild ? 0 : IdToIndex(field_start_id); index < field_id_copy.size(); - ++index) { - set_id(field_id_copy[index], IndexToId(index)); - } - WriterMutexLock mu(self, *Locks::jni_id_lock_); - DCHECK_GE(deferred_allocation_refcount_, 1u); - if (--deferred_allocation_refcount_ == 0) { - deferred_allocation_field_id_start_ = 0; - deferred_allocation_method_id_start_ = 0; - } -} - -ScopedEnableSuspendAllJniIdQueries::ScopedEnableSuspendAllJniIdQueries() - : manager_(Runtime::Current()->GetJniIdManager()) { - manager_->StartDefer(); -} - -ScopedEnableSuspendAllJniIdQueries::~ScopedEnableSuspendAllJniIdQueries() { - manager_->EndDefer(); -} - -}; // namespace jni -}; // namespace art diff --git a/runtime/jni/jni_id_manager.h b/runtime/jni/jni_id_manager.h deleted file mode 100644 index 5e5c581be4..0000000000 --- a/runtime/jni/jni_id_manager.h +++ /dev/null @@ -1,89 +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_JNI_JNI_ID_MANAGER_H_ -#define ART_RUNTIME_JNI_JNI_ID_MANAGER_H_ - -#include <atomic> -#include <jni.h> -#include <vector> - -#include "art_field.h" -#include "art_method.h" -#include "base/mutex.h" - -namespace art { -namespace jni { - -class ScopedEnableSuspendAllJniIdQueries; -class JniIdManager { - public: - ArtMethod* DecodeMethodId(jmethodID method) REQUIRES(!Locks::jni_id_lock_); - ArtField* DecodeFieldId(jfieldID field) REQUIRES(!Locks::jni_id_lock_); - jmethodID EncodeMethodId(ArtMethod* method) REQUIRES(!Locks::jni_id_lock_) - REQUIRES_SHARED(Locks::mutator_lock_); - jfieldID EncodeFieldId(ArtField* field) REQUIRES(!Locks::jni_id_lock_) - REQUIRES_SHARED(Locks::mutator_lock_); - - private: - template <typename ArtType> - 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> uintptr_t GetNextId() REQUIRES(Locks::jni_id_lock_); - template <typename ArtType> - 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_); - - uintptr_t next_method_id_ GUARDED_BY(Locks::jni_id_lock_) = 1u; - std::vector<ArtMethod*> method_id_map_ GUARDED_BY(Locks::jni_id_lock_); - uintptr_t next_field_id_ GUARDED_BY(Locks::jni_id_lock_) = 1u; - std::vector<ArtField*> field_id_map_ GUARDED_BY(Locks::jni_id_lock_); - - // If non-zero indicates that some thread is trying to allocate ids without being able to update - // the method->id mapping (due to not being able to allocate or something). In this case decode - // and encode need to do a linear scan of the lists. The ScopedEnableSuspendAllJniIdQueries struct - // will deal with fixing everything up. - size_t deferred_allocation_refcount_ GUARDED_BY(Locks::jni_id_lock_) = 0; - // min jmethodID that might not have it's method->id mapping filled in. - uintptr_t deferred_allocation_method_id_start_ GUARDED_BY(Locks::jni_id_lock_) = 0u; - // min jfieldID that might not have it's field->id mapping filled in. - uintptr_t deferred_allocation_field_id_start_ GUARDED_BY(Locks::jni_id_lock_) = 0u; - - friend class ScopedEnableSuspendAllJniIdQueries; -}; - -// A scope that will enable using the Encode/Decode JNI id functions with all threads suspended. -// This is required since normally we need to be able to allocate to encode new ids. This should -// only be used when absolutely required, for example to invoke user-callbacks during heap walking -// or similar. -class ScopedEnableSuspendAllJniIdQueries { - public: - ScopedEnableSuspendAllJniIdQueries() REQUIRES_SHARED(Locks::mutator_lock_); - ~ScopedEnableSuspendAllJniIdQueries() REQUIRES_SHARED(Locks::mutator_lock_); - - private: - JniIdManager* manager_; -}; - -} // namespace jni -} // namespace art - -#endif // ART_RUNTIME_JNI_JNI_ID_MANAGER_H_ diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc index cd775d630f..af335f65ff 100644 --- a/runtime/jni/jni_internal.cc +++ b/runtime/jni/jni_internal.cc @@ -428,7 +428,6 @@ static ObjPtr<mirror::Class> EnsureInitialized(Thread* self, ObjPtr<mirror::Clas return h_klass.Get(); } -template<bool kEnableIndexIds> static jmethodID FindMethodID(ScopedObjectAccess& soa, jclass jni_class, const char* name, const char* sig, bool is_static) REQUIRES_SHARED(Locks::mutator_lock_) { @@ -450,16 +449,14 @@ static jmethodID FindMethodID(ScopedObjectAccess& soa, jclass jni_class, ThrowNoSuchMethodError(soa, c, name, sig, is_static ? "static" : "non-static"); return nullptr; } - return jni::EncodeArtMethod<kEnableIndexIds>(method); + return jni::EncodeArtMethod(method); } -template<bool kEnableIndexIds> static ObjPtr<mirror::ClassLoader> GetClassLoader(const ScopedObjectAccess& soa) REQUIRES_SHARED(Locks::mutator_lock_) { ArtMethod* method = soa.Self()->GetCurrentMethod(nullptr); // If we are running Runtime.nativeLoad, use the overriding ClassLoader it set. - if (method == - jni::DecodeArtMethod<kEnableIndexIds>(WellKnownClasses::java_lang_Runtime_nativeLoad)) { + if (method == jni::DecodeArtMethod(WellKnownClasses::java_lang_Runtime_nativeLoad)) { return soa.Decode<mirror::ClassLoader>(soa.Self()->GetClassLoaderOverride()); } // If we have a method, use its ClassLoader for context. @@ -485,7 +482,6 @@ static ObjPtr<mirror::ClassLoader> GetClassLoader(const ScopedObjectAccess& soa) return nullptr; } -template<bool kEnableIndexIds> static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, const char* name, const char* sig, bool is_static) REQUIRES_SHARED(Locks::mutator_lock_) { @@ -538,7 +534,7 @@ static jfieldID FindFieldID(const ScopedObjectAccess& soa, jclass jni_class, con sig, name, c->GetDescriptor(&temp)); return nullptr; } - return jni::EncodeArtField<kEnableIndexIds>(field); + return jni::EncodeArtField(field); } static void ThrowAIOOBE(ScopedObjectAccess& soa, @@ -645,7 +641,6 @@ static ArtMethod* FindMethod(ObjPtr<mirror::Class> c, return nullptr; } -template <bool kEnableIndexIds> class JNI { public: static jint GetVersion(JNIEnv*) { @@ -666,7 +661,7 @@ class JNI { ObjPtr<mirror::Class> c = nullptr; if (runtime->IsStarted()) { StackHandleScope<1> hs(soa.Self()); - Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetClassLoader<kEnableIndexIds>(soa))); + Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetClassLoader(soa))); c = class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader); } else { c = class_linker->FindSystemClass(soa.Self(), descriptor.c_str()); @@ -677,7 +672,7 @@ class JNI { static jmethodID FromReflectedMethod(JNIEnv* env, jobject jlr_method) { CHECK_NON_NULL_ARGUMENT(jlr_method); ScopedObjectAccess soa(env); - return jni::EncodeArtMethod<kEnableIndexIds>(ArtMethod::FromReflectedMethod(soa, jlr_method)); + return jni::EncodeArtMethod(ArtMethod::FromReflectedMethod(soa, jlr_method)); } static jfieldID FromReflectedField(JNIEnv* env, jobject jlr_field) { @@ -689,7 +684,7 @@ class JNI { return nullptr; } ObjPtr<mirror::Field> field = ObjPtr<mirror::Field>::DownCast(obj_field); - return jni::EncodeArtField<kEnableIndexIds>(field->GetArtField()); + return jni::EncodeArtField(field->GetArtField()); } static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) { @@ -940,7 +935,7 @@ class JNI { } if (c->IsStringClass()) { // Replace calls to String.<init> with equivalent StringFactory call. - jmethodID sf_mid = jni::EncodeArtMethod<kEnableIndexIds>( + jmethodID sf_mid = jni::EncodeArtMethod( WellKnownClasses::StringInitToStringFactory(jni::DecodeArtMethod(mid))); return CallStaticObjectMethodV(env, WellKnownClasses::java_lang_StringFactory, sf_mid, args); } @@ -967,7 +962,7 @@ class JNI { } if (c->IsStringClass()) { // Replace calls to String.<init> with equivalent StringFactory call. - jmethodID sf_mid = jni::EncodeArtMethod<kEnableIndexIds>( + jmethodID sf_mid = jni::EncodeArtMethod( WellKnownClasses::StringInitToStringFactory(jni::DecodeArtMethod(mid))); return CallStaticObjectMethodA(env, WellKnownClasses::java_lang_StringFactory, sf_mid, args); } @@ -988,7 +983,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(name); CHECK_NON_NULL_ARGUMENT(sig); ScopedObjectAccess soa(env); - return FindMethodID<kEnableIndexIds>(soa, java_class, name, sig, false); + return FindMethodID(soa, java_class, name, sig, false); } static jmethodID GetStaticMethodID(JNIEnv* env, jclass java_class, const char* name, @@ -997,7 +992,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(name); CHECK_NON_NULL_ARGUMENT(sig); ScopedObjectAccess soa(env); - return FindMethodID<kEnableIndexIds>(soa, java_class, name, sig, true); + return FindMethodID(soa, java_class, name, sig, true); } static jobject CallObjectMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -1529,7 +1524,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(name); CHECK_NON_NULL_ARGUMENT(sig); ScopedObjectAccess soa(env); - return FindFieldID<kEnableIndexIds>(soa, java_class, name, sig, false); + return FindFieldID(soa, java_class, name, sig, false); } static jfieldID GetStaticFieldID(JNIEnv* env, jclass java_class, const char* name, @@ -1538,14 +1533,14 @@ class JNI { CHECK_NON_NULL_ARGUMENT(name); CHECK_NON_NULL_ARGUMENT(sig); ScopedObjectAccess soa(env); - return FindFieldID<kEnableIndexIds>(soa, java_class, name, sig, true); + return FindFieldID(soa, java_class, name, sig, true); } static jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fid) { CHECK_NON_NULL_ARGUMENT(obj); CHECK_NON_NULL_ARGUMENT(fid); ScopedObjectAccess soa(env); - ArtField* f = jni::DecodeArtField<kEnableIndexIds>(fid); + ArtField* f = jni::DecodeArtField(fid); NotifyGetField(f, obj); ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(obj); return soa.AddLocalReference<jobject>(f->GetObject(o)); @@ -1554,7 +1549,7 @@ class JNI { static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) { CHECK_NON_NULL_ARGUMENT(fid); ScopedObjectAccess soa(env); - ArtField* f = jni::DecodeArtField<kEnableIndexIds>(fid); + ArtField* f = jni::DecodeArtField(fid); NotifyGetField(f, nullptr); return soa.AddLocalReference<jobject>(f->GetObject(f->GetDeclaringClass())); } @@ -1563,7 +1558,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_object); CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); ScopedObjectAccess soa(env); - ArtField* f = jni::DecodeArtField<kEnableIndexIds>(fid); + ArtField* f = jni::DecodeArtField(fid); NotifySetObjectField(f, java_object, java_value); ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(java_object); ObjPtr<mirror::Object> v = soa.Decode<mirror::Object>(java_value); @@ -1573,7 +1568,7 @@ class JNI { static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) { CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); ScopedObjectAccess soa(env); - ArtField* f = jni::DecodeArtField<kEnableIndexIds>(fid); + ArtField* f = jni::DecodeArtField(fid); NotifySetObjectField(f, nullptr, java_value); ObjPtr<mirror::Object> v = soa.Decode<mirror::Object>(java_value); f->SetObject<false>(f->GetDeclaringClass(), v); @@ -1583,7 +1578,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(instance); \ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \ ScopedObjectAccess soa(env); \ - ArtField* f = jni::DecodeArtField<kEnableIndexIds>(fid); \ + ArtField* f = jni::DecodeArtField(fid); \ NotifyGetField(f, instance); \ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(instance); \ return f->Get ##fn (o) @@ -1591,7 +1586,7 @@ class JNI { #define GET_STATIC_PRIMITIVE_FIELD(fn) \ CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \ ScopedObjectAccess soa(env); \ - ArtField* f = jni::DecodeArtField<kEnableIndexIds>(fid); \ + ArtField* f = jni::DecodeArtField(fid); \ NotifyGetField(f, nullptr); \ return f->Get ##fn (f->GetDeclaringClass()) @@ -1599,7 +1594,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT_RETURN_VOID(instance); \ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \ ScopedObjectAccess soa(env); \ - ArtField* f = jni::DecodeArtField<kEnableIndexIds>(fid); \ + ArtField* f = jni::DecodeArtField(fid); \ NotifySetPrimitiveField(f, instance, JValue::FromPrimitive<decltype(value)>(value)); \ ObjPtr<mirror::Object> o = soa.Decode<mirror::Object>(instance); \ f->Set ##fn <false>(o, value) @@ -1607,7 +1602,7 @@ class JNI { #define SET_STATIC_PRIMITIVE_FIELD(fn, value) \ CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \ ScopedObjectAccess soa(env); \ - ArtField* f = jni::DecodeArtField<kEnableIndexIds>(fid); \ + ArtField* f = jni::DecodeArtField(fid); \ NotifySetPrimitiveField(f, nullptr, JValue::FromPrimitive<decltype(value)>(value)); \ f->Set ##fn <false>(f->GetDeclaringClass(), value) @@ -2886,253 +2881,244 @@ class JNI { } }; -template<bool kEnableIndexIds> -struct JniNativeInterfaceFunctions { - using JNIImpl = JNI<kEnableIndexIds>; - static constexpr JNINativeInterface gJniNativeInterface = { - nullptr, // reserved0. - nullptr, // reserved1. - nullptr, // reserved2. - nullptr, // reserved3. - JNIImpl::GetVersion, - JNIImpl::DefineClass, - JNIImpl::FindClass, - JNIImpl::FromReflectedMethod, - JNIImpl::FromReflectedField, - JNIImpl::ToReflectedMethod, - JNIImpl::GetSuperclass, - JNIImpl::IsAssignableFrom, - JNIImpl::ToReflectedField, - JNIImpl::Throw, - JNIImpl::ThrowNew, - JNIImpl::ExceptionOccurred, - JNIImpl::ExceptionDescribe, - JNIImpl::ExceptionClear, - JNIImpl::FatalError, - JNIImpl::PushLocalFrame, - JNIImpl::PopLocalFrame, - JNIImpl::NewGlobalRef, - JNIImpl::DeleteGlobalRef, - JNIImpl::DeleteLocalRef, - JNIImpl::IsSameObject, - JNIImpl::NewLocalRef, - JNIImpl::EnsureLocalCapacity, - JNIImpl::AllocObject, - JNIImpl::NewObject, - JNIImpl::NewObjectV, - JNIImpl::NewObjectA, - JNIImpl::GetObjectClass, - JNIImpl::IsInstanceOf, - JNIImpl::GetMethodID, - JNIImpl::CallObjectMethod, - JNIImpl::CallObjectMethodV, - JNIImpl::CallObjectMethodA, - JNIImpl::CallBooleanMethod, - JNIImpl::CallBooleanMethodV, - JNIImpl::CallBooleanMethodA, - JNIImpl::CallByteMethod, - JNIImpl::CallByteMethodV, - JNIImpl::CallByteMethodA, - JNIImpl::CallCharMethod, - JNIImpl::CallCharMethodV, - JNIImpl::CallCharMethodA, - JNIImpl::CallShortMethod, - JNIImpl::CallShortMethodV, - JNIImpl::CallShortMethodA, - JNIImpl::CallIntMethod, - JNIImpl::CallIntMethodV, - JNIImpl::CallIntMethodA, - JNIImpl::CallLongMethod, - JNIImpl::CallLongMethodV, - JNIImpl::CallLongMethodA, - JNIImpl::CallFloatMethod, - JNIImpl::CallFloatMethodV, - JNIImpl::CallFloatMethodA, - JNIImpl::CallDoubleMethod, - JNIImpl::CallDoubleMethodV, - JNIImpl::CallDoubleMethodA, - JNIImpl::CallVoidMethod, - JNIImpl::CallVoidMethodV, - JNIImpl::CallVoidMethodA, - JNIImpl::CallNonvirtualObjectMethod, - JNIImpl::CallNonvirtualObjectMethodV, - JNIImpl::CallNonvirtualObjectMethodA, - JNIImpl::CallNonvirtualBooleanMethod, - JNIImpl::CallNonvirtualBooleanMethodV, - JNIImpl::CallNonvirtualBooleanMethodA, - JNIImpl::CallNonvirtualByteMethod, - JNIImpl::CallNonvirtualByteMethodV, - JNIImpl::CallNonvirtualByteMethodA, - JNIImpl::CallNonvirtualCharMethod, - JNIImpl::CallNonvirtualCharMethodV, - JNIImpl::CallNonvirtualCharMethodA, - JNIImpl::CallNonvirtualShortMethod, - JNIImpl::CallNonvirtualShortMethodV, - JNIImpl::CallNonvirtualShortMethodA, - JNIImpl::CallNonvirtualIntMethod, - JNIImpl::CallNonvirtualIntMethodV, - JNIImpl::CallNonvirtualIntMethodA, - JNIImpl::CallNonvirtualLongMethod, - JNIImpl::CallNonvirtualLongMethodV, - JNIImpl::CallNonvirtualLongMethodA, - JNIImpl::CallNonvirtualFloatMethod, - JNIImpl::CallNonvirtualFloatMethodV, - JNIImpl::CallNonvirtualFloatMethodA, - JNIImpl::CallNonvirtualDoubleMethod, - JNIImpl::CallNonvirtualDoubleMethodV, - JNIImpl::CallNonvirtualDoubleMethodA, - JNIImpl::CallNonvirtualVoidMethod, - JNIImpl::CallNonvirtualVoidMethodV, - JNIImpl::CallNonvirtualVoidMethodA, - JNIImpl::GetFieldID, - JNIImpl::GetObjectField, - JNIImpl::GetBooleanField, - JNIImpl::GetByteField, - JNIImpl::GetCharField, - JNIImpl::GetShortField, - JNIImpl::GetIntField, - JNIImpl::GetLongField, - JNIImpl::GetFloatField, - JNIImpl::GetDoubleField, - JNIImpl::SetObjectField, - JNIImpl::SetBooleanField, - JNIImpl::SetByteField, - JNIImpl::SetCharField, - JNIImpl::SetShortField, - JNIImpl::SetIntField, - JNIImpl::SetLongField, - JNIImpl::SetFloatField, - JNIImpl::SetDoubleField, - JNIImpl::GetStaticMethodID, - JNIImpl::CallStaticObjectMethod, - JNIImpl::CallStaticObjectMethodV, - JNIImpl::CallStaticObjectMethodA, - JNIImpl::CallStaticBooleanMethod, - JNIImpl::CallStaticBooleanMethodV, - JNIImpl::CallStaticBooleanMethodA, - JNIImpl::CallStaticByteMethod, - JNIImpl::CallStaticByteMethodV, - JNIImpl::CallStaticByteMethodA, - JNIImpl::CallStaticCharMethod, - JNIImpl::CallStaticCharMethodV, - JNIImpl::CallStaticCharMethodA, - JNIImpl::CallStaticShortMethod, - JNIImpl::CallStaticShortMethodV, - JNIImpl::CallStaticShortMethodA, - JNIImpl::CallStaticIntMethod, - JNIImpl::CallStaticIntMethodV, - JNIImpl::CallStaticIntMethodA, - JNIImpl::CallStaticLongMethod, - JNIImpl::CallStaticLongMethodV, - JNIImpl::CallStaticLongMethodA, - JNIImpl::CallStaticFloatMethod, - JNIImpl::CallStaticFloatMethodV, - JNIImpl::CallStaticFloatMethodA, - JNIImpl::CallStaticDoubleMethod, - JNIImpl::CallStaticDoubleMethodV, - JNIImpl::CallStaticDoubleMethodA, - JNIImpl::CallStaticVoidMethod, - JNIImpl::CallStaticVoidMethodV, - JNIImpl::CallStaticVoidMethodA, - JNIImpl::GetStaticFieldID, - JNIImpl::GetStaticObjectField, - JNIImpl::GetStaticBooleanField, - JNIImpl::GetStaticByteField, - JNIImpl::GetStaticCharField, - JNIImpl::GetStaticShortField, - JNIImpl::GetStaticIntField, - JNIImpl::GetStaticLongField, - JNIImpl::GetStaticFloatField, - JNIImpl::GetStaticDoubleField, - JNIImpl::SetStaticObjectField, - JNIImpl::SetStaticBooleanField, - JNIImpl::SetStaticByteField, - JNIImpl::SetStaticCharField, - JNIImpl::SetStaticShortField, - JNIImpl::SetStaticIntField, - JNIImpl::SetStaticLongField, - JNIImpl::SetStaticFloatField, - JNIImpl::SetStaticDoubleField, - JNIImpl::NewString, - JNIImpl::GetStringLength, - JNIImpl::GetStringChars, - JNIImpl::ReleaseStringChars, - JNIImpl::NewStringUTF, - JNIImpl::GetStringUTFLength, - JNIImpl::GetStringUTFChars, - JNIImpl::ReleaseStringUTFChars, - JNIImpl::GetArrayLength, - JNIImpl::NewObjectArray, - JNIImpl::GetObjectArrayElement, - JNIImpl::SetObjectArrayElement, - JNIImpl::NewBooleanArray, - JNIImpl::NewByteArray, - JNIImpl::NewCharArray, - JNIImpl::NewShortArray, - JNIImpl::NewIntArray, - JNIImpl::NewLongArray, - JNIImpl::NewFloatArray, - JNIImpl::NewDoubleArray, - JNIImpl::GetBooleanArrayElements, - JNIImpl::GetByteArrayElements, - JNIImpl::GetCharArrayElements, - JNIImpl::GetShortArrayElements, - JNIImpl::GetIntArrayElements, - JNIImpl::GetLongArrayElements, - JNIImpl::GetFloatArrayElements, - JNIImpl::GetDoubleArrayElements, - JNIImpl::ReleaseBooleanArrayElements, - JNIImpl::ReleaseByteArrayElements, - JNIImpl::ReleaseCharArrayElements, - JNIImpl::ReleaseShortArrayElements, - JNIImpl::ReleaseIntArrayElements, - JNIImpl::ReleaseLongArrayElements, - JNIImpl::ReleaseFloatArrayElements, - JNIImpl::ReleaseDoubleArrayElements, - JNIImpl::GetBooleanArrayRegion, - JNIImpl::GetByteArrayRegion, - JNIImpl::GetCharArrayRegion, - JNIImpl::GetShortArrayRegion, - JNIImpl::GetIntArrayRegion, - JNIImpl::GetLongArrayRegion, - JNIImpl::GetFloatArrayRegion, - JNIImpl::GetDoubleArrayRegion, - JNIImpl::SetBooleanArrayRegion, - JNIImpl::SetByteArrayRegion, - JNIImpl::SetCharArrayRegion, - JNIImpl::SetShortArrayRegion, - JNIImpl::SetIntArrayRegion, - JNIImpl::SetLongArrayRegion, - JNIImpl::SetFloatArrayRegion, - JNIImpl::SetDoubleArrayRegion, - JNIImpl::RegisterNatives, - JNIImpl::UnregisterNatives, - JNIImpl::MonitorEnter, - JNIImpl::MonitorExit, - JNIImpl::GetJavaVM, - JNIImpl::GetStringRegion, - JNIImpl::GetStringUTFRegion, - JNIImpl::GetPrimitiveArrayCritical, - JNIImpl::ReleasePrimitiveArrayCritical, - JNIImpl::GetStringCritical, - JNIImpl::ReleaseStringCritical, - JNIImpl::NewWeakGlobalRef, - JNIImpl::DeleteWeakGlobalRef, - JNIImpl::ExceptionCheck, - JNIImpl::NewDirectByteBuffer, - JNIImpl::GetDirectBufferAddress, - JNIImpl::GetDirectBufferCapacity, - JNIImpl::GetObjectRefType, - }; +const JNINativeInterface gJniNativeInterface = { + nullptr, // reserved0. + nullptr, // reserved1. + nullptr, // reserved2. + nullptr, // reserved3. + JNI::GetVersion, + JNI::DefineClass, + JNI::FindClass, + JNI::FromReflectedMethod, + JNI::FromReflectedField, + JNI::ToReflectedMethod, + JNI::GetSuperclass, + JNI::IsAssignableFrom, + JNI::ToReflectedField, + JNI::Throw, + JNI::ThrowNew, + JNI::ExceptionOccurred, + JNI::ExceptionDescribe, + JNI::ExceptionClear, + JNI::FatalError, + JNI::PushLocalFrame, + JNI::PopLocalFrame, + JNI::NewGlobalRef, + JNI::DeleteGlobalRef, + JNI::DeleteLocalRef, + JNI::IsSameObject, + JNI::NewLocalRef, + JNI::EnsureLocalCapacity, + JNI::AllocObject, + JNI::NewObject, + JNI::NewObjectV, + JNI::NewObjectA, + JNI::GetObjectClass, + JNI::IsInstanceOf, + JNI::GetMethodID, + JNI::CallObjectMethod, + JNI::CallObjectMethodV, + JNI::CallObjectMethodA, + JNI::CallBooleanMethod, + JNI::CallBooleanMethodV, + JNI::CallBooleanMethodA, + JNI::CallByteMethod, + JNI::CallByteMethodV, + JNI::CallByteMethodA, + JNI::CallCharMethod, + JNI::CallCharMethodV, + JNI::CallCharMethodA, + JNI::CallShortMethod, + JNI::CallShortMethodV, + JNI::CallShortMethodA, + JNI::CallIntMethod, + JNI::CallIntMethodV, + JNI::CallIntMethodA, + JNI::CallLongMethod, + JNI::CallLongMethodV, + JNI::CallLongMethodA, + JNI::CallFloatMethod, + JNI::CallFloatMethodV, + JNI::CallFloatMethodA, + JNI::CallDoubleMethod, + JNI::CallDoubleMethodV, + JNI::CallDoubleMethodA, + JNI::CallVoidMethod, + JNI::CallVoidMethodV, + JNI::CallVoidMethodA, + JNI::CallNonvirtualObjectMethod, + JNI::CallNonvirtualObjectMethodV, + JNI::CallNonvirtualObjectMethodA, + JNI::CallNonvirtualBooleanMethod, + JNI::CallNonvirtualBooleanMethodV, + JNI::CallNonvirtualBooleanMethodA, + JNI::CallNonvirtualByteMethod, + JNI::CallNonvirtualByteMethodV, + JNI::CallNonvirtualByteMethodA, + JNI::CallNonvirtualCharMethod, + JNI::CallNonvirtualCharMethodV, + JNI::CallNonvirtualCharMethodA, + JNI::CallNonvirtualShortMethod, + JNI::CallNonvirtualShortMethodV, + JNI::CallNonvirtualShortMethodA, + JNI::CallNonvirtualIntMethod, + JNI::CallNonvirtualIntMethodV, + JNI::CallNonvirtualIntMethodA, + JNI::CallNonvirtualLongMethod, + JNI::CallNonvirtualLongMethodV, + JNI::CallNonvirtualLongMethodA, + JNI::CallNonvirtualFloatMethod, + JNI::CallNonvirtualFloatMethodV, + JNI::CallNonvirtualFloatMethodA, + JNI::CallNonvirtualDoubleMethod, + JNI::CallNonvirtualDoubleMethodV, + JNI::CallNonvirtualDoubleMethodA, + JNI::CallNonvirtualVoidMethod, + JNI::CallNonvirtualVoidMethodV, + JNI::CallNonvirtualVoidMethodA, + JNI::GetFieldID, + JNI::GetObjectField, + JNI::GetBooleanField, + JNI::GetByteField, + JNI::GetCharField, + JNI::GetShortField, + JNI::GetIntField, + JNI::GetLongField, + JNI::GetFloatField, + JNI::GetDoubleField, + JNI::SetObjectField, + JNI::SetBooleanField, + JNI::SetByteField, + JNI::SetCharField, + JNI::SetShortField, + JNI::SetIntField, + JNI::SetLongField, + JNI::SetFloatField, + JNI::SetDoubleField, + JNI::GetStaticMethodID, + JNI::CallStaticObjectMethod, + JNI::CallStaticObjectMethodV, + JNI::CallStaticObjectMethodA, + JNI::CallStaticBooleanMethod, + JNI::CallStaticBooleanMethodV, + JNI::CallStaticBooleanMethodA, + JNI::CallStaticByteMethod, + JNI::CallStaticByteMethodV, + JNI::CallStaticByteMethodA, + JNI::CallStaticCharMethod, + JNI::CallStaticCharMethodV, + JNI::CallStaticCharMethodA, + JNI::CallStaticShortMethod, + JNI::CallStaticShortMethodV, + JNI::CallStaticShortMethodA, + JNI::CallStaticIntMethod, + JNI::CallStaticIntMethodV, + JNI::CallStaticIntMethodA, + JNI::CallStaticLongMethod, + JNI::CallStaticLongMethodV, + JNI::CallStaticLongMethodA, + JNI::CallStaticFloatMethod, + JNI::CallStaticFloatMethodV, + JNI::CallStaticFloatMethodA, + JNI::CallStaticDoubleMethod, + JNI::CallStaticDoubleMethodV, + JNI::CallStaticDoubleMethodA, + JNI::CallStaticVoidMethod, + JNI::CallStaticVoidMethodV, + JNI::CallStaticVoidMethodA, + JNI::GetStaticFieldID, + JNI::GetStaticObjectField, + JNI::GetStaticBooleanField, + JNI::GetStaticByteField, + JNI::GetStaticCharField, + JNI::GetStaticShortField, + JNI::GetStaticIntField, + JNI::GetStaticLongField, + JNI::GetStaticFloatField, + JNI::GetStaticDoubleField, + JNI::SetStaticObjectField, + JNI::SetStaticBooleanField, + JNI::SetStaticByteField, + JNI::SetStaticCharField, + JNI::SetStaticShortField, + JNI::SetStaticIntField, + JNI::SetStaticLongField, + JNI::SetStaticFloatField, + JNI::SetStaticDoubleField, + JNI::NewString, + JNI::GetStringLength, + JNI::GetStringChars, + JNI::ReleaseStringChars, + JNI::NewStringUTF, + JNI::GetStringUTFLength, + JNI::GetStringUTFChars, + JNI::ReleaseStringUTFChars, + JNI::GetArrayLength, + JNI::NewObjectArray, + JNI::GetObjectArrayElement, + JNI::SetObjectArrayElement, + JNI::NewBooleanArray, + JNI::NewByteArray, + JNI::NewCharArray, + JNI::NewShortArray, + JNI::NewIntArray, + JNI::NewLongArray, + JNI::NewFloatArray, + JNI::NewDoubleArray, + JNI::GetBooleanArrayElements, + JNI::GetByteArrayElements, + JNI::GetCharArrayElements, + JNI::GetShortArrayElements, + JNI::GetIntArrayElements, + JNI::GetLongArrayElements, + JNI::GetFloatArrayElements, + JNI::GetDoubleArrayElements, + JNI::ReleaseBooleanArrayElements, + JNI::ReleaseByteArrayElements, + JNI::ReleaseCharArrayElements, + JNI::ReleaseShortArrayElements, + JNI::ReleaseIntArrayElements, + JNI::ReleaseLongArrayElements, + JNI::ReleaseFloatArrayElements, + JNI::ReleaseDoubleArrayElements, + JNI::GetBooleanArrayRegion, + JNI::GetByteArrayRegion, + JNI::GetCharArrayRegion, + JNI::GetShortArrayRegion, + JNI::GetIntArrayRegion, + JNI::GetLongArrayRegion, + JNI::GetFloatArrayRegion, + JNI::GetDoubleArrayRegion, + JNI::SetBooleanArrayRegion, + JNI::SetByteArrayRegion, + JNI::SetCharArrayRegion, + JNI::SetShortArrayRegion, + JNI::SetIntArrayRegion, + JNI::SetLongArrayRegion, + JNI::SetFloatArrayRegion, + JNI::SetDoubleArrayRegion, + JNI::RegisterNatives, + JNI::UnregisterNatives, + JNI::MonitorEnter, + JNI::MonitorExit, + JNI::GetJavaVM, + JNI::GetStringRegion, + JNI::GetStringUTFRegion, + JNI::GetPrimitiveArrayCritical, + JNI::ReleasePrimitiveArrayCritical, + JNI::GetStringCritical, + JNI::ReleaseStringCritical, + JNI::NewWeakGlobalRef, + JNI::DeleteWeakGlobalRef, + JNI::ExceptionCheck, + JNI::NewDirectByteBuffer, + JNI::GetDirectBufferAddress, + JNI::GetDirectBufferCapacity, + JNI::GetObjectRefType, }; const JNINativeInterface* GetJniNativeInterface() { - // The template argument is passed down through the Encode/DecodeArtMethod/Field calls so if - // JniIdsAreIndices is false the calls will be a simple cast with no branches. This ensures that - // the normal case is still fast. - return Runtime::Current()->JniIdsAreIndices() - ? &JniNativeInterfaceFunctions<true>::gJniNativeInterface - : &JniNativeInterfaceFunctions<false>::gJniNativeInterface; + return &gJniNativeInterface; } void (*gJniSleepForeverStub[])() = { diff --git a/runtime/jni/jni_internal.h b/runtime/jni/jni_internal.h index b6e106cc88..4359074dbd 100644 --- a/runtime/jni/jni_internal.h +++ b/runtime/jni/jni_internal.h @@ -20,9 +20,7 @@ #include <jni.h> #include <iosfwd> -#include "base/locks.h" #include "base/macros.h" -#include "runtime.h" namespace art { @@ -43,61 +41,24 @@ void JniShutdownNativeCallerCheck(); namespace jni { -// We want to maintain a branchless fast-path for performance reasons. The JniIdManager is the -// ultimate source of truth for how the IDs are handed out but we inline the normal non-index cases -// here. - -template <bool kEnableIndexIds> -ALWAYS_INLINE -static bool IsIndexId(jmethodID mid) { - return kEnableIndexIds && ((reinterpret_cast<uintptr_t>(mid) % 2) != 0); -} - -template <bool kEnableIndexIds> -ALWAYS_INLINE -static bool IsIndexId(jfieldID fid) { - return kEnableIndexIds && ((reinterpret_cast<uintptr_t>(fid) % 2) != 0); -} - -template <bool kEnableIndexIds = true> ALWAYS_INLINE static inline ArtField* DecodeArtField(jfieldID fid) { - if (IsIndexId<kEnableIndexIds>(fid)) { - return Runtime::Current()->GetJniIdManager()->DecodeFieldId(fid); - } else { - return reinterpret_cast<ArtField*>(fid); - } + return reinterpret_cast<ArtField*>(fid); } -template <bool kEnableIndexIds = true> ALWAYS_INLINE -static inline jfieldID EncodeArtField(ArtField* field) REQUIRES_SHARED(Locks::mutator_lock_) { - if (kEnableIndexIds && Runtime::Current()->JniIdsAreIndices()) { - return Runtime::Current()->GetJniIdManager()->EncodeFieldId(field); - } else { - return reinterpret_cast<jfieldID>(field); - } +static inline jfieldID EncodeArtField(ArtField* field) { + return reinterpret_cast<jfieldID>(field); } -template <bool kEnableIndexIds = true> ALWAYS_INLINE -static inline jmethodID EncodeArtMethod(ArtMethod* art_method) - REQUIRES_SHARED(Locks::mutator_lock_) { - if (kEnableIndexIds && Runtime::Current()->JniIdsAreIndices()) { - return Runtime::Current()->GetJniIdManager()->EncodeMethodId(art_method); - } else { - return reinterpret_cast<jmethodID>(art_method); - } +static inline jmethodID EncodeArtMethod(ArtMethod* art_method) { + return reinterpret_cast<jmethodID>(art_method); } -template <bool kEnableIndexIds = true> ALWAYS_INLINE static inline ArtMethod* DecodeArtMethod(jmethodID method_id) { - if (IsIndexId<kEnableIndexIds>(method_id)) { - return Runtime::Current()->GetJniIdManager()->DecodeMethodId(method_id); - } else { - return reinterpret_cast<ArtMethod*>(method_id); - } + return reinterpret_cast<ArtMethod*>(method_id); } } // namespace jni diff --git a/runtime/jni_id_type.h b/runtime/jni_id_type.h deleted file mode 100644 index 7802ec6c37..0000000000 --- a/runtime/jni_id_type.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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. - */ - -#ifndef ART_RUNTIME_JNI_ID_TYPE_H_ -#define ART_RUNTIME_JNI_ID_TYPE_H_ - -#include <iosfwd> - -namespace art { - -enum class JniIdType { - // All Jni method/field IDs are pointers to the corresponding Art{Field,Method} type - kPointer, - - // All Jni method/field IDs are indices into a table. - kIndices, - - // The current default provider. Used if you run -XjdwpProvider:default - kDefault = kPointer, -}; - -std::ostream& operator<<(std::ostream& os, const JniIdType& rhs); - -} // namespace art -#endif // ART_RUNTIME_JNI_ID_TYPE_H_ diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc index c0a950d614..a36fe1253c 100644 --- a/runtime/mirror/class.cc +++ b/runtime/mirror/class.cc @@ -16,17 +16,14 @@ #include "class.h" -#include "android-base/macros.h" #include "android-base/stringprintf.h" -#include "array-inl.h" #include "art_field-inl.h" #include "art_method-inl.h" -#include "base/enums.h" #include "base/logging.h" // For VLOG. #include "base/utils.h" #include "class-inl.h" -#include "class_ext-inl.h" +#include "class_ext.h" #include "class_linker-inl.h" #include "class_loader.h" #include "class_root.h" @@ -1550,126 +1547,5 @@ void Class::SetAccessFlagsDCheck(uint32_t new_access_flags) { (new_access_flags & kAccVerificationAttempted) != 0); } -ObjPtr<PointerArray> Class::GetMethodIds() { - ObjPtr<ClassExt> ext(GetExtData()); - if (ext.IsNull()) { - return nullptr; - } else { - return ext->GetJMethodIDs(); - } -} -ObjPtr<PointerArray> Class::GetOrCreateMethodIds() { - DCHECK(Runtime::Current()->JniIdsAreIndices()) << "JNI Ids are pointers!"; - Thread* self = Thread::Current(); - StackHandleScope<1> hs(self); - Handle<Class> h_this(hs.NewHandle(this)); - ObjPtr<ClassExt> ext(EnsureExtDataPresent(h_this, self)); - if (ext.IsNull()) { - self->AssertPendingOOMException(); - return nullptr; - } - return ext->EnsureJMethodIDsArrayPresent(NumMethods()); -} - -ObjPtr<PointerArray> Class::GetStaticFieldIds() { - ObjPtr<ClassExt> ext(GetExtData()); - if (ext.IsNull()) { - return nullptr; - } else { - return ext->GetStaticJFieldIDs(); - } -} -ObjPtr<PointerArray> Class::GetOrCreateStaticFieldIds() { - DCHECK(Runtime::Current()->JniIdsAreIndices()) << "JNI Ids are pointers!"; - Thread* self = Thread::Current(); - StackHandleScope<1> hs(self); - Handle<Class> h_this(hs.NewHandle(this)); - ObjPtr<ClassExt> ext(EnsureExtDataPresent(h_this, self)); - if (ext.IsNull()) { - self->AssertPendingOOMException(); - return nullptr; - } - return ext->EnsureStaticJFieldIDsArrayPresent(NumStaticFields()); -} -ObjPtr<PointerArray> Class::GetInstanceFieldIds() { - ObjPtr<ClassExt> ext(GetExtData()); - if (ext.IsNull()) { - return nullptr; - } else { - return ext->GetInstanceJFieldIDs(); - } -} -ObjPtr<PointerArray> Class::GetOrCreateInstanceFieldIds() { - DCHECK(Runtime::Current()->JniIdsAreIndices()) << "JNI Ids are pointers!"; - Thread* self = Thread::Current(); - StackHandleScope<1> hs(self); - Handle<Class> h_this(hs.NewHandle(this)); - ObjPtr<ClassExt> ext(EnsureExtDataPresent(h_this, self)); - if (ext.IsNull()) { - self->AssertPendingOOMException(); - return nullptr; - } - return ext->EnsureInstanceJFieldIDsArrayPresent(NumInstanceFields()); -} - -size_t Class::GetStaticFieldIdOffset(ArtField* field) { - DCHECK_LT(reinterpret_cast<uintptr_t>(field), - reinterpret_cast<uintptr_t>(&*GetSFieldsPtr()->end())) - << "field not part of the current class. " << field->PrettyField() << " class is " - << PrettyClass(); - DCHECK_GE(reinterpret_cast<uintptr_t>(field), - reinterpret_cast<uintptr_t>(&*GetSFieldsPtr()->begin())) - << "field not part of the current class. " << field->PrettyField() << " class is " - << PrettyClass(); - uintptr_t start = reinterpret_cast<uintptr_t>(&GetSFieldsPtr()->At(0)); - uintptr_t fld = reinterpret_cast<uintptr_t>(field); - size_t res = (fld - start) / sizeof(ArtField); - DCHECK_EQ(&GetSFieldsPtr()->At(res), field) - << "Incorrect field computation expected: " << field->PrettyField() - << " got: " << GetSFieldsPtr()->At(res).PrettyField(); - return res; -} - -size_t Class::GetInstanceFieldIdOffset(ArtField* field) { - DCHECK_LT(reinterpret_cast<uintptr_t>(field), - reinterpret_cast<uintptr_t>(&*GetIFieldsPtr()->end())) - << "field not part of the current class. " << field->PrettyField() << " class is " - << PrettyClass(); - DCHECK_GE(reinterpret_cast<uintptr_t>(field), - reinterpret_cast<uintptr_t>(&*GetIFieldsPtr()->begin())) - << "field not part of the current class. " << field->PrettyField() << " class is " - << PrettyClass(); - uintptr_t start = reinterpret_cast<uintptr_t>(&GetIFieldsPtr()->At(0)); - uintptr_t fld = reinterpret_cast<uintptr_t>(field); - size_t res = (fld - start) / sizeof(ArtField); - DCHECK_EQ(&GetIFieldsPtr()->At(res), field) - << "Incorrect field computation expected: " << field->PrettyField() - << " got: " << GetIFieldsPtr()->At(res).PrettyField(); - return res; -} - -size_t Class::GetMethodIdOffset(ArtMethod* method, PointerSize pointer_size) { - DCHECK(GetMethodsSlice(kRuntimePointerSize).Contains(method)) - << "method not part of the current class. " << method->PrettyMethod() << "( " << reinterpret_cast<void*>(method) << ")" << " class is " - << PrettyClass() << [&]() REQUIRES_SHARED(Locks::mutator_lock_) { - std::ostringstream os; - os << " Methods are ["; - for (ArtMethod& m : GetMethodsSlice(kRuntimePointerSize)) { - os << m.PrettyMethod() << "( " << reinterpret_cast<void*>(&m) << "), "; - } - os << "]"; - return os.str(); - }(); - uintptr_t start = reinterpret_cast<uintptr_t>(&*GetMethodsSlice(pointer_size).begin()); - uintptr_t fld = reinterpret_cast<uintptr_t>(method); - size_t art_method_size = ArtMethod::Size(pointer_size); - size_t art_method_align = ArtMethod::Alignment(pointer_size); - size_t res = (fld - start) / art_method_size; - DCHECK_EQ(&GetMethodsPtr()->At(res, art_method_size, art_method_align), method) - << "Incorrect method computation expected: " << method->PrettyMethod() - << " got: " << GetMethodsPtr()->At(res, art_method_size, art_method_align).PrettyMethod(); - return res; -} - } // namespace mirror } // namespace art diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h index 144350f02e..09d5532deb 100644 --- a/runtime/mirror/class.h +++ b/runtime/mirror/class.h @@ -1229,23 +1229,6 @@ class MANAGED Class final : public Object { void FixupNativePointers(Class* dest, PointerSize pointer_size, const Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_); - // Get or create the various jni id arrays in a lock-less thread safe manner. - ObjPtr<PointerArray> GetOrCreateMethodIds() REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr<PointerArray> GetMethodIds() REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr<PointerArray> GetOrCreateStaticFieldIds() REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr<PointerArray> GetStaticFieldIds() REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr<PointerArray> GetOrCreateInstanceFieldIds() REQUIRES_SHARED(Locks::mutator_lock_); - ObjPtr<PointerArray> GetInstanceFieldIds() REQUIRES_SHARED(Locks::mutator_lock_); - - // Calculate the index in the ifields_, methods_ or sfields_ arrays a method is located at. This - // is to be used with the above Get{,OrCreate}...Ids functions. - size_t GetStaticFieldIdOffset(ArtField* field) - REQUIRES_SHARED(Locks::mutator_lock_); - size_t GetInstanceFieldIdOffset(ArtField* field) - REQUIRES_SHARED(Locks::mutator_lock_); - size_t GetMethodIdOffset(ArtMethod* method, PointerSize pointer_size) - REQUIRES_SHARED(Locks::mutator_lock_); - private: template <typename T, VerifyObjectFlags kVerifyFlags, typename Visitor> void FixupNativePointer( diff --git a/runtime/mirror/class_ext-inl.h b/runtime/mirror/class_ext-inl.h index ead02eed3b..bf51654447 100644 --- a/runtime/mirror/class_ext-inl.h +++ b/runtime/mirror/class_ext-inl.h @@ -19,81 +19,12 @@ #include "class_ext.h" -#include "array-inl.h" #include "art_method-inl.h" -#include "handle_scope.h" #include "object-inl.h" namespace art { namespace mirror { -template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> -inline ObjPtr<PointerArray> ClassExt::EnsureJniIdsArrayPresent(MemberOffset off, size_t count) { - ObjPtr<PointerArray> existing( - GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>(off)); - if (!existing.IsNull()) { - return existing; - } - Thread* self = Thread::Current(); - StackHandleScope<2> hs(self); - Handle<ClassExt> h_this(hs.NewHandle(this)); - Handle<PointerArray> new_arr( - hs.NewHandle(Runtime::Current()->GetClassLinker()->AllocPointerArray(self, count))); - if (new_arr.IsNull()) { - // Fail. - self->AssertPendingOOMException(); - return nullptr; - } - bool set; - // Set the ext_data_ field using CAS semantics. - if (Runtime::Current()->IsActiveTransaction()) { - set = h_this->CasFieldObject<true>( - off, nullptr, new_arr.Get(), CASMode::kStrong, std::memory_order_seq_cst); - } else { - set = h_this->CasFieldObject<false>( - off, nullptr, new_arr.Get(), CASMode::kStrong, std::memory_order_seq_cst); - } - ObjPtr<PointerArray> ret( - set ? new_arr.Get() - : h_this->GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>(off)); - CHECK(!ret.IsNull()); - return ret; -} - -template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> -inline ObjPtr<PointerArray> ClassExt::EnsureJMethodIDsArrayPresent(size_t count) { - return EnsureJniIdsArrayPresent<kVerifyFlags, kReadBarrierOption>( - MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, jmethod_ids_)), count); -} -template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> -inline ObjPtr<PointerArray> ClassExt::EnsureStaticJFieldIDsArrayPresent(size_t count) { - return EnsureJniIdsArrayPresent<kVerifyFlags, kReadBarrierOption>( - MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, static_jfield_ids_)), count); -} -template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> -inline ObjPtr<PointerArray> ClassExt::EnsureInstanceJFieldIDsArrayPresent(size_t count) { - return EnsureJniIdsArrayPresent<kVerifyFlags, kReadBarrierOption>( - MemberOffset(OFFSET_OF_OBJECT_MEMBER(ClassExt, instance_jfield_ids_)), count); -} - -template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> -inline ObjPtr<PointerArray> ClassExt::GetInstanceJFieldIDs() { - return GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>( - OFFSET_OF_OBJECT_MEMBER(ClassExt, instance_jfield_ids_)); -} - -template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> -inline ObjPtr<PointerArray> ClassExt::GetStaticJFieldIDs() { - return GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>( - OFFSET_OF_OBJECT_MEMBER(ClassExt, static_jfield_ids_)); -} - -template <VerifyObjectFlags kVerifyFlags, ReadBarrierOption kReadBarrierOption> -inline ObjPtr<PointerArray> ClassExt::GetJMethodIDs() { - return GetFieldObject<PointerArray, kVerifyFlags, kReadBarrierOption>( - OFFSET_OF_OBJECT_MEMBER(ClassExt, jmethod_ids_)); -} - inline ObjPtr<Object> ClassExt::GetVerifyError() { return GetFieldObject<ClassExt>(OFFSET_OF_OBJECT_MEMBER(ClassExt, verify_error_)); } diff --git a/runtime/mirror/class_ext.h b/runtime/mirror/class_ext.h index 6fb225fd69..70bea33c1f 100644 --- a/runtime/mirror/class_ext.h +++ b/runtime/mirror/class_ext.h @@ -48,33 +48,6 @@ class MANAGED ClassExt : public Object { template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - ObjPtr<PointerArray> EnsureInstanceJFieldIDsArrayPresent(size_t count) - REQUIRES_SHARED(Locks::mutator_lock_); - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, - ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - ObjPtr<PointerArray> GetInstanceJFieldIDs() REQUIRES_SHARED(Locks::mutator_lock_); - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, - ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - ObjPtr<PointerArray> EnsureStaticJFieldIDsArrayPresent(size_t count) - REQUIRES_SHARED(Locks::mutator_lock_); - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, - ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - ObjPtr<PointerArray> GetStaticJFieldIDs() REQUIRES_SHARED(Locks::mutator_lock_); - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, - ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - ObjPtr<PointerArray> EnsureJMethodIDsArrayPresent(size_t count) - REQUIRES_SHARED(Locks::mutator_lock_); - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, - ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - ObjPtr<PointerArray> GetJMethodIDs() REQUIRES_SHARED(Locks::mutator_lock_); - - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, - ReadBarrierOption kReadBarrierOption = kWithReadBarrier> ObjPtr<PointerArray> GetObsoleteMethods() REQUIRES_SHARED(Locks::mutator_lock_); ObjPtr<Object> GetOriginalDexFile() REQUIRES_SHARED(Locks::mutator_lock_); @@ -109,36 +82,19 @@ class MANAGED ClassExt : public Object { static ObjPtr<ClassExt> Alloc(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_); private: - template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, - ReadBarrierOption kReadBarrierOption = kWithReadBarrier> - ObjPtr<PointerArray> EnsureJniIdsArrayPresent(MemberOffset off, size_t count) - REQUIRES_SHARED(Locks::mutator_lock_); - // Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses". - // An array containing the jfieldIDs assigned to each field in the corresponding position in the - // classes ifields_ array or '0' if no id has been assigned to that field yet. - HeapReference<PointerArray> instance_jfield_ids_; - - // An array containing the jmethodIDs assigned to each method in the corresponding position in - // the classes methods_ array or '0' if no id has been assigned to that method yet. - HeapReference<PointerArray> jmethod_ids_; - HeapReference<ObjectArray<DexCache>> obsolete_dex_caches_; HeapReference<PointerArray> obsolete_methods_; HeapReference<Object> original_dex_file_; - // An array containing the jfieldIDs assigned to each field in the corresponding position in the - // classes sfields_ array or '0' if no id has been assigned to that field yet. - HeapReference<PointerArray> static_jfield_ids_; - // The saved verification error of this class. HeapReference<Object> verify_error_; // Native pointer to DexFile and ClassDef index of this class before it was JVMTI-redefined. - int32_t pre_redefine_class_def_index_; int64_t pre_redefine_dex_file_ptr_; + int32_t pre_redefine_class_def_index_; friend struct art::ClassExtOffsets; // for verifying offset information DISALLOW_IMPLICIT_CONSTRUCTORS(ClassExt); diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index afcf40d7b5..a5e9d95ea6 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -367,10 +367,6 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize .WithType<bool>() .WithValueMap({{"false", false}, {"true", true}}) .IntoKey(M::FastClassNotFoundException) - .Define("-Xopaque-jni-ids:_") - .WithType<bool>() - .WithValueMap({{"true", true}, {"false", false}}) - .IntoKey(M::OpaqueJniIds) .Ignore({ "-ea", "-da", "-enableassertions", "-disableassertions", "--runtime-arg", "-esa", "-dsa", "-enablesystemassertions", "-disablesystemassertions", "-Xrs", "-Xint:_", @@ -788,7 +784,6 @@ void ParsedOptions::Usage(const char* fmt, ...) { "(Enable new and experimental agent support)\n"); UsageMessage(stream, " -Xexperimental:agents" "(Enable new and experimental agent support)\n"); - UsageMessage(stream, " -Xopaque-jni-ids:{true,false} (Use opauque integers for jni ids)\n"); UsageMessage(stream, "\n"); UsageMessage(stream, "The following previously supported Dalvik options are ignored:\n"); diff --git a/runtime/runtime.cc b/runtime/runtime.cc index ad20575af7..12fda4382b 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -94,9 +94,7 @@ #include "jit/jit_code_cache.h" #include "jit/profile_saver.h" #include "jni/java_vm_ext.h" -#include "jni/jni_id_manager.h" #include "jni/jni_internal.h" -#include "jni_id_type.h" #include "linear_alloc.h" #include "memory_representation.h" #include "mirror/array.h" @@ -1183,8 +1181,6 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { oat_file_manager_ = new OatFileManager; - jni_id_manager_ = new jni::JniIdManager; - Thread::SetSensitiveThreadHook(runtime_options.GetOrDefault(Opt::HookIsSensitiveThread)); Monitor::Init(runtime_options.GetOrDefault(Opt::LockProfThreshold), runtime_options.GetOrDefault(Opt::StackDumpLockProfThreshold)); @@ -1306,13 +1302,6 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { is_low_memory_mode_ = runtime_options.Exists(Opt::LowMemoryMode); madvise_random_access_ = runtime_options.GetOrDefault(Opt::MadviseRandomAccess); - if (!runtime_options.Exists(Opt::OpaqueJniIds)) { - jni_ids_indirection_ = JniIdType::kDefault; - } else { - jni_ids_indirection_ = *runtime_options.Get(Opt::OpaqueJniIds) ? JniIdType::kIndices - : JniIdType::kPointer; - } - plugins_ = runtime_options.ReleaseOrDefault(Opt::Plugins); agent_specs_ = runtime_options.ReleaseOrDefault(Opt::AgentPath); // TODO Add back in -agentlib diff --git a/runtime/runtime.h b/runtime/runtime.h index 65e3541aea..6e27a9f31a 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -37,8 +37,6 @@ #include "gc_root.h" #include "instrumentation.h" #include "jdwp_provider.h" -#include "jni/jni_id_manager.h" -#include "jni_id_type.h" #include "obj_ptr.h" #include "offsets.h" #include "process_state.h" @@ -281,10 +279,6 @@ class Runtime { return class_linker_; } - jni::JniIdManager* GetJniIdManager() const { - return jni_id_manager_; - } - size_t GetDefaultStackSize() const { return default_stack_size_; } @@ -840,10 +834,6 @@ class Runtime { return jdwp_provider_; } - bool JniIdsAreIndices() const { - return jni_ids_indirection_ != JniIdType::kPointer; - } - uint32_t GetVerifierLoggingThresholdMs() const { return verifier_logging_threshold_ms_; } @@ -1015,8 +1005,6 @@ class Runtime { SignalCatcher* signal_catcher_; - jni::JniIdManager* jni_id_manager_; - std::unique_ptr<JavaVMExt> java_vm_; std::unique_ptr<jit::Jit> jit_; @@ -1200,10 +1188,6 @@ class Runtime { // The jdwp provider we were configured with. JdwpProvider jdwp_provider_; - // True if jmethodID and jfieldID are opaque Indices. When false (the default) these are simply - // pointers. This is set by -Xopaque-jni-ids:{true,false}. - JniIdType jni_ids_indirection_; - // Saved environment. class EnvSnapshot { public: diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def index d2594b2040..43a722937c 100644 --- a/runtime/runtime_options.def +++ b/runtime/runtime_options.def @@ -77,7 +77,6 @@ RUNTIME_OPTIONS_KEY (bool, EnableHSpaceCompactForOOM, true) RUNTIME_OPTIONS_KEY (bool, UseJitCompilation, true) RUNTIME_OPTIONS_KEY (bool, DumpNativeStackOnSigQuit, true) RUNTIME_OPTIONS_KEY (bool, MadviseRandomAccess, false) -RUNTIME_OPTIONS_KEY (bool, OpaqueJniIds, false) // -Xopaque-jni-ids:{true, false} RUNTIME_OPTIONS_KEY (unsigned int, JITCompileThreshold) RUNTIME_OPTIONS_KEY (unsigned int, JITWarmupThreshold) RUNTIME_OPTIONS_KEY (unsigned int, JITOsrThreshold) diff --git a/runtime/thread.cc b/runtime/thread.cc index d5aea19e87..3e83f654b5 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -4280,16 +4280,8 @@ ScopedExceptionStorage::ScopedExceptionStorage(art::Thread* self) self_->ClearException(); } -void ScopedExceptionStorage::SuppressOldException(const char* message) { - CHECK(self_->IsExceptionPending()) << *self_; - ObjPtr<mirror::Throwable> old_suppressed(excp_.Get()); - excp_.Assign(self_->GetException()); - LOG(WARNING) << message << "Suppressing old exception: " << old_suppressed->Dump(); - self_->ClearException(); -} - ScopedExceptionStorage::~ScopedExceptionStorage() { - CHECK(!self_->IsExceptionPending()) << *self_; + CHECK(!self_->IsExceptionPending()) << self_; if (!excp_.IsNull()) { self_->SetException(excp_.Get()); } diff --git a/runtime/thread.h b/runtime/thread.h index 9a230e2380..8fe9466112 100644 --- a/runtime/thread.h +++ b/runtime/thread.h @@ -1901,13 +1901,12 @@ class ThreadLifecycleCallback { class ScopedExceptionStorage { public: explicit ScopedExceptionStorage(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_); - void SuppressOldException(const char* message = "") REQUIRES_SHARED(Locks::mutator_lock_); ~ScopedExceptionStorage() REQUIRES_SHARED(Locks::mutator_lock_); private: Thread* self_; StackHandleScope<1> hs_; - MutableHandle<mirror::Throwable> excp_; + Handle<mirror::Throwable> excp_; }; std::ostream& operator<<(std::ostream& os, const Thread& thread); diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py index 379b2c6fbc..ac1b2c6af4 100755 --- a/test/testrunner/testrunner.py +++ b/test/testrunner/testrunner.py @@ -435,7 +435,7 @@ def run_tests(tests): options_test += ' --no-image' if debuggable == 'debuggable': - options_test += ' --debuggable --runtime-option -Xopaque-jni-ids:true' + options_test += ' --debuggable' if jvmti == 'jvmti-stress': options_test += ' --jvmti-trace-stress --jvmti-redefine-stress --jvmti-field-stress' @@ -797,7 +797,7 @@ def parse_test_name(test_name): It supports two types of test_name: 1) Like 001-HelloWorld. In this case, it will just verify if the test actually exists and if it does, it returns the testname. - 2) Like test-art-host-run-test-debug-prebuild-interpreter-no-relocate-ntrace-cms-checkjni-pointer-ids-picimage-ndebuggable-001-HelloWorld32 + 2) Like test-art-host-run-test-debug-prebuild-interpreter-no-relocate-ntrace-cms-checkjni-picimage-ndebuggable-001-HelloWorld32 In this case, it will parse all the variants and check if they are placed correctly. If yes, it will set the various VARIANT_TYPES to use the variants required to run the test. Again, it returns the test_name |