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