diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:45:36 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:45:36 +0000 |
commit | 6f08730ec5f639f05f2f15354171e4a3c9af9dc1 (patch) | |
tree | 7374e9d4448083010ada98d17976199c7e945d47 /lib/profile/InstrProfilingWriter.c | |
parent | c003a57e2e4a1ad9be0338806bc1038b6987155f (diff) | |
download | src-test2-6f08730ec5f639f05f2f15354171e4a3c9af9dc1.tar.gz src-test2-6f08730ec5f639f05f2f15354171e4a3c9af9dc1.zip |
Notes
Diffstat (limited to 'lib/profile/InstrProfilingWriter.c')
-rw-r--r-- | lib/profile/InstrProfilingWriter.c | 224 |
1 files changed, 165 insertions, 59 deletions
diff --git a/lib/profile/InstrProfilingWriter.c b/lib/profile/InstrProfilingWriter.c index a07bc538ed4b..95f37e8e9b4f 100644 --- a/lib/profile/InstrProfilingWriter.c +++ b/lib/profile/InstrProfilingWriter.c @@ -9,20 +9,31 @@ #include "InstrProfiling.h" #include "InstrProfilingInternal.h" +#ifdef _MSC_VER +/* For _alloca */ +#include <malloc.h> +#endif #include <string.h> #define INSTR_PROF_VALUE_PROF_DATA #include "InstrProfData.inc" -void (*FreeHook)(void *) = NULL; -void* (*CallocHook)(size_t, size_t) = NULL; -uint32_t VPBufferSize = 0; + +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; /* The buffer writer is reponsponsible in keeping writer state * across the call. */ -COMPILER_RT_VISIBILITY uint32_t llvmBufferWriter(ProfDataIOVec *IOVecs, - uint32_t NumIOVecs, - void **WriterCtx) { +COMPILER_RT_VISIBILITY uint32_t lprofBufferWriter(ProfDataIOVec *IOVecs, + uint32_t NumIOVecs, + void **WriterCtx) { uint32_t I; char **Buffer = (char **)WriterCtx; for (I = 0; I < NumIOVecs; I++) { @@ -43,28 +54,31 @@ static void llvmInitBufferIO(ProfBufferIO *BufferIO, WriterCallback FileWriter, } COMPILER_RT_VISIBILITY ProfBufferIO * -llvmCreateBufferIO(WriterCallback FileWriter, void *File, uint32_t BufferSz) { - ProfBufferIO *BufferIO = (ProfBufferIO *)CallocHook(1, sizeof(ProfBufferIO)); - uint8_t *Buffer = (uint8_t *)CallocHook(1, BufferSz); +lprofCreateBufferIO(WriterCallback FileWriter, void *File) { + uint8_t *Buffer = DynamicBufferIOBuffer; + uint32_t BufferSize = VPBufferSize; if (!Buffer) { - FreeHook(BufferIO); - return 0; + Buffer = &BufferIOBuffer[0]; + BufferSize = sizeof(BufferIOBuffer); } - llvmInitBufferIO(BufferIO, FileWriter, File, Buffer, BufferSz); - return BufferIO; + llvmInitBufferIO(&TheBufferIO, FileWriter, File, Buffer, BufferSize); + return &TheBufferIO; } -COMPILER_RT_VISIBILITY void llvmDeleteBufferIO(ProfBufferIO *BufferIO) { - FreeHook(BufferIO->BufferStart); - FreeHook(BufferIO); +COMPILER_RT_VISIBILITY void lprofDeleteBufferIO(ProfBufferIO *BufferIO) { + if (DynamicBufferIOBuffer) { + FreeHook(DynamicBufferIOBuffer); + DynamicBufferIOBuffer = 0; + VPBufferSize = 0; + } } COMPILER_RT_VISIBILITY int -llvmBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, uint32_t Size) { +lprofBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, uint32_t Size) { /* Buffer is not large enough, it is time to flush. */ if (Size + BufferIO->CurOffset > BufferIO->BufferSz) { - if (llvmBufferIOFlush(BufferIO) != 0) - return -1; + if (lprofBufferIOFlush(BufferIO) != 0) + return -1; } /* Special case, bypass the buffer completely. */ ProfDataIOVec IO[] = {{Data, sizeof(uint8_t), Size}}; @@ -74,13 +88,13 @@ llvmBufferIOWrite(ProfBufferIO *BufferIO, const uint8_t *Data, uint32_t Size) { } else { /* Write the data to buffer */ uint8_t *Buffer = BufferIO->BufferStart + BufferIO->CurOffset; - llvmBufferWriter(IO, 1, (void **)&Buffer); + lprofBufferWriter(IO, 1, (void **)&Buffer); BufferIO->CurOffset = Buffer - BufferIO->BufferStart; } return 0; } -COMPILER_RT_VISIBILITY int llvmBufferIOFlush(ProfBufferIO *BufferIO) { +COMPILER_RT_VISIBILITY int lprofBufferIOFlush(ProfBufferIO *BufferIO) { if (BufferIO->CurOffset) { ProfDataIOVec IO[] = { {BufferIO->BufferStart, sizeof(uint8_t), BufferIO->CurOffset}}; @@ -91,60 +105,151 @@ COMPILER_RT_VISIBILITY int llvmBufferIOFlush(ProfBufferIO *BufferIO) { return 0; } -COMPILER_RT_VISIBILITY int llvmWriteProfData(WriterCallback Writer, - void *WriterCtx, - ValueProfData **ValueDataArray, - const uint64_t ValueDataSize) { - /* 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(); - const uint64_t *CountersBegin = __llvm_profile_begin_counters(); - const uint64_t *CountersEnd = __llvm_profile_end_counters(); - const char *NamesBegin = __llvm_profile_begin_names(); - const char *NamesEnd = __llvm_profile_end_names(); - return llvmWriteProfDataImpl(Writer, WriterCtx, DataBegin, DataEnd, - CountersBegin, CountersEnd, ValueDataArray, - ValueDataSize, NamesBegin, NamesEnd); +/* 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, + VPDataReaderType *VPDataReader, + const __llvm_profile_data *Data) { + 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; + + /* 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; + + /* 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; } -#define VP_BUFFER_SIZE 8 * 1024 static int writeValueProfData(WriterCallback Writer, void *WriterCtx, - ValueProfData **ValueDataBegin, - uint64_t NumVData) { + VPDataReaderType *VPDataReader, + const __llvm_profile_data *DataBegin, + const __llvm_profile_data *DataEnd) { ProfBufferIO *BufferIO; - uint32_t I = 0, BufferSz; + const __llvm_profile_data *DI = 0; - if (!ValueDataBegin) + if (!VPDataReader) return 0; - BufferSz = VPBufferSize ? VPBufferSize : VP_BUFFER_SIZE; - BufferIO = llvmCreateBufferIO(Writer, WriterCtx, BufferSz); + BufferIO = lprofCreateBufferIO(Writer, WriterCtx); - for (I = 0; I < NumVData; I++) { - ValueProfData *CurVData = ValueDataBegin[I]; - if (!CurVData) - continue; - if (llvmBufferIOWrite(BufferIO, (const uint8_t *)CurVData, - CurVData->TotalSize) != 0) + for (DI = DataBegin; DI < DataEnd; DI++) { + if (writeOneValueProfData(BufferIO, VPDataReader, DI)) return -1; } - if (llvmBufferIOFlush(BufferIO) != 0) + if (lprofBufferIOFlush(BufferIO) != 0) return -1; - llvmDeleteBufferIO(BufferIO); + lprofDeleteBufferIO(BufferIO); return 0; } -COMPILER_RT_VISIBILITY int llvmWriteProfDataImpl( - WriterCallback Writer, void *WriterCtx, - const __llvm_profile_data *DataBegin, const __llvm_profile_data *DataEnd, - const uint64_t *CountersBegin, const uint64_t *CountersEnd, - ValueProfData **ValueDataBegin, const uint64_t ValueDataSize, - const char *NamesBegin, const char *NamesEnd) { +COMPILER_RT_VISIBILITY int lprofWriteData(WriterCallback Writer, + void *WriterCtx, + 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(); + const uint64_t *CountersBegin = __llvm_profile_begin_counters(); + const uint64_t *CountersEnd = __llvm_profile_end_counters(); + const char *NamesBegin = __llvm_profile_begin_names(); + const char *NamesEnd = __llvm_profile_end_names(); + return lprofWriteDataImpl(Writer, WriterCtx, DataBegin, DataEnd, + CountersBegin, CountersEnd, VPDataReader, + NamesBegin, NamesEnd); +} + +COMPILER_RT_VISIBILITY int +lprofWriteDataImpl(WriterCallback Writer, void *WriterCtx, + const __llvm_profile_data *DataBegin, + const __llvm_profile_data *DataEnd, + const uint64_t *CountersBegin, const uint64_t *CountersEnd, + VPDataReaderType *VPDataReader, const char *NamesBegin, + const char *NamesEnd) { /* Calculate size of sections. */ - const uint64_t DataSize = DataEnd - DataBegin; + const uint64_t DataSize = __llvm_profile_get_data_size(DataBegin, DataEnd); const uint64_t CountersSize = CountersEnd - CountersBegin; const uint64_t NamesSize = NamesEnd - NamesBegin; const uint64_t Padding = __llvm_profile_get_num_padding_bytes(NamesSize); @@ -158,7 +263,7 @@ COMPILER_RT_VISIBILITY int llvmWriteProfDataImpl( if (!DataSize) return 0; - /* Initialize header struture. */ +/* Initialize header structure. */ #define INSTR_PROF_RAW_HEADER(Type, Name, Init) Header.Name = Init; #include "InstrProfData.inc" @@ -171,5 +276,6 @@ COMPILER_RT_VISIBILITY int llvmWriteProfDataImpl( if (Writer(IOVec, sizeof(IOVec) / sizeof(*IOVec), &WriterCtx)) return -1; - return writeValueProfData(Writer, WriterCtx, ValueDataBegin, DataSize); + return writeValueProfData(Writer, WriterCtx, VPDataReader, DataBegin, + DataEnd); } |