ladybird/Libraries/LibJS/Runtime/ShadowRealm.h
Andreas Kling 4d92c4d71a LibJS: Skip initializing constant slots in ExecutionContext
Every function call allocates an ExecutionContext with a trailing array
of Values for registers, locals, constants, and arguments. Previously,
the constructor would initialize all slots to js_special_empty_value(),
but constant slots were then immediately overwritten by the interpreter
copying in values from the Executable before execution began.

To eliminate this redundant initialization, we rearrange the layout from
[registers | constants | locals] to [registers | locals | constants].
This groups registers and locals together at the front, allowing us to
initialize only those slots while leaving constant slots uninitialized
until they're populated with their actual values.

This reduces the per-call initialization cost from O(registers + locals
+ constants) to O(registers + locals).

Also tightens up the types involved (size_t -> u32) and adds VERIFYs to
guard against overflow when computing the combined slot counts, and to
ensure the total fits within the 29-bit operand index field.
2026-01-19 10:48:12 +01:00

42 lines
1.6 KiB
C++

/*
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/ExecutionContext.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/Realm.h>
namespace JS {
class ShadowRealm final : public Object {
JS_OBJECT(ShadowRealm, Object);
GC_DECLARE_ALLOCATOR(ShadowRealm);
public:
virtual ~ShadowRealm() override = default;
[[nodiscard]] Realm const& shadow_realm() const { return *m_shadow_realm; }
[[nodiscard]] Realm& shadow_realm() { return *m_shadow_realm; }
void set_shadow_realm(GC::Ref<Realm> realm) { m_shadow_realm = realm; }
private:
ShadowRealm(Object& prototype);
virtual void visit_edges(Visitor&) override;
// 3.5 Properties of ShadowRealm Instances, https://tc39.es/proposal-shadowrealm/#sec-properties-of-shadowrealm-instances
GC::Ptr<Realm> m_shadow_realm; // [[ShadowRealm]]
};
ThrowCompletionOr<void> copy_name_and_length(VM&, FunctionObject& function, FunctionObject& target, Optional<StringView> prefix = {}, Optional<unsigned> arg_count = {});
ThrowCompletionOr<Value> perform_shadow_realm_eval(VM&, Value source, Realm& caller_realm, Realm& eval_realm);
ThrowCompletionOr<Value> shadow_realm_import_value(VM&, Utf16FlyString specifier_string, Utf16FlyString export_name_string, Realm& caller_realm, Realm& eval_realm);
ThrowCompletionOr<Value> get_wrapped_value(VM&, Realm& caller_realm, Value);
NonnullOwnPtr<ExecutionContext> get_shadow_realm_context(Realm& shadow_realm, bool strict_eval, u32 registers_and_locals_count, u32 constants_count);
}