Index: lib/profile/InstrProfiling.c =================================================================== --- lib/profile/InstrProfiling.c +++ lib/profile/InstrProfiling.c @@ -129,24 +129,6 @@ return 1; } -static void deallocateValueProfileCounters(__llvm_profile_data *Data) { - uint64_t NumVSites = 0, I; - uint32_t VKI; - if (!Data->Values) - return; - for (VKI = IPVK_First; VKI <= IPVK_Last; ++VKI) - NumVSites += Data->NumValueSites[VKI]; - for (I = 0; I < NumVSites; I++) { - ValueProfNode *Node = ((ValueProfNode **)Data->Values)[I]; - while (Node) { - ValueProfNode *Next = Node->Next; - free(Node); - Node = Next; - } - } - free(Data->Values); -} - LLVM_LIBRARY_VISIBILITY void __llvm_profile_instrument_target(uint64_t TargetValue, void *Data, uint32_t CounterIndex) { @@ -217,6 +199,8 @@ #define DTOR_VALUE_RECORD(R) finalizeValueProfRuntimeRecord(&R); +void **DataValuePtrs LLVM_LIBRARY_VISIBILITY; + LLVM_LIBRARY_VISIBILITY uint64_t __llvm_profile_gather_value_data(uint8_t **VDataArray) { size_t S = 0, RealSize = 0, BufferCapacity = 0, Extra = 0; @@ -251,6 +235,11 @@ if (!*VDataArray) PROF_OOM_RETURN("Failed to write value profile data "); + size_t DataSize = DataEnd - DataBegin; + DataValuePtrs = calloc(DataSize, sizeof(void *)); + if (!DataValuePtrs) + PROF_OOM_RETURN("Failed to write value profile data "); + ValueProfData *VD = (ValueProfData *)(*VDataArray); /* * Extract value profile data and write into ValueProfData structure @@ -272,12 +261,10 @@ PROF_ERR("Value profile data is dropped :%s \n", "Out of buffer space. Use environment " " LLVM_VALUE_PROF_BUFFER_EXTRA to allocate more"); - I->Values = 0; } serializeValueProfDataFromRT(&R, VD); - deallocateValueProfileCounters(I); - I->Values = VD; + DataValuePtrs[I - DataBegin] = VD; RealSize += VD->TotalSize; VD = (ValueProfData *)((char *)VD + VD->TotalSize); DTOR_VALUE_RECORD(R); Index: lib/profile/InstrProfilingFile.c =================================================================== --- lib/profile/InstrProfilingFile.c +++ lib/profile/InstrProfilingFile.c @@ -17,14 +17,70 @@ #define UNCONST(ptr) ((void *)(uintptr_t)(ptr)) +#define BUFFSIZE 1024 +extern void **DataValuePtrs; + +/* The Values field of __llvm_profile_data structure is used to storek runtime + * ValueProfNode data pointers which is not what needs to be written out + * to the disk. Do the fix up before writing. + */ +static uint32_t writePerFuncData(const __llvm_profile_data *DataBegin, + uint32_t ItemSize, uint32_t NumData, + FILE *File) { + __llvm_profile_data *Buffer; + uint32_t RemainItem = NumData, CurIndex = 0; + /* Same sanity check. */ + if (ItemSize != sizeof(__llvm_profile_data)) + return 1; + + if ((size_t)(__llvm_profile_end_data() - DataBegin) != NumData) + return 1; + + if (!NumData) + return 0; + + /* Allocate a small write buffer for ValuePtr field fix up before writing out. + */ + Buffer = (__llvm_profile_data *)calloc(BUFFSIZE, ItemSize); + if (!Buffer) + return 1; + + CurIndex = 0; + while (RemainItem) { + uint32_t I; + uint32_t ActualSize = (RemainItem > BUFFSIZE ? BUFFSIZE : RemainItem); + memcpy(&Buffer[CurIndex], &DataBegin[CurIndex], ActualSize * ItemSize); + /* Now patch the data */ + for (I = 0; I < ActualSize; I++) + Buffer[CurIndex + I].Values = DataValuePtrs[CurIndex + I]; + + /* Now write out */ + if (fwrite(&Buffer[CurIndex], ItemSize, ActualSize, File) != ActualSize) { + free(Buffer); + return 1; + } + + RemainItem -= ActualSize; + CurIndex += ActualSize; + } + + free(Buffer); + free(DataValuePtrs); + return 0; +} + /* Return 1 if there is an error, otherwise return 0. */ static uint32_t fileWriter(ProfDataIOVec *IOVecs, uint32_t NumIOVecs, void **WriterCtx) { uint32_t I; FILE *File = (FILE *)*WriterCtx; for (I = 0; I < NumIOVecs; I++) { - if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, File) != - IOVecs[I].NumElm) + if (IOVecs[I].Data == __llvm_profile_begin_data() && DataValuePtrs != 0) { + if (writePerFuncData(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, + File)) + return 1; + } else if (fwrite(IOVecs[I].Data, IOVecs[I].ElmSize, IOVecs[I].NumElm, + File) != IOVecs[I].NumElm) return 1; } return 0; @@ -85,7 +141,7 @@ static void setFilename(const char *Filename, int OwnsFilename) { /* Check if this is a new filename and therefore needs truncation. */ int NewFile = !__llvm_profile_CurrentFilename || - (Filename && strcmp(Filename, __llvm_profile_CurrentFilename)); + (Filename && strcmp(Filename, __llvm_profile_CurrentFilename)); if (__llvm_profile_OwnsFilename) free(UNCONST(__llvm_profile_CurrentFilename));