@@ -414,6 +414,144 @@ static void setSummary(IndexedInstrProf::Summary *TheSummary,
414
414
TheSummary->setEntry (I, Res[I]);
415
415
}
416
416
417
+ // Serialize Schema.
418
+ static void writeMemProfSchema (ProfOStream &OS,
419
+ const memprof::MemProfSchema &Schema) {
420
+ OS.write (static_cast <uint64_t >(Schema.size ()));
421
+ for (const auto Id : Schema)
422
+ OS.write (static_cast <uint64_t >(Id));
423
+ }
424
+
425
+ // Serialize MemProfRecordData. Return RecordTableOffset.
426
+ static uint64_t writeMemProfRecords (
427
+ ProfOStream &OS,
428
+ llvm::MapVector<GlobalValue::GUID, memprof::IndexedMemProfRecord>
429
+ &MemProfRecordData,
430
+ memprof::MemProfSchema *Schema) {
431
+ auto RecordWriter =
432
+ std::make_unique<memprof::RecordWriterTrait>(memprof::Version1);
433
+ RecordWriter->Schema = Schema;
434
+ OnDiskChainedHashTableGenerator<memprof::RecordWriterTrait>
435
+ RecordTableGenerator;
436
+ for (auto &I : MemProfRecordData) {
437
+ // Insert the key (func hash) and value (memprof record).
438
+ RecordTableGenerator.insert (I.first , I.second , *RecordWriter.get ());
439
+ }
440
+ // Release the memory of this MapVector as it is no longer needed.
441
+ MemProfRecordData.clear ();
442
+
443
+ // The call to Emit invokes RecordWriterTrait::EmitData which destructs
444
+ // the memprof record copies owned by the RecordTableGenerator. This works
445
+ // because the RecordTableGenerator is not used after this point.
446
+ return RecordTableGenerator.Emit (OS.OS , *RecordWriter);
447
+ }
448
+
449
+ // Serialize MemProfFrameData. Return FrameTableOffset.
450
+ static uint64_t writeMemProfFrames (
451
+ ProfOStream &OS,
452
+ llvm::MapVector<memprof::FrameId, memprof::Frame> &MemProfFrameData) {
453
+ auto FrameWriter = std::make_unique<memprof::FrameWriterTrait>();
454
+ OnDiskChainedHashTableGenerator<memprof::FrameWriterTrait>
455
+ FrameTableGenerator;
456
+ for (auto &I : MemProfFrameData) {
457
+ // Insert the key (frame id) and value (frame contents).
458
+ FrameTableGenerator.insert (I.first , I.second );
459
+ }
460
+ // Release the memory of this MapVector as it is no longer needed.
461
+ MemProfFrameData.clear ();
462
+
463
+ return FrameTableGenerator.Emit (OS.OS , *FrameWriter);
464
+ }
465
+
466
+ static Error writeMemProfV0 (
467
+ ProfOStream &OS,
468
+ llvm::MapVector<GlobalValue::GUID, memprof::IndexedMemProfRecord>
469
+ &MemProfRecordData,
470
+ llvm::MapVector<memprof::FrameId, memprof::Frame> &MemProfFrameData) {
471
+ uint64_t HeaderUpdatePos = OS.tell ();
472
+ OS.write (0ULL ); // Reserve space for the memprof record table offset.
473
+ OS.write (0ULL ); // Reserve space for the memprof frame payload offset.
474
+ OS.write (0ULL ); // Reserve space for the memprof frame table offset.
475
+
476
+ auto Schema = memprof::PortableMemInfoBlock::getSchema ();
477
+ writeMemProfSchema (OS, Schema);
478
+
479
+ uint64_t RecordTableOffset =
480
+ writeMemProfRecords (OS, MemProfRecordData, &Schema);
481
+
482
+ uint64_t FramePayloadOffset = OS.tell ();
483
+ uint64_t FrameTableOffset = writeMemProfFrames (OS, MemProfFrameData);
484
+
485
+ uint64_t Header[] = {RecordTableOffset, FramePayloadOffset, FrameTableOffset};
486
+ OS.patch ({{HeaderUpdatePos, Header, std::size (Header)}});
487
+
488
+ return Error::success ();
489
+ }
490
+
491
+ static Error writeMemProfV1 (
492
+ ProfOStream &OS,
493
+ llvm::MapVector<GlobalValue::GUID, memprof::IndexedMemProfRecord>
494
+ &MemProfRecordData,
495
+ llvm::MapVector<memprof::FrameId, memprof::Frame> &MemProfFrameData) {
496
+ OS.write (memprof::Version0);
497
+ uint64_t HeaderUpdatePos = OS.tell ();
498
+ OS.write (0ULL ); // Reserve space for the memprof record table offset.
499
+ OS.write (0ULL ); // Reserve space for the memprof frame payload offset.
500
+ OS.write (0ULL ); // Reserve space for the memprof frame table offset.
501
+
502
+ auto Schema = memprof::PortableMemInfoBlock::getSchema ();
503
+ writeMemProfSchema (OS, Schema);
504
+
505
+ uint64_t RecordTableOffset =
506
+ writeMemProfRecords (OS, MemProfRecordData, &Schema);
507
+
508
+ uint64_t FramePayloadOffset = OS.tell ();
509
+ uint64_t FrameTableOffset = writeMemProfFrames (OS, MemProfFrameData);
510
+
511
+ uint64_t Header[] = {RecordTableOffset, FramePayloadOffset, FrameTableOffset};
512
+ OS.patch ({{HeaderUpdatePos, Header, std::size (Header)}});
513
+
514
+ return Error::success ();
515
+ }
516
+
517
+ // The MemProf profile data includes a simple schema
518
+ // with the format described below followed by the hashtable:
519
+ // uint64_t Version
520
+ // uint64_t RecordTableOffset = RecordTableGenerator.Emit
521
+ // uint64_t FramePayloadOffset = Stream offset before emitting the frame table
522
+ // uint64_t FrameTableOffset = FrameTableGenerator.Emit
523
+ // uint64_t Num schema entries
524
+ // uint64_t Schema entry 0
525
+ // uint64_t Schema entry 1
526
+ // ....
527
+ // uint64_t Schema entry N - 1
528
+ // OnDiskChainedHashTable MemProfRecordData
529
+ // OnDiskChainedHashTable MemProfFrameData
530
+ static Error writeMemProf (
531
+ ProfOStream &OS,
532
+ llvm::MapVector<GlobalValue::GUID, memprof::IndexedMemProfRecord>
533
+ &MemProfRecordData,
534
+ llvm::MapVector<memprof::FrameId, memprof::Frame> &MemProfFrameData,
535
+ memprof::IndexedVersion MemProfVersionRequested) {
536
+
537
+ switch (MemProfVersionRequested) {
538
+ case memprof::Version0:
539
+ return writeMemProfV0 (OS, MemProfRecordData, MemProfFrameData);
540
+ case memprof::Version1:
541
+ return writeMemProfV1 (OS, MemProfRecordData, MemProfFrameData);
542
+ case memprof::Version2:
543
+ // TODO: Implement. Fall through to the error handling below for now.
544
+ break ;
545
+ }
546
+
547
+ return make_error<InstrProfError>(
548
+ instrprof_error::unsupported_version,
549
+ formatv (" MemProf version {} not supported; "
550
+ " requires version between {} and {}, inclusive" ,
551
+ MemProfVersionRequested, memprof::MinimumSupportedVersion,
552
+ memprof::MaximumSupportedVersion));
553
+ }
554
+
417
555
Error InstrProfWriter::writeImpl (ProfOStream &OS) {
418
556
using namespace IndexedInstrProf ;
419
557
using namespace support ;
@@ -517,85 +655,13 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) {
517
655
// Write the hash table.
518
656
uint64_t HashTableStart = Generator.Emit (OS.OS , *InfoObj);
519
657
520
- // Write the MemProf profile data if we have it. This includes a simple schema
521
- // with the format described below followed by the hashtable:
522
- // uint64_t Version
523
- // uint64_t RecordTableOffset = RecordTableGenerator.Emit
524
- // uint64_t FramePayloadOffset = Stream offset before emitting the frame table
525
- // uint64_t FrameTableOffset = FrameTableGenerator.Emit
526
- // uint64_t Num schema entries
527
- // uint64_t Schema entry 0
528
- // uint64_t Schema entry 1
529
- // ....
530
- // uint64_t Schema entry N - 1
531
- // OnDiskChainedHashTable MemProfRecordData
532
- // OnDiskChainedHashTable MemProfFrameData
658
+ // Write the MemProf profile data if we have it.
533
659
uint64_t MemProfSectionStart = 0 ;
534
660
if (static_cast <bool >(ProfileKind & InstrProfKind::MemProf)) {
535
- if (MemProfVersionRequested < memprof::MinimumSupportedVersion ||
536
- MemProfVersionRequested > memprof::MaximumSupportedVersion) {
537
- return make_error<InstrProfError>(
538
- instrprof_error::unsupported_version,
539
- formatv (" MemProf version {} not supported; "
540
- " requires version between {} and {}, inclusive" ,
541
- MemProfVersionRequested, memprof::MinimumSupportedVersion,
542
- memprof::MaximumSupportedVersion));
543
- }
544
-
545
661
MemProfSectionStart = OS.tell ();
546
-
547
- if (MemProfVersionRequested >= memprof::Version1)
548
- OS.write (MemProfVersionRequested);
549
-
550
- OS.write (0ULL ); // Reserve space for the memprof record table offset.
551
- OS.write (0ULL ); // Reserve space for the memprof frame payload offset.
552
- OS.write (0ULL ); // Reserve space for the memprof frame table offset.
553
-
554
- auto Schema = memprof::PortableMemInfoBlock::getSchema ();
555
- OS.write (static_cast <uint64_t >(Schema.size ()));
556
- for (const auto Id : Schema) {
557
- OS.write (static_cast <uint64_t >(Id));
558
- }
559
-
560
- auto RecordWriter =
561
- std::make_unique<memprof::RecordWriterTrait>(memprof::Version1);
562
- RecordWriter->Schema = &Schema;
563
- OnDiskChainedHashTableGenerator<memprof::RecordWriterTrait>
564
- RecordTableGenerator;
565
- for (auto &I : MemProfRecordData) {
566
- // Insert the key (func hash) and value (memprof record).
567
- RecordTableGenerator.insert (I.first , I.second , *RecordWriter.get ());
568
- }
569
- // Release the memory of this MapVector as it is no longer needed.
570
- MemProfRecordData.clear ();
571
-
572
- // The call to Emit invokes RecordWriterTrait::EmitData which destructs
573
- // the memprof record copies owned by the RecordTableGenerator. This works
574
- // because the RecordTableGenerator is not used after this point.
575
- uint64_t RecordTableOffset =
576
- RecordTableGenerator.Emit (OS.OS , *RecordWriter);
577
-
578
- uint64_t FramePayloadOffset = OS.tell ();
579
-
580
- auto FrameWriter = std::make_unique<memprof::FrameWriterTrait>();
581
- OnDiskChainedHashTableGenerator<memprof::FrameWriterTrait>
582
- FrameTableGenerator;
583
- for (auto &I : MemProfFrameData) {
584
- // Insert the key (frame id) and value (frame contents).
585
- FrameTableGenerator.insert (I.first , I.second );
586
- }
587
- // Release the memory of this MapVector as it is no longer needed.
588
- MemProfFrameData.clear ();
589
-
590
- uint64_t FrameTableOffset = FrameTableGenerator.Emit (OS.OS , *FrameWriter);
591
-
592
- uint64_t Header[] = {RecordTableOffset, FramePayloadOffset,
593
- FrameTableOffset};
594
- uint64_t HeaderUpdatePos = MemProfSectionStart;
595
- if (MemProfVersionRequested >= memprof::Version1)
596
- // The updates go just after the version field.
597
- HeaderUpdatePos += sizeof (uint64_t );
598
- OS.patch ({{HeaderUpdatePos, Header, std::size (Header)}});
662
+ if (auto E = writeMemProf (OS, MemProfRecordData, MemProfFrameData,
663
+ MemProfVersionRequested))
664
+ return E;
599
665
}
600
666
601
667
// BinaryIdSection has two parts:
0 commit comments