LibJS: Remove unused target field from Completion

This shrinks Completion by 16 bytes, which has non-trivial impact
on performance.
This commit is contained in:
Andreas Kling 2024-05-10 09:28:48 +02:00 committed by Alexander Kalenik
parent a77c6e15f4
commit ae11a4de1c
Notes: sideshowbarker 2024-07-16 20:21:48 +09:00
9 changed files with 23 additions and 26 deletions

View file

@ -1819,7 +1819,7 @@ ThrowCompletionOr<void> IteratorClose::execute_impl(Bytecode::Interpreter& inter
auto& iterator = verify_cast<IteratorRecord>(interpreter.get(m_iterator_record).as_object()); auto& iterator = verify_cast<IteratorRecord>(interpreter.get(m_iterator_record).as_object());
// FIXME: Return the value of the resulting completion. (Note that m_completion_value can be empty!) // FIXME: Return the value of the resulting completion. (Note that m_completion_value can be empty!)
TRY(iterator_close(vm, iterator, Completion { m_completion_type, m_completion_value, {} })); TRY(iterator_close(vm, iterator, Completion { m_completion_type, m_completion_value }));
return {}; return {};
} }
@ -1829,7 +1829,7 @@ ThrowCompletionOr<void> AsyncIteratorClose::execute_impl(Bytecode::Interpreter&
auto& iterator = verify_cast<IteratorRecord>(interpreter.get(m_iterator_record).as_object()); auto& iterator = verify_cast<IteratorRecord>(interpreter.get(m_iterator_record).as_object());
// FIXME: Return the value of the resulting completion. (Note that m_completion_value can be empty!) // FIXME: Return the value of the resulting completion. (Note that m_completion_value can be empty!)
TRY(async_iterator_close(vm, iterator, Completion { m_completion_type, m_completion_value, {} })); TRY(async_iterator_close(vm, iterator, Completion { m_completion_type, m_completion_value }));
return {}; return {};
} }

View file

@ -403,7 +403,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from_async)
TRY(array->set(vm.names.length, Value(k), Object::ShouldThrowExceptions::Yes)); TRY(array->set(vm.names.length, Value(k), Object::ShouldThrowExceptions::Yes));
// b. Return Completion Record { [[Type]]: return, [[Value]]: A, [[Target]]: empty }. // b. Return Completion Record { [[Type]]: return, [[Value]]: A, [[Target]]: empty }.
return Completion { Completion::Type::Return, array, {} }; return Completion { Completion::Type::Return, array };
} }
// 8. Let nextValue be ? IteratorValue(nextResult). // 8. Let nextValue be ? IteratorValue(nextResult).
@ -508,7 +508,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayConstructor::from_async)
TRY(array->set(vm.names.length, Value(length), Object::ShouldThrowExceptions::Yes)); TRY(array->set(vm.names.length, Value(length), Object::ShouldThrowExceptions::Yes));
// ix. Return Completion Record { [[Type]]: return, [[Value]]: A, [[Target]]: empty }. // ix. Return Completion Record { [[Type]]: return, [[Value]]: A, [[Target]]: empty }.
return Completion { Completion::Type::Return, array, {} }; return Completion { Completion::Type::Return, array };
} }
}; };

View file

@ -119,7 +119,7 @@ JS_DEFINE_NATIVE_FUNCTION(AsyncGeneratorPrototype::return_)
auto generator = TRY_OR_REJECT(vm, promise_capability, async_generator_validate(vm, generator_this_value, OptionalNone {})); auto generator = TRY_OR_REJECT(vm, promise_capability, async_generator_validate(vm, generator_this_value, OptionalNone {}));
// 5. Let completion be Completion Record { [[Type]]: return, [[Value]]: value, [[Target]]: empty }. // 5. Let completion be Completion Record { [[Type]]: return, [[Value]]: value, [[Target]]: empty }.
auto completion = Completion(Completion::Type::Return, vm.argument(0), {}); auto completion = Completion(Completion::Type::Return, vm.argument(0));
// 6. Perform AsyncGeneratorEnqueue(generator, completion, promiseCapability). // 6. Perform AsyncGeneratorEnqueue(generator, completion, promiseCapability).
generator->async_generator_enqueue(completion, promise_capability); generator->async_generator_enqueue(completion, promise_capability);

View file

@ -144,7 +144,7 @@ Completion throw_completion(Value value)
log_exception(value); log_exception(value);
// 1. Return Completion Record { [[Type]]: throw, [[Value]]: value, [[Target]]: empty }. // 1. Return Completion Record { [[Type]]: throw, [[Value]]: value, [[Target]]: empty }.
return { Completion::Type::Throw, value, {} }; return { Completion::Type::Throw, value };
} }
} }

View file

