@@ -201,6 +201,9 @@ enum class SecProfSummaryFlags : uint32_t {
201201 // / SecFlagIsPreInlined means this profile contains ShouldBeInlined
202202 // / contexts thus this is CS preinliner computed.
203203 SecFlagIsPreInlined = (1 << 4 ),
204+
205+ // / SecFlagHasVTableTypeProf means this profile contains vtable type profiles.
206+ SecFlagHasVTableTypeProf = (1 << 5 ),
204207};
205208
206209enum class SecFuncMetadataFlags : uint32_t {
@@ -312,16 +315,19 @@ struct LineLocationHash {
312315
313316raw_ostream &operator <<(raw_ostream &OS, const LineLocation &Loc);
314317
318+ using TypeMap = std::map<FunctionId, uint64_t >;
319+
315320// / Representation of a single sample record.
316321// /
317322// / A sample record is represented by a positive integer value, which
318323// / indicates how frequently was the associated line location executed.
319324// /
320325// / 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.
325331class SampleRecord {
326332public:
327333 using CallTarget = std::pair<FunctionId, uint64_t >;
@@ -336,6 +342,7 @@ class SampleRecord {
336342
337343 using SortedCallTargetSet = std::set<CallTarget, CallTargetComparator>;
338344 using CallTargetMap = std::unordered_map<FunctionId, uint64_t >;
345+
339346 SampleRecord () = default ;
340347
341348 // / Increment the number of samples for this record by \p S.
@@ -374,6 +381,14 @@ class SampleRecord {
374381 : sampleprof_error::success;
375382 }
376383
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+
377392 // / Remove called function from the call target map. Return the target sample
378393 // / count of the called function.
379394 uint64_t removeCalledTarget (FunctionId F) {
@@ -391,6 +406,7 @@ class SampleRecord {
391406
392407 uint64_t getSamples () const { return NumSamples; }
393408 const CallTargetMap &getCallTargets () const { return CallTargets; }
409+ const TypeMap &getTypes () const { return TypeCounts; }
394410 const SortedCallTargetSet getSortedCallTargets () const {
395411 return sortCallTargets (CallTargets);
396412 }
@@ -439,6 +455,7 @@ class SampleRecord {
439455private:
440456 uint64_t NumSamples = 0 ;
441457 CallTargetMap CallTargets;
458+ TypeMap TypeCounts;
442459};
443460
444461raw_ostream &operator <<(raw_ostream &OS, const SampleRecord &Sample);
@@ -734,6 +751,7 @@ using BodySampleMap = std::map<LineLocation, SampleRecord>;
734751// memory, which is *very* significant for large profiles.
735752using FunctionSamplesMap = std::map<FunctionId, FunctionSamples>;
736753using CallsiteSampleMap = std::map<LineLocation, FunctionSamplesMap>;
754+ using CallsiteTypeMap = std::map<LineLocation, TypeMap>;
737755using LocToLocMap =
738756 std::unordered_map<LineLocation, LineLocation, LineLocationHash>;
739757
@@ -791,6 +809,11 @@ class FunctionSamples {
791809 Func, Num, Weight);
792810 }
793811
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+
794817 sampleprof_error addSampleRecord (LineLocation Location,
795818 const SampleRecord &SampleRecord,
796819 uint64_t Weight = 1 ) {
@@ -916,6 +939,13 @@ class FunctionSamples {
916939 return &Iter->second ;
917940 }
918941
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+
919949 // / Returns a pointer to FunctionSamples at the given callsite location
920950 // / \p Loc with callee \p CalleeName. If no callsite can be found, relax
921951 // / the restriction to return the FunctionSamples at callsite location
@@ -977,6 +1007,14 @@ class FunctionSamples {
9771007 return CallsiteSamples;
9781008 }
9791009
1010+ const CallsiteTypeMap &getCallsiteTypes () const {
1011+ return VirtualCallsiteTypes;
1012+ }
1013+
1014+ TypeMap& getTypeSamplesAt (const LineLocation &Loc) {
1015+ return VirtualCallsiteTypes[mapIRLocToProfileLoc (Loc)];
1016+ }
1017+
9801018 // / Return the maximum of sample counts in a function body. When SkipCallSite
9811019 // / is false, which is the default, the return count includes samples in the
9821020 // / inlined functions. When SkipCallSite is true, the return count only
@@ -1274,6 +1312,8 @@ class FunctionSamples {
12741312 // / collected in the call to baz() at line offset 8.
12751313 CallsiteSampleMap CallsiteSamples;
12761314
1315+ CallsiteTypeMap VirtualCallsiteTypes;
1316+
12771317 // / IR to profile location map generated by stale profile matching.
12781318 // /
12791319 // / Each entry is a mapping from the location on current build to the matched
0 commit comments