< prev index next >

src/hotspot/share/prims/jvmtiTagMap.cpp

Print this page
rev 47972 : [mq]: Access_jvmtiTagMap


  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 }
< prev index next >