Browse Source

LibJS: Pass call/construct argument lists as ReadonlySpan<Value>

(Instead of MarkedVector<Value>.) This is a step towards not storing
argument lists in MarkedVector<Value> at all. Note that they still end
up in MarkedVectors since that's what ExecutionContext has.
Andreas Kling 1 year ago
parent
commit
ece961f882
29 changed files with 119 additions and 112 deletions
  1. 5 5
      Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp
  2. 1 1
      Userland/Libraries/LibJS/Bytecode/CommonImplementations.h
  3. 2 6
      Userland/Libraries/LibJS/JIT/Compiler.cpp
  4. 6 12
      Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp
  5. 27 27
      Userland/Libraries/LibJS/Runtime/AbstractOperations.h
  6. 18 0
      Userland/Libraries/LibJS/Runtime/Array.cpp
  7. 1 0
      Userland/Libraries/LibJS/Runtime/Array.h
  8. 8 7
      Userland/Libraries/LibJS/Runtime/BoundFunction.cpp
  9. 2 2
      Userland/Libraries/LibJS/Runtime/BoundFunction.h
  10. 4 4
      Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp
  11. 2 2
      Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h
  12. 2 2
      Userland/Libraries/LibJS/Runtime/FunctionObject.h
  13. 4 8
      Userland/Libraries/LibJS/Runtime/FunctionPrototype.cpp
  14. 1 1
      Userland/Libraries/LibJS/Runtime/FunctionPrototype.h
  15. 2 2
      Userland/Libraries/LibJS/Runtime/JobCallback.cpp
  16. 1 1
      Userland/Libraries/LibJS/Runtime/JobCallback.h
  17. 4 4
      Userland/Libraries/LibJS/Runtime/NativeFunction.cpp
  18. 2 2
      Userland/Libraries/LibJS/Runtime/NativeFunction.h
  19. 5 7
      Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp
  20. 4 4
      Userland/Libraries/LibJS/Runtime/ProxyObject.cpp
  21. 2 2
      Userland/Libraries/LibJS/Runtime/ProxyObject.h
  22. 2 2
      Userland/Libraries/LibJS/Runtime/ReflectObject.cpp
  23. 1 1
      Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp
  24. 1 1
      Userland/Libraries/LibJS/Runtime/TypedArray.cpp
  25. 2 2
      Userland/Libraries/LibJS/Runtime/VM.cpp
  26. 1 1
      Userland/Libraries/LibJS/Runtime/VM.h
  27. 4 1
      Userland/Libraries/LibJS/Runtime/Value.cpp
  28. 3 3
      Userland/Libraries/LibJS/Runtime/WrappedFunction.cpp
  29. 2 2
      Userland/Libraries/LibJS/Runtime/WrappedFunction.h

+ 5 - 5
Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp

@@ -279,7 +279,7 @@ ThrowCompletionOr<void> put_by_property_key(VM& vm, Value base, Value this_value
     return {};
     return {};
 }
 }
 
 
-ThrowCompletionOr<Value> perform_call(Interpreter& interpreter, Value this_value, Op::CallType call_type, Value callee, MarkedVector<Value> argument_values)
+ThrowCompletionOr<Value> perform_call(Interpreter& interpreter, Value this_value, Op::CallType call_type, Value callee, ReadonlySpan<Value> argument_values)
 {
 {
     auto& vm = interpreter.vm();
     auto& vm = interpreter.vm();
     auto& function = callee.as_function();
     auto& function = callee.as_function();
@@ -288,11 +288,11 @@ ThrowCompletionOr<Value> perform_call(Interpreter& interpreter, Value this_value
         if (callee == interpreter.realm().intrinsics().eval_function())
         if (callee == interpreter.realm().intrinsics().eval_function())
             return_value = TRY(perform_eval(vm, !argument_values.is_empty() ? argument_values[0].value_or(JS::js_undefined()) : js_undefined(), vm.in_strict_mode() ? CallerMode::Strict : CallerMode::NonStrict, EvalMode::Direct));
             return_value = TRY(perform_eval(vm, !argument_values.is_empty() ? argument_values[0].value_or(JS::js_undefined()) : js_undefined(), vm.in_strict_mode() ? CallerMode::Strict : CallerMode::NonStrict, EvalMode::Direct));
         else
         else
-            return_value = TRY(JS::call(vm, function, this_value, move(argument_values)));
+            return_value = TRY(JS::call(vm, function, this_value, argument_values));
     } else if (call_type == Op::CallType::Call)
     } else if (call_type == Op::CallType::Call)
-        return_value = TRY(JS::call(vm, function, this_value, move(argument_values)));
+        return_value = TRY(JS::call(vm, function, this_value, argument_values));
     else
     else
-        return_value = TRY(construct(vm, function, move(argument_values)));
+        return_value = TRY(construct(vm, function, argument_values));
 
 
     return return_value;
     return return_value;
 }
 }
