blob: 5a6f1ace073fd0c53bf8a7b8ff7bc451b4b53ad2 [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"
Andreas Gampe7fbc4a52018-11-28 08:26:47 -080025#include "base/locks.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070026#include "base/macros.h"
Vladimir Marko3a21e382016-09-02 12:38:38 +010027#include "stack_reference.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070028
29namespace art {
Mathieu Chartier0795f232016-09-27 18:43:30 -070030
Andreas Gampea1ffdba2019-01-04 16:08:51 -080031template<class T> class Handle;
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070032class HandleScope;
Andreas Gampea1ffdba2019-01-04 16:08:51 -080033template<class T> class HandleWrapper;
34template<class T> class HandleWrapperObjPtr;
35template<class T> class MutableHandle;
Andreas Gampec73cb642017-02-22 10:11:30 -080036template<class MirrorType> class ObjPtr;
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070037class Thread;
38class VariableSizedHandleScope;
Mathieu Chartier0795f232016-09-27 18:43:30 -070039
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070040namespace mirror {
41class Object;
Andreas Gampedeae7db2017-05-30 09:56:41 -070042} // namespace mirror
Ian Rogerse63db272014-07-15 15:36:11 -070043
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070044// Basic handle scope, tracked by a list. May be variable sized.
45class PACKED(4) BaseHandleScope {
46 public:
47 bool IsVariableSized() const {
48 return number_of_references_ == kNumReferencesVariableSized;
49 }
50
51 // Number of references contained within this handle scope.
52 ALWAYS_INLINE uint32_t NumberOfReferences() const;
53
54 ALWAYS_INLINE bool Contains(StackReference<mirror::Object>* handle_scope_entry) const;
55
56 template <typename Visitor>
57 ALWAYS_INLINE void VisitRoots(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_);
58
59 // Link to previous BaseHandleScope or null.
60 BaseHandleScope* GetLink() const {
61 return link_;
62 }
63
64 ALWAYS_INLINE VariableSizedHandleScope* AsVariableSized();
65 ALWAYS_INLINE HandleScope* AsHandleScope();
66 ALWAYS_INLINE const VariableSizedHandleScope* AsVariableSized() const;
67 ALWAYS_INLINE const HandleScope* AsHandleScope() const;
68
69 protected:
70 BaseHandleScope(BaseHandleScope* link, uint32_t num_references)
71 : link_(link),
72 number_of_references_(num_references) {}
73
74 // Variable sized constructor.
Andreas Gampeea47ff82016-11-03 08:20:17 -070075 explicit BaseHandleScope(BaseHandleScope* link)
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070076 : link_(link),
77 number_of_references_(kNumReferencesVariableSized) {}
78
79 static constexpr int32_t kNumReferencesVariableSized = -1;
80
81 // Link-list of handle scopes. The root is held by a Thread.
82 BaseHandleScope* const link_;
83
84 // Number of handlerized references. -1 for variable sized handle scopes.
85 const int32_t number_of_references_;
86
87 private:
88 DISALLOW_COPY_AND_ASSIGN(BaseHandleScope);
89};
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070090
Ian Rogers22d5e732014-07-15 22:23:51 -070091// HandleScopes are scoped objects containing a number of Handles. They are used to allocate
92// handles, for these handles (and the objects contained within them) to be visible/roots for the
93// GC. It is most common to stack allocate HandleScopes using StackHandleScope.
Mathieu Chartiere8a3c572016-10-11 16:52:17 -070094class PACKED(4) HandleScope : public BaseHandleScope {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070095 public:
96 ~HandleScope() {}
97
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070098 // We have versions with and without explicit pointer size of the following. The first two are
99 // used at runtime, so OFFSETOF_MEMBER computes the right offsets automatically. The last one
100 // takes the pointer size explicitly so that at compile time we can cross-compile correctly.
101
102 // Returns the size of a HandleScope containing num_references handles.
Mathieu Chartier3e0acf62015-01-08 09:41:25 -0800103 static size_t SizeOf(uint32_t num_references);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700104
Andreas Gampecf4035a2014-05-28 22:43:01 -0700105 // Returns the size of a HandleScope containing num_references handles.
Andreas Gampe542451c2016-07-26 09:02:02 -0700106 static size_t SizeOf(PointerSize pointer_size, uint32_t num_references);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700107
Ian Rogers59c07062014-10-10 13:03:39 -0700108 ALWAYS_INLINE mirror::Object* GetReference(size_t i) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700109 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700110
Vladimir Markof39745e2016-01-26 12:16:55 +0000111 ALWAYS_INLINE Handle<mirror::Object> GetHandle(size_t i);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700112
Ian Rogers59c07062014-10-10 13:03:39 -0700113 ALWAYS_INLINE MutableHandle<mirror::Object> GetMutableHandle(size_t i)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700114 REQUIRES_SHARED(Locks::mutator_lock_);
Andreas Gampe5a4b8a22014-09-11 08:30:08 -0700115
Ian Rogers59c07062014-10-10 13:03:39 -0700116 ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700117 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700118
Mathieu Chartier3e0acf62015-01-08 09:41:25 -0800119 ALWAYS_INLINE bool Contains(StackReference<mirror::Object>* handle_scope_entry) const;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700120
Ian Rogers59c07062014-10-10 13:03:39 -0700121 // Offset of link within HandleScope, used by generated code.
Andreas Gampe542451c2016-07-26 09:02:02 -0700122 static constexpr size_t LinkOffset(PointerSize pointer_size ATTRIBUTE_UNUSED) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700123 return 0;
124 }
125
Ian Rogers59c07062014-10-10 13:03:39 -0700126 // Offset of length within handle scope, used by generated code.
Andreas Gampe542451c2016-07-26 09:02:02 -0700127 static constexpr size_t NumberOfReferencesOffset(PointerSize pointer_size) {
128 return static_cast<size_t>(pointer_size);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700129 }
130
Ian Rogers59c07062014-10-10 13:03:39 -0700131 // Offset of link within handle scope, used by generated code.
Andreas Gampe542451c2016-07-26 09:02:02 -0700132 static constexpr size_t ReferencesOffset(PointerSize pointer_size) {
133 return NumberOfReferencesOffset(pointer_size) + sizeof(number_of_references_);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700134 }
135
Ian Rogers59c07062014-10-10 13:03:39 -0700136 // Placement new creation.
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700137 static HandleScope* Create(void* storage, BaseHandleScope* link, uint32_t num_references)
Ian Rogers59c07062014-10-10 13:03:39 -0700138 WARN_UNUSED {
139 return new (storage) HandleScope(link, num_references);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700140 }
141
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700142 // Number of references contained within this handle scope.
143 ALWAYS_INLINE uint32_t NumberOfReferences() const {
144 DCHECK_GE(number_of_references_, 0);
145 return static_cast<uint32_t>(number_of_references_);
146 }
147
148 template <typename Visitor>
Andreas Gampea1ffdba2019-01-04 16:08:51 -0800149 ALWAYS_INLINE void VisitRoots(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700150
Ian Rogers59c07062014-10-10 13:03:39 -0700151 protected:
152 // Return backing storage used for references.
153 ALWAYS_INLINE StackReference<mirror::Object>* GetReferences() const {
Andreas Gampe542451c2016-07-26 09:02:02 -0700154 uintptr_t address = reinterpret_cast<uintptr_t>(this) + ReferencesOffset(kRuntimePointerSize);
Ian Rogers59c07062014-10-10 13:03:39 -0700155 return reinterpret_cast<StackReference<mirror::Object>*>(address);
156 }
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700157
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700158 explicit HandleScope(size_t number_of_references) : HandleScope(nullptr, number_of_references) {}
Mathieu Chartierd035c2d2014-10-27 17:30:20 -0700159
Ian Rogers59c07062014-10-10 13:03:39 -0700160 // Semi-hidden constructor. Construction expected by generated code and StackHandleScope.
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700161 HandleScope(BaseHandleScope* link, uint32_t num_references)
162 : BaseHandleScope(link, num_references) {}
Ian Rogers59c07062014-10-10 13:03:39 -0700163
164 // Storage for references.
165 // StackReference<mirror::Object> references_[number_of_references_]
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700166
167 private:
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700168 DISALLOW_COPY_AND_ASSIGN(HandleScope);
169};
170
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700171// Fixed size handle scope that is not necessarily linked in the thread.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700172template<size_t kNumReferences>
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700173class PACKED(4) FixedSizeHandleScope : public HandleScope {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700174 public:
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700175 template<class T>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700176 ALWAYS_INLINE MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbc56fc32014-06-03 15:37:03 -0700177
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700178 template<class T>
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700179 ALWAYS_INLINE HandleWrapper<T> NewHandleWrapper(T** object)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700180 REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700181
Mathieu Chartier0795f232016-09-27 18:43:30 -0700182 template<class T>
183 ALWAYS_INLINE HandleWrapperObjPtr<T> NewHandleWrapper(ObjPtr<T>* object)
184 REQUIRES_SHARED(Locks::mutator_lock_);
185
Andreas Gampec73cb642017-02-22 10:11:30 -0800186 template<class MirrorType>
187 ALWAYS_INLINE MutableHandle<MirrorType> NewHandle(ObjPtr<MirrorType> object)
Mathieu Chartier0795f232016-09-27 18:43:30 -0700188 REQUIRES_SHARED(Locks::mutator_lock_);
189
Ian Rogers59c07062014-10-10 13:03:39 -0700190 ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700191 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbc56fc32014-06-03 15:37:03 -0700192
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700193 size_t RemainingSlots() const {
194 return kNumReferences - pos_;
Mathieu Chartiere401d142015-04-22 13:56:20 -0700195 }
196
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700197 private:
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700198 explicit ALWAYS_INLINE FixedSizeHandleScope(BaseHandleScope* link,
199 mirror::Object* fill_value = nullptr);
200 ALWAYS_INLINE ~FixedSizeHandleScope() {}
201
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700202 template<class T>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700203 ALWAYS_INLINE MutableHandle<T> GetHandle(size_t i) REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700204 DCHECK_LT(i, kNumReferences);
205 return MutableHandle<T>(&GetReferences()[i]);
206 }
207
Ian Rogers59c07062014-10-10 13:03:39 -0700208 // Reference storage needs to be first as expected by the HandleScope layout.
209 StackReference<mirror::Object> storage_[kNumReferences];
Ian Rogers22d5e732014-07-15 22:23:51 -0700210
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700211 // Position new handles will be created.
Vladimir Marko26248c72017-02-21 17:00:28 +0000212 uint32_t pos_ = 0;
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700213
214 template<size_t kNumRefs> friend class StackHandleScope;
215 friend class VariableSizedHandleScope;
216};
217
218// Scoped handle storage of a fixed size that is stack allocated.
219template<size_t kNumReferences>
Roland Levillainbbc6e7e2018-08-24 16:58:47 +0100220class PACKED(4) StackHandleScope final : public FixedSizeHandleScope<kNumReferences> {
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700221 public:
222 explicit ALWAYS_INLINE StackHandleScope(Thread* self, mirror::Object* fill_value = nullptr);
223 ALWAYS_INLINE ~StackHandleScope();
224
225 Thread* Self() const {
226 return self_;
227 }
228
229 private:
Ian Rogers22d5e732014-07-15 22:23:51 -0700230 // The thread that the stack handle scope is a linked list upon. The stack handle scope will
231 // push and pop itself from this thread.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700232 Thread* const self_;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700233};
234
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700235// Utility class to manage a variable sized handle scope by having a list of fixed size handle
236// scopes.
237// Calls to NewHandle will create a new handle inside the current FixedSizeHandleScope.
238// When the current handle scope becomes full a new one is created and put at the front of the
239// list.
240class VariableSizedHandleScope : public BaseHandleScope {
Calin Juravleacf735c2015-02-12 15:25:22 +0000241 public:
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700242 explicit VariableSizedHandleScope(Thread* const self);
243 ~VariableSizedHandleScope();
Calin Juravleacf735c2015-02-12 15:25:22 +0000244
245 template<class T>
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700246 MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_);
Calin Juravleacf735c2015-02-12 15:25:22 +0000247
Andreas Gampec73cb642017-02-22 10:11:30 -0800248 template<class MirrorType>
249 MutableHandle<MirrorType> NewHandle(ObjPtr<MirrorType> ptr)
Mathieu Chartier3398c782016-09-30 10:27:43 -0700250 REQUIRES_SHARED(Locks::mutator_lock_);
251
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700252 // Number of references contained within this handle scope.
253 ALWAYS_INLINE uint32_t NumberOfReferences() const;
254
255 ALWAYS_INLINE bool Contains(StackReference<mirror::Object>* handle_scope_entry) const;
256
257 template <typename Visitor>
258 void VisitRoots(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_);
259
Calin Juravleacf735c2015-02-12 15:25:22 +0000260 private:
Alex Lightde7718d2019-01-14 10:13:40 -0800261 static constexpr size_t kMaxLocalScopeSize = 64u;
262 // In order to have consistent compilation with both 32bit and 64bit dex2oat
263 // binaries we need this to be an actual constant. We picked this because it
264 // will ensure that we use <64bit internal scopes.
265 static constexpr size_t kNumReferencesPerScope = 12u;
Calin Juravleacf735c2015-02-12 15:25:22 +0000266
267 Thread* const self_;
268
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700269 // Linked list of fixed size handle scopes.
270 using LocalScopeType = FixedSizeHandleScope<kNumReferencesPerScope>;
Alex Lightde7718d2019-01-14 10:13:40 -0800271 static_assert(sizeof(LocalScopeType) <= kMaxLocalScopeSize, "Unexpected size of LocalScopeType");
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700272 LocalScopeType* current_scope_;
Calin Juravleacf735c2015-02-12 15:25:22 +0000273
Mathieu Chartiere8a3c572016-10-11 16:52:17 -0700274 DISALLOW_COPY_AND_ASSIGN(VariableSizedHandleScope);
Calin Juravleacf735c2015-02-12 15:25:22 +0000275};
276
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700277} // namespace art
278
279#endif // ART_RUNTIME_HANDLE_SCOPE_H_