1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-17 00:45:07 +00:00
serenity/Userland/Libraries/LibJS/Runtime/DeclarativeEnvironment.h
Andreas Kling ff60e8ffc6 LibJS: Use Vector instead of HashMap in DeclarativeEnvironment
Constructing the HashMap in DeclarativeEnvironment was by far the most
expensive thing when making JavaScript function calls.

As it turns out, we don't really need this to be a HashMap in the first
place, as lookups are cached (by EnvironmentCoordinate) after the first
access, so after that we were not even looking in the HashMap, going
directly to the bindings Vector instead.

This reduces function_declaration_instantiation() from 16% to 9% when
idling in "Biolab Disaster". It also reduces has_binding() from 3% to
1% on the same content.

With these changes, we now actually get to idle a little bit between
game frames on my machine. :^)
2022-03-07 14:49:21 +01:00

63 lines
2.5 KiB
C++

/*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/FlyString.h>
#include <AK/HashMap.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/Environment.h>
#include <LibJS/Runtime/Value.h>
namespace JS {
class DeclarativeEnvironment : public Environment {
JS_ENVIRONMENT(DeclarativeEnvironment, Environment);
public:
DeclarativeEnvironment();
explicit DeclarativeEnvironment(Environment* parent_scope);
virtual ~DeclarativeEnvironment() override;
virtual ThrowCompletionOr<bool> has_binding(FlyString const& name, Optional<size_t>* = nullptr) const override;
virtual ThrowCompletionOr<void> create_mutable_binding(GlobalObject&, FlyString const& name, bool can_be_deleted) override;
virtual ThrowCompletionOr<void> create_immutable_binding(GlobalObject&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<void> initialize_binding(GlobalObject&, FlyString const& name, Value) override;
virtual ThrowCompletionOr<void> set_mutable_binding(GlobalObject&, FlyString const& name, Value, bool strict) override;
virtual ThrowCompletionOr<Value> get_binding_value(GlobalObject&, FlyString const& name, bool strict) override;
virtual ThrowCompletionOr<bool> delete_binding(GlobalObject&, FlyString const& name) override;
void initialize_or_set_mutable_binding(Badge<ScopeNode>, GlobalObject& global_object, FlyString const& name, Value value);
ThrowCompletionOr<void> initialize_or_set_mutable_binding(GlobalObject& global_object, FlyString const& name, Value value);
// This is not a method defined in the spec! Do not use this in any LibJS (or other spec related) code.
[[nodiscard]] Vector<FlyString> const& bindings() const { return m_names; }
ThrowCompletionOr<Value> get_binding_value_direct(GlobalObject&, size_t index, bool strict);
ThrowCompletionOr<void> set_mutable_binding_direct(GlobalObject&, size_t index, Value, bool strict);
protected:
virtual void visit_edges(Visitor&) override;
private:
virtual bool is_declarative_environment() const override { return true; }
struct Binding {
Value value;
bool strict { false };
bool mutable_ { false };
bool can_be_deleted { false };
bool initialized { false };
};
Vector<FlyString> m_names;
Vector<Binding> m_bindings;
};
template<>
inline bool Environment::fast_is<DeclarativeEnvironment>() const { return is_declarative_environment(); }
}