From 31e6b45c64181fbd3928856bb4a5f0081390ea3e Mon Sep 17 00:00:00 2001 From: Xinliang David Li Date: Sat, 14 May 2016 20:12:42 +0000 Subject: [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 --- lib/profile/InstrProfilingWriter.c | 117 ++++++++++++++++++++++++++++++++----- 1 file changed, 104 insertions(+), 13 deletions(-) (limited to 'lib/profile/InstrProfilingWriter.c') 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 +#else +#include +#endif #include #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); } -- cgit v1.2.3