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