2021-06-09 10:02:01 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2021, Gunnar Beutner <gbeutner@serenityos.org>
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <AK/DistinctNumeric.h>
|
2025-08-07 19:31:52 -04:00
|
|
|
#include <AK/Utf16String.h>
|
2021-06-09 10:02:01 +02:00
|
|
|
#include <AK/Vector.h>
|
2026-05-06 00:16:40 +02:00
|
|
|
#include <LibJS/Runtime/ExternalMemory.h>
|
2021-06-09 10:02:01 +02:00
|
|
|
|
|
|
|
|
namespace JS::Bytecode {
|
|
|
|
|
|
2025-04-05 21:46:37 +02:00
|
|
|
struct StringTableIndex {
|
|
|
|
|
static constexpr u32 invalid = 0xffffffffu;
|
|
|
|
|
bool is_valid() const { return value != invalid; }
|
|
|
|
|
u32 value { 0 };
|
|
|
|
|
};
|
2021-06-09 10:02:01 +02:00
|
|
|
|
2025-07-19 10:41:08 -07:00
|
|
|
class StringTable {
|
2021-06-09 10:02:01 +02:00
|
|
|
AK_MAKE_NONMOVABLE(StringTable);
|
|
|
|
|
AK_MAKE_NONCOPYABLE(StringTable);
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
StringTable() = default;
|
|
|
|
|
|
2025-08-07 19:31:52 -04:00
|
|
|
StringTableIndex insert(Utf16String);
|
|
|
|
|
Utf16String const& get(StringTableIndex) const;
|
2021-06-09 10:02:01 +02:00
|
|
|
void dump() const;
|
|
|
|
|
bool is_empty() const { return m_strings.is_empty(); }
|
LibJS: Add bytecode validator scaffolding driven from Bytecode.def
The plan is to start caching compiled JS bytecode on disk. Before
loading anything from a cache we need confidence that the bytes are
structurally well-formed, since a corrupted or tampered-with cache
file could otherwise hand the interpreter an out-of-bounds jump or a
constant-pool index that points past the end of the table.
This commit lays down the scaffolding for that validator. The walker
lives in Rust (Libraries/LibJS/Rust/src/bytecode/validator.rs) so
that it can share the existing Bytecode.def-driven layout machinery
with the encoder. C++ calls into it through cbindgen, the same way
the rest of the Rust pipeline is wired up.
For now, the validator only does Pass 1: walk the byte stream,
verify each instruction is 8-byte aligned, the opcode byte is in
range, and the reported length keeps us inside the buffer. The
length lookup is generated from Bytecode.def so fixed-length and
variable-length instructions stay in sync with the rest of the
codegen automatically. Per-field bounds checks (operands, labels,
table indices, cache indices) and structural extras (basic block
offsets, exception handlers, source map) come in follow-up commits.
The validator runs after every successful compilation in debug and
sanitizer builds, gated on !NDEBUG || HAS_ADDRESS_SANITIZER, so we
get an extra sanity check on every executable the encoder produces
without paying for it in release builds. Failure trips a
VERIFY_NOT_REACHED with the offset, opcode, and error category
logged via dbgln().
2026-05-02 09:49:32 +02:00
|
|
|
size_t size() const { return m_strings.size(); }
|
2026-05-06 00:16:40 +02:00
|
|
|
size_t external_memory_size() const
|
|
|
|
|
{
|
|
|
|
|
size_t size = vector_external_memory_size(m_strings);
|
|
|
|
|
for (auto const& string : m_strings)
|
|
|
|
|
size = saturating_add_external_memory_size(size, utf16_string_external_memory_size(string));
|
|
|
|
|
return size;
|
|
|
|
|
}
|
2021-06-09 10:02:01 +02:00
|
|
|
|
|
|
|
|
private:
|
2025-08-07 19:31:52 -04:00
|
|
|
Vector<Utf16String> m_strings;
|
2021-06-09 10:02:01 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|
2025-04-05 21:46:37 +02:00
|
|
|
|
|
|
|
|
namespace AK {
|
2025-05-13 07:06:33 -04:00
|
|
|
|
2025-04-05 21:46:37 +02:00
|
|
|
template<>
|
2026-03-18 20:43:56 +01:00
|
|
|
struct SentinelOptionalTraits<JS::Bytecode::StringTableIndex> {
|
|
|
|
|
static constexpr JS::Bytecode::StringTableIndex sentinel_value() { return { JS::Bytecode::StringTableIndex::invalid }; }
|
|
|
|
|
static constexpr bool is_sentinel(JS::Bytecode::StringTableIndex const& value) { return !value.is_valid(); }
|
|
|
|
|
};
|
2025-04-05 21:46:37 +02:00
|
|
|
|
2026-03-18 20:43:56 +01:00
|
|
|
template<>
|
|
|
|
|
class Optional<JS::Bytecode::StringTableIndex> : public SentinelOptional<JS::Bytecode::StringTableIndex> {
|
2025-04-05 21:46:37 +02:00
|
|
|
public:
|
2026-03-18 20:43:56 +01:00
|
|
|
using SentinelOptional::SentinelOptional;
|
2025-04-05 21:46:37 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
}
|