11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef INCLUDE_CPPGC_ALLOCATION_H_
61cb0ef41Sopenharmony_ci#define INCLUDE_CPPGC_ALLOCATION_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <atomic>
91cb0ef41Sopenharmony_ci#include <cstddef>
101cb0ef41Sopenharmony_ci#include <cstdint>
111cb0ef41Sopenharmony_ci#include <new>
121cb0ef41Sopenharmony_ci#include <type_traits>
131cb0ef41Sopenharmony_ci#include <utility>
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ci#include "cppgc/custom-space.h"
161cb0ef41Sopenharmony_ci#include "cppgc/internal/api-constants.h"
171cb0ef41Sopenharmony_ci#include "cppgc/internal/gc-info.h"
181cb0ef41Sopenharmony_ci#include "cppgc/type-traits.h"
191cb0ef41Sopenharmony_ci#include "v8config.h"  // NOLINT(build/include_directory)
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci#if defined(__has_attribute)
221cb0ef41Sopenharmony_ci#if __has_attribute(assume_aligned)
231cb0ef41Sopenharmony_ci#define CPPGC_DEFAULT_ALIGNED \
241cb0ef41Sopenharmony_ci  __attribute__((assume_aligned(api_constants::kDefaultAlignment)))
251cb0ef41Sopenharmony_ci#define CPPGC_DOUBLE_WORD_ALIGNED \
261cb0ef41Sopenharmony_ci  __attribute__((assume_aligned(2 * api_constants::kDefaultAlignment)))
271cb0ef41Sopenharmony_ci#endif  // __has_attribute(assume_aligned)
281cb0ef41Sopenharmony_ci#endif  // defined(__has_attribute)
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci#if !defined(CPPGC_DEFAULT_ALIGNED)
311cb0ef41Sopenharmony_ci#define CPPGC_DEFAULT_ALIGNED
321cb0ef41Sopenharmony_ci#endif
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci#if !defined(CPPGC_DOUBLE_WORD_ALIGNED)
351cb0ef41Sopenharmony_ci#define CPPGC_DOUBLE_WORD_ALIGNED
361cb0ef41Sopenharmony_ci#endif
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_cinamespace cppgc {
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci/**
411cb0ef41Sopenharmony_ci * AllocationHandle is used to allocate garbage-collected objects.
421cb0ef41Sopenharmony_ci */
431cb0ef41Sopenharmony_ciclass AllocationHandle;
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_cinamespace internal {
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci// Similar to C++17 std::align_val_t;
481cb0ef41Sopenharmony_cienum class AlignVal : size_t {};
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ciclass V8_EXPORT MakeGarbageCollectedTraitInternal {
511cb0ef41Sopenharmony_ci protected:
521cb0ef41Sopenharmony_ci  static inline void MarkObjectAsFullyConstructed(const void* payload) {
531cb0ef41Sopenharmony_ci    // See api_constants for an explanation of the constants.
541cb0ef41Sopenharmony_ci    std::atomic<uint16_t>* atomic_mutable_bitfield =
551cb0ef41Sopenharmony_ci        reinterpret_cast<std::atomic<uint16_t>*>(
561cb0ef41Sopenharmony_ci            const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(
571cb0ef41Sopenharmony_ci                reinterpret_cast<const uint8_t*>(payload) -
581cb0ef41Sopenharmony_ci                api_constants::kFullyConstructedBitFieldOffsetFromPayload)));
591cb0ef41Sopenharmony_ci    // It's safe to split use load+store here (instead of a read-modify-write
601cb0ef41Sopenharmony_ci    // operation), since it's guaranteed that this 16-bit bitfield is only
611cb0ef41Sopenharmony_ci    // modified by a single thread. This is cheaper in terms of code bloat (on
621cb0ef41Sopenharmony_ci    // ARM) and performance.
631cb0ef41Sopenharmony_ci    uint16_t value = atomic_mutable_bitfield->load(std::memory_order_relaxed);
641cb0ef41Sopenharmony_ci    value |= api_constants::kFullyConstructedBitMask;
651cb0ef41Sopenharmony_ci    atomic_mutable_bitfield->store(value, std::memory_order_release);
661cb0ef41Sopenharmony_ci  }
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  // Dispatch based on compile-time information.
691cb0ef41Sopenharmony_ci  //
701cb0ef41Sopenharmony_ci  // Default implementation is for a custom space with >`kDefaultAlignment` byte
711cb0ef41Sopenharmony_ci  // alignment.
721cb0ef41Sopenharmony_ci  template <typename GCInfoType, typename CustomSpace, size_t alignment>
731cb0ef41Sopenharmony_ci  struct AllocationDispatcher final {
741cb0ef41Sopenharmony_ci    static void* Invoke(AllocationHandle& handle, size_t size) {
751cb0ef41Sopenharmony_ci      static_assert(std::is_base_of<CustomSpaceBase, CustomSpace>::value,
761cb0ef41Sopenharmony_ci                    "Custom space must inherit from CustomSpaceBase.");
771cb0ef41Sopenharmony_ci      static_assert(
781cb0ef41Sopenharmony_ci          !CustomSpace::kSupportsCompaction,
791cb0ef41Sopenharmony_ci          "Custom spaces that support compaction do not support allocating "
801cb0ef41Sopenharmony_ci          "objects with non-default (i.e. word-sized) alignment.");
811cb0ef41Sopenharmony_ci      return MakeGarbageCollectedTraitInternal::Allocate(
821cb0ef41Sopenharmony_ci          handle, size, static_cast<AlignVal>(alignment),
831cb0ef41Sopenharmony_ci          internal::GCInfoTrait<GCInfoType>::Index(), CustomSpace::kSpaceIndex);
841cb0ef41Sopenharmony_ci    }
851cb0ef41Sopenharmony_ci  };
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  // Fast path for regular allocations for the default space with
881cb0ef41Sopenharmony_ci  // `kDefaultAlignment` byte alignment.
891cb0ef41Sopenharmony_ci  template <typename GCInfoType>
901cb0ef41Sopenharmony_ci  struct AllocationDispatcher<GCInfoType, void,
911cb0ef41Sopenharmony_ci                              api_constants::kDefaultAlignment>
921cb0ef41Sopenharmony_ci      final {
931cb0ef41Sopenharmony_ci    static void* Invoke(AllocationHandle& handle, size_t size) {
941cb0ef41Sopenharmony_ci      return MakeGarbageCollectedTraitInternal::Allocate(
951cb0ef41Sopenharmony_ci          handle, size, internal::GCInfoTrait<GCInfoType>::Index());
961cb0ef41Sopenharmony_ci    }
971cb0ef41Sopenharmony_ci  };
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  // Default space with >`kDefaultAlignment` byte alignment.
1001cb0ef41Sopenharmony_ci  template <typename GCInfoType, size_t alignment>
1011cb0ef41Sopenharmony_ci  struct AllocationDispatcher<GCInfoType, void, alignment> final {
1021cb0ef41Sopenharmony_ci    static void* Invoke(AllocationHandle& handle, size_t size) {
1031cb0ef41Sopenharmony_ci      return MakeGarbageCollectedTraitInternal::Allocate(
1041cb0ef41Sopenharmony_ci          handle, size, static_cast<AlignVal>(alignment),
1051cb0ef41Sopenharmony_ci          internal::GCInfoTrait<GCInfoType>::Index());
1061cb0ef41Sopenharmony_ci    }
1071cb0ef41Sopenharmony_ci  };
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  // Custom space with `kDefaultAlignment` byte alignment.
1101cb0ef41Sopenharmony_ci  template <typename GCInfoType, typename CustomSpace>
1111cb0ef41Sopenharmony_ci  struct AllocationDispatcher<GCInfoType, CustomSpace,
1121cb0ef41Sopenharmony_ci                              api_constants::kDefaultAlignment>
1131cb0ef41Sopenharmony_ci      final {
1141cb0ef41Sopenharmony_ci    static void* Invoke(AllocationHandle& handle, size_t size) {
1151cb0ef41Sopenharmony_ci      static_assert(std::is_base_of<CustomSpaceBase, CustomSpace>::value,
1161cb0ef41Sopenharmony_ci                    "Custom space must inherit from CustomSpaceBase.");
1171cb0ef41Sopenharmony_ci      return MakeGarbageCollectedTraitInternal::Allocate(
1181cb0ef41Sopenharmony_ci          handle, size, internal::GCInfoTrait<GCInfoType>::Index(),
1191cb0ef41Sopenharmony_ci          CustomSpace::kSpaceIndex);
1201cb0ef41Sopenharmony_ci    }
1211cb0ef41Sopenharmony_ci  };
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci private:
1241cb0ef41Sopenharmony_ci  static void* CPPGC_DEFAULT_ALIGNED Allocate(cppgc::AllocationHandle&, size_t,
1251cb0ef41Sopenharmony_ci                                              GCInfoIndex);
1261cb0ef41Sopenharmony_ci  static void* CPPGC_DOUBLE_WORD_ALIGNED Allocate(cppgc::AllocationHandle&,
1271cb0ef41Sopenharmony_ci                                                  size_t, AlignVal,
1281cb0ef41Sopenharmony_ci                                                  GCInfoIndex);
1291cb0ef41Sopenharmony_ci  static void* CPPGC_DEFAULT_ALIGNED Allocate(cppgc::AllocationHandle&, size_t,
1301cb0ef41Sopenharmony_ci                                              GCInfoIndex, CustomSpaceIndex);
1311cb0ef41Sopenharmony_ci  static void* CPPGC_DOUBLE_WORD_ALIGNED Allocate(cppgc::AllocationHandle&,
1321cb0ef41Sopenharmony_ci                                                  size_t, AlignVal, GCInfoIndex,
1331cb0ef41Sopenharmony_ci                                                  CustomSpaceIndex);
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci  friend class HeapObjectHeader;
1361cb0ef41Sopenharmony_ci};
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci}  // namespace internal
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci/**
1411cb0ef41Sopenharmony_ci * Base trait that provides utilities for advancers users that have custom
1421cb0ef41Sopenharmony_ci * allocation needs (e.g., overriding size). It's expected that users override
1431cb0ef41Sopenharmony_ci * MakeGarbageCollectedTrait (see below) and inherit from
1441cb0ef41Sopenharmony_ci * MakeGarbageCollectedTraitBase and make use of the low-level primitives
1451cb0ef41Sopenharmony_ci * offered to allocate and construct an object.
1461cb0ef41Sopenharmony_ci */
1471cb0ef41Sopenharmony_citemplate <typename T>
1481cb0ef41Sopenharmony_ciclass MakeGarbageCollectedTraitBase
1491cb0ef41Sopenharmony_ci    : private internal::MakeGarbageCollectedTraitInternal {
1501cb0ef41Sopenharmony_ci private:
1511cb0ef41Sopenharmony_ci  static_assert(internal::IsGarbageCollectedType<T>::value,
1521cb0ef41Sopenharmony_ci                "T needs to be a garbage collected object");
1531cb0ef41Sopenharmony_ci  static_assert(!IsGarbageCollectedWithMixinTypeV<T> ||
1541cb0ef41Sopenharmony_ci                    sizeof(T) <=
1551cb0ef41Sopenharmony_ci                        internal::api_constants::kLargeObjectSizeThreshold,
1561cb0ef41Sopenharmony_ci                "GarbageCollectedMixin may not be a large object");
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci protected:
1591cb0ef41Sopenharmony_ci  /**
1601cb0ef41Sopenharmony_ci   * Allocates memory for an object of type T.
1611cb0ef41Sopenharmony_ci   *
1621cb0ef41Sopenharmony_ci   * \param handle AllocationHandle identifying the heap to allocate the object
1631cb0ef41Sopenharmony_ci   *   on.
1641cb0ef41Sopenharmony_ci   * \param size The size that should be reserved for the object.
1651cb0ef41Sopenharmony_ci   * \returns the memory to construct an object of type T on.
1661cb0ef41Sopenharmony_ci   */
1671cb0ef41Sopenharmony_ci  V8_INLINE static void* Allocate(AllocationHandle& handle, size_t size) {
1681cb0ef41Sopenharmony_ci    static_assert(
1691cb0ef41Sopenharmony_ci        std::is_base_of<typename T::ParentMostGarbageCollectedType, T>::value,
1701cb0ef41Sopenharmony_ci        "U of GarbageCollected<U> must be a base of T. Check "
1711cb0ef41Sopenharmony_ci        "GarbageCollected<T> base class inheritance.");
1721cb0ef41Sopenharmony_ci    static constexpr size_t kWantedAlignment =
1731cb0ef41Sopenharmony_ci        alignof(T) < internal::api_constants::kDefaultAlignment
1741cb0ef41Sopenharmony_ci            ? internal::api_constants::kDefaultAlignment
1751cb0ef41Sopenharmony_ci            : alignof(T);
1761cb0ef41Sopenharmony_ci    static_assert(
1771cb0ef41Sopenharmony_ci        kWantedAlignment <= internal::api_constants::kMaxSupportedAlignment,
1781cb0ef41Sopenharmony_ci        "Requested alignment larger than alignof(std::max_align_t) bytes. "
1791cb0ef41Sopenharmony_ci        "Please file a bug to possibly get this restriction lifted.");
1801cb0ef41Sopenharmony_ci    return AllocationDispatcher<
1811cb0ef41Sopenharmony_ci        typename internal::GCInfoFolding<
1821cb0ef41Sopenharmony_ci            T, typename T::ParentMostGarbageCollectedType>::ResultType,
1831cb0ef41Sopenharmony_ci        typename SpaceTrait<T>::Space, kWantedAlignment>::Invoke(handle, size);
1841cb0ef41Sopenharmony_ci  }
1851cb0ef41Sopenharmony_ci
1861cb0ef41Sopenharmony_ci  /**
1871cb0ef41Sopenharmony_ci   * Marks an object as fully constructed, resulting in precise handling by the
1881cb0ef41Sopenharmony_ci   * garbage collector.
1891cb0ef41Sopenharmony_ci   *
1901cb0ef41Sopenharmony_ci   * \param payload The base pointer the object is allocated at.
1911cb0ef41Sopenharmony_ci   */
1921cb0ef41Sopenharmony_ci  V8_INLINE static void MarkObjectAsFullyConstructed(const void* payload) {
1931cb0ef41Sopenharmony_ci    internal::MakeGarbageCollectedTraitInternal::MarkObjectAsFullyConstructed(
1941cb0ef41Sopenharmony_ci        payload);
1951cb0ef41Sopenharmony_ci  }
1961cb0ef41Sopenharmony_ci};
1971cb0ef41Sopenharmony_ci
1981cb0ef41Sopenharmony_ci/**
1991cb0ef41Sopenharmony_ci * Passed to MakeGarbageCollected to specify how many bytes should be appended
2001cb0ef41Sopenharmony_ci * to the allocated object.
2011cb0ef41Sopenharmony_ci *
2021cb0ef41Sopenharmony_ci * Example:
2031cb0ef41Sopenharmony_ci * \code
2041cb0ef41Sopenharmony_ci * class InlinedArray final : public GarbageCollected<InlinedArray> {
2051cb0ef41Sopenharmony_ci *  public:
2061cb0ef41Sopenharmony_ci *   explicit InlinedArray(size_t bytes) : size(bytes), byte_array(this + 1) {}
2071cb0ef41Sopenharmony_ci *   void Trace(Visitor*) const {}
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ci *   size_t size;
2101cb0ef41Sopenharmony_ci *   char* byte_array;
2111cb0ef41Sopenharmony_ci * };
2121cb0ef41Sopenharmony_ci *
2131cb0ef41Sopenharmony_ci * auto* inlined_array = MakeGarbageCollected<InlinedArray(
2141cb0ef41Sopenharmony_ci *    GetAllocationHandle(), AdditionalBytes(4), 4);
2151cb0ef41Sopenharmony_ci * for (size_t i = 0; i < 4; i++) {
2161cb0ef41Sopenharmony_ci *   Process(inlined_array->byte_array[i]);
2171cb0ef41Sopenharmony_ci * }
2181cb0ef41Sopenharmony_ci * \endcode
2191cb0ef41Sopenharmony_ci */
2201cb0ef41Sopenharmony_cistruct AdditionalBytes {
2211cb0ef41Sopenharmony_ci  constexpr explicit AdditionalBytes(size_t bytes) : value(bytes) {}
2221cb0ef41Sopenharmony_ci  const size_t value;
2231cb0ef41Sopenharmony_ci};
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci/**
2261cb0ef41Sopenharmony_ci * Default trait class that specifies how to construct an object of type T.
2271cb0ef41Sopenharmony_ci * Advanced users may override how an object is constructed using the utilities
2281cb0ef41Sopenharmony_ci * that are provided through MakeGarbageCollectedTraitBase.
2291cb0ef41Sopenharmony_ci *
2301cb0ef41Sopenharmony_ci * Any trait overriding construction must
2311cb0ef41Sopenharmony_ci * - allocate through `MakeGarbageCollectedTraitBase<T>::Allocate`;
2321cb0ef41Sopenharmony_ci * - mark the object as fully constructed using
2331cb0ef41Sopenharmony_ci *   `MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed`;
2341cb0ef41Sopenharmony_ci */
2351cb0ef41Sopenharmony_citemplate <typename T>
2361cb0ef41Sopenharmony_ciclass MakeGarbageCollectedTrait : public MakeGarbageCollectedTraitBase<T> {
2371cb0ef41Sopenharmony_ci public:
2381cb0ef41Sopenharmony_ci  template <typename... Args>
2391cb0ef41Sopenharmony_ci  static T* Call(AllocationHandle& handle, Args&&... args) {
2401cb0ef41Sopenharmony_ci    void* memory =
2411cb0ef41Sopenharmony_ci        MakeGarbageCollectedTraitBase<T>::Allocate(handle, sizeof(T));
2421cb0ef41Sopenharmony_ci    T* object = ::new (memory) T(std::forward<Args>(args)...);
2431cb0ef41Sopenharmony_ci    MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed(object);
2441cb0ef41Sopenharmony_ci    return object;
2451cb0ef41Sopenharmony_ci  }
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci  template <typename... Args>
2481cb0ef41Sopenharmony_ci  static T* Call(AllocationHandle& handle, AdditionalBytes additional_bytes,
2491cb0ef41Sopenharmony_ci                 Args&&... args) {
2501cb0ef41Sopenharmony_ci    void* memory = MakeGarbageCollectedTraitBase<T>::Allocate(
2511cb0ef41Sopenharmony_ci        handle, sizeof(T) + additional_bytes.value);
2521cb0ef41Sopenharmony_ci    T* object = ::new (memory) T(std::forward<Args>(args)...);
2531cb0ef41Sopenharmony_ci    MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed(object);
2541cb0ef41Sopenharmony_ci    return object;
2551cb0ef41Sopenharmony_ci  }
2561cb0ef41Sopenharmony_ci};
2571cb0ef41Sopenharmony_ci
2581cb0ef41Sopenharmony_ci/**
2591cb0ef41Sopenharmony_ci * Allows users to specify a post-construction callback for specific types. The
2601cb0ef41Sopenharmony_ci * callback is invoked on the instance of type T right after it has been
2611cb0ef41Sopenharmony_ci * constructed. This can be useful when the callback requires a
2621cb0ef41Sopenharmony_ci * fully-constructed object to be able to dispatch to virtual methods.
2631cb0ef41Sopenharmony_ci */
2641cb0ef41Sopenharmony_citemplate <typename T, typename = void>
2651cb0ef41Sopenharmony_cistruct PostConstructionCallbackTrait {
2661cb0ef41Sopenharmony_ci  static void Call(T*) {}
2671cb0ef41Sopenharmony_ci};
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_ci/**
2701cb0ef41Sopenharmony_ci * Constructs a managed object of type T where T transitively inherits from
2711cb0ef41Sopenharmony_ci * GarbageCollected.
2721cb0ef41Sopenharmony_ci *
2731cb0ef41Sopenharmony_ci * \param args List of arguments with which an instance of T will be
2741cb0ef41Sopenharmony_ci *   constructed.
2751cb0ef41Sopenharmony_ci * \returns an instance of type T.
2761cb0ef41Sopenharmony_ci */
2771cb0ef41Sopenharmony_citemplate <typename T, typename... Args>
2781cb0ef41Sopenharmony_ciV8_INLINE T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
2791cb0ef41Sopenharmony_ci  T* object =
2801cb0ef41Sopenharmony_ci      MakeGarbageCollectedTrait<T>::Call(handle, std::forward<Args>(args)...);
2811cb0ef41Sopenharmony_ci  PostConstructionCallbackTrait<T>::Call(object);
2821cb0ef41Sopenharmony_ci  return object;
2831cb0ef41Sopenharmony_ci}
2841cb0ef41Sopenharmony_ci
2851cb0ef41Sopenharmony_ci/**
2861cb0ef41Sopenharmony_ci * Constructs a managed object of type T where T transitively inherits from
2871cb0ef41Sopenharmony_ci * GarbageCollected. Created objects will have additional bytes appended to
2881cb0ef41Sopenharmony_ci * it. Allocated memory would suffice for `sizeof(T) + additional_bytes`.
2891cb0ef41Sopenharmony_ci *
2901cb0ef41Sopenharmony_ci * \param additional_bytes Denotes how many bytes to append to T.
2911cb0ef41Sopenharmony_ci * \param args List of arguments with which an instance of T will be
2921cb0ef41Sopenharmony_ci *   constructed.
2931cb0ef41Sopenharmony_ci * \returns an instance of type T.
2941cb0ef41Sopenharmony_ci */
2951cb0ef41Sopenharmony_citemplate <typename T, typename... Args>
2961cb0ef41Sopenharmony_ciV8_INLINE T* MakeGarbageCollected(AllocationHandle& handle,
2971cb0ef41Sopenharmony_ci                                  AdditionalBytes additional_bytes,
2981cb0ef41Sopenharmony_ci                                  Args&&... args) {
2991cb0ef41Sopenharmony_ci  T* object = MakeGarbageCollectedTrait<T>::Call(handle, additional_bytes,
3001cb0ef41Sopenharmony_ci                                                 std::forward<Args>(args)...);
3011cb0ef41Sopenharmony_ci  PostConstructionCallbackTrait<T>::Call(object);
3021cb0ef41Sopenharmony_ci  return object;
3031cb0ef41Sopenharmony_ci}
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_ci}  // namespace cppgc
3061cb0ef41Sopenharmony_ci
3071cb0ef41Sopenharmony_ci#undef CPPGC_DEFAULT_ALIGNED
3081cb0ef41Sopenharmony_ci#undef CPPGC_DOUBLE_WORD_ALIGNED
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ci#endif  // INCLUDE_CPPGC_ALLOCATION_H_
311