فهرست منبع

LibJS/JIT: Allow multiple jumps to the same Assembler::Label

Andreas Kling 1 سال پیش
والد
کامیت
4b7f5f4ae7
2فایلهای تغییر یافته به همراه32 افزوده شده و 27 حذف شده
  1. 24 13
      Userland/Libraries/LibJS/JIT/Assembler.h
  2. 8 14
      Userland/Libraries/LibJS/JIT/Compiler.cpp

+ 24 - 13
Userland/Libraries/LibJS/JIT/Assembler.h

@@ -178,22 +178,31 @@ struct Assembler {
     }
     }
 
 
     struct Label {
     struct Label {
-        size_t offset_in_instruction_stream { 0 };
+        size_t offset_of_label_in_instruction_stream { 0 };
+        Vector<size_t> jump_slot_offsets_in_instruction_stream;
+
+        void add_jump(size_t offset)
+        {
+            jump_slot_offsets_in_instruction_stream.append(offset);
+        }
 
 
         void link(Assembler& assembler)
         void link(Assembler& assembler)
         {
         {
-            auto offset = assembler.m_output.size() - offset_in_instruction_stream;
-            auto jump_slot = offset_in_instruction_stream - 4;
-            assembler.m_output[jump_slot + 0] = (offset >> 0) & 0xff;
-            assembler.m_output[jump_slot + 1] = (offset >> 8) & 0xff;
-            assembler.m_output[jump_slot + 2] = (offset >> 16) & 0xff;
-            assembler.m_output[jump_slot + 3] = (offset >> 24) & 0xff;
+            offset_of_label_in_instruction_stream = assembler.m_output.size();
+            for (auto offset_in_instruction_stream : jump_slot_offsets_in_instruction_stream) {
+                auto offset = offset_of_label_in_instruction_stream - offset_in_instruction_stream;
+                auto jump_slot = offset_in_instruction_stream - 4;
+                assembler.m_output[jump_slot + 0] = (offset >> 0) & 0xff;
+                assembler.m_output[jump_slot + 1] = (offset >> 8) & 0xff;
+                assembler.m_output[jump_slot + 2] = (offset >> 16) & 0xff;
+                assembler.m_output[jump_slot + 3] = (offset >> 24) & 0xff;
+            }
         }
         }
     };
     };
 
 
     [[nodiscard]] Label make_label()
     [[nodiscard]] Label make_label()
     {
     {
-        return { .offset_in_instruction_stream = m_output.size() };
+        return { .offset_of_label_in_instruction_stream = m_output.size() };
     }
     }
 
 
     [[nodiscard]] Label jump()
     [[nodiscard]] Label jump()
@@ -201,7 +210,9 @@ struct Assembler {
         // jmp target (RIP-relative 32-bit offset)
         // jmp target (RIP-relative 32-bit offset)
         emit8(0xe9);
         emit8(0xe9);
         emit32(0xdeadbeef);
         emit32(0xdeadbeef);
-        return make_label();
+        auto label = make_label();
+        label.add_jump(m_output.size());
+        return label;
     }
     }
 
 
     void jump(Label& label)
     void jump(Label& label)
@@ -209,7 +220,7 @@ struct Assembler {
         // jmp target (RIP-relative 32-bit offset)
         // jmp target (RIP-relative 32-bit offset)
         emit8(0xe9);
         emit8(0xe9);
         emit32(0xdeadbeef);
         emit32(0xdeadbeef);
-        label.offset_in_instruction_stream = m_output.size();
+        label.add_jump(m_output.size());
     }
     }
 
 
     void jump(Operand op)
     void jump(Operand op)
@@ -284,7 +295,7 @@ struct Assembler {
         emit8(0x0f);
         emit8(0x0f);
         emit8(0x84);
         emit8(0x84);
         emit32(0xdeadbeef);
         emit32(0xdeadbeef);
-        label.offset_in_instruction_stream = m_output.size();
+        label.add_jump(m_output.size());
     }
     }
 
 
     void jump_if_not_equal(Operand lhs, Operand rhs, Label& label)
     void jump_if_not_equal(Operand lhs, Operand rhs, Label& label)
@@ -295,7 +306,7 @@ struct Assembler {
         emit8(0x0f);
         emit8(0x0f);
         emit8(0x85);
         emit8(0x85);
         emit32(0xdeadbeef);
         emit32(0xdeadbeef);
-        label.offset_in_instruction_stream = m_output.size();
+        label.add_jump(m_output.size());
     }
     }
 
 
     void jump_if_less_than(Operand lhs, Operand rhs, Label& label)
     void jump_if_less_than(Operand lhs, Operand rhs, Label& label)
