mirror of
https://github.com/fergalmoran/ladybird.git
synced 2026-01-06 16:45:03 +00:00
LibJS: Combine DeclarativeEnvironment's bindings and names into one list
This reduces the size of the DeclarativeEnvironment from 72 bytes to 48
bytes. This savings helps in the context of nested for-loops which use
'let' to bind the initial variable declarations. In this case, the spec
dicates we create a new environment for each loop iteration by way of
the CreatePerIterationEnvironment AO.
In particular, test262's generated RegExp tests contains many loops of
the form:
for (let i = 0; i < a_number_on_the_order_of_10; ++i)
for (let j = 0; j < a_number_on_the_order_of_10_thousand; ++j)
This results in creating hundreds of thousands of environments.
This commit is contained in:
committed by
Linus Groh
parent
8d784310e0
commit
533170fbfa
@@ -37,7 +37,7 @@ void DeclarativeEnvironment::visit_edges(Visitor& visitor)
|
||||
// 9.1.1.1.1 HasBinding ( N ), https://tc39.es/ecma262/#sec-declarative-environment-records-hasbinding-n
|
||||
ThrowCompletionOr<bool> DeclarativeEnvironment::has_binding(FlyString const& name, Optional<size_t>* out_index) const
|
||||
{
|
||||
auto index = m_names.find_first_index(name);
|
||||
auto index = find_binding_index(name);
|
||||
if (!index.has_value())
|
||||
return false;
|
||||
if (!is_permanently_screwed_by_eval() && out_index)
|
||||
@@ -50,16 +50,16 @@ ThrowCompletionOr<void> DeclarativeEnvironment::create_mutable_binding(GlobalObj
|
||||
{
|
||||
// 2. Create a mutable binding in envRec for N and record that it is uninitialized. If D is true, record that the newly created binding may be deleted by a subsequent DeleteBinding call.
|
||||
m_bindings.append(Binding {
|
||||
.name = name,
|
||||
.value = {},
|
||||
.strict = false,
|
||||
.mutable_ = true,
|
||||
.can_be_deleted = can_be_deleted,
|
||||
.initialized = false,
|
||||
});
|
||||
m_names.append(name);
|
||||
|
||||
// 1. Assert: envRec does not already have a binding for N.
|
||||
// NOTE: We skip this to avoid O(n) traversal of m_names.
|
||||
// NOTE: We skip this to avoid O(n) traversal of m_bindings.
|
||||
|
||||
// 3. Return NormalCompletion(empty).
|
||||
return {};
|
||||
@@ -70,16 +70,16 @@ ThrowCompletionOr<void> DeclarativeEnvironment::create_immutable_binding(GlobalO
|
||||
{
|
||||
// 2. Create an immutable binding in envRec for N and record that it is uninitialized. If S is true, record that the newly created binding is a strict binding.
|
||||
m_bindings.append(Binding {
|
||||
.name = name,
|
||||
.value = {},
|
||||
.strict = strict,
|
||||
.mutable_ = false,
|
||||
.can_be_deleted = false,
|
||||
.initialized = false,
|
||||
});
|
||||
m_names.append(name);
|
||||
|
||||
// 1. Assert: envRec does not already have a binding for N.
|
||||
// NOTE: We skip this to avoid O(n) traversal of m_names.
|
||||
// NOTE: We skip this to avoid O(n) traversal of m_bindings.
|
||||
|
||||
// 3. Return NormalCompletion(empty).
|
||||
return {};
|
||||
@@ -88,7 +88,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::create_immutable_binding(GlobalO
|
||||
// 9.1.1.1.4 InitializeBinding ( N, V ), https://tc39.es/ecma262/#sec-declarative-environment-records-initializebinding-n-v
|
||||
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding(GlobalObject&, FlyString const& name, Value value)
|
||||
{
|
||||
auto index = m_names.find_first_index(name);
|
||||
auto index = find_binding_index(name);
|
||||
VERIFY(index.has_value());
|
||||
auto& binding = m_bindings[*index];
|
||||
|
||||
@@ -109,7 +109,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::initialize_binding(GlobalObject&
|
||||
ThrowCompletionOr<void> DeclarativeEnvironment::set_mutable_binding(GlobalObject& global_object, FlyString const& name, Value value, bool strict)
|
||||
{
|
||||
// 1. If envRec does not have a binding for N, then
|
||||
auto index = m_names.find_first_index(name);
|
||||
auto index = find_binding_index(name);
|
||||
if (!index.has_value()) {
|
||||
// a. If S is true, throw a ReferenceError exception.
|
||||
if (strict)
|
||||
@@ -139,7 +139,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::set_mutable_binding_direct(Globa
|
||||
strict = true;
|
||||
|
||||
if (!binding.initialized)
|
||||
return vm().throw_completion<ReferenceError>(global_object, ErrorType::BindingNotInitialized, m_names[index]);
|
||||
return vm().throw_completion<ReferenceError>(global_object, ErrorType::BindingNotInitialized, binding.name);
|
||||
|
||||
if (binding.mutable_) {
|
||||
binding.value = value;
|
||||
@@ -155,7 +155,7 @@ ThrowCompletionOr<void> DeclarativeEnvironment::set_mutable_binding_direct(Globa
|
||||
ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value(GlobalObject& global_object, FlyString const& name, bool strict)
|
||||
{
|
||||
// 1. Assert: envRec has a binding for N.
|
||||
auto index = m_names.find_first_index(name);
|
||||
auto index = find_binding_index(name);
|
||||
VERIFY(index.has_value());
|
||||
|
||||
// 2-3. (extracted into a non-standard function below)
|
||||
@@ -168,7 +168,7 @@ ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value_direct(Global
|
||||
|
||||
// 2. If the binding for N in envRec is an uninitialized binding, throw a ReferenceError exception.
|
||||
if (!binding.initialized)
|
||||
return vm().throw_completion<ReferenceError>(global_object, ErrorType::BindingNotInitialized, m_names[index]);
|
||||
return vm().throw_completion<ReferenceError>(global_object, ErrorType::BindingNotInitialized, binding.name);
|
||||
|
||||
// 3. Return the value currently bound to N in envRec.
|
||||
return binding.value;
|
||||
@@ -178,7 +178,7 @@ ThrowCompletionOr<Value> DeclarativeEnvironment::get_binding_value_direct(Global
|
||||
ThrowCompletionOr<bool> DeclarativeEnvironment::delete_binding(GlobalObject&, FlyString const& name)
|
||||
{
|
||||
// 1. Assert: envRec has a binding for the name that is the value of N.
|
||||
auto index = m_names.find_first_index(name);
|
||||
auto index = find_binding_index(name);
|
||||
VERIFY(index.has_value());
|
||||
|
||||
auto& binding = m_bindings[*index];
|
||||
@@ -188,9 +188,8 @@ ThrowCompletionOr<bool> DeclarativeEnvironment::delete_binding(GlobalObject&, Fl
|
||||
return false;
|
||||
|
||||
// 3. Remove the binding for N from envRec.
|
||||
// NOTE: We keep the entries in m_bindings and m_names to avoid disturbing indices.
|
||||
// NOTE: We keep the entries in m_bindings to avoid disturbing indices.
|
||||
binding = {};
|
||||
m_names[*index] = {};
|
||||
|
||||
// 4. Return true.
|
||||
return true;
|
||||
@@ -198,7 +197,7 @@ ThrowCompletionOr<bool> DeclarativeEnvironment::delete_binding(GlobalObject&, Fl
|
||||
|
||||
ThrowCompletionOr<void> DeclarativeEnvironment::initialize_or_set_mutable_binding(GlobalObject& global_object, FlyString const& name, Value value)
|
||||
{
|
||||
auto index = m_names.find_first_index(name);
|
||||
auto index = find_binding_index(name);
|
||||
VERIFY(index.has_value());
|
||||
auto& binding = m_bindings[*index];
|
||||
if (!binding.initialized)
|
||||
|
||||
Reference in New Issue
Block a user