Bläddra i källkod

LibJS: Add LoadArgument bytecode instruction for fast argument access

This is generated for Identifier nodes that represent a function
argument variable. It loads a given argument index from the current
call frame into the accumulator.
Andreas Kling 4 år sedan
förälder
incheckning
91fbeeab72

+ 4 - 1
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -260,7 +260,10 @@ void StringLiteral::generate_bytecode(Bytecode::Generator& generator) const
 
 
 void Identifier::generate_bytecode(Bytecode::Generator& generator) const
 void Identifier::generate_bytecode(Bytecode::Generator& generator) const
 {
 {
-    generator.emit<Bytecode::Op::GetVariable>(generator.intern_string(m_string));
+    if (m_argument_index.has_value())
+        generator.emit<Bytecode::Op::LoadArgument>(m_argument_index.value());
+    else
+        generator.emit<Bytecode::Op::GetVariable>(generator.intern_string(m_string));
 }
 }
 
 
 void AssignmentExpression::generate_bytecode(Bytecode::Generator& generator) const
 void AssignmentExpression::generate_bytecode(Bytecode::Generator& generator) const

+ 1 - 0
Userland/Libraries/LibJS/Bytecode/Instruction.h

@@ -61,6 +61,7 @@
     O(Decrement)                  \
     O(Decrement)                  \
     O(Throw)                      \
     O(Throw)                      \
     O(PushLexicalEnvironment)     \
     O(PushLexicalEnvironment)     \
+    O(LoadArgument)               \
     O(EnterUnwindContext)         \
     O(EnterUnwindContext)         \
     O(LeaveUnwindContext)         \
     O(LeaveUnwindContext)         \
     O(ContinuePendingUnwind)      \
     O(ContinuePendingUnwind)      \

+ 10 - 0
Userland/Libraries/LibJS/Bytecode/Op.cpp

@@ -311,6 +311,11 @@ void PutByValue::execute(Bytecode::Interpreter& interpreter) const
     }
     }
 }
 }
 
 
+void LoadArgument::execute(Bytecode::Interpreter& interpreter) const
+{
+    interpreter.accumulator() = interpreter.vm().argument(m_index);
+}
+
 String Load::to_string(Bytecode::Executable const&) const
 String Load::to_string(Bytecode::Executable const&) const
 {
 {
     return String::formatted("Load {}", m_src);
     return String::formatted("Load {}", m_src);
@@ -493,4 +498,9 @@ String PutByValue::to_string(const Bytecode::Executable&) const
     return String::formatted("PutByValue base:{}, property:{}", m_base, m_property);
     return String::formatted("PutByValue base:{}, property:{}", m_base, m_property);
 }
 }
 
 
+String LoadArgument::to_string(const Bytecode::Executable&) const
+{
+    return String::formatted("LoadArgument {}", m_index);
+}
+
 }
 }

+ 16 - 0
Userland/Libraries/LibJS/Bytecode/Op.h

@@ -529,6 +529,22 @@ public:
 private:
 private:
     HashMap<u32, Variable> m_variables;
     HashMap<u32, Variable> m_variables;
 };
 };
+
+class LoadArgument final : public Instruction {
+public:
+    explicit LoadArgument(size_t index)
+        : Instruction(Type::LoadArgument)
+        , m_index(index)
+    {
+    }
+
+    void execute(Bytecode::Interpreter&) const;
+    String to_string(Bytecode::Executable const&) const;
+
+private:
+    size_t m_index { 0 };
+};
+
 }
 }
 
 
 namespace JS::Bytecode {
 namespace JS::Bytecode {