blob: 2b283ae3dfe4eb1980fa1ae6bc8a16c68237cfbc [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 Gampe542451c2016-07-26 09:02:02 -070022#include "base/enums.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070023#include "base/logging.h"
24#include "base/macros.h"
Vladimir Marko3a21e382016-09-02 12:38:38 +010025#include "base/mutex.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070026#include "handle.h"
Vladimir Marko3a21e382016-09-02 12:38:38 +010027#include "stack_reference.h"
Mathieu Chartier3e0acf62015-01-08 09:41:25 -080028#include "verify_object.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070029
30namespace art {
Mathieu Chartier0795f232016-09-27 18:43:30 -070031
32template<class MirrorType, bool kPoison> class ObjPtr;
33
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070034namespace mirror {
35class Object;
36}
Ian Rogerse63db272014-07-15 15:36:11 -070037
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070038class Thread;
39
Ian Rogers22d5e732014-07-15 22:23:51 -070040// HandleScopes are scoped objects containing a number of Handles. They are used to allocate
41// handles, for these handles (and the objects contained within them) to be visible/roots for the
42// GC. It is most common to stack allocate HandleScopes using StackHandleScope.
Mathieu Chartierbc56fc32014-06-03 15:37:03 -070043class PACKED(4) HandleScope {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070044 public:
45 ~HandleScope() {}
46
47 // Number of references contained within this handle scope.
48 uint32_t NumberOfReferences() const {
49 return number_of_references_;
50 }
51
52 // We have versions with and without explicit pointer size of the following. The first two are
53 // used at runtime, so OFFSETOF_MEMBER computes the right offsets automatically. The last one
54 // takes the pointer size explicitly so that at compile time we can cross-compile correctly.
55
56 // Returns the size of a HandleScope containing num_references handles.
Mathieu Chartier3e0acf62015-01-08 09:41:25 -080057 static size_t SizeOf(uint32_t num_references);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070058
Andreas Gampecf4035a2014-05-28 22:43:01 -070059 // Returns the size of a HandleScope containing num_references handles.
Andreas Gampe542451c2016-07-26 09:02:02 -070060 static size_t SizeOf(PointerSize pointer_size, uint32_t num_references);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070061
62 // Link to previous HandleScope or null.
63 HandleScope* GetLink() const {
64 return link_;
65 }
66
Ian Rogers59c07062014-10-10 13:03:39 -070067 ALWAYS_INLINE mirror::Object* GetReference(size_t i) const
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070068 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070069
Vladimir Markof39745e2016-01-26 12:16:55 +000070 ALWAYS_INLINE Handle<mirror::Object> GetHandle(size_t i);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070071
Ian Rogers59c07062014-10-10 13:03:39 -070072 ALWAYS_INLINE MutableHandle<mirror::Object> GetMutableHandle(size_t i)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070073 REQUIRES_SHARED(Locks::mutator_lock_);
Andreas Gampe5a4b8a22014-09-11 08:30:08 -070074
Ian Rogers59c07062014-10-10 13:03:39 -070075 ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -070076 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070077
Mathieu Chartier3e0acf62015-01-08 09:41:25 -080078 ALWAYS_INLINE bool Contains(StackReference<mirror::Object>* handle_scope_entry) const;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070079
Ian Rogers59c07062014-10-10 13:03:39 -070080 // Offset of link within HandleScope, used by generated code.
Andreas Gampe542451c2016-07-26 09:02:02 -070081 static constexpr size_t LinkOffset(PointerSize pointer_size ATTRIBUTE_UNUSED) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070082 return 0;
83 }
84
Ian Rogers59c07062014-10-10 13:03:39 -070085 // Offset of length within handle scope, used by generated code.
Andreas Gampe542451c2016-07-26 09:02:02 -070086 static constexpr size_t NumberOfReferencesOffset(PointerSize pointer_size) {
87 return static_cast<size_t>(pointer_size);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070088 }
89
Ian Rogers59c07062014-10-10 13:03:39 -070090 // Offset of link within handle scope, used by generated code.
Andreas Gampe542451c2016-07-26 09:02:02 -070091 static constexpr size_t ReferencesOffset(PointerSize pointer_size) {
92 return NumberOfReferencesOffset(pointer_size) + sizeof(number_of_references_);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070093 }
94
Ian Rogers59c07062014-10-10 13:03:39 -070095 // Placement new creation.
96 static HandleScope* Create(void* storage, HandleScope* link, uint32_t num_references)
97 WARN_UNUSED {
98 return new (storage) HandleScope(link, num_references);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070099 }
100
Ian Rogers59c07062014-10-10 13:03:39 -0700101 protected:
102 // Return backing storage used for references.
103 ALWAYS_INLINE StackReference<mirror::Object>* GetReferences() const {
Andreas Gampe542451c2016-07-26 09:02:02 -0700104 uintptr_t address = reinterpret_cast<uintptr_t>(this) + ReferencesOffset(kRuntimePointerSize);
Ian Rogers59c07062014-10-10 13:03:39 -0700105 return reinterpret_cast<StackReference<mirror::Object>*>(address);
106 }
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700107
Mathieu Chartierd035c2d2014-10-27 17:30:20 -0700108 explicit HandleScope(size_t number_of_references) :
109 link_(nullptr), number_of_references_(number_of_references) {
110 }
111
Ian Rogers59c07062014-10-10 13:03:39 -0700112 // Semi-hidden constructor. Construction expected by generated code and StackHandleScope.
Roland Levillain3887c462015-08-12 18:15:42 +0100113 HandleScope(HandleScope* link, uint32_t num_references) :
Ian Rogers59c07062014-10-10 13:03:39 -0700114 link_(link), number_of_references_(num_references) {
115 }
116
117 // Link-list of handle scopes. The root is held by a Thread.
118 HandleScope* const link_;
119
120 // Number of handlerized references.
121 const uint32_t number_of_references_;
122
123 // Storage for references.
124 // StackReference<mirror::Object> references_[number_of_references_]
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700125
126 private:
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700127 DISALLOW_COPY_AND_ASSIGN(HandleScope);
128};
129
130// A wrapper which wraps around Object** and restores the pointer in the destructor.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700131// TODO: Delete
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700132template<class T>
Andreas Gampe5a4b8a22014-09-11 08:30:08 -0700133class HandleWrapper : public MutableHandle<T> {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700134 public:
Andreas Gampe5a4b8a22014-09-11 08:30:08 -0700135 HandleWrapper(T** obj, const MutableHandle<T>& handle)
136 : MutableHandle<T>(handle), obj_(obj) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700137 }
138
Andreas Gampe758a8012015-04-03 21:28:42 -0700139 HandleWrapper(const HandleWrapper&) = default;
140
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700141 ~HandleWrapper() {
Andreas Gampe5a4b8a22014-09-11 08:30:08 -0700142 *obj_ = MutableHandle<T>::Get();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700143 }
144
145 private:
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700146 T** const obj_;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700147};
148
Mathieu Chartier0795f232016-09-27 18:43:30 -0700149
150// A wrapper which wraps around ObjPtr<Object>* and restores the pointer in the destructor.
151// TODO: Add more functionality.
152template<class T>
153class HandleWrapperObjPtr : public MutableHandle<T> {
154 public:
155 HandleWrapperObjPtr(ObjPtr<T>* obj, const MutableHandle<T>& handle)
156 : MutableHandle<T>(handle), obj_(obj) {}
157
158 HandleWrapperObjPtr(const HandleWrapperObjPtr&) = default;
159
160 ~HandleWrapperObjPtr() {
161 *obj_ = ObjPtr<T>(MutableHandle<T>::Get());
162 }
163
164 private:
165 ObjPtr<T>* const obj_;
166};
167
168
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700169// Scoped handle storage of a fixed size that is usually stack allocated.
170template<size_t kNumReferences>
Ian Rogers22d5e732014-07-15 22:23:51 -0700171class PACKED(4) StackHandleScope FINAL : public HandleScope {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700172 public:
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700173 explicit ALWAYS_INLINE StackHandleScope(Thread* self, mirror::Object* fill_value = nullptr);
174 ALWAYS_INLINE ~StackHandleScope();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700175
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700176 template<class T>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700177 ALWAYS_INLINE MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbc56fc32014-06-03 15:37:03 -0700178
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700179 template<class T>
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700180 ALWAYS_INLINE HandleWrapper<T> NewHandleWrapper(T** object)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700181 REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700182
Mathieu Chartier0795f232016-09-27 18:43:30 -0700183 template<class T>
184 ALWAYS_INLINE HandleWrapperObjPtr<T> NewHandleWrapper(ObjPtr<T>* object)
185 REQUIRES_SHARED(Locks::mutator_lock_);
186
187 template<class MirrorType, bool kPoison>
188 ALWAYS_INLINE MutableHandle<MirrorType> NewHandle(ObjPtr<MirrorType, kPoison> object)
189 REQUIRES_SHARED(Locks::mutator_lock_);
190
Ian Rogers59c07062014-10-10 13:03:39 -0700191 ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700192 REQUIRES_SHARED(Locks::mutator_lock_);
Mathieu Chartierbc56fc32014-06-03 15:37:03 -0700193
Mathieu Chartiere401d142015-04-22 13:56:20 -0700194 Thread* Self() const {
195 return self_;
196 }
197
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700198 private:
199 template<class T>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700200 ALWAYS_INLINE MutableHandle<T> GetHandle(size_t i) REQUIRES_SHARED(Locks::mutator_lock_) {
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700201 DCHECK_LT(i, kNumReferences);
202 return MutableHandle<T>(&GetReferences()[i]);
203 }
204
Ian Rogers59c07062014-10-10 13:03:39 -0700205 // Reference storage needs to be first as expected by the HandleScope layout.
206 StackReference<mirror::Object> storage_[kNumReferences];
Ian Rogers22d5e732014-07-15 22:23:51 -0700207
208 // The thread that the stack handle scope is a linked list upon. The stack handle scope will
209 // push and pop itself from this thread.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700210 Thread* const self_;
Ian Rogers22d5e732014-07-15 22:23:51 -0700211
212 // Position new handles will be created.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700213 size_t pos_;
214
215 template<size_t kNumRefs> friend class StackHandleScope;
216};
217
Calin Juravleacf735c2015-02-12 15:25:22 +0000218// Utility class to manage a collection (stack) of StackHandleScope. All the managed
219// scope handle have the same fixed sized.
220// Calls to NewHandle will create a new handle inside the top StackHandleScope.
221// When the handle scope becomes full a new one is created and push on top of the
222// previous.
223//
224// NB:
225// - it is not safe to use the *same* StackHandleScopeCollection intermix with
226// other StackHandleScopes.
227// - this is a an easy way around implementing a full ZoneHandleScope to manage an
228// arbitrary number of handles.
229class StackHandleScopeCollection {
230 public:
231 explicit StackHandleScopeCollection(Thread* const self) :
232 self_(self),
233 current_scope_num_refs_(0) {
234 }
235
236 ~StackHandleScopeCollection() {
237 while (!scopes_.empty()) {
238 delete scopes_.top();
239 scopes_.pop();
240 }
241 }
242
243 template<class T>
Andreas Gampebdf7f1c2016-08-30 16:38:47 -0700244 MutableHandle<T> NewHandle(T* object) REQUIRES_SHARED(Locks::mutator_lock_) {
Calin Juravleacf735c2015-02-12 15:25:22 +0000245 if (scopes_.empty() || current_scope_num_refs_ >= kNumReferencesPerScope) {
246 StackHandleScope<kNumReferencesPerScope>* scope =
247 new StackHandleScope<kNumReferencesPerScope>(self_);
248 scopes_.push(scope);
249 current_scope_num_refs_ = 0;
250 }
251 current_scope_num_refs_++;
252 return scopes_.top()->NewHandle(object);
253 }
254
255 private:
256 static constexpr size_t kNumReferencesPerScope = 4;
257
258 Thread* const self_;
259
260 std::stack<StackHandleScope<kNumReferencesPerScope>*> scopes_;
261 size_t current_scope_num_refs_;
262
263 DISALLOW_COPY_AND_ASSIGN(StackHandleScopeCollection);
264};
265
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700266} // namespace art
267
268#endif // ART_RUNTIME_HANDLE_SCOPE_H_