MemProf.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #include "llvm/ProfileData/MemProf.h"
  2. #include "llvm/ADT/SmallVector.h"
  3. #include "llvm/IR/Function.h"
  4. #include "llvm/ProfileData/InstrProf.h"
  5. #include "llvm/Support/Endian.h"
  6. #include "llvm/Support/EndianStream.h"
  7. namespace llvm {
  8. namespace memprof {
  9. void IndexedMemProfRecord::serialize(const MemProfSchema &Schema,
  10. raw_ostream &OS) {
  11. using namespace support;
  12. endian::Writer LE(OS, little);
  13. LE.write<uint64_t>(AllocSites.size());
  14. for (const IndexedAllocationInfo &N : AllocSites) {
  15. LE.write<uint64_t>(N.CallStack.size());
  16. for (const FrameId &Id : N.CallStack)
  17. LE.write<FrameId>(Id);
  18. N.Info.serialize(Schema, OS);
  19. }
  20. // Related contexts.
  21. LE.write<uint64_t>(CallSites.size());
  22. for (const auto &Frames : CallSites) {
  23. LE.write<uint64_t>(Frames.size());
  24. for (const FrameId &Id : Frames)
  25. LE.write<FrameId>(Id);
  26. }
  27. }
  28. IndexedMemProfRecord
  29. IndexedMemProfRecord::deserialize(const MemProfSchema &Schema,
  30. const unsigned char *Ptr) {
  31. using namespace support;
  32. IndexedMemProfRecord Record;
  33. // Read the meminfo nodes.
  34. const uint64_t NumNodes = endian::readNext<uint64_t, little, unaligned>(Ptr);
  35. for (uint64_t I = 0; I < NumNodes; I++) {
  36. IndexedAllocationInfo Node;
  37. const uint64_t NumFrames =
  38. endian::readNext<uint64_t, little, unaligned>(Ptr);
  39. for (uint64_t J = 0; J < NumFrames; J++) {
  40. const FrameId Id = endian::readNext<FrameId, little, unaligned>(Ptr);
  41. Node.CallStack.push_back(Id);
  42. }
  43. Node.Info.deserialize(Schema, Ptr);
  44. Ptr += PortableMemInfoBlock::serializedSize();
  45. Record.AllocSites.push_back(Node);
  46. }
  47. // Read the callsite information.
  48. const uint64_t NumCtxs = endian::readNext<uint64_t, little, unaligned>(Ptr);
  49. for (uint64_t J = 0; J < NumCtxs; J++) {
  50. const uint64_t NumFrames =
  51. endian::readNext<uint64_t, little, unaligned>(Ptr);
  52. llvm::SmallVector<FrameId> Frames;
  53. Frames.reserve(NumFrames);
  54. for (uint64_t K = 0; K < NumFrames; K++) {
  55. const FrameId Id = endian::readNext<FrameId, little, unaligned>(Ptr);
  56. Frames.push_back(Id);
  57. }
  58. Record.CallSites.push_back(Frames);
  59. }
  60. return Record;
  61. }
  62. GlobalValue::GUID IndexedMemProfRecord::getGUID(const StringRef FunctionName) {
  63. const auto Pos = FunctionName.find(".llvm.");
  64. // We use the function guid which we expect to be a uint64_t. At
  65. // this time, it is the lower 64 bits of the md5 of the function
  66. // name. Any suffix with .llvm. is trimmed since these are added by
  67. // thinLTO global promotion. At the time the profile is consumed,
  68. // these suffixes will not be present.
  69. return Function::getGUID(FunctionName.take_front(Pos));
  70. }
  71. Expected<MemProfSchema> readMemProfSchema(const unsigned char *&Buffer) {
  72. using namespace support;
  73. const unsigned char *Ptr = Buffer;
  74. const uint64_t NumSchemaIds =
  75. endian::readNext<uint64_t, little, unaligned>(Ptr);
  76. if (NumSchemaIds > static_cast<uint64_t>(Meta::Size)) {
  77. return make_error<InstrProfError>(instrprof_error::malformed,
  78. "memprof schema invalid");
  79. }
  80. MemProfSchema Result;
  81. for (size_t I = 0; I < NumSchemaIds; I++) {
  82. const uint64_t Tag = endian::readNext<uint64_t, little, unaligned>(Ptr);
  83. if (Tag >= static_cast<uint64_t>(Meta::Size)) {
  84. return make_error<InstrProfError>(instrprof_error::malformed,
  85. "memprof schema invalid");
  86. }
  87. Result.push_back(static_cast<Meta>(Tag));
  88. }
  89. // Advace the buffer to one past the schema if we succeeded.
  90. Buffer = Ptr;
  91. return Result;
  92. }
  93. } // namespace memprof
  94. } // namespace llvm