Make TypeSerializer's StringMap use the same allocator.

llvm-svn: 303576
This commit is contained in:
Zachary Turner 2017-05-22 21:07:14 +00:00
parent fb31da1306
commit 12f8c31c04
6 changed files with 26 additions and 46 deletions

View File

@ -45,12 +45,13 @@ class TypeSerializer : public TypeVisitorCallbacks {
} }
}; };
typedef SmallVector<MutableArrayRef<uint8_t>, 2> RecordList; typedef SmallVector<MutableArrayRef<uint8_t>, 2> MutableRecordList;
typedef SmallVector<ArrayRef<uint8_t>, 2> RecordList;
static constexpr uint8_t ContinuationLength = 8; static constexpr uint8_t ContinuationLength = 8;
BumpPtrAllocator &RecordStorage; BumpPtrAllocator &RecordStorage;
RecordSegment CurrentSegment; RecordSegment CurrentSegment;
RecordList FieldListSegments; MutableRecordList FieldListSegments;
TypeIndex LastTypeIndex; TypeIndex LastTypeIndex;
Optional<TypeLeafKind> TypeKind; Optional<TypeLeafKind> TypeKind;
@ -61,7 +62,7 @@ class TypeSerializer : public TypeVisitorCallbacks {
TypeRecordMapping Mapping; TypeRecordMapping Mapping;
RecordList SeenRecords; RecordList SeenRecords;
StringMap<TypeIndex> HashedRecords; StringMap<TypeIndex, BumpPtrAllocator&> HashedRecords;
bool isInFieldList() const; bool isInFieldList() const;
TypeIndex calcNextTypeIndex() const; TypeIndex calcNextTypeIndex() const;
@ -69,9 +70,7 @@ class TypeSerializer : public TypeVisitorCallbacks {
MutableArrayRef<uint8_t> getCurrentSubRecordData(); MutableArrayRef<uint8_t> getCurrentSubRecordData();
MutableArrayRef<uint8_t> getCurrentRecordData(); MutableArrayRef<uint8_t> getCurrentRecordData();
Error writeRecordPrefix(TypeLeafKind Kind); Error writeRecordPrefix(TypeLeafKind Kind);
TypeIndex insertRecordBytesPrivate(MutableArrayRef<uint8_t> Record); TypeIndex insertRecordBytesPrivate(ArrayRef<uint8_t> &Record);
TypeIndex insertRecordBytesWithCopy(CVType &Record,
MutableArrayRef<uint8_t> Data);
Expected<MutableArrayRef<uint8_t>> Expected<MutableArrayRef<uint8_t>>
addPadding(MutableArrayRef<uint8_t> Record); addPadding(MutableArrayRef<uint8_t> Record);
@ -79,9 +78,9 @@ class TypeSerializer : public TypeVisitorCallbacks {
public: public:
explicit TypeSerializer(BumpPtrAllocator &Storage); explicit TypeSerializer(BumpPtrAllocator &Storage);
ArrayRef<MutableArrayRef<uint8_t>> records() const; ArrayRef<ArrayRef<uint8_t>> records() const;
TypeIndex getLastTypeIndex() const; TypeIndex getLastTypeIndex() const;
TypeIndex insertRecordBytes(MutableArrayRef<uint8_t> Record); TypeIndex insertRecordBytes(ArrayRef<uint8_t> Record);
Expected<TypeIndex> visitTypeEndGetIndex(CVType &Record); Expected<TypeIndex> visitTypeEndGetIndex(CVType &Record);
Error visitTypeBegin(CVType &Record) override; Error visitTypeBegin(CVType &Record) override;

View File

@ -64,7 +64,7 @@ public:
return *ExpectedIndex; return *ExpectedIndex;
} }
TypeIndex writeSerializedRecord(MutableArrayRef<uint8_t> Record) { TypeIndex writeSerializedRecord(ArrayRef<uint8_t> Record) {
return Serializer.insertRecordBytes(Record); return Serializer.insertRecordBytes(Record);
} }
@ -77,7 +77,7 @@ public:
} }
} }
ArrayRef<MutableArrayRef<uint8_t>> records() const { ArrayRef<ArrayRef<uint8_t>> records() const {
return Serializer.records(); return Serializer.records();
} }
}; };

