浏览代码

LibJS/JIT: Compile the CopyObjectExcludingProperties instruction

Simon Wanner 1 年之前
父节点
当前提交
ac59e982a9

+ 4 - 0
Userland/Libraries/LibJS/Bytecode/Op.h

@@ -241,6 +241,10 @@ public:
         return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Register) * excluded_names_count);
         return round_up_to_power_of_two(alignof(void*), sizeof(*this) + sizeof(Register) * excluded_names_count);
     }
     }
 
 
+    Register from_object() const { return m_from_object; }
+    size_t excluded_names_count() const { return m_excluded_names_count; }
+    Register const* excluded_names() const { return m_excluded_names; }
+
 private:
 private:
     Register m_from_object;
     Register m_from_object;
     size_t m_excluded_names_count { 0 };
     size_t m_excluded_names_count { 0 };

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

@@ -1679,6 +1679,44 @@ void Compiler::compile_put_by_value_with_this(Bytecode::Op::PutByValueWithThis c
     check_exception();
     check_exception();
 }
 }
 
 
+static Value cxx_copy_object_excluding_properties(VM& vm, Value from_object, u64 excluded_names_count, Value* excluded_names)
+{
+    auto& realm = *vm.current_realm();
+    auto to_object = Object::create(realm, realm.intrinsics().object_prototype());
+
+    HashTable<PropertyKey> excluded_names_table;
+    for (size_t i = 0; i < excluded_names_count; ++i) {
+        excluded_names_table.set(TRY_OR_SET_EXCEPTION(excluded_names[i].to_property_key(vm)));
+    }
+    TRY_OR_SET_EXCEPTION(to_object->copy_data_properties(vm, from_object, excluded_names_table));
+    return to_object;
+}
+
+void Compiler::compile_copy_object_excluding_properties(Bytecode::Op::CopyObjectExcludingProperties const& op)
+{
+    load_vm_register(ARG1, op.from_object());
+    m_assembler.mov(
+        Assembler::Operand::Register(ARG2),
+        Assembler::Operand::Imm(op.excluded_names_count()));
+
+    // Build `Value arg3[op.excluded_names_count()] {...}` on the stack.
+    auto stack_space = align_up_to(op.excluded_names_count() * sizeof(Value), 16);
+    m_assembler.sub(Assembler::Operand::Register(STACK_POINTER), Assembler::Operand::Imm(stack_space));
+    m_assembler.mov(Assembler::Operand::Register(ARG3), Assembler::Operand::Register(STACK_POINTER));
+    for (size_t i = 0; i < op.excluded_names_count(); ++i) {
+        load_vm_register(GPR0, op.excluded_names()[i]);
+        m_assembler.mov(Assembler::Operand::Mem64BaseAndOffset(ARG3, i * sizeof(Value)), Assembler::Operand::Register(GPR0));
+    }
+
+    native_call((void*)cxx_copy_object_excluding_properties);
+
+    // Restore the stack pointer / discard array.
+    m_assembler.add(Assembler::Operand::Register(STACK_POINTER), Assembler::Operand::Imm(stack_space));
+
+    store_vm_register(Bytecode::Register::accumulator(), RET);
+    check_exception();
+}
+
 void Compiler::jump_to_exit()
 void Compiler::jump_to_exit()
 {
 {
     m_assembler.jump(m_exit_label);
     m_assembler.jump(m_exit_label);

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

@@ -138,7 +138,8 @@ private:
         O(GetMethod, get_method)                                                 \
         O(GetMethod, get_method)                                                 \
         O(GetNewTarget, get_new_target)                                          \
         O(GetNewTarget, get_new_target)                                          \
         O(HasPrivateId, has_private_id)                                          \
         O(HasPrivateId, has_private_id)                                          \
-        O(PutByValueWithThis, put_by_value_with_this)
+        O(PutByValueWithThis, put_by_value_with_this)                            \
+        O(CopyObjectExcludingProperties, copy_object_excluding_properties)
 
 
 #    define DECLARE_COMPILE_OP(OpTitleCase, op_snake_case, ...) \
 #    define DECLARE_COMPILE_OP(OpTitleCase, op_snake_case, ...) \
         void compile_##op_snake_case(Bytecode::Op::OpTitleCase const&);
         void compile_##op_snake_case(Bytecode::Op::OpTitleCase const&);