@ -63,10 +63,9 @@ public:
Throw, Throw,
}; };
ALWAYS_INLINE Completion(Type type, Optional<Value> value, Optional<DeprecatedFlyString> target) ALWAYS_INLINE Completion(Type type, Optional<Value> value)
: m_type(type) : m_type(type)
, m_value(move(value)) , m_value(move(value))
, m_target(move(target))
{ {
VERIFY(type != Type::Empty); VERIFY(type != Type::Empty);
if (m_value.has_value()) if (m_value.has_value())
@ -78,12 +77,12 @@ public:
// 5.2.3.1 Implicit Completion Values, https://tc39.es/ecma262/#sec-implicit-completion-values // 5.2.3.1 Implicit Completion Values, https://tc39.es/ecma262/#sec-implicit-completion-values
// Not `explicit` on purpose. // Not `explicit` on purpose.
ALWAYS_INLINE Completion(Value value) ALWAYS_INLINE Completion(Value value)
: Completion(Type::Normal, value, {}) : Completion(Type::Normal, value)
{ {
} }
ALWAYS_INLINE Completion(Optional<Value> value) ALWAYS_INLINE Completion(Optional<Value> value)
: Completion(Type::Normal, move(value), {}) : Completion(Type::Normal, move(value))
{ {
} }
@ -104,8 +103,6 @@ public:
} }
[[nodiscard]] Optional<Value>& value() { return m_value; } [[nodiscard]] Optional<Value>& value() { return m_value; }
[[nodiscard]] Optional<Value> const& value() const { return m_value; } [[nodiscard]] Optional<Value> const& value() const { return m_value; }
[[nodiscard]] Optional<DeprecatedFlyString>& target() { return m_target; }
[[nodiscard]] Optional<DeprecatedFlyString> const& target() const { return m_target; }
// "abrupt completion refers to any completion with a [[Type]] value other than normal" // "abrupt completion refers to any completion with a [[Type]] value other than normal"
[[nodiscard]] bool is_abrupt() const { return m_type != Type::Normal; } [[nodiscard]] bool is_abrupt() const { return m_type != Type::Normal; }
@ -117,7 +114,7 @@ public:
{ {
VERIFY(is_error()); VERIFY(is_error());
VERIFY(m_value.has_value()); VERIFY(m_value.has_value());
return { m_type, release_value(), move(m_target) }; return { m_type, release_value() };
} }
// 6.2.3.4 UpdateEmpty ( completionRecord, value ), https://tc39.es/ecma262/#sec-updateempty // 6.2.3.4 UpdateEmpty ( completionRecord, value ), https://tc39.es/ecma262/#sec-updateempty
@ -132,7 +129,7 @@ public:
return *this; return *this;
// 3. Return Completion Record { [[Type]]: completionRecord.[[Type]], [[Value]]: value, [[Target]]: completionRecord.[[Target]] }. // 3. Return Completion Record { [[Type]]: completionRecord.[[Type]], [[Value]]: value, [[Target]]: completionRecord.[[Target]] }.
return { m_type, move(value), m_target }; return { m_type, move(value) };
} }
private: private:
@ -150,9 +147,9 @@ private:
return m_type == Type::Empty; return m_type == Type::Empty;
} }
Type m_type { Type::Normal }; // [[Type]] Type m_type { Type::Normal }; // [[Type]]
Optional<Value> m_value; // [[Value]] Optional<Value> m_value; // [[Value]]
Optional<DeprecatedFlyString> m_target; // [[Target]] // NOTE: We don't need the [[Target]] slot since control flow is handled in bytecode.
}; };
} }
@ -354,7 +351,7 @@ ThrowCompletionOr<Value> await(VM&, Value);
inline Completion normal_completion(Optional<Value> value) inline Completion normal_completion(Optional<Value> value)
{ {
// 1. Return Completion Record { [[Type]]: normal, [[Value]]: value, [[Target]]: empty }. // 1. Return Completion Record { [[Type]]: normal, [[Value]]: value, [[Target]]: empty }.
return { Completion::Type::Normal, move(value), {} }; return { Completion::Type::Normal, move(value) };
} }
// 6.2.4.2 ThrowCompletion ( value ), https://tc39.es/ecma262/#sec-throwcompletion // 6.2.4.2 ThrowCompletion ( value ), https://tc39.es/ecma262/#sec-throwcompletion

View file

