[PGO] Convert InstrProfRecord based serialization methods to use common C methods

1. Convert serialization methods using InstrProfRecord as source into C (impl)
   interfaces using Closure.
2. Reimplement InstrProfRecord serialization method to use new C interface
   as dummy wrapper. 

Now it is ready to implement wrapper for runtime value profile data.

(The new code need better source location -- but not changed in this patch to
 minimize diffs. )

llvm-svn: 254057
This commit is contained in:
Xinliang David Li 2015-11-25 06:23:38 +00:00
parent ac5b860633
commit f47cf5505f
2 changed files with 109 additions and 48 deletions

View File

@ -474,9 +474,6 @@ typedef struct ValueProfRecord {
/// Read data from this record and save it to Record.
void deserializeTo(InstrProfRecord &Record,
InstrProfRecord::ValueMapType *VMap);
/// Extract data from \c Record and serialize into this instance.
void serializeFrom(const InstrProfRecord &Record, uint32_t ValueKind,
uint32_t NumValueSites);
/// In-place byte swap:
/// Do byte swap for this instance. \c Old is the original order before
/// the swap, and \c New is the New byte order.
@ -524,8 +521,6 @@ typedef struct ValueProfData {
/// Read data from this data and save it to \c Record.
void deserializeTo(InstrProfRecord &Record,
InstrProfRecord::ValueMapType *VMap);
/// Return the first \c ValueProfRecord instance.
ValueProfRecord *getFirstValueProfRecord();
} ValueProfData;
/* The closure is designed to abstact away two types of value profile data:
@ -542,21 +537,20 @@ typedef struct ValueProfData {
* in class InstrProfRecord.
*/
typedef struct ValueProfRecordClosure {
void *Record;
uint32_t (*GetNumValueKinds)(void *Record);
uint32_t (*GetNumValueSites)(void *Record, uint32_t VKind);
uint32_t (*GetNumValueData)(void *Record, uint32_t VKind);
uint32_t (*GetNumValueDataForSite)(void *R, uint32_t VK, uint32_t S);
const void *Record;
uint32_t (*GetNumValueKinds)(const void *Record);
uint32_t (*GetNumValueSites)(const void *Record, uint32_t VKind);
uint32_t (*GetNumValueData)(const void *Record, uint32_t VKind);
uint32_t (*GetNumValueDataForSite)(const void *R, uint32_t VK, uint32_t S);
/* After extracting the value profile data from the value profile record,
* this method is used to map the in-memory value to on-disk value. If
* the method is null, value will be written out untranslated.
*/
uint64_t (*RemapValueData)(uint32_t, uint64_t Value);
void (*GetValueForSite)(InstrProfValueData *Dst, void *R, uint32_t K,
void (*GetValueForSite)(const void *R, InstrProfValueData *Dst, uint32_t K,
uint32_t S, uint64_t (*Mapper)(uint32_t, uint64_t));
ValueProfData *(*AllocateValueProfData)(size_t TotalSizeInBytes);
ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes);
} ValueProfRecordClosure;
/// Return the \c ValueProfRecord header size including the padding bytes.
@ -599,6 +593,11 @@ inline ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) {
NumValueData));
}
/// Return the first \c ValueProfRecord instance.
inline ValueProfRecord *getFirstValueProfRecord(ValueProfData *This) {
return (ValueProfRecord *)((char *)This + sizeof(ValueProfData));
}
namespace IndexedInstrProf {
enum class HashT : uint32_t {

View File

@ -155,16 +155,21 @@ void ValueProfRecord::deserializeTo(InstrProfRecord &Record,
}
}
void ValueProfRecord::serializeFrom(const InstrProfRecord &Record,
uint32_t ValueKind,
uint32_t NumValueSites) {
Kind = ValueKind;
this->NumValueSites = NumValueSites;
InstrProfValueData *DstVD = getValueProfRecordValueData(this);
for (uint32_t S = 0; S < NumValueSites; S++) {
uint32_t ND = Record.getNumValueDataForSite(ValueKind, S);
SiteCountArray[S] = ND;
Record.getValueForSite(DstVD, ValueKind, S, stringToHash);
// Extract data from \c Closure and serialize into \c This instance.
void serializeValueProfRecordFrom(ValueProfRecord *This,
ValueProfRecordClosure *Closure,
uint32_t ValueKind, uint32_t NumValueSites) {
uint32_t S;
const void *Record = Closure->Record;
This->Kind = ValueKind;
This->NumValueSites = NumValueSites;
InstrProfValueData *DstVD = getValueProfRecordValueData(This);
for (S = 0; S < NumValueSites; S++) {
uint32_t ND = Closure->GetNumValueDataForSite(Record, ValueKind, S);
This->SiteCountArray[S] = ND;
Closure->GetValueForSite(Record, DstVD, ValueKind, S,
Closure->RemapValueData);
DstVD += ND;
}
}
@ -205,18 +210,22 @@ void ValueProfRecord::swapBytes(support::endianness Old,
}
}
uint32_t ValueProfData::getSize(const InstrProfRecord &Record) {
/// Return the total size in bytes of the on-disk value profile data
/// given the data stored in Record.
uint32_t getValueProfDataSize(ValueProfRecordClosure *Closure) {
uint32_t Kind;
uint32_t TotalSize = sizeof(ValueProfData);
uint32_t NumValueKinds = Record.getNumValueKinds();
const void *Record = Closure->Record;
uint32_t NumValueKinds = Closure->GetNumValueKinds(Record);
if (NumValueKinds == 0)
return TotalSize;
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
uint32_t NumValueSites = Record.getNumValueSites(Kind);
for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
uint32_t NumValueSites = Closure->GetNumValueSites(Record, Kind);
if (!NumValueSites)
continue;
TotalSize +=
getValueProfRecordSize(NumValueSites, Record.getNumValueData(Kind));
TotalSize += getValueProfRecordSize(NumValueSites,
Closure->GetNumValueData(Record, Kind));
}
return TotalSize;
}
@ -226,37 +235,95 @@ void ValueProfData::deserializeTo(InstrProfRecord &Record,
if (NumValueKinds == 0)
return;
ValueProfRecord *VR = getFirstValueProfRecord();
ValueProfRecord *VR = getFirstValueProfRecord(this);
for (uint32_t K = 0; K < NumValueKinds; K++) {
VR->deserializeTo(Record, VMap);
VR = getValueProfRecordNext(VR);
}
}
static std::unique_ptr<ValueProfData> AllocValueProfData(uint32_t TotalSize) {
static std::unique_ptr<ValueProfData> allocValueProfData(uint32_t TotalSize) {
return std::unique_ptr<ValueProfData>(new (::operator new(TotalSize))
ValueProfData());
}
std::unique_ptr<ValueProfData>
ValueProfData::serializeFrom(const InstrProfRecord &Record) {
uint32_t TotalSize = getSize(Record);
ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure) {
uint32_t TotalSize = getValueProfDataSize(Closure);
std::unique_ptr<ValueProfData> VPD = AllocValueProfData(TotalSize);
ValueProfData *VPD = Closure->AllocValueProfData(TotalSize);
VPD->TotalSize = TotalSize;
VPD->NumValueKinds = Record.getNumValueKinds();
ValueProfRecord *VR = VPD->getFirstValueProfRecord();
VPD->NumValueKinds = Closure->GetNumValueKinds(Closure->Record);
ValueProfRecord *VR = getFirstValueProfRecord(VPD);
for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
uint32_t NumValueSites = Record.getNumValueSites(Kind);
uint32_t NumValueSites = Closure->GetNumValueSites(Closure->Record, Kind);
if (!NumValueSites)
continue;
VR->serializeFrom(Record, Kind, NumValueSites);
serializeValueProfRecordFrom(VR, Closure, Kind, NumValueSites);
VR = getValueProfRecordNext(VR);
}
return VPD;
}
// C wrappers of InstrProfRecord member functions used in Closure.
// These C wrappers are used as adaptors so that C++ code can be
// invoked as callbacks.
uint32_t getNumValueKindsInstrProf(const void *Record) {
return reinterpret_cast<const InstrProfRecord *>(Record)->getNumValueKinds();
}
uint32_t getNumValueSitesInstrProf(const void *Record, uint32_t VKind) {
return reinterpret_cast<const InstrProfRecord *>(Record)
->getNumValueSites(VKind);
}
uint32_t getNumValueDataInstrProf(const void *Record, uint32_t VKind) {
return reinterpret_cast<const InstrProfRecord *>(Record)
->getNumValueData(VKind);
}
uint32_t getNumValueDataForSiteInstrProf(const void *R, uint32_t VK,
uint32_t S) {
return reinterpret_cast<const InstrProfRecord *>(R)
->getNumValueDataForSite(VK, S);
}
void getValueForSiteInstrProf(const void *R, InstrProfValueData *Dst,
uint32_t K, uint32_t S,
uint64_t (*Mapper)(uint32_t, uint64_t)) {
return reinterpret_cast<const InstrProfRecord *>(R)
->getValueForSite(Dst, K, S, Mapper);
}
ValueProfData *allocValueProfDataInstrProf(size_t TotalSizeInBytes) {
return (ValueProfData *)(new (::operator new(TotalSizeInBytes))
ValueProfData());
}
static ValueProfRecordClosure InstrProfRecordClosure = {
0,
getNumValueKindsInstrProf,
getNumValueSitesInstrProf,
getNumValueDataInstrProf,
getNumValueDataForSiteInstrProf,
stringToHash,
getValueForSiteInstrProf,
allocValueProfDataInstrProf};
uint32_t ValueProfData::getSize(const InstrProfRecord &Record) {
InstrProfRecordClosure.Record = &Record;
return getValueProfDataSize(&InstrProfRecordClosure);
}
std::unique_ptr<ValueProfData>
ValueProfData::serializeFrom(const InstrProfRecord &Record) {
InstrProfRecordClosure.Record = &Record;
std::unique_ptr<ValueProfData> VPD(
serializeValueProfDataFrom(&InstrProfRecordClosure));
return VPD;
}
ErrorOr<std::unique_ptr<ValueProfData>>
ValueProfData::getValueProfData(const unsigned char *D,
const unsigned char *const BufferEnd,
@ -277,14 +344,14 @@ ValueProfData::getValueProfData(const unsigned char *D,
if (TotalSize % sizeof(uint64_t))
return instrprof_error::malformed;
std::unique_ptr<ValueProfData> VPD = AllocValueProfData(TotalSize);
std::unique_ptr<ValueProfData> VPD = allocValueProfData(TotalSize);
memcpy(VPD.get(), D, TotalSize);
// Byte swap.
VPD->swapBytesToHost(Endianness);
// Data integrity check:
ValueProfRecord *VR = VPD->getFirstValueProfRecord();
ValueProfRecord *VR = getFirstValueProfRecord(VPD.get());
for (uint32_t K = 0; K < VPD->NumValueKinds; K++) {
if (VR->Kind > IPVK_Last)
return instrprof_error::malformed;
@ -304,7 +371,7 @@ void ValueProfData::swapBytesToHost(support::endianness Endianness) {
sys::swapByteOrder<uint32_t>(TotalSize);
sys::swapByteOrder<uint32_t>(NumValueKinds);
ValueProfRecord *VR = getFirstValueProfRecord();
ValueProfRecord *VR = getFirstValueProfRecord(this);
for (uint32_t K = 0; K < NumValueKinds; K++) {
VR->swapBytes(Endianness, getHostEndianness());
VR = getValueProfRecordNext(VR);
@ -316,7 +383,7 @@ void ValueProfData::swapBytesFromHost(support::endianness Endianness) {
if (Endianness == getHostEndianness())
return;
ValueProfRecord *VR = getFirstValueProfRecord();
ValueProfRecord *VR = getFirstValueProfRecord(this);
for (uint32_t K = 0; K < NumValueKinds; K++) {
ValueProfRecord *NVR = getValueProfRecordNext(VR);
VR->swapBytes(getHostEndianness(), Endianness);
@ -325,9 +392,4 @@ void ValueProfData::swapBytesFromHost(support::endianness Endianness) {
sys::swapByteOrder<uint32_t>(TotalSize);
sys::swapByteOrder<uint32_t>(NumValueKinds);
}
ValueProfRecord *ValueProfData::getFirstValueProfRecord() {
return reinterpret_cast<ValueProfRecord *>((char *)this +
sizeof(ValueProfData));
}
}