diff options
author | Matthew Olsson <matthewcolsson@gmail.com> | 2021-06-13 12:24:40 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-06-19 09:38:26 +0200 |
commit | f39ab2e60aa136f2a5d164109a27465654ea6f13 (patch) | |
tree | 9a9fa01ca0122299b904f90c3892f6da28c8f2f5 /Userland | |
parent | 3ee627909affafdd8d51df8272e32a7d55f3ca9d (diff) | |
download | serenity-f39ab2e60aa136f2a5d164109a27465654ea6f13.zip |
LibJS: Add JumpUndefined bytecode
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Instruction.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.cpp | 18 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.h | 11 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Pass/GenerateCFG.cpp | 2 |
4 files changed, 31 insertions, 1 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index ac0e8de028..e3ca74d91d 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -40,6 +40,7 @@ O(Jump) \ O(JumpConditional) \ O(JumpNullish) \ + O(JumpUndefined) \ O(Call) \ O(NewFunction) \ O(Return) \ diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 6dfe48a42e..607878882a 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -195,6 +195,17 @@ void JumpNullish::execute_impl(Bytecode::Interpreter& interpreter) const interpreter.jump(m_false_target.value()); } +void JumpUndefined::execute_impl(Bytecode::Interpreter& interpreter) const +{ + VERIFY(m_true_target.has_value()); + VERIFY(m_false_target.has_value()); + auto result = interpreter.accumulator(); + if (result.is_undefined()) + interpreter.jump(m_true_target.value()); + else + interpreter.jump(m_false_target.value()); +} + void Call::execute_impl(Bytecode::Interpreter& interpreter) const { auto callee = interpreter.reg(m_callee); @@ -439,6 +450,13 @@ String JumpNullish::to_string_impl(Bytecode::Executable const&) const return String::formatted("JumpNullish null:{} nonnull:{}", true_string, false_string); } +String JumpUndefined::to_string_impl(Bytecode::Executable const&) const +{ + auto true_string = m_true_target.has_value() ? String::formatted("{}", *m_true_target) : "<empty>"; + auto false_string = m_false_target.has_value() ? String::formatted("{}", *m_false_target) : "<empty>"; + return String::formatted("JumpUndefined undefined:{} not undefined:{}", true_string, false_string); +} + String Call::to_string_impl(Bytecode::Executable const&) const { StringBuilder builder; diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 653b9d1889..af93adb28b 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -377,6 +377,17 @@ public: String to_string_impl(Bytecode::Executable const&) const; }; +class JumpUndefined final : public Jump { +public: + explicit JumpUndefined(Optional<Label> true_target = {}, Optional<Label> false_target = {}) + : Jump(Type::JumpUndefined, move(true_target), move(false_target)) + { + } + + void execute_impl(Bytecode::Interpreter&) const; + String to_string_impl(Bytecode::Executable const&) const; +}; + // NOTE: This instruction is variable-width depending on the number of arguments! class Call final : public Instruction { public: diff --git a/Userland/Libraries/LibJS/Bytecode/Pass/GenerateCFG.cpp b/Userland/Libraries/LibJS/Bytecode/Pass/GenerateCFG.cpp index 167e3c6052..e6cafc443d 100644 --- a/Userland/Libraries/LibJS/Bytecode/Pass/GenerateCFG.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Pass/GenerateCFG.cpp @@ -58,7 +58,7 @@ void GenerateCFG::perform(PassPipelineExecutable& executable) continue; } - if (instruction.type() == Instruction::Type::JumpConditional || instruction.type() == Instruction::Type::JumpNullish) { + if (instruction.type() == Instruction::Type::JumpConditional || instruction.type() == Instruction::Type::JumpNullish || instruction.type() == Instruction::Type::JumpUndefined) { auto& true_target = static_cast<Op::Jump const&>(instruction).true_target(); enter_label(true_target, current_block); auto& false_target = static_cast<Op::Jump const&>(instruction).false_target(); |