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