소스 검색

UserspaceEmulator: Cache the region we're executing code from

Instead of caching a raw pointer to the next instruction, cache the
region we're fetching instructions from, and a pointer to its base.
This way we don't need to keep invalidating and reloading the cache
whenever the CPU jumps.
Andreas Kling 4 년 전
부모
커밋
d14695f823
2개의 변경된 파일15개의 추가작업 그리고 18개의 파일을 삭제
  1. 3 2
      DevTools/UserspaceEmulator/SoftCPU.cpp
  2. 12 16
      DevTools/UserspaceEmulator/SoftCPU.h

+ 3 - 2
DevTools/UserspaceEmulator/SoftCPU.cpp

@@ -140,8 +140,9 @@ void SoftCPU::update_code_cache()
         TODO();
         TODO();
     }
     }
 
 
-    m_cached_code_ptr = region->cacheable_ptr(eip() - region->base());
-    m_cached_code_end = region->cacheable_ptr(region->size());
+    // FIXME: This cache needs to be invalidated if the code region is ever unmapped.
+    m_cached_code_region = region;
+    m_cached_code_base_ptr = region->data();
 }
 }
 
 
 ValueWithShadow<u8> SoftCPU::read_memory8(X86::LogicalAddress address)
 ValueWithShadow<u8> SoftCPU::read_memory8(X86::LogicalAddress address)

+ 12 - 16
DevTools/UserspaceEmulator/SoftCPU.h

@@ -26,6 +26,7 @@
 
 
 #pragma once
 #pragma once
 
 
+#include "Region.h"
 #include "ValueWithShadow.h"
 #include "ValueWithShadow.h"
 #include <LibX86/Instruction.h>
 #include <LibX86/Instruction.h>
 #include <LibX86/Interpreter.h>
 #include <LibX86/Interpreter.h>
@@ -33,6 +34,7 @@
 namespace UserspaceEmulator {
 namespace UserspaceEmulator {
 
 
 class Emulator;
 class Emulator;
+class Region;
 
 
 union PartAddressableRegister {
 union PartAddressableRegister {
     struct {
     struct {
@@ -68,8 +70,6 @@ public:
     void set_eip(u32 eip)
     void set_eip(u32 eip)
     {
     {
         m_eip = eip;
         m_eip = eip;
-        m_cached_code_ptr = nullptr;
-        m_cached_code_end = nullptr;
     }
     }
 
 
     struct Flags {
     struct Flags {
@@ -1151,8 +1151,8 @@ private:
     // FIXME: Or just something like m_flags_tainted?
     // FIXME: Or just something like m_flags_tainted?
     ValueWithShadow<u16> m_fpu_cw { 0, 0 };
     ValueWithShadow<u16> m_fpu_cw { 0, 0 };
 
 
-    const u8* m_cached_code_ptr { nullptr };
-    const u8* m_cached_code_end { nullptr };
+    Region* m_cached_code_region { nullptr };
+    u8* m_cached_code_base_ptr { nullptr };
 
 
     u32 m_secret_handshake_state { 0 };
     u32 m_secret_handshake_state { 0 };
     u32 m_secret_data[3];
     u32 m_secret_data[3];
@@ -1160,44 +1160,40 @@ private:
 
 
 ALWAYS_INLINE u8 SoftCPU::read8()
 ALWAYS_INLINE u8 SoftCPU::read8()
 {
 {
-    if (!m_cached_code_ptr || m_cached_code_ptr >= m_cached_code_end)
+    if (!m_cached_code_region || !m_cached_code_region->contains(m_eip))
         update_code_cache();
         update_code_cache();
 
 
-    u8 value = *m_cached_code_ptr;
-    m_cached_code_ptr += 1;
+    u8 value = m_cached_code_base_ptr[m_eip - m_cached_code_region->base()];
     m_eip += 1;
     m_eip += 1;
     return value;
     return value;
 }
 }
 
 
 ALWAYS_INLINE u16 SoftCPU::read16()
 ALWAYS_INLINE u16 SoftCPU::read16()
 {
 {
-    if (!m_cached_code_ptr || (m_cached_code_ptr + 1) >= m_cached_code_end)
+    if (!m_cached_code_region || !m_cached_code_region->contains(m_eip))
         update_code_cache();
         update_code_cache();
 
 
-    u16 value = *reinterpret_cast<const u16*>(m_cached_code_ptr);
-    m_cached_code_ptr += 2;
+    u16 value = *reinterpret_cast<const u16*>(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]);
     m_eip += 2;
     m_eip += 2;
     return value;
     return value;
 }
 }
 
 
 ALWAYS_INLINE u32 SoftCPU::read32()
 ALWAYS_INLINE u32 SoftCPU::read32()
 {
 {
-    if (!m_cached_code_ptr || (m_cached_code_ptr + 3) >= m_cached_code_end)
+    if (!m_cached_code_region || !m_cached_code_region->contains(m_eip))
         update_code_cache();
         update_code_cache();
 
 
-    u32 value = *reinterpret_cast<const u32*>(m_cached_code_ptr);
-    m_cached_code_ptr += 4;
+    u32 value = *reinterpret_cast<const u32*>(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]);
     m_eip += 4;
     m_eip += 4;
     return value;
     return value;
 }
 }
 
 
 ALWAYS_INLINE u64 SoftCPU::read64()
 ALWAYS_INLINE u64 SoftCPU::read64()
 {
 {
-    if (!m_cached_code_ptr || (m_cached_code_ptr + 7) >= m_cached_code_end)
+    if (!m_cached_code_region || !m_cached_code_region->contains(m_eip))
         update_code_cache();
         update_code_cache();
 
 
-    u64 value = *reinterpret_cast<const u64*>(m_cached_code_ptr);
-    m_cached_code_ptr += 8;
+    auto value = *reinterpret_cast<const u64*>(&m_cached_code_base_ptr[m_eip - m_cached_code_region->base()]);
     m_eip += 8;
     m_eip += 8;
     return value;
     return value;
 }
 }