LibJS: Shrink Identifier's environment coordinate cache

This patch does two things:

- We now use u32 instead of size_t for the hops and index fields
  in EnvironmentCoordinate. This means we're limited to an environment
  nesting level and variable count of 4Gs respectively.

- Instead of wrapping it in an Optional, EnvironmentCoordinate now has
  a custom valid/invalid state using a magic marker value.

These two changes reduce the size of Identifier by 16 bytes. :^)
This commit is contained in:
Andreas Kling 2022-11-21 18:01:22 +01:00
parent 76f438eb3e
commit 0f1f925532
Notes: sideshowbarker 2024-07-17 08:43:11 +09:00
4 changed files with 16 additions and 10 deletions

View file

@ -1387,13 +1387,13 @@ ThrowCompletionOr<Reference> Expression::to_reference(Interpreter&) const
ThrowCompletionOr<Reference> Identifier::to_reference(Interpreter& interpreter) const
{
if (m_cached_environment_coordinate.has_value()) {
if (m_cached_environment_coordinate.is_valid()) {
Environment* environment = nullptr;
if (m_cached_environment_coordinate->index == EnvironmentCoordinate::global_marker) {
if (m_cached_environment_coordinate.index == EnvironmentCoordinate::global_marker) {
environment = &interpreter.vm().current_realm()->global_environment();
} else {
environment = interpreter.vm().running_execution_context().lexical_environment;
for (size_t i = 0; i < m_cached_environment_coordinate->hops; ++i)
for (size_t i = 0; i < m_cached_environment_coordinate.hops; ++i)
environment = environment->outer_environment();
VERIFY(environment);
VERIFY(environment->is_declarative_environment());
@ -1406,7 +1406,7 @@ ThrowCompletionOr<Reference> Identifier::to_reference(Interpreter& interpreter)
auto reference = TRY(interpreter.vm().resolve_binding(string()));
if (reference.environment_coordinate().has_value())
m_cached_environment_coordinate = reference.environment_coordinate();
m_cached_environment_coordinate = reference.environment_coordinate().value();
return reference;
}

View file

@ -1222,7 +1222,7 @@ private:
virtual bool is_identifier() const override { return true; }
FlyString m_string;
mutable Optional<EnvironmentCoordinate> m_cached_environment_coordinate;
mutable EnvironmentCoordinate m_cached_environment_coordinate;
};
class PrivateIdentifier final : public Expression {

View file

@ -12,10 +12,13 @@
namespace JS {
struct EnvironmentCoordinate {
size_t hops { 0 };
size_t index { 0 };
u32 hops { invalid_marker };
u32 index { invalid_marker };
static constexpr size_t global_marker = 0xffffffff;
bool is_valid() const { return hops != invalid_marker && index != invalid_marker; }
static constexpr u32 global_marker = 0xffffffff;
static constexpr u32 invalid_marker = 0xfffffffe;
};
}

View file

@ -565,8 +565,11 @@ ThrowCompletionOr<Reference> VM::get_identifier_reference(Environment* environme
// Note: This is an optimization for looking up the same reference.
Optional<EnvironmentCoordinate> environment_coordinate;
if (index.has_value())
environment_coordinate = EnvironmentCoordinate { .hops = hops, .index = index.value() };
if (index.has_value()) {
VERIFY(hops <= NumericLimits<u32>::max());
VERIFY(index.value() <= NumericLimits<u32>::max());
environment_coordinate = EnvironmentCoordinate { .hops = static_cast<u32>(hops), .index = static_cast<u32>(index.value()) };
}
// 3. If exists is true, then
if (exists) {