|
11 | 11 | //===----------------------------------------------------------------------===//
|
12 | 12 |
|
13 | 13 | #include "llvm/ProfileData/InstrProf.h"
|
| 14 | +#include "llvm/ProfileData/InstrProfReader.h" |
14 | 15 | #include "llvm/ProfileData/MemProf.h"
|
15 | 16 | #include "llvm/Support/FormatVariadic.h"
|
16 | 17 | #include "llvm/Support/OnDiskHashTable.h"
|
@@ -297,4 +298,127 @@ Error writeMemProf(ProfOStream &OS, memprof::IndexedMemProfData &MemProfData,
|
297 | 298 | memprof::MaximumSupportedVersion));
|
298 | 299 | }
|
299 | 300 |
|
| 301 | +Error IndexedMemProfReader::deserializeV2(const unsigned char *Start, |
| 302 | + const unsigned char *Ptr) { |
| 303 | + // The value returned from RecordTableGenerator.Emit. |
| 304 | + const uint64_t RecordTableOffset = |
| 305 | + support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); |
| 306 | + // The offset in the stream right before invoking |
| 307 | + // FrameTableGenerator.Emit. |
| 308 | + const uint64_t FramePayloadOffset = |
| 309 | + support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); |
| 310 | + // The value returned from FrameTableGenerator.Emit. |
| 311 | + const uint64_t FrameTableOffset = |
| 312 | + support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); |
| 313 | + |
| 314 | + // The offset in the stream right before invoking |
| 315 | + // CallStackTableGenerator.Emit. |
| 316 | + uint64_t CallStackPayloadOffset = 0; |
| 317 | + // The value returned from CallStackTableGenerator.Emit. |
| 318 | + uint64_t CallStackTableOffset = 0; |
| 319 | + if (Version >= memprof::Version2) { |
| 320 | + CallStackPayloadOffset = |
| 321 | + support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); |
| 322 | + CallStackTableOffset = |
| 323 | + support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); |
| 324 | + } |
| 325 | + |
| 326 | + // Read the schema. |
| 327 | + auto SchemaOr = memprof::readMemProfSchema(Ptr); |
| 328 | + if (!SchemaOr) |
| 329 | + return SchemaOr.takeError(); |
| 330 | + Schema = SchemaOr.get(); |
| 331 | + |
| 332 | + // Now initialize the table reader with a pointer into data buffer. |
| 333 | + MemProfRecordTable.reset(MemProfRecordHashTable::Create( |
| 334 | + /*Buckets=*/Start + RecordTableOffset, |
| 335 | + /*Payload=*/Ptr, |
| 336 | + /*Base=*/Start, memprof::RecordLookupTrait(Version, Schema))); |
| 337 | + |
| 338 | + // Initialize the frame table reader with the payload and bucket offsets. |
| 339 | + MemProfFrameTable.reset(MemProfFrameHashTable::Create( |
| 340 | + /*Buckets=*/Start + FrameTableOffset, |
| 341 | + /*Payload=*/Start + FramePayloadOffset, |
| 342 | + /*Base=*/Start)); |
| 343 | + |
| 344 | + if (Version >= memprof::Version2) |
| 345 | + MemProfCallStackTable.reset(MemProfCallStackHashTable::Create( |
| 346 | + /*Buckets=*/Start + CallStackTableOffset, |
| 347 | + /*Payload=*/Start + CallStackPayloadOffset, |
| 348 | + /*Base=*/Start)); |
| 349 | + |
| 350 | + return Error::success(); |
| 351 | +} |
| 352 | + |
| 353 | +Error IndexedMemProfReader::deserializeV3(const unsigned char *Start, |
| 354 | + const unsigned char *Ptr) { |
| 355 | + // The offset in the stream right before invoking |
| 356 | + // CallStackTableGenerator.Emit. |
| 357 | + const uint64_t CallStackPayloadOffset = |
| 358 | + support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); |
| 359 | + // The offset in the stream right before invoking RecordTableGenerator.Emit. |
| 360 | + const uint64_t RecordPayloadOffset = |
| 361 | + support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); |
| 362 | + // The value returned from RecordTableGenerator.Emit. |
| 363 | + const uint64_t RecordTableOffset = |
| 364 | + support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); |
| 365 | + |
| 366 | + // Read the schema. |
| 367 | + auto SchemaOr = memprof::readMemProfSchema(Ptr); |
| 368 | + if (!SchemaOr) |
| 369 | + return SchemaOr.takeError(); |
| 370 | + Schema = SchemaOr.get(); |
| 371 | + |
| 372 | + FrameBase = Ptr; |
| 373 | + CallStackBase = Start + CallStackPayloadOffset; |
| 374 | + |
| 375 | + // Compute the number of elements in the radix tree array. Since we use this |
| 376 | + // to reserve enough bits in a BitVector, it's totally OK if we overestimate |
| 377 | + // this number a little bit because of padding just before the next section. |
| 378 | + RadixTreeSize = (RecordPayloadOffset - CallStackPayloadOffset) / |
| 379 | + sizeof(memprof::LinearFrameId); |
| 380 | + |
| 381 | + // Now initialize the table reader with a pointer into data buffer. |
| 382 | + MemProfRecordTable.reset(MemProfRecordHashTable::Create( |
| 383 | + /*Buckets=*/Start + RecordTableOffset, |
| 384 | + /*Payload=*/Start + RecordPayloadOffset, |
| 385 | + /*Base=*/Start, memprof::RecordLookupTrait(memprof::Version3, Schema))); |
| 386 | + |
| 387 | + return Error::success(); |
| 388 | +} |
| 389 | + |
| 390 | +Error IndexedMemProfReader::deserialize(const unsigned char *Start, |
| 391 | + uint64_t MemProfOffset) { |
| 392 | + const unsigned char *Ptr = Start + MemProfOffset; |
| 393 | + |
| 394 | + // Read the MemProf version number. |
| 395 | + const uint64_t FirstWord = |
| 396 | + support::endian::readNext<uint64_t, llvm::endianness::little>(Ptr); |
| 397 | + |
| 398 | + if (FirstWord == memprof::Version2 || FirstWord == memprof::Version3) { |
| 399 | + // Everything is good. We can proceed to deserialize the rest. |
| 400 | + Version = static_cast<memprof::IndexedVersion>(FirstWord); |
| 401 | + } else { |
| 402 | + return make_error<InstrProfError>( |
| 403 | + instrprof_error::unsupported_version, |
| 404 | + formatv("MemProf version {} not supported; " |
| 405 | + "requires version between {} and {}, inclusive", |
| 406 | + FirstWord, memprof::MinimumSupportedVersion, |
| 407 | + memprof::MaximumSupportedVersion)); |
| 408 | + } |
| 409 | + |
| 410 | + switch (Version) { |
| 411 | + case memprof::Version2: |
| 412 | + if (Error E = deserializeV2(Start, Ptr)) |
| 413 | + return E; |
| 414 | + break; |
| 415 | + case memprof::Version3: |
| 416 | + if (Error E = deserializeV3(Start, Ptr)) |
| 417 | + return E; |
| 418 | + break; |
| 419 | + } |
| 420 | + |
| 421 | + return Error::success(); |
| 422 | +} |
| 423 | + |
300 | 424 | } // namespace llvm
|
0 commit comments