浏览代码

LibJS: Implement bytecode generation for BigInts

Gunnar Beutner 4 年之前
父节点
当前提交
50ece3dd1b

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

@@ -660,6 +660,7 @@ public:
 
     virtual Value execute(Interpreter&, GlobalObject&) const override;
     virtual void dump(int indent) const override;
+    virtual Optional<Bytecode::Register> generate_bytecode(Bytecode::Generator&) const override;
 
 private:
     String m_value;

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

@@ -208,6 +208,13 @@ Optional<Bytecode::Register> NullLiteral::generate_bytecode(Bytecode::Generator&
     return dst;
 }
 
+Optional<Bytecode::Register> BigIntLiteral::generate_bytecode(Bytecode::Generator& generator) const
+{
+    auto dst = generator.allocate_register();
+    generator.emit<Bytecode::Op::NewBigInt>(dst, Crypto::SignedBigInteger::from_base10(m_value.substring(0, m_value.length() - 1)));
+    return dst;
+}
+
 Optional<Bytecode::Register> StringLiteral::generate_bytecode(Bytecode::Generator& generator) const
 {
     auto dst = generator.allocate_register();

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

@@ -26,6 +26,7 @@
     O(AbstractEquals)             \
     O(TypedInequals)              \
     O(TypedEquals)                \
+    O(NewBigInt)                  \
     O(NewString)                  \
     O(NewObject)                  \
     O(GetVariable)                \

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

@@ -8,6 +8,7 @@
 #include <LibJS/AST.h>
 #include <LibJS/Bytecode/Interpreter.h>
 #include <LibJS/Bytecode/Op.h>
+#include <LibJS/Runtime/BigInt.h>
 #include <LibJS/Runtime/GlobalObject.h>
 #include <LibJS/Runtime/ScriptFunction.h>
 #include <LibJS/Runtime/Value.h>
@@ -112,6 +113,11 @@ static Value typeof_(GlobalObject& global_object, Value value)
 
 JS_ENUMERATE_COMMON_UNARY_OPS(JS_DEFINE_COMMON_UNARY_OP)
 
+void NewBigInt::execute(Bytecode::Interpreter& interpreter) const
+{
+    interpreter.reg(m_dst) = js_bigint(interpreter.vm().heap(), m_bigint);
+}
+
 void NewString::execute(Bytecode::Interpreter& interpreter) const
 {
     interpreter.reg(m_dst) = js_string(interpreter.vm(), m_string);
@@ -231,6 +237,11 @@ String LoadRegister::to_string() const
     return String::formatted("LoadRegister dst:{}, src:{}", m_dst, m_src);
 }
 
+String NewBigInt::to_string() const
+{
+    return String::formatted("NewBigInt dst:{}, bigint:\"{}\"", m_dst, m_bigint.to_base10());
+}
+
 String NewString::to_string() const
 {
     return String::formatted("NewString dst:{}, string:\"{}\"", m_dst, m_string);

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

@@ -8,6 +8,7 @@
 #pragma once
 
 #include <AK/FlyString.h>
+#include <LibCrypto/BigInt/SignedBigInteger.h>
 #include <LibJS/Bytecode/Instruction.h>
 #include <LibJS/Bytecode/Label.h>
 #include <LibJS/Bytecode/Register.h>
@@ -157,6 +158,23 @@ private:
     Register m_dst;
 };
 
+class NewBigInt final : public Instruction {
+public:
+    explicit NewBigInt(Register dst, Crypto::SignedBigInteger bigint)
+        : Instruction(Type::NewBigInt)
+        , m_dst(dst)
+        , m_bigint(move(bigint))
+    {
+    }
+
+    void execute(Bytecode::Interpreter&) const;
+    String to_string() const;
+
+private:
+    Register m_dst;
+    Crypto::SignedBigInteger m_bigint;
+};
+
 class SetVariable final : public Instruction {
 public:
     SetVariable(FlyString identifier, Register src)