hotspot/src/share/vm/prims/jvmtiTagMap.cpp
author ysr
Thu, 03 Dec 2009 15:01:57 -0800
changeset 4461 c17c526d36ef
parent 3908 24b55ad4c228
child 4571 80b553bddc26
permissions -rw-r--r--
6906727: UseCompressedOops: some card-marking fixes related to object arrays Summary: Introduced a new write_ref_array(HeapWords* start, size_t count) method that does the requisite MemRegion range calculation so (some of the) clients of the erstwhile write_ref_array(MemRegion mr) do not need to worry. This removed all external uses of array_size(), which was also simplified and made private. Asserts were added to catch other possible issues. Further, less essential, fixes stemming from this investigation are deferred to CR 6904516 (to follow shortly in hs17). Reviewed-by: kvn, coleenp, jmasa
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     1
/*
2105
347008ce7984 6814575: Update copyright year
xdono
parents: 1893
diff changeset
     2
 * Copyright 2003-2009 Sun Microsystems, Inc.  All Rights Reserved.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     4
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
489c9b5090e2 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
489c9b5090e2 Initial load
duke
parents:
diff changeset
     7
 * published by the Free Software Foundation.
489c9b5090e2 Initial load
duke
parents:
diff changeset
     8
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
489c9b5090e2 Initial load
duke
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
489c9b5090e2 Initial load
duke
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
489c9b5090e2 Initial load
duke
parents:
diff changeset
    13
 * accompanied this code).
489c9b5090e2 Initial load
duke
parents:
diff changeset
    14
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
489c9b5090e2 Initial load
duke
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    18
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    19
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    20
 * CA 95054 USA or visit www.sun.com if you need additional information or
489c9b5090e2 Initial load
duke
parents:
diff changeset
    21
 * have any questions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    22
 *
489c9b5090e2 Initial load
duke
parents:
diff changeset
    23
 */
489c9b5090e2 Initial load
duke
parents:
diff changeset
    24
489c9b5090e2 Initial load
duke
parents:
diff changeset
    25
# include "incls/_precompiled.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    26
# include "incls/_jvmtiTagMap.cpp.incl"
489c9b5090e2 Initial load
duke
parents:
diff changeset
    27
489c9b5090e2 Initial load
duke
parents:
diff changeset
    28
// JvmtiTagHashmapEntry
489c9b5090e2 Initial load
duke
parents:
diff changeset
    29
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    30
// Each entry encapsulates a JNI weak reference to the tagged object
489c9b5090e2 Initial load
duke
parents:
diff changeset
    31
// and the tag value. In addition an entry includes a next pointer which
489c9b5090e2 Initial load
duke
parents:
diff changeset
    32
// is used to chain entries together.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    33
489c9b5090e2 Initial load
duke
parents:
diff changeset
    34
class JvmtiTagHashmapEntry : public CHeapObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    35
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    36
  friend class JvmtiTagMap;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    37
489c9b5090e2 Initial load
duke
parents:
diff changeset
    38
  jweak _object;                        // JNI weak ref to tagged object
489c9b5090e2 Initial load
duke
parents:
diff changeset
    39
  jlong _tag;                           // the tag
489c9b5090e2 Initial load
duke
parents:
diff changeset
    40
  JvmtiTagHashmapEntry* _next;          // next on the list
489c9b5090e2 Initial load
duke
parents:
diff changeset
    41
489c9b5090e2 Initial load
duke
parents:
diff changeset
    42
  inline void init(jweak object, jlong tag) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    43
    _object = object;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    44
    _tag = tag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    45
    _next = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    46
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    47
489c9b5090e2 Initial load
duke
parents:
diff changeset
    48
  // constructor
