Updated backpatching logic during object deserialization to perform
authorTed Kremenek <kremenek@apple.com>
Sun, 28 Oct 2007 21:17:59 +0000 (21:17 +0000)
committerTed Kremenek <kremenek@apple.com>
Sun, 28 Oct 2007 21:17:59 +0000 (21:17 +0000)
eager backpatching instead of waithing until all objects have been
deserialized.  This allows us to reduce the memory footprint needed
for backpatching.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@43422 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Bitcode/Deserialize.h
lib/Bitcode/Reader/Deserialize.cpp

index 4a9b06381ad714a6e611f0b8a6beb178ab6ca853..508b4deee82ea80b50bf19dd5beebb607e89dc0a 100644 (file)
 namespace llvm {
   
 class Deserializer {  
-  BitstreamReader& Stream;
-  SmallVector<uint64_t,10> Record;
-  unsigned RecIdx;
-  BumpPtrAllocator Allocator;
-  
+
+  //===----------------------------------------------------------===//
+  // Internal type definitions.
+  //===----------------------------------------------------------===//
+
   struct PtrIdInfo {
     static inline unsigned getEmptyKey() { return ~((unsigned) 0x0); }
     static inline unsigned getTombstoneKey() { return getEmptyKey()-1; }
@@ -39,26 +39,58 @@ class Deserializer {
     static inline bool isPod() { return true; }
   };
   
-  struct BPatchNode {
-    BPatchNode* const Next;
+  struct BPNode {
+    BPNode* Next;
     uintptr_t& PtrRef;
-    BPatchNode(BPatchNode* n, void*& pref) 
-      : Next(n), PtrRef(reinterpret_cast<uintptr_t&>(pref)) {
+    BPNode(BPNode* n, uintptr_t& pref) 
+      : Next(n), PtrRef(pref) {
         PtrRef = 0;
       }
   };
   
-  struct BPatchEntry {
-    BPatchNode* Head;
-    void* Ptr;    
-    BPatchEntry() : Head(NULL), Ptr(NULL) {}
+  class BPatchEntry {
+    uintptr_t Ptr;
+  public:
+    
+    BPatchEntry() : Ptr(0x1) {}
+      
+    BPatchEntry(void* P) : Ptr(reinterpret_cast<uintptr_t>(P)) {}
+
+    bool hasFinalPtr() const { return Ptr & 0x1 ? true : false; }
+    void setFinalPtr(BPNode*& FreeList, void* P);
+
+    BPNode* getBPNode() const {
+      assert (!hasFinalPtr());
+      return reinterpret_cast<BPNode*>(Ptr & ~0x1);
+    }
+    
+    void setBPNode(BPNode* N) {
+      assert (!hasFinalPtr());
+      Ptr = reinterpret_cast<uintptr_t>(N) | 0x1;
+    }
+    
+    uintptr_t getRawPtr() const { return Ptr; }
+
     static inline bool isPod() { return true; }
-  };  
-  
+  };
+
   typedef llvm::DenseMap<unsigned,BPatchEntry,PtrIdInfo,BPatchEntry> MapTy;
 
+  //===----------------------------------------------------------===//
+  // Internal data members.
+  //===----------------------------------------------------------===//
+  
+  BitstreamReader& Stream;
+  SmallVector<uint64_t,10> Record;
+  unsigned RecIdx;
+  BumpPtrAllocator Allocator;
+  BPNode* FreeList;
   MapTy BPatchMap;  
   
+  //===----------------------------------------------------------===//
+  // Public Interface.
+  //===----------------------------------------------------------===//
+  
 public:
   Deserializer(BitstreamReader& stream);
   ~Deserializer();
@@ -99,13 +131,15 @@ public:
     return x;
   }
   
-  void ReadPtr(void*& PtrRef);
-  void ReadPtr(uintptr_t& PtrRef) { ReadPtr(reinterpret_cast<void*&>(PtrRef)); }
+  template <typename T>
+  void ReadPtr(T*& PtrRef) { ReadUIntPtr(reinterpret_cast<uintptr_t&>(PtrRef));}
+
+  void ReadPtr(uintptr_t& PtrRef) { ReadUIntPtr(PtrRef); }
+  
+  void ReadUIntPtr(uintptr_t& PtrRef);
   
   void RegisterPtr(unsigned PtrId, void* Ptr);
 
-
-  void BackpatchPointers();
 private:
   void ReadRecord();  
   bool inRecord();
index 66df46ea23e32e6a17194d767b1d5c55d655a591..9caef6dae1e54db47ead44c85c68156b70e77cb9 100644 (file)
 using namespace llvm;
 
 Deserializer::Deserializer(BitstreamReader& stream)
-  : Stream(stream), RecIdx(0) {
+  : Stream(stream), RecIdx(0), FreeList(NULL) {
 }
 
 Deserializer::~Deserializer() {
   assert (RecIdx >= Record.size() && 
           "Still scanning bitcode record when deserialization completed.");
   
-  BackpatchPointers();
+  assert (FreeList == NULL && "Some pointers were not backpatched.");
 }
 
 
@@ -96,11 +96,11 @@ void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
 
 void Deserializer::RegisterPtr(unsigned PtrId,void* Ptr) {
   BPatchEntry& E = BPatchMap[PtrId];
-  assert (E.Ptr == NULL && "Pointer already registered.");
-  E.Ptr = Ptr;
+  assert (E.hasFinalPtr() && "Pointer already registered.");
+  E.setFinalPtr(FreeList,Ptr);
 }
 
-void Deserializer::ReadPtr(void*& PtrRef) {
+void Deserializer::ReadUIntPtr(uintptr_t& PtrRef) {
   unsigned PtrId = ReadInt();
   
   if (PtrId == 0) {
@@ -110,32 +110,46 @@ void Deserializer::ReadPtr(void*& PtrRef) {
   
   BPatchEntry& E = BPatchMap[PtrId];
   
-  if (E.Ptr == NULL) {
-    // Register backpatch.
-    void* P = Allocator.Allocate<BPatchNode>();    
-    E.Head = new (P) BPatchNode(E.Head,PtrRef);
+  if (E.hasFinalPtr())
+    PtrRef = E.getRawPtr();
+  else {
+    // Register backpatch.  Check the freelist for a BPNode.
+    BPNode* N;
+
+    if (FreeList) {
+      N = FreeList;
+      FreeList = FreeList->Next;
+    }
+    else // No available BPNode.  Allocate one.
+      N = (BPNode*) Allocator.Allocate<BPNode>();
+    
+    new (N) BPNode(E.getBPNode(),PtrRef);
+    E.setBPNode(N);
   }
-  else
-    PtrRef = E.Ptr;
 }
 
-void Deserializer::BackpatchPointers() {
-  for (MapTy::iterator I=BPatchMap.begin(),E=BPatchMap.end(); I!=E; ++I) {
-    
-    BPatchEntry& Entry = I->second;
-    assert (Entry.Ptr && "No pointer found for backpatch.");
-    
-    for (BPatchNode* N = Entry.Head; N != NULL; N = N->Next)
-      // Bitwise-OR in the pointer to support "smart" pointers that use
-      // unused bits to store extra data.
-      N->PtrRef |= reinterpret_cast<uintptr_t>(Entry.Ptr);
-    
-    Entry.Head = NULL;
+
+void Deserializer::BPatchEntry::setFinalPtr(BPNode*& FreeList, void* P) {
+  assert (!hasFinalPtr());
+  
+  // Perform backpatching.
+  
+  BPNode* Last = NULL;
+  
+  for (BPNode* N = getBPNode() ; N != NULL; N = N->Next) {
+    Last = N;
+    N->PtrRef |= reinterpret_cast<uintptr_t>(P);
   }
   
-  Allocator.Reset();
+  if (Last) {
+    Last->Next = FreeList;
+    FreeList = getBPNode();    
+  }
+  
+  Ptr = reinterpret_cast<uintptr_t>(P);
 }
 
+
 #define INT_READ(TYPE)\
 void SerializeTrait<TYPE>::Read(Deserializer& D, TYPE& X) {\
   X = (TYPE) D.ReadInt(); }\