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