Explorar o código

LibJS/Bytecode: Rename Call and SuperCall to &WithArgumentArray

Forcing every function call to allocate a new Array just to accommodate
spread parameters is not very nice, so let's start moving towards making
this a special case rather than the general (and only) case.
Andreas Kling %!s(int64=2) %!d(string=hai) anos
pai
achega
7eb87dec9f

+ 11 - 11
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -344,7 +344,7 @@ Bytecode::CodeGenerationErrorOr<void> SuperCall::generate_bytecode(Bytecode::Gen
         TRY(arguments_to_array_for_call(generator, m_arguments));
         TRY(arguments_to_array_for_call(generator, m_arguments));
     }
     }
 
 
-    generator.emit<Bytecode::Op::SuperCall>(m_is_synthetic == IsPartOfSyntheticConstructor::Yes);
+    generator.emit<Bytecode::Op::SuperCallWithArgumentArray>(m_is_synthetic == IsPartOfSyntheticConstructor::Yes);
 
 
     return {};
     return {};
 }
 }
@@ -1465,20 +1465,20 @@ Bytecode::CodeGenerationErrorOr<void> CallExpression::generate_bytecode(Bytecode
 
 
     TRY(arguments_to_array_for_call(generator, arguments()));
     TRY(arguments_to_array_for_call(generator, arguments()));
 
 
-    Bytecode::Op::Call::CallType call_type;
+    Bytecode::Op::CallType call_type;
     if (is<NewExpression>(*this)) {
     if (is<NewExpression>(*this)) {
-        call_type = Bytecode::Op::Call::CallType::Construct;
+        call_type = Bytecode::Op::CallType::Construct;
     } else if (m_callee->is_identifier() && static_cast<Identifier const&>(*m_callee).string() == "eval"sv) {
     } else if (m_callee->is_identifier() && static_cast<Identifier const&>(*m_callee).string() == "eval"sv) {
-        call_type = Bytecode::Op::Call::CallType::DirectEval;
+        call_type = Bytecode::Op::CallType::DirectEval;
     } else {
     } else {
-        call_type = Bytecode::Op::Call::CallType::Call;
+        call_type = Bytecode::Op::CallType::Call;
     }
     }
 
 
     Optional<Bytecode::StringTableIndex> expression_string_index;
     Optional<Bytecode::StringTableIndex> expression_string_index;
     if (auto expression_string = this->expression_string(); expression_string.has_value())
     if (auto expression_string = this->expression_string(); expression_string.has_value())
         expression_string_index = generator.intern_string(expression_string.release_value());
         expression_string_index = generator.intern_string(expression_string.release_value());
 
 
-    generator.emit<Bytecode::Op::Call>(call_type, callee_reg, this_reg, expression_string_index);
+    generator.emit<Bytecode::Op::CallWithArgumentArray>(call_type, callee_reg, this_reg, expression_string_index);
 
 
     return {};
     return {};
 }
 }
