oopMapCache.hpp 7.0 KB
Newer Older
D
duke 已提交
1
/*
2
 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
19 20 21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
D
duke 已提交
22 23 24
 *
 */

25 26 27 28
#ifndef SHARE_VM_INTERPRETER_OOPMAPCACHE_HPP
#define SHARE_VM_INTERPRETER_OOPMAPCACHE_HPP

#include "oops/generateOopMap.hpp"
29
#include "runtime/mutex.hpp"
30

D
duke 已提交
31 32 33 34
// A Cache for storing (method, bci) -> oopMap.
// The memory management system uses the cache when locating object
// references in an interpreted frame.
//
35
// OopMapCache's are allocated lazily per InstanceKlass.
D
duke 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

// The oopMap (InterpreterOopMap) is stored as a bit mask. If the
// bit_mask can fit into two words it is stored in
// the _bit_mask array, otherwise it is allocated on the heap.
// For OopMapCacheEntry the bit_mask is allocated in the C heap
// because these entries persist between garbage collections.
// For InterpreterOopMap the bit_mask is allocated in
// a resource area for better performance.  InterpreterOopMap
// should only be created and deleted during same garbage collection.
//
// If ENABBLE_ZAP_DEAD_LOCALS is defined, two bits are used
// per entry instead of one. In all cases,
// the first bit is set to indicate oops as opposed to other
// values. If the second bit is available,
// it is set for dead values. We get the following encoding:
//
// 00 live value
// 01 live oop
// 10 dead value
// 11 <unused>                                   (we cannot distinguish between dead oops or values with the current oop map generator)


class OffsetClosure  {
 public:
  virtual void offset_do(int offset) = 0;
};


class InterpreterOopMap: ResourceObj {
  friend class OopMapCache;

 public:
  enum {
69
    N                = 4,                // the number of words reserved
D
duke 已提交
70 71 72 73 74 75 76 77 78 79 80 81
                                         // for inlined mask storage
    small_mask_limit = N * BitsPerWord,  // the maximum number of bits
                                         // available for small masks,
                                         // small_mask_limit can be set to 0
                                         // for testing bit_mask allocation

    bits_per_entry   = 2,
    dead_bit_number  = 1,
    oop_bit_number   = 0
  };

 private:
82
  Method*        _method;         // the method for which the mask is valid
D
duke 已提交
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
  unsigned short _bci;            // the bci    for which the mask is valid
  int            _mask_size;      // the mask size in bits
  int            _expression_stack_size; // the size of the expression stack in slots

 protected:
  intptr_t       _bit_mask[N];    // the bit mask if
                                  // mask_size <= small_mask_limit,
                                  // ptr to bit mask otherwise
                                  // "protected" so that sub classes can
                                  // access it without using trickery in
                                  // methd bit_mask().
#ifdef ASSERT
  bool _resource_allocate_bit_mask;
#endif

  // access methods
99
  Method*        method() const                  { return _method; }
100
  void           set_method(Method* v)           { _method = v; }
D
duke 已提交
101 102 103 104 105 106
  int            bci() const                     { return _bci; }
  void           set_bci(int v)                  { _bci = v; }
  int            mask_size() const               { return _mask_size; }
  void           set_mask_size(int v)            { _mask_size = v; }
  // Test bit mask size and return either the in-line bit mask or allocated
  // bit mask.
107
  uintptr_t*  bit_mask() const                   { return (uintptr_t*)(mask_size() <= small_mask_limit ? (intptr_t)_bit_mask : _bit_mask[0]); }
D
duke 已提交
108 109

  // return the word size of_bit_mask.  mask_size() <= 4 * MAX_USHORT
110
  size_t mask_word_size() const {
D
duke 已提交
111 112 113
    return (mask_size() + BitsPerWord - 1) / BitsPerWord;
  }

114
  uintptr_t entry_at(int offset) const           { int i = offset * bits_per_entry; return bit_mask()[i / BitsPerWord] >> (i % BitsPerWord); }
D
duke 已提交
115

116
  void set_expression_stack_size(int sz)         { _expression_stack_size = sz; }
D
duke 已提交
117 118

  // Lookup
119 120
  bool match(methodHandle method, int bci) const { return _method == method() && _bci == bci; }
  bool is_empty() const;
D
duke 已提交
121 122 123 124 125 126 127 128 129 130 131 132 133 134

  // Initialization
  void initialize();

 public:
  InterpreterOopMap();
  ~InterpreterOopMap();

  // Copy the OopMapCacheEntry in parameter "from" into this
  // InterpreterOopMap.  If the _bit_mask[0] in "from" points to
  // allocated space (i.e., the bit mask was to large to hold
  // in-line), allocate the space from a Resource area.
  void resource_copy(OopMapCacheEntry* from);

135 136
  void iterate_oop(OffsetClosure* oop_closure) const;
  void print() const;
D
duke 已提交
137

138
  int number_of_entries() const                  { return mask_size() / bits_per_entry; }
139
  bool is_dead(int offset) const                 { return (entry_at(offset) & (1 << dead_bit_number)) != 0; }
140
  bool is_oop (int offset) const                 { return (entry_at(offset) & (1 << oop_bit_number )) != 0; }
D
duke 已提交
141

142
  int expression_stack_size() const              { return _expression_stack_size; }
D
duke 已提交
143 144 145 146 147 148

#ifdef ENABLE_ZAP_DEAD_LOCALS
  void iterate_all(OffsetClosure* oop_closure, OffsetClosure* value_closure, OffsetClosure* dead_closure);
#endif
};

Z
zgu 已提交
149
class OopMapCache : public CHeapObj<mtClass> {
D
duke 已提交
150 151 152 153 154 155 156
 private:
  enum { _size        = 32,     // Use fixed size for now
         _probe_depth = 3       // probe depth in case of collisions
  };

  OopMapCacheEntry* _array;

157
  unsigned int hash_value_for(methodHandle method, int bci) const;
D
duke 已提交
158 159
  OopMapCacheEntry* entry_at(int i) const;

160
  mutable Mutex _mut;
D
duke 已提交
161 162 163 164 165 166 167 168 169 170 171 172

  void flush();

 public:
  OopMapCache();
  ~OopMapCache();                                // free up memory

  // flush cache entry is occupied by an obsolete method
  void flush_obsolete_entries();

  // Returns the oopMap for (method, bci) in parameter "entry".
  // Returns false if an oop map was not found.
173
  void lookup(methodHandle method, int bci, InterpreterOopMap* entry) const;
D
duke 已提交
174 175 176 177 178 179 180

  // Compute an oop map without updating the cache or grabbing any locks (for debugging)
  static void compute_one_oop_map(methodHandle method, int bci, InterpreterOopMap* entry);

  // Returns total no. of bytes allocated as part of OopMapCache's
  static long memory_usage()                     PRODUCT_RETURN0;
};
181 182

#endif // SHARE_VM_INTERPRETER_OOPMAPCACHE_HPP