@@ -306,7 +317,7 @@ struct Assembler {
         emit8(0x0f);
         emit8(0x0f);
         emit8(0x8c);
         emit8(0x8c);
         emit32(0xdeadbeef);
         emit32(0xdeadbeef);
-        label.offset_in_instruction_stream = m_output.size();
+        label.add_jump(m_output.size());
     }
     }
 
 
     void bitwise_and(Operand dst, Operand src)
     void bitwise_and(Operand dst, Operand src)

+ 8 - 14
Userland/Libraries/LibJS/JIT/Compiler.cpp

@@ -198,22 +198,19 @@ void Compiler::branch_if_both_int32(Assembler::Reg lhs, Assembler::Reg rhs, Code
     m_assembler.mov(Assembler::Operand::Register(GPR1), Assembler::Operand::Register(rhs));
     m_assembler.mov(Assembler::Operand::Register(GPR1), Assembler::Operand::Register(rhs));
     m_assembler.shift_right(Assembler::Operand::Register(GPR1), Assembler::Operand::Imm8(48));
     m_assembler.shift_right(Assembler::Operand::Register(GPR1), Assembler::Operand::Imm8(48));
 
 
-    // FIXME: Use one label once Assembler::Label supports multiple jumps to it.
-    auto not_int32_case1 = m_assembler.make_label();
-    auto not_int32_case2 = m_assembler.make_label();
+    auto not_int32_case = m_assembler.make_label();
     m_assembler.jump_if_not_equal(
     m_assembler.jump_if_not_equal(
         Assembler::Operand::Register(GPR0),
         Assembler::Operand::Register(GPR0),
         Assembler::Operand::Imm32(INT32_TAG),
         Assembler::Operand::Imm32(INT32_TAG),
-        not_int32_case1);
+        not_int32_case);
     m_assembler.jump_if_not_equal(
     m_assembler.jump_if_not_equal(
         Assembler::Operand::Register(GPR1),
         Assembler::Operand::Register(GPR1),
         Assembler::Operand::Imm32(INT32_TAG),
         Assembler::Operand::Imm32(INT32_TAG),
-        not_int32_case2);
+        not_int32_case);
 
 
     codegen();
     codegen();
 
 
-    not_int32_case1.link(m_assembler);
-    not_int32_case2.link(m_assembler);
+    not_int32_case.link(m_assembler);
 }
 }
 
 
 void Compiler::compile_increment(Bytecode::Op::Increment const&)
 void Compiler::compile_increment(Bytecode::Op::Increment const&)
@@ -464,9 +461,7 @@ void Compiler::compile_less_than(Bytecode::Op::LessThan const& op)
     load_vm_register(ARG1, op.lhs());
     load_vm_register(ARG1, op.lhs());
     load_vm_register(ARG2, Bytecode::Register::accumulator());
     load_vm_register(ARG2, Bytecode::Register::accumulator());
 
 
-    // FIXME: Unify when we have multi-jump labels.
-    auto end1 = m_assembler.make_label();
-    auto end2 = m_assembler.make_label();
+    auto end = m_assembler.make_label();
 
 
     branch_if_both_int32(ARG1, ARG2, [&] {
     branch_if_both_int32(ARG1, ARG2, [&] {
         // if (ARG1 < ARG2) return true;
         // if (ARG1 < ARG2) return true;
@@ -482,7 +477,7 @@ void Compiler::compile_less_than(Bytecode::Op::LessThan const& op)
             Assembler::Operand::Register(GPR0),
             Assembler::Operand::Register(GPR0),
             Assembler::Operand::Imm64(Value(false).encoded()));
             Assembler::Operand::Imm64(Value(false).encoded()));
         store_vm_register(Bytecode::Register::accumulator(), GPR0);
         store_vm_register(Bytecode::Register::accumulator(), GPR0);
-        m_assembler.jump(end1);
+        m_assembler.jump(end);
 
 
         true_case.link(m_assembler);
         true_case.link(m_assembler);
         m_assembler.mov(
         m_assembler.mov(
@@ -490,14 +485,13 @@ void Compiler::compile_less_than(Bytecode::Op::LessThan const& op)
             Assembler::Operand::Imm64(Value(true).encoded()));
             Assembler::Operand::Imm64(Value(true).encoded()));
         store_vm_register(Bytecode::Register::accumulator(), GPR0);
         store_vm_register(Bytecode::Register::accumulator(), GPR0);
 
 
-        m_assembler.jump(end2);
+        m_assembler.jump(end);
     });
     });
 
 
     m_assembler.native_call((void*)cxx_less_than);
     m_assembler.native_call((void*)cxx_less_than);
     store_vm_register(Bytecode::Register::accumulator(), RET);
     store_vm_register(Bytecode::Register::accumulator(), RET);
     check_exception();
     check_exception();
-    end1.link(m_assembler);
-    end2.link(m_assembler);
+    end.link(m_assembler);
 }
 }
 
 
 static ThrowCompletionOr<Value> not_(VM&, Value value)
 static ThrowCompletionOr<Value> not_(VM&, Value value)