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