Skip to content

Commit

Permalink
LibJS: Transform function arguments into operands
Browse files Browse the repository at this point in the history
  • Loading branch information
kalenikaliaksandr committed May 14, 2024
1 parent 931ef1d commit fe1dc19
Show file tree
Hide file tree
Showing 6 changed files with 24 additions and 102 deletions.
39 changes: 22 additions & 17 deletions Userland/Libraries/LibJS/Bytecode/Generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,24 +56,19 @@ CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(E
auto const& parameter = formal_parameters[param_index];

if (parameter.is_rest) {
auto argument_reg = allocate_register();
emit<Op::CreateRestParams>(argument_reg.operand(), param_index);
emit<Op::SetArgument>(param_index, argument_reg.operand());
emit<Op::CreateRestParams>(argument(param_index).operand(), param_index);
} else if (parameter.default_value) {
auto& if_undefined_block = make_block();
auto& if_not_undefined_block = make_block();

auto argument_reg = allocate_register();
emit<Op::GetArgument>(argument_reg.operand(), param_index);

emit<Op::JumpUndefined>(
argument_reg.operand(),
argument(param_index).operand(),
Label { if_undefined_block },
Label { if_not_undefined_block });

switch_to_basic_block(if_undefined_block);
auto operand = TRY(parameter.default_value->generate_bytecode(*this));
emit<Op::SetArgument>(param_index, *operand);
emit<Op::Mov>(argument(param_index), *operand);
emit<Op::Jump>(Label { if_not_undefined_block });

switch_to_basic_block(if_not_undefined_block);
Expand All @@ -82,22 +77,18 @@ CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(E
if (auto const* identifier = parameter.binding.get_pointer<NonnullRefPtr<Identifier const>>(); identifier) {
if ((*identifier)->is_local()) {
auto local_variable_index = (*identifier)->local_variable_index();
emit<Op::GetArgument>(local(local_variable_index), param_index);
emit<Op::Mov>(local(local_variable_index), argument(param_index));
set_local_initialized((*identifier)->local_variable_index());
} else {
auto id = intern_identifier((*identifier)->string());
auto init_mode = function.m_has_duplicates ? Op::SetVariable::InitializationMode::Set : Op::SetVariable::InitializationMode::Initialize;
auto argument_reg = allocate_register();
emit<Op::GetArgument>(argument_reg.operand(), param_index);
emit<Op::SetVariable>(id, argument_reg.operand(),
emit<Op::SetVariable>(id, argument(param_index).operand(),
init_mode,
Op::EnvironmentMode::Lexical);
}
} else if (auto const* binding_pattern = parameter.binding.get_pointer<NonnullRefPtr<BindingPattern const>>(); binding_pattern) {
auto input_operand = allocate_register();
emit<Op::GetArgument>(input_operand.operand(), param_index);
auto init_mode = function.m_has_duplicates ? Op::SetVariable::InitializationMode::Set : Bytecode::Op::SetVariable::InitializationMode::Initialize;
TRY((*binding_pattern)->generate_bytecode(*this, init_mode, input_operand, false));
TRY((*binding_pattern)->generate_bytecode(*this, init_mode, argument(param_index), false));
}
}

Expand Down Expand Up @@ -278,6 +269,9 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::emit_function_body_by

auto number_of_registers = generator.m_next_register;
auto number_of_constants = generator.m_constants.size();
auto number_of_locals = (u32)0;
if (function)
number_of_locals = function->m_local_variables_names.size();

for (auto& block : generator.m_root_basic_blocks) {
basic_block_start_offsets.append(bytecode.size());
Expand All @@ -300,7 +294,7 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::emit_function_body_by
while (!it.at_end()) {
auto& instruction = const_cast<Instruction&>(*it);

instruction.visit_operands([number_of_registers, number_of_constants](Operand& operand) {
instruction.visit_operands([number_of_registers, number_of_constants, number_of_locals](Operand& operand) {
switch (operand.type()) {
case Operand::Type::Register:
break;
Expand All @@ -310,6 +304,9 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::emit_function_body_by
case Operand::Type::Constant:
operand.offset_index_by(number_of_registers);
break;
case Operand::Type::Argument:
operand.offset_index_by(number_of_registers + number_of_constants + number_of_locals);
break;
default:
VERIFY_NOT_REACHED();
}
Expand Down Expand Up @@ -361,7 +358,7 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::emit_function_body_by
}
if (!block->is_terminated()) {
Op::End end(generator.add_constant(js_undefined()));
end.visit_operands([number_of_registers, number_of_constants](Operand& operand) {
end.visit_operands([number_of_registers, number_of_constants, number_of_locals](Operand& operand) {
switch (operand.type()) {
case Operand::Type::Register:
break;
Expand All @@ -371,6 +368,9 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::emit_function_body_by
case Operand::Type::Constant:
operand.offset_index_by(number_of_registers);
break;
case Operand::Type::Argument:
operand.offset_index_by(number_of_registers + number_of_constants + number_of_locals);
break;
default:
VERIFY_NOT_REACHED();
}
Expand Down Expand Up @@ -457,6 +457,11 @@ ScopedOperand Generator::local(u32 local_index)
return ScopedOperand { *this, Operand { Operand::Type::Local, static_cast<u32>(local_index) } };
}

ScopedOperand Generator::argument(u32 argument_index)
{
return ScopedOperand { *this, Operand { Operand::Type::Argument, static_cast<u32>(argument_index) } };
}

Generator::SourceLocationScope::SourceLocationScope(Generator& generator, ASTNode const& node)
: m_generator(generator)
, m_previous_node(m_generator.m_current_ast_node)
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibJS/Bytecode/Generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class Generator {

[[nodiscard]] ScopedOperand allocate_register();
[[nodiscard]] ScopedOperand local(u32 local_index);
[[nodiscard]] ScopedOperand argument(u32 local_index);
[[nodiscard]] ScopedOperand accumulator();

void free_register(Register);
Expand Down
2 changes: 0 additions & 2 deletions Userland/Libraries/LibJS/Bytecode/Instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
O(EnterObjectEnvironment) \
O(EnterUnwindContext) \
O(Exp) \
O(GetArgument) \
O(GetById) \
O(GetByIdWithThis) \
O(GetByValue) \
Expand Down Expand Up @@ -121,7 +120,6 @@
O(Return) \
O(RightShift) \
O(ScheduleJump) \
O(SetArgument) \
O(SetVariable) \
O(StrictlyEquals) \
O(StrictlyInequals) \
Expand Down
35 changes: 0 additions & 35 deletions Userland/Libraries/LibJS/Bytecode/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,6 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
}

auto& running_execution_context = this->running_execution_context();
auto* arguments = running_execution_context.arguments().data();
auto& accumulator = this->accumulator();
auto& executable = current_executable();
auto const* bytecode = executable.bytecode.data();
Expand Down Expand Up @@ -363,18 +362,6 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
for (;;) {
goto* bytecode_dispatch_table[static_cast<size_t>((*reinterpret_cast<Instruction const*>(&bytecode[program_counter])).type())];

handle_GetArgument: {
auto const& instruction = *reinterpret_cast<Op::GetArgument const*>(&bytecode[program_counter]);
set(instruction.dst(), arguments[instruction.index()]);
DISPATCH_NEXT(GetArgument);
}

handle_SetArgument: {
auto const& instruction = *reinterpret_cast<Op::SetArgument const*>(&bytecode[program_counter]);
arguments[instruction.index()] = get(instruction.src());
DISPATCH_NEXT(SetArgument);
}

handle_Mov: {
auto& instruction = *reinterpret_cast<Op::Mov const*>(&bytecode[program_counter]);
set(instruction.dst(), get(instruction.src()));
Expand Down Expand Up @@ -1389,18 +1376,6 @@ ThrowCompletionOr<void> SetVariable::execute_impl(Bytecode::Interpreter& interpr
return {};
}

ThrowCompletionOr<void> SetArgument::execute_impl(Bytecode::Interpreter&) const
{
// Handled in the interpreter loop.
__builtin_unreachable();
}

ThrowCompletionOr<void> GetArgument::execute_impl(Bytecode::Interpreter&) const
{
// Handled in the interpreter loop.
__builtin_unreachable();
}

ThrowCompletionOr<void> GetById::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto base_identifier = interpreter.current_executable().get_identifier(m_base_identifier);
Expand Down Expand Up @@ -2143,16 +2118,6 @@ ByteString SetVariable::to_byte_string_impl(Bytecode::Executable const& executab
mode_string, initialization_mode_name);
}

ByteString GetArgument::to_byte_string_impl(Bytecode::Executable const& executable) const
{
return ByteString::formatted("GetArgument {}, {}", index(), format_operand("dst"sv, dst(), executable));
}

ByteString SetArgument::to_byte_string_impl(Bytecode::Executable const& executable) const
{
return ByteString::formatted("SetArgument {}, {}", index(), format_operand("src"sv, src(), executable));
}

static StringView property_kind_to_string(PropertyKind kind)
{
switch (kind) {
Expand Down
48 changes: 0 additions & 48 deletions Userland/Libraries/LibJS/Bytecode/Op.h
Original file line number Diff line number Diff line change
Expand Up @@ -699,54 +699,6 @@ class SetVariable final : public Instruction {
mutable EnvironmentCoordinate m_cache;
};

class SetArgument final : public Instruction {
public:
SetArgument(size_t index, Operand src)
: Instruction(Type::SetArgument)
, m_index(index)
, m_src(src)
{
}

ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
ByteString to_byte_string_impl(Bytecode::Executable const&) const;
void visit_operands_impl(Function<void(Operand&)> visitor)
{
visitor(m_src);
}

size_t index() const { return m_index; }
Operand src() const { return m_src; }

private:
u32 m_index;
Operand m_src;
};

class GetArgument final : public Instruction {
public:
GetArgument(Operand dst, size_t index)
: Instruction(Type::GetArgument)
, m_index(index)
, m_dst(dst)
{
}

ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
ByteString to_byte_string_impl(Bytecode::Executable const&) const;
void visit_operands_impl(Function<void(Operand&)> visitor)
{
visitor(m_dst);
}

u32 index() const { return m_index; }
Operand dst() const { return m_dst; }

private:
u32 m_index;
Operand m_dst;
};

class GetCalleeAndThisFromEnvironment final : public Instruction {
public:
explicit GetCalleeAndThisFromEnvironment(Operand callee, Operand this_value, IdentifierTableIndex identifier)
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibJS/Bytecode/Operand.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Operand {
Register,
Local,
Constant,
Argument,
};

[[nodiscard]] bool operator==(Operand const&) const = default;
Expand Down

0 comments on commit fe1dc19

Please sign in to comment.