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(); }\