summaryrefslogtreecommitdiff
path: root/chromium/v8/include/cppgc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/v8/include/cppgc
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/v8/include/cppgc')
-rw-r--r--chromium/v8/include/cppgc/allocation.h42
-rw-r--r--chromium/v8/include/cppgc/garbage-collected.h5
-rw-r--r--chromium/v8/include/cppgc/heap.h78
-rw-r--r--chromium/v8/include/cppgc/internal/accessors.h26
-rw-r--r--chromium/v8/include/cppgc/internal/api-constants.h17
-rw-r--r--chromium/v8/include/cppgc/internal/atomic-entry-flag.h48
-rw-r--r--chromium/v8/include/cppgc/internal/caged-heap-local-data.h67
-rw-r--r--chromium/v8/include/cppgc/internal/compiler-specific.h12
-rw-r--r--chromium/v8/include/cppgc/internal/gc-info.h6
-rw-r--r--chromium/v8/include/cppgc/internal/persistent-node.h9
-rw-r--r--chromium/v8/include/cppgc/internal/pointer-policies.h7
-rw-r--r--chromium/v8/include/cppgc/internal/prefinalizer-handler.h7
-rw-r--r--chromium/v8/include/cppgc/internal/process-heap.h34
-rw-r--r--chromium/v8/include/cppgc/internal/write-barrier.h78
-rw-r--r--chromium/v8/include/cppgc/liveness-broker.h30
-rw-r--r--chromium/v8/include/cppgc/macros.h22
-rw-r--r--chromium/v8/include/cppgc/member.h54
-rw-r--r--chromium/v8/include/cppgc/persistent.h95
-rw-r--r--chromium/v8/include/cppgc/platform.h112
-rw-r--r--chromium/v8/include/cppgc/prefinalizer.h6
-rw-r--r--chromium/v8/include/cppgc/source-location.h36
-rw-r--r--chromium/v8/include/cppgc/trace-trait.h44
-rw-r--r--chromium/v8/include/cppgc/visitor.h143
23 files changed, 794 insertions, 184 deletions
diff --git a/chromium/v8/include/cppgc/allocation.h b/chromium/v8/include/cppgc/allocation.h
index 49ad49c34d6..ac5062ad01a 100644
--- a/chromium/v8/include/cppgc/allocation.h
+++ b/chromium/v8/include/cppgc/allocation.h
@@ -11,7 +11,6 @@
#include "cppgc/custom-space.h"
#include "cppgc/garbage-collected.h"
-#include "cppgc/heap.h"
#include "cppgc/internal/api-constants.h"
#include "cppgc/internal/gc-info.h"
@@ -21,6 +20,15 @@ template <typename T>
class MakeGarbageCollectedTraitBase;
namespace internal {
+class ObjectAllocator;
+} // namespace internal
+
+/**
+ * AllocationHandle is used to allocate garbage-collected objects.
+ */
+class AllocationHandle;
+
+namespace internal {
class V8_EXPORT MakeGarbageCollectedTraitInternal {
protected:
@@ -36,9 +44,10 @@ class V8_EXPORT MakeGarbageCollectedTraitInternal {
atomic_mutable_bitfield->store(value, std::memory_order_release);
}
- static void* Allocate(cppgc::Heap* heap, size_t size, GCInfoIndex index);
- static void* Allocate(cppgc::Heap* heapx, size_t size, GCInfoIndex index,
- CustomSpaceIndex space_inde);
+ static void* Allocate(cppgc::AllocationHandle& handle, size_t size,
+ GCInfoIndex index);
+ static void* Allocate(cppgc::AllocationHandle& handle, size_t size,
+ GCInfoIndex index, CustomSpaceIndex space_index);
friend class HeapObjectHeader;
};
@@ -58,22 +67,22 @@ class MakeGarbageCollectedTraitBase
private:
template <typename U, typename CustomSpace>
struct SpacePolicy {
- static void* Allocate(Heap* heap, size_t size) {
+ static void* Allocate(AllocationHandle& handle, size_t size) {
// Custom space.
static_assert(std::is_base_of<CustomSpaceBase, CustomSpace>::value,
"Custom space must inherit from CustomSpaceBase.");
return internal::MakeGarbageCollectedTraitInternal::Allocate(
- heap, size, internal::GCInfoTrait<T>::Index(),
+ handle, size, internal::GCInfoTrait<T>::Index(),
CustomSpace::kSpaceIndex);
}
};
template <typename U>
struct SpacePolicy<U, void> {
- static void* Allocate(Heap* heap, size_t size) {
+ static void* Allocate(AllocationHandle& handle, size_t size) {
// Default space.
return internal::MakeGarbageCollectedTraitInternal::Allocate(
- heap, size, internal::GCInfoTrait<T>::Index());
+ handle, size, internal::GCInfoTrait<T>::Index());
}
};
@@ -81,12 +90,14 @@ class MakeGarbageCollectedTraitBase
/**
* Allocates memory for an object of type T.
*
- * \param heap The heap to allocate this object on.
+ * \param handle AllocationHandle identifying the heap to allocate the object
+ * on.
* \param size The size that should be reserved for the object.
* \returns the memory to construct an object of type T on.
*/
- static void* Allocate(Heap* heap, size_t size) {
- return SpacePolicy<T, typename SpaceTrait<T>::Space>::Allocate(heap, size);
+ static void* Allocate(AllocationHandle& handle, size_t size) {
+ return SpacePolicy<T, typename SpaceTrait<T>::Space>::Allocate(handle,
+ size);
}
/**
@@ -115,14 +126,15 @@ template <typename T>
class MakeGarbageCollectedTrait : public MakeGarbageCollectedTraitBase<T> {
public:
template <typename... Args>
- static T* Call(Heap* heap, Args&&... args) {
+ static T* Call(AllocationHandle& handle, Args&&... args) {
static_assert(internal::IsGarbageCollectedType<T>::value,
"T needs to be a garbage collected object");
static_assert(
!internal::IsGarbageCollectedMixinType<T>::value ||
sizeof(T) <= internal::api_constants::kLargeObjectSizeThreshold,
"GarbageCollectedMixin may not be a large object");
- void* memory = MakeGarbageCollectedTraitBase<T>::Allocate(heap, sizeof(T));
+ void* memory =
+ MakeGarbageCollectedTraitBase<T>::Allocate(handle, sizeof(T));
T* object = ::new (memory) T(std::forward<Args>(args)...);
MakeGarbageCollectedTraitBase<T>::MarkObjectAsFullyConstructed(object);
return object;
@@ -149,9 +161,9 @@ struct PostConstructionCallbackTrait {
* \returns an instance of type T.
*/
template <typename T, typename... Args>
-T* MakeGarbageCollected(Heap* heap, Args&&... args) {
+T* MakeGarbageCollected(AllocationHandle& handle, Args&&... args) {
T* object =
- MakeGarbageCollectedTrait<T>::Call(heap, std::forward<Args>(args)...);
+ MakeGarbageCollectedTrait<T>::Call(handle, std::forward<Args>(args)...);
PostConstructionCallbackTrait<T>::Call(object);
return object;
}
diff --git a/chromium/v8/include/cppgc/garbage-collected.h b/chromium/v8/include/cppgc/garbage-collected.h
index c263a9fecf0..299b861d845 100644
--- a/chromium/v8/include/cppgc/garbage-collected.h
+++ b/chromium/v8/include/cppgc/garbage-collected.h
@@ -8,7 +8,6 @@
#include <type_traits>
#include "cppgc/internal/api-constants.h"
-#include "cppgc/macros.h"
#include "cppgc/platform.h"
#include "cppgc/trace-trait.h"
#include "cppgc/type-traits.h"
@@ -161,7 +160,7 @@ class GarbageCollectedMixin : public internal::GarbageCollectedBase {
} \
\
private: \
- friend class internal::__thisIsHereToForceASemicolonAfterThisMacro
+ static_assert(true, "Force semicolon.")
/**
* Merge two or more Mixins into one.
@@ -185,7 +184,7 @@ class GarbageCollectedMixin : public internal::GarbageCollectedBase {
} \
\
private: \
- friend class internal::__thisIsHereToForceASemicolonAfterThisMacro
+ static_assert(true, "Force semicolon.")
} // namespace cppgc
diff --git a/chromium/v8/include/cppgc/heap.h b/chromium/v8/include/cppgc/heap.h
index 90046c35055..ca0dbeca7ff 100644
--- a/chromium/v8/include/cppgc/heap.h
+++ b/chromium/v8/include/cppgc/heap.h
@@ -10,9 +10,21 @@
#include "cppgc/common.h"
#include "cppgc/custom-space.h"
+#include "cppgc/platform.h"
#include "v8config.h" // NOLINT(build/include_directory)
+/**
+ * cppgc - A C++ garbage collection library.
+ */
namespace cppgc {
+
+class AllocationHandle;
+
+/**
+ * Implementation details of cppgc. Those details are considered internal and
+ * may change at any point in time without notice. Users should never rely on
+ * the contents of this namespace.
+ */
namespace internal {
class Heap;
} // namespace internal
@@ -24,7 +36,44 @@ class V8_EXPORT Heap {
*/
using StackState = EmbedderStackState;
+ /**
+ * Specifies whether conservative stack scanning is supported.
+ */
+ enum class StackSupport : uint8_t {
+ /**
+ * Conservative stack scan is supported.
+ */
+ kSupportsConservativeStackScan,
+ /**
+ * Conservative stack scan is not supported. Embedders may use this option
+ * when using custom infrastructure that is unsupported by the library.
+ */
+ kNoConservativeStackScan,
+ };
+
+ /**
+ * Constraints for a Heap setup.
+ */
+ struct ResourceConstraints {
+ /**
+ * Allows the heap to grow to some initial size in bytes before triggering
+ * garbage collections. This is useful when it is known that applications
+ * need a certain minimum heap to run to avoid repeatedly invoking the
+ * garbage collector when growing the heap.
+ */
+ size_t initial_heap_size_bytes = 0;
+ };
+
+ /**
+ * Options specifying Heap properties (e.g. custom spaces) when initializing a
+ * heap through Heap::Create().
+ */
struct HeapOptions {
+ /**
+ * Creates reasonable defaults for instantiating a Heap.
+ *
+ * \returns the HeapOptions that can be passed to Heap::Create().
+ */
static HeapOptions Default() { return {}; }
/**
@@ -33,9 +82,34 @@ class V8_EXPORT Heap {
* to the index they reside in the vector.
*/
std::vector<std::unique_ptr<CustomSpaceBase>> custom_spaces;
+
+ /**
+ * Specifies whether conserative stack scan is supported. When conservative
+ * stack scan is not supported, the collector may try to invoke
+ * garbage collections using non-nestable task, which are guaranteed to have
+ * no interesting stack, through the provided Platform. If such tasks are
+ * not supported by the Platform, the embedder must take care of invoking
+ * the GC through ForceGarbageCollectionSlow().
+ */
+ StackSupport stack_support = StackSupport::kSupportsConservativeStackScan;
+
+ /**
+ * Resource constraints specifying various properties that the internal
+ * GC scheduler follows.
+ */
+ ResourceConstraints resource_constraints;
};
- static std::unique_ptr<Heap> Create(HeapOptions = HeapOptions::Default());
+ /**
+ * Creates a new heap that can be used for object allocation.
+ *
+ * \param platform implemented and provided by the embedder.
+ * \param options HeapOptions specifying various properties for the Heap.
+ * \returns a new Heap instance.
+ */
+ static std::unique_ptr<Heap> Create(
+ std::shared_ptr<Platform> platform,
+ HeapOptions options = HeapOptions::Default());
virtual ~Heap() = default;
@@ -52,6 +126,8 @@ class V8_EXPORT Heap {
const char* source, const char* reason,
StackState stack_state = StackState::kMayContainHeapPointers);
+ AllocationHandle& GetAllocationHandle();
+
private:
Heap() = default;
diff --git a/chromium/v8/include/cppgc/internal/accessors.h b/chromium/v8/include/cppgc/internal/accessors.h
deleted file mode 100644
index ee0a0042fe0..00000000000
--- a/chromium/v8/include/cppgc/internal/accessors.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// 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_INTERNAL_ACCESSORS_H_
-#define INCLUDE_CPPGC_INTERNAL_ACCESSORS_H_
-
-#include "cppgc/internal/api-constants.h"
-
-namespace cppgc {
-
-class Heap;
-
-namespace internal {
-
-inline cppgc::Heap* GetHeapFromPayload(const void* payload) {
- return *reinterpret_cast<cppgc::Heap**>(
- ((reinterpret_cast<uintptr_t>(payload) & api_constants::kPageBaseMask) +
- api_constants::kGuardPageSize) +
- api_constants::kHeapOffset);
-}
-
-} // namespace internal
-} // namespace cppgc
-
-#endif // INCLUDE_CPPGC_INTERNAL_ACCESSORS_H_
diff --git a/chromium/v8/include/cppgc/internal/api-constants.h b/chromium/v8/include/cppgc/internal/api-constants.h
index ef910a48571..1303b8b861f 100644
--- a/chromium/v8/include/cppgc/internal/api-constants.h
+++ b/chromium/v8/include/cppgc/internal/api-constants.h
@@ -17,6 +17,11 @@ namespace internal {
// Internal constants to avoid exposing internal types on the API surface.
namespace api_constants {
+
+constexpr size_t kKB = 1024;
+constexpr size_t kMB = kKB * 1024;
+constexpr size_t kGB = kMB * 1024;
+
// Offset of the uint16_t bitfield from the payload contaning the
// in-construction bit. This is subtracted from the payload pointer to get
// to the right bitfield.
@@ -25,17 +30,15 @@ static constexpr size_t kFullyConstructedBitFieldOffsetFromPayload =
// Mask for in-construction bit.
static constexpr size_t kFullyConstructedBitMask = size_t{1};
-// Page constants used to align pointers to page begin.
static constexpr size_t kPageSize = size_t{1} << 17;
-static constexpr size_t kPageAlignment = kPageSize;
-static constexpr size_t kPageBaseMask = ~(kPageAlignment - 1);
-static constexpr size_t kGuardPageSize = 4096;
-
-// Offset of the Heap backref.
-static constexpr size_t kHeapOffset = 0;
static constexpr size_t kLargeObjectSizeThreshold = kPageSize / 2;
+#if defined(CPPGC_CAGED_HEAP)
+constexpr size_t kCagedHeapReservationSize = static_cast<size_t>(4) * kGB;
+constexpr size_t kCagedHeapReservationAlignment = kCagedHeapReservationSize;
+#endif
+
} // namespace api_constants
} // namespace internal
diff --git a/chromium/v8/include/cppgc/internal/atomic-entry-flag.h b/chromium/v8/include/cppgc/internal/atomic-entry-flag.h
new file mode 100644
index 00000000000..5a7d3b8f8ac
--- /dev/null
+++ b/chromium/v8/include/cppgc/internal/atomic-entry-flag.h
@@ -0,0 +1,48 @@
+// 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_INTERNAL_ATOMIC_ENTRY_FLAG_H_
+#define INCLUDE_CPPGC_INTERNAL_ATOMIC_ENTRY_FLAG_H_
+
+#include <atomic>
+
+namespace cppgc {
+namespace internal {
+
+// A flag which provides a fast check whether a scope may be entered on the
+// current thread, without needing to access thread-local storage or mutex. Can
+// have false positives (i.e., spuriously report that it might be entered), so
+// it is expected that this will be used in tandem with a precise check that the
+// scope is in fact entered on that thread.
+//
+// Example:
+// g_frobnicating_flag.MightBeEntered() &&
+// ThreadLocalFrobnicator().IsFrobnicating()
+//
+// Relaxed atomic operations are sufficient, since:
+// - all accesses remain atomic
+// - each thread must observe its own operations in order
+// - no thread ever exits the flag more times than it enters (if used correctly)
+// And so if a thread observes zero, it must be because it has observed an equal
+// number of exits as entries.
+class AtomicEntryFlag final {
+ public:
+ void Enter() { entries_.fetch_add(1, std::memory_order_relaxed); }
+ void Exit() { entries_.fetch_sub(1, std::memory_order_relaxed); }
+
+ // Returns false only if the current thread is not between a call to Enter
+ // and a call to Exit. Returns true if this thread or another thread may
+ // currently be in the scope guarded by this flag.
+ bool MightBeEntered() const {
+ return entries_.load(std::memory_order_relaxed) != 0;
+ }
+
+ private:
+ std::atomic_int entries_{0};
+};
+
+} // namespace internal
+} // namespace cppgc
+
+#endif // INCLUDE_CPPGC_INTERNAL_ATOMIC_ENTRY_FLAG_H_
diff --git a/chromium/v8/include/cppgc/internal/caged-heap-local-data.h b/chromium/v8/include/cppgc/internal/caged-heap-local-data.h
new file mode 100644
index 00000000000..8c421477384
--- /dev/null
+++ b/chromium/v8/include/cppgc/internal/caged-heap-local-data.h
@@ -0,0 +1,67 @@
+// 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_INTERNAL_CAGED_HEAP_LOCAL_DATA_H_
+#define INCLUDE_CPPGC_INTERNAL_CAGED_HEAP_LOCAL_DATA_H_
+
+#include <array>
+
+#include "cppgc/internal/api-constants.h"
+#include "cppgc/internal/logging.h"
+#include "cppgc/platform.h"
+
+namespace cppgc {
+namespace internal {
+
+class HeapBase;
+
+#if defined(CPPGC_YOUNG_GENERATION)
+
+// AgeTable contains entries that correspond to 4KB memory regions. Each entry
+// can be in one of three states: kOld, kYoung or kUnknown.
+class AgeTable final {
+ static constexpr size_t kGranularityBits = 12; // 4KiB per byte.
+
+ public:
+ enum class Age : uint8_t { kOld, kYoung, kUnknown };
+
+ static constexpr size_t kEntrySizeInBytes = 1 << kGranularityBits;
+
+ Age& operator[](uintptr_t offset) { return table_[entry(offset)]; }
+ Age operator[](uintptr_t offset) const { return table_[entry(offset)]; }
+
+ void Reset(PageAllocator* allocator);
+
+ private:
+ static constexpr size_t kAgeTableSize =
+ api_constants::kCagedHeapReservationSize >> kGranularityBits;
+
+ size_t entry(uintptr_t offset) const {
+ const size_t entry = offset >> kGranularityBits;
+ CPPGC_DCHECK(table_.size() > entry);
+ return entry;
+ }
+
+ std::array<Age, kAgeTableSize> table_;
+};
+
+static_assert(sizeof(AgeTable) == 1 * api_constants::kMB,
+ "Size of AgeTable is 1MB");
+
+#endif // CPPGC_YOUNG_GENERATION
+
+struct CagedHeapLocalData final {
+ explicit CagedHeapLocalData(HeapBase* heap_base) : heap_base(heap_base) {}
+
+ bool is_marking_in_progress = false;
+ HeapBase* heap_base = nullptr;
+#if defined(CPPGC_YOUNG_GENERATION)
+ AgeTable age_table;
+#endif
+};
+
+} // namespace internal
+} // namespace cppgc
+
+#endif // INCLUDE_CPPGC_INTERNAL_CAGED_HEAP_LOCAL_DATA_H_
diff --git a/chromium/v8/include/cppgc/internal/compiler-specific.h b/chromium/v8/include/cppgc/internal/compiler-specific.h
index e1f5c1d57fb..c580894b35d 100644
--- a/chromium/v8/include/cppgc/internal/compiler-specific.h
+++ b/chromium/v8/include/cppgc/internal/compiler-specific.h
@@ -7,6 +7,12 @@
namespace cppgc {
+#if defined(__has_attribute)
+#define CPPGC_HAS_ATTRIBUTE(FEATURE) __has_attribute(FEATURE)
+#else
+#define CPPGC_HAS_ATTRIBUTE(FEATURE) 0
+#endif
+
#if defined(__has_cpp_attribute)
#define CPPGC_HAS_CPP_ATTRIBUTE(FEATURE) __has_cpp_attribute(FEATURE)
#else
@@ -21,6 +27,12 @@ namespace cppgc {
#define CPPGC_NO_UNIQUE_ADDRESS
#endif
+#if CPPGC_HAS_ATTRIBUTE(unused) // NOLINTNEXTLINE
+#define CPPGC_UNUSED __attribute__((unused))
+#else
+#define CPPGC_UNUSED
+#endif
+
} // namespace cppgc
#endif // INCLUDE_CPPGC_INTERNAL_COMPILER_SPECIFIC_H_
diff --git a/chromium/v8/include/cppgc/internal/gc-info.h b/chromium/v8/include/cppgc/internal/gc-info.h
index 9aac1361c61..3d361e6d71a 100644
--- a/chromium/v8/include/cppgc/internal/gc-info.h
+++ b/chromium/v8/include/cppgc/internal/gc-info.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "cppgc/internal/finalizer-trait.h"
+#include "cppgc/trace-trait.h"
#include "v8config.h" // NOLINT(build/include_directory)
namespace cppgc {
@@ -18,7 +19,7 @@ using GCInfoIndex = uint16_t;
class V8_EXPORT RegisteredGCInfoIndex final {
public:
RegisteredGCInfoIndex(FinalizationCallback finalization_callback,
- bool has_v_table);
+ TraceCallback trace_callback, bool has_v_table);
GCInfoIndex GetIndex() const { return index_; }
private:
@@ -32,7 +33,8 @@ struct GCInfoTrait {
static GCInfoIndex Index() {
static_assert(sizeof(T), "T must be fully defined");
static const RegisteredGCInfoIndex registered_index(
- FinalizerTrait<T>::kCallback, std::is_polymorphic<T>::value);
+ FinalizerTrait<T>::kCallback, TraceTrait<T>::Trace,
+ std::is_polymorphic<T>::value);
return registered_index.GetIndex();
}
};
diff --git a/chromium/v8/include/cppgc/internal/persistent-node.h b/chromium/v8/include/cppgc/internal/persistent-node.h
index 11cf69623e8..e05efe36213 100644
--- a/chromium/v8/include/cppgc/internal/persistent-node.h
+++ b/chromium/v8/include/cppgc/internal/persistent-node.h
@@ -56,6 +56,11 @@ class PersistentNode final {
bool IsUsed() const { return trace_; }
+ void* owner() const {
+ CPPGC_DCHECK(IsUsed());
+ return owner_;
+ }
+
private:
// PersistentNode acts as a designated union:
// If trace_ != nullptr, owner_ points to the corresponding Persistent handle.
@@ -67,11 +72,13 @@ class PersistentNode final {
TraceCallback trace_ = nullptr;
};
-class V8_EXPORT PersistentRegion {
+class V8_EXPORT PersistentRegion final {
using PersistentNodeSlots = std::array<PersistentNode, 256u>;
public:
PersistentRegion() = default;
+ // Clears Persistent fields to avoid stale pointers after heap teardown.
+ ~PersistentRegion();
PersistentRegion(const PersistentRegion&) = delete;
PersistentRegion& operator=(const PersistentRegion&) = delete;
diff --git a/chromium/v8/include/cppgc/internal/pointer-policies.h b/chromium/v8/include/cppgc/internal/pointer-policies.h
index fe8d94b57a6..a6cd4e8586d 100644
--- a/chromium/v8/include/cppgc/internal/pointer-policies.h
+++ b/chromium/v8/include/cppgc/internal/pointer-policies.h
@@ -8,6 +8,7 @@
#include <cstdint>
#include <type_traits>
+#include "cppgc/internal/write-barrier.h"
#include "cppgc/source-location.h"
#include "v8config.h" // NOLINT(build/include_directory)
@@ -26,8 +27,8 @@ struct DijkstraWriteBarrierPolicy {
// Since in initializing writes the source object is always white, having no
// barrier doesn't break the tri-color invariant.
}
- static void AssigningBarrier(const void*, const void*) {
- // TODO(chromium:1056170): Add actual implementation.
+ static void AssigningBarrier(const void* slot, const void* value) {
+ WriteBarrier::MarkingBarrier(slot, value);
}
};
@@ -116,7 +117,7 @@ class BasicMember;
struct SentinelPointer {
template <typename T>
operator T*() const { // NOLINT
- static constexpr intptr_t kSentinelValue = -1;
+ static constexpr intptr_t kSentinelValue = 1;
return reinterpret_cast<T*>(kSentinelValue);
}
// Hidden friends.
diff --git a/chromium/v8/include/cppgc/internal/prefinalizer-handler.h b/chromium/v8/include/cppgc/internal/prefinalizer-handler.h
index 939a9b8ff0a..ea0eca02a0e 100644
--- a/chromium/v8/include/cppgc/internal/prefinalizer-handler.h
+++ b/chromium/v8/include/cppgc/internal/prefinalizer-handler.h
@@ -15,14 +15,13 @@ class V8_EXPORT PreFinalizerRegistrationDispatcher final {
public:
using PreFinalizerCallback = bool (*)(const LivenessBroker&, void*);
struct PreFinalizer {
- void* object_;
- PreFinalizerCallback callback_;
+ void* object;
+ PreFinalizerCallback callback;
bool operator==(const PreFinalizer& other);
};
- static void RegisterPrefinalizer(cppgc::Heap* heap,
- PreFinalizer prefinalzier);
+ static void RegisterPrefinalizer(PreFinalizer pre_finalizer);
};
} // namespace internal
diff --git a/chromium/v8/include/cppgc/internal/process-heap.h b/chromium/v8/include/cppgc/internal/process-heap.h
new file mode 100644
index 00000000000..0f742a50a9c
--- /dev/null
+++ b/chromium/v8/include/cppgc/internal/process-heap.h
@@ -0,0 +1,34 @@
+// 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_INTERNAL_PROCESS_HEAP_H_
+#define INCLUDE_CPPGC_INTERNAL_PROCESS_HEAP_H_
+
+#include "cppgc/internal/atomic-entry-flag.h"
+#include "v8config.h" // NOLINT(build/include_directory)
+
+namespace cppgc {
+namespace internal {
+
+class V8_EXPORT ProcessHeap final {
+ public:
+ static void EnterIncrementalOrConcurrentMarking() {
+ concurrent_marking_flag_.Enter();
+ }
+ static void ExitIncrementalOrConcurrentMarking() {
+ concurrent_marking_flag_.Exit();
+ }
+
+ static bool IsAnyIncrementalOrConcurrentMarking() {
+ return concurrent_marking_flag_.MightBeEntered();
+ }
+
+ private:
+ static AtomicEntryFlag concurrent_marking_flag_;
+};
+
+} // namespace internal
+} // namespace cppgc
+
+#endif // INCLUDE_CPPGC_INTERNAL_PROCESS_HEAP_H_
diff --git a/chromium/v8/include/cppgc/internal/write-barrier.h b/chromium/v8/include/cppgc/internal/write-barrier.h
new file mode 100644
index 00000000000..5bf550b0261
--- /dev/null
+++ b/chromium/v8/include/cppgc/internal/write-barrier.h
@@ -0,0 +1,78 @@
+// 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_INTERNAL_WRITE_BARRIER_H_
+#define INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_
+
+#include "cppgc/internal/api-constants.h"
+#include "cppgc/internal/process-heap.h"
+#include "v8config.h" // NOLINT(build/include_directory)
+
+#if defined(CPPGC_CAGED_HEAP)
+#include "cppgc/internal/caged-heap-local-data.h"
+#endif
+
+namespace cppgc {
+namespace internal {
+
+class V8_EXPORT WriteBarrier final {
+ public:
+ static V8_INLINE void MarkingBarrier(const void* slot, const void* value) {
+#if defined(CPPGC_CAGED_HEAP)
+ const uintptr_t start =
+ reinterpret_cast<uintptr_t>(value) &
+ ~(api_constants::kCagedHeapReservationAlignment - 1);
+ const uintptr_t slot_offset = reinterpret_cast<uintptr_t>(slot) - start;
+ if (slot_offset > api_constants::kCagedHeapReservationSize) {
+ // Check if slot is on stack or value is sentinel or nullptr. This relies
+ // on the fact that kSentinelPointer is encoded as 0x1.
+ return;
+ }
+
+ CagedHeapLocalData* local_data =
+ reinterpret_cast<CagedHeapLocalData*>(start);
+ if (V8_UNLIKELY(local_data->is_marking_in_progress)) {
+ MarkingBarrierSlow(value);
+ return;
+ }
+#if defined(CPPGC_YOUNG_GENERATION)
+ GenerationalBarrier(local_data, slot, slot_offset,
+ reinterpret_cast<uintptr_t>(value) - start);
+#endif
+#else
+ if (V8_LIKELY(!ProcessHeap::IsAnyIncrementalOrConcurrentMarking())) return;
+
+ MarkingBarrierSlowWithSentinelCheck(value);
+#endif // CPPGC_CAGED_HEAP
+ }
+
+ private:
+ WriteBarrier() = delete;
+
+ static void MarkingBarrierSlow(const void* value);
+ static void MarkingBarrierSlowWithSentinelCheck(const void* value);
+
+#if defined(CPPGC_YOUNG_GENERATION)
+ static V8_INLINE void GenerationalBarrier(CagedHeapLocalData* local_data,
+ const void* slot,
+ uintptr_t slot_offset,
+ uintptr_t value_offset) {
+ const AgeTable& age_table = local_data->age_table;
+
+ // Bail out if the slot is in young generation.
+ if (V8_LIKELY(age_table[slot_offset] == AgeTable::Age::kYoung)) return;
+
+ GenerationalBarrierSlow(local_data, age_table, slot, value_offset);
+ }
+
+ static void GenerationalBarrierSlow(CagedHeapLocalData* local_data,
+ const AgeTable& ageTable,
+ const void* slot, uintptr_t value_offset);
+#endif
+};
+
+} // namespace internal
+} // namespace cppgc
+
+#endif // INCLUDE_CPPGC_INTERNAL_WRITE_BARRIER_H_
diff --git a/chromium/v8/include/cppgc/liveness-broker.h b/chromium/v8/include/cppgc/liveness-broker.h
index 69dbc11f1f4..883be46240f 100644
--- a/chromium/v8/include/cppgc/liveness-broker.h
+++ b/chromium/v8/include/cppgc/liveness-broker.h
@@ -16,6 +16,30 @@ namespace internal {
class LivenessBrokerFactory;
} // namespace internal
+/**
+ * The broker is passed to weak callbacks to allow (temporarily) querying
+ * the liveness state of an object. References to non-live objects must be
+ * cleared when IsHeapObjectAlive() returns false.
+ *
+ * \code
+ * class GCedWithCustomWeakCallback final
+ * : public GarbageCollected<GCedWithCustomWeakCallback> {
+ * public:
+ * UntracedMember<Bar> bar;
+ *
+ * void CustomWeakCallbackMethod(const LivenessBroker& broker) {
+ * if (!broker.IsHeapObjectAlive(bar))
+ * bar = nullptr;
+ * }
+ *
+ * void Trace(cppgc::Visitor* visitor) const {
+ * visitor->RegisterWeakCallbackMethod<
+ * GCedWithCustomWeakCallback,
+ * &GCedWithCustomWeakCallback::CustomWeakCallbackMethod>(this);
+ * }
+ * };
+ * \endcode
+ */
class V8_EXPORT LivenessBroker final {
public:
template <typename T>
@@ -26,12 +50,6 @@ class V8_EXPORT LivenessBroker final {
}
template <typename T>
- bool IsHeapObjectAlive(const WeakMember<T>& weak_member) const {
- return (weak_member != kSentinelPointer) &&
- IsHeapObjectAlive<T>(weak_member.Get());
- }
-
- template <typename T>
bool IsHeapObjectAlive(const UntracedMember<T>& untraced_member) const {
return (untraced_member != kSentinelPointer) &&
IsHeapObjectAlive<T>(untraced_member.Get());
diff --git a/chromium/v8/include/cppgc/macros.h b/chromium/v8/include/cppgc/macros.h
index 7c7a10e433a..c0b1814e294 100644
--- a/chromium/v8/include/cppgc/macros.h
+++ b/chromium/v8/include/cppgc/macros.h
@@ -5,21 +5,19 @@
#ifndef INCLUDE_CPPGC_MACROS_H_
#define INCLUDE_CPPGC_MACROS_H_
-namespace cppgc {
+#include "cppgc/internal/compiler-specific.h"
-namespace internal {
-class __thisIsHereToForceASemicolonAfterThisMacro {};
-} // namespace internal
+namespace cppgc {
// Use if the object is only stack allocated.
-#define CPPGC_STACK_ALLOCATED() \
- public: \
- using IsStackAllocatedTypeMarker = int; \
- \
- private: \
- void* operator new(size_t) = delete; \
- void* operator new(size_t, void*) = delete; \
- friend class internal::__thisIsHereToForceASemicolonAfterThisMacro
+#define CPPGC_STACK_ALLOCATED() \
+ public: \
+ using IsStackAllocatedTypeMarker CPPGC_UNUSED = int; \
+ \
+ private: \
+ void* operator new(size_t) = delete; \
+ void* operator new(size_t, void*) = delete; \
+ static_assert(true, "Force semicolon.")
} // namespace cppgc
diff --git a/chromium/v8/include/cppgc/member.h b/chromium/v8/include/cppgc/member.h
index a183edb96fd..22c1adc0af7 100644
--- a/chromium/v8/include/cppgc/member.h
+++ b/chromium/v8/include/cppgc/member.h
@@ -19,19 +19,43 @@ class Visitor;
namespace internal {
+class MemberBase {
+ protected:
+ MemberBase() = default;
+ explicit MemberBase(void* value) : raw_(value) {}
+
+ void* const* GetRawSlot() const { return &raw_; }
+ void* GetRaw() const { return raw_; }
+ void SetRaw(void* value) { raw_ = value; }
+
+ void* GetRawAtomic() const {
+ return reinterpret_cast<const std::atomic<void*>*>(&raw_)->load(
+ std::memory_order_relaxed);
+ }
+ void SetRawAtomic(void* value) {
+ reinterpret_cast<std::atomic<void*>*>(&raw_)->store(
+ value, std::memory_order_relaxed);
+ }
+
+ void ClearFromGC() const { raw_ = nullptr; }
+
+ private:
+ mutable void* raw_ = nullptr;
+};
+
// The basic class from which all Member classes are 'generated'.
template <typename T, typename WeaknessTag, typename WriteBarrierPolicy,
typename CheckingPolicy>
-class BasicMember : private CheckingPolicy {
+class BasicMember final : private MemberBase, private CheckingPolicy {
public:
using PointeeType = T;
constexpr BasicMember() = default;
constexpr BasicMember(std::nullptr_t) {} // NOLINT
- BasicMember(SentinelPointer s) : raw_(s) {} // NOLINT
- BasicMember(T* raw) : raw_(raw) { // NOLINT
+ BasicMember(SentinelPointer s) : MemberBase(s) {} // NOLINT
+ BasicMember(T* raw) : MemberBase(raw) { // NOLINT
InitializingWriteBarrier();
- this->CheckPointer(raw_);
+ this->CheckPointer(Get());
}
BasicMember(T& raw) : BasicMember(&raw) {} // NOLINT
BasicMember(const BasicMember& other) : BasicMember(other.Get()) {}
@@ -106,9 +130,12 @@ class BasicMember : private CheckingPolicy {
T* operator->() const { return Get(); }
T& operator*() const { return *Get(); }
- T* Get() const {
+ // CFI cast exemption to allow passing SentinelPointer through T* and support
+ // heterogeneous assignments between different Member and Persistent handles
+ // based on their actual types.
+ V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
// Executed by the mutator, hence non atomic load.
- return raw_;
+ return static_cast<T*>(MemberBase::GetRaw());
}
void Clear() { SetRawAtomic(nullptr); }
@@ -120,25 +147,18 @@ class BasicMember : private CheckingPolicy {
}
private:
- void SetRawAtomic(T* raw) {
- reinterpret_cast<std::atomic<T*>*>(&raw_)->store(raw,
- std::memory_order_relaxed);
- }
T* GetRawAtomic() const {
- return reinterpret_cast<const std::atomic<T*>*>(&raw_)->load(
- std::memory_order_relaxed);
+ return static_cast<T*>(MemberBase::GetRawAtomic());
}
void InitializingWriteBarrier() const {
- WriteBarrierPolicy::InitializingBarrier(
- reinterpret_cast<const void*>(&raw_), static_cast<const void*>(raw_));
+ WriteBarrierPolicy::InitializingBarrier(GetRawSlot(), GetRaw());
}
void AssigningWriteBarrier() const {
- WriteBarrierPolicy::AssigningBarrier(reinterpret_cast<const void*>(&raw_),
- static_cast<const void*>(raw_));
+ WriteBarrierPolicy::AssigningBarrier(GetRawSlot(), GetRaw());
}
- T* raw_ = nullptr;
+ void ClearFromGC() const { MemberBase::ClearFromGC(); }
friend class cppgc::Visitor;
};
diff --git a/chromium/v8/include/cppgc/persistent.h b/chromium/v8/include/cppgc/persistent.h
index fc6b0b9d92e..c2d8a7a5a64 100644
--- a/chromium/v8/include/cppgc/persistent.h
+++ b/chromium/v8/include/cppgc/persistent.h
@@ -15,14 +15,43 @@
#include "v8config.h" // NOLINT(build/include_directory)
namespace cppgc {
+
+class Visitor;
+
namespace internal {
+class PersistentBase {
+ protected:
+ PersistentBase() = default;
+ explicit PersistentBase(void* raw) : raw_(raw) {}
+
+ void* GetValue() const { return raw_; }
+ void SetValue(void* value) { raw_ = value; }
+
+ PersistentNode* GetNode() const { return node_; }
+ void SetNode(PersistentNode* node) { node_ = node; }
+
+ // Performs a shallow clear which assumes that internal persistent nodes are
+ // destroyed elsewhere.
+ void ClearFromGC() const {
+ raw_ = nullptr;
+ node_ = nullptr;
+ }
+
+ private:
+ mutable void* raw_ = nullptr;
+ mutable PersistentNode* node_ = nullptr;
+
+ friend class PersistentRegion;
+};
+
// The basic class from which all Persistent classes are generated.
template <typename T, typename WeaknessPolicy, typename LocationPolicy,
typename CheckingPolicy>
-class BasicPersistent : public LocationPolicy,
- private WeaknessPolicy,
- private CheckingPolicy {
+class BasicPersistent final : public PersistentBase,
+ public LocationPolicy,
+ private WeaknessPolicy,
+ private CheckingPolicy {
public:
using typename WeaknessPolicy::IsStrongPersistent;
using PointeeType = T;
@@ -38,15 +67,15 @@ class BasicPersistent : public LocationPolicy,
BasicPersistent( // NOLINT
SentinelPointer s, const SourceLocation& loc = SourceLocation::Current())
- : LocationPolicy(loc), raw_(s) {}
+ : PersistentBase(s), LocationPolicy(loc) {}
- // Raw value contstructors.
+ // Raw value constructors.
BasicPersistent(T* raw, // NOLINT
const SourceLocation& loc = SourceLocation::Current())
- : LocationPolicy(loc), raw_(raw) {
+ : PersistentBase(raw), LocationPolicy(loc) {
if (!IsValid()) return;
- node_ = WeaknessPolicy::GetPersistentRegion(raw_).AllocateNode(
- this, &BasicPersistent::Trace);
+ SetNode(WeaknessPolicy::GetPersistentRegion(GetValue())
+ .AllocateNode(this, &BasicPersistent::Trace));
this->CheckPointer(Get());
}
@@ -74,13 +103,11 @@ class BasicPersistent : public LocationPolicy,
BasicPersistent(
BasicPersistent&& other,
const SourceLocation& loc = SourceLocation::Current()) noexcept
- : LocationPolicy(std::move(other)),
- raw_(std::move(other.raw_)),
- node_(std::move(other.node_)) {
+ : PersistentBase(std::move(other)), LocationPolicy(std::move(other)) {
if (!IsValid()) return;
- node_->UpdateOwner(this);
- other.raw_ = nullptr;
- other.node_ = nullptr;
+ GetNode()->UpdateOwner(this);
+ other.SetValue(nullptr);
+ other.SetNode(nullptr);
this->CheckPointer(Get());
}
@@ -114,13 +141,12 @@ class BasicPersistent : public LocationPolicy,
BasicPersistent& operator=(BasicPersistent&& other) {
if (this == &other) return *this;
Clear();
+ PersistentBase::operator=(std::move(other));
LocationPolicy::operator=(std::move(other));
- raw_ = std::move(other.raw_);
- node_ = std::move(other.node_);
if (!IsValid()) return *this;
- node_->UpdateOwner(this);
- other.raw_ = nullptr;
- other.node_ = nullptr;
+ GetNode()->UpdateOwner(this);
+ other.SetValue(nullptr);
+ other.SetNode(nullptr);
this->CheckPointer(Get());
return *this;
}
@@ -156,7 +182,12 @@ class BasicPersistent : public LocationPolicy,
T* operator->() const { return Get(); }
T& operator*() const { return *Get(); }
- T* Get() const { return raw_; }
+ // CFI cast exemption to allow passing SentinelPointer through T* and support
+ // heterogeneous assignments between different Member and Persistent handles
+ // based on their actual types.
+ V8_CLANG_NO_SANITIZE("cfi-unrelated-cast") T* Get() const {
+ return static_cast<T*>(GetValue());
+ }
void Clear() { Assign(nullptr); }
@@ -176,29 +207,35 @@ class BasicPersistent : public LocationPolicy,
// Ideally, handling kSentinelPointer would be done by the embedder. On the
// other hand, having Persistent aware of it is beneficial since no node
// gets wasted.
- return raw_ != nullptr && raw_ != kSentinelPointer;
+ return GetValue() != nullptr && GetValue() != kSentinelPointer;
}
void Assign(T* ptr) {
if (IsValid()) {
if (ptr && ptr != kSentinelPointer) {
// Simply assign the pointer reusing the existing node.
- raw_ = ptr;
+ SetValue(ptr);
this->CheckPointer(ptr);
return;
}
- WeaknessPolicy::GetPersistentRegion(raw_).FreeNode(node_);
- node_ = nullptr;
+ WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
+ SetNode(nullptr);
}
- raw_ = ptr;
+ SetValue(ptr);
if (!IsValid()) return;
- node_ = WeaknessPolicy::GetPersistentRegion(raw_).AllocateNode(
- this, &BasicPersistent::Trace);
+ SetNode(WeaknessPolicy::GetPersistentRegion(GetValue())
+ .AllocateNode(this, &BasicPersistent::Trace));
this->CheckPointer(Get());
}
- T* raw_ = nullptr;
- PersistentNode* node_ = nullptr;
+ void ClearFromGC() const {
+ if (IsValid()) {
+ WeaknessPolicy::GetPersistentRegion(GetValue()).FreeNode(GetNode());
+ PersistentBase::ClearFromGC();
+ }
+ }
+
+ friend class cppgc::Visitor;
};
template <typename T1, typename WeaknessPolicy1, typename LocationPolicy1,
diff --git a/chromium/v8/include/cppgc/platform.h b/chromium/v8/include/cppgc/platform.h
index 8dc5e14a7d6..72694c6ee13 100644
--- a/chromium/v8/include/cppgc/platform.h
+++ b/chromium/v8/include/cppgc/platform.h
@@ -10,16 +10,114 @@
namespace cppgc {
-// TODO(v8:10346): Put PageAllocator in a non-V8 include header to avoid
-// depending on namespace v8.
+// TODO(v8:10346): Create separate includes for concepts that are not
+// V8-specific.
+using IdleTask = v8::IdleTask;
+using JobHandle = v8::JobHandle;
+using JobTask = v8::JobTask;
using PageAllocator = v8::PageAllocator;
+using Task = v8::Task;
+using TaskPriority = v8::TaskPriority;
+using TaskRunner = v8::TaskRunner;
-// Initializes the garbage collector with the provided platform. Must be called
-// before creating a Heap.
-V8_EXPORT void InitializePlatform(PageAllocator* page_allocator);
+/**
+ * Platform interface used by Heap. Contains allocators and executors.
+ */
+class V8_EXPORT Platform {
+ public:
+ virtual ~Platform() = default;
-// Must be called after destroying the last used heap.
-V8_EXPORT void ShutdownPlatform();
+ /**
+ * Returns the allocator used by cppgc to allocate its heap and various
+ * support structures.
+ */
+ virtual PageAllocator* GetPageAllocator() = 0;
+
+ /**
+ * Monotonically increasing time in seconds from an arbitrary fixed point in
+ * the past. This function is expected to return at least
+ * millisecond-precision values. For this reason,
+ * it is recommended that the fixed point be no further in the past than
+ * the epoch.
+ **/
+ virtual double MonotonicallyIncreasingTime() = 0;
+
+ /**
+ * Foreground task runner that should be used by a Heap.
+ */
+ virtual std::shared_ptr<TaskRunner> GetForegroundTaskRunner() {
+ return nullptr;
+ }
+
+ /**
+ * Posts |job_task| to run in parallel. Returns a JobHandle associated with
+ * the Job, which can be joined or canceled.
+ * This avoids degenerate cases:
+ * - Calling CallOnWorkerThread() for each work item, causing significant
+ * overhead.
+ * - Fixed number of CallOnWorkerThread() calls that split the work and might
+ * run for a long time. This is problematic when many components post
+ * "num cores" tasks and all expect to use all the cores. In these cases,
+ * the scheduler lacks context to be fair to multiple same-priority requests
+ * and/or ability to request lower priority work to yield when high priority
+ * work comes in.
+ * A canonical implementation of |job_task| looks like:
+ * class MyJobTask : public JobTask {
+ * public:
+ * MyJobTask(...) : worker_queue_(...) {}
+ * // JobTask:
+ * void Run(JobDelegate* delegate) override {
+ * while (!delegate->ShouldYield()) {
+ * // Smallest unit of work.
+ * auto work_item = worker_queue_.TakeWorkItem(); // Thread safe.
+ * if (!work_item) return;
+ * ProcessWork(work_item);
+ * }
+ * }
+ *
+ * size_t GetMaxConcurrency() const override {
+ * return worker_queue_.GetSize(); // Thread safe.
+ * }
+ * };
+ * auto handle = PostJob(TaskPriority::kUserVisible,
+ * std::make_unique<MyJobTask>(...));
+ * handle->Join();
+ *
+ * PostJob() and methods of the returned JobHandle/JobDelegate, must never be
+ * called while holding a lock that could be acquired by JobTask::Run or
+ * JobTask::GetMaxConcurrency -- that could result in a deadlock. This is
+ * because [1] JobTask::GetMaxConcurrency may be invoked while holding
+ * internal lock (A), hence JobTask::GetMaxConcurrency can only use a lock (B)
+ * if that lock is *never* held while calling back into JobHandle from any
+ * thread (A=>B/B=>A deadlock) and [2] JobTask::Run or
+ * JobTask::GetMaxConcurrency may be invoked synchronously from JobHandle
+ * (B=>JobHandle::foo=>B deadlock).
+ *
+ * A sufficient PostJob() implementation that uses the default Job provided in
+ * libplatform looks like:
+ * std::unique_ptr<JobHandle> PostJob(
+ * TaskPriority priority, std::unique_ptr<JobTask> job_task) override {
+ * return std::make_unique<DefaultJobHandle>(
+ * std::make_shared<DefaultJobState>(
+ * this, std::move(job_task), kNumThreads));
+ * }
+ */
+ virtual std::unique_ptr<JobHandle> PostJob(
+ TaskPriority priority, std::unique_ptr<JobTask> job_task) {
+ return nullptr;
+ }
+};
+
+/**
+ * Process-global initialization of the garbage collector. Must be called before
+ * creating a Heap.
+ */
+V8_EXPORT void InitializeProcess(PageAllocator*);
+
+/**
+ * Must be called after destroying the last used heap.
+ */
+V8_EXPORT void ShutdownProcess();
namespace internal {
diff --git a/chromium/v8/include/cppgc/prefinalizer.h b/chromium/v8/include/cppgc/prefinalizer.h
index 2f6d68a1dac..75764d02cde 100644
--- a/chromium/v8/include/cppgc/prefinalizer.h
+++ b/chromium/v8/include/cppgc/prefinalizer.h
@@ -5,11 +5,9 @@
#ifndef INCLUDE_CPPGC_PREFINALIZER_H_
#define INCLUDE_CPPGC_PREFINALIZER_H_
-#include "cppgc/internal/accessors.h"
#include "cppgc/internal/compiler-specific.h"
#include "cppgc/internal/prefinalizer-handler.h"
#include "cppgc/liveness-broker.h"
-#include "cppgc/macros.h"
namespace cppgc {
@@ -23,7 +21,7 @@ class PrefinalizerRegistration final {
"USING_PRE_FINALIZER(T) must be defined.");
cppgc::internal::PreFinalizerRegistrationDispatcher::RegisterPrefinalizer(
- internal::GetHeapFromPayload(self), {self, T::InvokePreFinalizer});
+ {self, T::InvokePreFinalizer});
}
void* operator new(size_t, void* location) = delete;
@@ -47,7 +45,7 @@ class PrefinalizerRegistration final {
private: \
CPPGC_NO_UNIQUE_ADDRESS internal::PrefinalizerRegistration<Class> \
prefinalizer_dummy_{this}; \
- friend class internal::__thisIsHereToForceASemicolonAfterThisMacro
+ static_assert(true, "Force semicolon.")
} // namespace cppgc
diff --git a/chromium/v8/include/cppgc/source-location.h b/chromium/v8/include/cppgc/source-location.h
index 8cc52d6a539..139c9d86c08 100644
--- a/chromium/v8/include/cppgc/source-location.h
+++ b/chromium/v8/include/cppgc/source-location.h
@@ -23,10 +23,16 @@
namespace cppgc {
-// Encapsulates source location information. Mimics C++20's
-// std::source_location.
+/**
+ * Encapsulates source location information. Mimics C++20's
+ * std::source_location.
+ */
class V8_EXPORT SourceLocation final {
public:
+ /**
+ * Construct source location information corresponding to the location of the
+ * call site.
+ */
#if CPPGC_SUPPORTS_SOURCE_LOCATION
static constexpr SourceLocation Current(
const char* function = __builtin_FUNCTION(),
@@ -37,12 +43,38 @@ class V8_EXPORT SourceLocation final {
static constexpr SourceLocation Current() { return SourceLocation(); }
#endif // CPPGC_SUPPORTS_SOURCE_LOCATION
+ /**
+ * Constructs unspecified source location information.
+ */
constexpr SourceLocation() = default;
+ /**
+ * Returns the name of the function associated with the position represented
+ * by this object, if any.
+ *
+ * \returns the function name as cstring.
+ */
constexpr const char* Function() const { return function_; }
+
+ /**
+ * Returns the name of the current source file represented by this object.
+ *
+ * \returns the file name as cstring.
+ */
constexpr const char* FileName() const { return file_; }
+
+ /**
+ * Returns the line number represented by this object.
+ *
+ * \returns the line number.
+ */
constexpr size_t Line() const { return line_; }
+ /**
+ * Returns a human-readable string representing this object.
+ *
+ * \returns a human-readable string representing source location information.
+ */
std::string ToString() const;
private:
diff --git a/chromium/v8/include/cppgc/trace-trait.h b/chromium/v8/include/cppgc/trace-trait.h
index e246bc53b7d..59e0b14c451 100644
--- a/chromium/v8/include/cppgc/trace-trait.h
+++ b/chromium/v8/include/cppgc/trace-trait.h
@@ -14,6 +14,8 @@ class Visitor;
namespace internal {
+// Implementation of the default TraceTrait handling GarbageCollected and
+// GarbageCollectedMixin.
template <typename T,
bool =
IsGarbageCollectedMixinTypeV<typename std::remove_const<T>::type>>
@@ -21,25 +23,57 @@ struct TraceTraitImpl;
} // namespace internal
-using TraceCallback = void (*)(Visitor*, const void*);
-
-// TraceDescriptor is used to describe how to trace an object.
+/**
+ * Callback for invoking tracing on a given object.
+ *
+ * \param visitor The visitor to dispatch to.
+ * \param object The object to invoke tracing on.
+ */
+using TraceCallback = void (*)(Visitor* visitor, const void* object);
+
+/**
+ * Describes how to trace an object, i.e., how to visit all Oilpan-relevant
+ * fields of an object.
+ */
struct TraceDescriptor {
- // The adjusted base pointer of the object that should be traced.
+ /**
+ * Adjusted base pointer, i.e., the pointer to the class inheriting directly
+ * from GarbageCollected, of the object that is being traced.
+ */
const void* base_object_payload;
- // A callback for tracing the object.
+ /**
+ * Callback for tracing the object.
+ */
TraceCallback callback;
};
+/**
+ * Trait specifying how the garbage collector processes an object of type T.
+ *
+ * Advanced users may override handling by creating a specialization for their
+ * type.
+ */
template <typename T>
struct TraceTrait {
static_assert(internal::IsTraceableV<T>, "T must have a Trace() method");
+ /**
+ * Accessor for retrieving a TraceDescriptor to process an object of type T.
+ *
+ * \param self The object to be processed.
+ * \returns a TraceDescriptor to process the object.
+ */
static TraceDescriptor GetTraceDescriptor(const void* self) {
return internal::TraceTraitImpl<T>::GetTraceDescriptor(
static_cast<const T*>(self));
}
+ /**
+ * Function invoking the tracing for an object of type T.
+ *
+ * \param visitor The visitor to dispatch to.
+ * \param self The object to invoke tracing on.
+ */
static void Trace(Visitor* visitor, const void* self) {
static_cast<const T*>(self)->Trace(visitor);
}
diff --git a/chromium/v8/include/cppgc/visitor.h b/chromium/v8/include/cppgc/visitor.h
index a73a4abb2bd..b70fde537bd 100644
--- a/chromium/v8/include/cppgc/visitor.h
+++ b/chromium/v8/include/cppgc/visitor.h
@@ -14,7 +14,11 @@
#include "cppgc/trace-trait.h"
namespace cppgc {
+
namespace internal {
+template <typename T, typename WeaknessPolicy, typename LocationPolicy,
+ typename CheckingPolicy>
+class BasicPersistent;
class VisitorBase;
} // namespace internal
@@ -22,10 +26,28 @@ using WeakCallback = void (*)(const LivenessBroker&, const void*);
/**
* Visitor passed to trace methods. All managed pointers must have called the
- * visitor's trace method on them.
+ * Visitor's trace method on them.
+ *
+ * \code
+ * class Foo final : public GarbageCollected<Foo> {
+ * public:
+ * void Trace(Visitor* visitor) const {
+ * visitor->Trace(foo_);
+ * visitor->Trace(weak_foo_);
+ * }
+ * private:
+ * Member<Foo> foo_;
+ * WeakMember<Foo> weak_foo_;
+ * };
+ * \endcode
*/
class Visitor {
public:
+ /**
+ * Trace method for Member.
+ *
+ * \param member Member reference retaining an object.
+ */
template <typename T>
void Trace(const Member<T>& member) {
const T* value = member.GetRawAtomic();
@@ -33,11 +55,16 @@ class Visitor {
Trace(value);
}
+ /**
+ * Trace method for WeakMember.
+ *
+ * \param weak_member WeakMember reference weakly retaining an object.
+ */
template <typename T>
void Trace(const WeakMember<T>& weak_member) {
- static_assert(sizeof(T), "T must be fully defined");
+ static_assert(sizeof(T), "Pointee type must be fully defined.");
static_assert(internal::IsGarbageCollectedType<T>::value,
- "T must be GarabgeCollected or GarbageCollectedMixin type");
+ "T must be GarbageCollected or GarbageCollectedMixin type");
const T* value = weak_member.GetRawAtomic();
@@ -52,41 +79,42 @@ class Visitor {
&HandleWeak<WeakMember<T>>, &weak_member);
}
- template <typename Persistent,
- std::enable_if_t<Persistent::IsStrongPersistent::value>* = nullptr>
- void TraceRoot(const Persistent& p, const SourceLocation& loc) {
- using PointeeType = typename Persistent::PointeeType;
- static_assert(sizeof(PointeeType),
- "Persistent's pointee type must be fully defined");
- static_assert(internal::IsGarbageCollectedType<PointeeType>::value,
- "Persisent's pointee type must be GarabgeCollected or "
- "GarbageCollectedMixin");
- if (!p.Get()) {
- return;
- }
- VisitRoot(p.Get(), TraceTrait<PointeeType>::GetTraceDescriptor(p.Get()));
- }
-
- template <
- typename WeakPersistent,
- std::enable_if_t<!WeakPersistent::IsStrongPersistent::value>* = nullptr>
- void TraceRoot(const WeakPersistent& p, const SourceLocation& loc) {
- using PointeeType = typename WeakPersistent::PointeeType;
- static_assert(sizeof(PointeeType),
- "Persistent's pointee type must be fully defined");
- static_assert(internal::IsGarbageCollectedType<PointeeType>::value,
- "Persisent's pointee type must be GarabgeCollected or "
- "GarbageCollectedMixin");
- VisitWeakRoot(p.Get(), TraceTrait<PointeeType>::GetTraceDescriptor(p.Get()),
- &HandleWeak<WeakPersistent>, &p);
+ /**
+ * Trace method for inlined objects that are not allocated themselves but
+ * otherwise follow managed heap layout and have a Trace() method.
+ *
+ * \param object reference of the inlined object.
+ */
+ template <typename T>
+ void Trace(const T& object) {
+#if V8_ENABLE_CHECKS
+ // This object is embedded in potentially multiple nested objects. The
+ // outermost object must not be in construction as such objects are (a) not
+ // processed immediately, and (b) only processed conservatively if not
+ // otherwise possible.
+ CheckObjectNotInConstruction(&object);
+#endif // V8_ENABLE_CHECKS
+ TraceTrait<T>::Trace(this, &object);
}
+ /**
+ * Registers a weak callback method on the object of type T. See
+ * LivenessBroker for an usage example.
+ *
+ * \param object of type T specifying a weak callback method.
+ */
template <typename T, void (T::*method)(const LivenessBroker&)>
- void RegisterWeakCallbackMethod(const T* obj) {
- RegisterWeakCallback(&WeakCallbackMethodDelegate<T, method>, obj);
+ void RegisterWeakCallbackMethod(const T* object) {
+ RegisterWeakCallback(&WeakCallbackMethodDelegate<T, method>, object);
}
- virtual void RegisterWeakCallback(WeakCallback, const void*) {}
+ /**
+ * Registers a weak callback that is invoked during garbage collection.
+ *
+ * \param callback to be invoked.
+ * \param data custom data that is passed to the callback.
+ */
+ virtual void RegisterWeakCallback(WeakCallback callback, const void* data) {}
protected:
virtual void Visit(const void* self, TraceDescriptor) {}
@@ -108,29 +136,64 @@ class Visitor {
template <typename PointerType>
static void HandleWeak(const LivenessBroker& info, const void* object) {
const PointerType* weak = static_cast<const PointerType*>(object);
+ // Sentinel values are preserved for weak pointers.
+ if (*weak == kSentinelPointer) return;
const auto* raw = weak->Get();
- if (raw && !info.IsHeapObjectAlive(raw)) {
- // Object is passed down through the marker as const. Alternatives are
- // - non-const Trace method;
- // - mutable pointer in MemberBase;
- const_cast<PointerType*>(weak)->Clear();
+ if (!info.IsHeapObjectAlive(raw)) {
+ weak->ClearFromGC();
}
}
Visitor() = default;
+ template <typename Persistent,
+ std::enable_if_t<Persistent::IsStrongPersistent::value>* = nullptr>
+ void TraceRoot(const Persistent& p, const SourceLocation& loc) {
+ using PointeeType = typename Persistent::PointeeType;
+ static_assert(sizeof(PointeeType),
+ "Persistent's pointee type must be fully defined");
+ static_assert(internal::IsGarbageCollectedType<PointeeType>::value,
+ "Persistent's pointee type must be GarbageCollected or "
+ "GarbageCollectedMixin");
+ if (!p.Get()) {
+ return;
+ }
+ VisitRoot(p.Get(), TraceTrait<PointeeType>::GetTraceDescriptor(p.Get()));
+ }
+
+ template <
+ typename WeakPersistent,
+ std::enable_if_t<!WeakPersistent::IsStrongPersistent::value>* = nullptr>
+ void TraceRoot(const WeakPersistent& p, const SourceLocation& loc) {
+ using PointeeType = typename WeakPersistent::PointeeType;
+ static_assert(sizeof(PointeeType),
+ "Persistent's pointee type must be fully defined");
+ static_assert(internal::IsGarbageCollectedType<PointeeType>::value,
+ "Persistent's pointee type must be GarbageCollected or "
+ "GarbageCollectedMixin");
+ VisitWeakRoot(p.Get(), TraceTrait<PointeeType>::GetTraceDescriptor(p.Get()),
+ &HandleWeak<WeakPersistent>, &p);
+ }
+
template <typename T>
void Trace(const T* t) {
- static_assert(sizeof(T), "T must be fully defined");
+ static_assert(sizeof(T), "Pointee type must be fully defined.");
static_assert(internal::IsGarbageCollectedType<T>::value,
- "T must be GarabgeCollected or GarbageCollectedMixin type");
+ "T must be GarbageCollected or GarbageCollectedMixin type");
if (!t) {
return;
}
Visit(t, TraceTrait<T>::GetTraceDescriptor(t));
}
+#if V8_ENABLE_CHECKS
+ V8_EXPORT void CheckObjectNotInConstruction(const void* address);
+#endif // V8_ENABLE_CHECKS
+
friend class internal::VisitorBase;
+ template <typename T, typename WeaknessPolicy, typename LocationPolicy,
+ typename CheckingPolicy>
+ friend class internal::BasicPersistent;
};
} // namespace cppgc