// 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_EXTERNAL_BUFFER_TABLE_H_ #define V8_SANDBOX_EXTERNAL_BUFFER_TABLE_H_ #include "include/v8config.h" #include "src/common/globals.h" #include "src/sandbox/compactible-external-entity-table.h" #include "src/sandbox/external-buffer-tag.h" #include "src/sandbox/tagged-payload.h" #ifdef V8_ENABLE_SANDBOX namespace v8 { namespace internal { class Counters; /** * The entries of an ExternalBufferTable. * * Each entry consists of two pointer-sized words where the first word * contains the external pointer, the marking bit, and a type tag. The second * word contains the buffer size. An entry can either be: * - A "regular" entry, containing the external pointer (with a type * tag and the marking bit in the unused upper bits) and the buffer size, or * - A freelist entry, tagged with the kExternalPointerFreeEntryTag and * containing the index of the next free entry in the lower 32 bits of the * first pointer-size word, or * - An evacuation entry, tagged with the kExternalPointerEvacuationEntryTag * and containing the address of the ExternalBufferSlot referencing the * entry that will be evacuated into this entry. See the compaction * algorithm overview for more details about these entries. */ struct ExternalBufferTableEntry { … }; // We expect ExternalBufferTable entries to consist of two 64-bit word. static_assert …; /** * A table storing pointer and size to buffer data located outside the sandbox. * * When the sandbox is enabled, the external buffer table (EBT) is used to * safely reference buffer data located outside of the sandbox. The EBT * guarantees that every access to the buffer data via an external pointer * either results in an invalid pointer or a valid pointer to a valid (live) * buffer of the expected type. The EBT also stores the size of the buffer data * as part of each entry to allow for bounds checking. * * Table memory management: * ------------------------ * The garbage collection algorithm works as follows: * - One bit of every entry is reserved for the marking bit. * - Every store to an entry automatically sets the marking bit when ORing * with the tag. This avoids the need for write barriers. * - Every load of an entry automatically removes the marking bit when ANDing * with the inverted tag. * - When the GC marking visitor finds a live object with an external pointer, * it marks the corresponding entry as alive through Mark(), which sets the * marking bit using an atomic CAS operation. * - When marking is finished, SweepAndCompact() iterates over a Space once * while the mutator is stopped and builds a freelist from all dead entries * while also removing the marking bit from any live entry. * * Table compaction: * ----------------- * Additionally, the external buffer table supports compaction. * For details about the compaction algorithm see the * CompactibleExternalEntityTable class. */ class V8_EXPORT_PRIVATE ExternalBufferTable : public CompactibleExternalEntityTable< ExternalBufferTableEntry, kExternalBufferTableReservationSize> { … }; static_assert …; } // namespace internal } // namespace v8 #endif // V8_ENABLE_SANDBOX #endif // V8_SANDBOX_EXTERNAL_BUFFER_TABLE_H_