| // Copyright 2021 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 V8_OBJECTS_MANAGED_INL_H_ |
| #define V8_OBJECTS_MANAGED_INL_H_ |
| |
| #include "src/objects/managed.h" |
| // Include the non-inl header before the rest of the headers. |
| |
| #include "include/cppgc/allocation.h" |
| #include "include/cppgc/heap.h" |
| #include "include/v8-isolate.h" |
| #include "include/v8-sandbox.h" |
| #include "src/execution/isolate.h" |
| #include "src/handles/global-handles-inl.h" |
| #include "src/heap/factory.h" |
| #include "src/heap/heap-write-barrier-inl.h" |
| #include "src/objects/heap-object-field-inl.h" |
| |
| namespace v8::internal { |
| |
| namespace detail { |
| // Called by either isolate shutdown or the {ManagedObjectFinalizer} in order |
| // to actually delete the shared pointer and decrement the shared refcount. |
| template <typename CppType> |
| void Destructor(void* ptr) { |
| auto shared_ptr_ptr = reinterpret_cast<std::shared_ptr<CppType>*>(ptr); |
| delete shared_ptr_ptr; |
| } |
| } // namespace detail |
| |
| // static |
| template <class CppType> |
| DirectHandle<Managed<CppType>> Managed<CppType>::From( |
| Isolate* isolate, size_t estimated_size, |
| std::shared_ptr<CppType> shared_ptr, AllocationType allocation_type) { |
| static constexpr ExternalPointerTag kTag = TagForManaged<CppType>::value; |
| static_assert(IsManagedExternalPointerType(kTag)); |
| SharedFlag shared = SharedFlag(IsSharedAllocationType(allocation_type)); |
| auto destructor = new ManagedPtrDestructor( |
| estimated_size, new std::shared_ptr<CppType>{std::move(shared_ptr)}, |
| detail::Destructor<CppType>, shared); |
| destructor->external_memory_accounter_.Increase( |
| reinterpret_cast<v8::Isolate*>(shared ? isolate->shared_space_isolate() |
| : isolate), |
| estimated_size); |
| DirectHandle<Managed<CppType>> handle = |
| Cast<Managed<CppType>>(isolate->factory()->NewForeign<kTag>( |
| reinterpret_cast<Address>(destructor), allocation_type)); |
| IndirectHandle<Object> global_handle = |
| isolate->global_handles()->Create(*handle); |
| SharedObjectConditionalSafePublishGuard publish_guard(*handle, |
| allocation_type); |
| destructor->global_handle_location_ = global_handle.location(); |
| GlobalHandles::MakeWeak(destructor->global_handle_location_, destructor, |
| &ManagedObjectFinalizer, |
| v8::WeakCallbackType::kParameter); |
| isolate->RegisterManagedPtrDestructor(destructor); |
| return handle; |
| } |
| |
| // static |
| template <class CppType> |
| DirectHandle<TrustedManaged<CppType>> TrustedManaged<CppType>::From( |
| Isolate* isolate, size_t estimated_size, |
| std::shared_ptr<CppType> shared_ptr) { |
| auto destructor = new ManagedPtrDestructor( |
| estimated_size, new std::shared_ptr<CppType>{std::move(shared_ptr)}, |
| detail::Destructor<CppType>, SharedFlag{false}); |
| destructor->external_memory_accounter_.Increase( |
| reinterpret_cast<v8::Isolate*>(isolate), estimated_size); |
| DirectHandle<TrustedManaged<CppType>> handle = |
| TrustedCast<TrustedManaged<CppType>>( |
| isolate->factory()->NewTrustedForeign( |
| reinterpret_cast<Address>(destructor))); |
| IndirectHandle<Object> global_handle = |
| isolate->global_handles()->Create(Cast<Object>(*handle)); |
| destructor->global_handle_location_ = global_handle.location(); |
| GlobalHandles::MakeWeak(destructor->global_handle_location_, destructor, |
| &ManagedObjectFinalizer, |
| v8::WeakCallbackType::kParameter); |
| isolate->RegisterManagedPtrDestructor(destructor); |
| return handle; |
| } |
| |
| inline CppGCManagedWrapper* CppGCManagedBase::GetWrapper() const { |
| return reinterpret_cast<CppGCManagedWrapper*>( |
| ReadCppHeapPointerField(offsetof(CppGCManagedBase, cpp_gc_wrapper_), |
| Isolate::Current(), kCppGCManagedTag)); |
| } |
| |
| inline size_t CppGCManagedBase::estimated_size() const { |
| return GetWrapper()->estimated_size(); |
| } |
| |
| // static |
| template <class CppType> |
| Handle<CppGCManaged<CppType>> CppGCManaged<CppType>::Create( |
| Isolate* isolate, size_t estimated_size, |
| std::shared_ptr<CppType> shared_ptr, AllocationType allocation_type) { |
| auto* shared_ptr_ptr = new std::shared_ptr<CppType>(std::move(shared_ptr)); |
| auto* destructor = cppgc::MakeGarbageCollected<CppGCManagedWrapper>( |
| reinterpret_cast<v8::Isolate*>(isolate) |
| ->GetCppHeap() |
| ->GetAllocationHandle(), |
| TypeIdForManaged<CppType>::value, estimated_size, shared_ptr_ptr, |
| detail::Destructor<CppType>, reinterpret_cast<v8::Isolate*>(isolate), |
| isolate->cpp_heap_isolate_alive_token()); |
| Tagged<CppGCManagedBase> raw = |
| *isolate->factory()->NewCppGCManagedBase(allocation_type); |
| raw->WriteLazilyInitializedCppHeapPointerField( |
| offsetof(CppGCManagedBase, cpp_gc_wrapper_), isolate, |
| reinterpret_cast<Address>(destructor), kCppGCManagedTag); |
| WriteBarrier::ForCppHeapPointer( |
| raw, |
| raw->RawCppHeapPointerField(offsetof(CppGCManagedBase, cpp_gc_wrapper_)), |
| destructor); |
| return handle(Cast<CppGCManaged<CppType>>(raw), isolate); |
| } |
| |
| template <class CppType> |
| typename CppGCManaged<CppType>::Ptr CppGCManaged<CppType>::ptr() const { |
| return Ptr(get()); |
| } |
| |
| template <class CppType> |
| CppType* CppGCManaged<CppType>::raw( |
| const DisallowGarbageCollection& no_gc) const { |
| return GetSharedPtr()->get(); |
| } |
| |
| template <class CppType> |
| std::shared_ptr<CppType> CppGCManaged<CppType>::get() const { |
| return *GetSharedPtr(); |
| } |
| |
| template <class CppType> |
| std::shared_ptr<CppType>* CppGCManaged<CppType>::GetSharedPtr() const { |
| auto wrapper = GetWrapper(); |
| CHECK_EQ(wrapper->type_id(), TypeIdForManaged<CppType>::value); |
| return reinterpret_cast<std::shared_ptr<CppType>*>(wrapper->shared_ptr_ptr()); |
| } |
| |
| template <class CppType> |
| void CppGCManaged<CppType>::SetManagedObject( |
| std::shared_ptr<CppType> new_managed, Isolate* isolate, |
| size_t new_estimated_size) { |
| CppGCManagedWrapper* wrapper = GetWrapper(); |
| *GetSharedPtr() = std::move(new_managed); |
| wrapper->UpdateEstimatedSize(new_estimated_size, isolate); |
| } |
| |
| } // namespace v8::internal |
| |
| #endif // V8_OBJECTS_MANAGED_INL_H_ |