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