]>
Commit | Line | Data |
---|---|---|
4008290f | 1 | /* Callgraph summary data structure. |
5624e564 | 2 | Copyright (C) 2014-2015 Free Software Foundation, Inc. |
4008290f ML |
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_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; | |
fdbdc4b5 ML |
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); | |
4008290f ML |
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 | ||
fdbdc4b5 ML |
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 | ||
4008290f ML |
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 | ||
198 | protected: | |
199 | /* Indication if we use ggc summary. */ | |
200 | bool m_ggc; | |
201 | ||
202 | private: | |
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 | ||
273 | template <typename T> | |
274 | void | |
275 | gt_ggc_mx(function_summary<T *>* const &summary) | |
276 | { | |
277 | gcc_checking_assert (summary->m_ggc); | |
278 | gt_ggc_mx (&summary->m_map); | |
279 | } | |
280 | ||
281 | template <typename T> | |
282 | void | |
283 | gt_pch_nx(function_summary<T *>* const &summary) | |
284 | { | |
285 | gcc_checking_assert (summary->m_ggc); | |
286 | gt_pch_nx (&summary->m_map); | |
287 | } | |
288 | ||
289 | template <typename T> | |
290 | void | |
291 | gt_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 */ |