/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef ART_RUNTIME_HANDLE_SCOPE_INL_H_
#define ART_RUNTIME_HANDLE_SCOPE_INL_H_

#include "handle_scope.h"

#include "base/mutex.h"
#include "handle.h"
#include "obj_ptr-inl.h"
#include "thread-inl.h"
#include "verify_object-inl.h"

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());
  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());
  for (size_t i = 0; i < kNumReferences; ++i) {
    SetReference(i, fill_value);
  }
  self_->PushHandleScope(this);
}

template<size_t kNumReferences>
inline StackHandleScope<kNumReferences>::~StackHandleScope() {
  HandleScope* top_handle_scope = self_->PopHandleScope();
  DCHECK_EQ(top_handle_scope, this);
  if (kDebugLocking) {
    Locks::mutator_lock_->AssertSharedHeld(self_);
  }
}

inline size_t HandleScope::SizeOf(uint32_t num_references) {
  size_t header_size = sizeof(HandleScope);
  size_t data_size = sizeof(StackReference<mirror::Object>) * num_references;
  return header_size + data_size;
}

inline size_t HandleScope::SizeOf(PointerSize pointer_size, uint32_t num_references) {
  // Assume that the layout is packed.
  size_t header_size = ReferencesOffset(pointer_size);
  size_t data_size = sizeof(StackReference<mirror::Object>) * num_references;
  return header_size + data_size;
}

inline mirror::Object* HandleScope::GetReference(size_t i) const {
  DCHECK_LT(i, number_of_references_);
  if (kDebugLocking) {
    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
  }
  return GetReferences()[i].AsMirrorPtr();
}

inline Handle<mirror::Object> HandleScope::GetHandle(size_t i) {
  DCHECK_LT(i, number_of_references_);
  return Handle<mirror::Object>(&GetReferences()[i]);
}

inline MutableHandle<mirror::Object> HandleScope::GetMutableHandle(size_t i) {
  DCHECK_LT(i, number_of_references_);
  return MutableHandle<mirror::Object>(&GetReferences()[i]);
}

inline void HandleScope::SetReference(size_t i, mirror::Object* object) {
  if (kDebugLocking) {
    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
  }
  DCHECK_LT(i, number_of_references_);
  GetReferences()[i].Assign(object);
}

inline bool HandleScope::Contains(StackReference<mirror::Object>* handle_scope_entry) const {
  // 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);
  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) {
  SetReference(pos_, object);
  MutableHandle<T> h(GetHandle<T>(pos_));
  pos_++;
  return h;
}

template<size_t kNumReferences> template<class MirrorType, bool kPoison>
inline MutableHandle<MirrorType> StackHandleScope<kNumReferences>::NewHandle(
    ObjPtr<MirrorType, kPoison> object) {
  return NewHandle(object.Decode());
}

template<size_t kNumReferences> template<class T>
inline HandleWrapper<T> StackHandleScope<kNumReferences>::NewHandleWrapper(T** object) {
  return HandleWrapper<T>(object, NewHandle(*object));
}

template<size_t kNumReferences> template<class T>
inline HandleWrapperObjPtr<T> StackHandleScope<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) {
  if (kDebugLocking) {
    Locks::mutator_lock_->AssertSharedHeld(Thread::Current());
  }
  DCHECK_LT(i, kNumReferences);
  VerifyObject(object);
  GetReferences()[i].Assign(object);
}

template<class MirrorType, bool kPoison>
inline MutableHandle<MirrorType> StackHandleScopeCollection::NewHandle(
    ObjPtr<MirrorType, kPoison> ptr) {
  return NewHandle(ptr.Decode());
}

}  // namespace art

#endif  // ART_RUNTIME_HANDLE_SCOPE_INL_H_
