1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_RUNTIME_JNI_JNI_ID_MANAGER_H_ 18 #define ART_RUNTIME_JNI_JNI_ID_MANAGER_H_ 19 20 #include <jni.h> 21 22 #include <atomic> 23 #include <vector> 24 25 #include "art_field.h" 26 #include "art_method.h" 27 #include "base/mutex.h" 28 #include "gc_root.h" 29 #include "jni_id_type.h" 30 #include "reflective_value_visitor.h" 31 32 namespace art { 33 namespace mirror { 34 class Object; 35 class ClassExt; 36 } // namespace mirror 37 template<typename RT> class ReflectiveHandle; 38 39 namespace jni { 40 41 class ScopedEnableSuspendAllJniIdQueries; 42 class JniIdManager { 43 public: 44 template <typename T, 45 typename = typename std::enable_if<std::is_same_v<T, jmethodID> || 46 std::is_same_v<T, jfieldID>>> IsIndexId(T val)47 static constexpr bool IsIndexId(T val) { 48 return val == nullptr || reinterpret_cast<uintptr_t>(val) % 2 == 1; 49 } 50 51 void Init(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_); 52 53 ArtMethod* DecodeMethodId(jmethodID method) REQUIRES(!Locks::jni_id_lock_); 54 ArtField* DecodeFieldId(jfieldID field) REQUIRES(!Locks::jni_id_lock_); 55 jmethodID EncodeMethodId(ReflectiveHandle<ArtMethod> method) REQUIRES(!Locks::jni_id_lock_) 56 REQUIRES_SHARED(Locks::mutator_lock_); 57 jmethodID EncodeMethodId(ArtMethod* method) REQUIRES(!Locks::jni_id_lock_) 58 REQUIRES_SHARED(Locks::mutator_lock_); 59 jfieldID EncodeFieldId(ReflectiveHandle<ArtField> field) REQUIRES(!Locks::jni_id_lock_) 60 REQUIRES_SHARED(Locks::mutator_lock_); 61 jfieldID EncodeFieldId(ArtField* field) REQUIRES(!Locks::jni_id_lock_) 62 REQUIRES_SHARED(Locks::mutator_lock_); 63 64 void VisitReflectiveTargets(ReflectiveValueVisitor* rvv) 65 REQUIRES(Locks::mutator_lock_, !Locks::jni_id_lock_); 66 67 void VisitRoots(RootVisitor* visitor) REQUIRES_SHARED(Locks::mutator_lock_); 68 69 ObjPtr<mirror::Object> GetPointerMarker() REQUIRES_SHARED(Locks::mutator_lock_); 70 71 private: 72 template <typename ArtType> 73 uintptr_t EncodeGenericId(ReflectiveHandle<ArtType> t) REQUIRES(!Locks::jni_id_lock_) 74 REQUIRES_SHARED(Locks::mutator_lock_); 75 template <typename ArtType> 76 ArtType* DecodeGenericId(uintptr_t input) REQUIRES(!Locks::jni_id_lock_); 77 template <typename ArtType> std::vector<ArtType*>& GetGenericMap() 78 REQUIRES(Locks::jni_id_lock_); 79 template <typename ArtType> uintptr_t GetNextId(JniIdType id) 80 REQUIRES_SHARED(Locks::mutator_lock_) 81 REQUIRES(Locks::jni_id_lock_); 82 template <typename ArtType> 83 size_t GetLinearSearchStartId(ReflectiveHandle<ArtType> t) 84 REQUIRES(Locks::jni_id_lock_) 85 REQUIRES_SHARED(Locks::mutator_lock_); 86 87 void StartDefer() REQUIRES(!Locks::jni_id_lock_) REQUIRES_SHARED(Locks::mutator_lock_); 88 void EndDefer() REQUIRES(!Locks::jni_id_lock_) REQUIRES_SHARED(Locks::mutator_lock_); 89 90 uintptr_t next_method_id_ GUARDED_BY(Locks::jni_id_lock_) = 1u; 91 std::vector<ArtMethod*> method_id_map_ GUARDED_BY(Locks::jni_id_lock_); 92 uintptr_t next_field_id_ GUARDED_BY(Locks::jni_id_lock_) = 1u; 93 std::vector<ArtField*> field_id_map_ GUARDED_BY(Locks::jni_id_lock_); 94 95 // If non-zero indicates that some thread is trying to allocate ids without being able to update 96 // the method->id mapping (due to not being able to allocate or something). In this case decode 97 // and encode need to do a linear scan of the lists. The ScopedEnableSuspendAllJniIdQueries struct 98 // will deal with fixing everything up. 99 size_t deferred_allocation_refcount_ GUARDED_BY(Locks::jni_id_lock_) = 0; 100 // min jmethodID that might not have it's method->id mapping filled in. 101 uintptr_t deferred_allocation_method_id_start_ GUARDED_BY(Locks::jni_id_lock_) = 0u; 102 // min jfieldID that might not have it's field->id mapping filled in. 103 uintptr_t deferred_allocation_field_id_start_ GUARDED_BY(Locks::jni_id_lock_) = 0u; 104 105 GcRoot<mirror::Object> pointer_marker_; 106 107 friend class ScopedEnableSuspendAllJniIdQueries; 108 // For GetPointerMarker 109 friend class mirror::ClassExt; 110 }; 111 112 // A scope that will enable using the Encode/Decode JNI id functions with all threads suspended. 113 // This is required since normally we need to be able to allocate to encode new ids. This should 114 // only be used when absolutely required, for example to invoke user-callbacks during heap walking 115 // or similar. 116 class ScopedEnableSuspendAllJniIdQueries { 117 public: 118 ScopedEnableSuspendAllJniIdQueries() REQUIRES_SHARED(Locks::mutator_lock_); 119 ~ScopedEnableSuspendAllJniIdQueries() REQUIRES_SHARED(Locks::mutator_lock_); 120 121 private: 122 JniIdManager* manager_; 123 }; 124 125 } // namespace jni 126 } // namespace art 127 128 #endif // ART_RUNTIME_JNI_JNI_ID_MANAGER_H_ 129