Skip to content

Commit

Permalink
LibJS: GetArguments SetArguments
Browse files Browse the repository at this point in the history
  • Loading branch information
kalenikaliaksandr committed May 10, 2024
1 parent 819daed commit 3732921
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 21 deletions.
34 changes: 24 additions & 10 deletions Userland/Libraries/LibJS/Bytecode/Generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,26 @@ 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 temp_reg = allocate_register();
emit<Op::CreateRestParams>(temp_reg.operand(), param_index);
emit<Op::SetArgument>(param_index, temp_reg.operand());
// emit<Op::CreateRestParams>(argument(param_index), param_index);
} else if (parameter.default_value) {
auto& if_undefined_block = make_block();
auto& if_not_undefined_block = make_block();

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

emit<Op::JumpUndefined>(
argument(param_index),
temp_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::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 +84,25 @@ 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));
auto temp_reg = allocate_register();
emit<Op::GetArgument>(temp_reg.operand(), param_index);
emit<Op::Mov>(local(local_variable_index), temp_reg.operand());
// 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;
emit<Op::SetVariable>(id, argument(param_index),
auto temp_reg = allocate_register();
emit<Op::GetArgument>(temp_reg.operand(), param_index);
emit<Op::SetVariable>(id, temp_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 = 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,10 +424,10 @@ 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) } };
}
// 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)
Expand Down
2 changes: 1 addition & 1 deletion Userland/Libraries/LibJS/Bytecode/Generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Generator {

[[nodiscard]] ScopedOperand allocate_register();
[[nodiscard]] ScopedOperand local(u32 local_index);
[[nodiscard]] ScopedOperand argument(u32 argument_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
51 changes: 43 additions & 8 deletions Userland/Libraries/LibJS/Bytecode/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ 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::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 @@ -163,8 +163,8 @@ ALWAYS_INLINE Value Interpreter::get(Operand op) const
return m_locals.data()[op.index()];
case Operand::Type::Constant:
return current_executable().constants[op.index()];
case Operand::Type::Argument:
return m_arguments.data()[op.index()];
// case Operand::Type::Argument:
// return m_arguments.data()[op.index()];
}
__builtin_unreachable();
}
Expand All @@ -178,9 +178,9 @@ 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::Argument:
// m_arguments.data()[op.index()] = value;
// return;
case Operand::Type::Constant:
VERIFY_NOT_REACHED();
}
Expand Down Expand Up @@ -353,6 +353,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 +396,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 @@ -1364,6 +1377,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 @@ -2097,6 +2122,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
4 changes: 2 additions & 2 deletions Userland/Libraries/LibJS/Bytecode/Operand.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace JS::Bytecode {
class Operand {
public:
enum class Type {
Argument,
// Argument,
Register,
Local,
Constant,
Expand All @@ -30,7 +30,7 @@ class Operand {

explicit Operand(Register);

[[nodiscard]] bool is_argument() const { return m_type == Type::Argument; }
// [[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 3732921

Please sign in to comment.