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 28namespace art { 29 30template<size_t kNumReferences> 31inline 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 44template<size_t kNumReferences> 45inline 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 52template<size_t kNumReferences> 53inline 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 61inline 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 67inline 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 74inline 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 82inline Handle<mirror::Object> HandleScope::GetHandle(size_t i) { 83 DCHECK_LT(i, NumberOfReferences()); 84 return Handle<mirror::Object>(&GetReferences()[i]); 85} 86 87inline MutableHandle<mirror::Object> HandleScope::GetMutableHandle(size_t i) { 88 DCHECK_LT(i, NumberOfReferences()); 89 return MutableHandle<mirror::Object>(&GetReferences()[i]); 90} 91 92inline 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 100inline 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 109template<size_t kNumReferences> template<class T> 110inline 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 117template<size_t kNumReferences> template<class MirrorType> 118inline MutableHandle<MirrorType> FixedSizeHandleScope<kNumReferences>::NewHandle( 119 ObjPtr<MirrorType> object) { 120 return NewHandle(object.Ptr()); 121} 122 123template<size_t kNumReferences> template<class T> 124inline HandleWrapper<T> FixedSizeHandleScope<kNumReferences>::NewHandleWrapper(T** object) { 125 return HandleWrapper<T>(object, NewHandle(*object)); 126} 127 128template<size_t kNumReferences> template<class T> 129inline HandleWrapperObjPtr<T> FixedSizeHandleScope<kNumReferences>::NewHandleWrapper( 130 ObjPtr<T>* object) { 131 return HandleWrapperObjPtr<T>(object, NewHandle(*object)); 132} 133 134template<size_t kNumReferences> 135inline 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. 145inline uint32_t BaseHandleScope::NumberOfReferences() const { 146 return LIKELY(!IsVariableSized()) 147 ? AsHandleScope()->NumberOfReferences() 148 : AsVariableSized()->NumberOfReferences(); 149} 150 151inline 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 157template <typename Visitor> 158inline void BaseHandleScope::VisitRoots(Visitor& visitor) { 159 if (LIKELY(!IsVariableSized())) { 160 AsHandleScope()->VisitRoots(visitor); 161 } else { 162 AsVariableSized()->VisitRoots(visitor); 163 } 164} 165 166inline VariableSizedHandleScope* BaseHandleScope::AsVariableSized() { 167 DCHECK(IsVariableSized()); 168 return down_cast<VariableSizedHandleScope*>(this); 169} 170 171inline HandleScope* BaseHandleScope::AsHandleScope() { 172 DCHECK(!IsVariableSized()); 173 return down_cast<HandleScope*>(this); 174} 175 176inline const VariableSizedHandleScope* BaseHandleScope::AsVariableSized() const { 177 DCHECK(IsVariableSized()); 178 return down_cast<const VariableSizedHandleScope*>(this); 179} 180 181inline const HandleScope* BaseHandleScope::AsHandleScope() const { 182 DCHECK(!IsVariableSized()); 183 return down_cast<const HandleScope*>(this); 184} 185 186template<class T> 187MutableHandle<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 194template<class MirrorType> 195inline MutableHandle<MirrorType> VariableSizedHandleScope::NewHandle(ObjPtr<MirrorType> ptr) { 196 return NewHandle(ptr.Ptr()); 197} 198 199inline 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 206inline 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 216inline 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 226inline 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 238template <typename Visitor> 239inline 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