annotate src/share/vm/prims/jvmtiTagMap.cpp @ 452:00b023ae2d78

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