1 /*
   2  * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #ifndef SHARE_VM_C1_C1_VALUEMAP_HPP
  26 #define SHARE_VM_C1_C1_VALUEMAP_HPP
  27 
  28 #include "c1/c1_Instruction.hpp"
  29 #include "c1/c1_ValueSet.hpp"
  30 #include "memory/allocation.hpp"
  31 
  32 class ValueMapEntry: public CompilationResourceObj {
  33  private:
  34   intx           _hash;
  35   Value          _value;
  36   int            _nesting;
  37   ValueMapEntry* _next;
  38 
  39  public:
  40   ValueMapEntry(intx hash, Value value, int nesting, ValueMapEntry* next)
  41     : _hash(hash)
  42     , _value(value)
  43     , _nesting(nesting)
  44     , _next(next)
  45   {
  46   }
  47 
  48   intx           hash()      { return _hash; }
  49   Value          value()     { return _value; }
  50   int            nesting()   { return _nesting; }
  51   ValueMapEntry* next()      { return _next; }
  52 
  53   void set_next(ValueMapEntry* next) { _next = next; }
  54 };
  55 
  56 define_array(ValueMapEntryArray, ValueMapEntry*)
  57 define_stack(ValueMapEntryList, ValueMapEntryArray)
  58 
  59 // ValueMap implements nested hash tables for value numbering.  It
  60 // maintains a set _killed_values which represents the instructions
  61 // which have been killed so far and an array of linked lists of
  62 // ValueMapEntries names _entries.  Each ValueMapEntry has a nesting
  63 // which indicates what ValueMap nesting it belongs to.  Higher
  64 // nesting values are always before lower values in the linked list.
  65 // This allows cloning of parent ValueMaps by simply copying the heads
  66 // of the list.  _entry_count represents the number of reachable
  67 // entries in the ValueMap.  A ValueMap is only allowed to mutate
  68 // ValueMapEntries with the same nesting level.  Adding or removing
  69 // entries at the current nesting level requires updating
  70 // _entry_count.  Elements in the parent's list that get killed can be
  71 // skipped if they are at the head of the list by simply moving to the
  72 // next element in the list and decrementing _entry_count.
  73 
  74 class ValueMap: public CompilationResourceObj {
  75  private:
  76   int           _nesting;
  77   ValueMapEntryArray _entries;
  78   ValueSet      _killed_values;
  79   int           _entry_count;
  80 
  81   int           nesting()                        { return _nesting; }
  82   bool          is_local_value_numbering()       { return _nesting == 0; }
  83   bool          is_global_value_numbering()      { return _nesting > 0; }
  84 
  85   int           entry_count()                    { return _entry_count; }
  86   int           size()                           { return _entries.length(); }
  87   ValueMapEntry* entry_at(int i)                 { return _entries.at(i); }
  88 
  89   // calculates the index of a hash value in a hash table of size n
  90   int           entry_index(intx hash, int n)    { return (unsigned int)hash % n; }
  91 
  92   // if entry_count > size_threshold, the size of the hash table is increased
  93   int           size_threshold()                 { return size(); }
  94 
  95   // management of the killed-bitset for global value numbering
  96   void          kill_value(Value v)              { if (is_global_value_numbering()) _killed_values.put(v); }
  97   bool          is_killed(Value v)               { if (is_global_value_numbering()) return _killed_values.contains(v); else return false; }
  98 
  99   // helper functions
 100   void          increase_table_size();
 101 
 102 #ifndef PRODUCT
 103   static int _number_of_finds;
 104   static int _number_of_hits;
 105   static int _number_of_kills;
 106 #endif // PRODUCT
 107 
 108  public:
 109   // creation
 110   ValueMap();                // empty value map
 111   ValueMap(ValueMap* old);   // value map with increased nesting
 112 
 113   // manipulation
 114   Value find_insert(Value x);
 115 
 116   void kill_memory();
 117   void kill_field(ciField* field);
 118   void kill_array(ValueType* type);
 119   void kill_exception();
 120   void kill_map(ValueMap* map);
 121   void kill_all();
 122 
 123 #ifndef PRODUCT
 124   // debugging/printing
 125   void print();
 126 
 127   static void reset_statistics();
 128   static void print_statistics();
 129 #endif
 130 };
 131 
 132 define_array(ValueMapArray, ValueMap*)
 133 
 134 
 135 class ValueNumberingVisitor: public InstructionVisitor {
 136  protected:
 137   // called by visitor functions for instructions that kill values
 138   virtual void kill_memory() = 0;
 139   virtual void kill_field(ciField* field) = 0;
 140   virtual void kill_array(ValueType* type) = 0;
 141 
 142   // visitor functions
 143   void do_StoreField     (StoreField*      x) {
 144     if (x->is_init_point()) {
 145       // putstatic is an initialization point so treat it as a wide kill
 146       kill_memory();
 147     } else {
 148       kill_field(x->field());
 149     }
 150   }
 151   void do_StoreIndexed   (StoreIndexed*    x) { kill_array(x->type()); }
 152   void do_MonitorEnter   (MonitorEnter*    x) { kill_memory(); }
 153   void do_MonitorExit    (MonitorExit*     x) { kill_memory(); }
 154   void do_Invoke         (Invoke*          x) { kill_memory(); }
 155   void do_UnsafePutRaw   (UnsafePutRaw*    x) { kill_memory(); }
 156   void do_UnsafePutObject(UnsafePutObject* x) { kill_memory(); }
 157   void do_Intrinsic      (Intrinsic*       x) { if (!x->preserves_state()) kill_memory(); }
 158 
 159   void do_Phi            (Phi*             x) { /* nothing to do */ }
 160   void do_Local          (Local*           x) { /* nothing to do */ }
 161   void do_Constant       (Constant*        x) { /* nothing to do */ }
 162   void do_LoadField      (LoadField*       x) {
 163     if (x->is_init_point()) {
 164       // getstatic is an initialization point so treat it as a wide kill
 165       kill_memory();
 166     }
 167   }
 168   void do_ArrayLength    (ArrayLength*     x) { /* nothing to do */ }
 169   void do_LoadIndexed    (LoadIndexed*     x) { /* nothing to do */ }
 170   void do_NegateOp       (NegateOp*        x) { /* nothing to do */ }
 171   void do_ArithmeticOp   (ArithmeticOp*    x) { /* nothing to do */ }
 172   void do_ShiftOp        (ShiftOp*         x) { /* nothing to do */ }
 173   void do_LogicOp        (LogicOp*         x) { /* nothing to do */ }
 174   void do_CompareOp      (CompareOp*       x) { /* nothing to do */ }
 175   void do_IfOp           (IfOp*            x) { /* nothing to do */ }
 176   void do_Convert        (Convert*         x) { /* nothing to do */ }
 177   void do_NullCheck      (NullCheck*       x) { /* nothing to do */ }
 178   void do_NewInstance    (NewInstance*     x) { /* nothing to do */ }
 179   void do_NewTypeArray   (NewTypeArray*    x) { /* nothing to do */ }
 180   void do_NewObjectArray (NewObjectArray*  x) { /* nothing to do */ }
 181   void do_NewMultiArray  (NewMultiArray*   x) { /* nothing to do */ }
 182   void do_CheckCast      (CheckCast*       x) { /* nothing to do */ }
 183   void do_InstanceOf     (InstanceOf*      x) { /* nothing to do */ }
 184   void do_BlockBegin     (BlockBegin*      x) { /* nothing to do */ }
 185   void do_Goto           (Goto*            x) { /* nothing to do */ }
 186   void do_If             (If*              x) { /* nothing to do */ }
 187   void do_IfInstanceOf   (IfInstanceOf*    x) { /* nothing to do */ }
 188   void do_TableSwitch    (TableSwitch*     x) { /* nothing to do */ }
 189   void do_LookupSwitch   (LookupSwitch*    x) { /* nothing to do */ }
 190   void do_Return         (Return*          x) { /* nothing to do */ }
 191   void do_Throw          (Throw*           x) { /* nothing to do */ }
 192   void do_Base           (Base*            x) { /* nothing to do */ }
 193   void do_OsrEntry       (OsrEntry*        x) { /* nothing to do */ }
 194   void do_ExceptionObject(ExceptionObject* x) { /* nothing to do */ }
 195   void do_RoundFP        (RoundFP*         x) { /* nothing to do */ }
 196   void do_UnsafeGetRaw   (UnsafeGetRaw*    x) { /* nothing to do */ }
 197   void do_UnsafeGetObject(UnsafeGetObject* x) { /* nothing to do */ }
 198   void do_UnsafePrefetchRead (UnsafePrefetchRead*  x) { /* nothing to do */ }
 199   void do_UnsafePrefetchWrite(UnsafePrefetchWrite* x) { /* nothing to do */ }
 200   void do_ProfileCall    (ProfileCall*     x) { /* nothing to do */ }
 201   void do_ProfileInvoke  (ProfileInvoke*   x) { /* nothing to do */ };
 202   void do_RuntimeCall    (RuntimeCall*     x) { /* nothing to do */ };
 203 };
 204 
 205 
 206 class ValueNumberingEffects: public ValueNumberingVisitor {
 207  private:
 208   ValueMap*     _map;
 209 
 210  public:
 211   // implementation for abstract methods of ValueNumberingVisitor
 212   void          kill_memory()                    { _map->kill_memory(); }
 213   void          kill_field(ciField* field)       { _map->kill_field(field); }
 214   void          kill_array(ValueType* type)      { _map->kill_array(type); }
 215 
 216   ValueNumberingEffects(ValueMap* map): _map(map) {}
 217 };
 218 
 219 
 220 class GlobalValueNumbering: public ValueNumberingVisitor {
 221  private:
 222   ValueMap*     _current_map;     // value map of current block
 223   ValueMapArray _value_maps;      // list of value maps for all blocks
 224 
 225  public:
 226   // accessors
 227   ValueMap*     current_map()                    { return _current_map; }
 228   ValueMap*     value_map_of(BlockBegin* block)  { return _value_maps.at(block->linear_scan_number()); }
 229   void          set_value_map_of(BlockBegin* block, ValueMap* map)   { assert(value_map_of(block) == NULL, ""); _value_maps.at_put(block->linear_scan_number(), map); }
 230 
 231   // implementation for abstract methods of ValueNumberingVisitor
 232   void          kill_memory()                    { current_map()->kill_memory(); }
 233   void          kill_field(ciField* field)       { current_map()->kill_field(field); }
 234   void          kill_array(ValueType* type)      { current_map()->kill_array(type); }
 235 
 236   // main entry point that performs global value numbering
 237   GlobalValueNumbering(IR* ir);
 238 };
 239 
 240 #endif // SHARE_VM_C1_C1_VALUEMAP_HPP