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_LOCKS_REQUIRED(Locks::mutator_lock_)53   ALWAYS_INLINE T& operator*() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
54     return *Get();
55   }
56 
57   ALWAYS_INLINE T* operator->() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
58     return Get();
59   }
60 
Get()61   ALWAYS_INLINE T* Get() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
62     return down_cast<T*>(reference_->AsMirrorPtr());
63   }
64 
ToJObject()65   ALWAYS_INLINE jobject ToJObject() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
66     if (UNLIKELY(reference_->AsMirrorPtr() == nullptr)) {
67       // Special case so that we work with NullHandles.
68       return nullptr;
69     }
70     return reinterpret_cast<jobject>(reference_);
71   }
72 
GetReference()73   ALWAYS_INLINE StackReference<mirror::Object>* GetReference()
74       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
75     return reference_;
76   }
77 
GetReference()78   ALWAYS_INLINE const StackReference<mirror::Object>* GetReference() const
79       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
80     return reference_;
81   }
82 
83  protected:
84   template<typename S>
Handle(StackReference<S> * reference)85   explicit Handle(StackReference<S>* reference)
86       : reference_(reference) {
87   }
88   template<typename S>
Handle(const Handle<S> & handle)89   explicit Handle(const Handle<S>& handle)
90       : reference_(handle.reference_) {
91   }
92 
93   StackReference<mirror::Object>* reference_;
94 
95  private:
96   friend class BuildGenericJniFrameVisitor;
97   template<class S> friend class Handle;
98   friend class HandleScope;
99   template<class S> friend class HandleWrapper;
100   template<size_t kNumReferences> friend class StackHandleScope;
101 };
102 
103 // Handles that support assignment.
104 template<class T>
105 class MutableHandle : public Handle<T> {
106  public:
MutableHandle()107   MutableHandle() {
108   }
109 
MutableHandle(const MutableHandle<T> & handle)110   ALWAYS_INLINE MutableHandle(const MutableHandle<T>& handle)
111       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
112       : Handle<T>(handle.reference_) {
113   }
114 
115   ALWAYS_INLINE MutableHandle<T>& operator=(const MutableHandle<T>& handle)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)116       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
117     Handle<T>::operator=(handle);
118     return *this;
119   }
120 
MutableHandle(StackReference<T> * reference)121   ALWAYS_INLINE explicit MutableHandle(StackReference<T>* reference)
122       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
123       : Handle<T>(reference) {
124   }
125 
Assign(T * reference)126   ALWAYS_INLINE T* Assign(T* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
127     StackReference<mirror::Object>* ref = Handle<T>::GetReference();
128     T* old = down_cast<T*>(ref->AsMirrorPtr());
129     ref->Assign(reference);
130     return old;
131   }
132 
133   template<typename S>
MutableHandle(const MutableHandle<S> & handle)134   explicit MutableHandle(const MutableHandle<S>& handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
135       : Handle<T>(handle) {
136   }
137 
138   template<typename S>
MutableHandle(StackReference<S> * reference)139   explicit MutableHandle(StackReference<S>* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
140       : Handle<T>(reference) {
141   }
142 
143  private:
144   friend class BuildGenericJniFrameVisitor;
145   friend class HandleScope;
146   template<class S> friend class HandleWrapper;
147   template<size_t kNumReferences> friend class StackHandleScope;
148 };
149 
150 // A special case of Handle that only holds references to null.
151 template<class T>
152 class NullHandle : public Handle<T> {
153  public:
NullHandle()154   NullHandle() : Handle<T>(&null_ref_) {
155   }
156 
157  private:
158   StackReference<mirror::Object> null_ref_;
159 };
160 
161 }  // namespace art
162 
163 #endif  // ART_RUNTIME_HANDLE_H_
164