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 "thread-inl.h" 25#include "verify_object-inl.h" 26 27namespace art { 28 29template<size_t kNumReferences> 30inline StackHandleScope<kNumReferences>::StackHandleScope(Thread* self, mirror::Object* fill_value) 31 : HandleScope(self->GetTopHandleScope(), kNumReferences), self_(self), pos_(0) { 32 DCHECK_EQ(self, Thread::Current()); 33 if (kDebugLocking) { 34 Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); 35 } 36 static_assert(kNumReferences >= 1, "StackHandleScope must contain at least 1 reference"); 37 // TODO: Figure out how to use a compile assert. 38 CHECK_EQ(&storage_[0], GetReferences()); 39 for (size_t i = 0; i < kNumReferences; ++i) { 40 SetReference(i, fill_value); 41 } 42 self_->PushHandleScope(this); 43} 44 45template<size_t kNumReferences> 46inline StackHandleScope<kNumReferences>::~StackHandleScope() { 47 HandleScope* top_handle_scope = self_->PopHandleScope(); 48 DCHECK_EQ(top_handle_scope, this); 49 if (kDebugLocking) { 50 Locks::mutator_lock_->AssertSharedHeld(self_); 51 } 52} 53 54inline size_t HandleScope::SizeOf(uint32_t num_references) { 55 size_t header_size = sizeof(HandleScope); 56 size_t data_size = sizeof(StackReference<mirror::Object>) * num_references; 57 return header_size + data_size; 58} 59 60inline size_t HandleScope::SizeOf(size_t pointer_size, uint32_t num_references) { 61 // Assume that the layout is packed. 62 size_t header_size = pointer_size + sizeof(number_of_references_); 63 size_t data_size = sizeof(StackReference<mirror::Object>) * num_references; 64 return header_size + data_size; 65} 66 67inline mirror::Object* HandleScope::GetReference(size_t i) const { 68 DCHECK_LT(i, number_of_references_); 69 if (kDebugLocking) { 70 Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); 71 } 72 return GetReferences()[i].AsMirrorPtr(); 73} 74 75inline Handle<mirror::Object> HandleScope::GetHandle(size_t i) { 76 DCHECK_LT(i, number_of_references_); 77 return Handle<mirror::Object>(&GetReferences()[i]); 78} 79 80inline MutableHandle<mirror::Object> HandleScope::GetMutableHandle(size_t i) { 81 DCHECK_LT(i, number_of_references_); 82 return MutableHandle<mirror::Object>(&GetReferences()[i]); 83} 84 85inline void HandleScope::SetReference(size_t i, mirror::Object* object) { 86 if (kDebugLocking) { 87 Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); 88 } 89 DCHECK_LT(i, number_of_references_); 90 GetReferences()[i].Assign(object); 91} 92 93inline bool HandleScope::Contains(StackReference<mirror::Object>* handle_scope_entry) const { 94 // A HandleScope should always contain something. One created by the 95 // jni_compiler should have a jobject/jclass as a native method is 96 // passed in a this pointer or a class 97 DCHECK_GT(number_of_references_, 0U); 98 return &GetReferences()[0] <= handle_scope_entry && 99 handle_scope_entry <= &GetReferences()[number_of_references_ - 1]; 100} 101 102template<size_t kNumReferences> template<class T> 103inline MutableHandle<T> StackHandleScope<kNumReferences>::NewHandle(T* object) { 104 SetReference(pos_, object); 105 MutableHandle<T> h(GetHandle<T>(pos_)); 106 pos_++; 107 return h; 108} 109 110template<size_t kNumReferences> template<class T> 111inline HandleWrapper<T> StackHandleScope<kNumReferences>::NewHandleWrapper(T** object) { 112 SetReference(pos_, *object); 113 MutableHandle<T> h(GetHandle<T>(pos_)); 114 pos_++; 115 return HandleWrapper<T>(object, h); 116} 117 118template<size_t kNumReferences> 119inline void StackHandleScope<kNumReferences>::SetReference(size_t i, mirror::Object* object) { 120 if (kDebugLocking) { 121 Locks::mutator_lock_->AssertSharedHeld(Thread::Current()); 122 } 123 DCHECK_LT(i, kNumReferences); 124 VerifyObject(object); 125 GetReferences()[i].Assign(object); 126} 127 128} // namespace art 129 130#endif // ART_RUNTIME_HANDLE_SCOPE_INL_H_ 131