Bläddra i källkod

LibJS/Bytecode: Store current interpreter register window as a Span

This avoids a bunch of indirections on every single register access.

~17% speed-up on Kraken/stanford-crypto-aes.js :^)
Andreas Kling 2 år sedan
förälder
incheckning
1efe4b58aa

+ 17 - 5
Userland/Libraries/LibJS/Bytecode/Interpreter.cpp

@@ -206,11 +206,9 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Realm& realm, Execu
     TemporaryChange restore_current_block { m_current_block, entry_point ?: executable.basic_blocks.first() };
 
     if (in_frame)
-        m_register_windows.append(in_frame);
+        push_register_window(in_frame, executable.number_of_registers);
     else
-        m_register_windows.append(make<RegisterWindow>(MarkedVector<Value>(vm().heap()), MarkedVector<GCPtr<Environment>>(vm().heap()), MarkedVector<GCPtr<Environment>>(vm().heap()), Vector<UnwindInfo> {}));
-
-    registers().resize(executable.number_of_registers);
+        push_register_window(make<RegisterWindow>(MarkedVector<Value>(vm().heap()), MarkedVector<GCPtr<Environment>>(vm().heap()), MarkedVector<GCPtr<Environment>>(vm().heap()), Vector<UnwindInfo> {}), executable.number_of_registers);
 
     for (;;) {
         Bytecode::InstructionStreamIterator pc(m_current_block->instruction_stream());
@@ -306,7 +304,7 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Realm& realm, Execu
         }
     }
 
-    auto frame = m_register_windows.take_last();
+    auto frame = pop_register_window();
 
     Value return_value = js_undefined();
     if (!m_return_value.is_empty()) {
@@ -453,4 +451,18 @@ Realm& Interpreter::realm()
     return *m_vm.current_realm();
 }
 
+void Interpreter::push_register_window(Variant<NonnullOwnPtr<RegisterWindow>, RegisterWindow*> window, size_t register_count)
+{
+    m_register_windows.append(move(window));
+    this->window().registers.resize(register_count);
+    m_current_register_window = this->window().registers;
+}
+
+Variant<NonnullOwnPtr<RegisterWindow>, RegisterWindow*> Interpreter::pop_register_window()
+{
+    auto window = m_register_windows.take_last();
+    m_current_register_window = m_register_windows.is_empty() ? Span<Value> {} : this->window().registers;
+    return window;
+}
+
 }

+ 6 - 1
Userland/Libraries/LibJS/Bytecode/Interpreter.h

@@ -101,10 +101,15 @@ private:
         return const_cast<Interpreter*>(this)->window();
     }
 
-    MarkedVector<Value>& registers() { return window().registers; }
+    Span<Value> registers() { return m_current_register_window; }
+    ReadonlySpan<Value> registers() const { return m_current_register_window; }
+
+    void push_register_window(Variant<NonnullOwnPtr<RegisterWindow>, RegisterWindow*>, size_t register_count);
+    [[nodiscard]] Variant<NonnullOwnPtr<RegisterWindow>, RegisterWindow*> pop_register_window();
 
     VM& m_vm;
     Vector<Variant<NonnullOwnPtr<RegisterWindow>, RegisterWindow*>> m_register_windows;
+    Span<Value> m_current_register_window;
     Optional<BasicBlock const*> m_pending_jump;
     BasicBlock const* m_scheduled_jump { nullptr };
     Value m_return_value;