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_SCOPE_INL_H_
18 #define ART_RUNTIME_HANDLE_SCOPE_INL_H_
19
20 #include "handle_scope.h"
21
22 #include "base/mutex.h"
23 #include "handle.h"
24 #include "handle_wrapper.h"
25 #include "obj_ptr-inl.h"
26 #include "thread-current-inl.h"
27 #include "verify_object.h"
28
29 namespace art {
30
31 template<size_t kNumReferences>
FixedSizeHandleScope(BaseHandleScope * link,mirror::Object * fill_value)32 inline FixedSizeHandleScope<kNumReferences>::FixedSizeHandleScope(BaseHandleScope* link,
33 mirror::Object* fill_value)
34 : HandleScope(link, kNumReferences) {
35 if (kDebugLocking) {
36 Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
37 }
38 static_assert(kNumReferences >= 1, "FixedSizeHandleScope must contain at least 1 reference");
39 DCHECK_EQ(&storage_[0], GetReferences()); // TODO: Figure out how to use a compile assert.
40 for (size_t i = 0; i < kNumReferences; ++i) {
41 SetReference(i, fill_value);
42 }
43 }
44
45 template<size_t kNumReferences>
StackHandleScope(Thread * self,mirror::Object * fill_value)46 inline StackHandleScope<kNumReferences>::StackHandleScope(Thread* self, mirror::Object* fill_value)
47 : FixedSizeHandleScope<kNumReferences>(self->GetTopHandleScope(), fill_value),
48 self_(self) {
49 DCHECK_EQ(self, Thread::Current());
50 self_->PushHandleScope(this);
51 }
52
53 template<size_t kNumReferences>
~StackHandleScope()54 inline StackHandleScope<kNumReferences>::~StackHandleScope() {
55 BaseHandleScope* top_handle_scope = self_->PopHandleScope();
56 DCHECK_EQ(top_handle_scope, this);
57 if (kDebugLocking) {
58 Locks::mutator_lock_->AssertSharedHeld(self_);
59 }
60 }
61
SizeOf(uint32_t num_references)62 inline size_t HandleScope::SizeOf(uint32_t num_references) {
63 size_t header_size = sizeof(HandleScope);
64 size_t data_size = sizeof(StackReference<mirror::Object>) * num_references;
65 return header_size + data_size;
66 }
67
SizeOf(PointerSize pointer_size,uint32_t num_references)68 inline size_t HandleScope::SizeOf(PointerSize pointer_size, uint32_t num_references) {
69 // Assume that the layout is packed.
70 size_t header_size = ReferencesOffset(pointer_size);
71 size_t data_size = sizeof(StackReference<mirror::Object>) * num_references;
72 return header_size + data_size;
73 }
74
GetReference(size_t i)75 inline mirror::Object* HandleScope::GetReference(size_t i) const {
76 DCHECK_LT(i, NumberOfReferences());
77 if (kDebugLocking) {
78 Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
79 }
80 return GetReferences()[i].AsMirrorPtr();
81 }
82
GetHandle(size_t i)83 inline Handle<mirror::Object> HandleScope::GetHandle(size_t i) {
84 DCHECK_LT(i, NumberOfReferences());
85 return Handle<mirror::Object>(&GetReferences()[i]);
86 }
87
GetMutableHandle(size_t i)88 inline MutableHandle<mirror::Object> HandleScope::GetMutableHandle(size_t i) {
89 DCHECK_LT(i, NumberOfReferences());
90 return MutableHandle<mirror::Object>(&GetReferences()[i]);
91 }
92
SetReference(size_t i,mirror::Object * object)93 inline void HandleScope::SetReference(size_t i, mirror::Object* object) {
94 if (kDebugLocking) {
95 Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
96 }
97 DCHECK_LT(i, NumberOfReferences());
98 GetReferences()[i].Assign(object);
99 }
100
Contains(StackReference<mirror::Object> * handle_scope_entry)101 inline bool HandleScope::Contains(StackReference<mirror::Object>* handle_scope_entry) const {
102 // A HandleScope should always contain something. One created by the
103 // jni_compiler should have a jobject/jclass as a native method is
104 // passed in a this pointer or a class
105 DCHECK_GT(NumberOfReferences(), 0U);
106 return &GetReferences()[0] <= handle_scope_entry &&
107 handle_scope_entry <= &GetReferences()[number_of_references_ - 1];
108 }
109
110 template <typename Visitor>
VisitRoots(Visitor & visitor)111 inline void HandleScope::VisitRoots(Visitor& visitor) {
112 for (size_t i = 0, count = NumberOfReferences(); i < count; ++i) {
113 // GetReference returns a pointer to the stack reference within the handle scope. If this
114 // needs to be updated, it will be done by the root visitor.
115 visitor.VisitRootIfNonNull(GetHandle(i).GetReference());
116 }
117 }
118
119 template<size_t kNumReferences> template<class T>
NewHandle(T * object)120 inline MutableHandle<T> FixedSizeHandleScope<kNumReferences>::NewHandle(T* object) {
121 SetReference(pos_, object);
122 MutableHandle<T> h(GetHandle<T>(pos_));
123 pos_++;
124 return h;
125 }
126
127 template<size_t kNumReferences> template<class MirrorType>
NewHandle(ObjPtr<MirrorType> object)128 inline MutableHandle<MirrorType> FixedSizeHandleScope<kNumReferences>::NewHandle(
129 ObjPtr<MirrorType> object) {
130 return NewHandle(object.Ptr());
131 }
132
133 template<size_t kNumReferences> template<class T>
NewHandleWrapper(T ** object)134 inline HandleWrapper<T> FixedSizeHandleScope<kNumReferences>::NewHandleWrapper(T** object) {
135 return HandleWrapper<T>(object, NewHandle(*object));
136 }
137
138 template<size_t kNumReferences> template<class T>
NewHandleWrapper(ObjPtr<T> * object)139 inline HandleWrapperObjPtr<T> FixedSizeHandleScope<kNumReferences>::NewHandleWrapper(
140 ObjPtr<T>* object) {
141 return HandleWrapperObjPtr<T>(object, NewHandle(*object));
142 }
143
144 template<size_t kNumReferences>
SetReference(size_t i,mirror::Object * object)145 inline void FixedSizeHandleScope<kNumReferences>::SetReference(size_t i, mirror::Object* object) {
146 if (kDebugLocking) {
147 Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
148 }
149 DCHECK_LT(i, kNumReferences);
150 VerifyObject(object);
151 GetReferences()[i].Assign(object);
152 }
153
154 // Number of references contained within this handle scope.
NumberOfReferences()155 inline uint32_t BaseHandleScope::NumberOfReferences() const {
156 return LIKELY(!IsVariableSized())
157 ? AsHandleScope()->NumberOfReferences()
158 : AsVariableSized()->NumberOfReferences();
159 }
160
Contains(StackReference<mirror::Object> * handle_scope_entry)161 inline bool BaseHandleScope::Contains(StackReference<mirror::Object>* handle_scope_entry) const {
162 return LIKELY(!IsVariableSized())
163 ? AsHandleScope()->Contains(handle_scope_entry)
164 : AsVariableSized()->Contains(handle_scope_entry);
165 }
166
167 template <typename Visitor>
VisitRoots(Visitor & visitor)168 inline void BaseHandleScope::VisitRoots(Visitor& visitor) {
169 if (LIKELY(!IsVariableSized())) {
170 AsHandleScope()->VisitRoots(visitor);
171 } else {
172 AsVariableSized()->VisitRoots(visitor);
173 }
174 }
175
AsVariableSized()176 inline VariableSizedHandleScope* BaseHandleScope::AsVariableSized() {
177 DCHECK(IsVariableSized());
178 return down_cast<VariableSizedHandleScope*>(this);
179 }
180
AsHandleScope()181 inline HandleScope* BaseHandleScope::AsHandleScope() {
182 DCHECK(!IsVariableSized());
183 return down_cast<HandleScope*>(this);
184 }
185
AsVariableSized()186 inline const VariableSizedHandleScope* BaseHandleScope::AsVariableSized() const {
187 DCHECK(IsVariableSized());
188 return down_cast<const VariableSizedHandleScope*>(this);
189 }
190
AsHandleScope()191 inline const HandleScope* BaseHandleScope::AsHandleScope() const {
192 DCHECK(!IsVariableSized());
193 return down_cast<const HandleScope*>(this);
194 }
195
196 template<class T>
NewHandle(T * object)197 MutableHandle<T> VariableSizedHandleScope::NewHandle(T* object) {
198 if (current_scope_->RemainingSlots() == 0) {
199 current_scope_ = new LocalScopeType(current_scope_);
200 }
201 return current_scope_->NewHandle(object);
202 }
203
204 template<class MirrorType>
NewHandle(ObjPtr<MirrorType> ptr)205 inline MutableHandle<MirrorType> VariableSizedHandleScope::NewHandle(ObjPtr<MirrorType> ptr) {
206 return NewHandle(ptr.Ptr());
207 }
208
VariableSizedHandleScope(Thread * const self)209 inline VariableSizedHandleScope::VariableSizedHandleScope(Thread* const self)
210 : BaseHandleScope(self->GetTopHandleScope()),
211 self_(self) {
212 current_scope_ = new LocalScopeType(/*link=*/ nullptr);
213 self_->PushHandleScope(this);
214 }
215
~VariableSizedHandleScope()216 inline VariableSizedHandleScope::~VariableSizedHandleScope() {
217 BaseHandleScope* top_handle_scope = self_->PopHandleScope();
218 DCHECK_EQ(top_handle_scope, this);
219 while (current_scope_ != nullptr) {
220 LocalScopeType* next = reinterpret_cast<LocalScopeType*>(current_scope_->GetLink());
221 delete current_scope_;
222 current_scope_ = next;
223 }
224 }
225
NumberOfReferences()226 inline uint32_t VariableSizedHandleScope::NumberOfReferences() const {
227 uint32_t sum = 0;
228 const LocalScopeType* cur = current_scope_;
229 while (cur != nullptr) {
230 sum += cur->NumberOfReferences();
231 cur = reinterpret_cast<const LocalScopeType*>(cur->GetLink());
232 }
233 return sum;
234 }
235
Contains(StackReference<mirror::Object> * handle_scope_entry)236 inline bool VariableSizedHandleScope::Contains(StackReference<mirror::Object>* handle_scope_entry)
237 const {
238 const LocalScopeType* cur = current_scope_;
239 while (cur != nullptr) {
240 if (cur->Contains(handle_scope_entry)) {
241 return true;
242 }
243 cur = reinterpret_cast<const LocalScopeType*>(cur->GetLink());
244 }
245 return false;
246 }
247
248 template <typename Visitor>
VisitRoots(Visitor & visitor)249 inline void VariableSizedHandleScope::VisitRoots(Visitor& visitor) {
250 LocalScopeType* cur = current_scope_;
251 while (cur != nullptr) {
252 cur->VisitRoots(visitor);
253 cur = reinterpret_cast<LocalScopeType*>(cur->GetLink());
254 }
255 }
256
257
258 } // namespace art
259
260 #endif // ART_RUNTIME_HANDLE_SCOPE_INL_H_
261