[compiler-rt] r269576 - [profile] Eliminate dynamic memory allocation for vp writing

Xinliang David Li via llvm-commits llvm-commits at lists.llvm.org
Sat May 14 13:12:43 PDT 2016


Author: davidxl
Date: Sat May 14 15:12:42 2016
New Revision: 269576

URL: http://llvm.org/viewvc/llvm-project?rev=269576&view=rev
Log:
[profile] Eliminate dynamic memory allocation for vp writing

This is part-3 of the effort to eliminate dependency on
libc allocator in instr profiler runtime. With this change,
the profile dumper is completely free of malloc/calloc. 
Value profile instr API implementation is the only remaining
piece with calloc dependency.


Modified:
    compiler-rt/trunk/lib/profile/InstrProfData.inc
    compiler-rt/trunk/lib/profile/InstrProfilingFile.c
    compiler-rt/trunk/lib/profile/InstrProfilingInternal.h
    compiler-rt/trunk/lib/profile/InstrProfilingPort.h
    compiler-rt/trunk/lib/profile/InstrProfilingValue.c
    compiler-rt/trunk/lib/profile/InstrProfilingWriter.c

Modified: compiler-rt/trunk/lib/profile/InstrProfData.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfData.inc?rev=269576&r1=269575&r2=269576&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfData.inc (original)
+++ compiler-rt/trunk/lib/profile/InstrProfData.inc Sat May 14 15:12:42 2016
@@ -361,32 +361,11 @@ typedef struct ValueProfRecordClosure {
   ValueProfData *(*AllocValueProfData)(size_t TotalSizeInBytes);
 } ValueProfRecordClosure;
 
-/*
- * A wrapper struct that represents value profile runtime data.
- * Like InstrProfRecord class which is used by profiling host tools,
- * ValueProfRuntimeRecord also implements the abstract intefaces defined in
- * ValueProfRecordClosure so that the runtime data can be serialized using
- * shared C implementation. In this structure, NumValueSites and Nodes
- * members are the primary fields while other fields hold the derived
- * information for fast implementation of closure interfaces.
- */
-typedef struct ValueProfRuntimeRecord {
-  /* Number of sites for each value profile kind.  */
-  const uint16_t *NumValueSites;
-  /* An array of linked-list headers. The size of of the array is the
-   * total number of value profile sites : sum(NumValueSites[*])). Each
-   * linked-list stores the values profiled for a value profile site. */
-  ValueProfNode **Nodes;
-
-  /* Total number of value profile kinds which have at least one
-   *  value profile sites. */
-  uint32_t NumValueKinds;
-  ValueProfNode **NodesKind[IPVK_Last + 1];
-} ValueProfRuntimeRecord;
 
 ValueProfRecord *getFirstValueProfRecord(ValueProfData *VPD);
 ValueProfRecord *getValueProfRecordNext(ValueProfRecord *VPR);
 InstrProfValueData *getValueProfRecordValueData(ValueProfRecord *VPR);
+uint32_t getValueProfRecordHeaderSize(uint32_t NumValueSites);
 
 #undef INSTR_PROF_VALUE_PROF_DATA
 #endif  /* INSTR_PROF_VALUE_PROF_DATA */
