v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
compactible-external-entity-table.h
Go to the documentation of this file.
1// Copyright 2024 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_SANDBOX_COMPACTIBLE_EXTERNAL_ENTITY_TABLE_H_
6#define V8_SANDBOX_COMPACTIBLE_EXTERNAL_ENTITY_TABLE_H_
7
8#include "include/v8config.h"
11
12#ifdef V8_COMPRESS_POINTERS
13
14namespace v8 {
15namespace internal {
16
17class Isolate;
18class Histogram;
19
20// Outcome of external pointer table compaction to use for the
21// ExternalPointerTableCompactionOutcome histogram.
22enum class ExternalEntityTableCompactionOutcome {
23 kSuccess = 0, // Compaction was successful.
24 // Outcome 1, partial success, is no longer supported.
25 kAborted = 2, // Compaction was aborted because the freelist grew too short.
26};
27
83template <typename Entry, size_t size>
84class V8_EXPORT_PRIVATE CompactibleExternalEntityTable
85 : public ExternalEntityTable<Entry, size> {
86 using Base = ExternalEntityTable<Entry, size>;
87
88 public:
89 static constexpr bool kSupportsCompaction = true;
90
91 struct CompactionResult {
92 uint32_t start_of_evacuation_area;
93 bool success;
94 };
95
96 CompactibleExternalEntityTable() = default;
97 CompactibleExternalEntityTable(const CompactibleExternalEntityTable&) =
98 delete;
99 CompactibleExternalEntityTable& operator=(
100 const CompactibleExternalEntityTable&) = delete;
101
102 // The Spaces used by pointer tables also contain the state related
103 // to compaction.
104 struct Space : public Base::Space {
105 public:
106 Space() : start_of_evacuation_area_(kNotCompactingMarker) {}
107
108 // Determine if compaction is needed and if so start the compaction.
109 // This is expected to be called at the start of the GC marking phase.
110 void StartCompactingIfNeeded();
111
112 private:
113 friend class CompactibleExternalEntityTable<Entry, size>;
114 friend class ExternalPointerTable;
115 friend class CppHeapPointerTable;
116
117 // Routines for compaction. See the comment about table compaction above.
118 inline bool IsCompacting();
119 inline void StartCompacting(uint32_t start_of_evacuation_area);
120 inline void StopCompacting();
121 inline void AbortCompacting(uint32_t start_of_evacuation_area);
122 inline bool CompactingWasAborted();
123
124 inline bool FieldWasInvalidated(Address field_address) const;
125 inline void ClearInvalidatedFields();
126 inline void AddInvalidatedField(Address field_address);
127
128 // This value indicates that this space is not currently being compacted. It
129 // is set to uint32_t max so that determining whether an entry should be
130 // evacuated becomes a single comparison:
131 // `bool should_be_evacuated = index >= start_of_evacuation_area`.
132 static constexpr uint32_t kNotCompactingMarker =
133 std::numeric_limits<uint32_t>::max();
134
135 // This value may be ORed into the start of evacuation area threshold
136 // during the GC marking phase to indicate that compaction has been
137 // aborted because the freelist grew too short and so evacuation entry
138 // allocation is no longer possible. This will prevent any further
139 // evacuation attempts as entries will be evacuated if their index is at or
140 // above the start of the evacuation area, which is now a huge value.
141 static constexpr uint32_t kCompactionAbortedMarker = 0xf0000000;
142
143 // When compacting this space, this field contains the index of the first
144 // entry in the evacuation area. The evacuation area then consists of all
145 // segments above this threshold, and the goal of compaction is to move all
146 // live entries out of these segments so that they can be deallocated after
147 // sweeping. The field can have the following values:
148 // - kNotCompactingMarker: compaction is not currently running.
149 // - A kEntriesPerSegment aligned value within: compaction is running and
150 // all entries after this value should be evacuated.
151 // - A value that has kCompactionAbortedMarker in its top bits:
152 // compaction has been aborted during marking. The original start of the
153 // evacuation area is still contained in the lower bits.
154 std::atomic<uint32_t> start_of_evacuation_area_;
155
156 // List of external pointer fields that have been invalidated.
157 // Only used when table compaction is running.
158 // We expect very few (usually none at all) fields to be invalidated during
159 // a GC, so a std::vector is probably better than a std::set or similar.
160 std::vector<Address> invalidated_fields_;
161
162 // Mutex guarding access to the invalidated_fields_ set.
163 base::Mutex invalidated_fields_mutex_;
164 };
165
166 // Allocate an EPT entry from the space's freelist, or add a freshly-allocated
167 // segment to the space and allocate there. If the space is compacting but
168 // the new index is above the evacuation threshold, abort compaction.
169 inline uint32_t AllocateEntry(Space* space);
170
171 CompactionResult FinishCompaction(Space* space, Histogram* counter);
172
173 inline void MaybeCreateEvacuationEntry(Space* space, uint32_t index,
174 Address handle_location);
175};
176
177} // namespace internal
178} // namespace v8
179
180#endif // V8_COMPRESS_POINTERS
181
182#endif // V8_SANDBOX_COMPACTIBLE_EXTERNAL_ENTITY_TABLE_H_
#define V8_EXPORT_PRIVATE
Definition macros.h:460