From 5973ef40ca290903e0b3a4952162c14b55af5d72 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Sun, 28 Oct 2007 21:17:59 +0000 Subject: [PATCH] Updated backpatching logic during object deserialization to perform 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 | 72 ++++++++++++++++++++++-------- lib/Bitcode/Reader/Deserialize.cpp | 62 +++++++++++++++---------- 2 files changed, 91 insertions(+), 43 deletions(-) diff --git a/include/llvm/Bitcode/Deserialize.h b/include/llvm/Bitcode/Deserialize.h index 4a9b06381ad..508b4deee82 100644 --- a/include/llvm/Bitcode/Deserialize.h +++ b/include/llvm/Bitcode/Deserialize.h @@ -26,11 +26,11 @@ namespace llvm { class Deserializer { - BitstreamReader& Stream; - SmallVector 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(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(P)) {} + + bool hasFinalPtr() const { return Ptr & 0x1 ? true : false; } + void setFinalPtr(BPNode*& FreeList, void* P); + + BPNode* getBPNode() const { + assert (!hasFinalPtr()); + return reinterpret_cast(Ptr & ~0x1); + } + + void setBPNode(BPNode* N) { + assert (!hasFinalPtr()); + Ptr = reinterpret_cast(N) | 0x1; + } + + uintptr_t getRawPtr() const { return Ptr; } + static inline bool isPod() { return true; } - }; - + }; + typedef llvm::DenseMap MapTy; + //===----------------------------------------------------------===// + // Internal data members. + //===----------------------------------------------------------===// + + BitstreamReader& Stream; + SmallVector 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(PtrRef)); } + template + void ReadPtr(T*& PtrRef) { ReadUIntPtr(reinterpret_cast(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(); diff --git a/lib/Bitcode/Reader/Deserialize.cpp b/lib/Bitcode/Reader/Deserialize.cpp index 66df46ea23e..9caef6dae1e 100644 --- a/lib/Bitcode/Reader/Deserialize.cpp +++ b/lib/Bitcode/Reader/Deserialize.cpp @@ -16,14 +16,14 @@ 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& 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(); - 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(); + + 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(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(P); } - Allocator.Reset(); + if (Last) { + Last->Next = FreeList; + FreeList = getBPNode(); + } + + Ptr = reinterpret_cast(P); } + #define INT_READ(TYPE)\ void SerializeTrait::Read(Deserializer& D, TYPE& X) {\ X = (TYPE) D.ReadInt(); }\