@@ -633,7 +633,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> super_call_with_argument_array(VM& vm, V
         return vm.throw_completion<TypeError>(ErrorType::NotAConstructor, "Super constructor");
         return vm.throw_completion<TypeError>(ErrorType::NotAConstructor, "Super constructor");
 
 
     // 6. Let result be ? Construct(func, argList, newTarget).
     // 6. Let result be ? Construct(func, argList, newTarget).
-    auto result = TRY(construct(vm, static_cast<FunctionObject&>(*func), move(arg_list), &new_target.as_function()));
+    auto result = TRY(construct(vm, static_cast<FunctionObject&>(*func), arg_list.span(), &new_target.as_function()));
 
 
     // 7. Let thisER be GetThisEnvironment().
     // 7. Let thisER be GetThisEnvironment().
     auto& this_environment = verify_cast<FunctionEnvironment>(*get_this_environment(vm));
     auto& this_environment = verify_cast<FunctionEnvironment>(*get_this_environment(vm));

+ 1 - 1
Userland/Libraries/LibJS/Bytecode/CommonImplementations.h

@@ -17,7 +17,7 @@ ThrowCompletionOr<Value> get_by_id(VM&, DeprecatedFlyString const& property, Val
 ThrowCompletionOr<Value> get_by_value(VM&, Value base_value, Value property_key_value);
 ThrowCompletionOr<Value> get_by_value(VM&, Value base_value, Value property_key_value);
 ThrowCompletionOr<Value> get_global(Bytecode::Interpreter&, DeprecatedFlyString const& identifier, GlobalVariableCache&);
 ThrowCompletionOr<Value> get_global(Bytecode::Interpreter&, DeprecatedFlyString const& identifier, GlobalVariableCache&);
 ThrowCompletionOr<void> put_by_property_key(VM&, Value base, Value this_value, Value value, PropertyKey name, Op::PropertyKind kind, PropertyLookupCache* = nullptr);
 ThrowCompletionOr<void> put_by_property_key(VM&, Value base, Value this_value, Value value, PropertyKey name, Op::PropertyKind kind, PropertyLookupCache* = nullptr);
-ThrowCompletionOr<Value> perform_call(Interpreter&, Value this_value, Op::CallType, Value callee, MarkedVector<Value> argument_values);
+ThrowCompletionOr<Value> perform_call(Interpreter&, Value this_value, Op::CallType, Value callee, ReadonlySpan<Value> argument_values);
 ThrowCompletionOr<void> throw_if_needed_for_call(Interpreter&, Value callee, Op::CallType, Optional<StringTableIndex> const& expression_string);
 ThrowCompletionOr<void> throw_if_needed_for_call(Interpreter&, Value callee, Op::CallType, Optional<StringTableIndex> const& expression_string);
 ThrowCompletionOr<Value> typeof_variable(VM&, DeprecatedFlyString const&);
 ThrowCompletionOr<Value> typeof_variable(VM&, DeprecatedFlyString const&);
 ThrowCompletionOr<void> set_variable(VM&, DeprecatedFlyString const&, Value, Op::EnvironmentMode, Op::SetVariable::InitializationMode, EnvironmentVariableCache&);
 ThrowCompletionOr<void> set_variable(VM&, DeprecatedFlyString const&, Value, Op::EnvironmentMode, Op::SetVariable::InitializationMode, EnvironmentVariableCache&);

+ 2 - 6
Userland/Libraries/LibJS/JIT/Compiler.cpp

@@ -2507,12 +2507,8 @@ static Value cxx_call(VM& vm, Value callee, u32 first_argument_index, u32 argume
 {
 {
     TRY_OR_SET_EXCEPTION(throw_if_needed_for_call(vm.bytecode_interpreter(), callee, call_type, expression_string));
     TRY_OR_SET_EXCEPTION(throw_if_needed_for_call(vm.bytecode_interpreter(), callee, call_type, expression_string));
 
 
-    MarkedVector<Value> argument_values(vm.heap());
-    argument_values.ensure_capacity(argument_count);
-    for (u32 i = 0; i < argument_count; ++i) {
-        argument_values.unchecked_append(vm.bytecode_interpreter().reg(Bytecode::Register { first_argument_index + i }));
-    }
-    return TRY_OR_SET_EXCEPTION(perform_call(vm.bytecode_interpreter(), this_value, call_type, callee, move(argument_values)));
+    auto argument_values = vm.bytecode_interpreter().registers().slice(first_argument_index, argument_count);
+    return TRY_OR_SET_EXCEPTION(perform_call(vm.bytecode_interpreter(), this_value, call_type, callee, argument_values));
 }
 }
 
 
 Assembler::Reg Compiler::argument_register(u32 index)
 Assembler::Reg Compiler::argument_register(u32 index)

+ 6 - 12
Userland/Libraries/LibJS/Runtime/AbstractOperations.cpp

@@ -47,46 +47,40 @@ ThrowCompletionOr<Value> require_object_coercible(VM& vm, Value value)
 }
 }
 
 
 // 7.3.14 Call ( F, V [ , argumentsList ] ), https://tc39.es/ecma262/#sec-call
 // 7.3.14 Call ( F, V [ , argumentsList ] ), https://tc39.es/ecma262/#sec-call
-ThrowCompletionOr<Value> call_impl(VM& vm, Value function, Value this_value, Optional<MarkedVector<Value>> arguments_list)
+ThrowCompletionOr<Value> call_impl(VM& vm, Value function, Value this_value, ReadonlySpan<Value> arguments_list)
 {
 {
     // 1. If argumentsList is not present, set argumentsList to a new empty List.
     // 1. If argumentsList is not present, set argumentsList to a new empty List.
-    if (!arguments_list.has_value())
-        arguments_list = MarkedVector<Value> { vm.heap() };
 
 
     // 2. If IsCallable(F) is false, throw a TypeError exception.
     // 2. If IsCallable(F) is false, throw a TypeError exception.
     if (!function.is_function())
     if (!function.is_function())
         return vm.throw_completion<TypeError>(ErrorType::NotAFunction, function.to_string_without_side_effects());
         return vm.throw_completion<TypeError>(ErrorType::NotAFunction, function.to_string_without_side_effects());
 
 
     // 3. Return ? F.[[Call]](V, argumentsList).
     // 3. Return ? F.[[Call]](V, argumentsList).
-    return function.as_function().internal_call(this_value, move(*arguments_list));
+    return function.as_function().internal_call(this_value, arguments_list);
 }
 }
 
 
-ThrowCompletionOr<Value> call_impl(VM& vm, FunctionObject& function, Value this_value, Optional<MarkedVector<Value>> arguments_list)
+ThrowCompletionOr<Value> call_impl(VM&, FunctionObject& function, Value this_value, ReadonlySpan<Value> arguments_list)
 {
 {
     // 1. If argumentsList is not present, set argumentsList to a new empty List.
     // 1. If argumentsList is not present, set argumentsList to a new empty List.
-    if (!arguments_list.has_value())
-        arguments_list = MarkedVector<Value> { vm.heap() };
 
 
     // 2. If IsCallable(F) is false, throw a TypeError exception.
     // 2. If IsCallable(F) is false, throw a TypeError exception.
     // Note: Called with a FunctionObject ref
     // Note: Called with a FunctionObject ref
 
 
     // 3. Return ? F.[[Call]](V, argumentsList).
     // 3. Return ? F.[[Call]](V, argumentsList).
-    return function.internal_call(this_value, move(*arguments_list));
+    return function.internal_call(this_value, arguments_list);
 }
 }
 
 
 // 7.3.15 Construct ( F [ , argumentsList [ , newTarget ] ] ), https://tc39.es/ecma262/#sec-construct
 // 7.3.15 Construct ( F [ , argumentsList [ , newTarget ] ] ), https://tc39.es/ecma262/#sec-construct
-ThrowCompletionOr<NonnullGCPtr<Object>> construct_impl(VM& vm, FunctionObject& function, Optional<MarkedVector<Value>> arguments_list, FunctionObject* new_target)
+ThrowCompletionOr<NonnullGCPtr<Object>> construct_impl(VM&, FunctionObject& function, ReadonlySpan<Value> arguments_list, FunctionObject* new_target)
 {
 {
     // 1. If newTarget is not present, set newTarget to F.
     // 1. If newTarget is not present, set newTarget to F.
     if (!new_target)
     if (!new_target)
         new_target = &function;
         new_target = &function;
 
 
     // 2. If argumentsList is not present, set argumentsList to a new empty List.
     // 2. If argumentsList is not present, set argumentsList to a new empty List.
-    if (!arguments_list.has_value())
-        arguments_list = MarkedVector<Value> { vm.heap() };
 
 
     // 3. Return ? F.[[Construct]](argumentsList, newTarget).
     // 3. Return ? F.[[Construct]](argumentsList, newTarget).
-    return function.internal_construct(move(*arguments_list), *new_target);
+    return function.internal_construct(arguments_list, *new_target);
 }
 }
 
 
 // 7.3.19 LengthOfArrayLike ( obj ), https://tc39.es/ecma262/#sec-lengthofarraylike
 // 7.3.19 LengthOfArrayLike ( obj ), https://tc39.es/ecma262/#sec-lengthofarraylike

+ 27 - 27
Userland/Libraries/LibJS/Runtime/AbstractOperations.h

@@ -28,9 +28,9 @@ NonnullGCPtr<Environment> get_this_environment(VM&);
 bool can_be_held_weakly(Value);
 bool can_be_held_weakly(Value);
 Object* get_super_constructor(VM&);
 Object* get_super_constructor(VM&);
 ThrowCompletionOr<Value> require_object_coercible(VM&, Value);
 ThrowCompletionOr<Value> require_object_coercible(VM&, Value);
-ThrowCompletionOr<Value> call_impl(VM&, Value function, Value this_value, Optional<MarkedVector<Value>> = {});
-ThrowCompletionOr<Value> call_impl(VM&, FunctionObject& function, Value this_value, Optional<MarkedVector<Value>> = {});
-ThrowCompletionOr<NonnullGCPtr<Object>> construct_impl(VM&, FunctionObject&, Optional<MarkedVector<Value>> = {}, FunctionObject* new_target = nullptr);
+ThrowCompletionOr<Value> call_impl(VM&, Value function, Value this_value, ReadonlySpan<Value> arguments = {});
+ThrowCompletionOr<Value> call_impl(VM&, FunctionObject& function, Value this_value, ReadonlySpan<Value> arguments = {});
+ThrowCompletionOr<NonnullGCPtr<Object>> construct_impl(VM&, FunctionObject&, ReadonlySpan<Value> arguments = {}, FunctionObject* new_target = nullptr);
 ThrowCompletionOr<size_t> length_of_array_like(VM&, Object const&);
 ThrowCompletionOr<size_t> length_of_array_like(VM&, Object const&);
 ThrowCompletionOr<MarkedVector<Value>> create_list_from_array_like(VM&, Value, Function<ThrowCompletionOr<void>(Value)> = {});
 ThrowCompletionOr<MarkedVector<Value>> create_list_from_array_like(VM&, Value, Function<ThrowCompletionOr<void>(Value)> = {});
 ThrowCompletionOr<FunctionObject*> species_constructor(VM&, Object const&, FunctionObject& default_constructor);
 ThrowCompletionOr<FunctionObject*> species_constructor(VM&, Object const&, FunctionObject& default_constructor);
@@ -75,45 +75,45 @@ ThrowCompletionOr<Value> perform_eval(VM&, Value, CallerMode, EvalMode);
 ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& program, Environment* variable_environment, Environment* lexical_environment, PrivateEnvironment* private_environment, bool strict);
 ThrowCompletionOr<void> eval_declaration_instantiation(VM& vm, Program const& program, Environment* variable_environment, Environment* lexical_environment, PrivateEnvironment* private_environment, bool strict);
 
 
 // 7.3.14 Call ( F, V [ , argumentsList ] ), https://tc39.es/ecma262/#sec-call
 // 7.3.14 Call ( F, V [ , argumentsList ] ), https://tc39.es/ecma262/#sec-call
-ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, Value function, Value this_value, MarkedVector<Value> arguments_list)
+ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, Value function, Value this_value, ReadonlySpan<Value> arguments_list)
 {
 {
-    return call_impl(vm, function, this_value, move(arguments_list));
+    return call_impl(vm, function, this_value, arguments_list);
 }
 }
 
 
-ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, Value function, Value this_value, Optional<MarkedVector<Value>> arguments_list)
+ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, Value function, Value this_value, Span<Value> arguments_list)
 {
 {
-    return call_impl(vm, function, this_value, move(arguments_list));
+    return call_impl(vm, function, this_value, static_cast<ReadonlySpan<Value>>(arguments_list));
 }
 }
 
 
 template<typename... Args>
 template<typename... Args>
 ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, Value function, Value this_value, Args&&... args)
 ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, Value function, Value this_value, Args&&... args)
 {
 {
-    if constexpr (sizeof...(Args) > 0) {
-        MarkedVector<Value> arguments_list { vm.heap() };
-        (..., arguments_list.append(forward<Args>(args)));
-        return call_impl(vm, function, this_value, move(arguments_list));
+    constexpr auto argument_count = sizeof...(Args);
+    if constexpr (argument_count > 0) {
+        AK::Array<Value, argument_count> arguments { forward<Args>(args)... };
+        return call_impl(vm, function, this_value, static_cast<ReadonlySpan<Value>>(arguments.span()));
     }
     }
 
 
     return call_impl(vm, function, this_value);
     return call_impl(vm, function, this_value);
 }
 }
 
 
-ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, FunctionObject& function, Value this_value, MarkedVector<Value> arguments_list)
+ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, FunctionObject& function, Value this_value, ReadonlySpan<Value> arguments_list)
 {
 {
-    return call_impl(vm, function, this_value, move(arguments_list));
+    return call_impl(vm, function, this_value, arguments_list);
 }
 }
 
 
-ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, FunctionObject& function, Value this_value, Optional<MarkedVector<Value>> arguments_list)
+ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, FunctionObject& function, Value this_value, Span<Value> arguments_list)
 {
 {
-    return call_impl(vm, function, this_value, move(arguments_list));
+    return call_impl(vm, function, this_value, static_cast<ReadonlySpan<Value>>(arguments_list));
 }
 }
 
 
 template<typename... Args>
 template<typename... Args>
 ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, FunctionObject& function, Value this_value, Args&&... args)
 ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, FunctionObject& function, Value this_value, Args&&... args)
 {
 {
-    if constexpr (sizeof...(Args) > 0) {
-        MarkedVector<Value> arguments_list { vm.heap() };
-        (..., arguments_list.append(forward<Args>(args)));
-        return call_impl(vm, function, this_value, move(arguments_list));
+    constexpr auto argument_count = sizeof...(Args);
+    if constexpr (argument_count > 0) {
+        AK::Array<Value, argument_count> arguments { forward<Args>(args)... };
+        return call_impl(vm, function, this_value, static_cast<ReadonlySpan<Value>>(arguments.span()));
     }
     }
 
 
     return call_impl(vm, function, this_value);
     return call_impl(vm, function, this_value);
@@ -123,23 +123,23 @@ ALWAYS_INLINE ThrowCompletionOr<Value> call(VM& vm, FunctionObject& function, Va
 template<typename... Args>
 template<typename... Args>
 ALWAYS_INLINE ThrowCompletionOr<NonnullGCPtr<Object>> construct(VM& vm, FunctionObject& function, Args&&... args)
 ALWAYS_INLINE ThrowCompletionOr<NonnullGCPtr<Object>> construct(VM& vm, FunctionObject& function, Args&&... args)
 {
 {
-    if constexpr (sizeof...(Args) > 0) {
-        MarkedVector<Value> arguments_list { vm.heap() };
-        (..., arguments_list.append(forward<Args>(args)));
-        return construct_impl(vm, function, move(arguments_list));
+    constexpr auto argument_count = sizeof...(Args);
+    if constexpr (argument_count > 0) {
+        AK::Array<Value, argument_count> arguments { forward<Args>(args)... };
+        return construct_impl(vm, function, static_cast<ReadonlySpan<Value>>(arguments.span()));
     }
     }
 
 
     return construct_impl(vm, function);
     return construct_impl(vm, function);
 }
 }
 
 
-ALWAYS_INLINE ThrowCompletionOr<NonnullGCPtr<Object>> construct(VM& vm, FunctionObject& function, MarkedVector<Value> arguments_list, FunctionObject* new_target = nullptr)
+ALWAYS_INLINE ThrowCompletionOr<NonnullGCPtr<Object>> construct(VM& vm, FunctionObject& function, ReadonlySpan<Value> arguments_list, FunctionObject* new_target = nullptr)
 {
 {
-    return construct_impl(vm, function, move(arguments_list), new_target);
+    return construct_impl(vm, function, arguments_list, new_target);
 }
 }
 
 
-ALWAYS_INLINE ThrowCompletionOr<NonnullGCPtr<Object>> construct(VM& vm, FunctionObject& function, Optional<MarkedVector<Value>> arguments_list, FunctionObject* new_target = nullptr)
+ALWAYS_INLINE ThrowCompletionOr<NonnullGCPtr<Object>> construct(VM& vm, FunctionObject& function, Span<Value> arguments_list, FunctionObject* new_target = nullptr)
 {
 {
-    return construct_impl(vm, function, move(arguments_list), new_target);
+    return construct_impl(vm, function, static_cast<ReadonlySpan<Value>>(arguments_list), new_target);
 }
 }
 
 
 // 10.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ), https://tc39.es/ecma262/#sec-ordinarycreatefromconstructor
 // 10.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] ), https://tc39.es/ecma262/#sec-ordinarycreatefromconstructor

+ 18 - 0
Userland/Libraries/LibJS/Runtime/Array.cpp

@@ -63,6 +63,24 @@ NonnullGCPtr<Array> Array::create_from(Realm& realm, Vector<Value> const& elemen
     return array;
     return array;
 }
 }
 
 
+NonnullGCPtr<Array> Array::create_from(Realm& realm, ReadonlySpan<Value> const& elements)
+{
+    // 1. Let array be ! ArrayCreate(0).
+    auto array = MUST(Array::create(realm, 0));
+
+    // 2. Let n be 0.
+    // 3. For each element e of elements, do
+    for (u32 n = 0; n < elements.size(); ++n) {
+        // a. Perform ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), e).
+        MUST(array->create_data_property_or_throw(n, elements[n]));
+
+        // b. Set n to n + 1.
+    }
+
+    // 4. Return array.
+    return array;
+}
+
 Array::Array(Object& prototype)
 Array::Array(Object& prototype)
     : Object(ConstructWithPrototypeTag::Tag, prototype)
     : Object(ConstructWithPrototypeTag::Tag, prototype)
 {
 {

+ 1 - 0
Userland/Libraries/LibJS/Runtime/Array.h

@@ -26,6 +26,7 @@ class Array : public Object {
 public:
 public:
     static ThrowCompletionOr<NonnullGCPtr<Array>> create(Realm&, u64 length, Object* prototype = nullptr);
     static ThrowCompletionOr<NonnullGCPtr<Array>> create(Realm&, u64 length, Object* prototype = nullptr);
     static NonnullGCPtr<Array> create_from(Realm&, Vector<Value> const&);
     static NonnullGCPtr<Array> create_from(Realm&, Vector<Value> const&);
+    static NonnullGCPtr<Array> create_from(Realm&, ReadonlySpan<Value> const&);
 
 
     // Non-standard but equivalent to CreateArrayFromList.
     // Non-standard but equivalent to CreateArrayFromList.
     template<typename T>
     template<typename T>

+ 8 - 7
Userland/Libraries/LibJS/Runtime/BoundFunction.cpp

@@ -45,7 +45,7 @@ BoundFunction::BoundFunction(Realm& realm, FunctionObject& bound_target_function
 }
 }
 
 
 // 10.4.1.1 [[Call]] ( thisArgument, argumentsList ), https://tc39.es/ecma262/#sec-bound-function-exotic-objects-call-thisargument-argumentslist
 // 10.4.1.1 [[Call]] ( thisArgument, argumentsList ), https://tc39.es/ecma262/#sec-bound-function-exotic-objects-call-thisargument-argumentslist
-ThrowCompletionOr<Value> BoundFunction::internal_call([[maybe_unused]] Value this_argument, MarkedVector<Value> arguments_list)
+ThrowCompletionOr<Value> BoundFunction::internal_call([[maybe_unused]] Value this_argument, ReadonlySpan<Value> arguments_list)
 {
 {
     auto& vm = this->vm();
     auto& vm = this->vm();
 
 
@@ -59,16 +59,17 @@ ThrowCompletionOr<Value> BoundFunction::internal_call([[maybe_unused]] Value thi
     auto& bound_args = m_bound_arguments;
     auto& bound_args = m_bound_arguments;
 
 
     // 4. Let args be the list-concatenation of boundArgs and argumentsList.
     // 4. Let args be the list-concatenation of boundArgs and argumentsList.
-    auto args = MarkedVector<Value> { heap() };
+    Vector<Value> args;
+    args.ensure_capacity(bound_args.size() + arguments_list.size());
     args.extend(bound_args);
     args.extend(bound_args);
-    args.extend(move(arguments_list));
+    args.append(arguments_list.data(), arguments_list.size());
 
 
     // 5. Return ? Call(target, boundThis, args).
     // 5. Return ? Call(target, boundThis, args).
-    return call(vm, &target, bound_this, move(args));
+    return call(vm, &target, bound_this, args.span());
 }
 }
 
 
 // 10.4.1.2 [[Construct]] ( argumentsList, newTarget ), https://tc39.es/ecma262/#sec-bound-function-exotic-objects-construct-argumentslist-newtarget
 // 10.4.1.2 [[Construct]] ( argumentsList, newTarget ), https://tc39.es/ecma262/#sec-bound-function-exotic-objects-construct-argumentslist-newtarget
-ThrowCompletionOr<NonnullGCPtr<Object>> BoundFunction::internal_construct(MarkedVector<Value> arguments_list, FunctionObject& new_target)
+ThrowCompletionOr<NonnullGCPtr<Object>> BoundFunction::internal_construct(ReadonlySpan<Value> arguments_list, FunctionObject& new_target)
 {
 {
     auto& vm = this->vm();
     auto& vm = this->vm();
 
 
@@ -84,7 +85,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> BoundFunction::internal_construct(Marked
     // 4. Let args be the list-concatenation of boundArgs and argumentsList.
     // 4. Let args be the list-concatenation of boundArgs and argumentsList.
     auto args = MarkedVector<Value> { heap() };
     auto args = MarkedVector<Value> { heap() };
     args.extend(bound_args);
     args.extend(bound_args);
-    args.extend(move(arguments_list));
+    args.append(arguments_list.data(), arguments_list.size());
 
 
     // 5. If SameValue(F, newTarget) is true, set newTarget to target.
     // 5. If SameValue(F, newTarget) is true, set newTarget to target.
     auto* final_new_target = &new_target;
     auto* final_new_target = &new_target;
@@ -92,7 +93,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> BoundFunction::internal_construct(Marked
         final_new_target = &target;
         final_new_target = &target;
 
 
     // 6. Return ? Construct(target, args, newTarget).
     // 6. Return ? Construct(target, args, newTarget).
-    return construct(vm, target, move(args), final_new_target);
+    return construct(vm, target, args.span(), final_new_target);
 }
 }
 
 
 void BoundFunction::visit_edges(Visitor& visitor)
 void BoundFunction::visit_edges(Visitor& visitor)

+ 2 - 2
Userland/Libraries/LibJS/Runtime/BoundFunction.h

@@ -20,8 +20,8 @@ public:
 
 
     virtual ~BoundFunction() override = default;
     virtual ~BoundFunction() override = default;
 
 
-    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, MarkedVector<Value> arguments_list) override;
-    virtual ThrowCompletionOr<NonnullGCPtr<Object>> internal_construct(MarkedVector<Value> arguments_list, FunctionObject& new_target) override;
+    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override;
+    virtual ThrowCompletionOr<NonnullGCPtr<Object>> internal_construct(ReadonlySpan<Value> arguments_list, FunctionObject& new_target) override;
 
 
     virtual DeprecatedFlyString const& name() const override { return m_name; }
     virtual DeprecatedFlyString const& name() const override { return m_name; }
     virtual bool is_strict_mode() const override { return m_bound_target_function->is_strict_mode(); }
     virtual bool is_strict_mode() const override { return m_bound_target_function->is_strict_mode(); }

+ 4 - 4
Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp

@@ -361,7 +361,7 @@ void ECMAScriptFunctionObject::initialize(Realm& realm)
 }
 }
 
 
 // 10.2.1 [[Call]] ( thisArgument, argumentsList ), https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
 // 10.2.1 [[Call]] ( thisArgument, argumentsList ), https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
-ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argument, MarkedVector<Value> arguments_list)
+ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argument, ReadonlySpan<Value> arguments_list)
 {
 {
     auto& vm = this->vm();
     auto& vm = this->vm();
 
 
@@ -373,7 +373,7 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
     callee_context.local_variables.resize(m_local_variables_names.size());
     callee_context.local_variables.resize(m_local_variables_names.size());
 
 
     // Non-standard
     // Non-standard
-    callee_context.arguments.extend(move(arguments_list));
+    callee_context.arguments.append(arguments_list.data(), arguments_list.size());
     callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
     callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
 
 
     // 2. Let calleeContext be PrepareForOrdinaryCall(F, undefined).
     // 2. Let calleeContext be PrepareForOrdinaryCall(F, undefined).
@@ -420,7 +420,7 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
 }
 }
 
 
 // 10.2.2 [[Construct]] ( argumentsList, newTarget ), https://tc39.es/ecma262/#sec-ecmascript-function-objects-construct-argumentslist-newtarget
 // 10.2.2 [[Construct]] ( argumentsList, newTarget ), https://tc39.es/ecma262/#sec-ecmascript-function-objects-construct-argumentslist-newtarget
-ThrowCompletionOr<NonnullGCPtr<Object>> ECMAScriptFunctionObject::internal_construct(MarkedVector<Value> arguments_list, FunctionObject& new_target)
+ThrowCompletionOr<NonnullGCPtr<Object>> ECMAScriptFunctionObject::internal_construct(ReadonlySpan<Value> arguments_list, FunctionObject& new_target)
 {
 {
     auto& vm = this->vm();
     auto& vm = this->vm();
 
 
@@ -443,7 +443,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ECMAScriptFunctionObject::internal_const
     callee_context.local_variables.resize(m_local_variables_names.size());
     callee_context.local_variables.resize(m_local_variables_names.size());
 
 
     // Non-standard
     // Non-standard
-    callee_context.arguments.extend(move(arguments_list));
+    callee_context.arguments.append(arguments_list.data(), arguments_list.size());
     callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
     callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
 
 
     // 4. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).
     // 4. Let calleeContext be PrepareForOrdinaryCall(F, newTarget).

+ 2 - 2
Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.h

@@ -44,8 +44,8 @@ public:
     virtual void initialize(Realm&) override;
     virtual void initialize(Realm&) override;
     virtual ~ECMAScriptFunctionObject() override = default;
     virtual ~ECMAScriptFunctionObject() override = default;
 
 
-    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, MarkedVector<Value> arguments_list) override;
-    virtual ThrowCompletionOr<NonnullGCPtr<Object>> internal_construct(MarkedVector<Value> arguments_list, FunctionObject& new_target) override;
+    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override;
+    virtual ThrowCompletionOr<NonnullGCPtr<Object>> internal_construct(ReadonlySpan<Value> arguments_list, FunctionObject& new_target) override;
 
 
     void make_method(Object& home_object);
     void make_method(Object& home_object);
 
 

+ 2 - 2
Userland/Libraries/LibJS/Runtime/FunctionObject.h

@@ -23,8 +23,8 @@ public:
 
 
     // Table 7: Additional Essential Internal Methods of Function Objects, https://tc39.es/ecma262/#table-additional-essential-internal-methods-of-function-objects
     // Table 7: Additional Essential Internal Methods of Function Objects, https://tc39.es/ecma262/#table-additional-essential-internal-methods-of-function-objects
 
 
-    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, MarkedVector<Value> arguments_list) = 0;
-    virtual ThrowCompletionOr<NonnullGCPtr<Object>> internal_construct([[maybe_unused]] MarkedVector<Value> arguments_list, [[maybe_unused]] FunctionObject& new_target) { VERIFY_NOT_REACHED(); }
+    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) = 0;
+    virtual ThrowCompletionOr<NonnullGCPtr<Object>> internal_construct([[maybe_unused]] ReadonlySpan<Value> arguments_list, [[maybe_unused]] FunctionObject& new_target) { VERIFY_NOT_REACHED(); }
 
 
     virtual DeprecatedFlyString const& name() const = 0;
     virtual DeprecatedFlyString const& name() const = 0;
 
 

+ 4 - 8
Userland/Libraries/LibJS/Runtime/FunctionPrototype.cpp

@@ -40,7 +40,7 @@ void FunctionPrototype::initialize(Realm& realm)
     define_direct_property(vm.names.name, PrimitiveString::create(vm, String {}), Attribute::Configurable);
     define_direct_property(vm.names.name, PrimitiveString::create(vm, String {}), Attribute::Configurable);
 }
 }
 
 
