summaryrefslogtreecommitdiff
path: root/lib/profile/InstrProfilingWriter.c
diff options
context:
space:
mode:
authorXinliang David Li <davidxl@google.com>2016-05-14 20:12:42 +0000
committerXinliang David Li <davidxl@google.com>2016-05-14 20:12:42 +0000
commit31e6b45c64181fbd3928856bb4a5f0081390ea3e (patch)
tree69005109496fd58761f67719aba120ec074960ae /lib/profile/InstrProfilingWriter.c
parent6948b5e68fe7b8361951ad9a0b8a01f0b4847537 (diff)
[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. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@269576 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/profile/InstrProfilingWriter.c')
-rw-r--r--lib/profile/InstrProfilingWriter.c117
1 files changed, 104 insertions, 13 deletions
diff --git a/lib/profile/InstrProfilingWriter.c b/lib/profile/InstrProfilingWriter.c
index 808ed62a1..30c1b785c 100644
--- a/lib/profile/InstrProfilingWriter.c
+++ b/lib/profile/InstrProfilingWriter.c
@@ -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)(void *) = NULL;
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 lprofBufferIOFlush(ProfBufferIO *BufferIO) {
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(WriterCallback Writer, void *WriterCtx,
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 lprofWriteData(WriterCallback Writer,
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, 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) {
/* Calculate size of sections. */
@@ -186,6 +277,6 @@ lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx,
if (Writer(IOVec, sizeof(IOVec) / sizeof(*IOVec), &WriterCtx))
return -1;
- return writeValueProfData(Writer, WriterCtx, VPDataGatherer, DataBegin,
+ return writeValueProfData(Writer, WriterCtx, VPDataReader, DataBegin,
DataEnd);
}