[Lldb-commits] [lldb] r182028 - Added a per-process cache for reserved memory

Sean Callanan scallanan at apple.com
Thu May 16 10:30:38 PDT 2013


Author: spyffe
Date: Thu May 16 12:30:37 2013
New Revision: 182028

URL: http://llvm.org/viewvc/llvm-project?rev=182028&view=rev
Log:
Added a per-process cache for reserved memory
regions that aren't actually allocated in the
process.  This cache is used by the expression
parser if the underlying process doesn't support
memory allocation, to avoid needless repeated
searches for unused address ranges.

Also fixed a silly bug in IRMemoryMap where it
would continue searching even after it found a
valid region.

<rdar://problem/13866629>

Modified:
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/source/Expression/IRMemoryMap.cpp
    lldb/trunk/source/Target/Process.cpp

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=182028&r1=182027&r2=182028&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Thu May 16 12:30:37 2013
@@ -3532,7 +3532,73 @@ public:
         else
             return m_public_run_lock;
     }
-
+    
+    //------------------------------------------------------------------
+    // This is a cache of reserved and available memory address ranges
+    // for a single modification ID (see m_mod_id).  It's meant for use
+    // by IRMemoryMap, but to stick with the process.  These memory
+    // ranges happen to be unallocated in the underlying process, but we
+    // make no guarantee that at a future modification ID they won't be
+    // gone.  This is only useful if the underlying process can't
+    // allocate memory.
+    //
+    // When a memory space is determined to be available it is
+    // registered as reserved at the current modification.  If it is
+    // freed later, it is added to the free list if the modification ID
+    // hasn't changed.  Then clients can simply query the free list for
+    // the size they want.
+    //------------------------------------------------------------------
+    class ReservationCache
+    {
+    public:
+        ReservationCache (Process &process);
+        
+        //------------------------------------------------------------------
+        // Mark that a particular range of addresses is in use.  Adds it
+        // to the reserved map, implicitly tying it to the current
+        // modification ID.
+        //------------------------------------------------------------------
+        void
+        Reserve (lldb::addr_t addr, size_t size);
+        
+        //------------------------------------------------------------------
+        // Mark that a range is no longer in use.  If it's found in the
+        // reservation list, that means that the modification ID hasn't
+        // changed since it was reserved, so it can be safely added to the
+        // free list.
+        //------------------------------------------------------------------
+        void
+        Unreserve (lldb::addr_t addr);
+        
+        //------------------------------------------------------------------
+        // Try to find an unused range of the given size in the free list.
+        //------------------------------------------------------------------
+        lldb::addr_t
+        Find (size_t size);
+    private:
+        //------------------------------------------------------------------
+        // Clear all lists if the modification ID has changed.
+        //------------------------------------------------------------------
+        void CheckModID();
+        
+        typedef std::map <lldb::addr_t, size_t> ReservedMap;
+        typedef std::vector <lldb::addr_t> FreeList;
+        typedef std::map <size_t, FreeList> FreeMap;
+        
+        ReservedMap     m_reserved_cache;
+        FreeMap         m_free_cache;
+        
+        Process        &m_process;
+        ProcessModID    m_mod_id;
+    };
+    
+    ReservationCache &
+    GetReservationCache ()
+    {
+        return m_reservation_cache;
+    }
+private:
+    ReservationCache m_reservation_cache;
 protected:
     //------------------------------------------------------------------
     // NextEventAction provides a way to register an action on the next

Modified: lldb/trunk/source/Expression/IRMemoryMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRMemoryMap.cpp?rev=182028&r1=182027&r2=182028&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRMemoryMap.cpp (original)
+++ lldb/trunk/source/Expression/IRMemoryMap.cpp Thu May 16 12:30:37 2013
@@ -31,19 +31,14 @@ IRMemoryMap::~IRMemoryMap ()
     
     if (process_sp)
     {
-        for (AllocationMap::value_type &allocation : m_allocations)
+        AllocationMap::iterator iter;
+        
+        Error err;
+
+        while ((iter = m_allocations.begin()) != m_allocations.end())
         {
-            if (allocation.second.m_policy == eAllocationPolicyMirror ||
-                allocation.second.m_policy == eAllocationPolicyProcessOnly ||
-                (allocation.second.m_policy == eAllocationPolicyHostOnly && process_sp->CanJIT()))
-                process_sp->DeallocateMemory(allocation.second.m_process_alloc);
-            
-            if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
-            {
-                log->Printf("IRMemoryMap::~IRMemoryMap deallocated [0x%llx..0x%llx)",
-                            (uint64_t)allocation.second.m_process_start,
-                            (uint64_t)allocation.second.m_process_start + (uint64_t)allocation.second.m_size);
-            }
+            err.Clear();
+            Free(iter->first, err);
         }
     }
 }