-ThrowCompletionOr<Value> FunctionPrototype::internal_call(Value, MarkedVector<Value>)
+ThrowCompletionOr<Value> FunctionPrototype::internal_call(Value, ReadonlySpan<Value>)
 {
 {
     // The Function prototype object:
     // The Function prototype object:
     // - accepts any arguments and returns undefined when invoked.
     // - accepts any arguments and returns undefined when invoked.
@@ -76,7 +76,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::apply)
     // FIXME: 5. Perform PrepareForTailCall().
     // FIXME: 5. Perform PrepareForTailCall().
 
 
     // 6. Return ? Call(func, thisArg, argList).
     // 6. Return ? Call(func, thisArg, argList).
-    return TRY(JS::call(vm, function, this_arg, move(arguments)));
+    return TRY(JS::call(vm, function, this_arg, arguments.span()));
 }
 }
 
 
 // 20.2.3.2 Function.prototype.bind ( thisArg, ...args ), https://tc39.es/ecma262/#sec-function.prototype.bind
 // 20.2.3.2 Function.prototype.bind ( thisArg, ...args ), https://tc39.es/ecma262/#sec-function.prototype.bind
@@ -130,14 +130,10 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::call)
     // FIXME: 3. Perform PrepareForTailCall().
     // FIXME: 3. Perform PrepareForTailCall().
 
 
     auto this_arg = vm.argument(0);
     auto this_arg = vm.argument(0);
-    MarkedVector<Value> arguments(vm.heap());
-    if (vm.argument_count() > 1) {
-        for (size_t i = 1; i < vm.argument_count(); ++i)
-            arguments.append(vm.argument(i));
-    }
+    auto args = vm.argument_count() > 1 ? vm.running_execution_context().arguments.span().slice(1) : ReadonlySpan<Value> {};
 
 
     // 4. Return ? Call(func, thisArg, args).
     // 4. Return ? Call(func, thisArg, args).
-    return TRY(JS::call(vm, function, this_arg, move(arguments)));
+    return TRY(JS::call(vm, function, this_arg, args));
 }
 }
 
 
 // 20.2.3.5 Function.prototype.toString ( ), https://tc39.es/ecma262/#sec-function.prototype.tostring
 // 20.2.3.5 Function.prototype.toString ( ), https://tc39.es/ecma262/#sec-function.prototype.tostring

+ 1 - 1
Userland/Libraries/LibJS/Runtime/FunctionPrototype.h

@@ -18,7 +18,7 @@ public:
     virtual void initialize(Realm&) override;
     virtual void initialize(Realm&) override;
     virtual ~FunctionPrototype() override = default;
     virtual ~FunctionPrototype() override = default;
 
 
-    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, MarkedVector<Value> arguments_list) override;
+    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override;
     virtual DeprecatedFlyString const& name() const override { return m_name; }
     virtual DeprecatedFlyString const& name() const override { return m_name; }
 
 
 private:
 private:

+ 2 - 2
Userland/Libraries/LibJS/Runtime/JobCallback.cpp

@@ -18,13 +18,13 @@ JobCallback make_job_callback(FunctionObject& callback)
 }
 }
 
 
 // 9.5.3 HostCallJobCallback ( jobCallback, V, argumentsList ), https://tc39.es/ecma262/#sec-hostcalljobcallback
 // 9.5.3 HostCallJobCallback ( jobCallback, V, argumentsList ), https://tc39.es/ecma262/#sec-hostcalljobcallback
-ThrowCompletionOr<Value> call_job_callback(VM& vm, JobCallback& job_callback, Value this_value, MarkedVector<Value> arguments_list)
+ThrowCompletionOr<Value> call_job_callback(VM& vm, JobCallback& job_callback, Value this_value, ReadonlySpan<Value> arguments_list)
 {
 {
     // 1. Assert: IsCallable(jobCallback.[[Callback]]) is true.
     // 1. Assert: IsCallable(jobCallback.[[Callback]]) is true.
     VERIFY(!job_callback.callback.is_null());
     VERIFY(!job_callback.callback.is_null());
 
 
     // 2. Return ? Call(jobCallback.[[Callback]], V, argumentsList).
     // 2. Return ? Call(jobCallback.[[Callback]], V, argumentsList).
-    return call(vm, job_callback.callback.cell(), this_value, move(arguments_list));
+    return call(vm, job_callback.callback.cell(), this_value, arguments_list);
 }
 }
 
 
 }
 }

