Explorar o código

LibJS/JIT: Consolidate exits from the jitted code

Instead of emitting the "restore callee-saved registers and return"
sequence again and again, just emit it once at the end of the generated
code, and have everyone jump to it.

This is a code size optimization that saves 207KiB on Kraken/ai-astar.js
Andreas Kling hai 1 ano
pai
achega
9afd12a8ba

+ 12 - 4
Userland/Libraries/LibJS/JIT/Compiler.cpp

@@ -337,7 +337,7 @@ void Compiler::check_exception()
         Assembler::Operand::Imm(0),
         handle_exception);
 
-    m_assembler.exit();
+    jump_to_exit();
 
     // handle_exception:
     handle_exception.link(m_assembler);
@@ -593,7 +593,7 @@ void Compiler::compile_return(Bytecode::Op::Return const&)
     // normal_return:
     normal_return.link(m_assembler);
     store_vm_register(Bytecode::Register::return_value(), GPR0);
-    m_assembler.exit();
+    jump_to_exit();
 }
 
 static Value cxx_new_string(VM& vm, DeprecatedString const& string)
@@ -971,7 +971,7 @@ void Compiler::compile_continue_pending_unwind(Bytecode::Op::ContinuePendingUnwi
 
     // finish the pending return from the try block
     store_vm_register(Bytecode::Register::return_value(), GPR0);
-    m_assembler.exit();
+    jump_to_exit();
 }
 
 static void cxx_create_lexical_environment(VM& vm)
@@ -999,6 +999,11 @@ void Compiler::compile_leave_lexical_environment(Bytecode::Op::LeaveLexicalEnvir
     m_assembler.native_call((void*)cxx_leave_lexical_environment);
 }
 
+void Compiler::jump_to_exit()
+{
+    m_assembler.jump(m_exit_label);
+}
+
 OwnPtr<NativeExecutable> Compiler::compile(Bytecode::Executable& bytecode_executable)
 {
     if (!getenv("LIBJS_JIT"))
@@ -1158,9 +1163,12 @@ OwnPtr<NativeExecutable> Compiler::compile(Bytecode::Executable& bytecode_execut
             ++it;
         }
         if (!block->is_terminated())
-            compiler.m_assembler.exit();
+            compiler.jump_to_exit();
     }
 
+    compiler.m_exit_label.link(compiler.m_assembler);
+    compiler.m_assembler.exit();
+
     auto* executable_memory = mmap(nullptr, compiler.m_output.size(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
     if (executable_memory == MAP_FAILED) {
         dbgln("mmap: {}", strerror(errno));

+ 3 - 0
Userland/Libraries/LibJS/JIT/Compiler.h

@@ -127,6 +127,8 @@ private:
     void push_unwind_context(bool valid, Optional<Bytecode::Label> const& handler, Optional<Bytecode::Label> const& finalizer);
     void pop_unwind_context();
 
+    void jump_to_exit();
+
     template<typename Codegen>
     void branch_if_int32(Assembler::Reg, Codegen);
 
@@ -160,6 +162,7 @@ private:
 
     Vector<u8> m_output;
     Assembler m_assembler { m_output };
+    Assembler::Label m_exit_label;
     Bytecode::Executable& m_bytecode_executable;
 };