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