11cb0ef41Sopenharmony_ci// Copyright 2021 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_EXPLICIT_MANAGEMENT_H_
61cb0ef41Sopenharmony_ci#define INCLUDE_CPPGC_EXPLICIT_MANAGEMENT_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <cstddef>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "cppgc/allocation.h"
111cb0ef41Sopenharmony_ci#include "cppgc/internal/logging.h"
121cb0ef41Sopenharmony_ci#include "cppgc/type-traits.h"
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_cinamespace cppgc {
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ciclass HeapHandle;
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cinamespace subtle {
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_citemplate <typename T>
211cb0ef41Sopenharmony_civoid FreeUnreferencedObject(HeapHandle& heap_handle, T& object);
221cb0ef41Sopenharmony_citemplate <typename T>
231cb0ef41Sopenharmony_cibool Resize(T& object, AdditionalBytes additional_bytes);
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci}  // namespace subtle
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_cinamespace internal {
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ciclass ExplicitManagementImpl final {
301cb0ef41Sopenharmony_ci private:
311cb0ef41Sopenharmony_ci  V8_EXPORT static void FreeUnreferencedObject(HeapHandle&, void*);
321cb0ef41Sopenharmony_ci  V8_EXPORT static bool Resize(void*, size_t);
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  template <typename T>
351cb0ef41Sopenharmony_ci  friend void subtle::FreeUnreferencedObject(HeapHandle&, T&);
361cb0ef41Sopenharmony_ci  template <typename T>
371cb0ef41Sopenharmony_ci  friend bool subtle::Resize(T&, AdditionalBytes);
381cb0ef41Sopenharmony_ci};
391cb0ef41Sopenharmony_ci}  // namespace internal
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_cinamespace subtle {
421cb0ef41Sopenharmony_ci
431cb0ef41Sopenharmony_ci/**
441cb0ef41Sopenharmony_ci * Informs the garbage collector that `object` can be immediately reclaimed. The
451cb0ef41Sopenharmony_ci * destructor may not be invoked immediately but only on next garbage
461cb0ef41Sopenharmony_ci * collection.
471cb0ef41Sopenharmony_ci *
481cb0ef41Sopenharmony_ci * It is up to the embedder to guarantee that no other object holds a reference
491cb0ef41Sopenharmony_ci * to `object` after calling `FreeUnreferencedObject()`. In case such a
501cb0ef41Sopenharmony_ci * reference exists, it's use results in a use-after-free.
511cb0ef41Sopenharmony_ci *
521cb0ef41Sopenharmony_ci * To aid in using the API, `FreeUnreferencedObject()` may be called from
531cb0ef41Sopenharmony_ci * destructors on objects that would be reclaimed in the same garbage collection
541cb0ef41Sopenharmony_ci * cycle.
551cb0ef41Sopenharmony_ci *
561cb0ef41Sopenharmony_ci * \param heap_handle The corresponding heap.
571cb0ef41Sopenharmony_ci * \param object Reference to an object that is of type `GarbageCollected` and
581cb0ef41Sopenharmony_ci *   should be immediately reclaimed.
591cb0ef41Sopenharmony_ci */
601cb0ef41Sopenharmony_citemplate <typename T>
611cb0ef41Sopenharmony_civoid FreeUnreferencedObject(HeapHandle& heap_handle, T& object) {
621cb0ef41Sopenharmony_ci  static_assert(IsGarbageCollectedTypeV<T>,
631cb0ef41Sopenharmony_ci                "Object must be of type GarbageCollected.");
641cb0ef41Sopenharmony_ci  internal::ExplicitManagementImpl::FreeUnreferencedObject(heap_handle,
651cb0ef41Sopenharmony_ci                                                           &object);
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci/**
691cb0ef41Sopenharmony_ci * Tries to resize `object` of type `T` with additional bytes on top of
701cb0ef41Sopenharmony_ci * sizeof(T). Resizing is only useful with trailing inlined storage, see e.g.
711cb0ef41Sopenharmony_ci * `MakeGarbageCollected(AllocationHandle&, AdditionalBytes)`.
721cb0ef41Sopenharmony_ci *
731cb0ef41Sopenharmony_ci * `Resize()` performs growing or shrinking as needed and may skip the operation
741cb0ef41Sopenharmony_ci * for internal reasons, see return value.
751cb0ef41Sopenharmony_ci *
761cb0ef41Sopenharmony_ci * It is up to the embedder to guarantee that in case of shrinking a larger
771cb0ef41Sopenharmony_ci * object down, the reclaimed area is not used anymore. Any subsequent use
781cb0ef41Sopenharmony_ci * results in a use-after-free.
791cb0ef41Sopenharmony_ci *
801cb0ef41Sopenharmony_ci * The `object` must be live when calling `Resize()`.
811cb0ef41Sopenharmony_ci *
821cb0ef41Sopenharmony_ci * \param object Reference to an object that is of type `GarbageCollected` and
831cb0ef41Sopenharmony_ci *   should be resized.
841cb0ef41Sopenharmony_ci * \param additional_bytes Bytes in addition to sizeof(T) that the object should
851cb0ef41Sopenharmony_ci *   provide.
861cb0ef41Sopenharmony_ci * \returns true when the operation was successful and the result can be relied
871cb0ef41Sopenharmony_ci *   on, and false otherwise.
881cb0ef41Sopenharmony_ci */
891cb0ef41Sopenharmony_citemplate <typename T>
901cb0ef41Sopenharmony_cibool Resize(T& object, AdditionalBytes additional_bytes) {
911cb0ef41Sopenharmony_ci  static_assert(IsGarbageCollectedTypeV<T>,
921cb0ef41Sopenharmony_ci                "Object must be of type GarbageCollected.");
931cb0ef41Sopenharmony_ci  return internal::ExplicitManagementImpl::Resize(
941cb0ef41Sopenharmony_ci      &object, sizeof(T) + additional_bytes.value);
951cb0ef41Sopenharmony_ci}
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci}  // namespace subtle
981cb0ef41Sopenharmony_ci}  // namespace cppgc
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci#endif  // INCLUDE_CPPGC_EXPLICIT_MANAGEMENT_H_
101