1 /* 2 * Copyright (C) 2014 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_HANDLE_H_ 18 #define ART_RUNTIME_HANDLE_H_ 19 20 #include <android-base/logging.h> 21 22 #include "base/casts.h" 23 #include "base/locks.h" 24 #include "base/macros.h" 25 #include "base/value_object.h" 26 #include "jni.h" 27 #include "obj_ptr.h" 28 #include "stack_reference.h" 29 30 namespace art { 31 32 class Thread; 33 34 template<class T> class Handle; 35 template<typename T> class IterationRange; 36 37 namespace mirror { 38 template<typename T> class ObjectArray; 39 template<typename T, typename C> class ArrayIter; 40 template<typename T> using HandleArrayIter = ArrayIter<T, Handle<ObjectArray<T>>>; 41 template<typename T> using ConstHandleArrayIter = ArrayIter<T, const Handle<ObjectArray<T>>>; 42 } // namespace mirror 43 44 // Handles are memory locations that contain GC roots. As the mirror::Object*s within a handle are 45 // GC visible then the GC may move the references within them, something that couldn't be done with 46 // a wrap pointer. Handles are generally allocated within HandleScopes. Handle is a super-class 47 // of MutableHandle and doesn't support assignment operations. 48 template<class T> 49 class Handle : public ValueObject { 50 public: Handle()51 Handle() : reference_(nullptr) { 52 } 53 54 ALWAYS_INLINE Handle(const Handle<T>& handle) = default; 55 56 ALWAYS_INLINE Handle<T>& operator=(const Handle<T>& handle) = default; 57 58 template <typename Type, 59 typename = typename std::enable_if_t<std::is_base_of_v<T, Type>>> Handle(const Handle<Type> & other)60 ALWAYS_INLINE Handle(const Handle<Type>& other) : reference_(other.reference_) { 61 } 62 Handle(StackReference<T> * reference)63 ALWAYS_INLINE explicit Handle(StackReference<T>* reference) : reference_(reference) { 64 } 65 REQUIRES_SHARED(Locks::mutator_lock_)66 ALWAYS_INLINE T& operator*() const REQUIRES_SHARED(Locks::mutator_lock_) { 67 return *Get(); 68 } 69 70 ALWAYS_INLINE T* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) { 71 return Get(); 72 } 73 Get()74 ALWAYS_INLINE T* Get() const REQUIRES_SHARED(Locks::mutator_lock_) { 75 return down_cast<T*>(reference_->AsMirrorPtr()); 76 } 77 78 template <typename Type, 79 typename = typename std::enable_if_t<std::is_same_v<mirror::ObjectArray<Type>, T>>> ConstIterate()80 ALWAYS_INLINE IterationRange<mirror::ConstHandleArrayIter<Type>> ConstIterate() const 81 REQUIRES_SHARED(Locks::mutator_lock_) { 82 return T::ConstIterate(*this); 83 } 84 template <typename Type, 85 typename = typename std::enable_if_t<std::is_same_v<mirror::ObjectArray<Type>, T>>> Iterate()86 ALWAYS_INLINE IterationRange<mirror::HandleArrayIter<Type>> Iterate() 87 REQUIRES_SHARED(Locks::mutator_lock_) { 88 return T::Iterate(*this); 89 } 90 IsNull()91 ALWAYS_INLINE bool IsNull() const { 92 // It's safe to null-check it without a read barrier. 93 return reference_->IsNull(); 94 } 95 ToJObject()96 ALWAYS_INLINE jobject ToJObject() const REQUIRES_SHARED(Locks::mutator_lock_) { 97 if (UNLIKELY(reference_->AsMirrorPtr() == nullptr)) { 98 // Special case so that we work with null handles. 99 return nullptr; 100 } 101 return reinterpret_cast<jobject>(reference_); 102 } 103 GetReference()104 ALWAYS_INLINE StackReference<mirror::Object>* GetReference() { 105 return reference_; 106 } 107 GetReference()108 ALWAYS_INLINE const StackReference<mirror::Object>* GetReference() const { 109 return reference_; 110 } 111 112 ALWAYS_INLINE bool operator!=(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) { 113 return !IsNull(); 114 } 115 116 ALWAYS_INLINE bool operator==(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) { 117 return IsNull(); 118 } 119 120 mirror::Object* ObjectFromGdb() REQUIRES_SHARED(Locks::mutator_lock_); 121 T* GetFromGdb() REQUIRES_SHARED(Locks::mutator_lock_); 122 123 protected: 124 template<typename S> Handle(StackReference<S> * reference)125 explicit Handle(StackReference<S>* reference) 126 : reference_(reference) { 127 } 128 template<typename S> Handle(const Handle<S> & handle)129 explicit Handle(const Handle<S>& handle) 130 : reference_(handle.reference_) { 131 } 132 133 StackReference<mirror::Object>* reference_; 134 135 private: 136 friend class BuildGenericJniFrameVisitor; 137 template<class S> friend class Handle; 138 friend class HandleScope; 139 template<class S> friend class HandleWrapper; 140 template<size_t kNumReferences> friend class StackHandleScope; 141 }; 142 143 // Handles that support assignment. 144 template<class T> 145 class MutableHandle : public Handle<T> { 146 public: MutableHandle()147 MutableHandle() { 148 } 149 150 ALWAYS_INLINE MutableHandle(const MutableHandle<T>& handle) 151 REQUIRES_SHARED(Locks::mutator_lock_) = default; 152 153 ALWAYS_INLINE MutableHandle<T>& operator=(const MutableHandle<T>& handle) 154 REQUIRES_SHARED(Locks::mutator_lock_) = default; 155 MutableHandle(StackReference<T> * reference)156 ALWAYS_INLINE explicit MutableHandle(StackReference<T>* reference) 157 REQUIRES_SHARED(Locks::mutator_lock_) 158 : Handle<T>(reference) { 159 } 160 Assign(T * reference)161 ALWAYS_INLINE T* Assign(T* reference) REQUIRES_SHARED(Locks::mutator_lock_) { 162 StackReference<mirror::Object>* ref = Handle<T>::GetReference(); 163 T* old = down_cast<T*>(ref->AsMirrorPtr()); 164 ref->Assign(reference); 165 return old; 166 } 167 Assign(ObjPtr<T> reference)168 ALWAYS_INLINE T* Assign(ObjPtr<T> reference) REQUIRES_SHARED(Locks::mutator_lock_) { 169 StackReference<mirror::Object>* ref = Handle<T>::GetReference(); 170 T* old = down_cast<T*>(ref->AsMirrorPtr()); 171 ref->Assign(reference.Ptr()); 172 return old; 173 } 174 175 176 template<typename S> MutableHandle(const MutableHandle<S> & handle)177 explicit MutableHandle(const MutableHandle<S>& handle) REQUIRES_SHARED(Locks::mutator_lock_) 178 : Handle<T>(handle) { 179 } 180 181 template<typename S> MutableHandle(StackReference<S> * reference)182 explicit MutableHandle(StackReference<S>* reference) REQUIRES_SHARED(Locks::mutator_lock_) 183 : Handle<T>(reference) { 184 } 185 186 private: 187 friend class BuildGenericJniFrameVisitor; 188 friend class HandleScope; 189 template<class S> friend class HandleWrapper; 190 template<size_t kNumReferences> friend class StackHandleScope; 191 }; 192 193 // A special case of Handle that only holds references to null. Invalid when if it goes out of 194 // scope. Example: Handle<T> h = ScopedNullHandle<T> will leave h being undefined. 195 template<class T> 196 class ScopedNullHandle : public Handle<T> { 197 public: ScopedNullHandle()198 ScopedNullHandle() : Handle<T>(&null_ref_) {} 199 200 private: 201 StackReference<mirror::Object> null_ref_; 202 }; 203 204 } // namespace art 205 206 #endif // ART_RUNTIME_HANDLE_H_ 207