Ver código fonte

LibJS+LibJIT: Add fast path for Int32 - Int32

Andreas Kling 1 ano atrás
pai
commit
17ae6edd8e

+ 25 - 0
Userland/Libraries/LibJIT/Assembler.h

@@ -664,6 +664,31 @@ struct Assembler {
         }
         }
     }
     }
 
 
+    void sub32(Operand dst, Operand src, Optional<Label&> overflow_label)
+    {
+        if (dst.is_register_or_memory() && src.type == Operand::Type::Reg) {
+            emit_rex_for_mr(dst, src, REX_W::No);
+            emit8(0x29);
+            emit_modrm_mr(dst, src);
+        } else if (dst.is_register_or_memory() && src.type == Operand::Type::Imm && src.fits_in_i8()) {
+            emit_rex_for_slash(dst, REX_W::No);
+            emit8(0x83);
+            emit_modrm_slash(5, dst);
+            emit8(src.offset_or_immediate);
+        } else if (dst.is_register_or_memory() && src.type == Operand::Type::Imm && src.fits_in_i32()) {
+            emit_rex_for_slash(dst, REX_W::No);
+            emit8(0x81);
+            emit_modrm_slash(5, dst);
+            emit32(src.offset_or_immediate);
+        } else {
+            VERIFY_NOT_REACHED();
+        }
+
+        if (overflow_label.has_value()) {
+            jump_if(Condition::Overflow, *overflow_label);
+        }
+    }
+
     // NOTE: It's up to the caller of this function to preserve registers as needed.
     // NOTE: It's up to the caller of this function to preserve registers as needed.
     void native_call(void* callee, Vector<Operand> const& stack_arguments = {})
     void native_call(void* callee, Vector<Operand> const& stack_arguments = {})
     {
     {

+ 42 - 0
Userland/Libraries/LibJS/JIT/Compiler.cpp

@@ -536,6 +536,48 @@ void Compiler::compile_add(Bytecode::Op::Add const& op)
     end.link(m_assembler);
     end.link(m_assembler);
 }
 }
 
 
+static Value cxx_sub(VM& vm, Value lhs, Value rhs)
+{
+    return TRY_OR_SET_EXCEPTION(sub(vm, lhs, rhs));
+}
+
+void Compiler::compile_sub(Bytecode::Op::Sub const& op)
+{
+    load_vm_register(ARG1, op.lhs());
+    load_accumulator(ARG2);
+
+    Assembler::Label end {};
+    Assembler::Label slow_case {};
+
+    branch_if_both_int32(ARG1, ARG2, [&] {
+        // GPR0 = ARG1 + ARG2 (32-bit)
+        // if (overflow) goto slow_case;
+        m_assembler.mov(
+            Assembler::Operand::Register(GPR0),
+            Assembler::Operand::Register(ARG1));
+        m_assembler.sub32(
+            Assembler::Operand::Register(GPR0),
+            Assembler::Operand::Register(ARG2),
+            slow_case);
+
+        // accumulator = GPR0 | SHIFTED_INT32_TAG;
+        m_assembler.mov(
+            Assembler::Operand::Register(GPR1),
+            Assembler::Operand::Imm(SHIFTED_INT32_TAG));
+        m_assembler.bitwise_or(
+            Assembler::Operand::Register(GPR0),
+            Assembler::Operand::Register(GPR1));
+        store_accumulator(GPR0);
+        m_assembler.jump(end);
+    });
+
+    slow_case.link(m_assembler);
+    native_call((void*)cxx_sub);
+    store_accumulator(RET);
+    check_exception();
+    end.link(m_assembler);
+}
+
 static Value cxx_less_than(VM& vm, Value lhs, Value rhs)
 static Value cxx_less_than(VM& vm, Value lhs, Value rhs)
 {
 {
     return TRY_OR_SET_EXCEPTION(less_than(vm, lhs, rhs));
     return TRY_OR_SET_EXCEPTION(less_than(vm, lhs, rhs));

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

@@ -41,7 +41,6 @@ private:
 #    endif
 #    endif
 
 
 #    define JS_ENUMERATE_COMMON_BINARY_OPS_WITHOUT_FAST_PATH(O) \
 #    define JS_ENUMERATE_COMMON_BINARY_OPS_WITHOUT_FAST_PATH(O) \
-        O(Sub, sub)                                             \
         O(Mul, mul)                                             \
         O(Mul, mul)                                             \
         O(Div, div)                                             \
         O(Div, div)                                             \
         O(Exp, exp)                                             \
         O(Exp, exp)                                             \