forked from OSchip/llvm-project
Rewrote backpatcher. Backpatcher now stores the "has final pointer"
flag in the **key** of the backpatch map, as opposed to the mapped value which contains either the final pointer, or a pointer to a chain of pointers that need to be backpatched. The bit flag was moved to the key because we were erroneously assuming that the backpatched pointers would be at an alignment of >= 2 bytes, which obviously doesn't work for character strings. Now we just steal the bit from the key. llvm-svn: 43595
This commit is contained in:
parent
df0768e1b1
commit
fb764e52b0
|
@ -30,54 +30,49 @@ class Deserializer {
|
||||||
//===----------------------------------------------------------===//
|
//===----------------------------------------------------------===//
|
||||||
// Internal type definitions.
|
// Internal type definitions.
|
||||||
//===----------------------------------------------------------===//
|
//===----------------------------------------------------------===//
|
||||||
|
|
||||||
struct PtrIdInfo {
|
|
||||||
static inline unsigned getEmptyKey() { return ~((unsigned) 0x0); }
|
|
||||||
static inline unsigned getTombstoneKey() { return getEmptyKey()-1; }
|
|
||||||
static inline unsigned getHashValue(unsigned X) { return X; }
|
|
||||||
static inline bool isEqual(unsigned X, unsigned Y) { return X == Y; }
|
|
||||||
static inline bool isPod() { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BPNode {
|
struct BPNode {
|
||||||
BPNode* Next;
|
BPNode* Next;
|
||||||
uintptr_t& PtrRef;
|
uintptr_t& PtrRef;
|
||||||
|
|
||||||
BPNode(BPNode* n, uintptr_t& pref)
|
BPNode(BPNode* n, uintptr_t& pref)
|
||||||
: Next(n), PtrRef(pref) {
|
: Next(n), PtrRef(pref) {
|
||||||
PtrRef = 0;
|
PtrRef = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class BPatchEntry {
|
struct BPEntry {
|
||||||
uintptr_t Ptr;
|
union { BPNode* Head; void* Ptr; };
|
||||||
public:
|
|
||||||
|
|
||||||
BPatchEntry() : Ptr(0x1) {}
|
BPEntry() : Head(NULL) {}
|
||||||
|
|
||||||
BPatchEntry(void* P) : Ptr(reinterpret_cast<uintptr_t>(P)) {}
|
|
||||||
|
|
||||||
bool hasFinalPtr() const { return Ptr & 0x1 ? false : true; }
|
|
||||||
void setFinalPtr(BPNode*& FreeList, const 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 getFinalPtr() const {
|
|
||||||
assert (!(Ptr & 0x1) && "Backpatch pointer not yet deserialized.");
|
|
||||||
return Ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool isPod() { return true; }
|
static inline bool isPod() { return true; }
|
||||||
};
|
|
||||||
|
void SetPtr(BPNode*& FreeList, void* P);
|
||||||
|
};
|
||||||
|
|
||||||
|
class BPKey {
|
||||||
|
unsigned Raw;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BPKey(unsigned PtrId) : Raw(PtrId << 1) { assert (PtrId > 0); }
|
||||||
|
|
||||||
|
void MarkFinal() { Raw |= 0x1; }
|
||||||
|
bool hasFinalPtr() const { return Raw & 0x1 ? true : false; }
|
||||||
|
unsigned getID() const { return Raw >> 1; }
|
||||||
|
|
||||||
|
static inline BPKey getEmptyKey() { return 0; }
|
||||||
|
static inline BPKey getTombstoneKey() { return 1; }
|
||||||
|
static inline unsigned getHashValue(const BPKey& K) { return K.Raw & ~0x1; }
|
||||||
|
|
||||||
typedef llvm::DenseMap<unsigned,BPatchEntry,PtrIdInfo,BPatchEntry> MapTy;
|
static bool isEqual(const BPKey& K1, const BPKey& K2) {
|
||||||
|
return (K1.Raw ^ K2.Raw) & ~0x1 ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isPod() { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef llvm::DenseMap<BPKey,BPEntry,BPKey,BPEntry> MapTy;
|
||||||
|
|
||||||
//===----------------------------------------------------------===//
|
//===----------------------------------------------------------===//
|
||||||
// Internal data members.
|
// Internal data members.
|
||||||
|
@ -162,6 +157,27 @@ private:
|
||||||
void ReadRecord();
|
void ReadRecord();
|
||||||
bool inRecord();
|
bool inRecord();
|
||||||
uintptr_t ReadInternalRefPtr();
|
uintptr_t ReadInternalRefPtr();
|
||||||
|
|
||||||
|
static inline bool HasFinalPtr(MapTy::value_type& V) {
|
||||||
|
return V.first.hasFinalPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uintptr_t GetFinalPtr(MapTy::value_type& V) {
|
||||||
|
return reinterpret_cast<uintptr_t>(V.second.Ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline BPNode* GetBPNode(MapTy::value_type& V) {
|
||||||
|
return V.second.Head;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void SetBPNode(MapTy::value_type& V, BPNode* N) {
|
||||||
|
V.second.Head = N;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetPtr(MapTy::value_type& V, const void* P) {
|
||||||
|
V.first.MarkFinal();
|
||||||
|
V.second.SetPtr(FreeList,const_cast<void*>(P));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
|
@ -25,7 +25,7 @@ Deserializer::~Deserializer() {
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
|
for (MapTy::iterator I=BPatchMap.begin(), E=BPatchMap.end(); I!=E; ++I)
|
||||||
assert (I->second.hasFinalPtr() &&
|
assert (I->first.hasFinalPtr() &&
|
||||||
"Some pointers were not backpatched.");
|
"Some pointers were not backpatched.");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -99,9 +99,11 @@ void Deserializer::ReadCStr(std::vector<char>& buff, bool isNullTerm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Deserializer::RegisterPtr(unsigned PtrId, const void* Ptr) {
|
void Deserializer::RegisterPtr(unsigned PtrId, const void* Ptr) {
|
||||||
BPatchEntry& E = BPatchMap[PtrId];
|
MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
|
||||||
assert (!E.hasFinalPtr() && "Pointer already registered.");
|
|
||||||
E.setFinalPtr(FreeList,Ptr);
|
assert (!HasFinalPtr(E) && "Pointer already registered.");
|
||||||
|
|
||||||
|
SetPtr(E,Ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Deserializer::ReadUIntPtr(uintptr_t& PtrRef) {
|
void Deserializer::ReadUIntPtr(uintptr_t& PtrRef) {
|
||||||
|
@ -111,11 +113,11 @@ void Deserializer::ReadUIntPtr(uintptr_t& PtrRef) {
|
||||||
PtrRef = 0;
|
PtrRef = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
|
||||||
|
|
||||||
BPatchEntry& E = BPatchMap[PtrId];
|
if (HasFinalPtr(E))
|
||||||
|
PtrRef = GetFinalPtr(E);
|
||||||
if (E.hasFinalPtr())
|
|
||||||
PtrRef = E.getFinalPtr();
|
|
||||||
else {
|
else {
|
||||||
// Register backpatch. Check the freelist for a BPNode.
|
// Register backpatch. Check the freelist for a BPNode.
|
||||||
BPNode* N;
|
BPNode* N;
|
||||||
|
@ -127,8 +129,8 @@ void Deserializer::ReadUIntPtr(uintptr_t& PtrRef) {
|
||||||
else // No available BPNode. Allocate one.
|
else // No available BPNode. Allocate one.
|
||||||
N = (BPNode*) Allocator.Allocate<BPNode>();
|
N = (BPNode*) Allocator.Allocate<BPNode>();
|
||||||
|
|
||||||
new (N) BPNode(E.getBPNode(),PtrRef);
|
new (N) BPNode(GetBPNode(E),PtrRef);
|
||||||
E.setBPNode(N);
|
SetBPNode(E,N);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,32 +139,28 @@ uintptr_t Deserializer::ReadInternalRefPtr() {
|
||||||
|
|
||||||
assert (PtrId != 0 && "References cannot refer the NULL address.");
|
assert (PtrId != 0 && "References cannot refer the NULL address.");
|
||||||
|
|
||||||
BPatchEntry& E = BPatchMap[PtrId];
|
MapTy::value_type& E = BPatchMap.FindAndConstruct(BPKey(PtrId));
|
||||||
|
|
||||||
assert (E.hasFinalPtr() &&
|
assert (!HasFinalPtr(E) &&
|
||||||
"Cannot backpatch references. Object must be already deserialized.");
|
"Cannot backpatch references. Object must be already deserialized.");
|
||||||
|
|
||||||
return E.getFinalPtr();
|
return GetFinalPtr(E);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Deserializer::BPatchEntry::setFinalPtr(BPNode*& FreeList, const void* P) {
|
void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
|
||||||
assert (!hasFinalPtr());
|
|
||||||
|
|
||||||
// Perform backpatching.
|
|
||||||
|
|
||||||
BPNode* Last = NULL;
|
BPNode* Last = NULL;
|
||||||
|
|
||||||
for (BPNode* N = getBPNode() ; N != NULL; N = N->Next) {
|
for (BPNode* N = Head; N != NULL; N=N->Next) {
|
||||||
Last = N;
|
Last = N;
|
||||||
N->PtrRef |= reinterpret_cast<uintptr_t>(P);
|
N->PtrRef |= reinterpret_cast<uintptr_t>(P);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Last) {
|
if (Last) {
|
||||||
Last->Next = FreeList;
|
Last->Next = FreeList;
|
||||||
FreeList = getBPNode();
|
FreeList = Head;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ptr = reinterpret_cast<uintptr_t>(P);
|
Ptr = const_cast<void*>(P);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue