LibJS: Allow GetById to cache getters

1.25x speed-up on this microbenchmark:

    let o = { get x() { return 1; } };
    for (let i = 0; i < 10_000_000; ++i)
        o.x;

I looked into this because I noticed getter invocation when profiling
long-running WPT tests. We already had the mechanism for non-getter
properties, and the change to support getters turned out to be trivial.
This commit is contained in:
Andreas Kling 2024-10-17 20:29:07 +02:00 committed by Andreas Kling
commit 3c5819a6d2
Notes: github-actions[bot] 2024-10-17 20:07:21 +00:00
2 changed files with 38 additions and 22 deletions

View file

@ -15,6 +15,7 @@
#include <LibJS/Bytecode/Label.h>
#include <LibJS/Bytecode/Op.h>
#include <LibJS/Runtime/AbstractOperations.h>
#include <LibJS/Runtime/Accessor.h>
#include <LibJS/Runtime/Array.h>
#include <LibJS/Runtime/BigInt.h>
#include <LibJS/Runtime/DeclarativeEnvironment.h>
@ -991,11 +992,18 @@ inline ThrowCompletionOr<Value> get_by_id(VM& vm, Optional<IdentifierTableIndex>
return false;
return true;
}();
if (can_use_cache)
return cache.prototype->get_direct(cache.property_offset.value());
if (can_use_cache) {
auto value = cache.prototype->get_direct(cache.property_offset.value());
if (value.is_accessor())
return TRY(call(vm, value.as_accessor().getter(), this_value));
return value;
}
} else if (&shape == cache.shape) {
// OPTIMIZATION: If the shape of the object hasn't changed, we can use the cached property offset.
return base_obj->get_direct(cache.property_offset.value());
auto value = base_obj->get_direct(cache.property_offset.value());
if (value.is_accessor())
return TRY(call(vm, value.as_accessor().getter(), this_value));
return value;
}
CacheablePropertyMetadata cacheable_metadata;
@ -1103,7 +1111,9 @@ inline ThrowCompletionOr<Value> get_global(Interpreter& interpreter, IdentifierT
// OPTIMIZATION: For global var bindings, if the shape of the global object hasn't changed,
// we can use the cached property offset.
if (&shape == cache.shape) {
return binding_object.get_direct(cache.property_offset.value());
auto value = binding_object.get_direct(cache.property_offset.value());
if (value.is_accessor())
return TRY(call(vm, value.as_accessor().getter(), js_undefined()));
}
// OPTIMIZATION: For global lexical bindings, if the global declarative environment hasn't changed,