mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 05:08:13 +00:00
LibJS/Bytecode: Add Call opcode for fixed-argument-count calls
This avoids the overhead of allocating a new Array on every function call, saving a substantial amount of time and avoiding GC thrash. This patch only makes use of Op::Call in CallExpression. There are other places we should codegen this op. We should also do the same for super expression calls. ~5% speed-up on Kraken/stanford-crypto-ccm.js
This commit is contained in:
parent
7eb87dec9f
commit
c37b204ce1
5 changed files with 135 additions and 41 deletions
|
@ -1463,8 +1463,6 @@ Bytecode::CodeGenerationErrorOr<void> CallExpression::generate_bytecode(Bytecode
|
|||
generator.emit<Bytecode::Op::Store>(callee_reg);
|
||||
}
|
||||
|
||||
TRY(arguments_to_array_for_call(generator, arguments()));
|
||||
|
||||
Bytecode::Op::CallType call_type;
|
||||
if (is<NewExpression>(*this)) {
|
||||
call_type = Bytecode::Op::CallType::Construct;
|
||||
|
@ -1478,7 +1476,26 @@ Bytecode::CodeGenerationErrorOr<void> CallExpression::generate_bytecode(Bytecode
|
|||
if (auto expression_string = this->expression_string(); expression_string.has_value())
|
||||
expression_string_index = generator.intern_string(expression_string.release_value());
|
||||
|
||||
generator.emit<Bytecode::Op::CallWithArgumentArray>(call_type, callee_reg, this_reg, expression_string_index);
|
||||
bool has_spread = any_of(arguments(), [](auto& argument) { return argument.is_spread; });
|
||||
|
||||
if (has_spread) {
|
||||
TRY(arguments_to_array_for_call(generator, arguments()));
|
||||
generator.emit<Bytecode::Op::CallWithArgumentArray>(call_type, callee_reg, this_reg, expression_string_index);
|
||||
} else {
|
||||
Optional<Bytecode::Register> first_argument_reg {};
|
||||
for (size_t i = 0; i < arguments().size(); ++i) {
|
||||
auto reg = generator.allocate_register();
|
||||
if (!first_argument_reg.has_value())
|
||||
first_argument_reg = reg;
|
||||
}
|
||||
u32 register_offset = 0;
|
||||
for (auto const& argument : arguments()) {
|
||||
TRY(argument.value->generate_bytecode(generator));
|
||||
generator.emit<Bytecode::Op::Store>(Bytecode::Register { first_argument_reg.value().index() + register_offset });
|
||||
register_offset += 1;
|
||||
}
|
||||
generator.emit<Bytecode::Op::Call>(call_type, callee_reg, this_reg, first_argument_reg.value_or(Bytecode::Register { 0 }), arguments().size(), expression_string_index);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue