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