chromium/v8/src/sandbox/external-buffer-table.h

// 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_