blob: 28a230291d143934c9befaad4b57dc3dba4118f0 [file] [log] [blame]
Mathieu Chartiereb8167a2014-05-07 15:43:14 -07001/*
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_SCOPE_H_
18#define ART_RUNTIME_HANDLE_SCOPE_H_
19
Calin Juravleacf735c2015-02-12 15:25:22 +000020#include <stack>
21
Andreas Gampe57943812017-12-06 21:39:13 -080022#include <android-base/logging.h>
23
Andreas Gampe542451c2016-07-26 09:02:02 -070024#include "base/enums.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070025#include "base/macros.h"
Vladimir Marko3a21e382016-09-02 12:38:38 +010026#include "base/mutex.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070027#include "handle.h"
Vladimir Marko3a21e382016-09-02 12:38:38 +010028#include "stack_reference.h"
Mathieu Chartier3e0acf62015-01-08 09:41:25 -080029#include "verify_object.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070030
31namespace art {
Mathieu Chartier0795f232016-09-27 18:43:30 -070032
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070033class HandleScope;
Andreas Gampec73cb642017-02-22 10:11:30 -080034template<class MirrorType> class ObjPtr;
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070035class Thread;
36class VariableSizedHandleScope;
Mathieu Chartier0795f232016-09-27 18:43:30 -070037
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070038namespace mirror {
39class Object;
Andreas Gampedeae7db2017-05-30 09:56:41 -070040} // namespace mirror
Ian Rogerse63db272014-07-15 15:36:11 -070041
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070042// Basic handle scope, tracked by a list. May be variable sized.
43class PACKED(4) BaseHandleScope {
44 public:
45 bool IsVariableSized() const {
46 return number_of_references_ == kNumReferencesVariableSized;
47 }
48
49 // Number of references contained within this handle scope.
50 ALWAYS_INLINE uint32_t NumberOfReferences() const;
51
52 ALWAYS_INLINE bool Contains(StackReference<mirror::Object>* handle_scope_entry) const;
53
54 template <typename Visitor>
55 ALWAYS_INLINE void VisitRoots(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_);
56
57 // Link to previous BaseHandleScope or null.
58 BaseHandleScope* GetLink() const {
59 return link_;
60 }
61
62 ALWAYS_INLINE VariableSizedHandleScope* AsVariableSized();
63 ALWAYS_INLINE HandleScope* AsHandleScope();
64 ALWAYS_INLINE const VariableSizedHandleScope* AsVariableSized() const;
65 ALWAYS_INLINE const HandleScope* AsHandleScope() const;
66
67 protected:
68 BaseHandleScope(BaseHandleScope* link, uint32_t num_references)
69 : link_(link),
70 number_of_references_(num_references) {}
71
72 // Variable sized constructor.
Andreas Gampeea47ff82016-11-03 08:20:17 -070073 explicit BaseHandleScope(BaseHandleScope* link)
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070074 : link_(link),
75 number_of_references_(kNumReferencesVariableSized) {}
76
77 static constexpr int32_t kNumReferencesVariableSized = -1;
78
79 // Link-list of handle scopes. The root is held by a Thread.
80 BaseHandleScope* const link_;
81
82 // Number of handlerized references. -1 for variable sized handle scopes.
83 const int32_t number_of_references_;
84
85 private:
86 DISALLOW_COPY_AND_ASSIGN(BaseHandleScope);
87};
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070088
Ian Rogers22d5e732014-07-15 22:23:51 -070089// HandleScopes are scoped objects containing a number of Handles. They are used to allocate
90// handles, for these handles (and the objects contained within them) to be visible/roots for the
91// GC. It is most common to stack allocate HandleScopes using StackHandleScope.
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070092class PACKED(4) HandleScope : public BaseHandleScope {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070093 public:
94 ~HandleScope() {}
95
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070096 // We have versions with and without explicit pointer size of the following. The first two are
97 // used at runtime, so OFFSETOF_MEMBER computes the right offsets automatically. The last one
98 // takes the pointer size explicitly so that at compile time we can cross-compile correctly.
99
100 // Returns the size of a HandleScope containing num_references handles.
Mathieu Chartier3e0acf62015-01-08 09:41:25 -0800101 static size_t SizeOf(uint32_t num_references);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700102
Andreas Gampecf4035a2014-05-28 22:43:01 -0700103 // Returns the size of a HandleScope containing num_references handles.
Andreas Gampe542451c2016-07-26 09:02:02 -0700104 static size_t SizeOf(PointerSize pointer_size, uint32_t num_references);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700105
Ian Rogers59c07062014-10-10 13:03:39 -0700106 ALWAYS_INLINE mirror::Object* GetReference(size_t i) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700107 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700108
Vladimir Markof39745e2016-01-26 12:16:55 +0000109 ALWAYS_INLINE Handle<mirror::Object> GetHandle(size_t i);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700110
Ian Rogers59c07062014-10-10 13:03:39 -0700111 ALWAYS_INLINE MutableHandle<mirror::Object> GetMutableHandle(size_t i)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700112 REQUIRES_SHARED(Locks::mutator_lock_);
Andreas Gampe5a4b8a22014-09-11 08:30:08 -0700113
Ian Rogers59c07062014-10-10 13:03:39 -0700114 ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700115 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700116
Mathieu Chartier3e0acf62015-01-08 09:41:25 -0800117 ALWAYS_INLINE bool Contains(StackReference<mirror::Object>* handle_scope_entry) const;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700118
Ian Rogers59c07062014-10-10 13:03:39 -0700119 // Offset of link within HandleScope, used by generated code.
Andreas Gampe542451c2016-07-26 09:02:02 -0700120 static constexpr size_t LinkOffset(PointerSize pointer_size ATTRIBUTE_UNUSED) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700121 return 0;
122 }
123
Ian Rogers59c07062014-10-10 13:03:39 -0700124 // Offset of length within handle scope, used by generated code.
Andreas Gampe542451c2016-07-26 09:02:02 -0700125 static constexpr size_t NumberOfReferencesOffset(PointerSize pointer_size) {
126 return static_cast<size_t>(pointer_size);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700127 }
128
Ian Rogers59c07062014-10-10 13:03:39 -0700129 // Offset of link within handle scope, used by generated code.
Andreas Gampe542451c2016-07-26 09:02:02 -0700130 static constexpr size_t ReferencesOffset(PointerSize pointer_size) {
131 return NumberOfReferencesOffset(pointer_size) + sizeof(number_of_references_);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700132 }
133
Ian Rogers59c07062014-10-10 13:03:39 -0700134 // Placement new creation.
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700135 static HandleScope* Create(void* storage, BaseHandleScope* link, uint32_t num_references)
Ian Rogers59c07062014-10-10 13:03:39 -0700136 WARN_UNUSED {
137 return new (storage) HandleScope(link, num_references);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700138 }
139
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700140 // Number of references contained within this handle scope.
141 ALWAYS_INLINE uint32_t NumberOfReferences() const {
142 DCHECK_GE(number_of_references_, 0);
143 return static_cast<uint32_t>(number_of_references_);
144 }
145
146 template <typename Visitor>
147 void VisitRoots(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
148 for (size_t i = 0, count = NumberOfReferences(); i < count; ++i) {
149 // GetReference returns a pointer to the stack reference within the handle scope. If this
150 // needs to be updated, it will be done by the root visitor.
151 visitor.VisitRootIfNonNull(GetHandle(i).GetReference());
152 }
153 }
154
Ian Rogers59c07062014-10-10 13:03:39 -0700155 protected:
156 // Return backing storage used for references.
157 ALWAYS_INLINE StackReference<mirror::Object>* GetReferences() const {
Andreas Gampe542451c2016-07-26 09:02:02 -0700158 uintptr_t address = reinterpret_cast<uintptr_t>(this) + ReferencesOffset(kRuntimePointerSize);
Ian Rogers59c07062014-10-10 13:03:39 -0700159 return reinterpret_cast<StackReference<mirror::Object>*>(address);
160 }
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700161
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700162 explicit HandleScope(size_t number_of_references) : HandleScope(nullptr, number_of_references) {}
Mathieu Chartierd035c2d2014-10-27 17:30:20 -0700163
Ian Rogers59c07062014-10-10 13:03:39 -0700164 // Semi-hidden constructor. Construction expected by generated code and StackHandleScope.
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700165 HandleScope(BaseHandleScope* link, uint32_t num_references)
166 : BaseHandleScope(link, num_references) {}
Ian Rogers59c07062014-10-10 13:03:39 -0700167
168 // Storage for references.
169 // StackReference<mirror::Object> references_[number_of_references_]
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700170
171 private:
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700172 DISALLOW_COPY_AND_ASSIGN(HandleScope);
173};
174
175// A wrapper which wraps around Object** and restores the pointer in the destructor.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700176// TODO: Delete
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700177template<class T>
Andreas Gampe5a4b8a22014-09-11 08:30:08 -0700178class HandleWrapper : public MutableHandle<T> {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700179 public:
Andreas Gampe5a4b8a22014-09-11 08:30:08 -0700180 HandleWrapper(T** obj, const MutableHandle<T>& handle)
181 : MutableHandle<T>(handle), obj_(obj) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700182 }
183
Andreas Gampe758a8012015-04-03 21:28:42 -0700184 HandleWrapper(const HandleWrapper&) = default;
185
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700186 ~HandleWrapper() {
Andreas Gampe5a4b8a22014-09-11 08:30:08 -0700187 *obj_ = MutableHandle<T>::Get();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700188 }
189
190 private:
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700191 T** const obj_;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700192};
193
Mathieu Chartier0795f232016-09-27 18:43:30 -0700194
195// A wrapper which wraps around ObjPtr<Object>* and restores the pointer in the destructor.
196// TODO: Add more functionality.
197template<class T>
198class HandleWrapperObjPtr : public MutableHandle<T> {
199 public:
200 HandleWrapperObjPtr(ObjPtr<T>* obj, const MutableHandle<T>& handle)
201 : MutableHandle<T>(handle), obj_(obj) {}
202
203 HandleWrapperObjPtr(const HandleWrapperObjPtr&) = default;
204
205 ~HandleWrapperObjPtr() {
206 *obj_ = ObjPtr<T>(MutableHandle<T>::Get());
207 }
208
209 private:
210 ObjPtr<T>* const obj_;
211};
212
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700213// Fixed size handle scope that is not necessarily linked in the thread.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700214template<size_t kNumReferences>
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700215class PACKED(4) FixedSizeHandleScope : public HandleScope {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700216 public:
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700217 template<class T>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700218 ALWAYS_INLINE MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbc56fc32014-06-03 15:37:03 -0700219
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700220 template<class T>
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700221 ALWAYS_INLINE HandleWrapper<T> NewHandleWrapper(T** object)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700222 REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700223
Mathieu Chartier0795f232016-09-27 18:43:30 -0700224 template<class T>
225 ALWAYS_INLINE HandleWrapperObjPtr<T> NewHandleWrapper(ObjPtr<T>* object)
226 REQUIRES_SHARED(Locks::mutator_lock_);
227
Andreas Gampec73cb642017-02-22 10:11:30 -0800228 template<class MirrorType>
229 ALWAYS_INLINE MutableHandle<MirrorType> NewHandle(ObjPtr<MirrorType> object)
Mathieu Chartier0795f232016-09-27 18:43:30 -0700230 REQUIRES_SHARED(Locks::mutator_lock_);
231
Ian Rogers59c07062014-10-10 13:03:39 -0700232 ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700233 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbc56fc32014-06-03 15:37:03 -0700234
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700235 size_t RemainingSlots() const {
236 return kNumReferences - pos_;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700237 }
238
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700239 private:
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700240 explicit ALWAYS_INLINE FixedSizeHandleScope(BaseHandleScope* link,
241 mirror::Object* fill_value = nullptr);
242 ALWAYS_INLINE ~FixedSizeHandleScope() {}
243
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700244 template<class T>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700245 ALWAYS_INLINE MutableHandle<T> GetHandle(size_t i) REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700246 DCHECK_LT(i, kNumReferences);
247 return MutableHandle<T>(&GetReferences()[i]);
248 }
249
Ian Rogers59c07062014-10-10 13:03:39 -0700250 // Reference storage needs to be first as expected by the HandleScope layout.
251 StackReference<mirror::Object> storage_[kNumReferences];
Ian Rogers22d5e732014-07-15 22:23:51 -0700252
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700253 // Position new handles will be created.
Vladimir Marko26248c72017-02-21 17:00:28 +0000254 uint32_t pos_ = 0;
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700255
256 template<size_t kNumRefs> friend class StackHandleScope;
257 friend class VariableSizedHandleScope;
258};
259
260// Scoped handle storage of a fixed size that is stack allocated.
261template<size_t kNumReferences>
262class PACKED(4) StackHandleScope FINAL : public FixedSizeHandleScope<kNumReferences> {
263 public:
264 explicit ALWAYS_INLINE StackHandleScope(Thread* self, mirror::Object* fill_value = nullptr);
265 ALWAYS_INLINE ~StackHandleScope();
266
267 Thread* Self() const {
268 return self_;
269 }
270
271 private:
Ian Rogers22d5e732014-07-15 22:23:51 -0700272 // The thread that the stack handle scope is a linked list upon. The stack handle scope will
273 // push and pop itself from this thread.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700274 Thread* const self_;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700275};
276
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700277// Utility class to manage a variable sized handle scope by having a list of fixed size handle
278// scopes.
279// Calls to NewHandle will create a new handle inside the current FixedSizeHandleScope.
280// When the current handle scope becomes full a new one is created and put at the front of the
281// list.
282class VariableSizedHandleScope : public BaseHandleScope {
Calin Juravleacf735c2015-02-12 15:25:22 +0000283 public:
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700284 explicit VariableSizedHandleScope(Thread* const self);
285 ~VariableSizedHandleScope();
Calin Juravleacf735c2015-02-12 15:25:22 +0000286
287 template<class T>
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700288 MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_);
Calin Juravleacf735c2015-02-12 15:25:22 +0000289
Andreas Gampec73cb642017-02-22 10:11:30 -0800290 template<class MirrorType>
291 MutableHandle<MirrorType> NewHandle(ObjPtr<MirrorType> ptr)
Mathieu Chartier3398c782016-09-30 10:27:43 -0700292 REQUIRES_SHARED(Locks::mutator_lock_);
293
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700294 // Number of references contained within this handle scope.
295 ALWAYS_INLINE uint32_t NumberOfReferences() const;
296
297 ALWAYS_INLINE bool Contains(StackReference<mirror::Object>* handle_scope_entry) const;
298
299 template <typename Visitor>
300 void VisitRoots(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_);
301
Calin Juravleacf735c2015-02-12 15:25:22 +0000302 private:
Vladimir Marko26248c72017-02-21 17:00:28 +0000303 static constexpr size_t kLocalScopeSize = 64u;
304 static constexpr size_t kSizeOfReferencesPerScope =
305 kLocalScopeSize
306 - /* BaseHandleScope::link_ */ sizeof(BaseHandleScope*)
307 - /* BaseHandleScope::number_of_references_ */ sizeof(int32_t)
308 - /* FixedSizeHandleScope<>::pos_ */ sizeof(uint32_t);
309 static constexpr size_t kNumReferencesPerScope =
310 kSizeOfReferencesPerScope / sizeof(StackReference<mirror::Object>);
Calin Juravleacf735c2015-02-12 15:25:22 +0000311
312 Thread* const self_;
313
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700314 // Linked list of fixed size handle scopes.
315 using LocalScopeType = FixedSizeHandleScope<kNumReferencesPerScope>;
Vladimir Marko26248c72017-02-21 17:00:28 +0000316 static_assert(sizeof(LocalScopeType) == kLocalScopeSize, "Unexpected size of LocalScopeType");
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700317 LocalScopeType* current_scope_;
Calin Juravleacf735c2015-02-12 15:25:22 +0000318
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700319 DISALLOW_COPY_AND_ASSIGN(VariableSizedHandleScope);
Calin Juravleacf735c2015-02-12 15:25:22 +0000320};
321
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700322} // namespace art
323
324#endif // ART_RUNTIME_HANDLE_SCOPE_H_