From 59ab6a381602f102d259706b7cdb13208e31a7bc Mon Sep 17 00:00:00 2001 From: Zachary Turner Date: Fri, 19 May 2017 04:56:48 +0000 Subject: [PATCH] [CodeView] Reduce memory usage in TypeSerializer. We were using a BumpPtrAllocator to allocate stable storage for a record, then trying to insert that into a hash table. If a collision occurred, the bytes were never inserted and the allocation was unnecessary. At the cost of an extra hash computation, check first if it exists, and only if it does do we allocate and insert. llvm-svn: 303407 --- .../llvm/DebugInfo/CodeView/TypeSerializer.h | 2 ++ .../lib/DebugInfo/CodeView/TypeSerializer.cpp | 33 ++++++++++++++++--- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h b/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h index 1f4873c4f969..6dad98247136 100644 --- a/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h +++ b/llvm/include/llvm/DebugInfo/CodeView/TypeSerializer.h @@ -70,6 +70,8 @@ class TypeSerializer : public TypeVisitorCallbacks { MutableArrayRef getCurrentRecordData(); Error writeRecordPrefix(TypeLeafKind Kind); TypeIndex insertRecordBytesPrivate(MutableArrayRef Record); + TypeIndex insertRecordBytesWithCopy(CVType &Record, + MutableArrayRef Data); Expected> addPadding(MutableArrayRef Record); diff --git a/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp b/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp index fd4d1853fa54..3b061e67e05e 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeSerializer.cpp @@ -66,6 +66,31 @@ TypeSerializer::insertRecordBytesPrivate(MutableArrayRef Record) { return Result.first->getValue(); } +TypeIndex +TypeSerializer::insertRecordBytesWithCopy(CVType &Record, + MutableArrayRef Data) { + assert(Data.size() % 4 == 0 && "Record is not aligned to 4 bytes!"); + + StringRef S(reinterpret_cast(Data.data()), Data.size()); + + // Do a two state lookup / insert so that we don't have to allocate unless + // we're going + // to do an insert. This is a big memory savings. + auto Iter = HashedRecords.find(S); + if (Iter != HashedRecords.end()) + return Iter->second; + + LastTypeIndex = calcNextTypeIndex(); + uint8_t *Copy = RecordStorage.Allocate(Data.size()); + ::memcpy(Copy, Data.data(), Data.size()); + Data = MutableArrayRef(Copy, Data.size()); + S = StringRef(reinterpret_cast(Data.data()), Data.size()); + HashedRecords.insert(std::make_pair(S, LastTypeIndex)); + SeenRecords.push_back(Data); + Record.RecordData = Data; + return LastTypeIndex; +} + Expected> TypeSerializer::addPadding(MutableArrayRef Record) { uint32_t Align = Record.size() % 4; @@ -137,11 +162,9 @@ Expected TypeSerializer::visitTypeEndGetIndex(CVType &Record) { reinterpret_cast(ThisRecordData.data()); Prefix->RecordLen = ThisRecordData.size() - sizeof(uint16_t); - uint8_t *Copy = RecordStorage.Allocate(ThisRecordData.size()); - ::memcpy(Copy, ThisRecordData.data(), ThisRecordData.size()); - ThisRecordData = MutableArrayRef(Copy, ThisRecordData.size()); - Record = CVType(*TypeKind, ThisRecordData); - TypeIndex InsertedTypeIndex = insertRecordBytesPrivate(ThisRecordData); + Record.Type = *TypeKind; + TypeIndex InsertedTypeIndex = + insertRecordBytesWithCopy(Record, ThisRecordData); // Write out each additional segment in reverse order, and update each // record's continuation index to point to the previous one.