/*
 * Copyright (C) 2019 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_REFLECTIVE_HANDLE_SCOPE_H_
#define ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_H_

#include <android-base/logging.h>

#include <array>
#include <compare>
#include <functional>
#include <stack>

#include "android-base/macros.h"
#include "base/enums.h"
#include "base/globals.h"
#include "base/locks.h"
#include "base/macros.h"
#include "base/value_object.h"
#include "reflective_handle.h"
#include "reflective_reference.h"
#include "reflective_value_visitor.h"

namespace art HIDDEN {

class ArtField;
class ArtMethod;
class BaseReflectiveHandleScope;
class Thread;

// This is a holder similar to StackHandleScope that is used to hold reflective references to
// ArtField and ArtMethod structures. A reflective reference is one that must be updated if the
// underlying class or instances are replaced due to structural redefinition or some other process.
// In general these don't need to be used. It's only when it's important that a reference to a field
// not become obsolete and it needs to be held over a suspend point that this should be used. This
// takes care of the book-keeping to allow the runtime to visit and update ReflectiveHandles when
// structural redefinition occurs.
class BaseReflectiveHandleScope {
 public:
  template <typename Visitor>
  ALWAYS_INLINE void VisitTargets(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_) {
    FunctionReflectiveValueVisitor v(&visitor);
    VisitTargets(&v);
  }

  ALWAYS_INLINE virtual ~BaseReflectiveHandleScope() {
    DCHECK(link_ == nullptr);
  }

  virtual void VisitTargets(ReflectiveValueVisitor* visitor)
      REQUIRES_SHARED(Locks::mutator_lock_) = 0;

  BaseReflectiveHandleScope* GetLink() {
    return link_;
  }

  Thread* GetThread() {
    return self_;
  }

  void Describe(std::ostream& os) const;

 protected:
  ALWAYS_INLINE BaseReflectiveHandleScope() : self_(nullptr), link_(nullptr) {}

  ALWAYS_INLINE inline void PushScope(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
  ALWAYS_INLINE inline void PopScope() REQUIRES_SHARED(Locks::mutator_lock_);

  // Thread this node is rooted in.
  Thread* self_;
  // Next node in the handle-scope linked list. Root is held by Thread.
  BaseReflectiveHandleScope* link_;

 private:
  DISALLOW_COPY_AND_ASSIGN(BaseReflectiveHandleScope);
};
std::ostream& operator<<(std::ostream& os, const BaseReflectiveHandleScope& brhs);

template <size_t kNumFields, size_t kNumMethods>
class StackReflectiveHandleScope : public BaseReflectiveHandleScope {
 private:
  static constexpr bool kHasFields = kNumFields > 0;
  static constexpr bool kHasMethods = kNumMethods > 0;

 public:
  ALWAYS_INLINE explicit StackReflectiveHandleScope(Thread* self)
      REQUIRES_SHARED(Locks::mutator_lock_);
  ALWAYS_INLINE ~StackReflectiveHandleScope() REQUIRES_SHARED(Locks::mutator_lock_);

  void VisitTargets(ReflectiveValueVisitor* visitor) override REQUIRES_SHARED(Locks::mutator_lock_);

  template <typename T,
            typename = typename std::enable_if_t<(kHasFields && std::is_same_v<T, ArtField>) ||
                                                 (kHasMethods && std::is_same_v<T, ArtMethod>)>>
  ALWAYS_INLINE MutableReflectiveHandle<T> NewHandle(T* t) REQUIRES_SHARED(Locks::mutator_lock_) {
    if constexpr (std::is_same_v<T, ArtField>) {
      return NewFieldHandle(t);
    } else {
      static_assert(std::is_same_v<T, ArtMethod>, "Expected ArtField or ArtMethod");
      return NewMethodHandle(t);
    }
  }
  template<typename T>
  ALWAYS_INLINE ReflectiveHandleWrapper<T> NewReflectiveHandleWrapper(T** t)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return ReflectiveHandleWrapper<T>(t, NewHandle(*t));
  }

  ALWAYS_INLINE MutableReflectiveHandle<ArtField> NewFieldHandle(ArtField* f)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    static_assert(kHasFields, "No fields");
    DCHECK_LT(field_pos_, kNumFields);
    MutableReflectiveHandle<ArtField> fh(GetMutableFieldHandle(field_pos_++));
    fh.Assign(f);
    return fh;
  }
  ALWAYS_INLINE ReflectiveHandleWrapper<ArtField> NewReflectiveFieldHandleWrapper(ArtField** f)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return ReflectiveHandleWrapper<ArtField>(f, NewMethodHandle(*f));
  }

  ALWAYS_INLINE ArtField* GetField(size_t i) {
    static_assert(kHasFields, "No fields");
    return GetFieldReference(i)->Ptr();
  }
  ALWAYS_INLINE ReflectiveHandle<ArtField> GetFieldHandle(size_t i) {
    static_assert(kHasFields, "No fields");
    return ReflectiveHandle<ArtField>(GetFieldReference(i));
  }
  ALWAYS_INLINE MutableReflectiveHandle<ArtField> GetMutableFieldHandle(size_t i) {
    static_assert(kHasFields, "No fields");
    return MutableReflectiveHandle<ArtField>(GetFieldReference(i));
  }

  ALWAYS_INLINE MutableReflectiveHandle<ArtMethod> NewMethodHandle(ArtMethod* m)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    static_assert(kHasMethods, "No methods");
    DCHECK_LT(method_pos_, kNumMethods);
    MutableReflectiveHandle<ArtMethod> mh(GetMutableMethodHandle(method_pos_++));
    mh.Assign(m);
    return mh;
  }
  ALWAYS_INLINE ReflectiveHandleWrapper<ArtMethod> NewReflectiveMethodHandleWrapper(ArtMethod** m)
      REQUIRES_SHARED(art::Locks::mutator_lock_) {
    return ReflectiveHandleWrapper<ArtMethod>(m, NewMethodHandle(*m));
  }

  ALWAYS_INLINE ArtMethod* GetMethod(size_t i) {
    static_assert(kHasMethods, "No methods");
    return GetMethodReference(i)->Ptr();
  }
  ALWAYS_INLINE ReflectiveHandle<ArtMethod> GetMethodHandle(size_t i) {
    static_assert(kHasMethods, "No methods");
    return ReflectiveHandle<ArtMethod>(GetMethodReference(i));
  }
  ALWAYS_INLINE MutableReflectiveHandle<ArtMethod> GetMutableMethodHandle(size_t i) {
    static_assert(kHasMethods, "No methods");
    return MutableReflectiveHandle<ArtMethod>(GetMethodReference(i));
  }

  size_t RemainingFieldSlots() const {
    return kNumFields - field_pos_;
  }

  size_t RemainingMethodSlots() const {
    return kNumMethods - method_pos_;
  }

 private:
  ReflectiveReference<ArtMethod>* GetMethodReference(size_t i) {
    DCHECK_LT(i, method_pos_);
    return &methods_[i];
  }

  ReflectiveReference<ArtField>* GetFieldReference(size_t i) {
    DCHECK_LT(i, field_pos_);
    return &fields_[i];
  }

  size_t field_pos_;
  size_t method_pos_;
  std::array<ReflectiveReference<ArtField>, kNumFields> fields_;
  std::array<ReflectiveReference<ArtMethod>, kNumMethods> methods_;
};

template <size_t kNumMethods>
using StackArtMethodHandleScope = StackReflectiveHandleScope</*kNumFields=*/0, kNumMethods>;

template <size_t kNumFields>
using StackArtFieldHandleScope = StackReflectiveHandleScope<kNumFields, /*kNumMethods=*/0>;

}  // namespace art

#endif  // ART_RUNTIME_REFLECTIVE_HANDLE_SCOPE_H_