+ 1 - 1
Userland/Libraries/LibJS/Runtime/JobCallback.h

@@ -23,6 +23,6 @@ struct JobCallback {
 };
 };
 
 
 JobCallback make_job_callback(FunctionObject& callback);
 JobCallback make_job_callback(FunctionObject& callback);
-ThrowCompletionOr<Value> call_job_callback(VM&, JobCallback&, Value this_value, MarkedVector<Value> arguments_list);
+ThrowCompletionOr<Value> call_job_callback(VM&, JobCallback&, Value this_value, ReadonlySpan<Value> arguments_list);
 
 
 }
 }

+ 4 - 4
Userland/Libraries/LibJS/Runtime/NativeFunction.cpp

@@ -96,7 +96,7 @@ NativeFunction::NativeFunction(DeprecatedFlyString name, Object& prototype)
 // these good candidates for a bit of code duplication :^)
 // these good candidates for a bit of code duplication :^)
 
 
 // 10.3.1 [[Call]] ( thisArgument, argumentsList ), https://tc39.es/ecma262/#sec-built-in-function-objects-call-thisargument-argumentslist
 // 10.3.1 [[Call]] ( thisArgument, argumentsList ), https://tc39.es/ecma262/#sec-built-in-function-objects-call-thisargument-argumentslist
-ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, MarkedVector<Value> arguments_list)
+ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, ReadonlySpan<Value> arguments_list)
 {
 {
     auto& vm = this->vm();
     auto& vm = this->vm();
 
 
@@ -132,7 +132,7 @@ ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, Mark
 
 
     // 8. Perform any necessary implementation-defined initialization of calleeContext.
     // 8. Perform any necessary implementation-defined initialization of calleeContext.
     callee_context.this_value = this_argument;
     callee_context.this_value = this_argument;
-    callee_context.arguments.extend(move(arguments_list));
+    callee_context.arguments.append(arguments_list.data(), arguments_list.size());
     callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
     callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
 
 
     callee_context.lexical_environment = caller_context.lexical_environment;
     callee_context.lexical_environment = caller_context.lexical_environment;
@@ -160,7 +160,7 @@ ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, Mark
 }
 }
 
 
 // 10.3.2 [[Construct]] ( argumentsList, newTarget ), https://tc39.es/ecma262/#sec-built-in-function-objects-construct-argumentslist-newtarget
 // 10.3.2 [[Construct]] ( argumentsList, newTarget ), https://tc39.es/ecma262/#sec-built-in-function-objects-construct-argumentslist-newtarget
