浏览代码

LibJS: Add bytecode support for regexp literals

Matthew Olsson 4 年之前
父节点
当前提交
df65ff8a1e

+ 1 - 0
Userland/Libraries/LibJS/AST.h

@@ -764,6 +764,7 @@ public:
 
 
     virtual Value execute(Interpreter&, GlobalObject&) const override;
     virtual Value execute(Interpreter&, GlobalObject&) const override;
     virtual void dump(int indent) const override;
     virtual void dump(int indent) const override;
+    virtual void generate_bytecode(Bytecode::Generator&) const override;
 
 
     String const& pattern() const { return m_pattern; }
     String const& pattern() const { return m_pattern; }
     String const& flags() const { return m_flags; }
     String const& flags() const { return m_flags; }

+ 7 - 0
Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp

@@ -258,6 +258,13 @@ void StringLiteral::generate_bytecode(Bytecode::Generator& generator) const
     generator.emit<Bytecode::Op::NewString>(generator.intern_string(m_value));
     generator.emit<Bytecode::Op::NewString>(generator.intern_string(m_value));
 }
 }
 
 
+void RegExpLiteral::generate_bytecode(Bytecode::Generator& generator) const
+{
+    auto source_index = generator.intern_string(m_pattern);
+    auto flags_index = generator.intern_string(m_flags);
+    generator.emit<Bytecode::Op::NewRegExp>(source_index, flags_index);
+}
+
 void Identifier::generate_bytecode(Bytecode::Generator& generator) const
 void Identifier::generate_bytecode(Bytecode::Generator& generator) const
 {
 {
     if (m_argument_index.has_value())
     if (m_argument_index.has_value())

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

@@ -32,6 +32,7 @@
     O(IteratorToArray)               \
     O(IteratorToArray)               \
     O(NewString)                     \
     O(NewString)                     \
     O(NewObject)                     \
     O(NewObject)                     \
+    O(NewRegExp)                     \
     O(CopyObjectExcludingProperties) \
     O(CopyObjectExcludingProperties) \
     O(GetVariable)                   \
     O(GetVariable)                   \
     O(SetVariable)                   \
     O(SetVariable)                   \

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

@@ -15,6 +15,7 @@
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/IteratorOperations.h>
 #include <LibJS/Runtime/IteratorOperations.h>
 #include <LibJS/Runtime/LexicalEnvironment.h>
 #include <LibJS/Runtime/LexicalEnvironment.h>
+#include <LibJS/Runtime/RegExpObject.h>
 #include <LibJS/Runtime/ScopeObject.h>
 #include <LibJS/Runtime/ScopeObject.h>
 #include <LibJS/Runtime/ScriptFunction.h>
 #include <LibJS/Runtime/ScriptFunction.h>
 #include <LibJS/Runtime/Value.h>
 #include <LibJS/Runtime/Value.h>
@@ -169,6 +170,14 @@ void NewObject::execute_impl(Bytecode::Interpreter& interpreter) const
     interpreter.accumulator() = Object::create(interpreter.global_object(), interpreter.global_object().object_prototype());
     interpreter.accumulator() = Object::create(interpreter.global_object(), interpreter.global_object().object_prototype());
 }
 }
 
 
+void NewRegExp::execute_impl(Bytecode::Interpreter& interpreter) const
+{
+    auto source = interpreter.current_executable().get_string(m_source_index);
+    auto flags = interpreter.current_executable().get_string(m_flags_index);
+
+    interpreter.accumulator() = RegExpObject::create(interpreter.global_object(), source, flags);
+}
+
 void CopyObjectExcludingProperties::execute_impl(Bytecode::Interpreter& interpreter) const
 void CopyObjectExcludingProperties::execute_impl(Bytecode::Interpreter& interpreter) const
 {
 {
     auto* from_object = interpreter.reg(m_from_object).to_object(interpreter.global_object());
     auto* from_object = interpreter.reg(m_from_object).to_object(interpreter.global_object());
@@ -498,6 +507,11 @@ String NewObject::to_string_impl(Bytecode::Executable const&) const
     return "NewObject";
     return "NewObject";
 }
 }
 
 
+String NewRegExp::to_string_impl(Bytecode::Executable const& executable) const
+{
+    return String::formatted("NewRegExp source:{} (\"{}\") flags:{} (\"{}\")", m_source_index, executable.get_string(m_source_index), m_flags_index, executable.get_string(m_flags_index));
+}
+
 String CopyObjectExcludingProperties::to_string_impl(const Bytecode::Executable&) const
 String CopyObjectExcludingProperties::to_string_impl(const Bytecode::Executable&) const
 {
 {
     StringBuilder builder;
     StringBuilder builder;

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

@@ -162,6 +162,24 @@ public:
     void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
     void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
 };
 };
 
 
+class NewRegExp final : public Instruction {
+public:
+    NewRegExp(StringTableIndex source_index, StringTableIndex flags_index)
+        : Instruction(Type::NewRegExp)
+        , m_source_index(source_index)
+        , m_flags_index(flags_index)
+    {
+    }
+
+    void execute_impl(Bytecode::Interpreter&) const;
+    String to_string_impl(Bytecode::Executable const&) const;
+    void replace_references_impl(BasicBlock const&, BasicBlock const&) { }
+
+private:
+    StringTableIndex m_source_index;
+    StringTableIndex m_flags_index;
+};
+
 // NOTE: This instruction is variable-width depending on the number of excluded names
 // NOTE: This instruction is variable-width depending on the number of excluded names
 class CopyObjectExcludingProperties final : public Instruction {
 class CopyObjectExcludingProperties final : public Instruction {
 public:
 public: