mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2026-04-19 10:20:22 +00:00
While we're in the bytecode compiler, we want to know which type of Operand we're dealing with, but once we've generated the bytecode stream, we only ever need its index. This patch simplifies Operand by removing the aarch64 bitfield hacks and makes it 32-bit on all platforms. We keep 3 type bits in the high bits of the index while compiling, and then zero them out when flattening the final bytecode stream. This makes bytecode more compact on x86_64, and avoids bit twiddling on aarch64. Everyone wins something! When stringifying bytecode for debugging output, we now have an API in Executable that can look at a raw operand index and tell you what type of operand it was, based on known quantities of each type in the stack frame.
138 lines
4 KiB
C++
138 lines
4 KiB
C++
/*
|
|
* Copyright (c) 2021-2025, Andreas Kling <andreas@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/HashMap.h>
|
|
#include <AK/NonnullOwnPtr.h>
|
|
#include <AK/OwnPtr.h>
|
|
#include <AK/Utf16FlyString.h>
|
|
#include <LibGC/CellAllocator.h>
|
|
#include <LibGC/Weak.h>
|
|
#include <LibGC/WeakInlines.h>
|
|
#include <LibJS/Bytecode/IdentifierTable.h>
|
|
#include <LibJS/Bytecode/Label.h>
|
|
#include <LibJS/Bytecode/Operand.h>
|
|
#include <LibJS/Bytecode/StringTable.h>
|
|
#include <LibJS/Export.h>
|
|
#include <LibJS/Forward.h>
|
|
#include <LibJS/Heap/Cell.h>
|
|
#include <LibJS/LocalVariable.h>
|
|
#include <LibJS/Runtime/EnvironmentCoordinate.h>
|
|
#include <LibJS/SourceRange.h>
|
|
|
|
namespace JS::Bytecode {
|
|
|
|
// Represents one polymorphic inline cache used for property lookups.
|
|
struct PropertyLookupCache {
|
|
static constexpr size_t max_number_of_shapes_to_remember = 4;
|
|
struct Entry {
|
|
enum class Type {
|
|
Empty,
|
|
AddOwnProperty,
|
|
ChangeOwnProperty,
|
|
GetOwnProperty,
|
|
ChangePropertyInPrototypeChain,
|
|
GetPropertyInPrototypeChain,
|
|
};
|
|
Type type { Type::Empty };
|
|
GC::Weak<Shape> from_shape;
|
|
GC::Weak<Shape> shape;
|
|
Optional<u32> property_offset;
|
|
GC::Weak<Object> prototype;
|
|
GC::Weak<PrototypeChainValidity> prototype_chain_validity;
|
|
Optional<u32> shape_dictionary_generation;
|
|
};
|
|
AK::Array<Entry, max_number_of_shapes_to_remember> entries;
|
|
};
|
|
|
|
struct GlobalVariableCache : public PropertyLookupCache {
|
|
u64 environment_serial_number { 0 };
|
|
u32 environment_binding_index { 0 };
|
|
bool has_environment_binding_index { false };
|
|
bool in_module_environment { false };
|
|
};
|
|
|
|
struct SourceRecord {
|
|
u32 source_start_offset {};
|
|
u32 source_end_offset {};
|
|
};
|
|
|
|
class JS_API Executable final : public Cell {
|
|
GC_CELL(Executable, Cell);
|
|
GC_DECLARE_ALLOCATOR(Executable);
|
|
|
|
public:
|
|
Executable(
|
|
Vector<u8> bytecode,
|
|
NonnullOwnPtr<IdentifierTable>,
|
|
NonnullOwnPtr<StringTable>,
|
|
NonnullOwnPtr<RegexTable>,
|
|
Vector<Value> constants,
|
|
NonnullRefPtr<SourceCode const>,
|
|
size_t number_of_property_lookup_caches,
|
|
size_t number_of_global_variable_caches,
|
|
size_t number_of_registers,
|
|
Strict);
|
|
|
|
virtual ~Executable() override;
|
|
|
|
Utf16FlyString name;
|
|
Vector<u8> bytecode;
|
|
Vector<PropertyLookupCache> property_lookup_caches;
|
|
Vector<GlobalVariableCache> global_variable_caches;
|
|
NonnullOwnPtr<StringTable> string_table;
|
|
NonnullOwnPtr<IdentifierTable> identifier_table;
|
|
NonnullOwnPtr<RegexTable> regex_table;
|
|
Vector<Value> constants;
|
|
|
|
NonnullRefPtr<SourceCode const> source_code;
|
|
size_t number_of_registers { 0 };
|
|
bool is_strict_mode { false };
|
|
|
|
size_t registers_and_constants_and_locals_count { 0 };
|
|
|
|
struct ExceptionHandlers {
|
|
size_t start_offset;
|
|
size_t end_offset;
|
|
Optional<size_t> handler_offset;
|
|
Optional<size_t> finalizer_offset;
|
|
};
|
|
|
|
Vector<ExceptionHandlers> exception_handlers;
|
|
Vector<size_t> basic_block_start_offsets;
|
|
|
|
HashMap<size_t, SourceRecord> source_map;
|
|
|
|
Vector<LocalVariable> local_variable_names;
|
|
size_t local_index_base { 0 };
|
|
size_t argument_index_base { 0 };
|
|
|
|
Optional<IdentifierTableIndex> length_identifier;
|
|
|
|
Utf16String const& get_string(StringTableIndex index) const { return string_table->get(index); }
|
|
Utf16FlyString const& get_identifier(IdentifierTableIndex index) const { return identifier_table->get(index); }
|
|
|
|
Optional<Utf16FlyString const&> get_identifier(Optional<IdentifierTableIndex> const& index) const
|
|
{
|
|
if (!index.has_value())
|
|
return {};
|
|
return get_identifier(*index);
|
|
}
|
|
|
|
[[nodiscard]] Optional<ExceptionHandlers const&> exception_handlers_for_offset(size_t offset) const;
|
|
|
|
[[nodiscard]] UnrealizedSourceRange source_range_at(size_t offset) const;
|
|
|
|
void dump() const;
|
|
|
|
[[nodiscard]] Operand original_operand_from_raw(u32) const;
|
|
|
|
private:
|
|
virtual void visit_edges(Visitor&) override;
|
|
};
|
|
|
|
}
|