LibJS: Skip allocating locals for arguments that allowed to be local

This allows us to get rid of instructions that move arguments to locals
and allocate smaller JS::Value vector in ExecutionContext by reusing
slots that were already allocated for arguments.

With this change for following function:
```js
function f(x, y) {
    return x + y;
}
```

we now produce following bytecode:
```
[   0]    0: Add dst:reg6, lhs:arg0, rhs:arg1
[  10]       Return value:reg6
```

instead of:
```
[   0]    0: GetArgument 0, dst:x~1
[  10]       GetArgument 1, dst:y~0
[  20]       Add dst:reg6, lhs:x~1, rhs:y~0
[  30]       Return value:reg6
```
This commit is contained in:
Aliaksandr Kalenik 2025-04-25 17:10:47 +02:00 committed by Andreas Kling
commit 2d732b2251
Notes: github-actions[bot] 2025-04-26 09:03:23 +00:00
6 changed files with 102 additions and 39 deletions

View file

@ -675,13 +675,29 @@ public:
FlyString const& string() const { return m_string; }
bool is_local() const { return m_local_variable_index.has_value(); }
size_t local_variable_index() const
struct Local {
enum Type {
Argument,
Variable,
};
Type type;
size_t index;
bool is_argument() const { return type == Argument; }
bool is_variable() const { return type == Variable; }
static Local variable(size_t index) { return { Variable, index }; }
static Local argument(size_t index) { return { Argument, index }; }
};
bool is_local() const { return m_local_index.has_value(); }
Local local_index() const
{
VERIFY(m_local_variable_index.has_value());
return m_local_variable_index.value();
VERIFY(m_local_index.has_value());
return m_local_index.value();
}
void set_local_variable_index(size_t index) { m_local_variable_index = index; }
void set_local_variable_index(size_t index) { m_local_index = Local::variable(index); }
void set_argument_index(size_t index) { m_local_index = Local::argument(index); }
bool is_global() const { return m_is_global; }
void set_is_global() { m_is_global = true; }
@ -694,7 +710,7 @@ private:
FlyString m_string;
Optional<size_t> m_local_variable_index;
Optional<Local> m_local_index;
bool m_is_global { false };
};
@ -719,6 +735,20 @@ public:
size_t size() const { return m_parameters.size(); }
Vector<FunctionParameter> const& parameters() const { return m_parameters; }
Optional<size_t> get_index_of_parameter_name(FlyString const& name) const
{
// Iterate backwards to return the last parameter with the same name
for (int i = m_parameters.size() - 1; i >= 0; i--) {
auto& parameter = m_parameters[i];
if (parameter.binding.has<NonnullRefPtr<Identifier const>>()) {
auto& identifier = parameter.binding.get<NonnullRefPtr<Identifier const>>();
if (identifier->string() == name)
return i;
}
}
return {};
}
private:
FunctionParameters(Vector<FunctionParameter> parameters)
: m_parameters(move(parameters))