489c9b5090e2 Initial load
duke
parents:
diff changeset
    49
  JvmtiTagHashmapEntry(jweak object, jlong tag)         { init(object, tag); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    50
489c9b5090e2 Initial load
duke
parents:
diff changeset
    51
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    52
489c9b5090e2 Initial load
duke
parents:
diff changeset
    53
  // accessor methods
489c9b5090e2 Initial load
duke
parents:
diff changeset
    54
  inline jweak object() const                           { return _object; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    55
  inline jlong tag() const                              { return _tag; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    56
489c9b5090e2 Initial load
duke
parents:
diff changeset
    57
  inline void set_tag(jlong tag) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    58
    assert(tag != 0, "can't be zero");
489c9b5090e2 Initial load
duke
parents:
diff changeset
    59
    _tag = tag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    60
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    61
489c9b5090e2 Initial load
duke
parents:
diff changeset
    62
  inline JvmtiTagHashmapEntry* next() const             { return _next; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    63
  inline void set_next(JvmtiTagHashmapEntry* next)      { _next = next; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
    64
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
    65
489c9b5090e2 Initial load
duke
parents:
diff changeset
    66
489c9b5090e2 Initial load
duke
parents:
diff changeset
    67
// JvmtiTagHashmap
489c9b5090e2 Initial load
duke
parents:
diff changeset
    68
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    69
// A hashmap is essentially a table of pointers to entries. Entries
489c9b5090e2 Initial load
duke
parents:
diff changeset
    70
// are hashed to a location, or position in the table, and then
489c9b5090e2 Initial load
duke
parents:
diff changeset
    71
// chained from that location. The "key" for hashing is address of
489c9b5090e2 Initial load
duke
parents:
diff changeset
    72
// the object, or oop. The "value" is the JNI weak reference to the
489c9b5090e2 Initial load
duke
parents:
diff changeset
    73
// object and the tag value. Keys are not stored with the entry.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    74
// Instead the weak reference is resolved to obtain the key.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    75
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    76
// A hashmap maintains a count of the number entries in the hashmap
489c9b5090e2 Initial load
duke
parents:
diff changeset
    77
// and resizes if the number of entries exceeds a given threshold.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    78
// The threshold is specified as a percentage of the size - for
489c9b5090e2 Initial load
duke
parents:
diff changeset
    79
// example a threshold of 0.75 will trigger the hashmap to resize
489c9b5090e2 Initial load
duke
parents:
diff changeset
    80
// if the number of entries is >75% of table size.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    81
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
    82
// A hashmap provides functions for adding, removing, and finding
489c9b5090e2 Initial load
duke
parents:
diff changeset
    83
// entries. It also provides a function to iterate over all entries
489c9b5090e2 Initial load
duke
parents:
diff changeset
    84
// in the hashmap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
    85
489c9b5090e2 Initial load
duke
parents:
diff changeset
    86
class JvmtiTagHashmap : public CHeapObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    87
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
    88
  friend class JvmtiTagMap;
489c9b5090e2 Initial load
duke
parents:
diff changeset
    89
489c9b5090e2 Initial load
duke
parents:
diff changeset
    90
  enum {
489c9b5090e2 Initial load
duke
parents:
diff changeset
    91
    small_trace_threshold  = 10000,                  // threshold for tracing
489c9b5090e2 Initial load
duke
parents:
diff changeset
    92
    medium_trace_threshold = 100000,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    93
    large_trace_threshold  = 1000000,
489c9b5090e2 Initial load
duke
parents:
diff changeset
    94
    initial_trace_threshold = small_trace_threshold
489c9b5090e2 Initial load
duke
parents:
diff changeset
    95
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
    96
489c9b5090e2 Initial load
duke
parents:
diff changeset
    97
  static int _sizes[];                  // array of possible hashmap sizes
489c9b5090e2 Initial load
duke
parents:
diff changeset
    98
  int _size;                            // actual size of the table
489c9b5090e2 Initial load
duke
parents:
diff changeset
    99
  int _size_index;                      // index into size table
489c9b5090e2 Initial load
duke
parents:
diff changeset
   100
489c9b5090e2 Initial load
duke
parents:
diff changeset
   101
  int _entry_count;                     // number of entries in the hashmap
489c9b5090e2 Initial load
duke
parents:
diff changeset
   102
489c9b5090e2 Initial load
duke
parents:
diff changeset
   103
  float _load_factor;                   // load factor as a % of the size
489c9b5090e2 Initial load
duke
parents:
diff changeset
   104
  int _resize_threshold;                // computed threshold to trigger resizing.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   105
  bool _resizing_enabled;               // indicates if hashmap can resize
489c9b5090e2 Initial load
duke
parents:
diff changeset
   106
489c9b5090e2 Initial load
duke
parents:
diff changeset
   107
  int _trace_threshold;                 // threshold for trace messages
489c9b5090e2 Initial load
duke
parents:
diff changeset
   108
489c9b5090e2 Initial load
duke
parents:
diff changeset
   109
  JvmtiTagHashmapEntry** _table;        // the table of entries.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   110
489c9b5090e2 Initial load
duke
parents:
diff changeset
   111
  // private accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
   112
  int resize_threshold() const                  { return _resize_threshold; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   113
  int trace_threshold() const                   { return _trace_threshold; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   114
489c9b5090e2 Initial load
duke
parents:
diff changeset
   115
  // initialize the hashmap
489c9b5090e2 Initial load
duke
parents:
diff changeset
   116
  void init(int size_index=0, float load_factor=4.0f) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   117
    int initial_size =  _sizes[size_index];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   118
    _size_index = size_index;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   119
    _size = initial_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   120
    _entry_count = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   121
    if (TraceJVMTIObjectTagging) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   122
      _trace_threshold = initial_trace_threshold;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   123
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   124
      _trace_threshold = -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   125
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   126
    _load_factor = load_factor;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   127
    _resize_threshold = (int)(_load_factor * _size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   128
    _resizing_enabled = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   129
    size_t s = initial_size * sizeof(JvmtiTagHashmapEntry*);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   130
    _table = (JvmtiTagHashmapEntry**)os::malloc(s);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   131
    if (_table == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   132
      vm_exit_out_of_memory(s, "unable to allocate initial hashtable for jvmti object tags");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   133
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   134
    for (int i=0; i<initial_size; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   135
      _table[i] = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   136
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   137
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   138
489c9b5090e2 Initial load
duke
parents:
diff changeset
   139
  // hash a given key (oop) with the specified size
489c9b5090e2 Initial load
duke
parents:
diff changeset
   140
  static unsigned int hash(oop key, int size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   141
    // shift right to get better distribution (as these bits will be zero
489c9b5090e2 Initial load
duke
parents:
diff changeset
   142
    // with aligned addresses)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   143
    unsigned int addr = (unsigned int)((intptr_t)key);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   144
#ifdef _LP64
489c9b5090e2 Initial load
duke
parents:
diff changeset
   145
    return (addr >> 3) % size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   146
#else
489c9b5090e2 Initial load
duke
parents:
diff changeset
   147
    return (addr >> 2) % size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   148
#endif
489c9b5090e2 Initial load
duke
parents:
diff changeset
   149
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   150
489c9b5090e2 Initial load
duke
parents:
diff changeset
   151
  // hash a given key (oop)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   152
  unsigned int hash(oop key) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   153
    return hash(key, _size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   154
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   155
489c9b5090e2 Initial load
duke
parents:
diff changeset
   156
  // resize the hashmap - allocates a large table and re-hashes
489c9b5090e2 Initial load
duke
parents:
diff changeset
   157
  // all entries into the new table.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   158
  void resize() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   159
    int new_size_index = _size_index+1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   160
    int new_size = _sizes[new_size_index];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   161
    if (new_size < 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   162
      // hashmap already at maximum capacity
489c9b5090e2 Initial load
duke
parents:
diff changeset
   163
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   164
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   165
489c9b5090e2 Initial load
duke
parents:
diff changeset
   166
    // allocate new table
489c9b5090e2 Initial load
duke
parents:
diff changeset
   167
    size_t s = new_size * sizeof(JvmtiTagHashmapEntry*);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   168
    JvmtiTagHashmapEntry** new_table = (JvmtiTagHashmapEntry**)os::malloc(s);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   169
    if (new_table == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   170
      warning("unable to allocate larger hashtable for jvmti object tags");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   171
      set_resizing_enabled(false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   172
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   173
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   174
489c9b5090e2 Initial load
duke
parents:
diff changeset
   175
    // initialize new table
489c9b5090e2 Initial load
duke
parents:
diff changeset
   176
    int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   177
    for (i=0; i<new_size; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   178
      new_table[i] = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   179
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   180
489c9b5090e2 Initial load
duke
parents:
diff changeset
   181
    // rehash all entries into the new table
489c9b5090e2 Initial load
duke
parents:
diff changeset
   182
    for (i=0; i<_size; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   183
      JvmtiTagHashmapEntry* entry = _table[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   184
      while (entry != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   185
        JvmtiTagHashmapEntry* next = entry->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   186
        oop key = JNIHandles::resolve(entry->object());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   187
        assert(key != NULL, "jni weak reference cleared!!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   188
        unsigned int h = hash(key, new_size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   189
        JvmtiTagHashmapEntry* anchor = new_table[h];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   190
        if (anchor == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   191
          new_table[h] = entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   192
          entry->set_next(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   193
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   194
          entry->set_next(anchor);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   195
          new_table[h] = entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   196
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   197
        entry = next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   198
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   199
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   200
489c9b5090e2 Initial load
duke
parents:
diff changeset
   201
    // free old table and update settings.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   202
    os::free((void*)_table);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   203
    _table = new_table;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   204
    _size_index = new_size_index;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   205
    _size = new_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   206
489c9b5090e2 Initial load
duke
parents:
diff changeset
   207
    // compute new resize threshold
489c9b5090e2 Initial load
duke
parents:
diff changeset
   208
    _resize_threshold = (int)(_load_factor * _size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   209
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   210
489c9b5090e2 Initial load
duke
parents:
diff changeset
   211
489c9b5090e2 Initial load
duke
parents:
diff changeset
   212
  // internal remove function - remove an entry at a given position in the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   213
  // table.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   214
  inline void remove(JvmtiTagHashmapEntry* prev, int pos, JvmtiTagHashmapEntry* entry) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   215
    assert(pos >= 0 && pos < _size, "out of range");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   216
    if (prev == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   217
      _table[pos] = entry->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   218
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   219
      prev->set_next(entry->next());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   220
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   221
    assert(_entry_count > 0, "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   222
    _entry_count--;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   223
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   224
489c9b5090e2 Initial load
duke
parents:
diff changeset
   225
  // resizing switch
489c9b5090e2 Initial load
duke
parents:
diff changeset
   226
  bool is_resizing_enabled() const          { return _resizing_enabled; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   227
  void set_resizing_enabled(bool enable)    { _resizing_enabled = enable; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   228
489c9b5090e2 Initial load
duke
parents:
diff changeset
   229
  // debugging
489c9b5090e2 Initial load
duke
parents:
diff changeset
   230
  void print_memory_usage();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   231
  void compute_next_trace_threshold();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   232
489c9b5090e2 Initial load
duke
parents:
diff changeset
   233
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   234
489c9b5090e2 Initial load
duke
parents:
diff changeset
   235
  // create a JvmtiTagHashmap of a preferred size and optionally a load factor.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   236
  // The preferred size is rounded down to an actual size.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   237
  JvmtiTagHashmap(int size, float load_factor=0.0f) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   238
    int i=0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   239
    while (_sizes[i] < size) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   240
      if (_sizes[i] < 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   241
        assert(i > 0, "sanity check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   242
        i--;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   243
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   244
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   245
      i++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   246
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   247
489c9b5090e2 Initial load
duke
parents:
diff changeset
   248
    // if a load factor is specified then use it, otherwise use default
489c9b5090e2 Initial load
duke
parents:
diff changeset
   249
    if (load_factor > 0.01f) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   250
      init(i, load_factor);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   251
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   252
      init(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   253
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   254
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   255
489c9b5090e2 Initial load
duke
parents:
diff changeset
   256
  // create a JvmtiTagHashmap with default settings
489c9b5090e2 Initial load
duke
parents:
diff changeset
   257
  JvmtiTagHashmap() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   258
    init();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   259
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   260
489c9b5090e2 Initial load
duke
parents:
diff changeset
   261
  // release table when JvmtiTagHashmap destroyed
489c9b5090e2 Initial load
duke
parents:
diff changeset
   262
  ~JvmtiTagHashmap() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   263
    if (_table != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   264
      os::free((void*)_table);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   265
      _table = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   266
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   267
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   268
489c9b5090e2 Initial load
duke
parents:
diff changeset
   269
  // accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
   270
  int size() const                              { return _size; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   271
  JvmtiTagHashmapEntry** table() const          { return _table; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   272
  int entry_count() const                       { return _entry_count; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   273
489c9b5090e2 Initial load
duke
parents:
diff changeset
   274
  // find an entry in the hashmap, returns NULL if not found.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   275
  inline JvmtiTagHashmapEntry* find(oop key) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   276
    unsigned int h = hash(key);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   277
    JvmtiTagHashmapEntry* entry = _table[h];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   278
    while (entry != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   279
      oop orig_key = JNIHandles::resolve(entry->object());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   280
      assert(orig_key != NULL, "jni weak reference cleared!!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   281
      if (key == orig_key) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   282
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   283
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   284
      entry = entry->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   285
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   286
    return entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   287
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   288
489c9b5090e2 Initial load
duke
parents:
diff changeset
   289
489c9b5090e2 Initial load
duke
parents:
diff changeset
   290
  // add a new entry to hashmap
489c9b5090e2 Initial load
duke
parents:
diff changeset
   291
  inline void add(oop key, JvmtiTagHashmapEntry* entry) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   292
    assert(key != NULL, "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   293
    assert(find(key) == NULL, "duplicate detected");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   294
    unsigned int h = hash(key);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   295
    JvmtiTagHashmapEntry* anchor = _table[h];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   296
    if (anchor == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   297
      _table[h] = entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   298
      entry->set_next(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   299
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   300
      entry->set_next(anchor);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   301
      _table[h] = entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   302
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   303
489c9b5090e2 Initial load
duke
parents:
diff changeset
   304
    _entry_count++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   305
    if (trace_threshold() > 0 && entry_count() >= trace_threshold()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   306
      assert(TraceJVMTIObjectTagging, "should only get here when tracing");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   307
      print_memory_usage();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   308
      compute_next_trace_threshold();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   309
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   310
489c9b5090e2 Initial load
duke
parents:
diff changeset
   311
    // if the number of entries exceed the threshold then resize
489c9b5090e2 Initial load
duke
parents:
diff changeset
   312
    if (entry_count() > resize_threshold() && is_resizing_enabled()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   313
      resize();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   314
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   315
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   316
489c9b5090e2 Initial load
duke
parents:
diff changeset
   317
  // remove an entry with the given key.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   318
  inline JvmtiTagHashmapEntry* remove(oop key) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   319
    unsigned int h = hash(key);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   320
    JvmtiTagHashmapEntry* entry = _table[h];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   321
    JvmtiTagHashmapEntry* prev = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   322
    while (entry != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   323
      oop orig_key = JNIHandles::resolve(entry->object());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   324
      assert(orig_key != NULL, "jni weak reference cleared!!");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   325
      if (key == orig_key) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   326
        break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   327
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   328
      prev = entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   329
      entry = entry->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   330
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   331
    if (entry != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   332
      remove(prev, h, entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   333
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   334
    return entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   335
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   336
489c9b5090e2 Initial load
duke
parents:
diff changeset
   337
  // iterate over all entries in the hashmap
489c9b5090e2 Initial load
duke
parents:
diff changeset
   338
  void entry_iterate(JvmtiTagHashmapEntryClosure* closure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   339
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   340
489c9b5090e2 Initial load
duke
parents:
diff changeset
   341
// possible hashmap sizes - odd primes that roughly double in size.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   342
// To avoid excessive resizing the odd primes from 4801-76831 and
489c9b5090e2 Initial load
duke
parents:
diff changeset
   343
// 76831-307261 have been removed. The list must be terminated by -1.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   344
int JvmtiTagHashmap::_sizes[] =  { 4801, 76831, 307261, 614563, 1228891,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   345
    2457733, 4915219, 9830479, 19660831, 39321619, 78643219, -1 };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   346
489c9b5090e2 Initial load
duke
parents:
diff changeset
   347
489c9b5090e2 Initial load
duke
parents:
diff changeset
   348
// A supporting class for iterating over all entries in Hashmap
489c9b5090e2 Initial load
duke
parents:
diff changeset
   349
class JvmtiTagHashmapEntryClosure {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   350
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   351
  virtual void do_entry(JvmtiTagHashmapEntry* entry) = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   352
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   353
489c9b5090e2 Initial load
duke
parents:
diff changeset
   354
489c9b5090e2 Initial load
duke
parents:
diff changeset
   355
// iterate over all entries in the hashmap
489c9b5090e2 Initial load
duke
parents:
diff changeset
   356
void JvmtiTagHashmap::entry_iterate(JvmtiTagHashmapEntryClosure* closure) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   357
  for (int i=0; i<_size; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   358
    JvmtiTagHashmapEntry* entry = _table[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   359
    JvmtiTagHashmapEntry* prev = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   360
    while (entry != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   361
      // obtain the next entry before invoking do_entry - this is
489c9b5090e2 Initial load
duke
parents:
diff changeset
   362
      // necessary because do_entry may remove the entry from the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   363
      // hashmap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   364
      JvmtiTagHashmapEntry* next = entry->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   365
      closure->do_entry(entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   366
      entry = next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   367
     }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   368
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   369
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   370
489c9b5090e2 Initial load
duke
parents:
diff changeset
   371
// debugging
489c9b5090e2 Initial load
duke
parents:
diff changeset
   372
void JvmtiTagHashmap::print_memory_usage() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   373
  intptr_t p = (intptr_t)this;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   374
  tty->print("[JvmtiTagHashmap @ " INTPTR_FORMAT, p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   375
489c9b5090e2 Initial load
duke
parents:
diff changeset
   376
  // table + entries in KB
489c9b5090e2 Initial load
duke
parents:
diff changeset
   377
  int hashmap_usage = (size()*sizeof(JvmtiTagHashmapEntry*) +
489c9b5090e2 Initial load
duke
parents:
diff changeset
   378
    entry_count()*sizeof(JvmtiTagHashmapEntry))/K;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   379
489c9b5090e2 Initial load
duke
parents:
diff changeset
   380
  int weak_globals_usage = (int)(JNIHandles::weak_global_handle_memory_usage()/K);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   381
  tty->print_cr(", %d entries (%d KB) <JNI weak globals: %d KB>]",
489c9b5090e2 Initial load
duke
parents:
diff changeset
   382
    entry_count(), hashmap_usage, weak_globals_usage);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   383
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   384
489c9b5090e2 Initial load
duke
parents:
diff changeset
   385
// compute threshold for the next trace message
489c9b5090e2 Initial load
duke
parents:
diff changeset
   386
void JvmtiTagHashmap::compute_next_trace_threshold() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   387
  if (trace_threshold() < medium_trace_threshold) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   388
    _trace_threshold += small_trace_threshold;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   389
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   390
    if (trace_threshold() < large_trace_threshold) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   391
      _trace_threshold += medium_trace_threshold;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   392
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   393
      _trace_threshold += large_trace_threshold;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   394
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   395
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   396
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   397
489c9b5090e2 Initial load
duke
parents:
diff changeset
   398
// memory region for young generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   399
MemRegion JvmtiTagMap::_young_gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   400
489c9b5090e2 Initial load
duke
parents:
diff changeset
   401
// get the memory region used for the young generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   402
void JvmtiTagMap::get_young_generation() {
1374
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   403
  CollectedHeap* ch = Universe::heap();
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   404
  switch (ch->kind()) {
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   405
    case (CollectedHeap::GenCollectedHeap): {
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   406
      _young_gen = ((GenCollectedHeap*)ch)->get_gen(0)->reserved();
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   407
      break;
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   408
    }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   409
#ifndef SERIALGC
1374
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   410
    case (CollectedHeap::ParallelScavengeHeap): {
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   411
      _young_gen = ((ParallelScavengeHeap*)ch)->young_gen()->reserved();
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   412
      break;
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   413
    }
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   414
    case (CollectedHeap::G1CollectedHeap): {
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   415
      // Until a more satisfactory solution is implemented, all
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   416
      // oops in the tag map will require rehash at each gc.
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   417
      // This is a correct, if extremely inefficient solution.
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   418
      // See RFE 6621729 for related commentary.
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   419
      _young_gen = ch->reserved_region();
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   420
      break;
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   421
    }
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   422
#endif  // !SERIALGC
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   423
    default:
4c24294029a9 6711316: Open source the Garbage-First garbage collector
ysr
parents: 360
diff changeset
   424
      ShouldNotReachHere();
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
   425
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   426
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   427
489c9b5090e2 Initial load
duke
parents:
diff changeset
   428
// returns true if oop is in the young generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   429
inline bool JvmtiTagMap::is_in_young(oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   430
  assert(_young_gen.start() != NULL, "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   431
  void* p = (void*)o;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   432
  bool in_young = _young_gen.contains(p);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   433
  return in_young;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   434
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   435
489c9b5090e2 Initial load
duke
parents:
diff changeset
   436
// returns the appropriate hashmap for a given object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   437
inline JvmtiTagHashmap* JvmtiTagMap::hashmap_for(oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   438
  if (is_in_young(o)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   439
    return _hashmap[0];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   440
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   441
    return _hashmap[1];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   442
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   443
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   444
489c9b5090e2 Initial load
duke
parents:
diff changeset
   445
489c9b5090e2 Initial load
duke
parents:
diff changeset
   446
// create a JvmtiTagMap
489c9b5090e2 Initial load
duke
parents:
diff changeset
   447
JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   448
  _env(env),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   449
  _lock(Mutex::nonleaf+2, "JvmtiTagMap._lock", false),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   450
  _free_entries(NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   451
  _free_entries_count(0)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   452
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
   453
  assert(JvmtiThreadState_lock->is_locked(), "sanity check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   454
  assert(((JvmtiEnvBase *)env)->tag_map() == NULL, "tag map already exists for environment");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   455
489c9b5090e2 Initial load
duke
parents:
diff changeset
   456
  // create the hashmaps
489c9b5090e2 Initial load
duke
parents:
diff changeset
   457
  for (int i=0; i<n_hashmaps; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   458
    _hashmap[i] = new JvmtiTagHashmap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   459
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   460
489c9b5090e2 Initial load
duke
parents:
diff changeset
   461
  // get the memory region used by the young generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
   462
  get_young_generation();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   463
489c9b5090e2 Initial load
duke
parents:
diff changeset
   464
  // finally add us to the environment
489c9b5090e2 Initial load
duke
parents:
diff changeset
   465
  ((JvmtiEnvBase *)env)->set_tag_map(this);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   466
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   467
489c9b5090e2 Initial load
duke
parents:
diff changeset
   468
489c9b5090e2 Initial load
duke
parents:
diff changeset
   469
// destroy a JvmtiTagMap
489c9b5090e2 Initial load
duke
parents:
diff changeset
   470
JvmtiTagMap::~JvmtiTagMap() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   471
489c9b5090e2 Initial load
duke
parents:
diff changeset
   472
  // no lock acquired as we assume the enclosing environment is
489c9b5090e2 Initial load
duke
parents:
diff changeset
   473
  // also being destroryed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   474
  ((JvmtiEnvBase *)_env)->set_tag_map(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   475
489c9b5090e2 Initial load
duke
parents:
diff changeset
   476
  // iterate over the hashmaps and destroy each of the entries
489c9b5090e2 Initial load
duke
parents:
diff changeset
   477
  for (int i=0; i<n_hashmaps; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   478
    JvmtiTagHashmap* hashmap = _hashmap[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   479
    JvmtiTagHashmapEntry** table = hashmap->table();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   480
    for (int j=0; j<hashmap->size(); j++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   481
      JvmtiTagHashmapEntry *entry = table[j];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   482
      while (entry != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   483
        JvmtiTagHashmapEntry* next = entry->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   484
        jweak ref = entry->object();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   485
        JNIHandles::destroy_weak_global(ref);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   486
        delete entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   487
        entry = next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   488
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   489
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   490
489c9b5090e2 Initial load
duke
parents:
diff changeset
   491
    // finally destroy the hashmap
489c9b5090e2 Initial load
duke
parents:
diff changeset
   492
    delete hashmap;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   493
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   494
489c9b5090e2 Initial load
duke
parents:
diff changeset
   495
  // remove any entries on the free list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   496
  JvmtiTagHashmapEntry* entry = _free_entries;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   497
  while (entry != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   498
    JvmtiTagHashmapEntry* next = entry->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   499
    delete entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   500
    entry = next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   501
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   502
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   503
489c9b5090e2 Initial load
duke
parents:
diff changeset
   504
// create a hashmap entry
489c9b5090e2 Initial load
duke
parents:
diff changeset
   505
// - if there's an entry on the (per-environment) free list then this
489c9b5090e2 Initial load
duke
parents:
diff changeset
   506
// is returned. Otherwise an new entry is allocated.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   507
JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(jweak ref, jlong tag) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   508
  assert(Thread::current()->is_VM_thread() || is_locked(), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   509
  JvmtiTagHashmapEntry* entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   510
  if (_free_entries == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   511
    entry = new JvmtiTagHashmapEntry(ref, tag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   512
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   513
    assert(_free_entries_count > 0, "mismatched _free_entries_count");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   514
    _free_entries_count--;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   515
    entry = _free_entries;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   516
    _free_entries = entry->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   517
    entry->init(ref, tag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   518
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   519
  return entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   520
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   521
489c9b5090e2 Initial load
duke
parents:
diff changeset
   522
// destroy an entry by returning it to the free list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   523
void JvmtiTagMap::destroy_entry(JvmtiTagHashmapEntry* entry) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   524
  assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   525
  // limit the size of the free list
489c9b5090e2 Initial load
duke
parents:
diff changeset
   526
  if (_free_entries_count >= max_free_entries) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   527
    delete entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   528
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   529
    entry->set_next(_free_entries);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   530
    _free_entries = entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   531
    _free_entries_count++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   532
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   533
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   534
489c9b5090e2 Initial load
duke
parents:
diff changeset
   535
// returns the tag map for the given environments. If the tag map
489c9b5090e2 Initial load
duke
parents:
diff changeset
   536
// doesn't exist then it is created.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   537
JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   538
  JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   539
  if (tag_map == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   540
    MutexLocker mu(JvmtiThreadState_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   541
    tag_map = ((JvmtiEnvBase *)env)->tag_map();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   542
    if (tag_map == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   543
      tag_map = new JvmtiTagMap(env);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   544
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   545
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   546
    CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   547
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   548
  return tag_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   549
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   550
489c9b5090e2 Initial load
duke
parents:
diff changeset
   551
// iterate over all entries in the tag map.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   552
void JvmtiTagMap::entry_iterate(JvmtiTagHashmapEntryClosure* closure) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   553
  for (int i=0; i<n_hashmaps; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   554
    JvmtiTagHashmap* hashmap = _hashmap[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
   555
    hashmap->entry_iterate(closure);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   556
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   557
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   558
489c9b5090e2 Initial load
duke
parents:
diff changeset
   559
// returns true if the hashmaps are empty
489c9b5090e2 Initial load
duke
parents:
diff changeset
   560
bool JvmtiTagMap::is_empty() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   561
  assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   562
  assert(n_hashmaps == 2, "not implemented");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   563
  return ((_hashmap[0]->entry_count() == 0) && (_hashmap[1]->entry_count() == 0));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   564
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   565
489c9b5090e2 Initial load
duke
parents:
diff changeset
   566
489c9b5090e2 Initial load
duke
parents:
diff changeset
   567
// Return the tag value for an object, or 0 if the object is
489c9b5090e2 Initial load
duke
parents:
diff changeset
   568
// not tagged
489c9b5090e2 Initial load
duke
parents:
diff changeset
   569
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   570
static inline jlong tag_for(JvmtiTagMap* tag_map, oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   571
  JvmtiTagHashmapEntry* entry = tag_map->hashmap_for(o)->find(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   572
  if (entry == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   573
    return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   574
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   575
    return entry->tag();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   576
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   577
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   578
489c9b5090e2 Initial load
duke
parents:
diff changeset
   579
// If the object is a java.lang.Class then return the klassOop,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   580
// otherwise return the original object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   581
static inline oop klassOop_if_java_lang_Class(oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   582
  if (o->klass() == SystemDictionary::class_klass()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   583
    if (!java_lang_Class::is_primitive(o)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   584
      o = (oop)java_lang_Class::as_klassOop(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   585
      assert(o != NULL, "class for non-primitive mirror must exist");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   586
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   587
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   588
  return o;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   589
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   590
489c9b5090e2 Initial load
duke
parents:
diff changeset
   591
// A CallbackWrapper is a support class for querying and tagging an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   592
// around a callback to a profiler. The constructor does pre-callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
   593
// work to get the tag value, klass tag value, ... and the destructor
489c9b5090e2 Initial load
duke
parents:
diff changeset
   594
// does the post-callback work of tagging or untagging the object.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   595
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   596
// {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   597
//   CallbackWrapper wrapper(tag_map, o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   598
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   599
//   (*callback)(wrapper.klass_tag(), wrapper.obj_size(), wrapper.obj_tag_p(), ...)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   600
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   601
// } // wrapper goes out of scope here which results in the destructor
489c9b5090e2 Initial load
duke
parents:
diff changeset
   602
//      checking to see if the object has been tagged, untagged, or the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   603
//      tag value has changed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   604
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   605
class CallbackWrapper : public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   606
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   607
  JvmtiTagMap* _tag_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   608
  JvmtiTagHashmap* _hashmap;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   609
  JvmtiTagHashmapEntry* _entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   610
  oop _o;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   611
  jlong _obj_size;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   612
  jlong _obj_tag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   613
  klassOop _klass;         // the object's class
489c9b5090e2 Initial load
duke
parents:
diff changeset
   614
  jlong _klass_tag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   615
489c9b5090e2 Initial load
duke
parents:
diff changeset
   616
 protected:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   617
  JvmtiTagMap* tag_map() const      { return _tag_map; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   618
489c9b5090e2 Initial load
duke
parents:
diff changeset
   619
  // invoked post-callback to tag, untag, or update the tag of an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   620
  void inline post_callback_tag_update(oop o, JvmtiTagHashmap* hashmap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   621
                                       JvmtiTagHashmapEntry* entry, jlong obj_tag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   622
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   623
  CallbackWrapper(JvmtiTagMap* tag_map, oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   624
    assert(Thread::current()->is_VM_thread() || tag_map->is_locked(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   625
           "MT unsafe or must be VM thread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   626
489c9b5090e2 Initial load
duke
parents:
diff changeset
   627
    // for Classes the klassOop is tagged
489c9b5090e2 Initial load
duke
parents:
diff changeset
   628
    _o = klassOop_if_java_lang_Class(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   629
489c9b5090e2 Initial load
duke
parents:
diff changeset
   630
    // object size
489c9b5090e2 Initial load
duke
parents:
diff changeset
   631
    _obj_size = _o->size() * wordSize;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   632
489c9b5090e2 Initial load
duke
parents:
diff changeset
   633
    // record the context
489c9b5090e2 Initial load
duke
parents:
diff changeset
   634
    _tag_map = tag_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   635
    _hashmap = tag_map->hashmap_for(_o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   636
    _entry = _hashmap->find(_o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   637
489c9b5090e2 Initial load
duke
parents:
diff changeset
   638
    // get object tag
489c9b5090e2 Initial load
duke
parents:
diff changeset
   639
    _obj_tag = (_entry == NULL) ? 0 : _entry->tag();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   640
489c9b5090e2 Initial load
duke
parents:
diff changeset
   641
    // get the class and the class's tag value
489c9b5090e2 Initial load
duke
parents:
diff changeset
   642
    if (_o == o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   643
      _klass = _o->klass();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   644
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   645
      // if the object represents a runtime class then use the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   646
      // tag for java.lang.Class
489c9b5090e2 Initial load
duke
parents:
diff changeset
   647
      _klass = SystemDictionary::class_klass();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   648
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   649
    _klass_tag = tag_for(tag_map, _klass);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   650
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   651
489c9b5090e2 Initial load
duke
parents:
diff changeset
   652
  ~CallbackWrapper() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   653
    post_callback_tag_update(_o, _hashmap, _entry, _obj_tag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   654
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   655
489c9b5090e2 Initial load
duke
parents:
diff changeset
   656
  inline jlong* obj_tag_p()                     { return &_obj_tag; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   657
  inline jlong obj_size() const                 { return _obj_size; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   658
  inline jlong obj_tag() const                  { return _obj_tag; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   659
  inline klassOop klass() const                 { return _klass; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   660
  inline jlong klass_tag() const                { return _klass_tag; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   661
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   662
489c9b5090e2 Initial load
duke
parents:
diff changeset
   663
489c9b5090e2 Initial load
duke
parents:
diff changeset
   664
489c9b5090e2 Initial load
duke
parents:
diff changeset
   665
// callback post-callback to tag, untag, or update the tag of an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   666
void inline CallbackWrapper::post_callback_tag_update(oop o,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   667
                                                      JvmtiTagHashmap* hashmap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   668
                                                      JvmtiTagHashmapEntry* entry,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   669
                                                      jlong obj_tag) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   670
  if (entry == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   671
    if (obj_tag != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   672
      // callback has tagged the object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   673
      assert(Thread::current()->is_VM_thread(), "must be VMThread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   674
      HandleMark hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   675
      Handle h(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   676
      jweak ref = JNIHandles::make_weak_global(h);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   677
      entry = tag_map()->create_entry(ref, obj_tag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   678
      hashmap->add(o, entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   679
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   680
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   681
    // object was previously tagged - the callback may have untagged
489c9b5090e2 Initial load
duke
parents:
diff changeset
   682
    // the object or changed the tag value
489c9b5090e2 Initial load
duke
parents:
diff changeset
   683
    if (obj_tag == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   684
      jweak ref = entry->object();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   685
489c9b5090e2 Initial load
duke
parents:
diff changeset
   686
      JvmtiTagHashmapEntry* entry_removed = hashmap->remove(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   687
      assert(entry_removed == entry, "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
   688
      tag_map()->destroy_entry(entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   689
489c9b5090e2 Initial load
duke
parents:
diff changeset
   690
      JNIHandles::destroy_weak_global(ref);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   691
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   692
      if (obj_tag != entry->tag()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   693
         entry->set_tag(obj_tag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   694
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   695
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   696
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   697
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   698
489c9b5090e2 Initial load
duke
parents:
diff changeset
   699
// An extended CallbackWrapper used when reporting an object reference
489c9b5090e2 Initial load
duke
parents:
diff changeset
   700
// to the agent.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   701
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   702
// {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   703
//   TwoOopCallbackWrapper wrapper(tag_map, referrer, o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   704
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   705
//   (*callback)(wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   706
//               wrapper.obj_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   707
//               wrapper.obj_tag_p()
489c9b5090e2 Initial load
duke
parents:
diff changeset
   708
//               wrapper.referrer_tag_p(), ...)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   709
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   710
// } // wrapper goes out of scope here which results in the destructor
489c9b5090e2 Initial load
duke
parents:
diff changeset
   711
//      checking to see if the referrer object has been tagged, untagged,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   712
//      or the tag value has changed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   713
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   714
class TwoOopCallbackWrapper : public CallbackWrapper {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   715
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   716
  bool _is_reference_to_self;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   717
  JvmtiTagHashmap* _referrer_hashmap;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   718
  JvmtiTagHashmapEntry* _referrer_entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   719
  oop _referrer;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   720
  jlong _referrer_obj_tag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   721
  jlong _referrer_klass_tag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   722
  jlong* _referrer_tag_p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   723
489c9b5090e2 Initial load
duke
parents:
diff changeset
   724
  bool is_reference_to_self() const             { return _is_reference_to_self; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   725
489c9b5090e2 Initial load
duke
parents:
diff changeset
   726
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   727
  TwoOopCallbackWrapper(JvmtiTagMap* tag_map, oop referrer, oop o) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   728
    CallbackWrapper(tag_map, o)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   729
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   730
    // self reference needs to be handled in a special way
489c9b5090e2 Initial load
duke
parents:
diff changeset
   731
    _is_reference_to_self = (referrer == o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   732
489c9b5090e2 Initial load
duke
parents:
diff changeset
   733
    if (_is_reference_to_self) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   734
      _referrer_klass_tag = klass_tag();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   735
      _referrer_tag_p = obj_tag_p();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   736
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   737
      // for Classes the klassOop is tagged
489c9b5090e2 Initial load
duke
parents:
diff changeset
   738
      _referrer = klassOop_if_java_lang_Class(referrer);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   739
      // record the context
489c9b5090e2 Initial load
duke
parents:
diff changeset
   740
      _referrer_hashmap = tag_map->hashmap_for(_referrer);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   741
      _referrer_entry = _referrer_hashmap->find(_referrer);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   742
489c9b5090e2 Initial load
duke
parents:
diff changeset
   743
      // get object tag
489c9b5090e2 Initial load
duke
parents:
diff changeset
   744
      _referrer_obj_tag = (_referrer_entry == NULL) ? 0 : _referrer_entry->tag();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   745
      _referrer_tag_p = &_referrer_obj_tag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   746
489c9b5090e2 Initial load
duke
parents:
diff changeset
   747
      // get referrer class tag.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   748
      klassOop k = (_referrer == referrer) ?  // Check if referrer is a class...
489c9b5090e2 Initial load
duke
parents:
diff changeset
   749
          _referrer->klass()                  // No, just get its class
489c9b5090e2 Initial load
duke
parents:
diff changeset
   750
         : SystemDictionary::class_klass();   // Yes, its class is Class
489c9b5090e2 Initial load
duke
parents:
diff changeset
   751
      _referrer_klass_tag = tag_for(tag_map, k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   752
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   753
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   754
489c9b5090e2 Initial load
duke
parents:
diff changeset
   755
  ~TwoOopCallbackWrapper() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   756
    if (!is_reference_to_self()){
489c9b5090e2 Initial load
duke
parents:
diff changeset
   757
      post_callback_tag_update(_referrer,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   758
                               _referrer_hashmap,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   759
                               _referrer_entry,
489c9b5090e2 Initial load
duke
parents:
diff changeset
   760
                               _referrer_obj_tag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   761
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   762
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   763
489c9b5090e2 Initial load
duke
parents:
diff changeset
   764
  // address of referrer tag
489c9b5090e2 Initial load
duke
parents:
diff changeset
   765
  // (for a self reference this will return the same thing as obj_tag_p())
489c9b5090e2 Initial load
duke
parents:
diff changeset
   766
  inline jlong* referrer_tag_p()        { return _referrer_tag_p; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   767
489c9b5090e2 Initial load
duke
parents:
diff changeset
   768
  // referrer's class tag
489c9b5090e2 Initial load
duke
parents:
diff changeset
   769
  inline jlong referrer_klass_tag()     { return _referrer_klass_tag; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   770
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   771
489c9b5090e2 Initial load
duke
parents:
diff changeset
   772
// tag an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   773
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   774
// This function is performance critical. If many threads attempt to tag objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
   775
// around the same time then it's possible that the Mutex associated with the
489c9b5090e2 Initial load
duke
parents:
diff changeset
   776
// tag map will be a hot lock. Eliminating this lock will not eliminate the issue
489c9b5090e2 Initial load
duke
parents:
diff changeset
   777
// because creating a JNI weak reference requires acquiring a global lock also.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   778
void JvmtiTagMap::set_tag(jobject object, jlong tag) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   779
  MutexLocker ml(lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   780
489c9b5090e2 Initial load
duke
parents:
diff changeset
   781
  // resolve the object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   782
  oop o = JNIHandles::resolve_non_null(object);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   783
489c9b5090e2 Initial load
duke
parents:
diff changeset
   784
  // for Classes we tag the klassOop
489c9b5090e2 Initial load
duke
parents:
diff changeset
   785
  o = klassOop_if_java_lang_Class(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   786
489c9b5090e2 Initial load
duke
parents:
diff changeset
   787
  // see if the object is already tagged
489c9b5090e2 Initial load
duke
parents:
diff changeset
   788
  JvmtiTagHashmap* hashmap = hashmap_for(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   789
  JvmtiTagHashmapEntry* entry = hashmap->find(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   790
489c9b5090e2 Initial load
duke
parents:
diff changeset
   791
  // if the object is not already tagged then we tag it
489c9b5090e2 Initial load
duke
parents:
diff changeset
   792
  if (entry == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   793
    if (tag != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   794
      HandleMark hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   795
      Handle h(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   796
      jweak ref = JNIHandles::make_weak_global(h);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   797
489c9b5090e2 Initial load
duke
parents:
diff changeset
   798
      // the object may have moved because make_weak_global may
489c9b5090e2 Initial load
duke
parents:
diff changeset
   799
      // have blocked - thus it is necessary resolve the handle
489c9b5090e2 Initial load
duke
parents:
diff changeset
   800
      // and re-hash the object.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   801
      o = h();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   802
      entry = create_entry(ref, tag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   803
      hashmap_for(o)->add(o, entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   804
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   805
      // no-op
489c9b5090e2 Initial load
duke
parents:
diff changeset
   806
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   807
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   808
    // if the object is already tagged then we either update
489c9b5090e2 Initial load
duke
parents:
diff changeset
   809
    // the tag (if a new tag value has been provided)
489c9b5090e2 Initial load
duke
parents:
diff changeset
   810
    // or remove the object if the new tag value is 0.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   811
    // Removing the object requires that we also delete the JNI
489c9b5090e2 Initial load
duke
parents:
diff changeset
   812
    // weak ref to the object.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   813
    if (tag == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   814
      jweak ref = entry->object();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   815
      hashmap->remove(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   816
      destroy_entry(entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   817
      JNIHandles::destroy_weak_global(ref);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   818
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   819
      entry->set_tag(tag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   820
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   821
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   822
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   823
489c9b5090e2 Initial load
duke
parents:
diff changeset
   824
// get the tag for an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   825
jlong JvmtiTagMap::get_tag(jobject object) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   826
  MutexLocker ml(lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   827
489c9b5090e2 Initial load
duke
parents:
diff changeset
   828
  // resolve the object
489c9b5090e2 Initial load
duke
parents:
diff changeset
   829
  oop o = JNIHandles::resolve_non_null(object);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   830
489c9b5090e2 Initial load
duke
parents:
diff changeset
   831
  // for Classes get the tag from the klassOop
489c9b5090e2 Initial load
duke
parents:
diff changeset
   832
  return tag_for(this, klassOop_if_java_lang_Class(o));
489c9b5090e2 Initial load
duke
parents:
diff changeset
   833
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   834
489c9b5090e2 Initial load
duke
parents:
diff changeset
   835
489c9b5090e2 Initial load
duke
parents:
diff changeset
   836
// Helper class used to describe the static or instance fields of a class.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   837
// For each field it holds the field index (as defined by the JVMTI specification),
489c9b5090e2 Initial load
duke
parents:
diff changeset
   838
// the field type, and the offset.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   839
489c9b5090e2 Initial load
duke
parents:
diff changeset
   840
class ClassFieldDescriptor: public CHeapObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   841
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   842
  int _field_index;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   843
  int _field_offset;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   844
  char _field_type;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   845
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   846
  ClassFieldDescriptor(int index, char type, int offset) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
   847
    _field_index(index), _field_type(type), _field_offset(offset) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   848
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   849
  int field_index()  const  { return _field_index; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   850
  char field_type()  const  { return _field_type; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   851
  int field_offset() const  { return _field_offset; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   852
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   853
489c9b5090e2 Initial load
duke
parents:
diff changeset
   854
class ClassFieldMap: public CHeapObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   855
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   856
  enum {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   857
    initial_field_count = 5
489c9b5090e2 Initial load
duke
parents:
diff changeset
   858
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   859
489c9b5090e2 Initial load
duke
parents:
diff changeset
   860
  // list of field descriptors
489c9b5090e2 Initial load
duke
parents:
diff changeset
   861
  GrowableArray<ClassFieldDescriptor*>* _fields;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   862
489c9b5090e2 Initial load
duke
parents:
diff changeset
   863
  // constructor
489c9b5090e2 Initial load
duke
parents:
diff changeset
   864
  ClassFieldMap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   865
489c9b5090e2 Initial load
duke
parents:
diff changeset
   866
  // add a field
489c9b5090e2 Initial load
duke
parents:
diff changeset
   867
  void add(int index, char type, int offset);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   868
489c9b5090e2 Initial load
duke
parents:
diff changeset
   869
  // returns the field count for the given class
489c9b5090e2 Initial load
duke
parents:
diff changeset
   870
  static int compute_field_count(instanceKlassHandle ikh);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   871
489c9b5090e2 Initial load
duke
parents:
diff changeset
   872
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   873
  ~ClassFieldMap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   874
489c9b5090e2 Initial load
duke
parents:
diff changeset
   875
  // access
489c9b5090e2 Initial load
duke
parents:
diff changeset
   876
  int field_count()                     { return _fields->length(); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   877
  ClassFieldDescriptor* field_at(int i) { return _fields->at(i); }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   878
489c9b5090e2 Initial load
duke
parents:
diff changeset
   879
  // functions to create maps of static or instance fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
   880
  static ClassFieldMap* create_map_of_static_fields(klassOop k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   881
  static ClassFieldMap* create_map_of_instance_fields(oop obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   882
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   883
489c9b5090e2 Initial load
duke
parents:
diff changeset
   884
ClassFieldMap::ClassFieldMap() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   885
  _fields = new (ResourceObj::C_HEAP) GrowableArray<ClassFieldDescriptor*>(initial_field_count, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   886
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   887
489c9b5090e2 Initial load
duke
parents:
diff changeset
   888
ClassFieldMap::~ClassFieldMap() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   889
  for (int i=0; i<_fields->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   890
    delete _fields->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   891
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   892
  delete _fields;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   893
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   894
489c9b5090e2 Initial load
duke
parents:
diff changeset
   895
void ClassFieldMap::add(int index, char type, int offset) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   896
  ClassFieldDescriptor* field = new ClassFieldDescriptor(index, type, offset);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   897
  _fields->append(field);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   898
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   899
489c9b5090e2 Initial load
duke
parents:
diff changeset
   900
// Returns a heap allocated ClassFieldMap to describe the static fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
   901
// of the given class.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   902
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   903
ClassFieldMap* ClassFieldMap::create_map_of_static_fields(klassOop k) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   904
  HandleMark hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   905
  instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   906
489c9b5090e2 Initial load
duke
parents:
diff changeset
   907
  // create the field map
489c9b5090e2 Initial load
duke
parents:
diff changeset
   908
  ClassFieldMap* field_map = new ClassFieldMap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   909
489c9b5090e2 Initial load
duke
parents:
diff changeset
   910
  FilteredFieldStream f(ikh, false, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   911
  int max_field_index = f.field_count()-1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   912
489c9b5090e2 Initial load
duke
parents:
diff changeset
   913
  int index = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   914
  for (FilteredFieldStream fld(ikh, true, true); !fld.eos(); fld.next(), index++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   915
    // ignore instance fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
   916
    if (!fld.access_flags().is_static()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   917
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   918
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   919
    field_map->add(max_field_index - index, fld.signature()->byte_at(0), fld.offset());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   920
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   921
  return field_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   922
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   923
489c9b5090e2 Initial load
duke
parents:
diff changeset
   924
// Returns a heap allocated ClassFieldMap to describe the instance fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
   925
// of the given class. All instance fields are included (this means public
489c9b5090e2 Initial load
duke
parents:
diff changeset
   926
// and private fields declared in superclasses and superinterfaces too).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   927
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   928
ClassFieldMap* ClassFieldMap::create_map_of_instance_fields(oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   929
  HandleMark hm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   930
  instanceKlassHandle ikh = instanceKlassHandle(Thread::current(), obj->klass());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   931
489c9b5090e2 Initial load
duke
parents:
diff changeset
   932
  // create the field map
489c9b5090e2 Initial load
duke
parents:
diff changeset
   933
  ClassFieldMap* field_map = new ClassFieldMap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   934
489c9b5090e2 Initial load
duke
parents:
diff changeset
   935
  FilteredFieldStream f(ikh, false, false);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   936
489c9b5090e2 Initial load
duke
parents:
diff changeset
   937
  int max_field_index = f.field_count()-1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   938
489c9b5090e2 Initial load
duke
parents:
diff changeset
   939
  int index = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   940
  for (FilteredFieldStream fld(ikh, false, false); !fld.eos(); fld.next(), index++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   941
    // ignore static fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
   942
    if (fld.access_flags().is_static()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   943
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   944
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   945
    field_map->add(max_field_index - index, fld.signature()->byte_at(0), fld.offset());
489c9b5090e2 Initial load
duke
parents:
diff changeset
   946
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   947
489c9b5090e2 Initial load
duke
parents:
diff changeset
   948
  return field_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   949
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   950
489c9b5090e2 Initial load
duke
parents:
diff changeset
   951
// Helper class used to cache a ClassFileMap for the instance fields of
489c9b5090e2 Initial load
duke
parents:
diff changeset
   952
// a cache. A JvmtiCachedClassFieldMap can be cached by an instanceKlass during
489c9b5090e2 Initial load
duke
parents:
diff changeset
   953
// heap iteration and avoid creating a field map for each object in the heap
489c9b5090e2 Initial load
duke
parents:
diff changeset
   954
// (only need to create the map when the first instance of a class is encountered).
489c9b5090e2 Initial load
duke
parents:
diff changeset
   955
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
   956
class JvmtiCachedClassFieldMap : public CHeapObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   957
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   958
   enum {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   959
     initial_class_count = 200
489c9b5090e2 Initial load
duke
parents:
diff changeset
   960
   };
489c9b5090e2 Initial load
duke
parents:
diff changeset
   961
  ClassFieldMap* _field_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   962
489c9b5090e2 Initial load
duke
parents:
diff changeset
   963
  ClassFieldMap* field_map() const          { return _field_map; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   964
489c9b5090e2 Initial load
duke
parents:
diff changeset
   965
  JvmtiCachedClassFieldMap(ClassFieldMap* field_map);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   966
  ~JvmtiCachedClassFieldMap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   967
489c9b5090e2 Initial load
duke
parents:
diff changeset
   968
  static GrowableArray<instanceKlass*>* _class_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   969
  static void add_to_class_list(instanceKlass* ik);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   970
489c9b5090e2 Initial load
duke
parents:
diff changeset
   971
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
   972
  // returns the field map for a given object (returning map cached
489c9b5090e2 Initial load
duke
parents:
diff changeset
   973
  // by instanceKlass if possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
   974
  static ClassFieldMap* get_map_of_instance_fields(oop obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
   975
489c9b5090e2 Initial load
duke
parents:
diff changeset
   976
  // removes the field map from all instanceKlasses - should be
489c9b5090e2 Initial load
duke
parents:
diff changeset
   977
  // called before VM operation completes
489c9b5090e2 Initial load
duke
parents:
diff changeset
   978
  static void clear_cache();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   979
489c9b5090e2 Initial load
duke
parents:
diff changeset
   980
  // returns the number of ClassFieldMap cached by instanceKlasses
489c9b5090e2 Initial load
duke
parents:
diff changeset
   981
  static int cached_field_map_count();
489c9b5090e2 Initial load
duke
parents:
diff changeset
   982
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
   983
489c9b5090e2 Initial load
duke
parents:
diff changeset
   984
GrowableArray<instanceKlass*>* JvmtiCachedClassFieldMap::_class_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   985
489c9b5090e2 Initial load
duke
parents:
diff changeset
   986
JvmtiCachedClassFieldMap::JvmtiCachedClassFieldMap(ClassFieldMap* field_map) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   987
  _field_map = field_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   988
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   989
489c9b5090e2 Initial load
duke
parents:
diff changeset
   990
JvmtiCachedClassFieldMap::~JvmtiCachedClassFieldMap() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   991
  if (_field_map != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   992
    delete _field_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
   993
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
   994
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
   995
489c9b5090e2 Initial load
duke
parents:
diff changeset
   996
// Marker class to ensure that the class file map cache is only used in a defined
489c9b5090e2 Initial load
duke
parents:
diff changeset
   997
// scope.
489c9b5090e2 Initial load
duke
parents:
diff changeset
   998
class ClassFieldMapCacheMark : public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
   999
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1000
   static bool _is_active;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1001
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1002
   ClassFieldMapCacheMark() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1003
     assert(Thread::current()->is_VM_thread(), "must be VMThread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1004
     assert(JvmtiCachedClassFieldMap::cached_field_map_count() == 0, "cache not empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1005
     assert(!_is_active, "ClassFieldMapCacheMark cannot be nested");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1006
     _is_active = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1007
   }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1008
   ~ClassFieldMapCacheMark() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1009
     JvmtiCachedClassFieldMap::clear_cache();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1010
     _is_active = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1011
   }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1012
   static bool is_active() { return _is_active; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1013
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1014
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1015
bool ClassFieldMapCacheMark::_is_active;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1016
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1017
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1018
// record that the given instanceKlass is caching a field map
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1019
void JvmtiCachedClassFieldMap::add_to_class_list(instanceKlass* ik) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1020
  if (_class_list == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1021
    _class_list = new (ResourceObj::C_HEAP) GrowableArray<instanceKlass*>(initial_class_count, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1022
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1023
  _class_list->push(ik);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1024
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1025
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1026
// returns the instance field map for the given object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1027
// (returns field map cached by the instanceKlass if possible)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1028
ClassFieldMap* JvmtiCachedClassFieldMap::get_map_of_instance_fields(oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1029
  assert(Thread::current()->is_VM_thread(), "must be VMThread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1030
  assert(ClassFieldMapCacheMark::is_active(), "ClassFieldMapCacheMark not active");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1031
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1032
  klassOop k = obj->klass();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1033
  instanceKlass* ik = instanceKlass::cast(k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1034
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1035
  // return cached map if possible
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1036
  JvmtiCachedClassFieldMap* cached_map = ik->jvmti_cached_class_field_map();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1037
  if (cached_map != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1038
    assert(cached_map->field_map() != NULL, "missing field list");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1039
    return cached_map->field_map();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1040
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1041
    ClassFieldMap* field_map = ClassFieldMap::create_map_of_instance_fields(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1042
    cached_map = new JvmtiCachedClassFieldMap(field_map);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1043
    ik->set_jvmti_cached_class_field_map(cached_map);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1044
    add_to_class_list(ik);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1045
    return field_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1046
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1047
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1048
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1049
// remove the fields maps cached from all instanceKlasses
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1050
void JvmtiCachedClassFieldMap::clear_cache() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1051
  assert(Thread::current()->is_VM_thread(), "must be VMThread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1052
  if (_class_list != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1053
    for (int i = 0; i < _class_list->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1054
      instanceKlass* ik = _class_list->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1055
      JvmtiCachedClassFieldMap* cached_map = ik->jvmti_cached_class_field_map();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1056
      assert(cached_map != NULL, "should not be NULL");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1057
      ik->set_jvmti_cached_class_field_map(NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1058
      delete cached_map;  // deletes the encapsulated field map
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1059
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1060
    delete _class_list;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1061
    _class_list = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1062
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1063
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1064
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1065
// returns the number of ClassFieldMap cached by instanceKlasses
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1066
int JvmtiCachedClassFieldMap::cached_field_map_count() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1067
  return (_class_list == NULL) ? 0 : _class_list->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1068
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1069
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1070
// helper function to indicate if an object is filtered by its tag or class tag
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1071
static inline bool is_filtered_by_heap_filter(jlong obj_tag,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1072
                                              jlong klass_tag,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1073
                                              int heap_filter) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1074
  // apply the heap filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1075
  if (obj_tag != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1076
    // filter out tagged objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1077
    if (heap_filter & JVMTI_HEAP_FILTER_TAGGED) return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1078
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1079
    // filter out untagged objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1080
    if (heap_filter & JVMTI_HEAP_FILTER_UNTAGGED) return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1081
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1082
  if (klass_tag != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1083
    // filter out objects with tagged classes
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1084
    if (heap_filter & JVMTI_HEAP_FILTER_CLASS_TAGGED) return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1085
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1086
    // filter out objects with untagged classes.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1087
    if (heap_filter & JVMTI_HEAP_FILTER_CLASS_UNTAGGED) return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1088
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1089
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1090
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1091
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1092
// helper function to indicate if an object is filtered by a klass filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1093
static inline bool is_filtered_by_klass_filter(oop obj, KlassHandle klass_filter) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1094
  if (!klass_filter.is_null()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1095
    if (obj->klass() != klass_filter()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1096
      return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1097
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1098
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1099
  return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1100
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1101
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1102
// helper function to tell if a field is a primitive field or not
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1103
static inline bool is_primitive_field_type(char type) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1104
  return (type != 'L' && type != '[');
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1105
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1106
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1107
// helper function to copy the value from location addr to jvalue.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1108
static inline void copy_to_jvalue(jvalue *v, address addr, jvmtiPrimitiveType value_type) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1109
  switch (value_type) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1110
    case JVMTI_PRIMITIVE_TYPE_BOOLEAN : { v->z = *(jboolean*)addr; break; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1111
    case JVMTI_PRIMITIVE_TYPE_BYTE    : { v->b = *(jbyte*)addr;    break; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1112
    case JVMTI_PRIMITIVE_TYPE_CHAR    : { v->c = *(jchar*)addr;    break; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1113
    case JVMTI_PRIMITIVE_TYPE_SHORT   : { v->s = *(jshort*)addr;   break; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1114
    case JVMTI_PRIMITIVE_TYPE_INT     : { v->i = *(jint*)addr;     break; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1115
    case JVMTI_PRIMITIVE_TYPE_LONG    : { v->j = *(jlong*)addr;    break; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1116
    case JVMTI_PRIMITIVE_TYPE_FLOAT   : { v->f = *(jfloat*)addr;   break; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1117
    case JVMTI_PRIMITIVE_TYPE_DOUBLE  : { v->d = *(jdouble*)addr;  break; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1118
    default: ShouldNotReachHere();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1119
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1120
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1121
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1122
// helper function to invoke string primitive value callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1123
// returns visit control flags
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1124
static jint invoke_string_value_callback(jvmtiStringPrimitiveValueCallback cb,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1125
                                         CallbackWrapper* wrapper,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1126
                                         oop str,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1127
                                         void* user_data)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1128
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1129
  assert(str->klass() == SystemDictionary::string_klass(), "not a string");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1130
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1131
  // get the string value and length
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1132
  // (string value may be offset from the base)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1133
  int s_len = java_lang_String::length(str);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1134
  typeArrayOop s_value = java_lang_String::value(str);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1135
  int s_offset = java_lang_String::offset(str);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1136
  jchar* value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1137
  if (s_len > 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1138
    value = s_value->char_at_addr(s_offset);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1139
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1140
    value = (jchar*) s_value->base(T_CHAR);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1141
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1142
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1143
  // invoke the callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1144
  return (*cb)(wrapper->klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1145
               wrapper->obj_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1146
               wrapper->obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1147
               value,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1148
               (jint)s_len,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1149
               user_data);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1150
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1151
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1152
// helper function to invoke string primitive value callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1153
// returns visit control flags
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1154
static jint invoke_array_primitive_value_callback(jvmtiArrayPrimitiveValueCallback cb,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1155
                                                  CallbackWrapper* wrapper,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1156
                                                  oop obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1157
                                                  void* user_data)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1158
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1159
  assert(obj->is_typeArray(), "not a primitive array");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1160
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1161
  // get base address of first element
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1162
  typeArrayOop array = typeArrayOop(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1163
  BasicType type = typeArrayKlass::cast(array->klass())->element_type();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1164
  void* elements = array->base(type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1165
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1166
  // jvmtiPrimitiveType is defined so this mapping is always correct
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1167
  jvmtiPrimitiveType elem_type = (jvmtiPrimitiveType)type2char(type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1168
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1169
  return (*cb)(wrapper->klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1170
               wrapper->obj_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1171
               wrapper->obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1172
               (jint)array->length(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1173
               elem_type,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1174
               elements,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1175
               user_data);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1176
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1177
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1178
// helper function to invoke the primitive field callback for all static fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1179
// of a given class
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1180
static jint invoke_primitive_field_callback_for_static_fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1181
  (CallbackWrapper* wrapper,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1182
   oop obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1183
   jvmtiPrimitiveFieldCallback cb,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1184
   void* user_data)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1185
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1186
  // for static fields only the index will be set
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1187
  static jvmtiHeapReferenceInfo reference_info = { 0 };
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1188
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1189
  assert(obj->klass() == SystemDictionary::class_klass(), "not a class");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1190
  if (java_lang_Class::is_primitive(obj)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1191
    return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1192
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1193
  klassOop k = java_lang_Class::as_klassOop(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1194
  Klass* klass = k->klass_part();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1195
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1196
  // ignore classes for object and type arrays
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1197
  if (!klass->oop_is_instance()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1198
    return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1199
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1200
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1201
  // ignore classes which aren't linked yet
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1202
  instanceKlass* ik = instanceKlass::cast(k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1203
  if (!ik->is_linked()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1204
    return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1205
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1206
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1207
  // get the field map
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1208
  ClassFieldMap* field_map = ClassFieldMap::create_map_of_static_fields(k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1209
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1210
  // invoke the callback for each static primitive field
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1211
  for (int i=0; i<field_map->field_count(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1212
    ClassFieldDescriptor* field = field_map->field_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1213
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1214
    // ignore non-primitive fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1215
    char type = field->field_type();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1216
    if (!is_primitive_field_type(type)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1217
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1218
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1219
    // one-to-one mapping
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1220
    jvmtiPrimitiveType value_type = (jvmtiPrimitiveType)type;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1221
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1222
    // get offset and field value
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1223
    int offset = field->field_offset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1224
    address addr = (address)k + offset;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1225
    jvalue value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1226
    copy_to_jvalue(&value, addr, value_type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1227
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1228
    // field index
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1229
    reference_info.field.index = field->field_index();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1230
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1231
    // invoke the callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1232
    jint res = (*cb)(JVMTI_HEAP_REFERENCE_STATIC_FIELD,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1233
                     &reference_info,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1234
                     wrapper->klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1235
                     wrapper->obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1236
                     value,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1237
                     value_type,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1238
                     user_data);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1239
    if (res & JVMTI_VISIT_ABORT) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1240
      delete field_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1241
      return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1242
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1243
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1244
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1245
  delete field_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1246
  return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1247
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1248
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1249
// helper function to invoke the primitive field callback for all instance fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1250
// of a given object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1251
static jint invoke_primitive_field_callback_for_instance_fields(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1252
  CallbackWrapper* wrapper,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1253
  oop obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1254
  jvmtiPrimitiveFieldCallback cb,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1255
  void* user_data)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1256
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1257
  // for instance fields only the index will be set
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1258
  static jvmtiHeapReferenceInfo reference_info = { 0 };
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1259
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1260
  // get the map of the instance fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1261
  ClassFieldMap* fields = JvmtiCachedClassFieldMap::get_map_of_instance_fields(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1262
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1263
  // invoke the callback for each instance primitive field
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1264
  for (int i=0; i<fields->field_count(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1265
    ClassFieldDescriptor* field = fields->field_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1266
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1267
    // ignore non-primitive fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1268
    char type = field->field_type();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1269
    if (!is_primitive_field_type(type)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1270
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1271
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1272
    // one-to-one mapping
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1273
    jvmtiPrimitiveType value_type = (jvmtiPrimitiveType)type;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1274
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1275
    // get offset and field value
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1276
    int offset = field->field_offset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1277
    address addr = (address)obj + offset;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1278
    jvalue value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1279
    copy_to_jvalue(&value, addr, value_type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1280
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1281
    // field index
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1282
    reference_info.field.index = field->field_index();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1283
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1284
    // invoke the callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1285
    jint res = (*cb)(JVMTI_HEAP_REFERENCE_FIELD,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1286
                     &reference_info,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1287
                     wrapper->klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1288
                     wrapper->obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1289
                     value,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1290
                     value_type,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1291
                     user_data);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1292
    if (res & JVMTI_VISIT_ABORT) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1293
      return res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1294
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1295
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1296
  return 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1297
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1298
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1299
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1300
// VM operation to iterate over all objects in the heap (both reachable
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1301
// and unreachable)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1302
class VM_HeapIterateOperation: public VM_Operation {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1303
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1304
  ObjectClosure* _blk;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1305
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1306
  VM_HeapIterateOperation(ObjectClosure* blk) { _blk = blk; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1307
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1308
  VMOp_Type type() const { return VMOp_HeapIterateOperation; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1309
  void doit() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1310
    // allows class files maps to be cached during iteration
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1311
    ClassFieldMapCacheMark cm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1312
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1313
    // make sure that heap is parsable (fills TLABs with filler objects)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1314
    Universe::heap()->ensure_parsability(false);  // no need to retire TLABs
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1315
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1316
    // Verify heap before iteration - if the heap gets corrupted then
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1317
    // JVMTI's IterateOverHeap will crash.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1318
    if (VerifyBeforeIteration) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1319
      Universe::verify();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1320
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1321
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1322
    // do the iteration
1893
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1388
diff changeset
  1323
    // If this operation encounters a bad object when using CMS,
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1388
diff changeset
  1324
    // consider using safe_object_iterate() which avoids perm gen
c82e388e17c5 6689653: JMapPerm fails with UseConcMarkSweepIncGC and compressed oops off
jmasa
parents: 1388
diff changeset
  1325
    // objects that may contain bad references.
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1326
    Universe::heap()->object_iterate(_blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1327
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1328
    // when sharing is enabled we must iterate over the shared spaces
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1329
    if (UseSharedSpaces) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1330
      GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1331
      CompactingPermGenGen* gen = (CompactingPermGenGen*)gch->perm_gen();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1332
      gen->ro_space()->object_iterate(_blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1333
      gen->rw_space()->object_iterate(_blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1334
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1335
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1336
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1337
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1338
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1339
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1340
// An ObjectClosure used to support the deprecated IterateOverHeap and
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1341
// IterateOverInstancesOfClass functions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1342
class IterateOverHeapObjectClosure: public ObjectClosure {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1343
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1344
  JvmtiTagMap* _tag_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1345
  KlassHandle _klass;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1346
  jvmtiHeapObjectFilter _object_filter;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1347
  jvmtiHeapObjectCallback _heap_object_callback;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1348
  const void* _user_data;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1349
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1350
  // accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1351
  JvmtiTagMap* tag_map() const                    { return _tag_map; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1352
  jvmtiHeapObjectFilter object_filter() const     { return _object_filter; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1353
  jvmtiHeapObjectCallback object_callback() const { return _heap_object_callback; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1354
  KlassHandle klass() const                       { return _klass; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1355
  const void* user_data() const                   { return _user_data; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1356
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1357
  // indicates if iteration has been aborted
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1358
  bool _iteration_aborted;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1359
  bool is_iteration_aborted() const               { return _iteration_aborted; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1360
  void set_iteration_aborted(bool aborted)        { _iteration_aborted = aborted; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1361
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1362
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1363
  IterateOverHeapObjectClosure(JvmtiTagMap* tag_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1364
                               KlassHandle klass,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1365
                               jvmtiHeapObjectFilter object_filter,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1366
                               jvmtiHeapObjectCallback heap_object_callback,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1367
                               const void* user_data) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1368
    _tag_map(tag_map),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1369
    _klass(klass),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1370
    _object_filter(object_filter),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1371
    _heap_object_callback(heap_object_callback),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1372
    _user_data(user_data),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1373
    _iteration_aborted(false)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1374
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1375
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1376
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1377
  void do_object(oop o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1378
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1379
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1380
// invoked for each object in the heap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1381
void IterateOverHeapObjectClosure::do_object(oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1382
  // check if iteration has been halted
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1383
  if (is_iteration_aborted()) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1384
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1385
  // ignore any objects that aren't visible to profiler
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1386
  if (!ServiceUtil::visible_oop(o)) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1387
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1388
  // instanceof check when filtering by klass
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1389
  if (!klass().is_null() && !o->is_a(klass()())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1390
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1391
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1392
  // prepare for the calllback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1393
  CallbackWrapper wrapper(tag_map(), o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1394
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1395
  // if the object is tagged and we're only interested in untagged objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1396
  // then don't invoke the callback. Similiarly, if the object is untagged
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1397
  // and we're only interested in tagged objects we skip the callback.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1398
  if (wrapper.obj_tag() != 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1399
    if (object_filter() == JVMTI_HEAP_OBJECT_UNTAGGED) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1400
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1401
    if (object_filter() == JVMTI_HEAP_OBJECT_TAGGED) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1402
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1403
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1404
  // invoke the agent's callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1405
  jvmtiIterationControl control = (*object_callback())(wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1406
                                                       wrapper.obj_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1407
                                                       wrapper.obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1408
                                                       (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1409
  if (control == JVMTI_ITERATION_ABORT) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1410
    set_iteration_aborted(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1411
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1412
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1413
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1414
// An ObjectClosure used to support the IterateThroughHeap function
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1415
class IterateThroughHeapObjectClosure: public ObjectClosure {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1416
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1417
  JvmtiTagMap* _tag_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1418
  KlassHandle _klass;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1419
  int _heap_filter;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1420
  const jvmtiHeapCallbacks* _callbacks;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1421
  const void* _user_data;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1422
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1423
  // accessor functions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1424
  JvmtiTagMap* tag_map() const                     { return _tag_map; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1425
  int heap_filter() const                          { return _heap_filter; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1426
  const jvmtiHeapCallbacks* callbacks() const      { return _callbacks; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1427
  KlassHandle klass() const                        { return _klass; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1428
  const void* user_data() const                    { return _user_data; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1429
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1430
  // indicates if the iteration has been aborted
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1431
  bool _iteration_aborted;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1432
  bool is_iteration_aborted() const                { return _iteration_aborted; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1433
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1434
  // used to check the visit control flags. If the abort flag is set
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1435
  // then we set the iteration aborted flag so that the iteration completes
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1436
  // without processing any further objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1437
  bool check_flags_for_abort(jint flags) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1438
    bool is_abort = (flags & JVMTI_VISIT_ABORT) != 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1439
    if (is_abort) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1440
      _iteration_aborted = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1441
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1442
    return is_abort;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1443
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1444
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1445
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1446
  IterateThroughHeapObjectClosure(JvmtiTagMap* tag_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1447
                                  KlassHandle klass,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1448
                                  int heap_filter,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1449
                                  const jvmtiHeapCallbacks* heap_callbacks,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1450
                                  const void* user_data) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1451
    _tag_map(tag_map),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1452
    _klass(klass),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1453
    _heap_filter(heap_filter),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1454
    _callbacks(heap_callbacks),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1455
    _user_data(user_data),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1456
    _iteration_aborted(false)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1457
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1458
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1459
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1460
  void do_object(oop o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1461
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1462
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1463
// invoked for each object in the heap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1464
void IterateThroughHeapObjectClosure::do_object(oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1465
  // check if iteration has been halted
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1466
  if (is_iteration_aborted()) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1467
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1468
  // ignore any objects that aren't visible to profiler
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1469
  if (!ServiceUtil::visible_oop(obj)) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1470
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1471
  // apply class filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1472
  if (is_filtered_by_klass_filter(obj, klass())) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1473
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1474
  // prepare for callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1475
  CallbackWrapper wrapper(tag_map(), obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1476
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1477
  // check if filtered by the heap filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1478
  if (is_filtered_by_heap_filter(wrapper.obj_tag(), wrapper.klass_tag(), heap_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1479
    return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1480
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1481
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1482
  // for arrays we need the length, otherwise -1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1483
  bool is_array = obj->is_array();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1484
  int len = is_array ? arrayOop(obj)->length() : -1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1485
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1486
  // invoke the object callback (if callback is provided)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1487
  if (callbacks()->heap_iteration_callback != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1488
    jvmtiHeapIterationCallback cb = callbacks()->heap_iteration_callback;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1489
    jint res = (*cb)(wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1490
                     wrapper.obj_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1491
                     wrapper.obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1492
                     (jint)len,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1493
                     (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1494
    if (check_flags_for_abort(res)) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1495
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1496
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1497
  // for objects and classes we report primitive fields if callback provided
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1498
  if (callbacks()->primitive_field_callback != NULL && obj->is_instance()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1499
    jint res;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1500
    jvmtiPrimitiveFieldCallback cb = callbacks()->primitive_field_callback;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1501
    if (obj->klass() == SystemDictionary::class_klass()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1502
      res = invoke_primitive_field_callback_for_static_fields(&wrapper,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1503
                                                                    obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1504
                                                                    cb,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1505
                                                                    (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1506
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1507
      res = invoke_primitive_field_callback_for_instance_fields(&wrapper,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1508
                                                                      obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1509
                                                                      cb,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1510
                                                                      (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1511
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1512
    if (check_flags_for_abort(res)) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1513
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1514
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1515
  // string callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1516
  if (!is_array &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1517
      callbacks()->string_primitive_value_callback != NULL &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1518
      obj->klass() == SystemDictionary::string_klass()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1519
    jint res = invoke_string_value_callback(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1520
                callbacks()->string_primitive_value_callback,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1521
                &wrapper,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1522
                obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1523
                (void*)user_data() );
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1524
    if (check_flags_for_abort(res)) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1525
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1526
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1527
  // array callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1528
  if (is_array &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1529
      callbacks()->array_primitive_value_callback != NULL &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1530
      obj->is_typeArray()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1531
    jint res = invoke_array_primitive_value_callback(
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1532
               callbacks()->array_primitive_value_callback,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1533
               &wrapper,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1534
               obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1535
               (void*)user_data() );
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1536
    if (check_flags_for_abort(res)) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1537
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1538
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1539
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1540
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1541
// Deprecated function to iterate over all objects in the heap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1542
void JvmtiTagMap::iterate_over_heap(jvmtiHeapObjectFilter object_filter,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1543
                                    KlassHandle klass,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1544
                                    jvmtiHeapObjectCallback heap_object_callback,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1545
                                    const void* user_data)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1546
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1547
  MutexLocker ml(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1548
  IterateOverHeapObjectClosure blk(this,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1549
                                   klass,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1550
                                   object_filter,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1551
                                   heap_object_callback,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1552
                                   user_data);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1553
  VM_HeapIterateOperation op(&blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1554
  VMThread::execute(&op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1555
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1556
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1557
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1558
// Iterates over all objects in the heap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1559
void JvmtiTagMap::iterate_through_heap(jint heap_filter,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1560
                                       KlassHandle klass,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1561
                                       const jvmtiHeapCallbacks* callbacks,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1562
                                       const void* user_data)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1563
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1564
  MutexLocker ml(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1565
  IterateThroughHeapObjectClosure blk(this,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1566
                                      klass,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1567
                                      heap_filter,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1568
                                      callbacks,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1569
                                      user_data);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1570
  VM_HeapIterateOperation op(&blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1571
  VMThread::execute(&op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1572
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1573
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1574
// support class for get_objects_with_tags
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1575
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1576
class TagObjectCollector : public JvmtiTagHashmapEntryClosure {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1577
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1578
  JvmtiEnv* _env;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1579
  jlong* _tags;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1580
  jint _tag_count;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1581
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1582
  GrowableArray<jobject>* _object_results;  // collected objects (JNI weak refs)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1583
  GrowableArray<uint64_t>* _tag_results;    // collected tags
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1584
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1585
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1586
  TagObjectCollector(JvmtiEnv* env, const jlong* tags, jint tag_count) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1587
    _env = env;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1588
    _tags = (jlong*)tags;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1589
    _tag_count = tag_count;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1590
    _object_results = new (ResourceObj::C_HEAP) GrowableArray<jobject>(1,true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1591
    _tag_results = new (ResourceObj::C_HEAP) GrowableArray<uint64_t>(1,true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1592
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1593
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1594
  ~TagObjectCollector() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1595
    delete _object_results;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1596
    delete _tag_results;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1597
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1598
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1599
  // for each tagged object check if the tag value matches
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1600
  // - if it matches then we create a JNI local reference to the object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1601
  // and record the reference and tag value.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1602
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1603
  void do_entry(JvmtiTagHashmapEntry* entry) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1604
    for (int i=0; i<_tag_count; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1605
      if (_tags[i] == entry->tag()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1606
        oop o = JNIHandles::resolve(entry->object());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1607
        assert(o != NULL && o != JNIHandles::deleted_handle(), "sanity check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1608
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1609
        // the mirror is tagged
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1610
        if (o->is_klass()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1611
          klassOop k = (klassOop)o;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1612
          o = Klass::cast(k)->java_mirror();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1613
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1614
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1615
        jobject ref = JNIHandles::make_local(JavaThread::current(), o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1616
        _object_results->append(ref);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1617
        _tag_results->append((uint64_t)entry->tag());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1618
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1619
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1620
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1621
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1622
  // return the results from the collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1623
  //
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1624
  jvmtiError result(jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1625
    jvmtiError error;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1626
    int count = _object_results->length();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1627
    assert(count >= 0, "sanity check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1628
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1629
    // if object_result_ptr is not NULL then allocate the result and copy
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1630
    // in the object references.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1631
    if (object_result_ptr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1632
      error = _env->Allocate(count * sizeof(jobject), (unsigned char**)object_result_ptr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1633
      if (error != JVMTI_ERROR_NONE) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1634
        return error;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1635
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1636
      for (int i=0; i<count; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1637
        (*object_result_ptr)[i] = _object_results->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1638
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1639
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1640
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1641
    // if tag_result_ptr is not NULL then allocate the result and copy
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1642
    // in the tag values.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1643
    if (tag_result_ptr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1644
      error = _env->Allocate(count * sizeof(jlong), (unsigned char**)tag_result_ptr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1645
      if (error != JVMTI_ERROR_NONE) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1646
        if (object_result_ptr != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1647
          _env->Deallocate((unsigned char*)object_result_ptr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1648
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1649
        return error;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1650
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1651
      for (int i=0; i<count; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1652
        (*tag_result_ptr)[i] = (jlong)_tag_results->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1653
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1654
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1655
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1656
    *count_ptr = count;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1657
    return JVMTI_ERROR_NONE;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1658
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1659
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1660
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1661
// return the list of objects with the specified tags
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1662
jvmtiError JvmtiTagMap::get_objects_with_tags(const jlong* tags,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1663
  jint count, jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1664
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1665
  TagObjectCollector collector(env(), tags, count);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1666
  {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1667
    // iterate over all tagged objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1668
    MutexLocker ml(lock());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1669
    entry_iterate(&collector);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1670
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1671
  return collector.result(count_ptr, object_result_ptr, tag_result_ptr);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1672
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1673
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1674
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1675
// ObjectMarker is used to support the marking objects when walking the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1676
// heap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1677
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1678
// This implementation uses the existing mark bits in an object for
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1679
// marking. Objects that are marked must later have their headers restored.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1680
// As most objects are unlocked and don't have their identity hash computed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1681
// we don't have to save their headers. Instead we save the headers that
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1682
// are "interesting". Later when the headers are restored this implementation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1683
// restores all headers to their initial value and then restores the few
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1684
// objects that had interesting headers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1685
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1686
// Future work: This implementation currently uses growable arrays to save
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1687
// the oop and header of interesting objects. As an optimization we could
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1688
// use the same technique as the GC and make use of the unused area
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1689
// between top() and end().
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1690
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1691
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1692
// An ObjectClosure used to restore the mark bits of an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1693
class RestoreMarksClosure : public ObjectClosure {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1694
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1695
  void do_object(oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1696
    if (o != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1697
      markOop mark = o->mark();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1698
      if (mark->is_marked()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1699
        o->init_mark();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1700
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1701
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1702
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1703
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1704
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1705
// ObjectMarker provides the mark and visited functions
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1706
class ObjectMarker : AllStatic {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1707
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1708
  // saved headers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1709
  static GrowableArray<oop>* _saved_oop_stack;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1710
  static GrowableArray<markOop>* _saved_mark_stack;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1711
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1712
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1713
  static void init();                       // initialize
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1714
  static void done();                       // clean-up
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1715
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1716
  static inline void mark(oop o);           // mark an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1717
  static inline bool visited(oop o);        // check if object has been visited
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1718
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1719
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1720
GrowableArray<oop>* ObjectMarker::_saved_oop_stack = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1721
GrowableArray<markOop>* ObjectMarker::_saved_mark_stack = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1722
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1723
// initialize ObjectMarker - prepares for object marking
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1724
void ObjectMarker::init() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1725
  assert(Thread::current()->is_VM_thread(), "must be VMThread");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1726
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1727
  // prepare heap for iteration
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1728
  Universe::heap()->ensure_parsability(false);  // no need to retire TLABs
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1729
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1730
  // create stacks for interesting headers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1731
  _saved_mark_stack = new (ResourceObj::C_HEAP) GrowableArray<markOop>(4000, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1732
  _saved_oop_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(4000, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1733
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1734
  if (UseBiasedLocking) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1735
    BiasedLocking::preserve_marks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1736
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1737
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1738
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1739
// Object marking is done so restore object headers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1740
void ObjectMarker::done() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1741
  // iterate over all objects and restore the mark bits to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1742
  // their initial value
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1743
  RestoreMarksClosure blk;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1744
  Universe::heap()->object_iterate(&blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1745
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1746
  // When sharing is enabled we need to restore the headers of the objects
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1747
  // in the readwrite space too.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1748
  if (UseSharedSpaces) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1749
    GenCollectedHeap* gch = GenCollectedHeap::heap();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1750
    CompactingPermGenGen* gen = (CompactingPermGenGen*)gch->perm_gen();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1751
    gen->rw_space()->object_iterate(&blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1752
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1753
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1754
  // now restore the interesting headers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1755
  for (int i = 0; i < _saved_oop_stack->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1756
    oop o = _saved_oop_stack->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1757
    markOop mark = _saved_mark_stack->at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1758
    o->set_mark(mark);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1759
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1760
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1761
  if (UseBiasedLocking) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1762
    BiasedLocking::restore_marks();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1763
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1764
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1765
  // free the stacks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1766
  delete _saved_oop_stack;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1767
  delete _saved_mark_stack;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1768
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1769
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1770
// mark an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1771
inline void ObjectMarker::mark(oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1772
  assert(Universe::heap()->is_in(o), "sanity check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1773
  assert(!o->mark()->is_marked(), "should only mark an object once");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1774
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1775
  // object's mark word
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1776
  markOop mark = o->mark();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1777
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1778
  if (mark->must_be_preserved(o)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1779
    _saved_mark_stack->push(mark);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1780
    _saved_oop_stack->push(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1781
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1782
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1783
  // mark the object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1784
  o->set_mark(markOopDesc::prototype()->set_marked());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1785
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1786
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1787
// return true if object is marked
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1788
inline bool ObjectMarker::visited(oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1789
  return o->mark()->is_marked();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1790
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1791
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1792
// Stack allocated class to help ensure that ObjectMarker is used
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1793
// correctly. Constructor initializes ObjectMarker, destructor calls
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1794
// ObjectMarker's done() function to restore object headers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1795
class ObjectMarkerController : public StackObj {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1796
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1797
  ObjectMarkerController() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1798
    ObjectMarker::init();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1799
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1800
  ~ObjectMarkerController() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1801
    ObjectMarker::done();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1802
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1803
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1804
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1805
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1806
// helper to map a jvmtiHeapReferenceKind to an old style jvmtiHeapRootKind
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1807
// (not performance critical as only used for roots)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1808
static jvmtiHeapRootKind toJvmtiHeapRootKind(jvmtiHeapReferenceKind kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1809
  switch (kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1810
    case JVMTI_HEAP_REFERENCE_JNI_GLOBAL:   return JVMTI_HEAP_ROOT_JNI_GLOBAL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1811
    case JVMTI_HEAP_REFERENCE_SYSTEM_CLASS: return JVMTI_HEAP_ROOT_SYSTEM_CLASS;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1812
    case JVMTI_HEAP_REFERENCE_MONITOR:      return JVMTI_HEAP_ROOT_MONITOR;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1813
    case JVMTI_HEAP_REFERENCE_STACK_LOCAL:  return JVMTI_HEAP_ROOT_STACK_LOCAL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1814
    case JVMTI_HEAP_REFERENCE_JNI_LOCAL:    return JVMTI_HEAP_ROOT_JNI_LOCAL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1815
    case JVMTI_HEAP_REFERENCE_THREAD:       return JVMTI_HEAP_ROOT_THREAD;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1816
    case JVMTI_HEAP_REFERENCE_OTHER:        return JVMTI_HEAP_ROOT_OTHER;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1817
    default: ShouldNotReachHere();          return JVMTI_HEAP_ROOT_OTHER;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1818
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1819
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1820
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1821
// Base class for all heap walk contexts. The base class maintains a flag
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1822
// to indicate if the context is valid or not.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1823
class HeapWalkContext VALUE_OBJ_CLASS_SPEC {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1824
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1825
  bool _valid;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1826
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1827
  HeapWalkContext(bool valid)                   { _valid = valid; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1828
  void invalidate()                             { _valid = false; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1829
  bool is_valid() const                         { return _valid; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1830
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1831
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1832
// A basic heap walk context for the deprecated heap walking functions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1833
// The context for a basic heap walk are the callbacks and fields used by
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1834
// the referrer caching scheme.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1835
class BasicHeapWalkContext: public HeapWalkContext {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1836
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1837
  jvmtiHeapRootCallback _heap_root_callback;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1838
  jvmtiStackReferenceCallback _stack_ref_callback;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1839
  jvmtiObjectReferenceCallback _object_ref_callback;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1840
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1841
  // used for caching
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1842
  oop _last_referrer;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1843
  jlong _last_referrer_tag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1844
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1845
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1846
  BasicHeapWalkContext() : HeapWalkContext(false) { }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1847
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1848
  BasicHeapWalkContext(jvmtiHeapRootCallback heap_root_callback,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1849
                       jvmtiStackReferenceCallback stack_ref_callback,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1850
                       jvmtiObjectReferenceCallback object_ref_callback) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1851
    HeapWalkContext(true),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1852
    _heap_root_callback(heap_root_callback),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1853
    _stack_ref_callback(stack_ref_callback),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1854
    _object_ref_callback(object_ref_callback),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1855
    _last_referrer(NULL),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1856
    _last_referrer_tag(0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1857
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1858
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1859
  // accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1860
  jvmtiHeapRootCallback heap_root_callback() const         { return _heap_root_callback; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1861
  jvmtiStackReferenceCallback stack_ref_callback() const   { return _stack_ref_callback; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1862
  jvmtiObjectReferenceCallback object_ref_callback() const { return _object_ref_callback;  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1863
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1864
  oop last_referrer() const               { return _last_referrer; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1865
  void set_last_referrer(oop referrer)    { _last_referrer = referrer; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1866
  jlong last_referrer_tag() const         { return _last_referrer_tag; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1867
  void set_last_referrer_tag(jlong value) { _last_referrer_tag = value; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1868
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1869
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1870
// The advanced heap walk context for the FollowReferences functions.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1871
// The context is the callbacks, and the fields used for filtering.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1872
class AdvancedHeapWalkContext: public HeapWalkContext {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1873
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1874
  jint _heap_filter;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1875
  KlassHandle _klass_filter;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1876
  const jvmtiHeapCallbacks* _heap_callbacks;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1877
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1878
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1879
  AdvancedHeapWalkContext() : HeapWalkContext(false) { }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1880
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1881
  AdvancedHeapWalkContext(jint heap_filter,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1882
                           KlassHandle klass_filter,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1883
                           const jvmtiHeapCallbacks* heap_callbacks) :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1884
    HeapWalkContext(true),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1885
    _heap_filter(heap_filter),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1886
    _klass_filter(klass_filter),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1887
    _heap_callbacks(heap_callbacks) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1888
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1889
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1890
  // accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1891
  jint heap_filter() const         { return _heap_filter; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1892
  KlassHandle klass_filter() const { return _klass_filter; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1893
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1894
  const jvmtiHeapReferenceCallback heap_reference_callback() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1895
    return _heap_callbacks->heap_reference_callback;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1896
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1897
  const jvmtiPrimitiveFieldCallback primitive_field_callback() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1898
    return _heap_callbacks->primitive_field_callback;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1899
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1900
  const jvmtiArrayPrimitiveValueCallback array_primitive_value_callback() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1901
    return _heap_callbacks->array_primitive_value_callback;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1902
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1903
  const jvmtiStringPrimitiveValueCallback string_primitive_value_callback() const {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1904
    return _heap_callbacks->string_primitive_value_callback;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1905
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1906
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1907
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1908
// The CallbackInvoker is a class with static functions that the heap walk can call
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1909
// into to invoke callbacks. It works in one of two modes. The "basic" mode is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1910
// used for the deprecated IterateOverReachableObjects functions. The "advanced"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1911
// mode is for the newer FollowReferences function which supports a lot of
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1912
// additional callbacks.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1913
class CallbackInvoker : AllStatic {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1914
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1915
  // heap walk styles
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1916
  enum { basic, advanced };
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1917
  static int _heap_walk_type;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1918
  static bool is_basic_heap_walk()           { return _heap_walk_type == basic; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1919
  static bool is_advanced_heap_walk()        { return _heap_walk_type == advanced; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1920
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1921
  // context for basic style heap walk
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1922
  static BasicHeapWalkContext _basic_context;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1923
  static BasicHeapWalkContext* basic_context() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1924
    assert(_basic_context.is_valid(), "invalid");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1925
    return &_basic_context;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1926
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1927
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1928
  // context for advanced style heap walk
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1929
  static AdvancedHeapWalkContext _advanced_context;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1930
  static AdvancedHeapWalkContext* advanced_context() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1931
    assert(_advanced_context.is_valid(), "invalid");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1932
    return &_advanced_context;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1933
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1934
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1935
  // context needed for all heap walks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1936
  static JvmtiTagMap* _tag_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1937
  static const void* _user_data;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1938
  static GrowableArray<oop>* _visit_stack;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1939
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1940
  // accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1941
  static JvmtiTagMap* tag_map()                        { return _tag_map; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1942
  static const void* user_data()                       { return _user_data; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1943
  static GrowableArray<oop>* visit_stack()             { return _visit_stack; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1944
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1945
  // if the object hasn't been visited then push it onto the visit stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1946
  // so that it will be visited later
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1947
  static inline bool check_for_visit(oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1948
    if (!ObjectMarker::visited(obj)) visit_stack()->push(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1949
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1950
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1951
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1952
  // invoke basic style callbacks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1953
  static inline bool invoke_basic_heap_root_callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1954
    (jvmtiHeapRootKind root_kind, oop obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1955
  static inline bool invoke_basic_stack_ref_callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1956
    (jvmtiHeapRootKind root_kind, jlong thread_tag, jint depth, jmethodID method,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1957
     int slot, oop obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1958
  static inline bool invoke_basic_object_reference_callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1959
    (jvmtiObjectReferenceKind ref_kind, oop referrer, oop referree, jint index);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1960
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1961
  // invoke advanced style callbacks
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1962
  static inline bool invoke_advanced_heap_root_callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1963
    (jvmtiHeapReferenceKind ref_kind, oop obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1964
  static inline bool invoke_advanced_stack_ref_callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1965
    (jvmtiHeapReferenceKind ref_kind, jlong thread_tag, jlong tid, int depth,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1966
     jmethodID method, jlocation bci, jint slot, oop obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1967
  static inline bool invoke_advanced_object_reference_callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1968
    (jvmtiHeapReferenceKind ref_kind, oop referrer, oop referree, jint index);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1969
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1970
  // used to report the value of primitive fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1971
  static inline bool report_primitive_field
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1972
    (jvmtiHeapReferenceKind ref_kind, oop obj, jint index, address addr, char type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1973
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1974
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1975
  // initialize for basic mode
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1976
  static void initialize_for_basic_heap_walk(JvmtiTagMap* tag_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1977
                                             GrowableArray<oop>* visit_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1978
                                             const void* user_data,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1979
                                             BasicHeapWalkContext context);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1980
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1981
  // initialize for advanced mode
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1982
  static void initialize_for_advanced_heap_walk(JvmtiTagMap* tag_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1983
                                                GrowableArray<oop>* visit_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1984
                                                const void* user_data,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1985
                                                AdvancedHeapWalkContext context);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1986
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1987
   // functions to report roots
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1988
  static inline bool report_simple_root(jvmtiHeapReferenceKind kind, oop o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1989
  static inline bool report_jni_local_root(jlong thread_tag, jlong tid, jint depth,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1990
    jmethodID m, oop o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1991
  static inline bool report_stack_ref_root(jlong thread_tag, jlong tid, jint depth,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1992
    jmethodID method, jlocation bci, jint slot, oop o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1993
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1994
  // functions to report references
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1995
  static inline bool report_array_element_reference(oop referrer, oop referree, jint index);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1996
  static inline bool report_class_reference(oop referrer, oop referree);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1997
  static inline bool report_class_loader_reference(oop referrer, oop referree);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1998
  static inline bool report_signers_reference(oop referrer, oop referree);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  1999
  static inline bool report_protection_domain_reference(oop referrer, oop referree);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2000
  static inline bool report_superclass_reference(oop referrer, oop referree);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2001
  static inline bool report_interface_reference(oop referrer, oop referree);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2002
  static inline bool report_static_field_reference(oop referrer, oop referree, jint slot);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2003
  static inline bool report_field_reference(oop referrer, oop referree, jint slot);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2004
  static inline bool report_constant_pool_reference(oop referrer, oop referree, jint index);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2005
  static inline bool report_primitive_array_values(oop array);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2006
  static inline bool report_string_value(oop str);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2007
  static inline bool report_primitive_instance_field(oop o, jint index, address value, char type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2008
  static inline bool report_primitive_static_field(oop o, jint index, address value, char type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2009
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2010
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2011
// statics
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2012
int CallbackInvoker::_heap_walk_type;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2013
BasicHeapWalkContext CallbackInvoker::_basic_context;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2014
AdvancedHeapWalkContext CallbackInvoker::_advanced_context;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2015
JvmtiTagMap* CallbackInvoker::_tag_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2016
const void* CallbackInvoker::_user_data;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2017
GrowableArray<oop>* CallbackInvoker::_visit_stack;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2018
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2019
// initialize for basic heap walk (IterateOverReachableObjects et al)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2020
void CallbackInvoker::initialize_for_basic_heap_walk(JvmtiTagMap* tag_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2021
                                                     GrowableArray<oop>* visit_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2022
                                                     const void* user_data,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2023
                                                     BasicHeapWalkContext context) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2024
  _tag_map = tag_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2025
  _visit_stack = visit_stack;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2026
  _user_data = user_data;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2027
  _basic_context = context;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2028
  _advanced_context.invalidate();       // will trigger assertion if used
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2029
  _heap_walk_type = basic;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2030
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2031
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2032
// initialize for advanced heap walk (FollowReferences)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2033
void CallbackInvoker::initialize_for_advanced_heap_walk(JvmtiTagMap* tag_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2034
                                                        GrowableArray<oop>* visit_stack,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2035
                                                        const void* user_data,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2036
                                                        AdvancedHeapWalkContext context) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2037
  _tag_map = tag_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2038
  _visit_stack = visit_stack;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2039
  _user_data = user_data;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2040
  _advanced_context = context;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2041
  _basic_context.invalidate();      // will trigger assertion if used
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2042
  _heap_walk_type = advanced;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2043
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2044
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2045
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2046
// invoke basic style heap root callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2047
inline bool CallbackInvoker::invoke_basic_heap_root_callback(jvmtiHeapRootKind root_kind, oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2048
  assert(ServiceUtil::visible_oop(obj), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2049
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2050
  // if we heap roots should be reported
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2051
  jvmtiHeapRootCallback cb = basic_context()->heap_root_callback();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2052
  if (cb == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2053
    return check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2054
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2055
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2056
  CallbackWrapper wrapper(tag_map(), obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2057
  jvmtiIterationControl control = (*cb)(root_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2058
                                        wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2059
                                        wrapper.obj_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2060
                                        wrapper.obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2061
                                        (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2062
  // push root to visit stack when following references
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2063
  if (control == JVMTI_ITERATION_CONTINUE &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2064
      basic_context()->object_ref_callback() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2065
    visit_stack()->push(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2066
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2067
  return control != JVMTI_ITERATION_ABORT;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2068
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2069
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2070
// invoke basic style stack ref callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2071
inline bool CallbackInvoker::invoke_basic_stack_ref_callback(jvmtiHeapRootKind root_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2072
                                                             jlong thread_tag,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2073
                                                             jint depth,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2074
                                                             jmethodID method,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2075
                                                             jint slot,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2076
                                                             oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2077
  assert(ServiceUtil::visible_oop(obj), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2078
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2079
  // if we stack refs should be reported
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2080
  jvmtiStackReferenceCallback cb = basic_context()->stack_ref_callback();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2081
  if (cb == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2082
    return check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2083
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2084
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2085
  CallbackWrapper wrapper(tag_map(), obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2086
  jvmtiIterationControl control = (*cb)(root_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2087
                                        wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2088
                                        wrapper.obj_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2089
                                        wrapper.obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2090
                                        thread_tag,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2091
                                        depth,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2092
                                        method,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2093
                                        slot,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2094
                                        (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2095
  // push root to visit stack when following references
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2096
  if (control == JVMTI_ITERATION_CONTINUE &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2097
      basic_context()->object_ref_callback() != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2098
    visit_stack()->push(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2099
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2100
  return control != JVMTI_ITERATION_ABORT;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2101
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2102
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2103
// invoke basic style object reference callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2104
inline bool CallbackInvoker::invoke_basic_object_reference_callback(jvmtiObjectReferenceKind ref_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2105
                                                                    oop referrer,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2106
                                                                    oop referree,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2107
                                                                    jint index) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2108
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2109
  assert(ServiceUtil::visible_oop(referrer), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2110
  assert(ServiceUtil::visible_oop(referree), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2111
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2112
  BasicHeapWalkContext* context = basic_context();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2113
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2114
  // callback requires the referrer's tag. If it's the same referrer
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2115
  // as the last call then we use the cached value.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2116
  jlong referrer_tag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2117
  if (referrer == context->last_referrer()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2118
    referrer_tag = context->last_referrer_tag();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2119
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2120
    referrer_tag = tag_for(tag_map(), klassOop_if_java_lang_Class(referrer));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2121
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2122
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2123
  // do the callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2124
  CallbackWrapper wrapper(tag_map(), referree);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2125
  jvmtiObjectReferenceCallback cb = context->object_ref_callback();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2126
  jvmtiIterationControl control = (*cb)(ref_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2127
                                        wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2128
                                        wrapper.obj_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2129
                                        wrapper.obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2130
                                        referrer_tag,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2131
                                        index,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2132
                                        (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2133
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2134
  // record referrer and referrer tag. For self-references record the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2135
  // tag value from the callback as this might differ from referrer_tag.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2136
  context->set_last_referrer(referrer);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2137
  if (referrer == referree) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2138
    context->set_last_referrer_tag(*wrapper.obj_tag_p());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2139
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2140
    context->set_last_referrer_tag(referrer_tag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2141
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2142
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2143
  if (control == JVMTI_ITERATION_CONTINUE) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2144
    return check_for_visit(referree);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2145
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2146
    return control != JVMTI_ITERATION_ABORT;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2147
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2148
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2149
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2150
// invoke advanced style heap root callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2151
inline bool CallbackInvoker::invoke_advanced_heap_root_callback(jvmtiHeapReferenceKind ref_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2152
                                                                oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2153
  assert(ServiceUtil::visible_oop(obj), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2154
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2155
  AdvancedHeapWalkContext* context = advanced_context();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2156
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2157
  // check that callback is provided
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2158
  jvmtiHeapReferenceCallback cb = context->heap_reference_callback();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2159
  if (cb == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2160
    return check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2161
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2162
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2163
  // apply class filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2164
  if (is_filtered_by_klass_filter(obj, context->klass_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2165
    return check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2166
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2167
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2168
  // setup the callback wrapper
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2169
  CallbackWrapper wrapper(tag_map(), obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2170
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2171
  // apply tag filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2172
  if (is_filtered_by_heap_filter(wrapper.obj_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2173
                                 wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2174
                                 context->heap_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2175
    return check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2176
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2177
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2178
  // for arrays we need the length, otherwise -1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2179
  jint len = (jint)(obj->is_array() ? arrayOop(obj)->length() : -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2180
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2181
  // invoke the callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2182
  jint res  = (*cb)(ref_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2183
                    NULL, // referrer info
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2184
                    wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2185
                    0,    // referrer_class_tag is 0 for heap root
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2186
                    wrapper.obj_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2187
                    wrapper.obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2188
                    NULL, // referrer_tag_p
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2189
                    len,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2190
                    (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2191
  if (res & JVMTI_VISIT_ABORT) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2192
    return false;// referrer class tag
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2193
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2194
  if (res & JVMTI_VISIT_OBJECTS) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2195
    check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2196
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2197
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2198
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2199
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2200
// report a reference from a thread stack to an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2201
inline bool CallbackInvoker::invoke_advanced_stack_ref_callback(jvmtiHeapReferenceKind ref_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2202
                                                                jlong thread_tag,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2203
                                                                jlong tid,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2204
                                                                int depth,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2205
                                                                jmethodID method,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2206
                                                                jlocation bci,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2207
                                                                jint slot,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2208
                                                                oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2209
  assert(ServiceUtil::visible_oop(obj), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2210
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2211
  AdvancedHeapWalkContext* context = advanced_context();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2212
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2213
  // check that callback is provider
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2214
  jvmtiHeapReferenceCallback cb = context->heap_reference_callback();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2215
  if (cb == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2216
    return check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2217
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2218
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2219
  // apply class filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2220
  if (is_filtered_by_klass_filter(obj, context->klass_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2221
    return check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2222
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2223
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2224
  // setup the callback wrapper
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2225
  CallbackWrapper wrapper(tag_map(), obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2226
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2227
  // apply tag filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2228
  if (is_filtered_by_heap_filter(wrapper.obj_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2229
                                 wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2230
                                 context->heap_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2231
    return check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2232
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2233
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2234
  // setup the referrer info
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2235
  jvmtiHeapReferenceInfo reference_info;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2236
  reference_info.stack_local.thread_tag = thread_tag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2237
  reference_info.stack_local.thread_id = tid;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2238
  reference_info.stack_local.depth = depth;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2239
  reference_info.stack_local.method = method;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2240
  reference_info.stack_local.location = bci;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2241
  reference_info.stack_local.slot = slot;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2242
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2243
  // for arrays we need the length, otherwise -1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2244
  jint len = (jint)(obj->is_array() ? arrayOop(obj)->length() : -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2245
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2246
  // call into the agent
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2247
  int res = (*cb)(ref_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2248
                  &reference_info,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2249
                  wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2250
                  0,    // referrer_class_tag is 0 for heap root (stack)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2251
                  wrapper.obj_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2252
                  wrapper.obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2253
                  NULL, // referrer_tag is 0 for root
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2254
                  len,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2255
                  (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2256
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2257
  if (res & JVMTI_VISIT_ABORT) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2258
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2259
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2260
  if (res & JVMTI_VISIT_OBJECTS) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2261
    check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2262
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2263
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2264
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2265
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2266
// This mask is used to pass reference_info to a jvmtiHeapReferenceCallback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2267
// only for ref_kinds defined by the JVM TI spec. Otherwise, NULL is passed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2268
#define REF_INFO_MASK  ((1 << JVMTI_HEAP_REFERENCE_FIELD)         \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2269
                      | (1 << JVMTI_HEAP_REFERENCE_STATIC_FIELD)  \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2270
                      | (1 << JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT) \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2271
                      | (1 << JVMTI_HEAP_REFERENCE_CONSTANT_POOL) \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2272
                      | (1 << JVMTI_HEAP_REFERENCE_STACK_LOCAL)   \
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2273
                      | (1 << JVMTI_HEAP_REFERENCE_JNI_LOCAL))
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2274
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2275
// invoke the object reference callback to report a reference
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2276
inline bool CallbackInvoker::invoke_advanced_object_reference_callback(jvmtiHeapReferenceKind ref_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2277
                                                                       oop referrer,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2278
                                                                       oop obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2279
                                                                       jint index)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2280
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2281
  // field index is only valid field in reference_info
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2282
  static jvmtiHeapReferenceInfo reference_info = { 0 };
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2283
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2284
  assert(ServiceUtil::visible_oop(referrer), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2285
  assert(ServiceUtil::visible_oop(obj), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2286
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2287
  AdvancedHeapWalkContext* context = advanced_context();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2288
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2289
  // check that callback is provider
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2290
  jvmtiHeapReferenceCallback cb = context->heap_reference_callback();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2291
  if (cb == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2292
    return check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2293
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2294
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2295
  // apply class filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2296
  if (is_filtered_by_klass_filter(obj, context->klass_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2297
    return check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2298
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2299
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2300
  // setup the callback wrapper
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2301
  TwoOopCallbackWrapper wrapper(tag_map(), referrer, obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2302
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2303
  // apply tag filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2304
  if (is_filtered_by_heap_filter(wrapper.obj_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2305
                                 wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2306
                                 context->heap_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2307
    return check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2308
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2309
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2310
  // field index is only valid field in reference_info
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2311
  reference_info.field.index = index;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2312
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2313
  // for arrays we need the length, otherwise -1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2314
  jint len = (jint)(obj->is_array() ? arrayOop(obj)->length() : -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2315
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2316
  // invoke the callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2317
  int res = (*cb)(ref_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2318
                  (REF_INFO_MASK & (1 << ref_kind)) ? &reference_info : NULL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2319
                  wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2320
                  wrapper.referrer_klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2321
                  wrapper.obj_size(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2322
                  wrapper.obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2323
                  wrapper.referrer_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2324
                  len,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2325
                  (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2326
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2327
  if (res & JVMTI_VISIT_ABORT) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2328
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2329
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2330
  if (res & JVMTI_VISIT_OBJECTS) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2331
    check_for_visit(obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2332
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2333
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2334
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2335
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2336
// report a "simple root"
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2337
inline bool CallbackInvoker::report_simple_root(jvmtiHeapReferenceKind kind, oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2338
  assert(kind != JVMTI_HEAP_REFERENCE_STACK_LOCAL &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2339
         kind != JVMTI_HEAP_REFERENCE_JNI_LOCAL, "not a simple root");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2340
  assert(ServiceUtil::visible_oop(obj), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2341
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2342
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2343
    // map to old style root kind
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2344
    jvmtiHeapRootKind root_kind = toJvmtiHeapRootKind(kind);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2345
    return invoke_basic_heap_root_callback(root_kind, obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2346
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2347
    assert(is_advanced_heap_walk(), "wrong heap walk type");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2348
    return invoke_advanced_heap_root_callback(kind, obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2349
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2350
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2351
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2352
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2353
// invoke the primitive array values
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2354
inline bool CallbackInvoker::report_primitive_array_values(oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2355
  assert(obj->is_typeArray(), "not a primitive array");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2356
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2357
  AdvancedHeapWalkContext* context = advanced_context();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2358
  assert(context->array_primitive_value_callback() != NULL, "no callback");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2359
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2360
  // apply class filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2361
  if (is_filtered_by_klass_filter(obj, context->klass_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2362
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2363
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2364
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2365
  CallbackWrapper wrapper(tag_map(), obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2366
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2367
  // apply tag filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2368
  if (is_filtered_by_heap_filter(wrapper.obj_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2369
                                 wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2370
                                 context->heap_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2371
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2372
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2373
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2374
  // invoke the callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2375
  int res = invoke_array_primitive_value_callback(context->array_primitive_value_callback(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2376
                                                  &wrapper,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2377
                                                  obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2378
                                                  (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2379
  return (!(res & JVMTI_VISIT_ABORT));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2380
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2381
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2382
// invoke the string value callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2383
inline bool CallbackInvoker::report_string_value(oop str) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2384
  assert(str->klass() == SystemDictionary::string_klass(), "not a string");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2385
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2386
  AdvancedHeapWalkContext* context = advanced_context();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2387
  assert(context->string_primitive_value_callback() != NULL, "no callback");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2388
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2389
  // apply class filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2390
  if (is_filtered_by_klass_filter(str, context->klass_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2391
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2392
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2393
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2394
  CallbackWrapper wrapper(tag_map(), str);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2395
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2396
  // apply tag filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2397
  if (is_filtered_by_heap_filter(wrapper.obj_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2398
                                 wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2399
                                 context->heap_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2400
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2401
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2402
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2403
  // invoke the callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2404
  int res = invoke_string_value_callback(context->string_primitive_value_callback(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2405
                                         &wrapper,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2406
                                         str,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2407
                                         (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2408
  return (!(res & JVMTI_VISIT_ABORT));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2409
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2410
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2411
// invoke the primitive field callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2412
inline bool CallbackInvoker::report_primitive_field(jvmtiHeapReferenceKind ref_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2413
                                                    oop obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2414
                                                    jint index,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2415
                                                    address addr,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2416
                                                    char type)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2417
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2418
  // for primitive fields only the index will be set
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2419
  static jvmtiHeapReferenceInfo reference_info = { 0 };
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2420
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2421
  AdvancedHeapWalkContext* context = advanced_context();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2422
  assert(context->primitive_field_callback() != NULL, "no callback");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2423
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2424
  // apply class filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2425
  if (is_filtered_by_klass_filter(obj, context->klass_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2426
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2427
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2428
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2429
  CallbackWrapper wrapper(tag_map(), obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2430
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2431
  // apply tag filter
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2432
  if (is_filtered_by_heap_filter(wrapper.obj_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2433
                                 wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2434
                                 context->heap_filter())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2435
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2436
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2437
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2438
  // the field index in the referrer
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2439
  reference_info.field.index = index;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2440
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2441
  // map the type
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2442
  jvmtiPrimitiveType value_type = (jvmtiPrimitiveType)type;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2443
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2444
  // setup the jvalue
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2445
  jvalue value;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2446
  copy_to_jvalue(&value, addr, value_type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2447
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2448
  jvmtiPrimitiveFieldCallback cb = context->primitive_field_callback();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2449
  int res = (*cb)(ref_kind,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2450
                  &reference_info,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2451
                  wrapper.klass_tag(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2452
                  wrapper.obj_tag_p(),
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2453
                  value,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2454
                  value_type,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2455
                  (void*)user_data());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2456
  return (!(res & JVMTI_VISIT_ABORT));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2457
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2458
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2459
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2460
// instance field
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2461
inline bool CallbackInvoker::report_primitive_instance_field(oop obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2462
                                                             jint index,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2463
                                                             address value,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2464
                                                             char type) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2465
  return report_primitive_field(JVMTI_HEAP_REFERENCE_FIELD,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2466
                                obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2467
                                index,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2468
                                value,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2469
                                type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2470
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2471
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2472
// static field
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2473
inline bool CallbackInvoker::report_primitive_static_field(oop obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2474
                                                           jint index,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2475
                                                           address value,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2476
                                                           char type) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2477
  return report_primitive_field(JVMTI_HEAP_REFERENCE_STATIC_FIELD,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2478
                                obj,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2479
                                index,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2480
                                value,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2481
                                type);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2482
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2483
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2484
// report a JNI local (root object) to the profiler
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2485
inline bool CallbackInvoker::report_jni_local_root(jlong thread_tag, jlong tid, jint depth, jmethodID m, oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2486
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2487
    return invoke_basic_stack_ref_callback(JVMTI_HEAP_ROOT_JNI_LOCAL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2488
                                           thread_tag,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2489
                                           depth,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2490
                                           m,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2491
                                           -1,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2492
                                           obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2493
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2494
    return invoke_advanced_stack_ref_callback(JVMTI_HEAP_REFERENCE_JNI_LOCAL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2495
                                              thread_tag, tid,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2496
                                              depth,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2497
                                              m,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2498
                                              (jlocation)-1,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2499
                                              -1,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2500
                                              obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2501
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2502
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2503
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2504
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2505
// report a local (stack reference, root object)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2506
inline bool CallbackInvoker::report_stack_ref_root(jlong thread_tag,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2507
                                                   jlong tid,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2508
                                                   jint depth,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2509
                                                   jmethodID method,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2510
                                                   jlocation bci,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2511
                                                   jint slot,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2512
                                                   oop obj) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2513
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2514
    return invoke_basic_stack_ref_callback(JVMTI_HEAP_ROOT_STACK_LOCAL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2515
                                           thread_tag,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2516
                                           depth,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2517
                                           method,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2518
                                           slot,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2519
                                           obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2520
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2521
    return invoke_advanced_stack_ref_callback(JVMTI_HEAP_REFERENCE_STACK_LOCAL,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2522
                                              thread_tag,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2523
                                              tid,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2524
                                              depth,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2525
                                              method,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2526
                                              bci,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2527
                                              slot,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2528
                                              obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2529
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2530
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2531
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2532
// report an object referencing a class.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2533
inline bool CallbackInvoker::report_class_reference(oop referrer, oop referree) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2534
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2535
    return invoke_basic_object_reference_callback(JVMTI_REFERENCE_CLASS, referrer, referree, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2536
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2537
    return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_CLASS, referrer, referree, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2538
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2539
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2540
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2541
// report a class referencing its class loader.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2542
inline bool CallbackInvoker::report_class_loader_reference(oop referrer, oop referree) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2543
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2544
    return invoke_basic_object_reference_callback(JVMTI_REFERENCE_CLASS_LOADER, referrer, referree, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2545
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2546
    return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_CLASS_LOADER, referrer, referree, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2547
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2548
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2549
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2550
// report a class referencing its signers.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2551
inline bool CallbackInvoker::report_signers_reference(oop referrer, oop referree) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2552
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2553
    return invoke_basic_object_reference_callback(JVMTI_REFERENCE_SIGNERS, referrer, referree, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2554
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2555
    return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_SIGNERS, referrer, referree, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2556
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2557
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2558
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2559
// report a class referencing its protection domain..
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2560
inline bool CallbackInvoker::report_protection_domain_reference(oop referrer, oop referree) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2561
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2562
    return invoke_basic_object_reference_callback(JVMTI_REFERENCE_PROTECTION_DOMAIN, referrer, referree, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2563
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2564
    return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_PROTECTION_DOMAIN, referrer, referree, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2565
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2566
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2567
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2568
// report a class referencing its superclass.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2569
inline bool CallbackInvoker::report_superclass_reference(oop referrer, oop referree) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2570
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2571
    // Send this to be consistent with past implementation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2572
    return invoke_basic_object_reference_callback(JVMTI_REFERENCE_CLASS, referrer, referree, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2573
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2574
    return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_SUPERCLASS, referrer, referree, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2575
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2576
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2577
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2578
// report a class referencing one of its interfaces.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2579
inline bool CallbackInvoker::report_interface_reference(oop referrer, oop referree) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2580
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2581
    return invoke_basic_object_reference_callback(JVMTI_REFERENCE_INTERFACE, referrer, referree, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2582
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2583
    return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_INTERFACE, referrer, referree, -1);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2584
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2585
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2586
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2587
// report a class referencing one of its static fields.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2588
inline bool CallbackInvoker::report_static_field_reference(oop referrer, oop referree, jint slot) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2589
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2590
    return invoke_basic_object_reference_callback(JVMTI_REFERENCE_STATIC_FIELD, referrer, referree, slot);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2591
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2592
    return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_STATIC_FIELD, referrer, referree, slot);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2593
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2594
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2595
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2596
// report an array referencing an element object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2597
inline bool CallbackInvoker::report_array_element_reference(oop referrer, oop referree, jint index) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2598
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2599
    return invoke_basic_object_reference_callback(JVMTI_REFERENCE_ARRAY_ELEMENT, referrer, referree, index);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2600
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2601
    return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT, referrer, referree, index);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2602
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2603
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2604
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2605
// report an object referencing an instance field object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2606
inline bool CallbackInvoker::report_field_reference(oop referrer, oop referree, jint slot) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2607
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2608
    return invoke_basic_object_reference_callback(JVMTI_REFERENCE_FIELD, referrer, referree, slot);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2609
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2610
    return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_FIELD, referrer, referree, slot);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2611
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2612
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2613
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2614
// report an array referencing an element object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2615
inline bool CallbackInvoker::report_constant_pool_reference(oop referrer, oop referree, jint index) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2616
  if (is_basic_heap_walk()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2617
    return invoke_basic_object_reference_callback(JVMTI_REFERENCE_CONSTANT_POOL, referrer, referree, index);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2618
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2619
    return invoke_advanced_object_reference_callback(JVMTI_HEAP_REFERENCE_CONSTANT_POOL, referrer, referree, index);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2620
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2621
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2622
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2623
// A supporting closure used to process simple roots
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2624
class SimpleRootsClosure : public OopClosure {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2625
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2626
  jvmtiHeapReferenceKind _kind;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2627
  bool _continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2628
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2629
  jvmtiHeapReferenceKind root_kind()    { return _kind; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2630
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2631
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2632
  void set_kind(jvmtiHeapReferenceKind kind) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2633
    _kind = kind;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2634
    _continue = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2635
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2636
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2637
  inline bool stopped() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2638
    return !_continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2639
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2640
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2641
  void do_oop(oop* obj_p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2642
    // iteration has terminated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2643
    if (stopped()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2644
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2645
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2646
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2647
    // ignore null or deleted handles
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2648
    oop o = *obj_p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2649
    if (o == NULL || o == JNIHandles::deleted_handle()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2650
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2651
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2652
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2653
    jvmtiHeapReferenceKind kind = root_kind();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2654
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2655
    // many roots are Klasses so we use the java mirror
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2656
    if (o->is_klass()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2657
      klassOop k = (klassOop)o;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2658
      o = Klass::cast(k)->java_mirror();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2659
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2660
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2661
      // SystemDictionary::always_strong_oops_do reports the application
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2662
      // class loader as a root. We want this root to be reported as
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2663
      // a root kind of "OTHER" rather than "SYSTEM_CLASS".
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2664
      if (o->is_instance() && root_kind() == JVMTI_HEAP_REFERENCE_SYSTEM_CLASS) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2665
        kind = JVMTI_HEAP_REFERENCE_OTHER;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2666
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2667
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2668
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2669
    // some objects are ignored - in the case of simple
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2670
    // roots it's mostly symbolOops that we are skipping
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2671
    // here.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2672
    if (!ServiceUtil::visible_oop(o)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2673
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2674
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2675
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2676
    // invoke the callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2677
    _continue = CallbackInvoker::report_simple_root(kind, o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2678
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2679
  }
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 1
diff changeset
  2680
  virtual void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2681
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2682
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2683
// A supporting closure used to process JNI locals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2684
class JNILocalRootsClosure : public OopClosure {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2685
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2686
  jlong _thread_tag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2687
  jlong _tid;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2688
  jint _depth;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2689
  jmethodID _method;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2690
  bool _continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2691
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2692
  void set_context(jlong thread_tag, jlong tid, jint depth, jmethodID method) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2693
    _thread_tag = thread_tag;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2694
    _tid = tid;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2695
    _depth = depth;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2696
    _method = method;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2697
    _continue = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2698
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2699
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2700
  inline bool stopped() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2701
    return !_continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2702
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2703
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2704
  void do_oop(oop* obj_p) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2705
    // iteration has terminated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2706
    if (stopped()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2707
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2708
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2709
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2710
    // ignore null or deleted handles
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2711
    oop o = *obj_p;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2712
    if (o == NULL || o == JNIHandles::deleted_handle()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2713
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2714
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2715
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2716
    if (!ServiceUtil::visible_oop(o)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2717
      return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2718
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2719
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2720
    // invoke the callback
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2721
    _continue = CallbackInvoker::report_jni_local_root(_thread_tag, _tid, _depth, _method, o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2722
  }
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 1
diff changeset
  2723
  virtual void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); }
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2724
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2725
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2726
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2727
// A VM operation to iterate over objects that are reachable from
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2728
// a set of roots or an initial object.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2729
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2730
// For VM_HeapWalkOperation the set of roots used is :-
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2731
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2732
// - All JNI global references
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2733
// - All inflated monitors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2734
// - All classes loaded by the boot class loader (or all classes
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2735
//     in the event that class unloading is disabled)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2736
// - All java threads
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2737
// - For each java thread then all locals and JNI local references
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2738
//      on the thread's execution stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2739
// - All visible/explainable objects from Universes::oops_do
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2740
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2741
class VM_HeapWalkOperation: public VM_Operation {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2742
 private:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2743
  enum {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2744
    initial_visit_stack_size = 4000
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2745
  };
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2746
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2747
  bool _is_advanced_heap_walk;                      // indicates FollowReferences
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2748
  JvmtiTagMap* _tag_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2749
  Handle _initial_object;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2750
  GrowableArray<oop>* _visit_stack;                 // the visit stack
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2751
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2752
  bool _collecting_heap_roots;                      // are we collecting roots
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2753
  bool _following_object_refs;                      // are we following object references
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2754
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2755
  bool _reporting_primitive_fields;                 // optional reporting
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2756
  bool _reporting_primitive_array_values;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2757
  bool _reporting_string_values;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2758
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2759
  GrowableArray<oop>* create_visit_stack() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2760
    return new (ResourceObj::C_HEAP) GrowableArray<oop>(initial_visit_stack_size, true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2761
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2762
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2763
  // accessors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2764
  bool is_advanced_heap_walk() const               { return _is_advanced_heap_walk; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2765
  JvmtiTagMap* tag_map() const                     { return _tag_map; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2766
  Handle initial_object() const                    { return _initial_object; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2767
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2768
  bool is_following_references() const             { return _following_object_refs; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2769
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2770
  bool is_reporting_primitive_fields()  const      { return _reporting_primitive_fields; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2771
  bool is_reporting_primitive_array_values() const { return _reporting_primitive_array_values; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2772
  bool is_reporting_string_values() const          { return _reporting_string_values; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2773
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2774
  GrowableArray<oop>* visit_stack() const          { return _visit_stack; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2775
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2776
  // iterate over the various object types
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2777
  inline bool iterate_over_array(oop o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2778
  inline bool iterate_over_type_array(oop o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2779
  inline bool iterate_over_class(klassOop o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2780
  inline bool iterate_over_object(oop o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2781
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2782
  // root collection
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2783
  inline bool collect_simple_roots();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2784
  inline bool collect_stack_roots();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2785
  inline bool collect_stack_roots(JavaThread* java_thread, JNILocalRootsClosure* blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2786
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2787
  // visit an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2788
  inline bool visit(oop o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2789
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2790
 public:
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2791
  VM_HeapWalkOperation(JvmtiTagMap* tag_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2792
                       Handle initial_object,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2793
                       BasicHeapWalkContext callbacks,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2794
                       const void* user_data);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2795
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2796
  VM_HeapWalkOperation(JvmtiTagMap* tag_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2797
                       Handle initial_object,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2798
                       AdvancedHeapWalkContext callbacks,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2799
                       const void* user_data);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2800
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2801
  ~VM_HeapWalkOperation();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2802
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2803
  VMOp_Type type() const { return VMOp_HeapWalkOperation; }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2804
  void doit();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2805
};
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2806
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2807
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2808
VM_HeapWalkOperation::VM_HeapWalkOperation(JvmtiTagMap* tag_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2809
                                           Handle initial_object,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2810
                                           BasicHeapWalkContext callbacks,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2811
                                           const void* user_data) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2812
  _is_advanced_heap_walk = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2813
  _tag_map = tag_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2814
  _initial_object = initial_object;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2815
  _following_object_refs = (callbacks.object_ref_callback() != NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2816
  _reporting_primitive_fields = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2817
  _reporting_primitive_array_values = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2818
  _reporting_string_values = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2819
  _visit_stack = create_visit_stack();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2820
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2821
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2822
  CallbackInvoker::initialize_for_basic_heap_walk(tag_map, _visit_stack, user_data, callbacks);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2823
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2824
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2825
VM_HeapWalkOperation::VM_HeapWalkOperation(JvmtiTagMap* tag_map,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2826
                                           Handle initial_object,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2827
                                           AdvancedHeapWalkContext callbacks,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2828
                                           const void* user_data) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2829
  _is_advanced_heap_walk = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2830
  _tag_map = tag_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2831
  _initial_object = initial_object;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2832
  _following_object_refs = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2833
  _reporting_primitive_fields = (callbacks.primitive_field_callback() != NULL);;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2834
  _reporting_primitive_array_values = (callbacks.array_primitive_value_callback() != NULL);;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2835
  _reporting_string_values = (callbacks.string_primitive_value_callback() != NULL);;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2836
  _visit_stack = create_visit_stack();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2837
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2838
  CallbackInvoker::initialize_for_advanced_heap_walk(tag_map, _visit_stack, user_data, callbacks);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2839
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2840
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2841
VM_HeapWalkOperation::~VM_HeapWalkOperation() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2842
  if (_following_object_refs) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2843
    assert(_visit_stack != NULL, "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2844
    delete _visit_stack;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2845
    _visit_stack = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2846
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2847
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2848
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2849
// an array references its class and has a reference to
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2850
// each element in the array
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2851
inline bool VM_HeapWalkOperation::iterate_over_array(oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2852
  objArrayOop array = objArrayOop(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2853
  if (array->klass() == Universe::systemObjArrayKlassObj()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2854
    // filtered out
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2855
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2856
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2857
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2858
  // array reference to its class
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2859
  oop mirror = objArrayKlass::cast(array->klass())->java_mirror();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2860
  if (!CallbackInvoker::report_class_reference(o, mirror)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2861
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2862
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2863
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2864
  // iterate over the array and report each reference to a
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2865
  // non-null element
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2866
  for (int index=0; index<array->length(); index++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2867
    oop elem = array->obj_at(index);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2868
    if (elem == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2869
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2870
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2871
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2872
    // report the array reference o[index] = elem
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2873
    if (!CallbackInvoker::report_array_element_reference(o, elem, index)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2874
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2875
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2876
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2877
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2878
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2879
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2880
// a type array references its class
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2881
inline bool VM_HeapWalkOperation::iterate_over_type_array(oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2882
  klassOop k = o->klass();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2883
  oop mirror = Klass::cast(k)->java_mirror();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2884
  if (!CallbackInvoker::report_class_reference(o, mirror)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2885
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2886
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2887
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2888
  // report the array contents if required
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2889
  if (is_reporting_primitive_array_values()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2890
    if (!CallbackInvoker::report_primitive_array_values(o)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2891
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2892
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2893
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2894
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2895
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2896
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2897
// verify that a static oop field is in range
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 1
diff changeset
  2898
static inline bool verify_static_oop(instanceKlass* ik,
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 1
diff changeset
  2899
                                     klassOop k, int offset) {
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 1
diff changeset
  2900
  address obj_p = (address)k + offset;
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 1
diff changeset
  2901
  address start = (address)ik->start_of_static_fields();
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 1
diff changeset
  2902
  address end = start + (ik->static_oop_field_size() * heapOopSize);
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2903
  assert(end >= start, "sanity check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2904
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2905
  if (obj_p >= start && obj_p < end) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2906
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2907
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2908
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2909
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2910
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2911
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2912
// a class references its super class, interfaces, class loader, ...
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2913
// and finally its static fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2914
inline bool VM_HeapWalkOperation::iterate_over_class(klassOop k) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2915
  int i;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2916
  Klass* klass = klassOop(k)->klass_part();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2917
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2918
  if (klass->oop_is_instance()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2919
    instanceKlass* ik = instanceKlass::cast(k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2920
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2921
    // ignore the class if it's has been initialized yet
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2922
    if (!ik->is_linked()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2923
      return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2924
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2925
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2926
    // get the java mirror
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2927
    oop mirror = klass->java_mirror();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2928
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2929
    // super (only if something more interesting than java.lang.Object)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2930
    klassOop java_super = ik->java_super();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2931
    if (java_super != NULL && java_super != SystemDictionary::object_klass()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2932
      oop super = Klass::cast(java_super)->java_mirror();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2933
      if (!CallbackInvoker::report_superclass_reference(mirror, super)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2934
        return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2935
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2936
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2937
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2938
    // class loader
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2939
    oop cl = ik->class_loader();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2940
    if (cl != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2941
      if (!CallbackInvoker::report_class_loader_reference(mirror, cl)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2942
        return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2943
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2944
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2945
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2946
    // protection domain
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2947
    oop pd = ik->protection_domain();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2948
    if (pd != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2949
      if (!CallbackInvoker::report_protection_domain_reference(mirror, pd)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2950
        return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2951
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2952
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2953
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2954
    // signers
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2955
    oop signers = ik->signers();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2956
    if (signers != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2957
      if (!CallbackInvoker::report_signers_reference(mirror, signers)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2958
        return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2959
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2960
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2961
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2962
    // references from the constant pool
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2963
    {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2964
      const constantPoolOop pool = ik->constants();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2965
      for (int i = 1; i < pool->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2966
        constantTag tag = pool->tag_at(i).value();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2967
        if (tag.is_string() || tag.is_klass()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2968
          oop entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2969
          if (tag.is_string()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2970
            entry = pool->resolved_string_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2971
            assert(java_lang_String::is_instance(entry), "must be string");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2972
          } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2973
            entry = Klass::cast(pool->resolved_klass_at(i))->java_mirror();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2974
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2975
          if (!CallbackInvoker::report_constant_pool_reference(mirror, entry, (jint)i)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2976
            return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2977
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2978
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2979
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2980
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2981
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2982
    // interfaces
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2983
    // (These will already have been reported as references from the constant pool
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2984
    //  but are specified by IterateOverReachableObjects and must be reported).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2985
    objArrayOop interfaces = ik->local_interfaces();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2986
    for (i = 0; i < interfaces->length(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2987
      oop interf = Klass::cast((klassOop)interfaces->obj_at(i))->java_mirror();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2988
      if (interf == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2989
        continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2990
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2991
      if (!CallbackInvoker::report_interface_reference(mirror, interf)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2992
        return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2993
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2994
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2995
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2996
    // iterate over the static fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2997
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2998
    ClassFieldMap* field_map = ClassFieldMap::create_map_of_static_fields(k);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  2999
    for (i=0; i<field_map->field_count(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3000
      ClassFieldDescriptor* field = field_map->field_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3001
      char type = field->field_type();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3002
      if (!is_primitive_field_type(type)) {
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 1
diff changeset
  3003
        oop fld_o = k->obj_field(field->field_offset());
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 1
diff changeset
  3004
        assert(verify_static_oop(ik, k, field->field_offset()), "sanity check");
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3005
        if (fld_o != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3006
          int slot = field->field_index();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3007
          if (!CallbackInvoker::report_static_field_reference(mirror, fld_o, slot)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3008
            delete field_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3009
            return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3010
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3011
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3012
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3013
         if (is_reporting_primitive_fields()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3014
           address addr = (address)k + field->field_offset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3015
           int slot = field->field_index();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3016
           if (!CallbackInvoker::report_primitive_static_field(mirror, slot, addr, type)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3017
             delete field_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3018
             return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3019
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3020
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3021
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3022
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3023
    delete field_map;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3024
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3025
    return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3026
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3027
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3028
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3029
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3030
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3031
// an object references a class and its instance fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3032
// (static fields are ignored here as we report these as
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3033
// references from the class).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3034
inline bool VM_HeapWalkOperation::iterate_over_object(oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3035
  // reference to the class
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3036
  if (!CallbackInvoker::report_class_reference(o, Klass::cast(o->klass())->java_mirror())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3037
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3038
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3039
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3040
  // iterate over instance fields
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3041
  ClassFieldMap* field_map = JvmtiCachedClassFieldMap::get_map_of_instance_fields(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3042
  for (int i=0; i<field_map->field_count(); i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3043
    ClassFieldDescriptor* field = field_map->field_at(i);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3044
    char type = field->field_type();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3045
    if (!is_primitive_field_type(type)) {
360
21d113ecbf6a 6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents: 1
diff changeset
  3046
      oop fld_o = o->obj_field(field->field_offset());
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3047
      if (fld_o != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3048
        // reflection code may have a reference to a klassOop.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3049
        // - see sun.reflect.UnsafeStaticFieldAccessorImpl and sun.misc.Unsafe
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3050
        if (fld_o->is_klass()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3051
          klassOop k = (klassOop)fld_o;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3052
          fld_o = Klass::cast(k)->java_mirror();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3053
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3054
        int slot = field->field_index();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3055
        if (!CallbackInvoker::report_field_reference(o, fld_o, slot)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3056
          return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3057
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3058
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3059
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3060
      if (is_reporting_primitive_fields()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3061
        // primitive instance field
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3062
        address addr = (address)o + field->field_offset();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3063
        int slot = field->field_index();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3064
        if (!CallbackInvoker::report_primitive_instance_field(o, slot, addr, type)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3065
          return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3066
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3067
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3068
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3069
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3070
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3071
  // if the object is a java.lang.String
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3072
  if (is_reporting_string_values() &&
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3073
      o->klass() == SystemDictionary::string_klass()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3074
    if (!CallbackInvoker::report_string_value(o)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3075
      return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3076
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3077
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3078
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3079
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3080
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3081
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3082
// collects all simple (non-stack) roots.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3083
// if there's a heap root callback provided then the callback is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3084
// invoked for each simple root.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3085
// if an object reference callback is provided then all simple
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3086
// roots are pushed onto the marking stack so that they can be
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3087
// processed later
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3088
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3089
inline bool VM_HeapWalkOperation::collect_simple_roots() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3090
  SimpleRootsClosure blk;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3091
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3092
  // JNI globals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3093
  blk.set_kind(JVMTI_HEAP_REFERENCE_JNI_GLOBAL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3094
  JNIHandles::oops_do(&blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3095
  if (blk.stopped()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3096
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3097
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3098
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3099
  // Preloaded classes and loader from the system dictionary
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3100
  blk.set_kind(JVMTI_HEAP_REFERENCE_SYSTEM_CLASS);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3101
  SystemDictionary::always_strong_oops_do(&blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3102
  if (blk.stopped()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3103
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3104
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3105
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3106
  // Inflated monitors
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3107
  blk.set_kind(JVMTI_HEAP_REFERENCE_MONITOR);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3108
  ObjectSynchronizer::oops_do(&blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3109
  if (blk.stopped()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3110
    return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3111
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3112
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3113
  // Threads
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3114
  for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3115
    oop threadObj = thread->threadObj();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3116
    if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3117
      bool cont = CallbackInvoker::report_simple_root(JVMTI_HEAP_REFERENCE_THREAD, threadObj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3118
      if (!cont) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3119
        return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3120
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3121
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3122
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3123
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3124
  // Other kinds of roots maintained by HotSpot
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3125
  // Many of these won't be visible but others (such as instances of important
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3126
  // exceptions) will be visible.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3127
  blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3128
  Universe::oops_do(&blk);
3908
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2105
diff changeset
  3129
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2105
diff changeset
  3130
  // If there are any non-perm roots in the code cache, visit them.
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2105
diff changeset
  3131
  blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER);
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2105
diff changeset
  3132
  CodeBlobToOopClosure look_in_blobs(&blk, false);
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2105
diff changeset
  3133
  CodeCache::scavenge_root_nmethods_do(&look_in_blobs);
24b55ad4c228 6863023: need non-perm oops in code cache for JSR 292
jrose
parents: 2105
diff changeset
  3134
1
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3135
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3136
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3137
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3138
// Walk the stack of a given thread and find all references (locals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3139
// and JNI calls) and report these as stack references
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3140
inline bool VM_HeapWalkOperation::collect_stack_roots(JavaThread* java_thread,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3141
                                                      JNILocalRootsClosure* blk)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3142
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3143
  oop threadObj = java_thread->threadObj();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3144
  assert(threadObj != NULL, "sanity check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3145
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3146
  // only need to get the thread's tag once per thread
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3147
  jlong thread_tag = tag_for(_tag_map, threadObj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3148
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3149
  // also need the thread id
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3150
  jlong tid = java_lang_Thread::thread_id(threadObj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3151
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3152
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3153
  if (java_thread->has_last_Java_frame()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3154
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3155
    // vframes are resource allocated
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3156
    Thread* current_thread = Thread::current();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3157
    ResourceMark rm(current_thread);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3158
    HandleMark hm(current_thread);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3159
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3160
    RegisterMap reg_map(java_thread);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3161
    frame f = java_thread->last_frame();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3162
    vframe* vf = vframe::new_vframe(&f, &reg_map, java_thread);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3163
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3164
    bool is_top_frame = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3165
    int depth = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3166
    frame* last_entry_frame = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3167
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3168
    while (vf != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3169
      if (vf->is_java_frame()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3170
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3171
        // java frame (interpreted, compiled, ...)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3172
        javaVFrame *jvf = javaVFrame::cast(vf);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3173
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3174
        // the jmethodID
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3175
        jmethodID method = jvf->method()->jmethod_id();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3176
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3177
        if (!(jvf->method()->is_native())) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3178
          jlocation bci = (jlocation)jvf->bci();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3179
          StackValueCollection* locals = jvf->locals();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3180
          for (int slot=0; slot<locals->size(); slot++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3181
            if (locals->at(slot)->type() == T_OBJECT) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3182
              oop o = locals->obj_at(slot)();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3183
              if (o == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3184
                continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3185
              }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3186
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3187
              // stack reference
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3188
              if (!CallbackInvoker::report_stack_ref_root(thread_tag, tid, depth, method,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3189
                                                   bci, slot, o)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3190
                return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3191
              }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3192
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3193
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3194
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3195
          blk->set_context(thread_tag, tid, depth, method);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3196
          if (is_top_frame) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3197
            // JNI locals for the top frame.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3198
            java_thread->active_handles()->oops_do(blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3199
          } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3200
            if (last_entry_frame != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3201
              // JNI locals for the entry frame
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3202
              assert(last_entry_frame->is_entry_frame(), "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3203
              last_entry_frame->entry_frame_call_wrapper()->handles()->oops_do(blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3204
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3205
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3206
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3207
        last_entry_frame = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3208
        depth++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3209
      } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3210
        // externalVFrame - for an entry frame then we report the JNI locals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3211
        // when we find the corresponding javaVFrame
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3212
        frame* fr = vf->frame_pointer();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3213
        assert(fr != NULL, "sanity check");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3214
        if (fr->is_entry_frame()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3215
          last_entry_frame = fr;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3216
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3217
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3218
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3219
      vf = vf->sender();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3220
      is_top_frame = false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3221
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3222
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3223
    // no last java frame but there may be JNI locals
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3224
    blk->set_context(thread_tag, tid, 0, (jmethodID)NULL);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3225
    java_thread->active_handles()->oops_do(blk);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3226
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3227
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3228
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3229
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3230
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3231
// collects all stack roots - for each thread it walks the execution
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3232
// stack to find all references and local JNI refs.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3233
inline bool VM_HeapWalkOperation::collect_stack_roots() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3234
  JNILocalRootsClosure blk;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3235
  for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3236
    oop threadObj = thread->threadObj();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3237
    if (threadObj != NULL && !thread->is_exiting() && !thread->is_hidden_from_external_view()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3238
      if (!collect_stack_roots(thread, &blk)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3239
        return false;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3240
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3241
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3242
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3243
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3244
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3245
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3246
// visit an object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3247
// first mark the object as visited
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3248
// second get all the outbound references from this object (in other words, all
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3249
// the objects referenced by this object).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3250
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3251
bool VM_HeapWalkOperation::visit(oop o) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3252
  // mark object as visited
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3253
  assert(!ObjectMarker::visited(o), "can't visit same object more than once");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3254
  ObjectMarker::mark(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3255
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3256
  // instance
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3257
  if (o->is_instance()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3258
    if (o->klass() == SystemDictionary::class_klass()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3259
      o = klassOop_if_java_lang_Class(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3260
      if (o->is_klass()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3261
        // a java.lang.Class
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3262
        return iterate_over_class(klassOop(o));
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3263
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3264
    } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3265
      return iterate_over_object(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3266
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3267
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3268
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3269
  // object array
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3270
  if (o->is_objArray()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3271
    return iterate_over_array(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3272
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3273
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3274
  // type array
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3275
  if (o->is_typeArray()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3276
    return iterate_over_type_array(o);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3277
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3278
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3279
  return true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3280
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3281
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3282
void VM_HeapWalkOperation::doit() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3283
  ResourceMark rm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3284
  ObjectMarkerController marker;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3285
  ClassFieldMapCacheMark cm;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3286
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3287
  assert(visit_stack()->is_empty(), "visit stack must be empty");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3288
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3289
  // the heap walk starts with an initial object or the heap roots
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3290
  if (initial_object().is_null()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3291
    if (!collect_simple_roots()) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3292
    if (!collect_stack_roots()) return;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3293
  } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3294
    visit_stack()->push(initial_object()());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3295
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3296
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3297
  // object references required
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3298
  if (is_following_references()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3299
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3300
    // visit each object until all reachable objects have been
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3301
    // visited or the callback asked to terminate the iteration.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3302
    while (!visit_stack()->is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3303
      oop o = visit_stack()->pop();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3304
      if (!ObjectMarker::visited(o)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3305
        if (!visit(o)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3306
          break;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3307
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3308
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3309
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3310
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3311
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3312
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3313
// iterate over all objects that are reachable from a set of roots
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3314
void JvmtiTagMap::iterate_over_reachable_objects(jvmtiHeapRootCallback heap_root_callback,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3315
                                                 jvmtiStackReferenceCallback stack_ref_callback,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3316
                                                 jvmtiObjectReferenceCallback object_ref_callback,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3317
                                                 const void* user_data) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3318
  MutexLocker ml(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3319
  BasicHeapWalkContext context(heap_root_callback, stack_ref_callback, object_ref_callback);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3320
  VM_HeapWalkOperation op(this, Handle(), context, user_data);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3321
  VMThread::execute(&op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3322
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3323
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3324
// iterate over all objects that are reachable from a given object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3325
void JvmtiTagMap::iterate_over_objects_reachable_from_object(jobject object,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3326
                                                             jvmtiObjectReferenceCallback object_ref_callback,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3327
                                                             const void* user_data) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3328
  oop obj = JNIHandles::resolve(object);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3329
  Handle initial_object(Thread::current(), obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3330
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3331
  MutexLocker ml(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3332
  BasicHeapWalkContext context(NULL, NULL, object_ref_callback);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3333
  VM_HeapWalkOperation op(this, initial_object, context, user_data);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3334
  VMThread::execute(&op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3335
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3336
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3337
// follow references from an initial object or the GC roots
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3338
void JvmtiTagMap::follow_references(jint heap_filter,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3339
                                    KlassHandle klass,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3340
                                    jobject object,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3341
                                    const jvmtiHeapCallbacks* callbacks,
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3342
                                    const void* user_data)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3343
{
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3344
  oop obj = JNIHandles::resolve(object);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3345
  Handle initial_object(Thread::current(), obj);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3346
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3347
  MutexLocker ml(Heap_lock);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3348
  AdvancedHeapWalkContext context(heap_filter, klass, callbacks);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3349
  VM_HeapWalkOperation op(this, initial_object, context, user_data);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3350
  VMThread::execute(&op);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3351
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3352
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3353
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3354
// called post-GC
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3355
// - for each JVMTI environment with an object tag map, call its rehash
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3356
// function to re-sync with the new object locations.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3357
void JvmtiTagMap::gc_epilogue(bool full) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3358
  assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3359
  if (JvmtiEnv::environments_might_exist()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3360
    // re-obtain the memory region for the young generation (might
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3361
    // changed due to adaptive resizing policy)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3362
    get_young_generation();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3363
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3364
    JvmtiEnvIterator it;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3365
    for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3366
      JvmtiTagMap* tag_map = env->tag_map();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3367
      if (tag_map != NULL && !tag_map->is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3368
        TraceTime t(full ? "JVMTI Full Rehash " : "JVMTI Rehash ", TraceJVMTIObjectTagging);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3369
        if (full) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3370
          tag_map->rehash(0, n_hashmaps);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3371
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3372
          tag_map->rehash(0, 0);        // tag map for young gen only
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3373
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3374
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3375
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3376
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3377
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3378
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3379
// CMS has completed referencing processing so we may have JNI weak refs
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3380
// to objects in the CMS generation that have been GC'ed.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3381
void JvmtiTagMap::cms_ref_processing_epilogue() {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3382
  assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3383
  assert(UseConcMarkSweepGC, "should only be used with CMS");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3384
  if (JvmtiEnv::environments_might_exist()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3385
    JvmtiEnvIterator it;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3386
    for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3387
      JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3388
      if (tag_map != NULL && !tag_map->is_empty()) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3389
        TraceTime t("JVMTI Rehash (CMS) ", TraceJVMTIObjectTagging);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3390
        tag_map->rehash(1, n_hashmaps);    // assume CMS not used in young gen
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3391
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3392
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3393
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3394
}
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3395
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3396
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3397
// For each entry in the hashmaps 'start' to 'end' :
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3398
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3399
// 1. resolve the JNI weak reference
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3400
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3401
// 2. If it resolves to NULL it means the object has been freed so the entry
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3402
//    is removed, the weak reference destroyed, and the object free event is
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3403
//    posted (if enabled).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3404
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3405
// 3. If the weak reference resolves to an object then we re-hash the object
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3406
//    to see if it has moved or has been promoted (from the young to the old
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3407
//    generation for example).
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3408
//
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3409
void JvmtiTagMap::rehash(int start, int end) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3410
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3411
  // does this environment have the OBJECT_FREE event enabled
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3412
  bool post_object_free = env()->is_enabled(JVMTI_EVENT_OBJECT_FREE);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3413
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3414
  // counters used for trace message
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3415
  int freed = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3416
  int moved = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3417
  int promoted = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3418
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3419
  // we assume there are two hashmaps - one for the young generation
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3420
  // and the other for all other spaces.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3421
  assert(n_hashmaps == 2, "not implemented");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3422
  JvmtiTagHashmap* young_hashmap = _hashmap[0];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3423
  JvmtiTagHashmap* other_hashmap = _hashmap[1];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3424
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3425
  // reenable sizing (if disabled)
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3426
  young_hashmap->set_resizing_enabled(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3427
  other_hashmap->set_resizing_enabled(true);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3428
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3429
  // when re-hashing the hashmap corresponding to the young generation we
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3430
  // collect the entries corresponding to objects that have been promoted.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3431
  JvmtiTagHashmapEntry* promoted_entries = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3432
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3433
  if (end >= n_hashmaps) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3434
    end = n_hashmaps - 1;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3435
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3436
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3437
  for (int i=start; i <= end; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3438
    JvmtiTagHashmap* hashmap = _hashmap[i];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3439
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3440
    // if the hashmap is empty then we can skip it
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3441
    if (hashmap->_entry_count == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3442
      continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3443
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3444
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3445
    // now iterate through each entry in the table
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3446
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3447
    JvmtiTagHashmapEntry** table = hashmap->table();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3448
    int size = hashmap->size();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3449
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3450
    for (int pos=0; pos<size; pos++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3451
      JvmtiTagHashmapEntry* entry = table[pos];
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3452
      JvmtiTagHashmapEntry* prev = NULL;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3453
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3454
      while (entry != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3455
        JvmtiTagHashmapEntry* next = entry->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3456
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3457
        jweak ref = entry->object();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3458
        oop oop = JNIHandles::resolve(ref);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3459
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3460
        // has object been GC'ed
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3461
        if (oop == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3462
          // grab the tag
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3463
          jlong tag = entry->tag();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3464
          guarantee(tag != 0, "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3465
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3466
          // remove GC'ed entry from hashmap and return the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3467
          // entry to the free list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3468
          hashmap->remove(prev, pos, entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3469
          destroy_entry(entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3470
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3471
          // destroy the weak ref
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3472
          JNIHandles::destroy_weak_global(ref);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3473
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3474
          // post the event to the profiler
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3475
          if (post_object_free) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3476
            JvmtiExport::post_object_free(env(), tag);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3477
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3478
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3479
          freed++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3480
          entry = next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3481
          continue;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3482
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3483
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3484
        // if this is the young hashmap then the object is either promoted
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3485
        // or moved.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3486
        // if this is the other hashmap then the object is moved.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3487
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3488
        bool same_gen;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3489
        if (i == 0) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3490
          assert(hashmap == young_hashmap, "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3491
          same_gen = is_in_young(oop);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3492
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3493
          same_gen = true;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3494
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3495
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3496
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3497
        if (same_gen) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3498
          // if the object has moved then re-hash it and move its
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3499
          // entry to its new location.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3500
          unsigned int new_pos = JvmtiTagHashmap::hash(oop, size);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3501
          if (new_pos != (unsigned int)pos) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3502
            if (prev == NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3503
              table[pos] = next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3504
            } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3505
              prev->set_next(next);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3506
            }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3507
            entry->set_next(table[new_pos]);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3508
            table[new_pos] = entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3509
            moved++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3510
          } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3511
            // object didn't move
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3512
            prev = entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3513
          }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3514
        } else {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3515
          // object has been promoted so remove the entry from the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3516
          // young hashmap
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3517
          assert(hashmap == young_hashmap, "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3518
          hashmap->remove(prev, pos, entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3519
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3520
          // move the entry to the promoted list
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3521
          entry->set_next(promoted_entries);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3522
          promoted_entries = entry;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3523
        }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3524
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3525
        entry = next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3526
      }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3527
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3528
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3529
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3530
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3531
  // add the entries, corresponding to the promoted objects, to the
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3532
  // other hashmap.
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3533
  JvmtiTagHashmapEntry* entry = promoted_entries;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3534
  while (entry != NULL) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3535
    oop o = JNIHandles::resolve(entry->object());
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3536
    assert(hashmap_for(o) == other_hashmap, "checking");
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3537
    JvmtiTagHashmapEntry* next = entry->next();
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3538
    other_hashmap->add(o, entry);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3539
    entry = next;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3540
    promoted++;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3541
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3542
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3543
  // stats
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3544
  if (TraceJVMTIObjectTagging) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3545
    int total_moves = promoted + moved;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3546
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3547
    int post_total = 0;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3548
    for (int i=0; i<n_hashmaps; i++) {
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3549
      post_total += _hashmap[i]->_entry_count;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3550
    }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3551
    int pre_total = post_total + freed;
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3552
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3553
    tty->print("(%d->%d, %d freed, %d promoted, %d total moves)",
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3554
        pre_total, post_total, freed, promoted, total_moves);
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3555
  }
489c9b5090e2 Initial load
duke
parents:
diff changeset
  3556
}