// Copyright 2024 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_SANDBOX_COMPACTIBLE_EXTERNAL_ENTITY_TABLE_H_ #define V8_SANDBOX_COMPACTIBLE_EXTERNAL_ENTITY_TABLE_H_ #include "include/v8config.h" #include "src/common/globals.h" #include "src/sandbox/external-entity-table.h" #ifdef V8_COMPRESS_POINTERS namespace v8 { namespace internal { class Isolate; class Histogram; // Outcome of external pointer table compaction to use for the // ExternalPointerTableCompactionOutcome histogram. enum class ExternalEntityTableCompactionOutcome { … }; /** * An intermediate table class that abstracts garbage collection mechanism * for pointer tables that support compaction. * * Table compaction: * ----------------- * The table's spaces are to some degree self-compacting: since the freelists * are sorted in ascending order, segments at the start of the table will * usually be fairly well utilized, while later segments might become * completely free, in which case they will be deallocated. * However, as a single live entry may keep an entire segment alive, the * following simple algorithm is used to compact a space if that is deemed * necessary: * - At the start of the GC marking phase, determine if a space needs to be * compacted. This decision is mostly based on the absolute and relative * size of the freelist. * - If compaction is needed, this algorithm determines by how many segments * it would like to shrink the space (N). It will then attempt to move all * live entries out of these segments so that they can be deallocated * afterwards during sweeping. * - The algorithm then simply selects the last N segments for evacuation, and * it "marks" them for evacuation simply by remembering the start of the * first selected segment. Everything after this threshold value then * becomes the evacuation area. In this way, it becomes very cheap to test * if an entry or segment should be evacuated: only a single integer * comparison against the threshold is required. It also establishes a * simple compaction invariant: compaction always moves an entry at or above * the threshold to a new position before the threshold. * - During marking, whenever a live entry inside the evacuation area is * found, a new "evacuation entry" is allocated from the freelist (which is * assumed to have enough free slots) and the address of the handle in the * object owning the table entry is written into it. * - During sweeping, these evacuation entries are resolved: the content of * the old entry is copied into the new entry and the handle in the object * is updated to point to the new entry. * * When compacting, it is expected that the evacuation area contains few live * entries and that the freelist will be able to serve all evacuation entry * allocations. In that case, compaction is essentially free (very little * marking overhead, no memory overhead). However, it can happen that the * application allocates a large number of table entries during marking, in * which case we might end up allocating new entries inside the evacuation area * or even allocate entire new segments for the space that's being compacted. * If that situation is detected, compaction is aborted during marking. * * This algorithm assumes that table entries (except for the null entry) are * never shared between multiple objects. Otherwise, the following could * happen: object A initially has handle H1 and is scanned during incremental * marking. Next, object B with handle H2 is scanned and marked for * evacuation. Afterwards, object A copies the handle H2 from object B. * During sweeping, only object B's handle will be updated to point to the * new entry while object A's handle is now dangling. If shared entries ever * become necessary, setting pointer handles would have to be guarded by * write barriers to avoid this scenario. */ template <typename Entry, size_t size> class V8_EXPORT_PRIVATE CompactibleExternalEntityTable : public ExternalEntityTable<Entry, size> { … }; } // namespace internal } // namespace v8 #endif // V8_COMPRESS_POINTERS #endif // V8_SANDBOX_COMPACTIBLE_EXTERNAL_ENTITY_TABLE_H_