mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-09 11:06:10 +00:00
LibJS: Optimize Function.prototype.apply()
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macOS, macos-15, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, Linux, blacksmith-16vcpu-ubuntu-2404, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, Linux, blacksmith-16vcpu-ubuntu-2404, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, Linux, blacksmith-16vcpu-ubuntu-2404, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macOS, macOS-arm64, macos-15) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, Linux, Linux-x86_64, blacksmith-8vcpu-ubuntu-2404) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
Some checks are pending
CI / Lagom (arm64, Sanitizer_CI, false, macOS, macos-15, Clang) (push) Waiting to run
CI / Lagom (x86_64, Fuzzers_CI, false, Linux, blacksmith-16vcpu-ubuntu-2404, Clang) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, false, Linux, blacksmith-16vcpu-ubuntu-2404, GNU) (push) Waiting to run
CI / Lagom (x86_64, Sanitizer_CI, true, Linux, blacksmith-16vcpu-ubuntu-2404, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (arm64, macOS, macOS-arm64, macos-15) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (x86_64, Linux, Linux-x86_64, blacksmith-8vcpu-ubuntu-2404) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Label PRs with merge conflicts / auto-labeler (push) Waiting to run
Push notes / build (push) Waiting to run
...by avoiding `CreateListFromArrayLike` in cases when we could directly use elements of underlying object's indexed properties storage. Makes this program go 2.1x faster: ```js function target(a, b, c) { return a + b + c; } const args = [1, 2, 3]; let result = 0; (function() { for (let i = 0; i < 10_000_000; i++) { result += target.apply(null, args); } })(); ```
This commit is contained in:
parent
3f7c4dd5f6
commit
1274f4e2f7
Notes:
github-actions[bot]
2025-06-03 15:17:07 +00:00
Author: https://github.com/kalenikaliaksandr
Commit: 1274f4e2f7
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4967
2 changed files with 26 additions and 0 deletions
|
@ -70,6 +70,22 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::apply)
|
|||
return TRY(JS::call(vm, function, this_arg));
|
||||
}
|
||||
|
||||
// NOTE: Do the check performed by CreateListFromArrayLike here, so we could avoid branching in optimized code path.
|
||||
if (!arg_array.is_object())
|
||||
return vm.throw_completion<TypeError>(ErrorType::NotAnObject, arg_array.to_string_without_side_effects());
|
||||
|
||||
// OPTIMIZATION: If argArray has a simple indexed storage without holes and doesn't interfere with indexed property access,
|
||||
// we can skip CreateListFromArrayLike and directly use the storage elements.
|
||||
auto& arg_array_object = arg_array.as_object();
|
||||
auto* storage = arg_array_object.indexed_properties().storage();
|
||||
if (!arg_array_object.may_interfere_with_indexed_property_access() && storage && storage->is_simple_storage()) {
|
||||
auto length = TRY(length_of_array_like(vm, arg_array_object));
|
||||
auto const* simple_storage = static_cast<SimpleIndexedPropertyStorage*>(storage);
|
||||
auto storage_elements = simple_storage->elements().span();
|
||||
if (!simple_storage->has_empty_elements() && storage_elements.size() >= length)
|
||||
return TRY(JS::call(vm, function, this_arg, storage_elements.slice(0, length)));
|
||||
}
|
||||
|
||||
// 4. Let argList be ? CreateListFromArrayLike(argArray).
|
||||
auto arguments = TRY(create_list_from_array_like(vm, arg_array));
|
||||
|
||||
|
|
|
@ -50,6 +50,16 @@ test("basic functionality", () => {
|
|||
expect((() => this).apply("foo")).toBe(globalThis);
|
||||
});
|
||||
|
||||
test("array with holes", () => {
|
||||
function target(a, b, c) {
|
||||
return a + b + c;
|
||||
}
|
||||
|
||||
const args = [1, , 3];
|
||||
const result = target.apply(null, args);
|
||||
expect(result).toBe(NaN);
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
test("does not accept non-function values", () => {
|
||||
expect(() => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue