// 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 #include #include "include/cppgc/garbage-collected.h" #include "include/cppgc/gc-info.h" #include "include/cppgc/heap.h" #include "include/cppgc/internals.h" namespace cppgc { template class MakeGarbageCollectedTraitBase; 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* atomic_mutable_bitfield = reinterpret_cast*>( const_cast(reinterpret_cast( reinterpret_cast(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::Heap* heap, size_t size, GCInfoIndex index); friend class HeapObjectHeader; }; } // namespace internal // Users with custom allocation needs (e.g. overriding size) should override // MakeGarbageCollectedTrait (see below) and inherit their trait from // MakeGarbageCollectedTraitBase to get access to low-level primitives. template class MakeGarbageCollectedTraitBase : private internal::MakeGarbageCollectedTraitInternal { protected: // Allocates an object of |size| bytes on |heap|. // // TODO(mlippautz): Allow specifying arena for specific embedder uses. static void* Allocate(Heap* heap, size_t size) { return internal::MakeGarbageCollectedTraitInternal::Allocate( heap, size, internal::GCInfoTrait::Index()); } // Marks an object as being fully constructed, resulting in precise handling // by the garbage collector. static void MarkObjectAsFullyConstructed(const void* payload) { // internal::MarkObjectAsFullyConstructed(payload); internal::MakeGarbageCollectedTraitInternal::MarkObjectAsFullyConstructed( payload); } }; template class MakeGarbageCollectedTrait : public MakeGarbageCollectedTraitBase { public: template static T* Call(Heap* heap, Args&&... args) { static_assert(internal::IsGarbageCollectedType::value, "T needs to be a garbage collected object"); void* memory = MakeGarbageCollectedTraitBase::Allocate(heap, sizeof(T)); T* object = ::new (memory) T(std::forward(args)...); MakeGarbageCollectedTraitBase::MarkObjectAsFullyConstructed(object); return object; } }; // Default MakeGarbageCollected: Constructs an instance of T, which is a garbage // collected type. template T* MakeGarbageCollected(Heap* heap, Args&&... args) { return MakeGarbageCollectedTrait::Call(heap, std::forward(args)...); } } // namespace cppgc #endif // INCLUDE_CPPGC_ALLOCATION_H_