mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-23 18:02:05 -05:00
LibJS/Bytecode: Move bytecode operand rewriting to a separate pass
This way we don't have to do it whenever performing some kind of instruction rewrite.
This commit is contained in:
parent
97983275bc
commit
7971cfdd89
2 changed files with 37 additions and 33 deletions
|
@ -275,12 +275,14 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::compile(VM& vm, ASTNo
|
||||||
|
|
||||||
HashMap<size_t, SourceRecord> source_map;
|
HashMap<size_t, SourceRecord> source_map;
|
||||||
|
|
||||||
|
Optional<ScopedOperand> undefined_constant;
|
||||||
|
|
||||||
for (auto& block : generator.m_root_basic_blocks) {
|
for (auto& block : generator.m_root_basic_blocks) {
|
||||||
if (!block->is_terminated()) {
|
if (!block->is_terminated()) {
|
||||||
// NOTE: We must ensure that the "undefined" constant, which will be used by the not yet
|
// NOTE: We must ensure that the "undefined" constant, which will be used by the not yet
|
||||||
// emitted End instruction, is taken into account while shifting local operands by the
|
// emitted End instruction, is taken into account while shifting local operands by the
|
||||||
// number of constants.
|
// number of constants.
|
||||||
(void)generator.add_constant(js_undefined());
|
undefined_constant = generator.add_constant(js_undefined());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -288,6 +290,35 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::compile(VM& vm, ASTNo
|
||||||
auto number_of_registers = generator.m_next_register;
|
auto number_of_registers = generator.m_next_register;
|
||||||
auto number_of_constants = generator.m_constants.size();
|
auto number_of_constants = generator.m_constants.size();
|
||||||
|
|
||||||
|
// Pass: Rewrite the bytecode to use the correct register and constant indices.
|
||||||
|
for (auto& block : generator.m_root_basic_blocks) {
|
||||||
|
Bytecode::InstructionStreamIterator it(block->instruction_stream());
|
||||||
|
while (!it.at_end()) {
|
||||||
|
auto& instruction = const_cast<Instruction&>(*it);
|
||||||
|
|
||||||
|
instruction.visit_operands([number_of_registers, number_of_constants](Operand& operand) {
|
||||||
|
switch (operand.type()) {
|
||||||
|
case Operand::Type::Register:
|
||||||
|
break;
|
||||||
|
case Operand::Type::Local:
|
||||||
|
operand.offset_index_by(number_of_registers + number_of_constants);
|
||||||
|
break;
|
||||||
|
case Operand::Type::Constant:
|
||||||
|
operand.offset_index_by(number_of_registers);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
VERIFY_NOT_REACHED();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also rewrite the `undefined` constant if we have one for inserting End.
|
||||||
|
if (undefined_constant.has_value())
|
||||||
|
undefined_constant.value().operand().offset_index_by(number_of_registers);
|
||||||
|
|
||||||
for (auto& block : generator.m_root_basic_blocks) {
|
for (auto& block : generator.m_root_basic_blocks) {
|
||||||
basic_block_start_offsets.append(bytecode.size());
|
basic_block_start_offsets.append(bytecode.size());
|
||||||
if (block->handler() || block->finalizer()) {
|
if (block->handler() || block->finalizer()) {
|
||||||
|
@ -309,21 +340,6 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::compile(VM& vm, ASTNo
|
||||||
while (!it.at_end()) {
|
while (!it.at_end()) {
|
||||||
auto& instruction = const_cast<Instruction&>(*it);
|
auto& instruction = const_cast<Instruction&>(*it);
|
||||||
|
|
||||||
instruction.visit_operands([number_of_registers, number_of_constants](Operand& operand) {
|
|
||||||
switch (operand.type()) {
|
|
||||||
case Operand::Type::Register:
|
|
||||||
break;
|
|
||||||
case Operand::Type::Local:
|
|
||||||
operand.offset_index_by(number_of_registers + number_of_constants);
|
|
||||||
break;
|
|
||||||
case Operand::Type::Constant:
|
|
||||||
operand.offset_index_by(number_of_registers);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// OPTIMIZATION: Don't emit jumps that just jump to the next block.
|
// OPTIMIZATION: Don't emit jumps that just jump to the next block.
|
||||||
if (instruction.type() == Instruction::Type::Jump) {
|
if (instruction.type() == Instruction::Type::Jump) {
|
||||||
auto& jump = static_cast<Bytecode::Op::Jump&>(instruction);
|
auto& jump = static_cast<Bytecode::Op::Jump&>(instruction);
|
||||||
|
@ -369,21 +385,7 @@ CodeGenerationErrorOr<NonnullGCPtr<Executable>> Generator::compile(VM& vm, ASTNo
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
if (!block->is_terminated()) {
|
if (!block->is_terminated()) {
|
||||||
Op::End end(generator.add_constant(js_undefined()));
|
Op::End end(*undefined_constant);
|
||||||
end.visit_operands([number_of_registers, number_of_constants](Operand& operand) {
|
|
||||||
switch (operand.type()) {
|
|
||||||
case Operand::Type::Register:
|
|
||||||
break;
|
|
||||||
case Operand::Type::Local:
|
|
||||||
operand.offset_index_by(number_of_registers + number_of_constants);
|
|
||||||
break;
|
|
||||||
case Operand::Type::Constant:
|
|
||||||
operand.offset_index_by(number_of_registers);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
VERIFY_NOT_REACHED();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
bytecode.append(reinterpret_cast<u8 const*>(&end), end.length());
|
bytecode.append(reinterpret_cast<u8 const*>(&end), end.length());
|
||||||
}
|
}
|
||||||
if (block->handler() || block->finalizer()) {
|
if (block->handler() || block->finalizer()) {
|
||||||
|
|
|
@ -21,7 +21,8 @@ public:
|
||||||
|
|
||||||
~ScopedOperandImpl();
|
~ScopedOperandImpl();
|
||||||
|
|
||||||
[[nodiscard]] Operand operand() const { return m_operand; }
|
[[nodiscard]] Operand const& operand() const { return m_operand; }
|
||||||
|
[[nodiscard]] Operand& operand() { return m_operand; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Generator& m_generator;
|
Generator& m_generator;
|
||||||
|
@ -35,7 +36,8 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] Operand operand() const { return m_impl->operand(); }
|
[[nodiscard]] Operand const& operand() const { return m_impl->operand(); }
|
||||||
|
[[nodiscard]] Operand& operand() { return m_impl->operand(); }
|
||||||
operator Operand() const { return operand(); }
|
operator Operand() const { return operand(); }
|
||||||
|
|
||||||
[[nodiscard]] bool operator==(ScopedOperand const& other) const { return operand() == other.operand(); }
|
[[nodiscard]] bool operator==(ScopedOperand const& other) const { return operand() == other.operand(); }
|
||||||
|
|
Loading…
Add table
Reference in a new issue