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