1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 08:57:34 +00:00

LibJS/JIT: Add fastpath for set variable

This commit is contained in:
Stephan Vedder 2023-11-16 07:13:35 +01:00 committed by Andreas Kling
parent b3cbe0fdb9
commit 84eecbb10e
8 changed files with 148 additions and 12 deletions

View file

@ -1080,7 +1080,7 @@ Bytecode::CodeGenerationErrorOr<void> FunctionDeclaration::generate_bytecode(Byt
Bytecode::Generator::SourceLocationScope scope(generator, *this);
auto index = generator.intern_identifier(name());
generator.emit<Bytecode::Op::GetVariable>(index, generator.next_environment_variable_cache());
generator.emit<Bytecode::Op::SetVariable>(index, Bytecode::Op::SetVariable::InitializationMode::Set, Bytecode::Op::EnvironmentMode::Var);
generator.emit<Bytecode::Op::SetVariable>(index, generator.next_environment_variable_cache(), Bytecode::Op::SetVariable::InitializationMode::Set, Bytecode::Op::EnvironmentMode::Var);
}
return {};
}
@ -1101,7 +1101,7 @@ Bytecode::CodeGenerationErrorOr<void> FunctionExpression::generate_bytecode_with
generator.emit_new_function(*this, lhs_name);
if (has_name) {
generator.emit<Bytecode::Op::SetVariable>(*name_identifier, Bytecode::Op::SetVariable::InitializationMode::Initialize, Bytecode::Op::EnvironmentMode::Lexical);
generator.emit<Bytecode::Op::SetVariable>(*name_identifier, generator.next_environment_variable_cache(), Bytecode::Op::SetVariable::InitializationMode::Initialize, Bytecode::Op::EnvironmentMode::Lexical);
generator.end_variable_scope();
}
@ -2368,7 +2368,7 @@ Bytecode::CodeGenerationErrorOr<void> TryStatement::generate_bytecode(Bytecode::
did_create_variable_scope_for_catch_clause = true;
auto parameter_identifier = generator.intern_identifier(parameter);
generator.emit<Bytecode::Op::CreateVariable>(parameter_identifier, Bytecode::Op::EnvironmentMode::Lexical, false);
generator.emit<Bytecode::Op::SetVariable>(parameter_identifier, Bytecode::Op::SetVariable::InitializationMode::Initialize);
generator.emit<Bytecode::Op::SetVariable>(parameter_identifier, generator.next_environment_variable_cache(), Bytecode::Op::SetVariable::InitializationMode::Initialize);
}
return {};
},
@ -3196,7 +3196,7 @@ Bytecode::CodeGenerationErrorOr<void> ExportStatement::generate_bytecode(Bytecod
TRY(generator.emit_named_evaluation_if_anonymous_function(static_cast<ClassExpression const&>(*m_statement), generator.intern_identifier("default"sv)));
if (!static_cast<ClassExpression const&>(*m_statement).has_name())
generator.emit<Bytecode::Op::SetVariable>(generator.intern_identifier(ExportStatement::local_name_for_default), Bytecode::Op::SetVariable::InitializationMode::Initialize);
generator.emit<Bytecode::Op::SetVariable>(generator.intern_identifier(ExportStatement::local_name_for_default), generator.next_environment_variable_cache(), Bytecode::Op::SetVariable::InitializationMode::Initialize);
return {};
}
@ -3204,7 +3204,7 @@ Bytecode::CodeGenerationErrorOr<void> ExportStatement::generate_bytecode(Bytecod
// ExportDeclaration : export default AssignmentExpression ;
VERIFY(is<Expression>(*m_statement));
TRY(generator.emit_named_evaluation_if_anonymous_function(static_cast<Expression const&>(*m_statement), generator.intern_identifier("default"sv)));
generator.emit<Bytecode::Op::SetVariable>(generator.intern_identifier(ExportStatement::local_name_for_default), Bytecode::Op::SetVariable::InitializationMode::Initialize);
generator.emit<Bytecode::Op::SetVariable>(generator.intern_identifier(ExportStatement::local_name_for_default), generator.next_environment_variable_cache(), Bytecode::Op::SetVariable::InitializationMode::Initialize);
return {};
}

View file