@@ -68,6 +63,14 @@ IRMemoryMap::FindSpace (size_t size)
             return ret;
     }
     
+    if (process_sp)
+    {
+        ret = process_sp->GetReservationCache().Find(size);
+        
+        if (ret != LLDB_INVALID_ADDRESS)
+            return ret;
+    }
+    
     for (int iterations = 0; iterations < 16; ++iterations)
     {
         lldb::addr_t candidate = LLDB_INVALID_ADDRESS;
@@ -106,6 +109,11 @@ IRMemoryMap::FindSpace (size_t size)
             continue;
         
         ret = candidate;
+        
+        if (process_sp)
+            process_sp->GetReservationCache().Reserve(candidate, size);
+    
+        return ret;
     }
     
     return ret;
@@ -382,9 +390,14 @@ IRMemoryMap::Free (lldb::addr_t process_
     case eAllocationPolicyHostOnly:
         {
             lldb::ProcessSP process_sp = m_process_wp.lock();
-            if (process_sp && process_sp->CanJIT())
-                process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
-
+            if (process_sp)
+            {
+                if (process_sp->CanJIT())
+                    process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
+                else
+                    process_sp->GetReservationCache().Unreserve(allocation.m_process_alloc); // FindSpace registered this memory
+            }
+    
             break;
         }
     case eAllocationPolicyMirror:

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=182028&r1=182027&r2=182028&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Thu May 16 12:30:37 2013
@@ -996,6 +996,7 @@ Process::Process(Target &target, Listene
     ProcessProperties (false),
     UserID (LLDB_INVALID_PROCESS_ID),
     Broadcaster (&(target.GetDebugger()), "lldb.process"),
+    m_reservation_cache (*this),
     m_target (target),
     m_public_state (eStateUnloaded),
     m_private_state (eStateUnloaded),
@@ -5589,3 +5590,60 @@ Process::DidExec ()
     DoDidExec();
     CompleteAttach ();
 }
+
+Process::ReservationCache::ReservationCache (Process &process) : m_process(process)
+{
+    m_mod_id = process.GetModID();
+}
+
+void
+Process::ReservationCache::Reserve (lldb::addr_t addr, size_t size)
+{
+    CheckModID();
+    m_reserved_cache[addr] = size;
+}
+
+void
+Process::ReservationCache::Unreserve (lldb::addr_t addr)
+{
+    CheckModID();
+    ReservedMap::iterator iter = m_reserved_cache.find(addr);
+    
+    if (iter != m_reserved_cache.end())
+    {
+        size_t size = iter->second;
+        m_reserved_cache.erase(iter);
+        m_free_cache[size].push_back(addr);
+    }
+}
+
+lldb::addr_t
+Process::ReservationCache::Find (size_t size)
+{
+    CheckModID();
+    lldb::addr_t ret = LLDB_INVALID_ADDRESS;
+    FreeMap::iterator map_iter = m_free_cache.find(size);
+    if (map_iter != m_free_cache.end())
+    {
+        if (!map_iter->second.empty())
+        {
+            ret = map_iter->second.back();
+            map_iter->second.pop_back();
+            m_reserved_cache[ret] = size;
+        }
+    }
+    
+    return ret;
+}
+
+void
+Process::ReservationCache::CheckModID()
+{
+    if (m_mod_id != m_process.GetModID())
+    {
+        // wipe all our caches, they're invalid
+        m_reserved_cache.clear();
+        m_free_cache.clear();
+        m_mod_id = m_process.GetModID();
+    }
+}





More information about the lldb-commits mailing list