@@ -201,6 +201,9 @@ enum class SecProfSummaryFlags : uint32_t {
201
201
// / SecFlagIsPreInlined means this profile contains ShouldBeInlined
202
202
// / contexts thus this is CS preinliner computed.
203
203
SecFlagIsPreInlined = (1 << 4 ),
204
+
205
+ // / SecFlagHasVTableTypeProf means this profile contains vtable type profiles.
206
+ SecFlagHasVTableTypeProf = (1 << 5 ),
204
207
};
205
208
206
209
enum class SecFuncMetadataFlags : uint32_t {
@@ -312,16 +315,19 @@ struct LineLocationHash {
312
315
313
316
raw_ostream &operator <<(raw_ostream &OS, const LineLocation &Loc);
314
317
318
+ using TypeMap = std::map<FunctionId, uint64_t >;
319
+
315
320
// / Representation of a single sample record.
316
321
// /
317
322
// / A sample record is represented by a positive integer value, which
318
323
// / indicates how frequently was the associated line location executed.
319
324
// /
320
325
// / Additionally, if the associated location contains a function call,
321
- // / the record will hold a list of all the possible called targets. For
322
- // / direct calls, this will be the exact function being invoked. For
323
- // / indirect calls (function pointers, virtual table dispatch), this
324
- // / will be a list of one or more functions.
326
+ // / the record will hold a list of all the possible called targets and the types
327
+ // / for virtual table dispatches. For direct calls, this will be the exact
328
+ // / function being invoked. For indirect calls (function pointers, virtual table
329
+ // / dispatch), this will be a list of one or more functions. For virtual table
330
+ // / dispatches, this record will also hold the type of the object.
325
331
class SampleRecord {
326
332
public:
327
333
using CallTarget = std::pair<FunctionId, uint64_t >;
@@ -336,6 +342,7 @@ class SampleRecord {
336
342
337
343
using SortedCallTargetSet = std::set<CallTarget, CallTargetComparator>;
338
344
using CallTargetMap = std::unordered_map<FunctionId, uint64_t >;
345
+
339
346
SampleRecord () = default ;
340
347
341
348
// / Increment the number of samples for this record by \p S.
@@ -374,6 +381,14 @@ class SampleRecord {
374
381
: sampleprof_error::success;
375
382
}
376
383
384
+ sampleprof_error addTypeCount (FunctionId F, uint64_t S, uint64_t Weight = 1 ) {
385
+ uint64_t &Samples = TypeCounts[F];
386
+ bool Overflowed;
387
+ Samples = SaturatingMultiplyAdd (S, Weight, Samples, &Overflowed);
388
+ return Overflowed ? sampleprof_error::counter_overflow
389
+ : sampleprof_error::success;
390
+ }
391
+
377
392
// / Remove called function from the call target map. Return the target sample
378
393
// / count of the called function.
379
394
uint64_t removeCalledTarget (FunctionId F) {
@@ -391,6 +406,7 @@ class SampleRecord {
391
406
392
407
uint64_t getSamples () const { return NumSamples; }
393
408
const CallTargetMap &getCallTargets () const { return CallTargets; }
409
+ const TypeMap &getTypes () const { return TypeCounts; }
394
410
const SortedCallTargetSet getSortedCallTargets () const {
395
411
return sortCallTargets (CallTargets);
396
412
}
@@ -439,6 +455,7 @@ class SampleRecord {
439
455
private:
440
456
uint64_t NumSamples = 0 ;
441
457
CallTargetMap CallTargets;
458
+ TypeMap TypeCounts;
442
459
};
443
460
444
461
raw_ostream &operator <<(raw_ostream &OS, const SampleRecord &Sample);
@@ -734,6 +751,7 @@ using BodySampleMap = std::map<LineLocation, SampleRecord>;
734
751
// memory, which is *very* significant for large profiles.
735
752
using FunctionSamplesMap = std::map<FunctionId, FunctionSamples>;
736
753
using CallsiteSampleMap = std::map<LineLocation, FunctionSamplesMap>;
754
+ using CallsiteTypeMap = std::map<LineLocation, TypeMap>;
737
755
using LocToLocMap =
738
756
std::unordered_map<LineLocation, LineLocation, LineLocationHash>;
739
757
@@ -791,6 +809,11 @@ class FunctionSamples {
791
809
Func, Num, Weight);
792
810
}
793
811
812
+ sampleprof_error addTypeSamples (const LineLocation &Loc, FunctionId Func,
813
+ uint64_t Num, uint64_t Weight = 1 ) {
814
+ return BodySamples[Loc].addTypeCount (Func, Num, Weight);
815
+ }
816
+
794
817
sampleprof_error addSampleRecord (LineLocation Location,
795
818
const SampleRecord &SampleRecord,
796
819
uint64_t Weight = 1 ) {
@@ -916,6 +939,13 @@ class FunctionSamples {
916
939
return &Iter->second ;
917
940
}
918
941
942
+ const TypeMap *findTypeSamplesAt (const LineLocation &Loc) const {
943
+ auto Iter = VirtualCallsiteTypes.find (mapIRLocToProfileLoc (Loc));
944
+ if (Iter == VirtualCallsiteTypes.end ())
945
+ return nullptr ;
946
+ return &Iter->second ;
947
+ }
948
+
919
949
// / Returns a pointer to FunctionSamples at the given callsite location
920
950
// / \p Loc with callee \p CalleeName. If no callsite can be found, relax
921
951
// / the restriction to return the FunctionSamples at callsite location
@@ -977,6 +1007,14 @@ class FunctionSamples {
977
1007
return CallsiteSamples;
978
1008
}
979
1009
1010
+ const CallsiteTypeMap &getCallsiteTypes () const {
1011
+ return VirtualCallsiteTypes;
1012
+ }
1013
+
1014
+ TypeMap& getTypeSamplesAt (const LineLocation &Loc) {
1015
+ return VirtualCallsiteTypes[mapIRLocToProfileLoc (Loc)];
1016
+ }
1017
+
980
1018
// / Return the maximum of sample counts in a function body. When SkipCallSite
981
1019
// / is false, which is the default, the return count includes samples in the
982
1020
// / inlined functions. When SkipCallSite is true, the return count only
@@ -1274,6 +1312,8 @@ class FunctionSamples {
1274
1312
// / collected in the call to baz() at line offset 8.
1275
1313
CallsiteSampleMap CallsiteSamples;
1276
1314
1315
+ CallsiteTypeMap VirtualCallsiteTypes;
1316
+
1277
1317
// / IR to profile location map generated by stale profile matching.
1278
1318
// /
1279
1319
// / Each entry is a mapping from the location on current build to the matched
0 commit comments