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