[PGO] Convert InstrProfRecord based serialization methods to use common C methods
authorXinliang David Li <davidxl@google.com>
Wed, 25 Nov 2015 06:23:38 +0000 (06:23 +0000)
committerXinliang David Li <davidxl@google.com>
Wed, 25 Nov 2015 06:23:38 +0000 (06:23 +0000)
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. )

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254057 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ProfileData/InstrProf.h
lib/ProfileData/InstrProf.cpp

index c03f6cc..3c1a4d0 100644 (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);
   /// 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.
   /// 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);
   /// 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:
 } 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 {
  * 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);
 
   /* 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));
                           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.
 } ValueProfRecordClosure;
 
 /// Return the \c ValueProfRecord header size including the padding bytes.
@@ -599,6 +593,11 @@ inline ValueProfRecord *getValueProfRecordNext(ValueProfRecord *This) {
                                                     NumValueData));
 }
 
                                                     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 {
 namespace IndexedInstrProf {
 
 enum class HashT : uint32_t {
index 34a354d..87757af 100644 (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;
   }
 }
     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 TotalSize = sizeof(ValueProfData);
-  uint32_t NumValueKinds = Record.getNumValueKinds();
+  const void *Record = Closure->Record;
+  uint32_t NumValueKinds = Closure->GetNumValueKinds(Record);
   if (NumValueKinds == 0)
     return TotalSize;
 
   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;
     if (!NumValueSites)
       continue;
-    TotalSize +=
-        getValueProfRecordSize(NumValueSites, Record.getNumValueData(Kind));
+    TotalSize += getValueProfRecordSize(NumValueSites,
+                                        Closure->GetNumValueData(Record, Kind));
   }
   return TotalSize;
 }
   }
   return TotalSize;
 }
@@ -226,37 +235,95 @@ void ValueProfData::deserializeTo(InstrProfRecord &Record,
   if (NumValueKinds == 0)
     return;
 
   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);
   }
 }
 
   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());
 }
 
   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->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++) {
   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;
     if (!NumValueSites)
       continue;
-    VR->serializeFrom(Record, Kind, NumValueSites);
+    serializeValueProfRecordFrom(VR, Closure, Kind, NumValueSites);
     VR = getValueProfRecordNext(VR);
   }
   return VPD;
 }
 
     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,
 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;
 
   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:
 
   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;
   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);
 
   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);
   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;
 
   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);
   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);
 }
   sys::swapByteOrder<uint32_t>(TotalSize);
   sys::swapByteOrder<uint32_t>(NumValueKinds);
 }
-
-ValueProfRecord *ValueProfData::getFirstValueProfRecord() {
-  return reinterpret_cast<ValueProfRecord *>((char *)this +
-                                             sizeof(ValueProfData));
-}
 }
 }