blob: af36d90bb50c08518b092dce0a3efdb21d617017 [file] [log] [blame]
Qin Zhao7e4933f2016-05-25 17:49:00 +00001//===-- cache_frag.cpp ----------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of EfficiencySanitizer, a family of performance tuners.
11//
12// This file contains cache fragmentation-specific code.
13//===----------------------------------------------------------------------===//
14
15#include "esan.h"
Qin Zhao4175a6d2016-06-02 18:45:25 +000016#include "sanitizer_common/sanitizer_addrhashmap.h"
17#include "sanitizer_common/sanitizer_placement_new.h"
Qin Zhao7e4933f2016-05-25 17:49:00 +000018
19namespace __esan {
20
Qin Zhao4175a6d2016-06-02 18:45:25 +000021//===-- Struct field access counter runtime -------------------------------===//
22
Qin Zhao9e396382016-05-31 21:27:39 +000023// This should be kept consistent with LLVM's EfficiencySanitizer StructInfo.
24struct StructInfo {
25 const char *StructName;
Qin Zhao4175a6d2016-06-02 18:45:25 +000026 u32 NumFields;
Qin Zhao9e396382016-05-31 21:27:39 +000027 u64 *FieldCounters;
28 const char **FieldTypeNames;
29};
30
31// This should be kept consistent with LLVM's EfficiencySanitizer CacheFragInfo.
32// The tool-specific information per compilation unit (module).
33struct CacheFragInfo {
34 const char *UnitName;
Qin Zhao4175a6d2016-06-02 18:45:25 +000035 u32 NumStructs;
Qin Zhao9e396382016-05-31 21:27:39 +000036 StructInfo *Structs;
37};
38
Qin Zhao4175a6d2016-06-02 18:45:25 +000039struct StructCounter {
40 StructInfo *Struct;
41 u64 Count; // The total access count of the struct.
42 u32 Variance; // Variance score for the struct layout access.
43};
44
45// We use StructHashMap to keep track of an unique copy of StructCounter.
46typedef AddrHashMap<StructCounter, 31051> StructHashMap;
47struct Context {
48 StructHashMap StructMap;
49 u32 NumStructs;
50 u64 TotalCount; // The total access count of all structs.
51};
52static Context *Ctx;
53
54static void registerStructInfo(CacheFragInfo *CacheFrag) {
55 for (u32 i = 0; i < CacheFrag->NumStructs; ++i) {
56 StructInfo *Struct = &CacheFrag->Structs[i];
57 StructHashMap::Handle H(&Ctx->StructMap, (uptr)Struct->FieldCounters);
58 if (H.created()) {
59 VPrintf(2, " Register %s: %u fields\n",
60 Struct->StructName, Struct->NumFields);
61 H->Struct = Struct;
62 ++Ctx->NumStructs;
63 } else {
64 VPrintf(2, " Duplicated %s: %u fields\n",
65 Struct->StructName, Struct->NumFields);
66 }
67 }
68}
69
70static void unregisterStructInfo(CacheFragInfo *CacheFrag) {
71 // FIXME: if the library is unloaded before finalizeCacheFrag, we should
72 // collect the result for later report.
73 for (u32 i = 0; i < CacheFrag->NumStructs; ++i) {
74 StructInfo *Struct = &CacheFrag->Structs[i];
75 StructHashMap::Handle H(&Ctx->StructMap, (uptr)Struct->FieldCounters, true);
76 if (H.exists()) {
77 VPrintf(2, " Unregister %s: %u fields\n",
78 Struct->StructName, Struct->NumFields);
79 --Ctx->NumStructs;
80 } else {
81 VPrintf(2, " Duplicated %s: %u fields\n",
82 Struct->StructName, Struct->NumFields);
83 }
84 }
85}
86
87static void reportStructSummary() {
88 // FIXME: iterate StructHashMap and generate the final report.
89 Report("%s is not finished: nothing yet to report\n", SanitizerToolName);
90}
91
Qin Zhao7e4933f2016-05-25 17:49:00 +000092//===-- Init/exit functions -----------------------------------------------===//
93
94void processCacheFragCompilationUnitInit(void *Ptr) {
Qin Zhao9e396382016-05-31 21:27:39 +000095 CacheFragInfo *CacheFrag = (CacheFragInfo *)Ptr;
96 VPrintf(2, "in esan::%s: %s with %u class(es)/struct(s)\n",
Qin Zhao4175a6d2016-06-02 18:45:25 +000097 __FUNCTION__, CacheFrag->UnitName, CacheFrag->NumStructs);
98 registerStructInfo(CacheFrag);
Qin Zhao7e4933f2016-05-25 17:49:00 +000099}
100
101void processCacheFragCompilationUnitExit(void *Ptr) {
Qin Zhao9e396382016-05-31 21:27:39 +0000102 CacheFragInfo *CacheFrag = (CacheFragInfo *)Ptr;
103 VPrintf(2, "in esan::%s: %s with %u class(es)/struct(s)\n",
Qin Zhao4175a6d2016-06-02 18:45:25 +0000104 __FUNCTION__, CacheFrag->UnitName, CacheFrag->NumStructs);
105 unregisterStructInfo(CacheFrag);
Qin Zhao7e4933f2016-05-25 17:49:00 +0000106}
107
108void initializeCacheFrag() {
109 VPrintf(2, "in esan::%s\n", __FUNCTION__);
Qin Zhao4175a6d2016-06-02 18:45:25 +0000110 // We use placement new to initialize Ctx before C++ static initializaion.
111 // We make CtxMem 8-byte aligned for atomic operations in AddrHashMap.
112 static u64 CtxMem[sizeof(Context) / sizeof(u64) + 1];
113 Ctx = new(CtxMem) Context();
114 Ctx->NumStructs = 0;
Qin Zhao7e4933f2016-05-25 17:49:00 +0000115}
116
117int finalizeCacheFrag() {
118 VPrintf(2, "in esan::%s\n", __FUNCTION__);
Qin Zhao4175a6d2016-06-02 18:45:25 +0000119 reportStructSummary();
Qin Zhao7e4933f2016-05-25 17:49:00 +0000120 return 0;
121}
122
123} // namespace __esan