diff --git a/Userland/Libraries/LibJS/JIT/Compiler.cpp b/Userland/Libraries/LibJS/JIT/Compiler.cpp index 06e572cd15b..6e3c5c0935b 100644 --- a/Userland/Libraries/LibJS/JIT/Compiler.cpp +++ b/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_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::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); store_accumulator(RET); check_exception(); + end.link(m_assembler); } static Value cxx_get_global(VM& vm, DeprecatedFlyString const& identifier, Bytecode::GlobalVariableCache& cache)