mirror of
https://github.com/RGBCube/serenity
synced 2025-05-24 05:55:06 +00:00
LibJS: Cache bytecode executables on the corresponding AST nodes
This greatly reduces the number of compilations necessary when functions declaring local functions are re-executed. For example Octane/typescript.js goes from 58080 bytecode executables to 960.
This commit is contained in:
parent
e346331424
commit
ae8c98104a
2 changed files with 21 additions and 5 deletions
|
@ -16,6 +16,7 @@
|
||||||
#include <AK/Variant.h>
|
#include <AK/Variant.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <LibJS/Bytecode/CodeGenerationError.h>
|
#include <LibJS/Bytecode/CodeGenerationError.h>
|
||||||
|
#include <LibJS/Bytecode/Executable.h>
|
||||||
#include <LibJS/Bytecode/IdentifierTable.h>
|
#include <LibJS/Bytecode/IdentifierTable.h>
|
||||||
#include <LibJS/Forward.h>
|
#include <LibJS/Forward.h>
|
||||||
#include <LibJS/Heap/Handle.h>
|
#include <LibJS/Heap/Handle.h>
|
||||||
|
@ -153,6 +154,12 @@ public:
|
||||||
: ASTNode(move(source_range))
|
: ASTNode(move(source_range))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bytecode::Executable const* bytecode_executable() const { return m_bytecode_executable; }
|
||||||
|
void set_bytecode_executable(Bytecode::Executable const* bytecode_executable) { m_bytecode_executable = bytecode_executable; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
RefPtr<Bytecode::Executable> m_bytecode_executable;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 14.13 Labelled Statements, https://tc39.es/ecma262/#sec-labelled-statements
|
// 14.13 Labelled Statements, https://tc39.es/ecma262/#sec-labelled-statements
|
||||||
|
@ -678,6 +685,7 @@ struct FunctionParameter {
|
||||||
Variant<NonnullRefPtr<Identifier const>, NonnullRefPtr<BindingPattern const>> binding;
|
Variant<NonnullRefPtr<Identifier const>, NonnullRefPtr<BindingPattern const>> binding;
|
||||||
RefPtr<Expression const> default_value;
|
RefPtr<Expression const> default_value;
|
||||||
bool is_rest { false };
|
bool is_rest { false };
|
||||||
|
RefPtr<Bytecode::Executable> bytecode_executable {};
|
||||||
};
|
};
|
||||||
|
|
||||||
class FunctionNode {
|
class FunctionNode {
|
||||||
|
@ -721,7 +729,7 @@ private:
|
||||||
DeprecatedString m_source_text;
|
DeprecatedString m_source_text;
|
||||||
NonnullRefPtr<Statement const> m_body;
|
NonnullRefPtr<Statement const> m_body;
|
||||||
Vector<FunctionParameter> const m_parameters;
|
Vector<FunctionParameter> const m_parameters;
|
||||||
const i32 m_function_length;
|
i32 const m_function_length;
|
||||||
FunctionKind m_kind;
|
FunctionKind m_kind;
|
||||||
bool m_is_strict_mode : 1 { false };
|
bool m_is_strict_mode : 1 { false };
|
||||||
bool m_might_need_arguments_object : 1 { false };
|
bool m_might_need_arguments_object : 1 { false };
|
||||||
|
|
|
@ -1174,8 +1174,13 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
|
||||||
for (auto& parameter : m_formal_parameters) {
|
for (auto& parameter : m_formal_parameters) {
|
||||||
if (!parameter.default_value)
|
if (!parameter.default_value)
|
||||||
continue;
|
continue;
|
||||||
auto executable = TRY(Bytecode::compile(vm, *parameter.default_value, FunctionKind::Normal, DeprecatedString::formatted("default parameter #{} for {}", default_parameter_index, m_name)));
|
if (parameter.bytecode_executable.is_null()) {
|
||||||
|
auto executable = TRY(Bytecode::compile(vm, *parameter.default_value, FunctionKind::Normal, DeprecatedString::formatted("default parameter #{} for {}", default_parameter_index++, m_name)));
|
||||||
|
const_cast<FunctionParameter&>(parameter).bytecode_executable = executable;
|
||||||
m_default_parameter_bytecode_executables.append(move(executable));
|
m_default_parameter_bytecode_executables.append(move(executable));
|
||||||
|
} else {
|
||||||
|
m_default_parameter_bytecode_executables.append(*parameter.bytecode_executable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1186,8 +1191,11 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
|
||||||
return declaration_result.release_error();
|
return declaration_result.release_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_bytecode_executable)
|
if (!m_bytecode_executable) {
|
||||||
m_bytecode_executable = TRY(Bytecode::compile(vm, *m_ecmascript_code, m_kind, m_name));
|
if (!m_ecmascript_code->bytecode_executable())
|
||||||
|
const_cast<Statement&>(*m_ecmascript_code).set_bytecode_executable(TRY(Bytecode::compile(vm, *m_ecmascript_code, m_kind, m_name)));
|
||||||
|
m_bytecode_executable = m_ecmascript_code->bytecode_executable();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_kind == FunctionKind::Async) {
|
if (m_kind == FunctionKind::Async) {
|
||||||
if (declaration_result.is_throw_completion()) {
|
if (declaration_result.is_throw_completion()) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue