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: ConstHandle()38 ConstHandle() : reference_(nullptr) { 39 } 40 ConstHandle(const ConstHandle<T> & handle)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 ConstHandle(StackReference<T> * reference)49 ALWAYS_INLINE explicit ConstHandle(StackReference<T>* reference) : reference_(reference) { 50 } 51 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)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 Get()60 ALWAYS_INLINE T* Get() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 61 return down_cast<T*>(reference_->AsMirrorPtr()); 62 } 63 ToJObject()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> ConstHandle(StackReference<S> * reference)74 explicit ConstHandle(StackReference<S>* reference) 75 : reference_(reference) { 76 } 77 template<typename S> ConstHandle(const ConstHandle<S> & handle)78 explicit ConstHandle(const ConstHandle<S>& handle) 79 : reference_(handle.reference_) { 80 } 81 GetReference()82 StackReference<mirror::Object>* GetReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE { 83 return reference_; 84 } GetReference()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: Handle()104 Handle() { 105 } 106 Handle(const Handle<T> & handle)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) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)112 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 113 ConstHandle<T>::operator=(handle); 114 return *this; 115 } 116 Handle(StackReference<T> * reference)117 ALWAYS_INLINE explicit Handle(StackReference<T>* reference) 118 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 119 : ConstHandle<T>(reference) { 120 } 121 Assign(T * reference)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> Handle(const Handle<S> & handle)130 explicit Handle(const Handle<S>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) 131 : ConstHandle<T>(handle) { 132 } 133 134 template<typename S> Handle(StackReference<S> * reference)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: NullHandle()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