瀏覽代碼

LibJS: Use ranges instead of specifying all registers for NewArray

Listing all the registers will lead to the inability to allocate enough
space in one basic block (as there can be an arbitrary number of
registers used), instead switch to specifying the range of registers
used and save a lot of space in the process.
Ali Mohammad Pur 3 年之前
父節點
當前提交
a37bee919a

+ 41 - 14
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -845,24 +845,33 @@ Bytecode::CodeGenerationErrorOr<void> ObjectExpression::generate_bytecode(Byteco
 Bytecode::CodeGenerationErrorOr<void> ArrayExpression::generate_bytecode(Bytecode::Generator& generator) const
 Bytecode::CodeGenerationErrorOr<void> ArrayExpression::generate_bytecode(Bytecode::Generator& generator) const
 {
 {
     Vector<Bytecode::Register> element_regs;
     Vector<Bytecode::Register> element_regs;
+    for (auto& element : m_elements) {
+        if (element && is<SpreadExpression>(*element)) {
+            return Bytecode::CodeGenerationError {
+                this,
+                "Unimplemented element kind: SpreadExpression"sv,
+            };
+        }
+        element_regs.append(generator.allocate_register());
+    }
+    size_t i = 0;
     for (auto& element : m_elements) {
     for (auto& element : m_elements) {
         if (element) {
         if (element) {
             TRY(element->generate_bytecode(generator));
             TRY(element->generate_bytecode(generator));
 
 
-            if (is<SpreadExpression>(*element)) {
-                return Bytecode::CodeGenerationError {
-                    this,
-                    "Unimplemented element kind: SpreadExpression"sv,
-                };
-            }
+            if (is<SpreadExpression>(*element))
+                VERIFY_NOT_REACHED();
         } else {
         } else {
             generator.emit<Bytecode::Op::LoadImmediate>(Value {});
             generator.emit<Bytecode::Op::LoadImmediate>(Value {});
         }
         }
-        auto element_reg = generator.allocate_register();
+        auto& element_reg = element_regs[i++];
         generator.emit<Bytecode::Op::Store>(element_reg);
         generator.emit<Bytecode::Op::Store>(element_reg);
-        element_regs.append(element_reg);
     }
     }
-    generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(element_regs.size(), element_regs);
+    if (element_regs.is_empty()) {
+        generator.emit<Bytecode::Op::NewArray>();
+    } else {
+        generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(2u, AK::Array { element_regs.first(), element_regs.last() });
+    }
     return {};
     return {};
 }
 }
 
 
@@ -1391,17 +1400,27 @@ Bytecode::CodeGenerationErrorOr<void> TaggedTemplateLiteral::generate_bytecode(B
 
 
     Vector<Bytecode::Register> string_regs;
     Vector<Bytecode::Register> string_regs;
     auto& expressions = m_template_literal->expressions();
     auto& expressions = m_template_literal->expressions();
+    for (size_t i = 0; i < expressions.size(); ++i) {
+        if (i % 2 != 0)
+            continue;
+        string_regs.append(generator.allocate_register());
+    }
+
+    size_t reg_index = 0;
     for (size_t i = 0; i < expressions.size(); ++i) {
     for (size_t i = 0; i < expressions.size(); ++i) {
         if (i % 2 != 0)
         if (i % 2 != 0)
             continue;
             continue;
 
 
         TRY(expressions[i].generate_bytecode(generator));
         TRY(expressions[i].generate_bytecode(generator));
-        auto string_reg = generator.allocate_register();
+        auto string_reg = string_regs[reg_index++];
         generator.emit<Bytecode::Op::Store>(string_reg);
         generator.emit<Bytecode::Op::Store>(string_reg);
-        string_regs.append(string_reg);
     }
     }
 
 
-    generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(string_regs.size(), string_regs);
+    if (string_regs.is_empty()) {
+        generator.emit<Bytecode::Op::NewArray>();
+    } else {
+        generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(2u, AK::Array { string_regs.first(), string_regs.last() });
+    }
     auto strings_reg = generator.allocate_register();
     auto strings_reg = generator.allocate_register();
     generator.emit<Bytecode::Op::Store>(strings_reg);
     generator.emit<Bytecode::Op::Store>(strings_reg);
 
 
@@ -1418,14 +1437,22 @@ Bytecode::CodeGenerationErrorOr<void> TaggedTemplateLiteral::generate_bytecode(B
     }
     }
 
 
     Vector<Bytecode::Register> raw_string_regs;
     Vector<Bytecode::Register> raw_string_regs;
+    for ([[maybe_unused]] auto& raw_string : m_template_literal->raw_strings())
+        string_regs.append(generator.allocate_register());
+
+    reg_index = 0;
     for (auto& raw_string : m_template_literal->raw_strings()) {
     for (auto& raw_string : m_template_literal->raw_strings()) {
         TRY(raw_string.generate_bytecode(generator));
         TRY(raw_string.generate_bytecode(generator));
-        auto raw_string_reg = generator.allocate_register();
+        auto raw_string_reg = string_regs[reg_index++];
         generator.emit<Bytecode::Op::Store>(raw_string_reg);
         generator.emit<Bytecode::Op::Store>(raw_string_reg);
         raw_string_regs.append(raw_string_reg);
         raw_string_regs.append(raw_string_reg);
     }
     }
 
 
-    generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(raw_string_regs.size(), raw_string_regs);
+    if (raw_string_regs.is_empty()) {
+        generator.emit<Bytecode::Op::NewArray>();
+    } else {
+        generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(2u, AK::Array { raw_string_regs.first(), raw_string_regs.last() });
+    }
     auto raw_strings_reg = generator.allocate_register();
     auto raw_strings_reg = generator.allocate_register();
     generator.emit<Bytecode::Op::Store>(raw_strings_reg);
     generator.emit<Bytecode::Op::Store>(raw_strings_reg);
 
 

+ 1 - 1
Userland/Libraries/LibJS/Bytecode/Op.cpp

@@ -129,7 +129,7 @@ ThrowCompletionOr<void> NewArray::execute_impl(Bytecode::Interpreter& interprete
 {
 {
     auto* array = MUST(Array::create(interpreter.global_object(), 0));
     auto* array = MUST(Array::create(interpreter.global_object(), 0));
     for (size_t i = 0; i < m_element_count; i++) {
     for (size_t i = 0; i < m_element_count; i++) {
-        auto& value = interpreter.reg(m_elements[i]);
+        auto& value = interpreter.reg(Register(m_elements[0].index() + i));
         array->indexed_properties().put(i, value, default_attributes);
         array->indexed_properties().put(i, value, default_attributes);
     }
     }
     interpreter.accumulator() = array;
     interpreter.accumulator() = array;

+ 5 - 5
Userland/Libraries/LibJS/Bytecode/Op.h

@@ -232,12 +232,12 @@ public:
     {
     {
     }
     }
 
 
-    explicit NewArray(Vector<Register> const& elements)
+    explicit NewArray(AK::Array<Register, 2> const& elements_range)
         : Instruction(Type::NewArray)
         : Instruction(Type::NewArray)
-        , m_element_count(elements.size())
+        , m_element_count(elements_range[1].index() - elements_range[0].index() + 1)
     {
     {
-        for (size_t i = 0; i < m_element_count; ++i)
-            m_elements[i] = elements[i];
+        m_elements[0] = elements_range[0];
+        m_elements[1] = elements_range[1];
     }
     }
 
 
     ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
     ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
@@ -246,7 +246,7 @@ public:
 
 
     size_t length_impl() const
     size_t length_impl() const
     {
     {
-        return sizeof(*this) + sizeof(Register) * m_element_count;
+        return sizeof(*this) + sizeof(Register) * (m_element_count == 0 ? 0 : 2);
     }
     }
 
 
 private:
 private: