diff --git a/Userland/Libraries/LibJS/JIT/Compiler.cpp b/Userland/Libraries/LibJS/JIT/Compiler.cpp index dac654f7a4..ab1289b841 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.cpp +++ b/Userland/Libraries/LibJS/JIT/Compiler.cpp @@ -1686,6 +1686,14 @@ OwnPtr Compiler::compile(Bytecode::Executable& bytecode_execut Compiler compiler { bytecode_executable }; + Vector mapping; + + mapping.append({ + .native_offset = compiler.m_output.size(), + .block_index = BytecodeMapping::EXECUTABLE, + .bytecode_offset = 0, + }); + compiler.m_assembler.enter(); compiler.m_assembler.mov( @@ -1696,12 +1704,20 @@ OwnPtr Compiler::compile(Bytecode::Executable& bytecode_execut Assembler::Operand::Register(LOCALS_ARRAY_BASE), Assembler::Operand::Register(ARG2)); - for (auto& block : bytecode_executable.basic_blocks) { + for (size_t block_index = 0; block_index < bytecode_executable.basic_blocks.size(); block_index++) { + auto& block = bytecode_executable.basic_blocks[block_index]; compiler.block_data_for(*block).start_offset = compiler.m_output.size(); compiler.set_current_block(*block); auto it = Bytecode::InstructionStreamIterator(block->instruction_stream()); while (!it.at_end()) { auto const& op = *it; + + mapping.append({ + .native_offset = compiler.m_output.size(), + .block_index = block_index, + .bytecode_offset = it.offset(), + }); + switch (op.type()) { # define CASE_BYTECODE_OP(OpTitleCase, op_snake_case, ...) \ case Bytecode::Instruction::Type::OpTitleCase: \ @@ -1723,6 +1739,12 @@ OwnPtr Compiler::compile(Bytecode::Executable& bytecode_execut compiler.jump_to_exit(); } + mapping.append({ + .native_offset = compiler.m_output.size(), + .block_index = BytecodeMapping::EXECUTABLE, + .bytecode_offset = 1, + }); + compiler.m_exit_label.link(compiler.m_assembler); compiler.m_assembler.exit(); @@ -1752,7 +1774,7 @@ OwnPtr Compiler::compile(Bytecode::Executable& bytecode_execut dbgln("\033[32;1mJIT compilation succeeded!\033[0m {}", bytecode_executable.name); } - auto executable = make(executable_memory, compiler.m_output.size()); + auto executable = make(executable_memory, compiler.m_output.size(), mapping); if constexpr (DUMP_JIT_DISASSEMBLY) executable->dump_disassembly(); return executable; diff --git a/Userland/Libraries/LibJS/JIT/NativeExecutable.cpp b/Userland/Libraries/LibJS/JIT/NativeExecutable.cpp index d827b8d9db..76020ef7a2 100644 --- a/Userland/Libraries/LibJS/JIT/NativeExecutable.cpp +++ b/Userland/Libraries/LibJS/JIT/NativeExecutable.cpp @@ -12,9 +12,10 @@ namespace JS::JIT { -NativeExecutable::NativeExecutable(void* code, size_t size) +NativeExecutable::NativeExecutable(void* code, size_t size, Vector mapping) : m_code(code) , m_size(size) + , m_mapping(move(mapping)) { } diff --git a/Userland/Libraries/LibJS/JIT/NativeExecutable.h b/Userland/Libraries/LibJS/JIT/NativeExecutable.h index d82aaee93e..1893dbe320 100644 --- a/Userland/Libraries/LibJS/JIT/NativeExecutable.h +++ b/Userland/Libraries/LibJS/JIT/NativeExecutable.h @@ -12,12 +12,21 @@ namespace JS::JIT { +struct BytecodeMapping { + size_t native_offset; + size_t block_index; + size_t bytecode_offset; + + // Special block index for labels outside any blocks. + static constexpr auto EXECUTABLE = NumericLimits::max(); +}; + class NativeExecutable { AK_MAKE_NONCOPYABLE(NativeExecutable); AK_MAKE_NONMOVABLE(NativeExecutable); public: - NativeExecutable(void* code, size_t size); + NativeExecutable(void* code, size_t size, Vector); ~NativeExecutable(); void run(VM&) const; @@ -26,6 +35,7 @@ public: private: void* m_code { nullptr }; size_t m_size { 0 }; + Vector m_mapping; }; }