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