@@ -480,9 +459,6 @@ uint32_t getValueProfDataSize(ValueProfR
   uint32_t Kind;
   uint32_t TotalSize = sizeof(ValueProfData);
   const void *Record = Closure->Record;
-  uint32_t NumValueKinds = Closure->GetNumValueKinds(Record);
-  if (NumValueKinds == 0)
-    return TotalSize;
 
   for (Kind = IPVK_First; Kind <= IPVK_Last; Kind++) {
     uint32_t NumValueSites = Closure->GetNumValueSites(Record, Kind);
@@ -525,7 +501,7 @@ void serializeValueProfRecordFrom(ValueP
 ValueProfData *serializeValueProfDataFrom(ValueProfRecordClosure *Closure,
                                           ValueProfData *DstData) {
   uint32_t Kind;
-  uint32_t TotalSize = 
+  uint32_t TotalSize =
       DstData ? DstData->TotalSize : getValueProfDataSize(Closure);
 
   ValueProfData *VPD =

Modified: compiler-rt/trunk/lib/profile/InstrProfilingFile.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingFile.c?rev=269576&r1=269575&r2=269576&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingFile.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingFile.c Sat May 14 15:12:42 2016
@@ -50,7 +50,7 @@ static void setupIOBuffer() {
 static int writeFile(FILE *File) {
   FreeHook = &free;
   setupIOBuffer();
-  return lprofWriteData(fileWriter, File, lprofGatherValueProfData);
+  return lprofWriteData(fileWriter, File, lprofGetVPDataReader());
 }
 
 static int writeFileWithName(const char *OutputName) {

Modified: compiler-rt/trunk/lib/profile/InstrProfilingInternal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingInternal.h?rev=269576&r1=269575&r2=269576&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingInternal.h (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingInternal.h Sat May 14 15:12:42 2016
@@ -99,25 +99,57 @@ int lprofBufferIOFlush(ProfBufferIO *Buf
 uint32_t lprofBufferWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs,
                            void **WriterCtx);
 
-typedef struct ValueProfData *(*VPGatherHookType)(
-    const __llvm_profile_data *Data);
+struct ValueProfData;
+struct ValueProfRecord;
+struct InstrProfValueData;
+struct ValueProfNode;
+
+/*!
+ * The class that defines a set of methods to read value profile
+ * data for streaming/serialization from the instrumentation runtime.
+ */
+typedef struct VPDataReaderType {
+  uint32_t (*InitRTRecord)(const __llvm_profile_data *Data,
+                           uint8_t *SiteCountArray[]);
+  /* Function pointer to getValueProfRecordHeader method. */
+  uint32_t (*GetValueProfRecordHeaderSize)(uint32_t NumSites);
+  /* Function pointer to getFristValueProfRecord method. */  
+  struct ValueProfRecord *(*GetFirstValueProfRecord)(struct ValueProfData *);
+  /* Return the number of value data for site \p Site.  */
+  uint32_t (*GetNumValueDataForSite)(uint32_t VK, uint32_t Site);
+  /* Return the total size of the value profile data of the 
+   * current function.  */
+  uint32_t (*GetValueProfDataSize)(void);
+  /*! 
+   * Read the next \p N value data for site \p Site and store the data
+   * in \p Dst. \p StartNode is the first value node to start with if
+   * it is not null. The function returns the pointer to the value
+   * node pointer to be used as the \p StartNode of the next batch reading.
+   * If there is nothing left, it returns NULL.
+   */
+  struct ValueProfNode *(*GetValueData)(uint32_t ValueKind, uint32_t Site,
+                                        struct InstrProfValueData *Dst,
+                                        struct ValueProfNode *StartNode,
+                                        uint32_t N);
+} VPDataReaderType;
+
 int lprofWriteData(WriterCallback Writer, void *WriterCtx,
-                   VPGatherHookType VPDataGatherer);
+                   VPDataReaderType *VPDataReader);
 int lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
                        const __llvm_profile_data *DataBegin,
                        const __llvm_profile_data *DataEnd,
                        const uint64_t *CountersBegin,
                        const uint64_t *CountersEnd,
-                       VPGatherHookType VPDataGatherer, const char *NamesBegin,
+                       VPDataReaderType *VPDataReader, const char *NamesBegin,
                        const char *NamesEnd);
-/* Gather value profile data from \c Data and return it. */
-struct ValueProfData *lprofGatherValueProfData(const __llvm_profile_data *Data);
 
 /* Merge value profile data pointed to by SrcValueProfData into
  * in-memory profile counters pointed by to DstData.  */
 void lprofMergeValueProfData(struct ValueProfData *SrcValueProfData,
                              __llvm_profile_data *DstData);
 
+VPDataReaderType *lprofGetVPDataReader();
+
 COMPILER_RT_VISIBILITY extern char *(*GetEnvHook)(const char *);
 COMPILER_RT_VISIBILITY extern void (*FreeHook)(void *);
 COMPILER_RT_VISIBILITY extern uint8_t *DynamicBufferIOBuffer;

Modified: compiler-rt/trunk/lib/profile/InstrProfilingPort.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingPort.h?rev=269576&r1=269575&r2=269576&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingPort.h (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingPort.h Sat May 14 15:12:42 2016
@@ -25,11 +25,14 @@
 #define COMPILER_RT_MAX_HOSTLEN 128
 #ifdef _MSC_VER
 #define COMPILER_RT_GETHOSTNAME(Name, Len) gethostname(Name, Len)
+#define COMPILER_RT_ALLOCA _alloca
 #elif defined(__PS4__)
 #define COMPILER_RT_GETHOSTNAME(Name, Len) (-1)
+#define COMPILER_RT_ALLOCA alloca
 #else
 #define COMPILER_RT_GETHOSTNAME(Name, Len) lprofGetHostName(Name, Len)
 #define COMPILER_RT_HAS_UNAME 1
+#define COMPILER_RT_ALLOCA alloca
 #endif
 
 #if COMPILER_RT_HAS_ATOMICS == 1

Modified: compiler-rt/trunk/lib/profile/InstrProfilingValue.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingValue.c?rev=269576&r1=269575&r2=269576&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingValue.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingValue.c Sat May 14 15:12:42 2016
@@ -117,135 +117,108 @@ __llvm_profile_instrument_target(uint64_
   }
 }
 
-ValueProfData *allocValueProfDataRT(size_t TotalSizeInBytes) {
-  return (ValueProfData *)calloc(TotalSizeInBytes, 1);
-}
-
 /*
- * The value profiler runtime library stores the value profile data
- * for a given function in \c NumValueSites and \c Nodes structures.
- * \c ValueProfRuntimeRecord class is used to encapsulate the runtime
- * profile data and provides fast interfaces to retrieve the profile
- * information. This interface is used to initialize the runtime record
- * and pre-compute the information needed for efficient implementation
- * of callbacks required by ValueProfRecordClosure class.
+ * A wrapper struct that represents value profile runtime data.
+ * Like InstrProfRecord class which is used by profiling host tools,
+ * ValueProfRuntimeRecord also implements the abstract intefaces defined in
+ * ValueProfRecordClosure so that the runtime data can be serialized using
+ * shared C implementation.
  */
-static int
-initializeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord,
-                                 const uint16_t *NumValueSites,
-                                 ValueProfNode **Nodes) {
-  unsigned I, S = 0, NumValueKinds = 0;
-  RuntimeRecord->NumValueSites = NumValueSites;
-  RuntimeRecord->Nodes = Nodes;
-  for (I = 0; I <= IPVK_Last; I++) {
-    uint16_t N = NumValueSites[I];
-    if (!N)
-      continue;
-    NumValueKinds++;
-
-    RuntimeRecord->NodesKind[I] = Nodes ? &Nodes[S] : INSTR_PROF_NULLPTR;
-    S += N;
-  }
-  RuntimeRecord->NumValueKinds = NumValueKinds;
-  return 0;
-}
+typedef struct ValueProfRuntimeRecord {
+  const __llvm_profile_data *Data;
+  ValueProfNode **NodesKind[IPVK_Last + 1];
+  uint8_t **SiteCountArray;
+} ValueProfRuntimeRecord;
 
-static void
-finalizeValueProfRuntimeRecord(ValueProfRuntimeRecord *RuntimeRecord) {}
+/* ValueProfRecordClosure Interface implementation. */
 
-/* ValueProfRecordClosure Interface implementation for
- * ValueProfDataRuntimeRecord.  */
-static uint32_t getNumValueKindsRT(const void *R) {
-  return ((const ValueProfRuntimeRecord *)R)->NumValueKinds;
+static uint32_t getNumValueSitesRT(const void *R, uint32_t VK) {
+  return ((const ValueProfRuntimeRecord *)R)->Data->NumValueSites[VK];
 }
 
-static uint32_t getNumValueSitesRT(const void *R, uint32_t VK) {
-  return ((const ValueProfRuntimeRecord *)R)->NumValueSites[VK];
+static uint32_t getNumValueDataRT(const void *R, uint32_t VK) {
+  uint32_t S = 0, I;
+  const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
+  if (Record->SiteCountArray[VK] == INSTR_PROF_NULLPTR)
+    return 0;
+  for (I = 0; I < Record->Data->NumValueSites[VK]; I++)
+    S += Record->SiteCountArray[VK][I];
+  return S;
 }
 
 static uint32_t getNumValueDataForSiteRT(const void *R, uint32_t VK,
                                          uint32_t S) {
-  uint32_t C = 0;
   const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
-  ValueProfNode *Site =
-      Record->NodesKind[VK] ? Record->NodesKind[VK][S] : INSTR_PROF_NULLPTR;
-  while (Site) {
-    C++;
-    Site = Site->Next;
-  }
-  if (C > UCHAR_MAX)
-    C = UCHAR_MAX;
-
-  return C;
+  return Record->SiteCountArray[VK][S];
 }
 
-static uint32_t getNumValueDataRT(const void *R, uint32_t VK) {
-  unsigned I, S = 0;
-  const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
-  for (I = 0; I < Record->NumValueSites[VK]; I++)
-    S += getNumValueDataForSiteRT(Record, VK, I);
-  return S;
+static ValueProfRuntimeRecord RTRecord;
+static ValueProfRecordClosure RTRecordClosure = {
+    &RTRecord,          INSTR_PROF_NULLPTR, /* GetNumValueKinds */
+    getNumValueSitesRT, getNumValueDataRT,  getNumValueDataForSiteRT,
+    INSTR_PROF_NULLPTR, /* RemapValueData */
+    INSTR_PROF_NULLPTR, /* GetValueForSite, */
+    INSTR_PROF_NULLPTR  /* AllocValueProfData */
+};
+
+static uint32_t
+initializeValueProfRuntimeRecord(const __llvm_profile_data *Data,
+                                 uint8_t *SiteCountArray[]) {
+  unsigned I, J, S = 0, NumValueKinds = 0;
+  ValueProfNode **Nodes = (ValueProfNode **)Data->Values;
+  RTRecord.Data = Data;
+  RTRecord.SiteCountArray = SiteCountArray;
+  for (I = 0; I <= IPVK_Last; I++) {
+    uint16_t N = Data->NumValueSites[I];
+    if (!N)
+      continue;
+
+    NumValueKinds++;
+
+    RTRecord.NodesKind[I] = Nodes ? &Nodes[S] : INSTR_PROF_NULLPTR;
+    for (J = 0; J < N; J++) {
+      /* Compute value count for each site. */
+      uint32_t C = 0;
+      ValueProfNode *Site =
+          Nodes ? RTRecord.NodesKind[I][J] : INSTR_PROF_NULLPTR;
+      while (Site) {
+        C++;
+        Site = Site->Next;
+      }
+      if (C > UCHAR_MAX)
+        C = UCHAR_MAX;
+      RTRecord.SiteCountArray[I][J] = C;
+    }
+    S += N;
+  }
+  return NumValueKinds;
 }
 
-static void getValueForSiteRT(const void *R, InstrProfValueData *Dst,
-                              uint32_t VK, uint32_t S) {
-  unsigned I, N = 0;
-  const ValueProfRuntimeRecord *Record = (const ValueProfRuntimeRecord *)R;
-  N = getNumValueDataForSiteRT(R, VK, S);
-  if (N == 0)
-    return;
-  ValueProfNode *VNode = Record->NodesKind[VK][S];
+static ValueProfNode *getNextNValueData(uint32_t VK, uint32_t Site,
+                                        InstrProfValueData *Dst,
+                                        ValueProfNode *StartNode, uint32_t N) {
+  unsigned I;
+  ValueProfNode *VNode = StartNode ? StartNode : RTRecord.NodesKind[VK][Site];
   for (I = 0; I < N; I++) {
     Dst[I] = VNode->VData;
     VNode = VNode->Next;
   }
+  return VNode;
 }
 
-static ValueProfRecordClosure RTRecordClosure = {
-    INSTR_PROF_NULLPTR, getNumValueKindsRT,       getNumValueSitesRT,
-    getNumValueDataRT,  getNumValueDataForSiteRT, INSTR_PROF_NULLPTR,
-    getValueForSiteRT,  allocValueProfDataRT};
-
-/*
- * Return a ValueProfData instance that stores the data collected
- * from runtime. If \c DstData is provided by the caller, the value
- * profile data will be store in *DstData and DstData is returned,
- * otherwise the method will allocate space for the value data and
- * return pointer to the newly allocated space.
- */
-static ValueProfData *
-serializeValueProfDataFromRT(const ValueProfRuntimeRecord *Record,
-                             ValueProfData *DstData) {
-  RTRecordClosure.Record = Record;
-  return serializeValueProfDataFrom(&RTRecordClosure, DstData);
+static uint32_t getValueProfDataSizeWrapper() {
+  return getValueProfDataSize(&RTRecordClosure);
 }
 
-/*
- * Return the size of ValueProfData structure to store data
- * recorded in the runtime record.
- */
-static uint32_t getValueProfDataSizeRT(const ValueProfRuntimeRecord *Record) {
-  RTRecordClosure.Record = Record;
-  return getValueProfDataSize(&RTRecordClosure);
+static uint32_t getNumValueDataForSiteWrapper(uint32_t VK, uint32_t S) {
+  return getNumValueDataForSiteRT(&RTRecord, VK, S);
 }
 
-COMPILER_RT_VISIBILITY struct ValueProfData *
-lprofGatherValueProfData(const __llvm_profile_data *Data) {
-  ValueProfData *VD = NULL;
-  ValueProfRuntimeRecord R;
-  if (initializeValueProfRuntimeRecord(&R, Data->NumValueSites, Data->Values))
-    PROF_OOM_RETURN("Failed to write value profile data ");
-
-  /* Compute the size of ValueProfData from this runtime record.  */
-  if (getNumValueKindsRT(&R) != 0) {
-    uint32_t VS = getValueProfDataSizeRT(&R);
-    VD = (ValueProfData *)calloc(VS, sizeof(uint8_t));
-    if (!VD)
-      PROF_OOM_RETURN("Failed to write value profile data ");
-    VD->TotalSize = VS;
-    serializeValueProfDataFromRT(&R, VD);
-  }
-  finalizeValueProfRuntimeRecord(&R);
+static VPDataReaderType TheVPDataReader = {
+    initializeValueProfRuntimeRecord, getValueProfRecordHeaderSize,
+    getFirstValueProfRecord,          getNumValueDataForSiteWrapper,
+    getValueProfDataSizeWrapper,      getNextNValueData};
 
-  return VD;
+COMPILER_RT_VISIBILITY VPDataReaderType *lprofGetVPDataReader() {
+  return &TheVPDataReader;
 }

Modified: compiler-rt/trunk/lib/profile/InstrProfilingWriter.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/profile/InstrProfilingWriter.c?rev=269576&r1=269575&r2=269576&view=diff
==============================================================================
--- compiler-rt/trunk/lib/profile/InstrProfilingWriter.c (original)
+++ compiler-rt/trunk/lib/profile/InstrProfilingWriter.c Sat May 14 15:12:42 2016
@@ -9,6 +9,11 @@
 
 #include "InstrProfiling.h"
 #include "InstrProfilingInternal.h"
+#ifdef _MSC_VER
+#include <malloc.h>
+#else
+#include <alloca.h>
+#endif
 #include <string.h>
 
 #define INSTR_PROF_VALUE_PROF_DATA
@@ -18,6 +23,9 @@ COMPILER_RT_VISIBILITY void (*FreeHook)(
 static ProfBufferIO TheBufferIO;
 #define VP_BUFFER_SIZE 8 * 1024
 static uint8_t BufferIOBuffer[VP_BUFFER_SIZE];
+static InstrProfValueData VPDataArray[16];
+static uint32_t VPDataArraySize = sizeof(VPDataArray) / sizeof(*VPDataArray);
+
 COMPILER_RT_VISIBILITY uint8_t *DynamicBufferIOBuffer = 0;
 COMPILER_RT_VISIBILITY uint32_t VPBufferSize = 0;
 
@@ -98,33 +106,116 @@ COMPILER_RT_VISIBILITY int lprofBufferIO
   return 0;
 }
 
+/* Write out value profile data for function specified with \c Data.
+ * The implementation does not use the method \c serializeValueProfData
+ * which depends on dynamic memory allocation. In this implementation,
+ * value profile data is written out to \c BufferIO piecemeal.
+ */
 static int writeOneValueProfData(ProfBufferIO *BufferIO,
-                                 VPGatherHookType VPDataGatherer,
+                                 VPDataReaderType *VPDataReader,
                                  const __llvm_profile_data *Data) {
-  ValueProfData *CurVData = VPDataGatherer(Data);
-  if (!CurVData)
+  unsigned I, NumValueKinds = 0;
+  ValueProfData VPHeader;
+  uint8_t *SiteCountArray[IPVK_Last + 1];
+
+  for (I = 0; I <= IPVK_Last; I++) {
+    if (!Data->NumValueSites[I])
+      SiteCountArray[I] = 0;
+    else {
+      uint32_t Sz =
+          VPDataReader->GetValueProfRecordHeaderSize(Data->NumValueSites[I]) -
+          offsetof(ValueProfRecord, SiteCountArray);
+      /* Only use alloca for this small byte array to avoid excessive
+       * stack growth.  */
+      SiteCountArray[I] = (uint8_t *)COMPILER_RT_ALLOCA(Sz);
+      memset(SiteCountArray[I], 0, Sz);
+    }
+  }
+
+  /* If NumValueKinds returned is 0, there is nothing to write, report
+     success and return. This should match the raw profile reader's behavior. */
+  if (!(NumValueKinds = VPDataReader->InitRTRecord(Data, SiteCountArray)))
     return 0;
-  if (lprofBufferIOWrite(BufferIO, (const uint8_t *)CurVData,
-                         CurVData->TotalSize) != 0)
+
+  /* First write the header structure. */
+  VPHeader.TotalSize = VPDataReader->GetValueProfDataSize();
+  VPHeader.NumValueKinds = NumValueKinds;
+  if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&VPHeader,
+                         sizeof(ValueProfData)))
+    return -1;
+
+  /* Make sure nothing else needs to be written before value profile
+   * records. */
+  if ((void *)VPDataReader->GetFirstValueProfRecord(&VPHeader) !=
+      (void *)(&VPHeader + 1))
     return -1;
-  FreeHook(CurVData);
+
+  /* Write out the value profile record for each value kind
+   * one by one. */
+  for (I = 0; I <= IPVK_Last; I++) {
+    uint32_t J;
+    ValueProfRecord RecordHeader;
+    /* The size of the value prof record header without counting the
+     * site count array .*/
+    uint32_t RecordHeaderSize = offsetof(ValueProfRecord, SiteCountArray);
+    uint32_t SiteCountArraySize;
+
+    if (!Data->NumValueSites[I])
+      continue;
+
+    /* Write out the record header.  */
+    RecordHeader.Kind = I;
+    RecordHeader.NumValueSites = Data->NumValueSites[I];
+    if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&RecordHeader,
+                           RecordHeaderSize))
+      return -1;
+
+    /* Write out the site value count array including padding space. */
+    SiteCountArraySize =
+        VPDataReader->GetValueProfRecordHeaderSize(Data->NumValueSites[I]) -
+        RecordHeaderSize;
+    if (lprofBufferIOWrite(BufferIO, SiteCountArray[I], SiteCountArraySize))
+      return -1;
+
+    /* Write out the value profile data for each value site.  */
+    for (J = 0; J < Data->NumValueSites[I]; J++) {
+      uint32_t NRead, NRemain;
+      ValueProfNode *NextStartNode = 0;
+      NRemain = VPDataReader->GetNumValueDataForSite(I, J);
+      if (!NRemain)
+        continue;
+      /* Read and write out value data in small chunks till it is done. */
+      do {
+        NRead = (NRemain > VPDataArraySize ? VPDataArraySize : NRemain);
+        NextStartNode =
+            VPDataReader->GetValueData(I, /* ValueKind */
+                                       J, /* Site */
+                                       &VPDataArray[0], NextStartNode, NRead);
+        if (lprofBufferIOWrite(BufferIO, (const uint8_t *)&VPDataArray[0],
+                               NRead * sizeof(InstrProfValueData)))
+          return -1;
+        NRemain -= NRead;
+      } while (NRemain != 0);
+    }
+  }
+  /* All done report success.  */
   return 0;
 }
 
 static int writeValueProfData(WriterCallback Writer, void *WriterCtx,
-                              VPGatherHookType VPDataGatherer,
+                              VPDataReaderType *VPDataReader,
                               const __llvm_profile_data *DataBegin,
                               const __llvm_profile_data *DataEnd) {
   ProfBufferIO *BufferIO;
   const __llvm_profile_data *DI = 0;
 
-  if (!VPDataGatherer)
+  if (!VPDataReader)
     return 0;
 
   BufferIO = lprofCreateBufferIO(Writer, WriterCtx);
 
   for (DI = DataBegin; DI < DataEnd; DI++) {
-    if (writeOneValueProfData(BufferIO, VPDataGatherer, DI))
+    if (writeOneValueProfData(BufferIO, VPDataReader, DI))
       return -1;
   }
 
@@ -137,7 +228,7 @@ static int writeValueProfData(WriterCall
 
 COMPILER_RT_VISIBILITY int lprofWriteData(WriterCallback Writer,
                                           void *WriterCtx,
-                                          VPGatherHookType VPDataGatherer) {
+                                          VPDataReaderType *VPDataReader) {
   /* Match logic in __llvm_profile_write_buffer(). */
   const __llvm_profile_data *DataBegin = __llvm_profile_begin_data();
   const __llvm_profile_data *DataEnd = __llvm_profile_end_data();
@@ -146,7 +237,7 @@ COMPILER_RT_VISIBILITY int lprofWriteDat
   const char *NamesBegin = __llvm_profile_begin_names();
   const char *NamesEnd = __llvm_profile_end_names();
   return lprofWriteDataImpl(Writer, WriterCtx, DataBegin, DataEnd,
-                            CountersBegin, CountersEnd, VPDataGatherer,
+                            CountersBegin, CountersEnd, VPDataReader,
                             NamesBegin, NamesEnd);
 }
 
@@ -155,7 +246,7 @@ lprofWriteDataImpl(WriterCallback Writer
                    const __llvm_profile_data *DataBegin,
                    const __llvm_profile_data *DataEnd,
                    const uint64_t *CountersBegin, const uint64_t *CountersEnd,
-                   VPGatherHookType VPDataGatherer, const char *NamesBegin,
+                   VPDataReaderType *VPDataReader, const char *NamesBegin,
                    const char *NamesEnd) {
 
   /* Calculate size of sections. */
@@ -186,6 +277,6 @@ lprofWriteDataImpl(WriterCallback Writer
   if (Writer(IOVec, sizeof(IOVec) / sizeof(*IOVec), &WriterCtx))
     return -1;
 
-  return writeValueProfData(Writer, WriterCtx, VPDataGatherer, DataBegin,
+  return writeValueProfData(Writer, WriterCtx, VPDataReader, DataBegin,
                             DataEnd);
 }




More information about the llvm-commits mailing list