@@ -1582,7 +1582,7 @@ Bytecode::CodeGenerationErrorOr<void> YieldExpression::generate_bytecode(Bytecod
 
 
         // i. Let innerResult be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « received.[[Value]] »).
         // i. Let innerResult be ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « received.[[Value]] »).
         generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(2, AK::Array { received_completion_value_register, received_completion_value_register });
         generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(2, AK::Array { received_completion_value_register, received_completion_value_register });
-        generator.emit<Bytecode::Op::Call>(Bytecode::Op::Call::CallType::Call, next_method_register, iterator_register);
+        generator.emit<Bytecode::Op::CallWithArgumentArray>(Bytecode::Op::CallType::Call, next_method_register, iterator_register);
 
 
         // FIXME: ii. If generatorKind is async, set innerResult to ? Await(innerResult).
         // FIXME: ii. If generatorKind is async, set innerResult to ? Await(innerResult).
 
 
@@ -1654,7 +1654,7 @@ Bytecode::CodeGenerationErrorOr<void> YieldExpression::generate_bytecode(Bytecod
 
 
         // 1. Let innerResult be ? Call(throw, iterator, « received.[[Value]] »).
         // 1. Let innerResult be ? Call(throw, iterator, « received.[[Value]] »).
         generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(2, AK::Array { received_completion_value_register, received_completion_value_register });
         generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(2, AK::Array { received_completion_value_register, received_completion_value_register });
-        generator.emit<Bytecode::Op::Call>(Bytecode::Op::Call::CallType::Call, throw_method_register, iterator_register);
+        generator.emit<Bytecode::Op::CallWithArgumentArray>(Bytecode::Op::CallType::Call, throw_method_register, iterator_register);
 
 
         // FIXME: 2. If generatorKind is async, set innerResult to ? Await(innerResult).
         // FIXME: 2. If generatorKind is async, set innerResult to ? Await(innerResult).
 
 
@@ -1742,7 +1742,7 @@ Bytecode::CodeGenerationErrorOr<void> YieldExpression::generate_bytecode(Bytecod
 
 
         // iv. Let innerReturnResult be ? Call(return, iterator, « received.[[Value]] »).
         // iv. Let innerReturnResult be ? Call(return, iterator, « received.[[Value]] »).
         generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(2, AK::Array { received_completion_value_register, received_completion_value_register });
         generator.emit_with_extra_register_slots<Bytecode::Op::NewArray>(2, AK::Array { received_completion_value_register, received_completion_value_register });
-        generator.emit<Bytecode::Op::Call>(Bytecode::Op::Call::CallType::Call, return_method_register, iterator_register);
+        generator.emit<Bytecode::Op::CallWithArgumentArray>(Bytecode::Op::CallType::Call, return_method_register, iterator_register);
 
 
         // FIXME: v. If generatorKind is async, set innerReturnResult to ? Await(innerReturnResult).
         // FIXME: v. If generatorKind is async, set innerReturnResult to ? Await(innerReturnResult).
 
 
@@ -2047,7 +2047,7 @@ Bytecode::CodeGenerationErrorOr<void> TaggedTemplateLiteral::generate_bytecode(B
     else
     else
         generator.emit<Bytecode::Op::NewArray>();
         generator.emit<Bytecode::Op::NewArray>();
 
 
-    generator.emit<Bytecode::Op::Call>(Bytecode::Op::Call::CallType::Call, tag_reg, this_reg);
+    generator.emit<Bytecode::Op::CallWithArgumentArray>(Bytecode::Op::CallType::Call, tag_reg, this_reg);
     return {};
     return {};
 }
 }
 
 
@@ -2815,7 +2815,7 @@ static Bytecode::CodeGenerationErrorOr<void> generate_optional_chain(Bytecode::G
         TRY(reference.visit(
         TRY(reference.visit(
             [&](OptionalChain::Call const& call) -> Bytecode::CodeGenerationErrorOr<void> {
             [&](OptionalChain::Call const& call) -> Bytecode::CodeGenerationErrorOr<void> {
                 TRY(arguments_to_array_for_call(generator, call.arguments));
                 TRY(arguments_to_array_for_call(generator, call.arguments));
-                generator.emit<Bytecode::Op::Call>(Bytecode::Op::Call::CallType::Call, current_value_register, current_base_register);
+                generator.emit<Bytecode::Op::CallWithArgumentArray>(Bytecode::Op::CallType::Call, current_value_register, current_base_register);
 
 
                 generator.emit<Bytecode::Op::Store>(current_value_register);
                 generator.emit<Bytecode::Op::Store>(current_value_register);
 
 

+ 2 - 2
Userland/Libraries/LibJS/Bytecode/Instruction.h

@@ -18,7 +18,7 @@
     O(BitwiseOr)                     \
     O(BitwiseOr)                     \
     O(BitwiseXor)                    \
     O(BitwiseXor)                    \
     O(BlockDeclarationInstantiation) \
     O(BlockDeclarationInstantiation) \
-    O(Call)                          \
+    O(CallWithArgumentArray)         \
     O(ConcatString)                  \
     O(ConcatString)                  \
     O(ContinuePendingUnwind)         \
     O(ContinuePendingUnwind)         \
     O(CopyObjectExcludingProperties) \
     O(CopyObjectExcludingProperties) \
@@ -89,7 +89,7 @@
     O(StrictlyEquals)                \
     O(StrictlyEquals)                \
     O(StrictlyInequals)              \
     O(StrictlyInequals)              \
     O(Sub)                           \
     O(Sub)                           \
-    O(SuperCall)                     \
+    O(SuperCallWithArgumentArray)    \
     O(Throw)                         \
     O(Throw)                         \
     O(ThrowIfNotObject)              \
     O(ThrowIfNotObject)              \
     O(ThrowIfNullish)                \
     O(ThrowIfNullish)                \

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

@@ -694,7 +694,7 @@ static MarkedVector<Value> argument_list_evaluation(Bytecode::Interpreter& inter
     return argument_values;
     return argument_values;
 }
 }
 
 
-Completion Call::throw_type_error_for_callee(Bytecode::Interpreter& interpreter, StringView callee_type) const
+Completion CallWithArgumentArray::throw_type_error_for_callee(Bytecode::Interpreter& interpreter, StringView callee_type) const
 {
 {
     auto& vm = interpreter.vm();
     auto& vm = interpreter.vm();
     auto callee = interpreter.reg(m_callee);
     auto callee = interpreter.reg(m_callee);
@@ -705,7 +705,7 @@ Completion Call::throw_type_error_for_callee(Bytecode::Interpreter& interpreter,
     return vm.throw_completion<TypeError>(ErrorType::IsNotA, TRY_OR_THROW_OOM(vm, callee.to_string_without_side_effects()), callee_type);
     return vm.throw_completion<TypeError>(ErrorType::IsNotA, TRY_OR_THROW_OOM(vm, callee.to_string_without_side_effects()), callee_type);
 }
 }
 
 
-ThrowCompletionOr<void> Call::execute_impl(Bytecode::Interpreter& interpreter) const
+ThrowCompletionOr<void> CallWithArgumentArray::execute_impl(Bytecode::Interpreter& interpreter) const
 {
 {
     auto& vm = interpreter.vm();
     auto& vm = interpreter.vm();
 
 
@@ -738,7 +738,7 @@ ThrowCompletionOr<void> Call::execute_impl(Bytecode::Interpreter& interpreter) c
 }
 }
 
 
 // 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
 // 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation
-ThrowCompletionOr<void> SuperCall::execute_impl(Bytecode::Interpreter& interpreter) const
+ThrowCompletionOr<void> SuperCallWithArgumentArray::execute_impl(Bytecode::Interpreter& interpreter) const
 {
 {
     auto& vm = interpreter.vm();
     auto& vm = interpreter.vm();
     // 1. Let newTarget be GetNewTarget().
     // 1. Let newTarget be GetNewTarget().
@@ -896,7 +896,7 @@ void CopyObjectExcludingProperties::replace_references_impl(Register from, Regis
     }
     }
 }
 }
 
 
-void Call::replace_references_impl(Register from, Register to)
+void CallWithArgumentArray::replace_references_impl(Register from, Register to)
 {
 {
     if (m_callee == from)
     if (m_callee == from)
         m_callee = to;
         m_callee = to;
@@ -1383,30 +1383,30 @@ DeprecatedString JumpUndefined::to_deprecated_string_impl(Bytecode::Executable c
     return DeprecatedString::formatted("JumpUndefined undefined:{} not undefined:{}", true_string, false_string);
     return DeprecatedString::formatted("JumpUndefined undefined:{} not undefined:{}", true_string, false_string);
 }
 }
 
 
-DeprecatedString Call::to_deprecated_string_impl(Bytecode::Executable const& executable) const
+DeprecatedString CallWithArgumentArray::to_deprecated_string_impl(Bytecode::Executable const& executable) const
 {
 {
     StringView type;
     StringView type;
     switch (m_type) {
     switch (m_type) {
-    case Call::CallType::Call:
+    case CallType::Call:
         type = ""sv;
         type = ""sv;
         break;
         break;
-    case Call::CallType::Construct:
+    case CallType::Construct:
         type = " (Construct)"sv;
         type = " (Construct)"sv;
         break;
         break;
-    case Call::CallType::DirectEval:
+    case CallType::DirectEval:
         type = " (DirectEval)"sv;
         type = " (DirectEval)"sv;
         break;
         break;
     }
     }
 
 
     if (m_expression_string.has_value())
     if (m_expression_string.has_value())
-        return DeprecatedString::formatted("Call{} callee:{}, this:{}, arguments:[...acc] ({})", type, m_callee, m_this_value, executable.get_string(m_expression_string.value()));
+        return DeprecatedString::formatted("CallWithArgumentArray{} callee:{}, this:{}, arguments:[...acc] ({})", type, m_callee, m_this_value, executable.get_string(m_expression_string.value()));
 
 
-    return DeprecatedString::formatted("Call{} callee:{}, this:{}, arguments:[...acc]", type, m_callee, m_this_value);
+    return DeprecatedString::formatted("CallWithArgumentArray{} callee:{}, this:{}, arguments:[...acc]", type, m_callee, m_this_value);
 }
 }
 
 
-DeprecatedString SuperCall::to_deprecated_string_impl(Bytecode::Executable const&) const
+DeprecatedString SuperCallWithArgumentArray::to_deprecated_string_impl(Bytecode::Executable const&) const
 {
 {
-    return "SuperCall arguments:[...acc]"sv;
+    return "SuperCallWithArgumentArray arguments:[...acc]"sv;
 }
 }
 
 
 DeprecatedString NewFunction::to_deprecated_string_impl(Bytecode::Executable const&) const
 DeprecatedString NewFunction::to_deprecated_string_impl(Bytecode::Executable const&) const

+ 12 - 14
Userland/Libraries/LibJS/Bytecode/Op.h

@@ -770,17 +770,16 @@ public:
     DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
     DeprecatedString to_deprecated_string_impl(Bytecode::Executable const&) const;
 };
 };
 
 
-// NOTE: This instruction is variable-width depending on the number of arguments!
-class Call final : public Instruction {
-public:
-    enum class CallType {
-        Call,
-        Construct,
-        DirectEval,
-    };
+enum class CallType {
+    Call,
+    Construct,
+    DirectEval,
+};
 
 
-    Call(CallType type, Register callee, Register this_value, Optional<StringTableIndex> expression_string = {})
-        : Instruction(Type::Call)
+class CallWithArgumentArray final : public Instruction {
+public:
+    CallWithArgumentArray(CallType type, Register callee, Register this_value, Optional<StringTableIndex> expression_string = {})
+        : Instruction(Type::CallWithArgumentArray)
         , m_callee(callee)
         , m_callee(callee)
         , m_this_value(this_value)
         , m_this_value(this_value)
         , m_type(type)
         , m_type(type)
@@ -802,11 +801,10 @@ private:
     Optional<StringTableIndex> m_expression_string;
     Optional<StringTableIndex> m_expression_string;
 };
 };
 
 
-// NOTE: This instruction is variable-width depending on the number of arguments!
-class SuperCall : public Instruction {
+class SuperCallWithArgumentArray : public Instruction {
 public:
 public:
-    explicit SuperCall(bool is_synthetic)
-        : Instruction(Type::SuperCall)
+    explicit SuperCallWithArgumentArray(bool is_synthetic)
+        : Instruction(Type::SuperCallWithArgumentArray)
         , m_is_synthetic(is_synthetic)
         , m_is_synthetic(is_synthetic)
     {
     {
     }
     }

+ 1 - 1
Userland/Libraries/LibJS/Bytecode/Pass/LoadElimination.cpp

@@ -124,7 +124,7 @@ static NonnullOwnPtr<BasicBlock> eliminate_loads(BasicBlock const& block, size_t
             // Attribute accesses (`a.o` or `a[o]`) may result in calls to getters or setters
             // Attribute accesses (`a.o` or `a[o]`) may result in calls to getters or setters
             // or may trigger proxies
             // or may trigger proxies
             // So these are treated like calls
             // So these are treated like calls
-        case Call:
+        case CallWithArgumentArray:
             // Calls, especially to local functions and eval, may poison visible and
             // Calls, especially to local functions and eval, may poison visible and
             // cached variables, hence we need to clear the lookup cache after emitting them
             // cached variables, hence we need to clear the lookup cache after emitting them
             // FIXME: In strict mode and with better identifier metrics, we might be able
             // FIXME: In strict mode and with better identifier metrics, we might be able