mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-21 23:20:20 +00:00
f87041bf3a
Resulting in a massive rename across almost everywhere! Alongside the namespace change, we now have the following names: * JS::NonnullGCPtr -> GC::Ref * JS::GCPtr -> GC::Ptr * JS::HeapFunction -> GC::Function * JS::CellImpl -> GC::Cell * JS::Handle -> GC::Root
118 lines
3.5 KiB
C++
118 lines
3.5 KiB
C++
/*
|
|
* Copyright (c) 2021-2024, Andreas Kling <andreas@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibJS/Bytecode/BasicBlock.h>
|
|
#include <LibJS/Bytecode/Executable.h>
|
|
#include <LibJS/Bytecode/Instruction.h>
|
|
#include <LibJS/Bytecode/RegexTable.h>
|
|
#include <LibJS/Runtime/Value.h>
|
|
#include <LibJS/SourceCode.h>
|
|
|
|
namespace JS::Bytecode {
|
|
|
|
GC_DEFINE_ALLOCATOR(Executable);
|
|
|
|
Executable::Executable(
|
|
Vector<u8> bytecode,
|
|
NonnullOwnPtr<IdentifierTable> identifier_table,
|
|
NonnullOwnPtr<StringTable> string_table,
|
|
NonnullOwnPtr<RegexTable> regex_table,
|
|
Vector<Value> constants,
|
|
NonnullRefPtr<SourceCode const> source_code,
|
|
size_t number_of_property_lookup_caches,
|
|
size_t number_of_global_variable_caches,
|
|
size_t number_of_registers,
|
|
bool is_strict_mode)
|
|
: bytecode(move(bytecode))
|
|
, string_table(move(string_table))
|
|
, identifier_table(move(identifier_table))
|
|
, regex_table(move(regex_table))
|
|
, constants(move(constants))
|
|
, source_code(move(source_code))
|
|
, number_of_registers(number_of_registers)
|
|
, is_strict_mode(is_strict_mode)
|
|
{
|
|
property_lookup_caches.resize(number_of_property_lookup_caches);
|
|
global_variable_caches.resize(number_of_global_variable_caches);
|
|
}
|
|
|
|
Executable::~Executable() = default;
|
|
|
|
void Executable::dump() const
|
|
{
|
|
warnln("\033[37;1mJS bytecode executable\033[0m \"{}\"", name);
|
|
InstructionStreamIterator it(bytecode, this);
|
|
|
|
size_t basic_block_offset_index = 0;
|
|
|
|
while (!it.at_end()) {
|
|
bool print_basic_block_marker = false;
|
|
if (basic_block_offset_index < basic_block_start_offsets.size()
|
|
&& it.offset() == basic_block_start_offsets[basic_block_offset_index]) {
|
|
++basic_block_offset_index;
|
|
print_basic_block_marker = true;
|
|
}
|
|
|
|
StringBuilder builder;
|
|
builder.appendff("[{:4x}] ", it.offset());
|
|
if (print_basic_block_marker)
|
|
builder.appendff("{:4}: ", basic_block_offset_index - 1);
|
|
else
|
|
builder.append(" "sv);
|
|
builder.append((*it).to_byte_string(*this));
|
|
|
|
warnln("{}", builder.string_view());
|
|
|
|
++it;
|
|
}
|
|
|
|
if (!exception_handlers.is_empty()) {
|
|
warnln("");
|
|
warnln("Exception handlers:");
|
|
for (auto& handlers : exception_handlers) {
|
|
warnln(" from {:4x} to {:4x} handler {:4x} finalizer {:4x}",
|
|
handlers.start_offset,
|
|
handlers.end_offset,
|
|
handlers.handler_offset.value_or(0),
|
|
handlers.finalizer_offset.value_or(0));
|
|
}
|
|
}
|
|
|
|
warnln("");
|
|
}
|
|
|
|
void Executable::visit_edges(Visitor& visitor)
|
|
{
|
|
Base::visit_edges(visitor);
|
|
visitor.visit(constants);
|
|
}
|
|
|
|
Optional<Executable::ExceptionHandlers const&> Executable::exception_handlers_for_offset(size_t offset) const
|
|
{
|
|
for (auto& handlers : exception_handlers) {
|
|
if (handlers.start_offset <= offset && offset < handlers.end_offset)
|
|
return handlers;
|
|
}
|
|
return {};
|
|
}
|
|
|
|
UnrealizedSourceRange Executable::source_range_at(size_t offset) const
|
|
{
|
|
if (offset >= bytecode.size())
|
|
return {};
|
|
auto it = InstructionStreamIterator(bytecode.span().slice(offset), this);
|
|
VERIFY(!it.at_end());
|
|
auto mapping = source_map.get(offset);
|
|
if (!mapping.has_value())
|
|
return {};
|
|
return UnrealizedSourceRange {
|
|
.source_code = source_code,
|
|
.start_offset = mapping->source_start_offset,
|
|
.end_offset = mapping->source_end_offset,
|
|
};
|
|
}
|
|
|
|
}
|