-ThrowCompletionOr<NonnullGCPtr<Object>> NativeFunction::internal_construct(MarkedVector<Value> arguments_list, FunctionObject& new_target)
+ThrowCompletionOr<NonnullGCPtr<Object>> NativeFunction::internal_construct(ReadonlySpan<Value> arguments_list, FunctionObject& new_target)
 {
 {
     auto& vm = this->vm();
     auto& vm = this->vm();
 
 
@@ -195,7 +195,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> NativeFunction::internal_construct(Marke
     // Note: This is already the default value.
     // Note: This is already the default value.
 
 
     // 8. Perform any necessary implementation-defined initialization of calleeContext.
     // 8. Perform any necessary implementation-defined initialization of calleeContext.
-    callee_context.arguments.extend(move(arguments_list));
+    callee_context.arguments.append(arguments_list.data(), arguments_list.size());
     callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
     callee_context.instruction_stream_iterator = vm.bytecode_interpreter().instruction_stream_iterator();
 
 
     callee_context.lexical_environment = caller_context.lexical_environment;
     callee_context.lexical_environment = caller_context.lexical_environment;

+ 2 - 2
Userland/Libraries/LibJS/Runtime/NativeFunction.h

@@ -26,8 +26,8 @@ public:
 
 
     virtual ~NativeFunction() override = default;
     virtual ~NativeFunction() override = default;
 
 
-    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, MarkedVector<Value> arguments_list) override;
-    virtual ThrowCompletionOr<NonnullGCPtr<Object>> internal_construct(MarkedVector<Value> arguments_list, FunctionObject& new_target) override;
+    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override;
+    virtual ThrowCompletionOr<NonnullGCPtr<Object>> internal_construct(ReadonlySpan<Value> arguments_list, FunctionObject& new_target) override;
 
 
     // Used for [[Call]] / [[Construct]]'s "...result of evaluating F in a manner that conforms to the specification of F".
     // Used for [[Call]] / [[Construct]]'s "...result of evaluating F in a manner that conforms to the specification of F".
     // Needs to be overridden by all NativeFunctions without an m_native_function.
     // Needs to be overridden by all NativeFunctions without an m_native_function.

+ 5 - 7
Userland/Libraries/LibJS/Runtime/PromiseJobs.cpp

@@ -52,9 +52,7 @@ static ThrowCompletionOr<Value> run_reaction_job(VM& vm, PromiseReaction& reacti
     // e. Else, let handlerResult be Completion(HostCallJobCallback(handler, undefined, « argument »)).
     // e. Else, let handlerResult be Completion(HostCallJobCallback(handler, undefined, « argument »)).
     else {
     else {
         dbgln_if(PROMISE_DEBUG, "run_reaction_job: Calling handler callback {} @ {} with argument {}", handler.value().callback.cell()->class_name(), handler.value().callback.cell(), argument);
         dbgln_if(PROMISE_DEBUG, "run_reaction_job: Calling handler callback {} @ {} with argument {}", handler.value().callback.cell()->class_name(), handler.value().callback.cell(), argument);
-        MarkedVector<Value> arguments(vm.heap());
-        arguments.append(argument);
-        handler_result = vm.host_call_job_callback(handler.value(), js_undefined(), move(arguments));
+        handler_result = vm.host_call_job_callback(handler.value(), js_undefined(), ReadonlySpan<Value> { &argument, 1 });
     }
     }
 
 
     // f. If promiseCapability is undefined, then
     // f. If promiseCapability is undefined, then
@@ -128,10 +126,10 @@ static ThrowCompletionOr<Value> run_resolve_thenable_job(VM& vm, Promise& promis
 
 
     // b. Let thenCallResult be Completion(HostCallJobCallback(then, thenable, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).
     // b. Let thenCallResult be Completion(HostCallJobCallback(then, thenable, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).
     dbgln_if(PROMISE_DEBUG, "run_resolve_thenable_job: Calling then job callback for thenable {}", &thenable);
     dbgln_if(PROMISE_DEBUG, "run_resolve_thenable_job: Calling then job callback for thenable {}", &thenable);
-    MarkedVector<Value> arguments(vm.heap());
-    arguments.append(Value(resolve_function));
-    arguments.append(Value(reject_function));
-    auto then_call_result = vm.host_call_job_callback(then, thenable, move(arguments));
+    AK::Array<Value, 2> arguments;
+    arguments[0] = Value(resolve_function);
+    arguments[1] = Value(reject_function);
+    auto then_call_result = vm.host_call_job_callback(then, thenable, arguments.span());
 
 
     // c. If thenCallResult is an abrupt completion, then
     // c. If thenCallResult is an abrupt completion, then
     if (then_call_result.is_error()) {
     if (then_call_result.is_error()) {

+ 4 - 4
Userland/Libraries/LibJS/Runtime/ProxyObject.cpp

@@ -774,7 +774,7 @@ ThrowCompletionOr<MarkedVector<Value>> ProxyObject::internal_own_property_keys()
 }
 }
 
 
 // 10.5.12 [[Call]] ( thisArgument, argumentsList ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-call-thisargument-argumentslist
 // 10.5.12 [[Call]] ( thisArgument, argumentsList ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-call-thisargument-argumentslist
-ThrowCompletionOr<Value> ProxyObject::internal_call(Value this_argument, MarkedVector<Value> arguments_list)
+ThrowCompletionOr<Value> ProxyObject::internal_call(Value this_argument, ReadonlySpan<Value> arguments_list)
 {
 {
     auto& vm = this->vm();
     auto& vm = this->vm();
     auto& realm = *vm.current_realm();
     auto& realm = *vm.current_realm();
@@ -797,7 +797,7 @@ ThrowCompletionOr<Value> ProxyObject::internal_call(Value this_argument, MarkedV
     // 6. If trap is undefined, then
     // 6. If trap is undefined, then
     if (!trap) {
     if (!trap) {
         // a. Return ? Call(target, thisArgument, argumentsList).
         // a. Return ? Call(target, thisArgument, argumentsList).
-        return call(vm, m_target, this_argument, move(arguments_list));
+        return call(vm, m_target, this_argument, arguments_list);
     }
     }
 
 
     // 7. Let argArray be CreateArrayFromList(argumentsList).
     // 7. Let argArray be CreateArrayFromList(argumentsList).
@@ -818,7 +818,7 @@ bool ProxyObject::has_constructor() const
 }
 }
 
 
 // 10.5.13 [[Construct]] ( argumentsList, newTarget ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
 // 10.5.13 [[Construct]] ( argumentsList, newTarget ), https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
-ThrowCompletionOr<NonnullGCPtr<Object>> ProxyObject::internal_construct(MarkedVector<Value> arguments_list, FunctionObject& new_target)
+ThrowCompletionOr<NonnullGCPtr<Object>> ProxyObject::internal_construct(ReadonlySpan<Value> arguments_list, FunctionObject& new_target)
 {
 {
     auto& vm = this->vm();
     auto& vm = this->vm();
     auto& realm = *vm.current_realm();
     auto& realm = *vm.current_realm();
@@ -842,7 +842,7 @@ ThrowCompletionOr<NonnullGCPtr<Object>> ProxyObject::internal_construct(MarkedVe
     // 7. If trap is undefined, then
     // 7. If trap is undefined, then
     if (!trap) {
     if (!trap) {
         // a. Return ? Construct(target, argumentsList, newTarget).
         // a. Return ? Construct(target, argumentsList, newTarget).
-        return construct(vm, static_cast<FunctionObject&>(*m_target), move(arguments_list), &new_target);
+        return construct(vm, static_cast<FunctionObject&>(*m_target), arguments_list, &new_target);
     }
     }
 
 
     // 8. Let argArray be CreateArrayFromList(argumentsList).
     // 8. Let argArray be CreateArrayFromList(argumentsList).

+ 2 - 2
Userland/Libraries/LibJS/Runtime/ProxyObject.h

@@ -43,8 +43,8 @@ public:
     virtual ThrowCompletionOr<bool> internal_set(PropertyKey const&, Value value, Value receiver, CacheablePropertyMetadata*) override;
     virtual ThrowCompletionOr<bool> internal_set(PropertyKey const&, Value value, Value receiver, CacheablePropertyMetadata*) override;
     virtual ThrowCompletionOr<bool> internal_delete(PropertyKey const&) override;
     virtual ThrowCompletionOr<bool> internal_delete(PropertyKey const&) override;
     virtual ThrowCompletionOr<MarkedVector<Value>> internal_own_property_keys() const override;
     virtual ThrowCompletionOr<MarkedVector<Value>> internal_own_property_keys() const override;
-    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, MarkedVector<Value> arguments_list) override;
-    virtual ThrowCompletionOr<NonnullGCPtr<Object>> internal_construct(MarkedVector<Value> arguments_list, FunctionObject& new_target) override;
+    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override;
+    virtual ThrowCompletionOr<NonnullGCPtr<Object>> internal_construct(ReadonlySpan<Value> arguments_list, FunctionObject& new_target) override;
 
 
 private:
 private:
     ProxyObject(Object& target, Object& handler, Object& prototype);
     ProxyObject(Object& target, Object& handler, Object& prototype);

+ 2 - 2
Userland/Libraries/LibJS/Runtime/ReflectObject.cpp

@@ -61,7 +61,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::apply)
 
 
     // 3. Perform PrepareForTailCall().
     // 3. Perform PrepareForTailCall().
     // 4. Return ? Call(target, thisArgument, args).
     // 4. Return ? Call(target, thisArgument, args).
-    return TRY(call(vm, target.as_function(), this_argument, move(args)));
+    return TRY(call(vm, target.as_function(), this_argument, args.span()));
 }
 }
 
 
 // 28.1.2 Reflect.construct ( target, argumentsList [ , newTarget ] ), https://tc39.es/ecma262/#sec-reflect.construct
 // 28.1.2 Reflect.construct ( target, argumentsList [ , newTarget ] ), https://tc39.es/ecma262/#sec-reflect.construct
@@ -86,7 +86,7 @@ JS_DEFINE_NATIVE_FUNCTION(ReflectObject::construct)
     auto args = TRY(create_list_from_array_like(vm, arguments_list));
     auto args = TRY(create_list_from_array_like(vm, arguments_list));
 
 
     // 5. Return ? Construct(target, args, newTarget).
     // 5. Return ? Construct(target, args, newTarget).
-    return TRY(JS::construct(vm, target.as_function(), move(args), &new_target.as_function()));
+    return TRY(JS::construct(vm, target.as_function(), args.span(), &new_target.as_function()));
 }
 }
 
 
 // 28.1.3 Reflect.defineProperty ( target, propertyKey, attributes ), https://tc39.es/ecma262/#sec-reflect.defineproperty
 // 28.1.3 Reflect.defineProperty ( target, propertyKey, attributes ), https://tc39.es/ecma262/#sec-reflect.defineproperty

+ 1 - 1
Userland/Libraries/LibJS/Runtime/RegExpPrototype.cpp

@@ -777,7 +777,7 @@ JS_DEFINE_NATIVE_FUNCTION(RegExpPrototype::symbol_replace)
             }
             }
 
 
             // iii. Let replValue be ? Call(replaceValue, undefined, replacerArgs).
             // iii. Let replValue be ? Call(replaceValue, undefined, replacerArgs).
-            auto replace_result = TRY(call(vm, replace_value.as_function(), js_undefined(), move(replacer_args)));
+            auto replace_result = TRY(call(vm, replace_value.as_function(), js_undefined(), replacer_args.span()));
 
 
             // iv. Let replacement be ? ToString(replValue).
             // iv. Let replacement be ? ToString(replValue).
             replacement = TRY(replace_result.to_string(vm));
             replacement = TRY(replace_result.to_string(vm));

+ 1 - 1
Userland/Libraries/LibJS/Runtime/TypedArray.cpp

@@ -322,7 +322,7 @@ ThrowCompletionOr<TypedArrayBase*> typed_array_create(VM& vm, FunctionObject& co
     if (!arguments.is_empty())
     if (!arguments.is_empty())
         first_argument = arguments[0];
         first_argument = arguments[0];
     // 1. Let newTypedArray be ? Construct(constructor, argumentList).
     // 1. Let newTypedArray be ? Construct(constructor, argumentList).
-    auto new_typed_array = TRY(construct(vm, constructor, move(arguments)));
+    auto new_typed_array = TRY(construct(vm, constructor, arguments.span()));
 
 
     // 2. Perform ? ValidateTypedArray(newTypedArray).
     // 2. Perform ? ValidateTypedArray(newTypedArray).
     if (!new_typed_array->is_typed_array())
     if (!new_typed_array->is_typed_array())

+ 2 - 2
Userland/Libraries/LibJS/Runtime/VM.cpp

@@ -78,8 +78,8 @@ VM::VM(OwnPtr<CustomData> custom_data, ErrorMessages error_messages)
         promise_rejection_tracker(promise, operation);
         promise_rejection_tracker(promise, operation);
     };
     };
 
 
