1 /*
   2  * Copyright (c) 1998, 2010, 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 // Recording and retrieval of oop relocations in compiled code.
  26 
  27 class CodeBlob;
  28 
  29 class OopRecorder : public ResourceObj {
  30  public:
  31   // A two-way mapping from positive indexes to oop handles.
  32   // The zero index is reserved for a constant (sharable) null.
  33   // Indexes may not be negative.
  34 
  35   // Use the given arena to manage storage, if not NULL.
  36   // By default, uses the current ResourceArea.
  37   OopRecorder(Arena* arena = NULL);
  38 
  39   // Generate a new index on which CodeBlob::oop_addr_at will work.
  40   // allocate_index and find_index never return the same index,
  41   // and allocate_index never returns the same index twice.
  42   // In fact, two successive calls to allocate_index return successive ints.
  43   int allocate_index(jobject h) {
  44     return add_handle(h, false);
  45   }
  46 
  47   // For a given jobject, this will return the same index repeatedly.
  48   // The index can later be given to oop_at to retrieve the oop.
  49   // However, the oop must not be changed via CodeBlob::oop_addr_at.
  50   int find_index(jobject h) {
  51     int index = maybe_find_index(h);
  52     if (index < 0) {  // previously unallocated
  53       index = add_handle(h, true);
  54     }
  55     return index;
  56   }
  57 
  58   // variant of find_index which does not allocate if not found (yields -1)
  59   int maybe_find_index(jobject h);
  60 
  61   // returns the size of the generated oop table, for sizing the CodeBlob.
  62   // must be called after all oops are allocated!
  63   int oop_size();
  64 
  65   // Retrieve the oop handle at a given index.
  66   jobject handle_at(int index);
  67 
  68   int element_count() {
  69     // there is always a NULL virtually present as first object
  70     return _handles->length() + first_index;
  71   }
  72 
  73   // copy the generated oop table to nmethod
  74   void copy_to(nmethod* nm);  // => nm->copy_oops(_handles)
  75 
  76   bool is_unused() { return _handles == NULL && !_complete; }
  77 #ifdef ASSERT
  78   bool is_complete() { return _complete; }
  79 #endif
  80 
  81  private:
  82   // leaky hash table of handle => index, to help detect duplicate insertion
  83   class IndexCache: public ResourceObj {
  84     // This class is only used by the OopRecorder class.
  85     friend class OopRecorder;
  86     enum {
  87       _log_cache_size = 9,
  88       _cache_size = (1<<_log_cache_size),
  89       // Index entries are ints.  The LSBit is a collision indicator.
  90       _collision_bit_shift = 0,
  91       _collision_bit = 1,
  92       _index_shift = _collision_bit_shift+1
  93     };
  94     int _cache[_cache_size];
  95     static juint cache_index(jobject handle) {
  96       juint ci = (int) (intptr_t) handle;
  97       ci ^= ci >> (BitsPerByte*2);
  98       ci += ci >> (BitsPerByte*1);
  99       return ci & (_cache_size-1);
 100     }
 101     int* cache_location(jobject handle) {
 102       return &_cache[ cache_index(handle) ];
 103     }
 104     static bool cache_location_collision(int* cloc) {
 105       return ((*cloc) & _collision_bit) != 0;
 106     }
 107     static int cache_location_index(int* cloc) {
 108       return (*cloc) >> _index_shift;
 109     }
 110     static void set_cache_location_index(int* cloc, int index) {
 111       int cval0 = (*cloc);
 112       int cval1 = (index << _index_shift);
 113       if (cval0 != 0 && cval1 != cval0)  cval1 += _collision_bit;
 114       (*cloc) = cval1;
 115     }
 116     IndexCache();
 117   };
 118 
 119   // Helper function; returns false for NULL or Universe::non_oop_word().
 120   inline bool is_real_jobject(jobject h);
 121 
 122   void maybe_initialize();
 123   int add_handle(jobject h, bool make_findable);
 124 
 125   enum { null_index = 0, first_index = 1, index_cache_threshold = 20 };
 126 
 127   GrowableArray<jobject>*   _handles;  // ordered list (first is always NULL)
 128   GrowableArray<int>*       _no_finds; // all unfindable indexes; usually empty
 129   IndexCache*               _indexes;  // map: jobject -> its probable index
 130   Arena*                    _arena;
 131   bool                      _complete;
 132 
 133 #ifdef ASSERT
 134   static int _find_index_calls, _hit_indexes, _missed_indexes;
 135 #endif
 136 };