diff --git a/Userland/Libraries/LibJS/CMakeLists.txt b/Userland/Libraries/LibJS/CMakeLists.txt index fba62681464..20a04b05c4e 100644 --- a/Userland/Libraries/LibJS/CMakeLists.txt +++ b/Userland/Libraries/LibJS/CMakeLists.txt @@ -268,3 +268,6 @@ set(SOURCES serenity_lib(LibJS js) target_link_libraries(LibJS PRIVATE LibCore LibCrypto LibFileSystem LibRegex LibSyntax LibLocale LibUnicode LibJIT) +if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64") + target_link_libraries(LibJS PRIVATE LibX86) +endif() diff --git a/Userland/Libraries/LibJS/JIT/Compiler.cpp b/Userland/Libraries/LibJS/JIT/Compiler.cpp index a1921386a02..9dcfc56dc81 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.cpp +++ b/Userland/Libraries/LibJS/JIT/Compiler.cpp @@ -24,6 +24,7 @@ # define LOG_JIT_SUCCESS 1 # define LOG_JIT_FAILURE 1 # define DUMP_JIT_MACHINE_CODE_TO_STDOUT 0 +# define DUMP_JIT_DISASSEMBLY 0 # define TRY_OR_SET_EXCEPTION(expression) \ ({ \ @@ -1154,7 +1155,10 @@ OwnPtr Compiler::compile(Bytecode::Executable& bytecode_execut dbgln("\033[32;1mJIT compilation succeeded!\033[0m {}", bytecode_executable.name); } - return make(executable_memory, compiler.m_output.size()); + auto executable = make(executable_memory, compiler.m_output.size()); + 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 af71d1c1517..d827b8d9dba 100644 --- a/Userland/Libraries/LibJS/JIT/NativeExecutable.cpp +++ b/Userland/Libraries/LibJS/JIT/NativeExecutable.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include namespace JS::JIT { @@ -30,4 +31,42 @@ void NativeExecutable::run(VM& vm) const vm.running_execution_context().local_variables.data()); } +void NativeExecutable::dump_disassembly() const +{ +#if ARCH(X86_64) + auto const* code_bytes = static_cast(m_code); + auto stream = X86::SimpleInstructionStream { code_bytes, m_size }; + auto disassembler = X86::Disassembler(stream); + + while (true) { + auto offset = stream.offset(); + auto virtual_offset = bit_cast(m_code) + offset; + auto insn = disassembler.next(); + if (!insn.has_value()) + break; + + StringBuilder builder; + builder.appendff("{:p} ", virtual_offset); + auto length = insn.value().length(); + for (size_t i = 0; i < 7; i++) { + if (i < length) + builder.appendff("{:02x} ", code_bytes[offset + i]); + else + builder.append(" "sv); + } + builder.append(" "sv); + builder.append(insn.value().to_deprecated_string(virtual_offset, nullptr)); + dbgln("{}", builder.string_view()); + + for (size_t bytes_printed = 7; bytes_printed < length; bytes_printed += 7) { + builder.clear(); + builder.appendff("{:p} ", virtual_offset + bytes_printed); + for (size_t i = bytes_printed; i < bytes_printed + 7 && i < length; i++) + builder.appendff(" {:02x}", code_bytes[offset + i]); + dbgln("{}", builder.string_view()); + } + } +#endif +} + } diff --git a/Userland/Libraries/LibJS/JIT/NativeExecutable.h b/Userland/Libraries/LibJS/JIT/NativeExecutable.h index 332a2a7054e..d82aaee93e2 100644 --- a/Userland/Libraries/LibJS/JIT/NativeExecutable.h +++ b/Userland/Libraries/LibJS/JIT/NativeExecutable.h @@ -21,6 +21,7 @@ public: ~NativeExecutable(); void run(VM&) const; + void dump_disassembly() const; private: void* m_code { nullptr };