summaryrefslogtreecommitdiff
path: root/runtime/handle_scope-inl.h
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/handle_scope-inl.h')
-rw-r--r--runtime/handle_scope-inl.h141
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_