// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef INCLUDE_CPPGC_ALLOCATION_H_
#define INCLUDE_CPPGC_ALLOCATION_H_

#include <stdint.h>

#include <atomic>

#include "cppgc/custom-space.h"
#include "cppgc/garbage-collected.h"
#include "cppgc/internal/api-constants.h"
#include "cppgc/internal/gc-info.h"

namespace cppgc {

template <typename T>
class MakeGarbageCollectedTraitBase;

namespace internal {
class ObjectAllocator;
}  // namespace internal

/**
 * AllocationHandle is used to allocate garbage-collected objects.
 */
class AllocationHandle;

namespace internal {

class V8_EXPORT MakeGarbageCollectedTraitInternal {
 protected:
  static inline void MarkObjectAsFullyConstructed(const void* payload) {
    // See api_constants for an explanation of the constants.
    std::atomic<uint16_t>* atomic_mutable_bitfield =
        reinterpret_cast<std::atomic<uint16_t>*>(
            const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(
                reinterpret_cast<const uint8_t*>(payload) -
                api_constants::kFullyConstructedBitFieldOffsetFromPayload)));
    uint16_t value = atomic_mutable_bitfield->load(std::memory_order_relaxed);
    value = value | api_constants::kFullyConstructedBitMask;
    atomic_mutable_bitfield->store(value, std::memory_order_release);
  }

  static void* Allocate(cppgc::AllocationHandle& handle, size_t size,
                        GCInfoIndex index);
  static void* Allocate(cppgc::AllocationHandle& handle, size_t size,
                        GCInfoIndex index, CustomSpaceIndex space_index);

  friend class HeapObjectHeader;
};

}  // namespace internal

/**
 * Base trait that provides utilities for advancers users that have custom
 * allocation needs (e.g., overriding size). It's expected that users override
 * MakeGarbageCollectedTrait (see below) and inherit from
 * MakeGarbageCollectedTraitBase and make use of the low-level primitives
 * offered to allocate and construct an object.
 */
template <typename T>
class MakeGarbageCollectedTraitBase
    : private internal::MakeGarbageCollectedTraitInternal {
 private:
  template <typename U, typename CustomSpace>
  struct SpacePolicy {
    static void* Allocate(AllocationHandle& handle, size_t size) {
      // Custom space.
      static_assert(std::is_base_of<CustomSpaceBase, CustomSpace>::value,
                    "Custom space must inherit from CustomSpaceBase.");
      return internal::MakeGarbageCollectedTraitInternal::Allocate(
          handle, size, internal::GCInfoTrait<T>::Index(),
          CustomSpace::kSpaceIndex);
    }
  };

  template <typename U>
  struct SpacePolicy<U, void> {
    static void* Allocate(AllocationHandle& handle, size_t size) {
      // Default space.
      return internal::MakeGarbageCollectedTraitInternal::Allocate(
          handle, size, internal::GCInfoTrait<T>::Index());
    }
  };

 protected:
  /**
   * Allocates memory for an object of type T.
   *
   * \param handle AllocationHandle identifying the heap to allocate the object
   *   on.
   * \param size The size that should be reserved for the object.
   * \returns the memory to construct an object of type T on.
   */
  static void* Allocate(AllocationHandle& handle, size_t size) {
    return SpacePolicy<T, typename SpaceTrait<T>::Space>::Allocate(handle,
                                                                   size);
  }

  /**
   * Marks an object as fully constructed, resulting in precise handling by the
   * garbage collector.
   *
   * \param payload The base pointer the object is allocated at.
   */
  static void MarkObjectAsFullyConstructed(const void* payload) {
    internal::MakeGarbageCollectedTraitInternal::MarkObjectAsFullyConstructed(
        payload);
  }
};

/**
 * struct used specify to MakeGarbageCollected how many bytes should be
 * appended to the allocated object.
 */
struct AdditionalBytes {
  explicit AdditionalBytes(size_t bytes) : value(bytes) {}
  const size_t value;
};

/**
 * Default trait class that specifies how to construct an object of type T.
 * Advanced users may override how an object is constructed using the utilities
 * that are provided through MakeGarbageCollectedTraitBase.
 *
 * Any trait overriding construction must
 * - allocate through `MakeGarbageCollectedTraitBase<T>::Allocate`;
 * - mark the object as fully constructed using
 *   `MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed`;
 */
template <typename T>
class MakeGarbageCollectedTrait : public MakeGarbageCollectedTraitBase<T> {
 public:
  template <typename... Args>
  static T* Call(AllocationHandle& handle, Args&&... args) {
    static_assert(internal::IsGarbageCollectedType<T>::value,
                  "T needs to be a garbage collected object");
    static_assert(
        !internal::IsGarbageCollectedMixinType<T>::value ||
            sizeof(T) <= internal::api_constants::kLargeObjectSizeThreshold,
        "GarbageCollectedMixin may not be a large object");
    void* memory =
        MakeGarbageCollectedTraitBase<T>::Allocate(handle, sizeof(T));
    T* object = ::new (memory) T(std::forward<Args>(args)...);
    MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed(object);
    return object;
  }

  template <typename... Args>
  static T* Call(AllocationHandle& handle, AdditionalBytes additional_bytes,
                 Args&&... args) {
    static_assert(internal::IsGarbageCollectedType<T>::value,
                  "T needs to be a garbage collected object");
    static_assert(
        !internal::IsGarbageCollectedMixinType<T>::value ||
            sizeof(T) <= internal::api_constants::kLargeObjectSizeThreshold,
        "GarbageCollectedMixin may not be a large object");
    void* memory = MakeGarbageCollectedTraitBase<T>::Allocate(
        handle, sizeof(T) + additional_bytes.value);
    T* object = ::new (memory) T(std::forward<Args>(args)...);
    MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed(object);
    return object;
  }
};

/**
 * Allows users to specify a post-construction callback for specific types. The
 * callback is invoked on the instance of type T right after it has been
 * constructed. This can be useful when the callback requires a
 * fully-constructed object to be able to dispatch to virtual methods.
 */
template <typename T, typename = void>
struct PostConstructionCallbackTrait {
  static void Call(T*) {}
};

/**
 * Constructs a managed object of type T where T transitively inherits from
 * GarbageCollected.
 *
 * \param args List of arguments with which an instance of T will be
 *   constructed.
 * \returns an instance of type T.
 */
template <typename T, typename... Args>
T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
  T* object =
      MakeGarbageCollectedTrait<T>::Call(handle, std::forward<Args>(args)...);
  PostConstructionCallbackTrait<T>::Call(object);
  return object;
}

/**
 * Constructs a managed object of type T where T transitively inherits from
 * GarbageCollected. Created objects will have additional bytes appended to
 * it. Allocated memory would suffice for `sizeof(T) + additional_bytes`.
 *
 * \param additional_bytes Denotes how many bytes to append to T.
 * \param args List of arguments with which an instance of T will be
 *   constructed.
 * \returns an instance of type T.
 */
template <typename T, typename... Args>
T* MakeGarbageCollected(AllocationHandle& handle,
                        AdditionalBytes additional_bytes, Args&&... args) {
  T* object = MakeGarbageCollectedTrait<T>::Call(handle, additional_bytes,
                                                 std::forward<Args>(args)...);
  PostConstructionCallbackTrait<T>::Call(object);
  return object;
}

}  // namespace cppgc

#endif  // INCLUDE_CPPGC_ALLOCATION_H_