-    host_call_job_callback = [this](JobCallback& job_callback, Value this_value, MarkedVector<Value> arguments) {
-        return call_job_callback(*this, job_callback, this_value, move(arguments));
+    host_call_job_callback = [this](JobCallback& job_callback, Value this_value, ReadonlySpan<Value> arguments) {
+        return call_job_callback(*this, job_callback, this_value, arguments);
     };
     };
 
 
     host_enqueue_finalization_registry_cleanup_job = [this](FinalizationRegistry& finalization_registry) {
     host_enqueue_finalization_registry_cleanup_job = [this](FinalizationRegistry& finalization_registry) {

+ 1 - 1
Userland/Libraries/LibJS/Runtime/VM.h

@@ -243,7 +243,7 @@ public:
     void enable_default_host_import_module_dynamically_hook();
     void enable_default_host_import_module_dynamically_hook();
 
 
     Function<void(Promise&, Promise::RejectionOperation)> host_promise_rejection_tracker;
     Function<void(Promise&, Promise::RejectionOperation)> host_promise_rejection_tracker;
-    Function<ThrowCompletionOr<Value>(JobCallback&, Value, MarkedVector<Value>)> host_call_job_callback;
+    Function<ThrowCompletionOr<Value>(JobCallback&, Value, ReadonlySpan<Value>)> host_call_job_callback;
     Function<void(FinalizationRegistry&)> host_enqueue_finalization_registry_cleanup_job;
     Function<void(FinalizationRegistry&)> host_enqueue_finalization_registry_cleanup_job;
     Function<void(Function<ThrowCompletionOr<Value>()>, Realm*)> host_enqueue_promise_job;
     Function<void(Function<ThrowCompletionOr<Value>()>, Realm*)> host_enqueue_promise_job;
     Function<JobCallback(FunctionObject&)> host_make_job_callback;
     Function<JobCallback(FunctionObject&)> host_make_job_callback;

+ 4 - 1
Userland/Libraries/LibJS/Runtime/Value.cpp

@@ -2505,7 +2505,10 @@ ThrowCompletionOr<Value> Value::invoke_internal(VM& vm, PropertyKey const& prope
     auto function = TRY(get(vm, property_key));
     auto function = TRY(get(vm, property_key));
 
 
     // 3. Return ? Call(func, V, argumentsList).
     // 3. Return ? Call(func, V, argumentsList).
-    return call(vm, function, *this, move(arguments));
+    ReadonlySpan<Value> argument_list;
+    if (arguments.has_value())
+        argument_list = arguments.value().span();
+    return call(vm, function, *this, argument_list);
 }
 }
 
 
 }
 }

+ 3 - 3
Userland/Libraries/LibJS/Runtime/WrappedFunction.cpp

@@ -54,7 +54,7 @@ void WrappedFunction::visit_edges(Visitor& visitor)
 }
 }
 
 
 // 2.1 [[Call]] ( thisArgument, argumentsList ), https://tc39.es/proposal-shadowrealm/#sec-wrapped-function-exotic-objects-call-thisargument-argumentslist
 // 2.1 [[Call]] ( thisArgument, argumentsList ), https://tc39.es/proposal-shadowrealm/#sec-wrapped-function-exotic-objects-call-thisargument-argumentslist
-ThrowCompletionOr<Value> WrappedFunction::internal_call(Value this_argument, MarkedVector<Value> arguments_list)
+ThrowCompletionOr<Value> WrappedFunction::internal_call(Value this_argument, ReadonlySpan<Value> arguments_list)
 {
 {
     auto& vm = this->vm();
     auto& vm = this->vm();
 
 
@@ -82,7 +82,7 @@ ThrowCompletionOr<Value> WrappedFunction::internal_call(Value this_argument, Mar
 }
 }
 
 
 // 2.2 OrdinaryWrappedFunctionCall ( F: a wrapped function exotic object, thisArgument: an ECMAScript language value, argumentsList: a List of ECMAScript language values, ), https://tc39.es/proposal-shadowrealm/#sec-ordinary-wrapped-function-call
 // 2.2 OrdinaryWrappedFunctionCall ( F: a wrapped function exotic object, thisArgument: an ECMAScript language value, argumentsList: a List of ECMAScript language values, ), https://tc39.es/proposal-shadowrealm/#sec-ordinary-wrapped-function-call
-ThrowCompletionOr<Value> ordinary_wrapped_function_call(WrappedFunction const& function, Value this_argument, MarkedVector<Value> const& arguments_list)
+ThrowCompletionOr<Value> ordinary_wrapped_function_call(WrappedFunction const& function, Value this_argument, ReadonlySpan<Value> arguments_list)
 {
 {
     auto& vm = function.vm();
     auto& vm = function.vm();
 
 
@@ -118,7 +118,7 @@ ThrowCompletionOr<Value> ordinary_wrapped_function_call(WrappedFunction const& f
     auto wrapped_this_argument = TRY(get_wrapped_value(vm, *target_realm, this_argument));
     auto wrapped_this_argument = TRY(get_wrapped_value(vm, *target_realm, this_argument));
 
 
     // 9. Let result be the Completion Record of Call(target, wrappedThisArgument, wrappedArgs).
     // 9. Let result be the Completion Record of Call(target, wrappedThisArgument, wrappedArgs).
-    auto result = call(vm, &target, wrapped_this_argument, move(wrapped_args));
+    auto result = call(vm, &target, wrapped_this_argument, wrapped_args.span());
 
 
     // 10. If result.[[Type]] is normal or result.[[Type]] is return, then
     // 10. If result.[[Type]] is normal or result.[[Type]] is return, then
     if (!result.is_throw_completion()) {
     if (!result.is_throw_completion()) {

+ 2 - 2
Userland/Libraries/LibJS/Runtime/WrappedFunction.h

@@ -20,7 +20,7 @@ public:
 
 
     virtual ~WrappedFunction() = default;
     virtual ~WrappedFunction() = default;
 
 
-    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, MarkedVector<Value> arguments_list) override;
+    virtual ThrowCompletionOr<Value> internal_call(Value this_argument, ReadonlySpan<Value> arguments_list) override;
 
 
     // FIXME: Remove this (and stop inventing random internal slots that shouldn't exist, jeez)
     // FIXME: Remove this (and stop inventing random internal slots that shouldn't exist, jeez)
     virtual DeprecatedFlyString const& name() const override { return m_wrapped_target_function->name(); }
     virtual DeprecatedFlyString const& name() const override { return m_wrapped_target_function->name(); }
@@ -40,7 +40,7 @@ private:
     NonnullGCPtr<Realm> m_realm;                            // [[Realm]]
     NonnullGCPtr<Realm> m_realm;                            // [[Realm]]
 };
 };
 
 
-ThrowCompletionOr<Value> ordinary_wrapped_function_call(WrappedFunction const&, Value this_argument, MarkedVector<Value> const& arguments_list);
+ThrowCompletionOr<Value> ordinary_wrapped_function_call(WrappedFunction const&, Value this_argument, ReadonlySpan<Value> arguments_list);
 void prepare_for_wrapped_function_call(WrappedFunction const&, ExecutionContext& callee_context);
 void prepare_for_wrapped_function_call(WrappedFunction const&, ExecutionContext& callee_context);
 
 
 }
 }