1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-08 05:27:14 +09:00
ladybird/Libraries/LibJS/Bytecode/Executable.h
Andreas Kling a677d96b8f LibJS: Make GetById cache polymorphic
Instead of monomorphic (1 shape), GetById inline caches are now
polymorphic (4 shapes).

This improves inline cache hit rates greatly on most web JavaScript.
For example, Speedometer 2.1 sees 88% -> 97% cache hit rate improvement.

1.71x speedup on MicroBench/pic-get-own.js
1.82x speedup on MicroBench/pic-get-pchain.js
2025-05-07 00:27:11 +02:00

120 lines
3.5 KiB
C++

/*
* Copyright (c) 2021-2024, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/FlyString.h>
#include <AK/HashMap.h>
#include <AK/NonnullOwnPtr.h>
#include <AK/OwnPtr.h>
#include <AK/WeakPtr.h>
#include <LibGC/CellAllocator.h>
#include <LibJS/Bytecode/IdentifierTable.h>
#include <LibJS/Bytecode/Label.h>
#include <LibJS/Bytecode/StringTable.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 {
WeakPtr<Shape> shape;
Optional<u32> property_offset;
WeakPtr<Object> prototype;
WeakPtr<PrototypeChainValidity> prototype_chain_validity;
};
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 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,
bool is_strict_mode);
virtual ~Executable() override;
FlyString 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 };
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;
String const& get_string(StringTableIndex index) const { return string_table->get(index); }
FlyString const& get_identifier(IdentifierTableIndex index) const { return identifier_table->get(index); }
Optional<FlyString 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;
private:
virtual void visit_edges(Visitor&) override;
};
}