Home | History | Annotate | Line # | Download | only in gcc
symbol-summary.h revision 1.1.1.1.2.1
      1 /* Callgraph summary data structure.
      2    Copyright (C) 2014-2016 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_map (13, ggc), m_insertion_enabled (true), m_symtab (symtab)
     41   {
     42     if (flag_checking)
     43       {
     44 	cgraph_node *node;
     45 	FOR_EACH_FUNCTION (node)
     46 	  gcc_assert (node->summary_uid > 0);
     47       }
     48 
     49     m_symtab_insertion_hook =
     50       symtab->add_cgraph_insertion_hook
     51       (function_summary::symtab_insertion, this);
     52 
     53     m_symtab_removal_hook =
     54       symtab->add_cgraph_removal_hook
     55       (function_summary::symtab_removal, this);
     56     m_symtab_duplication_hook =
     57       symtab->add_cgraph_duplication_hook
     58       (function_summary::symtab_duplication, this);
     59   }
     60 
     61   /* Destructor.  */
     62   virtual ~function_summary ()
     63   {
     64     release ();
     65   }
     66 
     67   /* Destruction method that can be called for GGT purpose.  */
     68   void release ()
     69   {
     70     if (m_symtab_insertion_hook)
     71       m_symtab->remove_cgraph_insertion_hook (m_symtab_insertion_hook);
     72 
     73     if (m_symtab_removal_hook)
     74       m_symtab->remove_cgraph_removal_hook (m_symtab_removal_hook);
     75 
     76     if (m_symtab_duplication_hook)
     77       m_symtab->remove_cgraph_duplication_hook (m_symtab_duplication_hook);
     78 
     79     m_symtab_insertion_hook = NULL;
     80     m_symtab_removal_hook = NULL;
     81     m_symtab_duplication_hook = NULL;
     82 
     83     /* Release all summaries.  */
     84     typedef typename hash_map <map_hash, T *>::iterator map_iterator;
     85     for (map_iterator it = m_map.begin (); it != m_map.end (); ++it)
     86       release ((*it).second);
     87   }
     88 
     89   /* Traverses all summarys with a function F called with
     90      ARG as argument.  */
     91   template<typename Arg, bool (*f)(const T &, Arg)>
     92   void traverse (Arg a) const
     93   {
     94     m_map.traverse <f> (a);
     95   }
     96 
     97   /* Basic implementation of insert operation.  */
     98   virtual void insert (cgraph_node *, T *) {}
     99 
    100   /* Basic implementation of removal operation.  */
    101   virtual void remove (cgraph_node *, T *) {}
    102 
    103   /* Basic implementation of duplication operation.  */
    104   virtual void duplicate (cgraph_node *, cgraph_node *, T *, T *) {}
    105 
    106   /* Allocates new data that are stored within map.  */
    107   T* allocate_new ()
    108   {
    109     return m_ggc ? new (ggc_alloc <T> ()) T() : new T () ;
    110   }
    111 
    112   /* Release an item that is stored within map.  */
    113   void release (T *item)
    114   {
    115     if (m_ggc)
    116       {
    117 	item->~T ();
    118 	ggc_free (item);
    119       }
    120     else
    121       delete item;
    122   }
    123 
    124   /* Getter for summary callgraph node pointer.  */
    125   T* get (cgraph_node *node)
    126   {
    127     return get (node->summary_uid);
    128   }
    129 
    130   /* Return number of elements handled by data structure.  */
    131   size_t elements ()
    132   {
    133     return m_map.elements ();
    134   }
    135 
    136   /* Enable insertion hook invocation.  */
    137   void enable_insertion_hook ()
    138   {
    139     m_insertion_enabled = true;
    140   }
    141 
    142   /* Enable insertion hook invocation.  */
    143   void disable_insertion_hook ()
    144   {
    145     m_insertion_enabled = false;
    146   }
    147 
    148   /* Symbol insertion hook that is registered to symbol table.  */
    149   static void symtab_insertion (cgraph_node *node, void *data)
    150   {
    151     function_summary *summary = (function_summary <T *> *) (data);
    152 
    153     if (summary->m_insertion_enabled)
    154       summary->insert (node, summary->get (node));
    155   }
    156 
    157   /* Symbol removal hook that is registered to symbol table.  */
    158   static void symtab_removal (cgraph_node *node, void *data)
    159   {
    160     gcc_checking_assert (node->summary_uid);
    161     function_summary *summary = (function_summary <T *> *) (data);
    162 
    163     int summary_uid = node->summary_uid;
    164     T **v = summary->m_map.get (summary_uid);
    165 
    166     if (v)
    167       {
    168 	summary->remove (node, *v);
    169 
    170 	if (!summary->m_ggc)
    171 	  delete (*v);
    172 
    173 	summary->m_map.remove (summary_uid);
    174       }
    175   }
    176 
    177   /* Symbol duplication hook that is registered to symbol table.  */
    178   static void symtab_duplication (cgraph_node *node, cgraph_node *node2,
    179 				  void *data)
    180   {
    181     function_summary *summary = (function_summary <T *> *) (data);
    182     T **v = summary->m_map.get (node->summary_uid);
    183 
    184     gcc_checking_assert (node2->summary_uid > 0);
    185 
    186     if (v)
    187       {
    188 	/* This load is necessary, because we insert a new value!  */
    189 	T *data = *v;
    190 	T *duplicate = summary->allocate_new ();
    191 	summary->m_map.put (node2->summary_uid, duplicate);
    192 	summary->duplicate (node, node2, data, duplicate);
    193       }
    194   }
    195 
    196 protected:
    197   /* Indication if we use ggc summary.  */
    198   bool m_ggc;
    199 
    200 private:
    201   typedef int_hash <int, 0, -1> map_hash;
    202 
    203   /* Getter for summary callgraph ID.  */
    204   T* get (int uid)
    205   {
    206     bool existed;
    207     T **v = &m_map.get_or_insert (uid, &existed);
    208     if (!existed)
    209       *v = allocate_new ();
    210 
    211     return *v;
    212   }
    213 
    214   /* Main summary store, where summary ID is used as key.  */
    215   hash_map <map_hash, T *> m_map;
    216   /* Internal summary insertion hook pointer.  */
    217   cgraph_node_hook_list *m_symtab_insertion_hook;
    218   /* Internal summary removal hook pointer.  */
    219   cgraph_node_hook_list *m_symtab_removal_hook;
    220   /* Internal summary duplication hook pointer.  */
    221   cgraph_2node_hook_list *m_symtab_duplication_hook;
    222   /* Indicates if insertion hook is enabled.  */
    223   bool m_insertion_enabled;
    224   /* Symbol table the summary is registered to.  */
    225   symbol_table *m_symtab;
    226 
    227   template <typename U> friend void gt_ggc_mx (function_summary <U *> * const &);
    228   template <typename U> friend void gt_pch_nx (function_summary <U *> * const &);
    229   template <typename U> friend void gt_pch_nx (function_summary <U *> * const &,
    230       gt_pointer_operator, void *);
    231 };
    232 
    233 template <typename T>
    234 void
    235 gt_ggc_mx(function_summary<T *>* const &summary)
    236 {
    237   gcc_checking_assert (summary->m_ggc);
    238   gt_ggc_mx (&summary->m_map);
    239 }
    240 
    241 template <typename T>
    242 void
    243 gt_pch_nx(function_summary<T *>* const &summary)
    244 {
    245   gcc_checking_assert (summary->m_ggc);
    246   gt_pch_nx (&summary->m_map);
    247 }
    248 
    249 template <typename T>
    250 void
    251 gt_pch_nx(function_summary<T *>* const& summary, gt_pointer_operator op,
    252 	  void *cookie)
    253 {
    254   gcc_checking_assert (summary->m_ggc);
    255   gt_pch_nx (&summary->m_map, op, cookie);
    256 }
    257 
    258 #endif  /* GCC_SYMBOL_SUMMARY_H  */
    259