@ -264,10 +264,13 @@ ThrowCompletionOr<void> set_variable(
DeprecatedFlyString const& name,
Value value,
Op::EnvironmentMode mode,
Op::SetVariable::InitializationMode initialization_mode)
Op::SetVariable::InitializationMode initialization_mode,
EnvironmentVariableCache& cache)
{
auto environment = mode == Op::EnvironmentMode::Lexical ? vm.running_execution_context().lexical_environment : vm.running_execution_context().variable_environment;
auto reference = TRY(vm.resolve_binding(name, environment));
if (reference.environment_coordinate().has_value())
cache = reference.environment_coordinate();
switch (initialization_mode) {
case Op::SetVariable::InitializationMode::Initialize:
TRY(reference.initialize_referenced_binding(vm, value));

View file

@ -20,7 +20,7 @@ ThrowCompletionOr<void> put_by_property_key(VM&, Value base, Value this_value, V
ThrowCompletionOr<Value> perform_call(Interpreter&, Value this_value, Op::CallType, Value callee, MarkedVector<Value> argument_values);
ThrowCompletionOr<void> throw_if_needed_for_call(Interpreter&, Value callee, Op::CallType, Optional<StringTableIndex> const& expression_string);
ThrowCompletionOr<Value> typeof_variable(VM&, DeprecatedFlyString const&);
ThrowCompletionOr<void> set_variable(VM&, DeprecatedFlyString const&, Value, Op::EnvironmentMode, Op::SetVariable::InitializationMode);
ThrowCompletionOr<void> set_variable(VM&, DeprecatedFlyString const&, Value, Op::EnvironmentMode, Op::SetVariable::InitializationMode, EnvironmentVariableCache&);
Value new_function(VM&, FunctionExpression const&, Optional<IdentifierTableIndex> const& lhs_name, Optional<Register> const& home_object);
ThrowCompletionOr<void> put_by_value(VM&, Value base, Value property_key_value, Value value, Op::PropertyKind);
ThrowCompletionOr<Value> get_variable(Bytecode::Interpreter&, DeprecatedFlyString const& name, EnvironmentVariableCache&);

View file

@ -414,7 +414,7 @@ void Generator::emit_set_variable(JS::Identifier const& identifier, Bytecode::Op
if (identifier.is_local()) {
emit<Bytecode::Op::SetLocal>(identifier.local_variable_index());
} else {
emit<Bytecode::Op::SetVariable>(intern_identifier(identifier.string()), initialization_mode, mode);
emit<Bytecode::Op::SetVariable>(intern_identifier(identifier.string()), next_environment_variable_cache(), initialization_mode, mode);
}
}

View file

@ -780,7 +780,12 @@ ThrowCompletionOr<void> SetVariable::execute_impl(Bytecode::Interpreter& interpr
{
auto& vm = interpreter.vm();
auto const& name = interpreter.current_executable().get_identifier(m_identifier);
TRY(set_variable(vm, name, interpreter.accumulator(), m_mode, m_initialization_mode));
TRY(set_variable(vm,
name,
interpreter.accumulator(),
m_mode,
m_initialization_mode,
interpreter.current_executable().environment_variable_caches[m_cache_index]));
return {};
}

View file

@ -472,11 +472,12 @@ public:
Initialize,
Set,
};
explicit SetVariable(IdentifierTableIndex identifier, InitializationMode initialization_mode = InitializationMode::Set, EnvironmentMode mode = EnvironmentMode::Lexical)
explicit SetVariable(IdentifierTableIndex identifier, u32 cache_index, InitializationMode initialization_mode = InitializationMode::Set, EnvironmentMode mode = EnvironmentMode::Lexical)
: Instruction(Type::SetVariable, sizeof(*this))
, m_identifier(identifier)
, m_mode(mode)
, m_initialization_mode(initialization_mode)
, m_cache_index(cache_index)
{
}
@ -486,11 +487,13 @@ public:
IdentifierTableIndex identifier() const { return m_identifier; }
EnvironmentMode mode() const { return m_mode; }
InitializationMode initialization_mode() const { return m_initialization_mode; }
u32 cache_index() const { return m_cache_index; }
private:
IdentifierTableIndex m_identifier;
EnvironmentMode m_mode;
InitializationMode m_initialization_mode { InitializationMode::Set };
u32 m_cache_index { 0 };
};
class SetLocal final : public Instruction {