diff options
author | Linus Groh <mail@linusgroh.de> | 2021-10-05 08:44:58 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-10-05 10:15:14 +0100 |
commit | 4fa57480932965874146b771e5078460ee071655 (patch) | |
tree | 3b746b7b95b1580f22b27548e042ba00b1148f53 /Userland/Libraries/LibJS/Bytecode/Op.cpp | |
parent | fcb355f193b6f0a9bb9afe7f5adb116ef0883dd2 (diff) | |
download | serenity-4fa57480932965874146b771e5078460ee071655.zip |
LibJS: Add an optimization to avoid needless arguments object creation
This gives FunctionNode a "might need arguments object" boolean flag and
sets it based on the simplest possible heuristic for this: if we
encounter an identifier called "arguments" or "eval" up to the next
(nested) function declaration or expression, we won't need an arguments
object. Otherwise, we *might* need one - the final decision is made in
the FunctionDeclarationInstantiation AO.
Now, this is obviously not perfect. Even if you avoid eval, something
like `foo.arguments` will still trigger a false positive - but it's a
start and already massively cuts down on needlessly allocated objects,
especially in real-world code that is often minified, and so a full
"arguments" identifier will be an actual arguments object more often
than not.
To illustrate the actual impact of this change, here's the number of
allocated arguments objects during a full test-js run:
Before:
- Unmapped arguments objects: 78765
- Mapped arguments objects: 2455
After:
- Unmapped arguments objects: 18
- Mapped arguments objects: 37
This results in a ~5% speedup of test-js on my Linux host machine, and
about 3.5% on i686 Serenity in QEMU (warm runs, average of 5).
The following microbenchmark (calling an empty function 1M times) runs
25% faster on Linux and 45% on Serenity:
function foo() {}
for (var i = 0; i < 1_000_000; ++i)
foo();
test262 reports no changes in either direction, apart from a speedup :^)
Diffstat (limited to 'Userland/Libraries/LibJS/Bytecode/Op.cpp')
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.cpp | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 99f9c718ac..ce4ca46364 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -334,7 +334,7 @@ void Call::execute_impl(Bytecode::Interpreter& interpreter) const void NewFunction::execute_impl(Bytecode::Interpreter& interpreter) const { auto& vm = interpreter.vm(); - interpreter.accumulator() = ECMAScriptFunctionObject::create(interpreter.global_object(), m_function_node.name(), m_function_node.body(), m_function_node.parameters(), m_function_node.function_length(), vm.lexical_environment(), m_function_node.kind(), m_function_node.is_strict_mode(), m_function_node.is_arrow_function()); + interpreter.accumulator() = ECMAScriptFunctionObject::create(interpreter.global_object(), m_function_node.name(), m_function_node.body(), m_function_node.parameters(), m_function_node.function_length(), vm.lexical_environment(), m_function_node.kind(), m_function_node.is_strict_mode(), m_function_node.might_need_arguments_object(), m_function_node.is_arrow_function()); } void Return::execute_impl(Bytecode::Interpreter& interpreter) const |