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