/*
 * 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_H_
#define ART_RUNTIME_HANDLE_H_

#include <android-base/logging.h>

#include "base/casts.h"
#include "base/locks.h"
#include "base/macros.h"
#include "base/value_object.h"
#include "jni.h"
#include "obj_ptr.h"
#include "stack_reference.h"

namespace art {

class Thread;

template<class T> class Handle;
template<typename T> class IterationRange;

namespace mirror {
template<typename T> class ObjectArray;
template<typename T, typename C> class ArrayIter;
template<typename T> using HandleArrayIter = ArrayIter<T, Handle<ObjectArray<T>>>;
template<typename T> using ConstHandleArrayIter = ArrayIter<T, const Handle<ObjectArray<T>>>;
}  // namespace mirror

// Handles are memory locations that contain GC roots. As the mirror::Object*s within a handle are
// GC visible then the GC may move the references within them, something that couldn't be done with
// a wrap pointer. Handles are generally allocated within HandleScopes. Handle is a super-class
// of MutableHandle and doesn't support assignment operations.
template<class T>
class Handle : public ValueObject {
 public:
  Handle() : reference_(nullptr) {
  }

  ALWAYS_INLINE Handle(const Handle<T>& handle) = default;

  ALWAYS_INLINE Handle<T>& operator=(const Handle<T>& handle) = default;

  template <typename Type,
            typename = typename std::enable_if_t<std::is_base_of_v<T, Type>>>
  ALWAYS_INLINE Handle(const Handle<Type>& other) : reference_(other.reference_) {
  }

  ALWAYS_INLINE explicit Handle(StackReference<T>* reference) : reference_(reference) {
  }

  ALWAYS_INLINE T& operator*() const REQUIRES_SHARED(Locks::mutator_lock_) {
    return *Get();
  }

  ALWAYS_INLINE T* operator->() const REQUIRES_SHARED(Locks::mutator_lock_) {
    return Get();
  }

  ALWAYS_INLINE T* Get() const REQUIRES_SHARED(Locks::mutator_lock_) {
    return down_cast<T*>(reference_->AsMirrorPtr());
  }

  template <typename Type,
            typename = typename std::enable_if_t<std::is_same_v<mirror::ObjectArray<Type>, T>>>
  ALWAYS_INLINE IterationRange<mirror::ConstHandleArrayIter<Type>> ConstIterate() const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    return T::ConstIterate(*this);
  }
  template <typename Type,
            typename = typename std::enable_if_t<std::is_same_v<mirror::ObjectArray<Type>, T>>>
  ALWAYS_INLINE IterationRange<mirror::HandleArrayIter<Type>> Iterate()
      REQUIRES_SHARED(Locks::mutator_lock_) {
    return T::Iterate(*this);
  }

  ALWAYS_INLINE bool IsNull() const {
    // It's safe to null-check it without a read barrier.
    return reference_->IsNull();
  }

  ALWAYS_INLINE StackReference<mirror::Object>* GetReference() {
    return reference_;
  }

  ALWAYS_INLINE const StackReference<mirror::Object>* GetReference() const {
    return reference_;
  }

  ALWAYS_INLINE bool operator!=(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) {
    return !IsNull();
  }

  ALWAYS_INLINE bool operator==(std::nullptr_t) const REQUIRES_SHARED(Locks::mutator_lock_) {
    return IsNull();
  }

  mirror::Object* ObjectFromGdb() REQUIRES_SHARED(Locks::mutator_lock_);
  T* GetFromGdb() REQUIRES_SHARED(Locks::mutator_lock_);

 protected:
  template<typename S>
  explicit Handle(StackReference<S>* reference)
      : reference_(reference) {
  }
  template<typename S>
  explicit Handle(const Handle<S>& handle)
      : reference_(handle.reference_) {
  }

  StackReference<mirror::Object>* reference_;

 private:
  friend class BuildGenericJniFrameVisitor;
  template<class S> friend class Handle;
  friend class HandleScope;
  template<class S> friend class HandleWrapper;
  template<size_t kNumReferences> friend class StackHandleScope;
};

// Handles that support assignment.
template<class T>
class MutableHandle : public Handle<T> {
 public:
  MutableHandle() {
  }

  ALWAYS_INLINE MutableHandle(const MutableHandle<T>& handle)
      REQUIRES_SHARED(Locks::mutator_lock_) = default;

  ALWAYS_INLINE MutableHandle<T>& operator=(const MutableHandle<T>& handle)
      REQUIRES_SHARED(Locks::mutator_lock_) = default;

  ALWAYS_INLINE explicit MutableHandle(StackReference<T>* reference)
      REQUIRES_SHARED(Locks::mutator_lock_)
      : Handle<T>(reference) {
  }

  ALWAYS_INLINE T* Assign(T* reference) REQUIRES_SHARED(Locks::mutator_lock_) {
    StackReference<mirror::Object>* ref = Handle<T>::GetReference();
    T* old = down_cast<T*>(ref->AsMirrorPtr());
    ref->Assign(reference);
    return old;
  }

  ALWAYS_INLINE T* Assign(ObjPtr<T> reference) REQUIRES_SHARED(Locks::mutator_lock_) {
    StackReference<mirror::Object>* ref = Handle<T>::GetReference();
    T* old = down_cast<T*>(ref->AsMirrorPtr());
    ref->Assign(reference.Ptr());
    return old;
  }


  template<typename S>
  explicit MutableHandle(const MutableHandle<S>& handle) REQUIRES_SHARED(Locks::mutator_lock_)
      : Handle<T>(handle) {
  }

  template<typename S>
  explicit MutableHandle(StackReference<S>* reference) REQUIRES_SHARED(Locks::mutator_lock_)
      : Handle<T>(reference) {
  }

 private:
  friend class BuildGenericJniFrameVisitor;
  friend class HandleScope;
  template<class S> friend class HandleWrapper;
  template<size_t kNumReferences> friend class StackHandleScope;
};

// A special case of Handle that only holds references to null. Invalid when if it goes out of
// scope. Example: Handle<T> h = ScopedNullHandle<T> will leave h being undefined.
template<class T>
class ScopedNullHandle : public Handle<T> {
 public:
  ScopedNullHandle() : Handle<T>(&null_ref_) {}

 private:
  StackReference<mirror::Object> null_ref_;
};

}  // namespace art

#endif  // ART_RUNTIME_HANDLE_H_