View File

@ -18,7 +18,7 @@ namespace codeview {
class TypeTableCollection : public TypeCollection { class TypeTableCollection : public TypeCollection {
public: public:
explicit TypeTableCollection(ArrayRef<MutableArrayRef<uint8_t>> Records); explicit TypeTableCollection(ArrayRef<ArrayRef<uint8_t>> Records);
Optional<TypeIndex> getFirst() override; Optional<TypeIndex> getFirst() override;
Optional<TypeIndex> getNext(TypeIndex Prev) override; Optional<TypeIndex> getNext(TypeIndex Prev) override;
@ -33,7 +33,7 @@ private:
bool hasCapacityFor(TypeIndex Index) const; bool hasCapacityFor(TypeIndex Index) const;
void ensureTypeExists(TypeIndex Index); void ensureTypeExists(TypeIndex Index);
ArrayRef<MutableArrayRef<uint8_t>> Records; ArrayRef<ArrayRef<uint8_t>> Records;
TypeDatabase Database; TypeDatabase Database;
}; };
} }

View File

@ -52,45 +52,26 @@ Error TypeSerializer::writeRecordPrefix(TypeLeafKind Kind) {
} }
TypeIndex TypeIndex
TypeSerializer::insertRecordBytesPrivate(MutableArrayRef<uint8_t> Record) { TypeSerializer::insertRecordBytesPrivate(ArrayRef<uint8_t> &Record) {
assert(Record.size() % 4 == 0 && "Record is not aligned to 4 bytes!"); assert(Record.size() % 4 == 0 && "Record is not aligned to 4 bytes!");
StringRef S(reinterpret_cast<const char *>(Record.data()), Record.size()); StringRef S(reinterpret_cast<const char *>(Record.data()), Record.size());
TypeIndex NextTypeIndex = calcNextTypeIndex(); TypeIndex NextTypeIndex = calcNextTypeIndex();
auto Result = HashedRecords.try_emplace(S, NextTypeIndex); auto Result = HashedRecords.try_emplace(S, NextTypeIndex);
StringRef NewData = Result.first->getKey();
Record = ArrayRef<uint8_t>(NewData.bytes_begin(), NewData.bytes_end());
if (Result.second) { if (Result.second) {
// If this triggered an insert into the map, store the bytes.
LastTypeIndex = NextTypeIndex; LastTypeIndex = NextTypeIndex;
SeenRecords.push_back(Record); SeenRecords.push_back(Record);
} }
return Result.first->getValue(); return Result.first->getValue();
} }
TypeIndex
TypeSerializer::insertRecordBytesWithCopy(CVType &Record,
MutableArrayRef<uint8_t> Data) {
assert(Data.size() % 4 == 0 && "Record is not aligned to 4 bytes!");
StringRef S(reinterpret_cast<const char *>(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<uint8_t>(Data.size());
::memcpy(Copy, Data.data(), Data.size());
Data = MutableArrayRef<uint8_t>(Copy, Data.size());
S = StringRef(reinterpret_cast<const char *>(Data.data()), Data.size());
HashedRecords.insert(std::make_pair(S, LastTypeIndex));
SeenRecords.push_back(Data);
Record.RecordData = Data;
return LastTypeIndex;
}
Expected<MutableArrayRef<uint8_t>> Expected<MutableArrayRef<uint8_t>>
TypeSerializer::addPadding(MutableArrayRef<uint8_t> Record) { TypeSerializer::addPadding(MutableArrayRef<uint8_t> Record) {
uint32_t Align = Record.size() % 4; uint32_t Align = Record.size() % 4;
@ -112,19 +93,19 @@ TypeSerializer::TypeSerializer(BumpPtrAllocator &Storage)
: RecordStorage(Storage), LastTypeIndex(), : RecordStorage(Storage), LastTypeIndex(),
RecordBuffer(MaxRecordLength * 2), RecordBuffer(MaxRecordLength * 2),
Stream(RecordBuffer, llvm::support::little), Writer(Stream), Stream(RecordBuffer, llvm::support::little), Writer(Stream),
Mapping(Writer) { Mapping(Writer), HashedRecords(Storage) {
// RecordBuffer needs to be able to hold enough data so that if we are 1 // RecordBuffer needs to be able to hold enough data so that if we are 1
// byte short of MaxRecordLen, and then we try to write MaxRecordLen bytes, // byte short of MaxRecordLen, and then we try to write MaxRecordLen bytes,
// we won't overflow. // we won't overflow.
} }
ArrayRef<MutableArrayRef<uint8_t>> TypeSerializer::records() const { ArrayRef<ArrayRef<uint8_t>> TypeSerializer::records() const {
return SeenRecords; return SeenRecords;
} }
TypeIndex TypeSerializer::getLastTypeIndex() const { return LastTypeIndex; } TypeIndex TypeSerializer::getLastTypeIndex() const { return LastTypeIndex; }
TypeIndex TypeSerializer::insertRecordBytes(MutableArrayRef<uint8_t> Record) { TypeIndex TypeSerializer::insertRecordBytes(ArrayRef<uint8_t> Record) {
assert(!TypeKind.hasValue() && "Already in a type mapping!"); assert(!TypeKind.hasValue() && "Already in a type mapping!");
assert(Writer.getOffset() == 0 && "Stream has data already!"); assert(Writer.getOffset() == 0 && "Stream has data already!");
@ -163,8 +144,8 @@ Expected<TypeIndex> TypeSerializer::visitTypeEndGetIndex(CVType &Record) {
Prefix->RecordLen = ThisRecordData.size() - sizeof(uint16_t); Prefix->RecordLen = ThisRecordData.size() - sizeof(uint16_t);
Record.Type = *TypeKind; Record.Type = *TypeKind;
TypeIndex InsertedTypeIndex = Record.RecordData = ThisRecordData;
insertRecordBytesWithCopy(Record, ThisRecordData); TypeIndex InsertedTypeIndex = insertRecordBytesPrivate(Record.RecordData);
// Write out each additional segment in reverse order, and update each // Write out each additional segment in reverse order, and update each
// record's continuation index to point to the previous one. // record's continuation index to point to the previous one.

View File

@ -25,7 +25,7 @@ static void error(Error &&EC) {
} }
TypeTableCollection::TypeTableCollection( TypeTableCollection::TypeTableCollection(
ArrayRef<MutableArrayRef<uint8_t>> Records) ArrayRef<ArrayRef<uint8_t>> Records)
: Records(Records), Database(Records.size()) {} : Records(Records), Database(Records.size()) {}
Optional<TypeIndex> TypeTableCollection::getFirst() { Optional<TypeIndex> TypeTableCollection::getFirst() {

View File

@ -878,11 +878,11 @@ static void mergePdbs() {
auto &DestTpi = Builder.getTpiBuilder(); auto &DestTpi = Builder.getTpiBuilder();
auto &DestIpi = Builder.getIpiBuilder(); auto &DestIpi = Builder.getIpiBuilder();
MergedTpi.ForEachRecord( MergedTpi.ForEachRecord(
[&DestTpi](TypeIndex TI, MutableArrayRef<uint8_t> Data) { [&DestTpi](TypeIndex TI, ArrayRef<uint8_t> Data) {
DestTpi.addTypeRecord(Data, None); DestTpi.addTypeRecord(Data, None);
}); });
MergedIpi.ForEachRecord( MergedIpi.ForEachRecord(
[&DestIpi](TypeIndex TI, MutableArrayRef<uint8_t> Data) { [&DestIpi](TypeIndex TI, ArrayRef<uint8_t> Data) {
DestIpi.addTypeRecord(Data, None); DestIpi.addTypeRecord(Data, None);
}); });