@ -1247,7 +1247,7 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
if (declaration_result.is_throw_completion()) { if (declaration_result.is_throw_completion()) {
auto promise_capability = MUST(new_promise_capability(vm, realm.intrinsics().promise_constructor())); auto promise_capability = MUST(new_promise_capability(vm, realm.intrinsics().promise_constructor()));
MUST(call(vm, *promise_capability->reject(), js_undefined(), *declaration_result.throw_completion().value())); MUST(call(vm, *promise_capability->reject(), js_undefined(), *declaration_result.throw_completion().value()));
return Completion { Completion::Type::Return, promise_capability->promise(), {} }; return Completion { Completion::Type::Return, promise_capability->promise() };
} }
} }
@ -1261,11 +1261,11 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
// NOTE: Running the bytecode should eventually return a completion. // NOTE: Running the bytecode should eventually return a completion.
// Until it does, we assume "return" and include the undefined fallback from the call site. // Until it does, we assume "return" and include the undefined fallback from the call site.
if (m_kind == FunctionKind::Normal) if (m_kind == FunctionKind::Normal)
return { Completion::Type::Return, result.value_or(js_undefined()), {} }; return { Completion::Type::Return, result.value_or(js_undefined()) };
if (m_kind == FunctionKind::AsyncGenerator) { if (m_kind == FunctionKind::AsyncGenerator) {
auto async_generator_object = TRY(AsyncGenerator::create(realm, result, this, vm.running_execution_context().copy())); auto async_generator_object = TRY(AsyncGenerator::create(realm, result, this, vm.running_execution_context().copy()));
return { Completion::Type::Return, async_generator_object, {} }; return { Completion::Type::Return, async_generator_object };
} }
auto generator_object = TRY(GeneratorObject::create(realm, result, this, vm.running_execution_context().copy())); auto generator_object = TRY(GeneratorObject::create(realm, result, this, vm.running_execution_context().copy()));
@ -1273,10 +1273,10 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
// NOTE: Async functions are entirely transformed to generator functions, and wrapped in a custom driver that returns a promise // NOTE: Async functions are entirely transformed to generator functions, and wrapped in a custom driver that returns a promise
// See AwaitExpression::generate_bytecode() for the transformation. // See AwaitExpression::generate_bytecode() for the transformation.
if (m_kind == FunctionKind::Async) if (m_kind == FunctionKind::Async)
return { Completion::Type::Return, AsyncFunctionDriverWrapper::create(realm, generator_object), {} }; return { Completion::Type::Return, AsyncFunctionDriverWrapper::create(realm, generator_object) };
VERIFY(m_kind == FunctionKind::Generator); VERIFY(m_kind == FunctionKind::Generator);
return { Completion::Type::Return, generator_object, {} }; return { Completion::Type::Return, generator_object };
} }
void ECMAScriptFunctionObject::set_name(DeprecatedFlyString const& name) void ECMAScriptFunctionObject::set_name(DeprecatedFlyString const& name)

View file

@ -44,7 +44,7 @@ JS_DEFINE_NATIVE_FUNCTION(GeneratorPrototype::return_)
auto generator_object = TRY(typed_this_object(vm)); auto generator_object = TRY(typed_this_object(vm));
// 2. Let C be Completion Record { [[Type]]: return, [[Value]]: value, [[Target]]: empty }. // 2. Let C be Completion Record { [[Type]]: return, [[Value]]: value, [[Target]]: empty }.
auto completion = Completion(Completion::Type::Return, vm.argument(0), {}); auto completion = Completion(Completion::Type::Return, vm.argument(0));
// 3. Return ? GeneratorResumeAbrupt(g, C, empty). // 3. Return ? GeneratorResumeAbrupt(g, C, empty).
return generator_object->resume_abrupt(vm, completion, {}); return generator_object->resume_abrupt(vm, completion, {});

View file

@ -62,7 +62,7 @@ JS_DEFINE_NATIVE_FUNCTION(IteratorHelperPrototype::return_)
} }
// 5. Let C be Completion { [[Type]]: return, [[Value]]: undefined, [[Target]]: empty }. // 5. Let C be Completion { [[Type]]: return, [[Value]]: undefined, [[Target]]: empty }.
Completion completion { Completion::Type::Return, js_undefined(), {} }; Completion completion { Completion::Type::Return, js_undefined() };
// 6. Return ? GeneratorResumeAbrupt(O, C, "Iterator Helper"). // 6. Return ? GeneratorResumeAbrupt(O, C, "Iterator Helper").
return TRY(iterator->resume_abrupt(vm, move(completion), "Iterator Helper"sv)); return TRY(iterator->resume_abrupt(vm, move(completion), "Iterator Helper"sv));

View file

@ -91,7 +91,7 @@ JS::Completion ClassicScript::run(RethrowErrors rethrow_errors, JS::GCPtr<JS::En
// 5. If script's error to rethrow is not null, then set evaluationStatus to Completion { [[Type]]: throw, [[Value]]: script's error to rethrow, [[Target]]: empty }. // 5. If script's error to rethrow is not null, then set evaluationStatus to Completion { [[Type]]: throw, [[Value]]: script's error to rethrow, [[Target]]: empty }.
if (!error_to_rethrow().is_null()) { if (!error_to_rethrow().is_null()) {
evaluation_status = JS::Completion { JS::Completion::Type::Throw, error_to_rethrow(), {} }; evaluation_status = JS::Completion { JS::Completion::Type::Throw, error_to_rethrow() };
} else { } else {
auto timer = Core::ElapsedTimer::start_new(); auto timer = Core::ElapsedTimer::start_new();