Bläddra i källkod

LibJS: Add GetByValue fast path for simple array access

iliadsh 1 år sedan
förälder
incheckning
94b47ff03b
1 ändrade filer med 112 tillägg och 0 borttagningar
  1. 112 0
      Userland/Libraries/LibJS/JIT/Compiler.cpp

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

@@ -1208,9 +1208,121 @@ void Compiler::compile_get_by_value(Bytecode::Op::GetByValue const& op)
 {
 {
     load_vm_register(ARG1, op.base());
     load_vm_register(ARG1, op.base());
     load_accumulator(ARG2);
     load_accumulator(ARG2);
+
+    Assembler::Label end {};
+    Assembler::Label slow_case {};
+
+    branch_if_object(ARG1, [&] {
+        branch_if_int32(ARG2, [&] {
+            // if (ARG2 < 0) goto slow_case;
+            m_assembler.mov(
+                Assembler::Operand::Register(GPR0),
+                Assembler::Operand::Register(ARG2));
+            m_assembler.sign_extend_32_to_64_bits(GPR0);
+            m_assembler.jump_if(
+                Assembler::Operand::Register(GPR0),
+                Assembler::Condition::SignedLessThan,
+                Assembler::Operand::Imm(0),
+                slow_case);
+
+            // GPR0 = extract_pointer(ARG1)
+            extract_object_pointer(GPR0, ARG1);
+
+            // if (object->may_interfere_with_indexed_property_access()) goto slow_case;
+            m_assembler.mov8(
+                Assembler::Operand::Register(GPR1),
+                Assembler::Operand::Mem64BaseAndOffset(GPR0, Object::may_interfere_with_indexed_property_access_offset()));
+            m_assembler.jump_if(
+                Assembler::Operand::Register(GPR1),
+                Assembler::Condition::NotEqualTo,
+                Assembler::Operand::Imm(0),
+                slow_case);
+
+            // GPR0 = object->indexed_properties().storage()
+            m_assembler.mov(
+                Assembler::Operand::Register(GPR0),
+                Assembler::Operand::Mem64BaseAndOffset(GPR0, Object::indexed_properties_offset() + IndexedProperties::storage_offset()));
+
+            // if (GPR0 == nullptr) goto slow_case;
+            m_assembler.jump_if(
+                Assembler::Operand::Register(GPR0),
+                Assembler::Condition::EqualTo,
+                Assembler::Operand::Imm(0),
+                slow_case);
+
+            // if (!GPR0->is_simple_storage()) goto slow_case;
+            m_assembler.mov8(
+                Assembler::Operand::Register(GPR1),
+                Assembler::Operand::Mem64BaseAndOffset(GPR0, IndexedPropertyStorage::is_simple_storage_offset()));
+            m_assembler.jump_if(
+                Assembler::Operand::Register(GPR1),
+                Assembler::Condition::EqualTo,
+                Assembler::Operand::Imm(0),
+                slow_case);
+
+            // GPR2 = extract_int32(ARG2)
+            m_assembler.mov32(
+                Assembler::Operand::Register(GPR2),
+                Assembler::Operand::Register(ARG2));
+
+            // if (GPR2 >= GPR0->array_like_size()) goto slow_case;
+            m_assembler.mov(
+                Assembler::Operand::Register(GPR1),
+                Assembler::Operand::Mem64BaseAndOffset(GPR0, SimpleIndexedPropertyStorage::array_size_offset()));
+            m_assembler.jump_if(
+                Assembler::Operand::Register(GPR2),
+                Assembler::Condition::SignedGreaterThanOrEqualTo,
+                Assembler::Operand::Register(GPR1),
+                slow_case);
+
+            // GPR0 = GPR0->elements().outline_buffer()
+            m_assembler.mov(
+                Assembler::Operand::Register(GPR0),
+                Assembler::Operand::Mem64BaseAndOffset(GPR0, SimpleIndexedPropertyStorage::elements_offset() + Vector<Value>::outline_buffer_offset()));
+
+            // GPR2 *= sizeof(Value)
+            m_assembler.mul32(
+                Assembler::Operand::Register(GPR2),
+                Assembler::Operand::Imm(sizeof(Value)),
+                slow_case);
+
+            // GPR0 = GPR0[GPR2]
+            m_assembler.add(
+                Assembler::Operand::Register(GPR0),
+                Assembler::Operand::Register(GPR2));
+            m_assembler.mov(
+                Assembler::Operand::Register(GPR0),
+                Assembler::Operand::Mem64BaseAndOffset(GPR0, 0));
+
+            // if (GPR0.is_empty()) goto slow_case;
+            m_assembler.mov(Assembler::Operand::Register(GPR1), Assembler::Operand::Register(GPR0));
+            m_assembler.shift_right(Assembler::Operand::Register(GPR1), Assembler::Operand::Imm(TAG_SHIFT));
+            m_assembler.jump_if(
+                Assembler::Operand::Register(GPR1),
+                Assembler::Condition::EqualTo,
+                Assembler::Operand::Imm(EMPTY_TAG),
+                slow_case);
+
+            // if (GPR0.is_accessor()) goto slow_case;
+            m_assembler.mov(Assembler::Operand::Register(GPR1), Assembler::Operand::Register(GPR0));
+            m_assembler.shift_right(Assembler::Operand::Register(GPR1), Assembler::Operand::Imm(TAG_SHIFT));
+            m_assembler.jump_if(
+                Assembler::Operand::Register(GPR1),
+                Assembler::Condition::EqualTo,
+                Assembler::Operand::Imm(ACCESSOR_TAG),
+                slow_case);
+
+            // accumulator = GPR0;
+            store_accumulator(GPR0);
+            m_assembler.jump(end);
+        });
+    });
+
+    slow_case.link(m_assembler);
     native_call((void*)cxx_get_by_value);
     native_call((void*)cxx_get_by_value);
     store_accumulator(RET);
     store_accumulator(RET);
     check_exception();
     check_exception();
+    end.link(m_assembler);
 }
 }
 
 
 static Value cxx_get_global(VM& vm, DeprecatedFlyString const& identifier, Bytecode::GlobalVariableCache& cache)
 static Value cxx_get_global(VM& vm, DeprecatedFlyString const& identifier, Bytecode::GlobalVariableCache& cache)