blob: 782bbeaabcb9974e9b729584da6af1248fdb8a51 [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
20#include "base/logging.h"
21#include "base/macros.h"
22#include "handle.h"
23#include "stack.h"
24#include "utils.h"
Mathieu Chartier3e0acf62015-01-08 09:41:25 -080025#include "verify_object.h"
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070026
27namespace art {
28namespace mirror {
29class Object;
30}
Ian Rogerse63db272014-07-15 15:36:11 -070031
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070032class Thread;
33
Ian Rogers22d5e732014-07-15 22:23:51 -070034// HandleScopes are scoped objects containing a number of Handles. They are used to allocate
35// handles, for these handles (and the objects contained within them) to be visible/roots for the
36// GC. It is most common to stack allocate HandleScopes using StackHandleScope.
Mathieu Chartierbc56fc32014-06-03 15:37:03 -070037class PACKED(4) HandleScope {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070038 public:
39 ~HandleScope() {}
40
41 // Number of references contained within this handle scope.
42 uint32_t NumberOfReferences() const {
43 return number_of_references_;
44 }
45
46 // We have versions with and without explicit pointer size of the following. The first two are
47 // used at runtime, so OFFSETOF_MEMBER computes the right offsets automatically. The last one
48 // takes the pointer size explicitly so that at compile time we can cross-compile correctly.
49
50 // Returns the size of a HandleScope containing num_references handles.
Mathieu Chartier3e0acf62015-01-08 09:41:25 -080051 static size_t SizeOf(uint32_t num_references);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070052
Andreas Gampecf4035a2014-05-28 22:43:01 -070053 // Returns the size of a HandleScope containing num_references handles.
Mathieu Chartier3e0acf62015-01-08 09:41:25 -080054 static size_t SizeOf(size_t pointer_size, uint32_t num_references);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070055
56 // Link to previous HandleScope or null.
57 HandleScope* GetLink() const {
58 return link_;
59 }
60
Ian Rogers59c07062014-10-10 13:03:39 -070061 ALWAYS_INLINE mirror::Object* GetReference(size_t i) const
Mathieu Chartier3e0acf62015-01-08 09:41:25 -080062 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070063
Ian Rogers59c07062014-10-10 13:03:39 -070064 ALWAYS_INLINE Handle<mirror::Object> GetHandle(size_t i)
Mathieu Chartier3e0acf62015-01-08 09:41:25 -080065 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070066
Ian Rogers59c07062014-10-10 13:03:39 -070067 ALWAYS_INLINE MutableHandle<mirror::Object> GetMutableHandle(size_t i)
Mathieu Chartier3e0acf62015-01-08 09:41:25 -080068 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Andreas Gampe5a4b8a22014-09-11 08:30:08 -070069
Ian Rogers59c07062014-10-10 13:03:39 -070070 ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
Mathieu Chartier3e0acf62015-01-08 09:41:25 -080071 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070072
Mathieu Chartier3e0acf62015-01-08 09:41:25 -080073 ALWAYS_INLINE bool Contains(StackReference<mirror::Object>* handle_scope_entry) const;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070074
Ian Rogers59c07062014-10-10 13:03:39 -070075 // Offset of link within HandleScope, used by generated code.
Ian Rogers6a3c1fc2014-10-31 00:33:20 -070076 static size_t LinkOffset(size_t pointer_size ATTRIBUTE_UNUSED) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070077 return 0;
78 }
79
Ian Rogers59c07062014-10-10 13:03:39 -070080 // Offset of length within handle scope, used by generated code.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070081 static size_t NumberOfReferencesOffset(size_t pointer_size) {
82 return pointer_size;
83 }
84
Ian Rogers59c07062014-10-10 13:03:39 -070085 // Offset of link within handle scope, used by generated code.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070086 static size_t ReferencesOffset(size_t pointer_size) {
87 return pointer_size + sizeof(number_of_references_);
88 }
89
Ian Rogers59c07062014-10-10 13:03:39 -070090 // Placement new creation.
91 static HandleScope* Create(void* storage, HandleScope* link, uint32_t num_references)
92 WARN_UNUSED {
93 return new (storage) HandleScope(link, num_references);
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070094 }
95
Ian Rogers59c07062014-10-10 13:03:39 -070096 protected:
97 // Return backing storage used for references.
98 ALWAYS_INLINE StackReference<mirror::Object>* GetReferences() const {
99 uintptr_t address = reinterpret_cast<uintptr_t>(this) + ReferencesOffset(sizeof(void*));
100 return reinterpret_cast<StackReference<mirror::Object>*>(address);
101 }
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700102
Mathieu Chartierd035c2d2014-10-27 17:30:20 -0700103 explicit HandleScope(size_t number_of_references) :
104 link_(nullptr), number_of_references_(number_of_references) {
105 }
106
Ian Rogers59c07062014-10-10 13:03:39 -0700107 // Semi-hidden constructor. Construction expected by generated code and StackHandleScope.
108 explicit HandleScope(HandleScope* link, uint32_t num_references) :
109 link_(link), number_of_references_(num_references) {
110 }
111
112 // Link-list of handle scopes. The root is held by a Thread.
113 HandleScope* const link_;
114
115 // Number of handlerized references.
116 const uint32_t number_of_references_;
117
118 // Storage for references.
119 // StackReference<mirror::Object> references_[number_of_references_]
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700120
121 private:
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700122 DISALLOW_COPY_AND_ASSIGN(HandleScope);
123};
124
125// A wrapper which wraps around Object** and restores the pointer in the destructor.
126// TODO: Add more functionality.
127template<class T>
Andreas Gampe5a4b8a22014-09-11 08:30:08 -0700128class HandleWrapper : public MutableHandle<T> {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700129 public:
Andreas Gampe5a4b8a22014-09-11 08:30:08 -0700130 HandleWrapper(T** obj, const MutableHandle<T>& handle)
131 : MutableHandle<T>(handle), obj_(obj) {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700132 }
133
134 ~HandleWrapper() {
Andreas Gampe5a4b8a22014-09-11 08:30:08 -0700135 *obj_ = MutableHandle<T>::Get();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700136 }
137
138 private:
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700139 T** const obj_;
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700140};
141
142// Scoped handle storage of a fixed size that is usually stack allocated.
143template<size_t kNumReferences>
Ian Rogers22d5e732014-07-15 22:23:51 -0700144class PACKED(4) StackHandleScope FINAL : public HandleScope {
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700145 public:
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700146 explicit ALWAYS_INLINE StackHandleScope(Thread* self, mirror::Object* fill_value = nullptr);
147 ALWAYS_INLINE ~StackHandleScope();
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700148
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700149 template<class T>
Mathieu Chartier3e0acf62015-01-08 09:41:25 -0800150 ALWAYS_INLINE MutableHandle<T> NewHandle(T* object) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Mathieu Chartierbc56fc32014-06-03 15:37:03 -0700151
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700152 template<class T>
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700153 ALWAYS_INLINE HandleWrapper<T> NewHandleWrapper(T** object)
Mathieu Chartier3e0acf62015-01-08 09:41:25 -0800154 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Ian Rogersb5cb18a2014-10-21 15:05:36 -0700155
Ian Rogers59c07062014-10-10 13:03:39 -0700156 ALWAYS_INLINE void SetReference(size_t i, mirror::Object* object)
Mathieu Chartier3e0acf62015-01-08 09:41:25 -0800157 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
Mathieu Chartierbc56fc32014-06-03 15:37:03 -0700158
Mathieu Chartier2d2621a2014-10-23 16:48:06 -0700159 private:
160 template<class T>
161 ALWAYS_INLINE MutableHandle<T> GetHandle(size_t i) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
162 DCHECK_LT(i, kNumReferences);
163 return MutableHandle<T>(&GetReferences()[i]);
164 }
165
Ian Rogers59c07062014-10-10 13:03:39 -0700166 // Reference storage needs to be first as expected by the HandleScope layout.
167 StackReference<mirror::Object> storage_[kNumReferences];
Ian Rogers22d5e732014-07-15 22:23:51 -0700168
169 // The thread that the stack handle scope is a linked list upon. The stack handle scope will
170 // push and pop itself from this thread.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700171 Thread* const self_;
Ian Rogers22d5e732014-07-15 22:23:51 -0700172
173 // Position new handles will be created.
Mathieu Chartiereb8167a2014-05-07 15:43:14 -0700174 size_t pos_;
175
176 template<size_t kNumRefs> friend class StackHandleScope;
177};
178
179} // namespace art
180
181#endif // ART_RUNTIME_HANDLE_SCOPE_H_