13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "classfile/javaClasses.inline.hpp"
27 #include "classfile/symbolTable.hpp"
28 #include "classfile/systemDictionary.hpp"
29 #include "classfile/vmSymbols.hpp"
30 #include "code/codeCache.hpp"
31 #include "jvmtifiles/jvmtiEnv.hpp"
32 #include "memory/resourceArea.hpp"
33 #include "oops/instanceMirrorKlass.hpp"
34 #include "oops/objArrayKlass.hpp"
35 #include "oops/objArrayOop.inline.hpp"
36 #include "oops/oop.inline.hpp"
37 #include "prims/jvmtiEventController.hpp"
38 #include "prims/jvmtiEventController.inline.hpp"
39 #include "prims/jvmtiExport.hpp"
40 #include "prims/jvmtiImpl.hpp"
41 #include "prims/jvmtiTagMap.hpp"
42 #include "runtime/biasedLocking.hpp"
43 #include "runtime/javaCalls.hpp"
44 #include "runtime/jniHandles.hpp"
45 #include "runtime/mutex.hpp"
46 #include "runtime/mutexLocker.hpp"
47 #include "runtime/reflectionUtils.hpp"
48 #include "runtime/thread.inline.hpp"
49 #include "runtime/threadSMR.hpp"
50 #include "runtime/vframe.hpp"
51 #include "runtime/vmThread.hpp"
52 #include "runtime/vm_operations.hpp"
53 #include "services/serviceUtil.hpp"
54 #include "utilities/macros.hpp"
55 #if INCLUDE_ALL_GCS
56 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
57 #include "gc/parallel/parallelScavengeHeap.hpp"
58 #endif // INCLUDE_ALL_GCS
59
60 // JvmtiTagHashmapEntry
61 //
62 // Each entry encapsulates a reference to the tagged object
63 // and the tag value. In addition an entry includes a next pointer which
64 // is used to chain entries together.
65
66 class JvmtiTagHashmapEntry : public CHeapObj<mtInternal> {
67 private:
68 friend class JvmtiTagMap;
69
70 oop _object; // tagged object
71 jlong _tag; // the tag
72 JvmtiTagHashmapEntry* _next; // next on the list
73
74 inline void init(oop object, jlong tag) {
75 _object = object;
76 _tag = tag;
77 _next = NULL;
78 }
79
80 // constructor
81 JvmtiTagHashmapEntry(oop object, jlong tag) { init(object, tag); }
82
83 public:
84
85 // accessor methods
86 inline oop object() const { return _object; }
87 inline oop* object_addr() { return &_object; }
88 inline jlong tag() const { return _tag; }
89
90 inline void set_tag(jlong tag) {
91 assert(tag != 0, "can't be zero");
92 _tag = tag;
93 }
94
95 inline JvmtiTagHashmapEntry* next() const { return _next; }
96 inline void set_next(JvmtiTagHashmapEntry* next) { _next = next; }
97 };
98
99
100 // JvmtiTagHashmap
101 //
102 // A hashmap is essentially a table of pointers to entries. Entries
103 // are hashed to a location, or position in the table, and then
104 // chained from that location. The "key" for hashing is address of
105 // the object, or oop. The "value" is the tag value.
106 //
107 // A hashmap maintains a count of the number entries in the hashmap
108 // and resizes if the number of entries exceeds a given threshold.
109 // The threshold is specified as a percentage of the size - for
110 // example a threshold of 0.75 will trigger the hashmap to resize
111 // if the number of entries is >75% of table size.
112 //
113 // A hashmap provides functions for adding, removing, and finding
114 // entries. It also provides a function to iterate over all entries
194 // allocate new table
195 size_t s = new_size * sizeof(JvmtiTagHashmapEntry*);
196 JvmtiTagHashmapEntry** new_table = (JvmtiTagHashmapEntry**)os::malloc(s, mtInternal);
197 if (new_table == NULL) {
198 warning("unable to allocate larger hashtable for jvmti object tags");
199 set_resizing_enabled(false);
200 return;
201 }
202
203 // initialize new table
204 int i;
205 for (i=0; i<new_size; i++) {
206 new_table[i] = NULL;
207 }
208
209 // rehash all entries into the new table
210 for (i=0; i<_size; i++) {
211 JvmtiTagHashmapEntry* entry = _table[i];
212 while (entry != NULL) {
213 JvmtiTagHashmapEntry* next = entry->next();
214 oop key = entry->object();
215 assert(key != NULL, "jni weak reference cleared!!");
216 unsigned int h = hash(key, new_size);
217 JvmtiTagHashmapEntry* anchor = new_table[h];
218 if (anchor == NULL) {
219 new_table[h] = entry;
220 entry->set_next(NULL);
221 } else {
222 entry->set_next(anchor);
223 new_table[h] = entry;
224 }
225 entry = next;
226 }
227 }
228
229 // free old table and update settings.
230 os::free((void*)_table);
231 _table = new_table;
232 _size_index = new_size_index;
233 _size = new_size;
234
287 }
288
289 // release table when JvmtiTagHashmap destroyed
290 ~JvmtiTagHashmap() {
291 if (_table != NULL) {
292 os::free((void*)_table);
293 _table = NULL;
294 }
295 }
296
297 // accessors
298 int size() const { return _size; }
299 JvmtiTagHashmapEntry** table() const { return _table; }
300 int entry_count() const { return _entry_count; }
301
302 // find an entry in the hashmap, returns NULL if not found.
303 inline JvmtiTagHashmapEntry* find(oop key) {
304 unsigned int h = hash(key);
305 JvmtiTagHashmapEntry* entry = _table[h];
306 while (entry != NULL) {
307 if (entry->object() == key) {
308 return entry;
309 }
310 entry = entry->next();
311 }
312 return NULL;
313 }
314
315
316 // add a new entry to hashmap
317 inline void add(oop key, JvmtiTagHashmapEntry* entry) {
318 assert(key != NULL, "checking");
319 assert(find(key) == NULL, "duplicate detected");
320 unsigned int h = hash(key);
321 JvmtiTagHashmapEntry* anchor = _table[h];
322 if (anchor == NULL) {
323 _table[h] = entry;
324 entry->set_next(NULL);
325 } else {
326 entry->set_next(anchor);
327 _table[h] = entry;
328 }
329
330 _entry_count++;
331 if (log_is_enabled(Debug, jvmti, objecttagging) && entry_count() >= trace_threshold()) {
332 print_memory_usage();
333 compute_next_trace_threshold();
334 }
335
336 // if the number of entries exceed the threshold then resize
337 if (entry_count() > resize_threshold() && is_resizing_enabled()) {
338 resize();
339 }
340 }
341
342 // remove an entry with the given key.
343 inline JvmtiTagHashmapEntry* remove(oop key) {
344 unsigned int h = hash(key);
345 JvmtiTagHashmapEntry* entry = _table[h];
346 JvmtiTagHashmapEntry* prev = NULL;
347 while (entry != NULL) {
348 if (key == entry->object()) {
349 break;
350 }
351 prev = entry;
352 entry = entry->next();
353 }
354 if (entry != NULL) {
355 remove(prev, h, entry);
356 }
357 return entry;
358 }
359
360 // iterate over all entries in the hashmap
361 void entry_iterate(JvmtiTagHashmapEntryClosure* closure);
362 };
363
364 // possible hashmap sizes - odd primes that roughly double in size.
365 // To avoid excessive resizing the odd primes from 4801-76831 and
366 // 76831-307261 have been removed. The list must be terminated by -1.
367 int JvmtiTagHashmap::_sizes[] = { 4801, 76831, 307261, 614563, 1228891,
368 2457733, 4915219, 9830479, 19660831, 39321619, 78643219, -1 };
1518 TagObjectCollector(JvmtiEnv* env, const jlong* tags, jint tag_count) {
1519 _env = env;
1520 _tags = (jlong*)tags;
1521 _tag_count = tag_count;
1522 _object_results = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jobject>(1,true);
1523 _tag_results = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<uint64_t>(1,true);
1524 }
1525
1526 ~TagObjectCollector() {
1527 delete _object_results;
1528 delete _tag_results;
1529 }
1530
1531 // for each tagged object check if the tag value matches
1532 // - if it matches then we create a JNI local reference to the object
1533 // and record the reference and tag value.
1534 //
1535 void do_entry(JvmtiTagHashmapEntry* entry) {
1536 for (int i=0; i<_tag_count; i++) {
1537 if (_tags[i] == entry->tag()) {
1538 oop o = entry->object();
1539 assert(o != NULL && Universe::heap()->is_in_reserved(o), "sanity check");
1540 #if INCLUDE_ALL_GCS
1541 if (UseG1GC) {
1542 // The reference in this tag map could be the only (implicitly weak)
1543 // reference to that object. If we hand it out, we need to keep it live wrt
1544 // SATB marking similar to other j.l.ref.Reference referents.
1545 G1SATBCardTableModRefBS::enqueue(o);
1546 }
1547 #endif
1548 jobject ref = JNIHandles::make_local(JavaThread::current(), o);
1549 _object_results->append(ref);
1550 _tag_results->append((uint64_t)entry->tag());
1551 }
1552 }
1553 }
1554
1555 // return the results from the collection
1556 //
1557 jvmtiError result(jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr) {
1558 jvmtiError error;
1559 int count = _object_results->length();
1560 assert(count >= 0, "sanity check");
1561
1562 // if object_result_ptr is not NULL then allocate the result and copy
1563 // in the object references.
1564 if (object_result_ptr != NULL) {
1565 error = _env->Allocate(count * sizeof(jobject), (unsigned char**)object_result_ptr);
1566 if (error != JVMTI_ERROR_NONE) {
1567 return error;
3346
3347 // if the hashmap is empty then we can skip it
3348 if (hashmap->_entry_count == 0) {
3349 return;
3350 }
3351
3352 // now iterate through each entry in the table
3353
3354 JvmtiTagHashmapEntry** table = hashmap->table();
3355 int size = hashmap->size();
3356
3357 JvmtiTagHashmapEntry* delayed_add = NULL;
3358
3359 for (int pos = 0; pos < size; ++pos) {
3360 JvmtiTagHashmapEntry* entry = table[pos];
3361 JvmtiTagHashmapEntry* prev = NULL;
3362
3363 while (entry != NULL) {
3364 JvmtiTagHashmapEntry* next = entry->next();
3365
3366 oop* obj = entry->object_addr();
3367
3368 // has object been GC'ed
3369 if (!is_alive->do_object_b(entry->object())) {
3370 // grab the tag
3371 jlong tag = entry->tag();
3372 guarantee(tag != 0, "checking");
3373
3374 // remove GC'ed entry from hashmap and return the
3375 // entry to the free list
3376 hashmap->remove(prev, pos, entry);
3377 destroy_entry(entry);
3378
3379 // post the event to the profiler
3380 if (post_object_free) {
3381 JvmtiExport::post_object_free(env(), tag);
3382 }
3383
3384 ++freed;
3385 } else {
3386 f->do_oop(entry->object_addr());
3387 oop new_oop = entry->object();
3388
3389 // if the object has moved then re-hash it and move its
3390 // entry to its new location.
3391 unsigned int new_pos = JvmtiTagHashmap::hash(new_oop, size);
3392 if (new_pos != (unsigned int)pos) {
3393 if (prev == NULL) {
3394 table[pos] = next;
3395 } else {
3396 prev->set_next(next);
3397 }
3398 if (new_pos < (unsigned int)pos) {
3399 entry->set_next(table[new_pos]);
3400 table[new_pos] = entry;
3401 } else {
3402 // Delay adding this entry to it's new position as we'd end up
3403 // hitting it again during this iteration.
3404 entry->set_next(delayed_add);
3405 delayed_add = entry;
3406 }
3407 moved++;
3408 } else {
3409 // object didn't move
3410 prev = entry;
3411 }
3412 }
3413
3414 entry = next;
3415 }
3416 }
3417
3418 // Re-add all the entries which were kept aside
3419 while (delayed_add != NULL) {
3420 JvmtiTagHashmapEntry* next = delayed_add->next();
3421 unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object(), size);
3422 delayed_add->set_next(table[pos]);
3423 table[pos] = delayed_add;
3424 delayed_add = next;
3425 }
3426
3427 log_debug(jvmti, objecttagging)("(%d->%d, %d freed, %d total moves)",
3428 hashmap->_entry_count + freed, hashmap->_entry_count, freed, moved);
3429 }
|
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "classfile/javaClasses.inline.hpp"
27 #include "classfile/symbolTable.hpp"
28 #include "classfile/systemDictionary.hpp"
29 #include "classfile/vmSymbols.hpp"
30 #include "code/codeCache.hpp"
31 #include "jvmtifiles/jvmtiEnv.hpp"
32 #include "memory/resourceArea.hpp"
33 #include "oops/access.inline.hpp"
34 #include "oops/instanceMirrorKlass.hpp"
35 #include "oops/objArrayKlass.hpp"
36 #include "oops/objArrayOop.inline.hpp"
37 #include "oops/oop.inline.hpp"
38 #include "prims/jvmtiEventController.hpp"
39 #include "prims/jvmtiEventController.inline.hpp"
40 #include "prims/jvmtiExport.hpp"
41 #include "prims/jvmtiImpl.hpp"
42 #include "prims/jvmtiTagMap.hpp"
43 #include "runtime/biasedLocking.hpp"
44 #include "runtime/javaCalls.hpp"
45 #include "runtime/jniHandles.hpp"
46 #include "runtime/mutex.hpp"
47 #include "runtime/mutexLocker.hpp"
48 #include "runtime/reflectionUtils.hpp"
49 #include "runtime/thread.inline.hpp"
50 #include "runtime/threadSMR.hpp"
51 #include "runtime/vframe.hpp"
52 #include "runtime/vmThread.hpp"
53 #include "runtime/vm_operations.hpp"
54 #include "services/serviceUtil.hpp"
55 #include "utilities/macros.hpp"
56
57 // JvmtiTagHashmapEntry
58 //
59 // Each entry encapsulates a reference to the tagged object
60 // and the tag value. In addition an entry includes a next pointer which
61 // is used to chain entries together.
62
63 class JvmtiTagHashmapEntry : public CHeapObj<mtInternal> {
64 private:
65 friend class JvmtiTagMap;
66
67 oop _object; // tagged object
68 jlong _tag; // the tag
69 JvmtiTagHashmapEntry* _next; // next on the list
70
71 inline void init(oop object, jlong tag) {
72 _object = object;
73 _tag = tag;
74 _next = NULL;
75 }
76
77 // constructor
78 JvmtiTagHashmapEntry(oop object, jlong tag) { init(object, tag); }
79
80 public:
81
82 // accessor methods
83 inline oop* object_addr() { return &_object; }
84 inline oop object() { return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(object_addr()); }
85 // Peek at the object without keeping it alive. The returned object must be
86 // kept alive using a normal access if it leaks out of a thread transition from VM.
87 inline oop object_peek() {
88 return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(object_addr());
89 }
90 inline jlong tag() const { return _tag; }
91
92 inline void set_tag(jlong tag) {
93 assert(tag != 0, "can't be zero");
94 _tag = tag;
95 }
96
97 inline bool equals(oop object) {
98 return object == object_peek();
99 }
100
101 inline JvmtiTagHashmapEntry* next() const { return _next; }
102 inline void set_next(JvmtiTagHashmapEntry* next) { _next = next; }
103 };
104
105
106 // JvmtiTagHashmap
107 //
108 // A hashmap is essentially a table of pointers to entries. Entries
109 // are hashed to a location, or position in the table, and then
110 // chained from that location. The "key" for hashing is address of
111 // the object, or oop. The "value" is the tag value.
112 //
113 // A hashmap maintains a count of the number entries in the hashmap
114 // and resizes if the number of entries exceeds a given threshold.
115 // The threshold is specified as a percentage of the size - for
116 // example a threshold of 0.75 will trigger the hashmap to resize
117 // if the number of entries is >75% of table size.
118 //
119 // A hashmap provides functions for adding, removing, and finding
120 // entries. It also provides a function to iterate over all entries
200 // allocate new table
201 size_t s = new_size * sizeof(JvmtiTagHashmapEntry*);
202 JvmtiTagHashmapEntry** new_table = (JvmtiTagHashmapEntry**)os::malloc(s, mtInternal);
203 if (new_table == NULL) {
204 warning("unable to allocate larger hashtable for jvmti object tags");
205 set_resizing_enabled(false);
206 return;
207 }
208
209 // initialize new table
210 int i;
211 for (i=0; i<new_size; i++) {
212 new_table[i] = NULL;
213 }
214
215 // rehash all entries into the new table
216 for (i=0; i<_size; i++) {
217 JvmtiTagHashmapEntry* entry = _table[i];
218 while (entry != NULL) {
219 JvmtiTagHashmapEntry* next = entry->next();
220 oop key = entry->object_peek();
221 assert(key != NULL, "jni weak reference cleared!!");
222 unsigned int h = hash(key, new_size);
223 JvmtiTagHashmapEntry* anchor = new_table[h];
224 if (anchor == NULL) {
225 new_table[h] = entry;
226 entry->set_next(NULL);
227 } else {
228 entry->set_next(anchor);
229 new_table[h] = entry;
230 }
231 entry = next;
232 }
233 }
234
235 // free old table and update settings.
236 os::free((void*)_table);
237 _table = new_table;
238 _size_index = new_size_index;
239 _size = new_size;
240
293 }
294
295 // release table when JvmtiTagHashmap destroyed
296 ~JvmtiTagHashmap() {
297 if (_table != NULL) {
298 os::free((void*)_table);
299 _table = NULL;
300 }
301 }
302
303 // accessors
304 int size() const { return _size; }
305 JvmtiTagHashmapEntry** table() const { return _table; }
306 int entry_count() const { return _entry_count; }
307
308 // find an entry in the hashmap, returns NULL if not found.
309 inline JvmtiTagHashmapEntry* find(oop key) {
310 unsigned int h = hash(key);
311 JvmtiTagHashmapEntry* entry = _table[h];
312 while (entry != NULL) {
313 if (entry->equals(key)) {
314 return entry;
315 }
316 entry = entry->next();
317 }
318 return NULL;
319 }
320
321
322 // add a new entry to hashmap
323 inline void add(oop key, JvmtiTagHashmapEntry* entry) {
324 assert(key != NULL, "checking");
325 assert(find(key) == NULL, "duplicate detected");
326 unsigned int h = hash(key);
327 JvmtiTagHashmapEntry* anchor = _table[h];
328 if (anchor == NULL) {
329 _table[h] = entry;
330 entry->set_next(NULL);
331 } else {
332 entry->set_next(anchor);
333 _table[h] = entry;
334 }
335
336 _entry_count++;
337 if (log_is_enabled(Debug, jvmti, objecttagging) && entry_count() >= trace_threshold()) {
338 print_memory_usage();
339 compute_next_trace_threshold();
340 }
341
342 // if the number of entries exceed the threshold then resize
343 if (entry_count() > resize_threshold() && is_resizing_enabled()) {
344 resize();
345 }
346 }
347
348 // remove an entry with the given key.
349 inline JvmtiTagHashmapEntry* remove(oop key) {
350 unsigned int h = hash(key);
351 JvmtiTagHashmapEntry* entry = _table[h];
352 JvmtiTagHashmapEntry* prev = NULL;
353 while (entry != NULL) {
354 if (entry->equals(key)) {
355 break;
356 }
357 prev = entry;
358 entry = entry->next();
359 }
360 if (entry != NULL) {
361 remove(prev, h, entry);
362 }
363 return entry;
364 }
365
366 // iterate over all entries in the hashmap
367 void entry_iterate(JvmtiTagHashmapEntryClosure* closure);
368 };
369
370 // possible hashmap sizes - odd primes that roughly double in size.
371 // To avoid excessive resizing the odd primes from 4801-76831 and
372 // 76831-307261 have been removed. The list must be terminated by -1.
373 int JvmtiTagHashmap::_sizes[] = { 4801, 76831, 307261, 614563, 1228891,
374 2457733, 4915219, 9830479, 19660831, 39321619, 78643219, -1 };
1524 TagObjectCollector(JvmtiEnv* env, const jlong* tags, jint tag_count) {
1525 _env = env;
1526 _tags = (jlong*)tags;
1527 _tag_count = tag_count;
1528 _object_results = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jobject>(1,true);
1529 _tag_results = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<uint64_t>(1,true);
1530 }
1531
1532 ~TagObjectCollector() {
1533 delete _object_results;
1534 delete _tag_results;
1535 }
1536
1537 // for each tagged object check if the tag value matches
1538 // - if it matches then we create a JNI local reference to the object
1539 // and record the reference and tag value.
1540 //
1541 void do_entry(JvmtiTagHashmapEntry* entry) {
1542 for (int i=0; i<_tag_count; i++) {
1543 if (_tags[i] == entry->tag()) {
1544 // The reference in this tag map could be the only (implicitly weak)
1545 // reference to that object. If we hand it out, we need to keep it live wrt
1546 // SATB marking similar to other j.l.ref.Reference referents. This is
1547 // achieved by using a phantom load in the object() accessor.
1548 oop o = entry->object();
1549 assert(o != NULL && Universe::heap()->is_in_reserved(o), "sanity check");
1550 jobject ref = JNIHandles::make_local(JavaThread::current(), o);
1551 _object_results->append(ref);
1552 _tag_results->append((uint64_t)entry->tag());
1553 }
1554 }
1555 }
1556
1557 // return the results from the collection
1558 //
1559 jvmtiError result(jint* count_ptr, jobject** object_result_ptr, jlong** tag_result_ptr) {
1560 jvmtiError error;
1561 int count = _object_results->length();
1562 assert(count >= 0, "sanity check");
1563
1564 // if object_result_ptr is not NULL then allocate the result and copy
1565 // in the object references.
1566 if (object_result_ptr != NULL) {
1567 error = _env->Allocate(count * sizeof(jobject), (unsigned char**)object_result_ptr);
1568 if (error != JVMTI_ERROR_NONE) {
1569 return error;
3348
3349 // if the hashmap is empty then we can skip it
3350 if (hashmap->_entry_count == 0) {
3351 return;
3352 }
3353
3354 // now iterate through each entry in the table
3355
3356 JvmtiTagHashmapEntry** table = hashmap->table();
3357 int size = hashmap->size();
3358
3359 JvmtiTagHashmapEntry* delayed_add = NULL;
3360
3361 for (int pos = 0; pos < size; ++pos) {
3362 JvmtiTagHashmapEntry* entry = table[pos];
3363 JvmtiTagHashmapEntry* prev = NULL;
3364
3365 while (entry != NULL) {
3366 JvmtiTagHashmapEntry* next = entry->next();
3367
3368 // has object been GC'ed
3369 if (!is_alive->do_object_b(entry->object_peek())) {
3370 // grab the tag
3371 jlong tag = entry->tag();
3372 guarantee(tag != 0, "checking");
3373
3374 // remove GC'ed entry from hashmap and return the
3375 // entry to the free list
3376 hashmap->remove(prev, pos, entry);
3377 destroy_entry(entry);
3378
3379 // post the event to the profiler
3380 if (post_object_free) {
3381 JvmtiExport::post_object_free(env(), tag);
3382 }
3383
3384 ++freed;
3385 } else {
3386 f->do_oop(entry->object_addr());
3387 oop new_oop = entry->object_peek();
3388
3389 // if the object has moved then re-hash it and move its
3390 // entry to its new location.
3391 unsigned int new_pos = JvmtiTagHashmap::hash(new_oop, size);
3392 if (new_pos != (unsigned int)pos) {
3393 if (prev == NULL) {
3394 table[pos] = next;
3395 } else {
3396 prev->set_next(next);
3397 }
3398 if (new_pos < (unsigned int)pos) {
3399 entry->set_next(table[new_pos]);
3400 table[new_pos] = entry;
3401 } else {
3402 // Delay adding this entry to it's new position as we'd end up
3403 // hitting it again during this iteration.
3404 entry->set_next(delayed_add);
3405 delayed_add = entry;
3406 }
3407 moved++;
3408 } else {
3409 // object didn't move
3410 prev = entry;
3411 }
3412 }
3413
3414 entry = next;
3415 }
3416 }
3417
3418 // Re-add all the entries which were kept aside
3419 while (delayed_add != NULL) {
3420 JvmtiTagHashmapEntry* next = delayed_add->next();
3421 unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object_peek(), size);
3422 delayed_add->set_next(table[pos]);
3423 table[pos] = delayed_add;
3424 delayed_add = next;
3425 }
3426
3427 log_debug(jvmti, objecttagging)("(%d->%d, %d freed, %d total moves)",
3428 hashmap->_entry_count + freed, hashmap->_entry_count, freed, moved);
3429 }
|