1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

ADT: Sink the guts of StringMapEntry::Create into StringMapEntryBase

Sink the interesting parts of StringMapEntry::Create into a new function
StringMapEntryBase::allocateWithKey that's only templated on the
allocator, taking the entry size and alignment as parameters.

As dblaikie pointed out in the review, it'd be interesting as a
follow-up to make this more generic and maybe sink at least some of it
into a source file; I haven't done that yet myself, but I left behind an
encouraging comment.

Differential Revision: https://reviews.llvm.org/D95654
This commit is contained in:
Duncan P. N. Exon Smith 2021-01-28 15:43:04 -08:00
parent b6df56d660
commit c70b8c71ee

View File

@ -27,8 +27,37 @@ public:
explicit StringMapEntryBase(size_t keyLength) : keyLength(keyLength) {}
size_t getKeyLength() const { return keyLength; }
protected:
/// Helper to tail-allocate \p Key. It'd be nice to generalize this so it
/// could be reused elsewhere, maybe even taking an llvm::function_ref to
/// type-erase the allocator and put it in a source file.
template <typename AllocatorTy>
static void *allocateWithKey(size_t EntrySize, size_t EntryAlign,
StringRef Key, AllocatorTy &Allocator);
};
// Define out-of-line to dissuade inlining.
template <typename AllocatorTy>
void *StringMapEntryBase::allocateWithKey(size_t EntrySize, size_t EntryAlign,
StringRef Key,
AllocatorTy &Allocator) {
size_t KeyLength = Key.size();
// Allocate a new item with space for the string at the end and a null
// terminator.
size_t AllocSize = EntrySize + KeyLength + 1;
void *Allocation = Allocator.Allocate(AllocSize, EntryAlign);
assert(Allocation && "Unhandled out-of-memory");
// Copy the string information.
char *Buffer = reinterpret_cast<char *>(Allocation) + EntrySize;
if (KeyLength > 0)
::memcpy(Buffer, Key.data(), KeyLength);
Buffer[KeyLength] = 0; // Null terminate for convenience of clients.
return Allocation;
}
/// StringMapEntryStorage - Holds the value in a StringMapEntry.
///
/// Factored out into a separate base class to make it easier to specialize.
@ -90,26 +119,9 @@ public:
template <typename AllocatorTy, typename... InitTy>
static StringMapEntry *Create(StringRef key, AllocatorTy &allocator,
InitTy &&... initVals) {
size_t keyLength = key.size();
// Allocate a new item with space for the string at the end and a null
// terminator.
size_t allocSize = sizeof(StringMapEntry) + keyLength + 1;
size_t alignment = alignof(StringMapEntry);
StringMapEntry *newItem =
static_cast<StringMapEntry *>(allocator.Allocate(allocSize, alignment));
assert(newItem && "Unhandled out-of-memory");
// Construct the value.
new (newItem) StringMapEntry(keyLength, std::forward<InitTy>(initVals)...);
// Copy the string information.
char *strBuffer = const_cast<char *>(newItem->getKeyData());
if (keyLength > 0)
memcpy(strBuffer, key.data(), keyLength);
strBuffer[keyLength] = 0; // Null terminate for convenience of clients.
return newItem;
return new (StringMapEntryBase::allocateWithKey(
sizeof(StringMapEntry), alignof(StringMapEntry), key, allocator))
StringMapEntry(key.size(), std::forward<InitTy>(initVals)...);
}
/// GetStringMapEntryFromKeyData - Given key data that is known to be embedded