• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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   StackReference<T>* reference_;
74 
75   template<typename S>
ConstHandle(StackReference<S> * reference)76   explicit ConstHandle(StackReference<S>* reference)
77       : reference_(reinterpret_cast<StackReference<T>*>(reference)) {
78   }
79   template<typename S>
ConstHandle(const ConstHandle<S> & handle)80   explicit ConstHandle(const ConstHandle<S>& handle)
81       : reference_(reinterpret_cast<StackReference<T>*>(handle.reference_)) {
82   }
83 
GetReference()84   StackReference<T>* GetReference() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) ALWAYS_INLINE {
85     return reference_;
86   }
GetReference()87   ALWAYS_INLINE const StackReference<T>* GetReference() const
88       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
89     return reference_;
90   }
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<T>* ref = ConstHandle<T>::GetReference();
124     T* const old = 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  protected:
135   template<typename S>
Handle(StackReference<S> * reference)136   explicit Handle(StackReference<S>* reference) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_)
137       : ConstHandle<T>(reference) {
138   }
139 
140  private:
141   friend class BuildGenericJniFrameVisitor;
142   friend class HandleScope;
143   template<class S> friend class HandleWrapper;
144   template<size_t kNumReferences> friend class StackHandleScope;
145 };
146 
147 // A special case of Handle that only holds references to null.
148 template<class T>
149 class NullHandle : public Handle<T> {
150  public:
NullHandle()151   NullHandle() : Handle<T>(&null_ref_) {
152   }
153 
154  private:
155   StackReference<T> null_ref_;
156 };
157 
158 }  // namespace art
159 
160 #endif  // ART_RUNTIME_HANDLE_H_
161