1/* Callgraph summary data structure. 2 Copyright (C) 2014-2015 Free Software Foundation, Inc. 3 Contributed by Martin Liska 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 3, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING3. If not see 19<http://www.gnu.org/licenses/>. */ 20 21#ifndef GCC_SYMBOL_SUMMARY_H 22#define GCC_SYMBOL_SUMMARY_H 23 24/* We want to pass just pointer types as argument for function_summary 25 template class. */ 26 27template <class T> 28class function_summary 29{ 30private: 31 function_summary(); 32}; 33 34template <class T> 35class GTY((user)) function_summary <T *> 36{ 37public: 38 /* Default construction takes SYMTAB as an argument. */ 39 function_summary (symbol_table *symtab, bool ggc = false): m_ggc (ggc), 40 m_map (13, ggc), m_insertion_enabled (true), m_symtab (symtab) 41 { 42#ifdef ENABLE_CHECKING 43 cgraph_node *node; 44 45 FOR_EACH_FUNCTION (node) 46 { 47 gcc_checking_assert (node->summary_uid > 0); 48 } 49#endif 50 51 m_symtab_insertion_hook = 52 symtab->add_cgraph_insertion_hook 53 (function_summary::symtab_insertion, this); 54 55 m_symtab_removal_hook = 56 symtab->add_cgraph_removal_hook 57 (function_summary::symtab_removal, this); 58 m_symtab_duplication_hook = 59 symtab->add_cgraph_duplication_hook 60 (function_summary::symtab_duplication, this); 61 } 62 63 /* Destructor. */ 64 virtual ~function_summary () 65 { 66 release (); 67 } 68 69 /* Destruction method that can be called for GGT purpose. */ 70 void release () 71 { 72 if (m_symtab_insertion_hook) 73 m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook); 74 75 if (m_symtab_removal_hook) 76 m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook); 77 78 if (m_symtab_duplication_hook) 79 m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook); 80 81 m_symtab_insertion_hook = NULL; 82 m_symtab_removal_hook = NULL; 83 m_symtab_duplication_hook = NULL; 84 85 /* Release all summaries. */ 86 typedef typename hash_map <int, T *, summary_hashmap_traits>::iterator map_iterator; 87 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it) 88 release ((*it).second); 89 } 90 91 /* Traverses all summarys with a function F called with 92 ARG as argument. */ 93 template<typename Arg, bool (*f)(const T &, Arg)> 94 void traverse (Arg a) const 95 { 96 m_map.traverse <f> (a); 97 } 98 99 /* Basic implementation of insert operation. */ 100 virtual void insert (cgraph_node *, T *) {} 101 102 /* Basic implementation of removal operation. */ 103 virtual void remove (cgraph_node *, T *) {} 104 105 /* Basic implementation of duplication operation. */ 106 virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *) {} 107 108 /* Allocates new data that are stored within map. */ 109 T* allocate_new () 110 { 111 return m_ggc ? new (ggc_alloc <T> ()) T() : new T () ; 112 } 113 114 /* Release an item that is stored within map. */ 115 void release (T *item) 116 { 117 if (m_ggc) 118 { 119 item->~T (); 120 ggc_free (item); 121 } 122 else 123 delete item; 124 } 125 126 /* Getter for summary callgraph node pointer. */ 127 T* get (cgraph_node *node) 128 { 129 return get (node->summary_uid); 130 } 131 132 /* Return number of elements handled by data structure. */ 133 size_t elements () 134 { 135 return m_map.elements (); 136 } 137 138 /* Enable insertion hook invocation. */ 139 void enable_insertion_hook () 140 { 141 m_insertion_enabled = true; 142 } 143 144 /* Enable insertion hook invocation. */ 145 void disable_insertion_hook () 146 { 147 m_insertion_enabled = false; 148 } 149 150 /* Symbol insertion hook that is registered to symbol table. */ 151 static void symtab_insertion (cgraph_node *node, void *data) 152 { 153 function_summary *summary = (function_summary <T *> *) (data); 154 155 if (summary->m_insertion_enabled) 156 summary->insert (node, summary->get (node)); 157 } 158 159 /* Symbol removal hook that is registered to symbol table. */ 160 static void symtab_removal (cgraph_node *node, void *data) 161 { 162 gcc_checking_assert (node->summary_uid); 163 function_summary *summary = (function_summary <T *> *) (data); 164 165 int summary_uid = node->summary_uid; 166 T **v = summary->m_map.get (summary_uid); 167 168 if (v) 169 { 170 summary->remove (node, *v); 171 172 if (!summary->m_ggc) 173 delete (*v); 174 175 summary->m_map.remove (summary_uid); 176 } 177 } 178 179 /* Symbol duplication hook that is registered to symbol table. */ 180 static void symtab_duplication (cgraph_node *node, cgraph_node *node2, 181 void *data) 182 { 183 function_summary *summary = (function_summary <T *> *) (data); 184 T **v = summary->m_map.get (node->summary_uid); 185 186 gcc_checking_assert (node2->summary_uid > 0); 187 188 if (v) 189 { 190 /* This load is necessary, because we insert a new value! */ 191 T *data = *v; 192 T *duplicate = summary->allocate_new (); 193 summary->m_map.put (node2->summary_uid, duplicate); 194 summary->duplicate (node, node2, data, duplicate); 195 } 196 } 197 198protected: 199 /* Indication if we use ggc summary. */ 200 bool m_ggc; 201 202private: 203 struct summary_hashmap_traits: default_hashmap_traits 204 { 205 static const int deleted_value = -1; 206 static const int empty_value = 0; 207 208 static hashval_t 209 hash (const int v) 210 { 211 return (hashval_t)v; 212 } 213 214 template<typename Type> 215 static bool 216 is_deleted (Type &e) 217 { 218 return e.m_key == deleted_value; 219 } 220 221 template<typename Type> 222 static bool 223 is_empty (Type &e) 224 { 225 return e.m_key == empty_value; 226 } 227 228 template<typename Type> 229 static void 230 mark_deleted (Type &e) 231 { 232 e.m_key = deleted_value; 233 } 234 235 template<typename Type> 236 static void 237 mark_empty (Type &e) 238 { 239 e.m_key = empty_value; 240 } 241 }; 242 243 /* Getter for summary callgraph ID. */ 244 T* get (int uid) 245 { 246 bool existed; 247 T **v = &m_map.get_or_insert (uid, &existed); 248 if (!existed) 249 *v = allocate_new (); 250 251 return *v; 252 } 253 254 /* Main summary store, where summary ID is used as key. */ 255 hash_map <int, T *, summary_hashmap_traits> m_map; 256 /* Internal summary insertion hook pointer. */ 257 cgraph_node_hook_list *m_symtab_insertion_hook; 258 /* Internal summary removal hook pointer. */ 259 cgraph_node_hook_list *m_symtab_removal_hook; 260 /* Internal summary duplication hook pointer. */ 261 cgraph_2node_hook_list *m_symtab_duplication_hook; 262 /* Indicates if insertion hook is enabled. */ 263 bool m_insertion_enabled; 264 /* Symbol table the summary is registered to. */ 265 symbol_table *m_symtab; 266 267 template <typename U> friend void gt_ggc_mx (function_summary <U *> * const &); 268 template <typename U> friend void gt_pch_nx (function_summary <U *> * const &); 269 template <typename U> friend void gt_pch_nx (function_summary <U *> * const &, 270 gt_pointer_operator, void *); 271}; 272 273template <typename T> 274void 275gt_ggc_mx(function_summary<T *>* const &summary) 276{ 277 gcc_checking_assert (summary->m_ggc); 278 gt_ggc_mx (&summary->m_map); 279} 280 281template <typename T> 282void 283gt_pch_nx(function_summary<T *>* const &summary) 284{ 285 gcc_checking_assert (summary->m_ggc); 286 gt_pch_nx (&summary->m_map); 287} 288 289template <typename T> 290void 291gt_pch_nx(function_summary<T *>* const& summary, gt_pointer_operator op, 292 void *cookie) 293{ 294 gcc_checking_assert (summary->m_ggc); 295 gt_pch_nx (&summary->m_map, op, cookie); 296} 297 298#endif /* GCC_SYMBOL_SUMMARY_H */ 299