1 /* Callgraph summary data structure. 2 Copyright (C) 2014-2019 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 /* Base class for function_summary and fast_function_summary classes. */ 25 26 template <class T> 27 class function_summary_base 28 { 29 public: 30 /* Default construction takes SYMTAB as an argument. */ 31 function_summary_base (symbol_table *symtab): m_symtab (symtab), 32 m_insertion_enabled (true), m_released (false) 33 {} 34 35 /* Basic implementation of insert operation. */ 36 virtual void insert (cgraph_node *, T *) {} 37 38 /* Basic implementation of removal operation. */ 39 virtual void remove (cgraph_node *, T *) {} 40 41 /* Basic implementation of duplication operation. */ 42 virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *) {} 43 44 /* Enable insertion hook invocation. */ 45 void enable_insertion_hook () 46 { 47 m_insertion_enabled = true; 48 } 49 50 /* Enable insertion hook invocation. */ 51 void disable_insertion_hook () 52 { 53 m_insertion_enabled = false; 54 } 55 56 protected: 57 /* Allocates new data that are stored within map. */ 58 T* allocate_new () 59 { 60 /* Call gcc_internal_because we do not want to call finalizer for 61 a type T. We call dtor explicitly. */ 62 return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ; 63 } 64 65 /* Release an item that is stored within map. */ 66 void release (T *item) 67 { 68 if (is_ggc ()) 69 { 70 item->~T (); 71 ggc_free (item); 72 } 73 else 74 delete item; 75 } 76 77 /* Unregister all call-graph hooks. */ 78 void unregister_hooks (); 79 80 /* Internal summary insertion hook pointer. */ 81 cgraph_node_hook_list *m_symtab_insertion_hook; 82 /* Internal summary removal hook pointer. */ 83 cgraph_node_hook_list *m_symtab_removal_hook; 84 /* Internal summary duplication hook pointer. */ 85 cgraph_2node_hook_list *m_symtab_duplication_hook; 86 /* Symbol table the summary is registered to. */ 87 symbol_table *m_symtab; 88 89 /* Indicates if insertion hook is enabled. */ 90 bool m_insertion_enabled; 91 /* Indicates if the summary is released. */ 92 bool m_released; 93 94 private: 95 /* Return true when the summary uses GGC memory for allocation. */ 96 virtual bool is_ggc () = 0; 97 }; 98 99 template <typename T> 100 void 101 function_summary_base<T>::unregister_hooks () 102 { 103 m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook); 104 m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook); 105 m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook); 106 } 107 108 /* We want to pass just pointer types as argument for function_summary 109 template class. */ 110 111 template <class T> 112 class function_summary 113 { 114 private: 115 function_summary(); 116 }; 117 118 /* Function summary is a helper class that is used to associate a data structure 119 related to a callgraph node. Typical usage can be seen in IPA passes which 120 create a temporary pass-related structures. The summary class registers 121 hooks that are triggered when a new node is inserted, duplicated and deleted. 122 A user of a summary class can ovewrite virtual methods than are triggered by 123 the summary if such hook is triggered. Apart from a callgraph node, the user 124 is given a data structure tied to the node. 125 126 The function summary class can work both with a heap-allocated memory and 127 a memory gained by garbage collected memory. */ 128 129 template <class T> 130 class GTY((user)) function_summary <T *>: public function_summary_base<T> 131 { 132 public: 133 /* Default construction takes SYMTAB as an argument. */ 134 function_summary (symbol_table *symtab, bool ggc = false); 135 136 /* Destructor. */ 137 virtual ~function_summary () 138 { 139 release (); 140 } 141 142 /* Destruction method that can be called for GGC purpose. */ 143 using function_summary_base<T>::release; 144 void release (); 145 146 /* Traverses all summarys with a function F called with 147 ARG as argument. */ 148 template<typename Arg, bool (*f)(const T &, Arg)> 149 void traverse (Arg a) const 150 { 151 m_map.traverse <f> (a); 152 } 153 154 /* Getter for summary callgraph node pointer. If a summary for a node 155 does not exist it will be created. */ 156 T* get_create (cgraph_node *node) 157 { 158 bool existed; 159 T **v = &m_map.get_or_insert (node->get_uid (), &existed); 160 if (!existed) 161 *v = this->allocate_new (); 162 163 return *v; 164 } 165 166 /* Getter for summary callgraph node pointer. */ 167 T* get (cgraph_node *node) ATTRIBUTE_PURE 168 { 169 T **v = m_map.get (node->get_uid ()); 170 return v == NULL ? NULL : *v; 171 } 172 173 /* Remove node from summary. */ 174 using function_summary_base<T>::remove; 175 void remove (cgraph_node *node) 176 { 177 int uid = node->get_uid (); 178 T **v = m_map.get (uid); 179 if (v) 180 { 181 m_map.remove (uid); 182 this->release (*v); 183 } 184 } 185 186 /* Return true if a summary for the given NODE already exists. */ 187 bool exists (cgraph_node *node) 188 { 189 return m_map.get (node->get_uid ()) != NULL; 190 } 191 192 /* Symbol insertion hook that is registered to symbol table. */ 193 static void symtab_insertion (cgraph_node *node, void *data); 194 195 /* Symbol removal hook that is registered to symbol table. */ 196 static void symtab_removal (cgraph_node *node, void *data); 197 198 /* Symbol duplication hook that is registered to symbol table. */ 199 static void symtab_duplication (cgraph_node *node, cgraph_node *node2, 200 void *data); 201 202 protected: 203 /* Indication if we use ggc summary. */ 204 bool m_ggc; 205 206 private: 207 /* Indication if we use ggc summary. */ 208 virtual bool is_ggc () 209 { 210 return m_ggc; 211 } 212 213 typedef int_hash <int, 0, -1> map_hash; 214 215 /* Main summary store, where summary ID is used as key. */ 216 hash_map <map_hash, T *> m_map; 217 218 template <typename U> friend void gt_ggc_mx (function_summary <U *> * const &); 219 template <typename U> friend void gt_pch_nx (function_summary <U *> * const &); 220 template <typename U> friend void gt_pch_nx (function_summary <U *> * const &, 221 gt_pointer_operator, void *); 222 }; 223 224 template <typename T> 225 function_summary<T *>::function_summary (symbol_table *symtab, bool ggc): 226 function_summary_base<T> (symtab), m_ggc (ggc), m_map (13, ggc) 227 { 228 this->m_symtab_insertion_hook 229 = this->m_symtab->add_cgraph_insertion_hook (function_summary::symtab_insertion, 230 this); 231 this->m_symtab_removal_hook 232 = this->m_symtab->add_cgraph_removal_hook (function_summary::symtab_removal, 233 this); 234 this->m_symtab_duplication_hook 235 = this->m_symtab->add_cgraph_duplication_hook (function_summary::symtab_duplication, 236 this); 237 } 238 239 template <typename T> 240 void 241 function_summary<T *>::release () 242 { 243 if (this->m_released) 244 return; 245 246 this->unregister_hooks (); 247 248 /* Release all summaries. */ 249 typedef typename hash_map <map_hash, T *>::iterator map_iterator; 250 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it) 251 this->release ((*it).second); 252 253 this->m_released = true; 254 } 255 256 template <typename T> 257 void 258 function_summary<T *>::symtab_insertion (cgraph_node *node, void *data) 259 { 260 gcc_checking_assert (node->get_uid ()); 261 function_summary *summary = (function_summary <T *> *) (data); 262 263 if (summary->m_insertion_enabled) 264 summary->insert (node, summary->get_create (node)); 265 } 266 267 template <typename T> 268 void 269 function_summary<T *>::symtab_removal (cgraph_node *node, void *data) 270 { 271 gcc_checking_assert (node->get_uid ()); 272 function_summary *summary = (function_summary <T *> *) (data); 273 summary->remove (node); 274 } 275 276 template <typename T> 277 void 278 function_summary<T *>::symtab_duplication (cgraph_node *node, 279 cgraph_node *node2, void *data) 280 { 281 function_summary *summary = (function_summary <T *> *) (data); 282 T *v = summary->get (node); 283 284 if (v) 285 summary->duplicate (node, node2, v, summary->get_create (node2)); 286 } 287 288 template <typename T> 289 void 290 gt_ggc_mx(function_summary<T *>* const &summary) 291 { 292 gcc_checking_assert (summary->m_ggc); 293 gt_ggc_mx (&summary->m_map); 294 } 295 296 template <typename T> 297 void 298 gt_pch_nx(function_summary<T *>* const &summary) 299 { 300 gcc_checking_assert (summary->m_ggc); 301 gt_pch_nx (&summary->m_map); 302 } 303 304 template <typename T> 305 void 306 gt_pch_nx(function_summary<T *>* const& summary, gt_pointer_operator op, 307 void *cookie) 308 { 309 gcc_checking_assert (summary->m_ggc); 310 gt_pch_nx (&summary->m_map, op, cookie); 311 } 312 313 /* Help template from std c++11. */ 314 315 template<typename T, typename U> 316 struct is_same 317 { 318 static const bool value = false; 319 }; 320 321 template<typename T> 322 struct is_same<T,T> //specialization 323 { 324 static const bool value = true; 325 }; 326 327 /* We want to pass just pointer types as argument for fast_function_summary 328 template class. */ 329 330 template <class T, class V> 331 class fast_function_summary 332 { 333 private: 334 fast_function_summary (); 335 }; 336 337 /* Function vector summary is a fast implementation of function_summary that 338 utilizes vector as primary storage of summaries. */ 339 340 template <class T, class V> 341 class GTY((user)) fast_function_summary <T *, V> 342 : public function_summary_base<T> 343 { 344 public: 345 /* Default construction takes SYMTAB as an argument. */ 346 fast_function_summary (symbol_table *symtab); 347 348 /* Destructor. */ 349 virtual ~fast_function_summary () 350 { 351 release (); 352 } 353 354 /* Destruction method that can be called for GGC purpose. */ 355 using function_summary_base<T>::release; 356 void release (); 357 358 /* Traverses all summarys with a function F called with 359 ARG as argument. */ 360 template<typename Arg, bool (*f)(const T &, Arg)> 361 void traverse (Arg a) const 362 { 363 for (unsigned i = 0; i < m_vector->length (); i++) 364 if ((*m_vector[i]) != NULL) 365 f ((*m_vector)[i]); 366 } 367 368 /* Getter for summary callgraph node pointer. If a summary for a node 369 does not exist it will be created. */ 370 T* get_create (cgraph_node *node) 371 { 372 int id = node->get_summary_id (); 373 if (id == -1) 374 id = this->m_symtab->assign_summary_id (node); 375 376 if ((unsigned int)id >= m_vector->length ()) 377 vec_safe_grow_cleared (m_vector, 378 this->m_symtab->cgraph_max_summary_id); 379 380 if ((*m_vector)[id] == NULL) 381 (*m_vector)[id] = this->allocate_new (); 382 383 return (*m_vector)[id]; 384 } 385 386 /* Getter for summary callgraph node pointer. */ 387 T* get (cgraph_node *node) ATTRIBUTE_PURE 388 { 389 return exists (node) ? (*m_vector)[node->get_summary_id ()] : NULL; 390 } 391 392 using function_summary_base<T>::remove; 393 void remove (cgraph_node *node) 394 { 395 if (exists (node)) 396 { 397 int id = node->get_summary_id (); 398 this->release ((*m_vector)[id]); 399 (*m_vector)[id] = NULL; 400 } 401 } 402 403 /* Return true if a summary for the given NODE already exists. */ 404 bool exists (cgraph_node *node) 405 { 406 int id = node->get_summary_id (); 407 return (id != -1 408 && (unsigned int)id < m_vector->length () 409 && (*m_vector)[id] != NULL); 410 } 411 412 /* Symbol insertion hook that is registered to symbol table. */ 413 static void symtab_insertion (cgraph_node *node, void *data); 414 415 /* Symbol removal hook that is registered to symbol table. */ 416 static void symtab_removal (cgraph_node *node, void *data); 417 418 /* Symbol duplication hook that is registered to symbol table. */ 419 static void symtab_duplication (cgraph_node *node, cgraph_node *node2, 420 void *data); 421 422 private: 423 virtual bool is_ggc (); 424 425 /* Summary is stored in the vector. */ 426 vec <T *, V> *m_vector; 427 428 template <typename U> friend void gt_ggc_mx (fast_function_summary <U *, va_gc> * const &); 429 template <typename U> friend void gt_pch_nx (fast_function_summary <U *, va_gc> * const &); 430 template <typename U> friend void gt_pch_nx (fast_function_summary <U *, va_gc> * const &, 431 gt_pointer_operator, void *); 432 }; 433 434 template <typename T, typename V> 435 fast_function_summary<T *, V>::fast_function_summary (symbol_table *symtab): 436 function_summary_base<T> (symtab), m_vector (NULL) 437 { 438 vec_alloc (m_vector, 13); 439 this->m_symtab_insertion_hook 440 = this->m_symtab->add_cgraph_insertion_hook (fast_function_summary::symtab_insertion, 441 this); 442 this->m_symtab_removal_hook 443 = this->m_symtab->add_cgraph_removal_hook (fast_function_summary::symtab_removal, 444 this); 445 this->m_symtab_duplication_hook 446 = this->m_symtab->add_cgraph_duplication_hook (fast_function_summary::symtab_duplication, 447 this); 448 } 449 450 template <typename T, typename V> 451 void 452 fast_function_summary<T *, V>::release () 453 { 454 if (this->m_released) 455 return; 456 457 this->unregister_hooks (); 458 459 /* Release all summaries. */ 460 for (unsigned i = 0; i < m_vector->length (); i++) 461 if ((*m_vector)[i] != NULL) 462 this->release ((*m_vector)[i]); 463 464 vec_free (m_vector); 465 466 this->m_released = true; 467 } 468 469 template <typename T, typename V> 470 void 471 fast_function_summary<T *, V>::symtab_insertion (cgraph_node *node, void *data) 472 { 473 gcc_checking_assert (node->get_uid ()); 474 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data); 475 476 if (summary->m_insertion_enabled) 477 summary->insert (node, summary->get_create (node)); 478 } 479 480 template <typename T, typename V> 481 void 482 fast_function_summary<T *, V>::symtab_removal (cgraph_node *node, void *data) 483 { 484 gcc_checking_assert (node->get_uid ()); 485 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data); 486 487 if (summary->exists (node)) 488 summary->remove (node); 489 } 490 491 template <typename T, typename V> 492 void 493 fast_function_summary<T *, V>::symtab_duplication (cgraph_node *node, 494 cgraph_node *node2, 495 void *data) 496 { 497 fast_function_summary *summary = (fast_function_summary <T *, V> *) (data); 498 T *v = summary->get (node); 499 500 if (v) 501 { 502 T *duplicate = summary->get_create (node2); 503 summary->duplicate (node, node2, v, duplicate); 504 } 505 } 506 507 template <typename T, typename V> 508 inline bool 509 fast_function_summary<T *, V>::is_ggc () 510 { 511 return is_same<V, va_gc>::value; 512 } 513 514 template <typename T> 515 void 516 gt_ggc_mx (fast_function_summary<T *, va_heap>* const &) 517 { 518 } 519 520 template <typename T> 521 void 522 gt_pch_nx (fast_function_summary<T *, va_heap>* const &) 523 { 524 } 525 526 template <typename T> 527 void 528 gt_pch_nx (fast_function_summary<T *, va_heap>* const&, gt_pointer_operator, 529 void *) 530 { 531 } 532 533 template <typename T> 534 void 535 gt_ggc_mx (fast_function_summary<T *, va_gc>* const &summary) 536 { 537 ggc_test_and_set_mark (summary->m_vector); 538 gt_ggc_mx (summary->m_vector); 539 } 540 541 template <typename T> 542 void 543 gt_pch_nx (fast_function_summary<T *, va_gc>* const &summary) 544 { 545 gt_pch_nx (summary->m_vector); 546 } 547 548 template <typename T> 549 void 550 gt_pch_nx (fast_function_summary<T *, va_gc>* const& summary, 551 gt_pointer_operator op, 552 void *cookie) 553 { 554 gt_pch_nx (summary->m_vector, op, cookie); 555 } 556 557 /* Base class for call_summary and fast_call_summary classes. */ 558 559 template <class T> 560 class call_summary_base 561 { 562 public: 563 /* Default construction takes SYMTAB as an argument. */ 564 call_summary_base (symbol_table *symtab): m_symtab (symtab), 565 m_initialize_when_cloning (true), m_released (false) 566 {} 567 568 /* Basic implementation of removal operation. */ 569 virtual void remove (cgraph_edge *, T *) {} 570 571 /* Basic implementation of duplication operation. */ 572 virtual void duplicate (cgraph_edge *, cgraph_edge *, T *, T *) {} 573 574 protected: 575 /* Allocates new data that are stored within map. */ 576 T* allocate_new () 577 { 578 /* Call gcc_internal_because we do not want to call finalizer for 579 a type T. We call dtor explicitly. */ 580 return is_ggc () ? new (ggc_internal_alloc (sizeof (T))) T () : new T () ; 581 } 582 583 /* Release an item that is stored within map. */ 584 void release (T *item) 585 { 586 if (is_ggc ()) 587 { 588 item->~T (); 589 ggc_free (item); 590 } 591 else 592 delete item; 593 } 594 595 /* Unregister all call-graph hooks. */ 596 void unregister_hooks (); 597 598 /* Symbol table the summary is registered to. */ 599 symbol_table *m_symtab; 600 601 /* Internal summary removal hook pointer. */ 602 cgraph_edge_hook_list *m_symtab_removal_hook; 603 /* Internal summary duplication hook pointer. */ 604 cgraph_2edge_hook_list *m_symtab_duplication_hook; 605 /* Initialize summary for an edge that is cloned. */ 606 bool m_initialize_when_cloning; 607 /* Indicates if the summary is released. */ 608 bool m_released; 609 610 private: 611 /* Return true when the summary uses GGC memory for allocation. */ 612 virtual bool is_ggc () = 0; 613 }; 614 615 template <typename T> 616 void 617 call_summary_base<T>::unregister_hooks () 618 { 619 m_symtab->remove_edge_removal_hook (m_symtab_removal_hook); 620 m_symtab->remove_edge_duplication_hook (m_symtab_duplication_hook); 621 } 622 623 /* An impossible class templated by non-pointers so, which makes sure that only 624 summaries gathering pointers can be created. */ 625 626 template <class T> 627 class call_summary 628 { 629 private: 630 call_summary (); 631 }; 632 633 /* Class to store auxiliary information about call graph edges. */ 634 635 template <class T> 636 class GTY((user)) call_summary <T *>: public call_summary_base<T> 637 { 638 public: 639 /* Default construction takes SYMTAB as an argument. */ 640 call_summary (symbol_table *symtab, bool ggc = false) 641 : call_summary_base<T> (symtab), m_ggc (ggc), m_map (13, ggc) 642 { 643 this->m_symtab_removal_hook 644 = this->m_symtab->add_edge_removal_hook (call_summary::symtab_removal, 645 this); 646 this->m_symtab_duplication_hook 647 = this->m_symtab->add_edge_duplication_hook (call_summary::symtab_duplication, 648 this); 649 } 650 651 /* Destructor. */ 652 virtual ~call_summary () 653 { 654 release (); 655 } 656 657 /* Destruction method that can be called for GGC purpose. */ 658 using call_summary_base<T>::release; 659 void release (); 660 661 /* Traverses all summarys with an edge E called with 662 ARG as argument. */ 663 template<typename Arg, bool (*f)(const T &, Arg)> 664 void traverse (Arg a) const 665 { 666 m_map.traverse <f> (a); 667 } 668 669 /* Getter for summary callgraph edge pointer. 670 If a summary for an edge does not exist, it will be created. */ 671 T* get_create (cgraph_edge *edge) 672 { 673 bool existed; 674 T **v = &m_map.get_or_insert (edge->get_uid (), &existed); 675 if (!existed) 676 *v = this->allocate_new (); 677 678 return *v; 679 } 680 681 /* Getter for summary callgraph edge pointer. */ 682 T* get (cgraph_edge *edge) ATTRIBUTE_PURE 683 { 684 T **v = m_map.get (edge->get_uid ()); 685 return v == NULL ? NULL : *v; 686 } 687 688 /* Remove edge from summary. */ 689 using call_summary_base<T>::remove; 690 void remove (cgraph_edge *edge) 691 { 692 int uid = edge->get_uid (); 693 T **v = m_map.get (uid); 694 if (v) 695 { 696 m_map.remove (uid); 697 this->release (*v); 698 } 699 } 700 701 /* Return true if a summary for the given EDGE already exists. */ 702 bool exists (cgraph_edge *edge) 703 { 704 return m_map.get (edge->get_uid ()) != NULL; 705 } 706 707 /* Symbol removal hook that is registered to symbol table. */ 708 static void symtab_removal (cgraph_edge *edge, void *data); 709 710 /* Symbol duplication hook that is registered to symbol table. */ 711 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2, 712 void *data); 713 714 protected: 715 /* Indication if we use ggc summary. */ 716 bool m_ggc; 717 718 private: 719 /* Indication if we use ggc summary. */ 720 virtual bool is_ggc () 721 { 722 return m_ggc; 723 } 724 725 typedef int_hash <int, 0, -1> map_hash; 726 727 /* Main summary store, where summary ID is used as key. */ 728 hash_map <map_hash, T *> m_map; 729 730 template <typename U> friend void gt_ggc_mx (call_summary <U *> * const &); 731 template <typename U> friend void gt_pch_nx (call_summary <U *> * const &); 732 template <typename U> friend void gt_pch_nx (call_summary <U *> * const &, 733 gt_pointer_operator, void *); 734 }; 735 736 template <typename T> 737 void 738 call_summary<T *>::release () 739 { 740 if (this->m_released) 741 return; 742 743 this->unregister_hooks (); 744 745 /* Release all summaries. */ 746 typedef typename hash_map <map_hash, T *>::iterator map_iterator; 747 for (map_iterator it = m_map.begin (); it != m_map.end (); ++it) 748 this->release ((*it).second); 749 750 this->m_released = true; 751 } 752 753 template <typename T> 754 void 755 call_summary<T *>::symtab_removal (cgraph_edge *edge, void *data) 756 { 757 call_summary *summary = (call_summary <T *> *) (data); 758 summary->remove (edge); 759 } 760 761 template <typename T> 762 void 763 call_summary<T *>::symtab_duplication (cgraph_edge *edge1, 764 cgraph_edge *edge2, void *data) 765 { 766 call_summary *summary = (call_summary <T *> *) (data); 767 T *edge1_summary = NULL; 768 769 if (summary->m_initialize_when_cloning) 770 edge1_summary = summary->get_create (edge1); 771 else 772 edge1_summary = summary->get (edge1); 773 774 if (edge1_summary) 775 summary->duplicate (edge1, edge2, edge1_summary, 776 summary->get_create (edge2)); 777 } 778 779 template <typename T> 780 void 781 gt_ggc_mx(call_summary<T *>* const &summary) 782 { 783 gcc_checking_assert (summary->m_ggc); 784 gt_ggc_mx (&summary->m_map); 785 } 786 787 template <typename T> 788 void 789 gt_pch_nx(call_summary<T *>* const &summary) 790 { 791 gcc_checking_assert (summary->m_ggc); 792 gt_pch_nx (&summary->m_map); 793 } 794 795 template <typename T> 796 void 797 gt_pch_nx(call_summary<T *>* const& summary, gt_pointer_operator op, 798 void *cookie) 799 { 800 gcc_checking_assert (summary->m_ggc); 801 gt_pch_nx (&summary->m_map, op, cookie); 802 } 803 804 /* We want to pass just pointer types as argument for fast_call_summary 805 template class. */ 806 807 template <class T, class V> 808 class fast_call_summary 809 { 810 private: 811 fast_call_summary (); 812 }; 813 814 /* Call vector summary is a fast implementation of call_summary that 815 utilizes vector as primary storage of summaries. */ 816 817 template <class T, class V> 818 class GTY((user)) fast_call_summary <T *, V>: public call_summary_base<T> 819 { 820 public: 821 /* Default construction takes SYMTAB as an argument. */ 822 fast_call_summary (symbol_table *symtab) 823 : call_summary_base<T> (symtab), m_vector (NULL) 824 { 825 vec_alloc (m_vector, 13); 826 this->m_symtab_removal_hook 827 = this->m_symtab->add_edge_removal_hook (fast_call_summary::symtab_removal, 828 this); 829 this->m_symtab_duplication_hook 830 = this->m_symtab->add_edge_duplication_hook (fast_call_summary::symtab_duplication, 831 this); 832 } 833 834 /* Destructor. */ 835 virtual ~fast_call_summary () 836 { 837 release (); 838 } 839 840 /* Destruction method that can be called for GGC purpose. */ 841 using call_summary_base<T>::release; 842 void release (); 843 844 /* Traverses all summarys with an edge F called with 845 ARG as argument. */ 846 template<typename Arg, bool (*f)(const T &, Arg)> 847 void traverse (Arg a) const 848 { 849 for (unsigned i = 0; i < m_vector->length (); i++) 850 if ((*m_vector[i]) != NULL) 851 f ((*m_vector)[i]); 852 } 853 854 /* Getter for summary callgraph edge pointer. 855 If a summary for an edge does not exist, it will be created. */ 856 T* get_create (cgraph_edge *edge) 857 { 858 int id = edge->get_summary_id (); 859 if (id == -1) 860 id = this->m_symtab->assign_summary_id (edge); 861 862 if ((unsigned)id >= m_vector->length ()) 863 vec_safe_grow_cleared (m_vector, this->m_symtab->edges_max_summary_id); 864 865 if ((*m_vector)[id] == NULL) 866 (*m_vector)[id] = this->allocate_new (); 867 868 return (*m_vector)[id]; 869 } 870 871 /* Getter for summary callgraph edge pointer. */ 872 T* get (cgraph_edge *edge) ATTRIBUTE_PURE 873 { 874 return exists (edge) ? (*m_vector)[edge->get_summary_id ()] : NULL; 875 } 876 877 /* Remove edge from summary. */ 878 using call_summary_base<T>::remove; 879 void remove (cgraph_edge *edge) 880 { 881 if (exists (edge)) 882 { 883 int id = edge->get_summary_id (); 884 this->release ((*m_vector)[id]); 885 (*m_vector)[id] = NULL; 886 } 887 } 888 889 /* Return true if a summary for the given EDGE already exists. */ 890 bool exists (cgraph_edge *edge) 891 { 892 int id = edge->get_summary_id (); 893 return (id != -1 894 && (unsigned)id < m_vector->length () 895 && (*m_vector)[id] != NULL); 896 } 897 898 /* Symbol removal hook that is registered to symbol table. */ 899 static void symtab_removal (cgraph_edge *edge, void *data); 900 901 /* Symbol duplication hook that is registered to symbol table. */ 902 static void symtab_duplication (cgraph_edge *edge1, cgraph_edge *edge2, 903 void *data); 904 905 private: 906 virtual bool is_ggc (); 907 908 /* Summary is stored in the vector. */ 909 vec <T *, V> *m_vector; 910 911 template <typename U> friend void gt_ggc_mx (fast_call_summary <U *, va_gc> * const &); 912 template <typename U> friend void gt_pch_nx (fast_call_summary <U *, va_gc> * const &); 913 template <typename U> friend void gt_pch_nx (fast_call_summary <U *, va_gc> * const &, 914 gt_pointer_operator, void *); 915 }; 916 917 template <typename T, typename V> 918 void 919 fast_call_summary<T *, V>::release () 920 { 921 if (this->m_released) 922 return; 923 924 this->unregister_hooks (); 925 926 /* Release all summaries. */ 927 for (unsigned i = 0; i < m_vector->length (); i++) 928 if ((*m_vector)[i] != NULL) 929 this->release ((*m_vector)[i]); 930 931 vec_free (m_vector); 932 933 this->m_released = true; 934 } 935 936 template <typename T, typename V> 937 void 938 fast_call_summary<T *, V>::symtab_removal (cgraph_edge *edge, void *data) 939 { 940 fast_call_summary *summary = (fast_call_summary <T *, V> *) (data); 941 summary->remove (edge); 942 } 943 944 template <typename T, typename V> 945 void 946 fast_call_summary<T *, V>::symtab_duplication (cgraph_edge *edge1, 947 cgraph_edge *edge2, void *data) 948 { 949 fast_call_summary *summary = (fast_call_summary <T *, V> *) (data); 950 T *edge1_summary = NULL; 951 952 if (summary->m_initialize_when_cloning) 953 edge1_summary = summary->get_create (edge1); 954 else 955 edge1_summary = summary->get (edge1); 956 957 if (edge1_summary) 958 { 959 T *duplicate = summary->get_create (edge2); 960 summary->duplicate (edge1, edge2, edge1_summary, duplicate); 961 } 962 } 963 964 template <typename T, typename V> 965 inline bool 966 fast_call_summary<T *, V>::is_ggc () 967 { 968 return is_same<V, va_gc>::value; 969 } 970 971 template <typename T> 972 void 973 gt_ggc_mx (fast_call_summary<T *, va_heap>* const &summary) 974 { 975 } 976 977 template <typename T> 978 void 979 gt_pch_nx (fast_call_summary<T *, va_heap>* const &summary) 980 { 981 } 982 983 template <typename T> 984 void 985 gt_pch_nx (fast_call_summary<T *, va_heap>* const& summary, 986 gt_pointer_operator op, 987 void *cookie) 988 { 989 } 990 991 template <typename T> 992 void 993 gt_ggc_mx (fast_call_summary<T *, va_gc>* const &summary) 994 { 995 ggc_test_and_set_mark (summary->m_vector); 996 gt_ggc_mx (&summary->m_vector); 997 } 998 999 template <typename T> 1000 void 1001 gt_pch_nx (fast_call_summary<T *, va_gc>* const &summary) 1002 { 1003 gt_pch_nx (&summary->m_vector); 1004 } 1005 1006 template <typename T> 1007 void 1008 gt_pch_nx (fast_call_summary<T *, va_gc>* const& summary, 1009 gt_pointer_operator op, 1010 void *cookie) 1011 { 1012 gt_pch_nx (&summary->m_vector, op, cookie); 1013 } 1014 1015 #endif /* GCC_SYMBOL_SUMMARY_H */ 1016