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