diff options
Diffstat (limited to 'runtime/handle_scope-inl.h')
-rw-r--r-- | runtime/handle_scope-inl.h | 141 |
1 files changed, 123 insertions, 18 deletions
diff --git a/runtime/handle_scope-inl.h b/runtime/handle_scope-inl.h index cceb0072a9..b212d095cb 100644 --- a/runtime/handle_scope-inl.h +++ b/runtime/handle_scope-inl.h @@ -28,24 +28,30 @@ namespace art { template<size_t kNumReferences> -inline StackHandleScope<kNumReferences>::StackHandleScope(Thread* self, mirror::Object* fill_value) - : HandleScope(self->GetTopHandleScope(), kNumReferences), self_(self), pos_(0) { - DCHECK_EQ(self, Thread::Current()); +inline FixedSizeHandleScope<kNumReferences>::FixedSizeHandleScope(BaseHandleScope* link, + mirror::Object* fill_value) + : HandleScope(link, kNumReferences) { if (kDebugLocking) { Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); } - static_assert(kNumReferences >= 1, "StackHandleScope must contain at least 1 reference"); - // TODO: Figure out how to use a compile assert. - CHECK_EQ(&storage_[0], GetReferences()); + static_assert(kNumReferences >= 1, "FixedSizeHandleScope must contain at least 1 reference"); + DCHECK_EQ(&storage_[0], GetReferences()); // TODO: Figure out how to use a compile assert. for (size_t i = 0; i < kNumReferences; ++i) { SetReference(i, fill_value); } +} + +template<size_t kNumReferences> +inline StackHandleScope<kNumReferences>::StackHandleScope(Thread* self, mirror::Object* fill_value) + : FixedSizeHandleScope<kNumReferences>(self->GetTopHandleScope(), fill_value), + self_(self) { + DCHECK_EQ(self, Thread::Current()); self_->PushHandleScope(this); } template<size_t kNumReferences> inline StackHandleScope<kNumReferences>::~StackHandleScope() { - HandleScope* top_handle_scope = self_->PopHandleScope(); + BaseHandleScope* top_handle_scope = self_->PopHandleScope(); DCHECK_EQ(top_handle_scope, this); if (kDebugLocking) { Locks::mutator_lock_->AssertSharedHeld(self_); @@ -66,7 +72,7 @@ inline size_t HandleScope::SizeOf(PointerSize pointer_size, uint32_t num_referen } inline mirror::Object* HandleScope::GetReference(size_t i) const { - DCHECK_LT(i, number_of_references_); + DCHECK_LT(i, NumberOfReferences()); if (kDebugLocking) { Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); } @@ -74,12 +80,12 @@ inline mirror::Object* HandleScope::GetReference(size_t i) const { } inline Handle<mirror::Object> HandleScope::GetHandle(size_t i) { - DCHECK_LT(i, number_of_references_); + DCHECK_LT(i, NumberOfReferences()); return Handle<mirror::Object>(&GetReferences()[i]); } inline MutableHandle<mirror::Object> HandleScope::GetMutableHandle(size_t i) { - DCHECK_LT(i, number_of_references_); + DCHECK_LT(i, NumberOfReferences()); return MutableHandle<mirror::Object>(&GetReferences()[i]); } @@ -87,7 +93,7 @@ inline void HandleScope::SetReference(size_t i, mirror::Object* object) { if (kDebugLocking) { Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); } - DCHECK_LT(i, number_of_references_); + DCHECK_LT(i, NumberOfReferences()); GetReferences()[i].Assign(object); } @@ -95,13 +101,13 @@ inline bool HandleScope::Contains(StackReference<mirror::Object>* handle_scope_e // A HandleScope should always contain something. One created by the // jni_compiler should have a jobject/jclass as a native method is // passed in a this pointer or a class - DCHECK_GT(number_of_references_, 0U); + DCHECK_GT(NumberOfReferences(), 0U); return &GetReferences()[0] <= handle_scope_entry && handle_scope_entry <= &GetReferences()[number_of_references_ - 1]; } template<size_t kNumReferences> template<class T> -inline MutableHandle<T> StackHandleScope<kNumReferences>::NewHandle(T* object) { +inline MutableHandle<T> FixedSizeHandleScope<kNumReferences>::NewHandle(T* object) { SetReference(pos_, object); MutableHandle<T> h(GetHandle<T>(pos_)); pos_++; @@ -109,24 +115,24 @@ inline MutableHandle<T> StackHandleScope<kNumReferences>::NewHandle(T* object) { } template<size_t kNumReferences> template<class MirrorType, bool kPoison> -inline MutableHandle<MirrorType> StackHandleScope<kNumReferences>::NewHandle( +inline MutableHandle<MirrorType> FixedSizeHandleScope<kNumReferences>::NewHandle( ObjPtr<MirrorType, kPoison> object) { return NewHandle(object.Ptr()); } template<size_t kNumReferences> template<class T> -inline HandleWrapper<T> StackHandleScope<kNumReferences>::NewHandleWrapper(T** object) { +inline HandleWrapper<T> FixedSizeHandleScope<kNumReferences>::NewHandleWrapper(T** object) { return HandleWrapper<T>(object, NewHandle(*object)); } template<size_t kNumReferences> template<class T> -inline HandleWrapperObjPtr<T> StackHandleScope<kNumReferences>::NewHandleWrapper( +inline HandleWrapperObjPtr<T> FixedSizeHandleScope<kNumReferences>::NewHandleWrapper( ObjPtr<T>* object) { return HandleWrapperObjPtr<T>(object, NewHandle(*object)); } template<size_t kNumReferences> -inline void StackHandleScope<kNumReferences>::SetReference(size_t i, mirror::Object* object) { +inline void FixedSizeHandleScope<kNumReferences>::SetReference(size_t i, mirror::Object* object) { if (kDebugLocking) { Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); } @@ -135,12 +141,111 @@ inline void StackHandleScope<kNumReferences>::SetReference(size_t i, mirror::Obj GetReferences()[i].Assign(object); } +// Number of references contained within this handle scope. +inline uint32_t BaseHandleScope::NumberOfReferences() const { + return LIKELY(!IsVariableSized()) + ? AsHandleScope()->NumberOfReferences() + : AsVariableSized()->NumberOfReferences(); +} + +inline bool BaseHandleScope::Contains(StackReference<mirror::Object>* handle_scope_entry) const { + return LIKELY(!IsVariableSized()) + ? AsHandleScope()->Contains(handle_scope_entry) + : AsVariableSized()->Contains(handle_scope_entry); +} + +template <typename Visitor> +inline void BaseHandleScope::VisitRoots(Visitor& visitor) { + if (LIKELY(!IsVariableSized())) { + AsHandleScope()->VisitRoots(visitor); + } else { + AsVariableSized()->VisitRoots(visitor); + } +} + +inline VariableSizedHandleScope* BaseHandleScope::AsVariableSized() { + DCHECK(IsVariableSized()); + return down_cast<VariableSizedHandleScope*>(this); +} + +inline HandleScope* BaseHandleScope::AsHandleScope() { + DCHECK(!IsVariableSized()); + return down_cast<HandleScope*>(this); +} + +inline const VariableSizedHandleScope* BaseHandleScope::AsVariableSized() const { + DCHECK(IsVariableSized()); + return down_cast<const VariableSizedHandleScope*>(this); +} + +inline const HandleScope* BaseHandleScope::AsHandleScope() const { + DCHECK(!IsVariableSized()); + return down_cast<const HandleScope*>(this); +} + +template<class T> +MutableHandle<T> VariableSizedHandleScope::NewHandle(T* object) { + if (current_scope_->RemainingSlots() == 0) { + current_scope_ = new LocalScopeType(current_scope_); + } + return current_scope_->NewHandle(object); +} + template<class MirrorType, bool kPoison> -inline MutableHandle<MirrorType> StackHandleScopeCollection::NewHandle( +inline MutableHandle<MirrorType> VariableSizedHandleScope::NewHandle( ObjPtr<MirrorType, kPoison> ptr) { return NewHandle(ptr.Ptr()); } +inline VariableSizedHandleScope::VariableSizedHandleScope(Thread* const self) + : BaseHandleScope(self->GetTopHandleScope()), + self_(self) { + current_scope_ = new LocalScopeType(/*link*/ nullptr); + self_->PushHandleScope(this); +} + +inline VariableSizedHandleScope::~VariableSizedHandleScope() { + BaseHandleScope* top_handle_scope = self_->PopHandleScope(); + DCHECK_EQ(top_handle_scope, this); + while (current_scope_ != nullptr) { + LocalScopeType* next = reinterpret_cast<LocalScopeType*>(current_scope_->GetLink()); + delete current_scope_; + current_scope_ = next; + } +} + +inline uint32_t VariableSizedHandleScope::NumberOfReferences() const { + uint32_t sum = 0; + const LocalScopeType* cur = current_scope_; + while (cur != nullptr) { + sum += cur->NumberOfReferences(); + cur = reinterpret_cast<const LocalScopeType*>(cur->GetLink()); + } + return sum; +} + +inline bool VariableSizedHandleScope::Contains(StackReference<mirror::Object>* handle_scope_entry) + const { + const LocalScopeType* cur = current_scope_; + while (cur != nullptr) { + if (cur->Contains(handle_scope_entry)) { + return true; + } + cur = reinterpret_cast<const LocalScopeType*>(cur->GetLink()); + } + return false; +} + +template <typename Visitor> +inline void VariableSizedHandleScope::VisitRoots(Visitor& visitor) { + LocalScopeType* cur = current_scope_; + while (cur != nullptr) { + cur->VisitRoots(visitor); + cur = reinterpret_cast<LocalScopeType*>(cur->GetLink()); + } +} + + } // namespace art #endif // ART_RUNTIME_HANDLE_SCOPE_INL_H_ |