Qin Zhao | 7e4933f | 2016-05-25 17:49:00 +0000 | [diff] [blame] | 1 | //===-- 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 Zhao | 4175a6d | 2016-06-02 18:45:25 +0000 | [diff] [blame] | 16 | #include "sanitizer_common/sanitizer_addrhashmap.h" |
| 17 | #include "sanitizer_common/sanitizer_placement_new.h" |
Qin Zhao | 7e4933f | 2016-05-25 17:49:00 +0000 | [diff] [blame] | 18 | |
| 19 | namespace __esan { |
| 20 | |
Qin Zhao | 4175a6d | 2016-06-02 18:45:25 +0000 | [diff] [blame] | 21 | //===-- Struct field access counter runtime -------------------------------===// |
| 22 | |
Qin Zhao | 9e39638 | 2016-05-31 21:27:39 +0000 | [diff] [blame] | 23 | // This should be kept consistent with LLVM's EfficiencySanitizer StructInfo. |
| 24 | struct StructInfo { |
| 25 | const char *StructName; |
Qin Zhao | 4175a6d | 2016-06-02 18:45:25 +0000 | [diff] [blame] | 26 | u32 NumFields; |
Qin Zhao | 9e39638 | 2016-05-31 21:27:39 +0000 | [diff] [blame] | 27 | 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). |
| 33 | struct CacheFragInfo { |
| 34 | const char *UnitName; |
Qin Zhao | 4175a6d | 2016-06-02 18:45:25 +0000 | [diff] [blame] | 35 | u32 NumStructs; |
Qin Zhao | 9e39638 | 2016-05-31 21:27:39 +0000 | [diff] [blame] | 36 | StructInfo *Structs; |
| 37 | }; |
| 38 | |
Qin Zhao | 4175a6d | 2016-06-02 18:45:25 +0000 | [diff] [blame] | 39 | struct 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. |
| 46 | typedef AddrHashMap<StructCounter, 31051> StructHashMap; |
| 47 | struct Context { |
| 48 | StructHashMap StructMap; |
| 49 | u32 NumStructs; |
| 50 | u64 TotalCount; // The total access count of all structs. |
| 51 | }; |
| 52 | static Context *Ctx; |
| 53 | |
| 54 | static 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 | |
| 70 | static 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 | |
| 87 | static 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 Zhao | 7e4933f | 2016-05-25 17:49:00 +0000 | [diff] [blame] | 92 | //===-- Init/exit functions -----------------------------------------------===// |
| 93 | |
| 94 | void processCacheFragCompilationUnitInit(void *Ptr) { |
Qin Zhao | 9e39638 | 2016-05-31 21:27:39 +0000 | [diff] [blame] | 95 | CacheFragInfo *CacheFrag = (CacheFragInfo *)Ptr; |
| 96 | VPrintf(2, "in esan::%s: %s with %u class(es)/struct(s)\n", |
Qin Zhao | 4175a6d | 2016-06-02 18:45:25 +0000 | [diff] [blame] | 97 | __FUNCTION__, CacheFrag->UnitName, CacheFrag->NumStructs); |
| 98 | registerStructInfo(CacheFrag); |
Qin Zhao | 7e4933f | 2016-05-25 17:49:00 +0000 | [diff] [blame] | 99 | } |
| 100 | |
| 101 | void processCacheFragCompilationUnitExit(void *Ptr) { |
Qin Zhao | 9e39638 | 2016-05-31 21:27:39 +0000 | [diff] [blame] | 102 | CacheFragInfo *CacheFrag = (CacheFragInfo *)Ptr; |
| 103 | VPrintf(2, "in esan::%s: %s with %u class(es)/struct(s)\n", |
Qin Zhao | 4175a6d | 2016-06-02 18:45:25 +0000 | [diff] [blame] | 104 | __FUNCTION__, CacheFrag->UnitName, CacheFrag->NumStructs); |
| 105 | unregisterStructInfo(CacheFrag); |
Qin Zhao | 7e4933f | 2016-05-25 17:49:00 +0000 | [diff] [blame] | 106 | } |
| 107 | |
| 108 | void initializeCacheFrag() { |
| 109 | VPrintf(2, "in esan::%s\n", __FUNCTION__); |
Qin Zhao | 4175a6d | 2016-06-02 18:45:25 +0000 | [diff] [blame] | 110 | // 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 Zhao | 7e4933f | 2016-05-25 17:49:00 +0000 | [diff] [blame] | 115 | } |
| 116 | |
| 117 | int finalizeCacheFrag() { |
| 118 | VPrintf(2, "in esan::%s\n", __FUNCTION__); |
Qin Zhao | 4175a6d | 2016-06-02 18:45:25 +0000 | [diff] [blame] | 119 | reportStructSummary(); |
Qin Zhao | 7e4933f | 2016-05-25 17:49:00 +0000 | [diff] [blame] | 120 | return 0; |
| 121 | } |
| 122 | |
| 123 | } // namespace __esan |