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