Skip to content

Commit

Permalink
LibJS: GetArgument SetArgument
Browse files Browse the repository at this point in the history
  • Loading branch information
kalenikaliaksandr committed May 10, 2024
1 parent 74791e0 commit ff334ad
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 23 deletions.
25 changes: 14 additions & 11 deletions Userland/Libraries/LibJS/Bytecode/Generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,24 @@ CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(E
auto const& parameter = formal_parameters[param_index];

if (parameter.is_rest) {
emit<Op::CreateRestParams>(argument(param_index), param_index);
auto argument_reg = allocate_register();
emit<Op::CreateRestParams>(argument_reg.operand(), param_index);
emit<Op::SetArgument>(param_index, argument_reg.operand());
} 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(param_index),
argument_reg.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::Mov>(argument(param_index), *operand);
emit<Op::SetArgument>(param_index, *operand);
emit<Op::Jump>(Label { if_not_undefined_block });

switch_to_basic_block(if_not_undefined_block);
Expand All @@ -77,18 +82,21 @@ 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::Mov>(local(local_variable_index), argument(param_index));
emit<Op::GetArgument>(local(local_variable_index), 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;
emit<Op::SetVariable>(id, argument(param_index),
auto argument_reg = allocate_register();
emit<Op::GetArgument>(argument_reg.operand(), param_index);
emit<Op::SetVariable>(id, argument_reg.operand(),
next_environment_variable_cache(),
init_mode,
Op::EnvironmentMode::Lexical);
}
} else if (auto const* binding_pattern = parameter.binding.get_pointer<NonnullRefPtr<BindingPattern const>>(); binding_pattern) {
auto input_operand = argument(param_index);
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));
}
Expand Down Expand Up @@ -410,11 +418,6 @@ 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: 0 additions & 1 deletion Userland/Libraries/LibJS/Bytecode/Generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ class Generator {

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

void free_register(Register);
Expand Down
2 changes: 2 additions & 0 deletions Userland/Libraries/LibJS/Bytecode/Instruction.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <LibJS/SourceRange.h>

#define ENUMERATE_BYTECODE_OPS(O) \
O(GetArgument) \
O(SetArgument) \
O(Add) \
O(ArrayAppend) \
O(AsyncIteratorClose) \
Expand Down
45 changes: 36 additions & 9 deletions Userland/Libraries/LibJS/Bytecode/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ static ByteString format_operand(StringView name, Operand operand, Bytecode::Exe
if (!name.is_empty())
builder.appendff("\033[32m{}\033[0m:", name);
switch (operand.type()) {
case Operand::Type::Argument:
builder.appendff("\033[33marg{}\033[0m", operand.index());
break;
case Operand::Type::Register:
builder.appendff("\033[33mreg{}\033[0m", operand.index());
break;
Expand Down Expand Up @@ -162,9 +159,7 @@ ALWAYS_INLINE Value Interpreter::get(Operand op) const
case Operand::Type::Local:
return m_locals.data()[op.index()];
case Operand::Type::Constant:
return m_constants.data()[op.index()];
case Operand::Type::Argument:
return m_arguments.data()[op.index()];
return current_executable().constants[op.index()];
}
__builtin_unreachable();
}
Expand All @@ -178,9 +173,6 @@ ALWAYS_INLINE void Interpreter::set(Operand op, Value value)
case Operand::Type::Local:
m_locals.data()[op.index()] = value;
return;
case Operand::Type::Argument:
m_arguments.data()[op.index()] = value;
return;
case Operand::Type::Constant:
break;
}
Expand Down Expand Up @@ -353,6 +345,7 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
}

auto& running_execution_context = vm().running_execution_context();
auto* arguments = running_execution_context.arguments.data();
auto* locals = running_execution_context.locals.data();
auto& accumulator = this->accumulator();
auto& executable = current_executable();
Expand Down Expand Up @@ -395,6 +388,18 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
DISPATCH_NEXT(SetLocal);
}

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

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

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

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 @@ -2096,6 +2113,16 @@ ByteString SetLocal::to_byte_string_impl(Bytecode::Executable const& executable)
format_operand("src"sv, src(), executable));
}

ByteString GetArgument::to_byte_string_impl(Bytecode::Executable const&) const
{
return "GetArgument"sv;
}

ByteString SetArgument::to_byte_string_impl(Bytecode::Executable const&) const
{
return "SetArgument"sv;
}

static StringView property_kind_to_string(PropertyKind kind)
{
switch (kind) {
Expand Down
40 changes: 40 additions & 0 deletions Userland/Libraries/LibJS/Bytecode/Op.h
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,46 @@ class SetLocal final : public Instruction {
Operand m_src;
};

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;

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;

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, u32 cache_index)
Expand Down
2 changes: 0 additions & 2 deletions Userland/Libraries/LibJS/Bytecode/Operand.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ namespace JS::Bytecode {
class Operand {
public:
enum class Type {
Argument,
Register,
Local,
Constant,
Expand All @@ -30,7 +29,6 @@ class Operand {

explicit Operand(Register);

[[nodiscard]] bool is_argument() const { return m_type == Type::Argument; }
[[nodiscard]] bool is_register() const { return m_type == Type::Register; }
[[nodiscard]] bool is_local() const { return m_type == Type::Local; }
[[nodiscard]] bool is_constant() const { return m_type == Type::Constant; }
Expand Down

0 comments on commit ff334ad

Please sign in to comment.