hotspot/src/share/vm/prims/jvmtiTagMap.cpp
changeset 7896 08aadd7aa3ee
parent 7397 5b173b4ca846
child 7916 84e5b29decb0
equal deleted inserted replaced
7895:e71bad345f3a 7896:08aadd7aa3ee
    48 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
    48 #include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp"
    49 #endif
    49 #endif
    50 
    50 
    51 // JvmtiTagHashmapEntry
    51 // JvmtiTagHashmapEntry
    52 //
    52 //
    53 // Each entry encapsulates a JNI weak reference to the tagged object
    53 // Each entry encapsulates a reference to the tagged object
    54 // and the tag value. In addition an entry includes a next pointer which
    54 // and the tag value. In addition an entry includes a next pointer which
    55 // is used to chain entries together.
    55 // is used to chain entries together.
    56 
    56 
    57 class JvmtiTagHashmapEntry : public CHeapObj {
    57 class JvmtiTagHashmapEntry : public CHeapObj {
    58  private:
    58  private:
    59   friend class JvmtiTagMap;
    59   friend class JvmtiTagMap;
    60 
    60 
    61   jweak _object;                        // JNI weak ref to tagged object
    61   oop _object;                          // tagged object
    62   jlong _tag;                           // the tag
    62   jlong _tag;                           // the tag
    63   JvmtiTagHashmapEntry* _next;          // next on the list
    63   JvmtiTagHashmapEntry* _next;          // next on the list
    64 
    64 
    65   inline void init(jweak object, jlong tag) {
    65   inline void init(oop object, jlong tag) {
    66     _object = object;
    66     _object = object;
    67     _tag = tag;
    67     _tag = tag;
    68     _next = NULL;
    68     _next = NULL;
    69   }
    69   }
    70 
    70 
    71   // constructor
    71   // constructor
    72   JvmtiTagHashmapEntry(jweak object, jlong tag)         { init(object, tag); }
    72   JvmtiTagHashmapEntry(oop object, jlong tag)         { init(object, tag); }
    73 
    73 
    74  public:
    74  public:
    75 
    75 
    76   // accessor methods
    76   // accessor methods
    77   inline jweak object() const                           { return _object; }
    77   inline oop object() const                           { return _object; }
    78   inline jlong tag() const                              { return _tag; }
    78   inline oop* object_addr()                           { return &_object; }
       
    79   inline jlong tag() const                            { return _tag; }
    79 
    80 
    80   inline void set_tag(jlong tag) {
    81   inline void set_tag(jlong tag) {
    81     assert(tag != 0, "can't be zero");
    82     assert(tag != 0, "can't be zero");
    82     _tag = tag;
    83     _tag = tag;
    83   }
    84   }
    90 // JvmtiTagHashmap
    91 // JvmtiTagHashmap
    91 //
    92 //
    92 // A hashmap is essentially a table of pointers to entries. Entries
    93 // A hashmap is essentially a table of pointers to entries. Entries
    93 // are hashed to a location, or position in the table, and then
    94 // are hashed to a location, or position in the table, and then
    94 // chained from that location. The "key" for hashing is address of
    95 // chained from that location. The "key" for hashing is address of
    95 // the object, or oop. The "value" is the JNI weak reference to the
    96 // the object, or oop. The "value" is the tag value.
    96 // object and the tag value. Keys are not stored with the entry.
       
    97 // Instead the weak reference is resolved to obtain the key.
       
    98 //
    97 //
    99 // A hashmap maintains a count of the number entries in the hashmap
    98 // A hashmap maintains a count of the number entries in the hashmap
   100 // and resizes if the number of entries exceeds a given threshold.
    99 // and resizes if the number of entries exceeds a given threshold.
   101 // The threshold is specified as a percentage of the size - for
   100 // The threshold is specified as a percentage of the size - for
   102 // example a threshold of 0.75 will trigger the hashmap to resize
   101 // example a threshold of 0.75 will trigger the hashmap to resize
   204     // rehash all entries into the new table
   203     // rehash all entries into the new table
   205     for (i=0; i<_size; i++) {
   204     for (i=0; i<_size; i++) {
   206       JvmtiTagHashmapEntry* entry = _table[i];
   205       JvmtiTagHashmapEntry* entry = _table[i];
   207       while (entry != NULL) {
   206       while (entry != NULL) {
   208         JvmtiTagHashmapEntry* next = entry->next();
   207         JvmtiTagHashmapEntry* next = entry->next();
   209         oop key = JNIHandles::resolve(entry->object());
   208         oop key = entry->object();
   210         assert(key != NULL, "jni weak reference cleared!!");
   209         assert(key != NULL, "jni weak reference cleared!!");
   211         unsigned int h = hash(key, new_size);
   210         unsigned int h = hash(key, new_size);
   212         JvmtiTagHashmapEntry* anchor = new_table[h];
   211         JvmtiTagHashmapEntry* anchor = new_table[h];
   213         if (anchor == NULL) {
   212         if (anchor == NULL) {
   214           new_table[h] = entry;
   213           new_table[h] = entry;
   297   // find an entry in the hashmap, returns NULL if not found.
   296   // find an entry in the hashmap, returns NULL if not found.
   298   inline JvmtiTagHashmapEntry* find(oop key) {
   297   inline JvmtiTagHashmapEntry* find(oop key) {
   299     unsigned int h = hash(key);
   298     unsigned int h = hash(key);
   300     JvmtiTagHashmapEntry* entry = _table[h];
   299     JvmtiTagHashmapEntry* entry = _table[h];
   301     while (entry != NULL) {
   300     while (entry != NULL) {
   302       oop orig_key = JNIHandles::resolve(entry->object());
   301       if (entry->object() == key) {
   303       assert(orig_key != NULL, "jni weak reference cleared!!");
   302          return entry;
   304       if (key == orig_key) {
       
   305         break;
       
   306       }
   303       }
   307       entry = entry->next();
   304       entry = entry->next();
   308     }
   305     }
   309     return entry;
   306     return NULL;
   310   }
   307   }
   311 
   308 
   312 
   309 
   313   // add a new entry to hashmap
   310   // add a new entry to hashmap
   314   inline void add(oop key, JvmtiTagHashmapEntry* entry) {
   311   inline void add(oop key, JvmtiTagHashmapEntry* entry) {
   341   inline JvmtiTagHashmapEntry* remove(oop key) {
   338   inline JvmtiTagHashmapEntry* remove(oop key) {
   342     unsigned int h = hash(key);
   339     unsigned int h = hash(key);
   343     JvmtiTagHashmapEntry* entry = _table[h];
   340     JvmtiTagHashmapEntry* entry = _table[h];
   344     JvmtiTagHashmapEntry* prev = NULL;
   341     JvmtiTagHashmapEntry* prev = NULL;
   345     while (entry != NULL) {
   342     while (entry != NULL) {
   346       oop orig_key = JNIHandles::resolve(entry->object());
   343       if (key == entry->object()) {
   347       assert(orig_key != NULL, "jni weak reference cleared!!");
       
   348       if (key == orig_key) {
       
   349         break;
   344         break;
   350       }
   345       }
   351       prev = entry;
   346       prev = entry;
   352       entry = entry->next();
   347       entry = entry->next();
   353     }
   348     }
   416       _trace_threshold += large_trace_threshold;
   411       _trace_threshold += large_trace_threshold;
   417     }
   412     }
   418   }
   413   }
   419 }
   414 }
   420 
   415 
   421 // memory region for young generation
       
   422 MemRegion JvmtiTagMap::_young_gen;
       
   423 
       
   424 // get the memory region used for the young generation
       
   425 void JvmtiTagMap::get_young_generation() {
       
   426   CollectedHeap* ch = Universe::heap();
       
   427   switch (ch->kind()) {
       
   428     case (CollectedHeap::GenCollectedHeap): {
       
   429       _young_gen = ((GenCollectedHeap*)ch)->get_gen(0)->reserved();
       
   430       break;
       
   431     }
       
   432 #ifndef SERIALGC
       
   433     case (CollectedHeap::ParallelScavengeHeap): {
       
   434       _young_gen = ((ParallelScavengeHeap*)ch)->young_gen()->reserved();
       
   435       break;
       
   436     }
       
   437     case (CollectedHeap::G1CollectedHeap): {
       
   438       // Until a more satisfactory solution is implemented, all
       
   439       // oops in the tag map will require rehash at each gc.
       
   440       // This is a correct, if extremely inefficient solution.
       
   441       // See RFE 6621729 for related commentary.
       
   442       _young_gen = ch->reserved_region();
       
   443       break;
       
   444     }
       
   445 #endif  // !SERIALGC
       
   446     default:
       
   447       ShouldNotReachHere();
       
   448   }
       
   449 }
       
   450 
       
   451 // returns true if oop is in the young generation
       
   452 inline bool JvmtiTagMap::is_in_young(oop o) {
       
   453   assert(_young_gen.start() != NULL, "checking");
       
   454   void* p = (void*)o;
       
   455   bool in_young = _young_gen.contains(p);
       
   456   return in_young;
       
   457 }
       
   458 
       
   459 // returns the appropriate hashmap for a given object
       
   460 inline JvmtiTagHashmap* JvmtiTagMap::hashmap_for(oop o) {
       
   461   if (is_in_young(o)) {
       
   462     return _hashmap[0];
       
   463   } else {
       
   464     return _hashmap[1];
       
   465   }
       
   466 }
       
   467 
       
   468 
       
   469 // create a JvmtiTagMap
   416 // create a JvmtiTagMap
   470 JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) :
   417 JvmtiTagMap::JvmtiTagMap(JvmtiEnv* env) :
   471   _env(env),
   418   _env(env),
   472   _lock(Mutex::nonleaf+2, "JvmtiTagMap._lock", false),
   419   _lock(Mutex::nonleaf+2, "JvmtiTagMap._lock", false),
   473   _free_entries(NULL),
   420   _free_entries(NULL),
   474   _free_entries_count(0)
   421   _free_entries_count(0)
   475 {
   422 {
   476   assert(JvmtiThreadState_lock->is_locked(), "sanity check");
   423   assert(JvmtiThreadState_lock->is_locked(), "sanity check");
   477   assert(((JvmtiEnvBase *)env)->tag_map() == NULL, "tag map already exists for environment");
   424   assert(((JvmtiEnvBase *)env)->tag_map() == NULL, "tag map already exists for environment");
   478 
   425 
   479   // create the hashmaps
   426   _hashmap = new JvmtiTagHashmap();
   480   for (int i=0; i<n_hashmaps; i++) {
       
   481     _hashmap[i] = new JvmtiTagHashmap();
       
   482   }
       
   483 
       
   484   // get the memory region used by the young generation
       
   485   get_young_generation();
       
   486 
   427 
   487   // finally add us to the environment
   428   // finally add us to the environment
   488   ((JvmtiEnvBase *)env)->set_tag_map(this);
   429   ((JvmtiEnvBase *)env)->set_tag_map(this);
   489 }
   430 }
   490 
   431 
   494 
   435 
   495   // no lock acquired as we assume the enclosing environment is
   436   // no lock acquired as we assume the enclosing environment is
   496   // also being destroryed.
   437   // also being destroryed.
   497   ((JvmtiEnvBase *)_env)->set_tag_map(NULL);
   438   ((JvmtiEnvBase *)_env)->set_tag_map(NULL);
   498 
   439 
   499   // iterate over the hashmaps and destroy each of the entries
   440   JvmtiTagHashmapEntry** table = _hashmap->table();
   500   for (int i=0; i<n_hashmaps; i++) {
   441   for (int j = 0; j < _hashmap->size(); j++) {
   501     JvmtiTagHashmap* hashmap = _hashmap[i];
   442     JvmtiTagHashmapEntry* entry = table[j];
   502     JvmtiTagHashmapEntry** table = hashmap->table();
   443     while (entry != NULL) {
   503     for (int j=0; j<hashmap->size(); j++) {
   444       JvmtiTagHashmapEntry* next = entry->next();
   504       JvmtiTagHashmapEntry *entry = table[j];
   445       delete entry;
   505       while (entry != NULL) {
   446       entry = next;
   506         JvmtiTagHashmapEntry* next = entry->next();
   447     }
   507         jweak ref = entry->object();
   448   }
   508         JNIHandles::destroy_weak_global(ref);
   449 
   509         delete entry;
   450   // finally destroy the hashmap
   510         entry = next;
   451   delete _hashmap;
   511       }
   452   _hashmap = NULL;
   512     }
       
   513 
       
   514     // finally destroy the hashmap
       
   515     delete hashmap;
       
   516   }
       
   517 
   453 
   518   // remove any entries on the free list
   454   // remove any entries on the free list
   519   JvmtiTagHashmapEntry* entry = _free_entries;
   455   JvmtiTagHashmapEntry* entry = _free_entries;
   520   while (entry != NULL) {
   456   while (entry != NULL) {
   521     JvmtiTagHashmapEntry* next = entry->next();
   457     JvmtiTagHashmapEntry* next = entry->next();
   522     delete entry;
   458     delete entry;
   523     entry = next;
   459     entry = next;
   524   }
   460   }
       
   461   _free_entries = NULL;
   525 }
   462 }
   526 
   463 
   527 // create a hashmap entry
   464 // create a hashmap entry
   528 // - if there's an entry on the (per-environment) free list then this
   465 // - if there's an entry on the (per-environment) free list then this
   529 // is returned. Otherwise an new entry is allocated.
   466 // is returned. Otherwise an new entry is allocated.
   530 JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(jweak ref, jlong tag) {
   467 JvmtiTagHashmapEntry* JvmtiTagMap::create_entry(oop ref, jlong tag) {
   531   assert(Thread::current()->is_VM_thread() || is_locked(), "checking");
   468   assert(Thread::current()->is_VM_thread() || is_locked(), "checking");
   532   JvmtiTagHashmapEntry* entry;
   469   JvmtiTagHashmapEntry* entry;
   533   if (_free_entries == NULL) {
   470   if (_free_entries == NULL) {
   534     entry = new JvmtiTagHashmapEntry(ref, tag);
   471     entry = new JvmtiTagHashmapEntry(ref, tag);
   535   } else {
   472   } else {
   556 }
   493 }
   557 
   494 
   558 // returns the tag map for the given environments. If the tag map
   495 // returns the tag map for the given environments. If the tag map
   559 // doesn't exist then it is created.
   496 // doesn't exist then it is created.
   560 JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
   497 JvmtiTagMap* JvmtiTagMap::tag_map_for(JvmtiEnv* env) {
   561   JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map();
   498   JvmtiTagMap* tag_map = ((JvmtiEnvBase*)env)->tag_map();
   562   if (tag_map == NULL) {
   499   if (tag_map == NULL) {
   563     MutexLocker mu(JvmtiThreadState_lock);
   500     MutexLocker mu(JvmtiThreadState_lock);
   564     tag_map = ((JvmtiEnvBase *)env)->tag_map();
   501     tag_map = ((JvmtiEnvBase*)env)->tag_map();
   565     if (tag_map == NULL) {
   502     if (tag_map == NULL) {
   566       tag_map = new JvmtiTagMap(env);
   503       tag_map = new JvmtiTagMap(env);
   567     }
   504     }
   568   } else {
   505   } else {
   569     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
   506     CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
   571   return tag_map;
   508   return tag_map;
   572 }
   509 }
   573 
   510 
   574 // iterate over all entries in the tag map.
   511 // iterate over all entries in the tag map.
   575 void JvmtiTagMap::entry_iterate(JvmtiTagHashmapEntryClosure* closure) {
   512 void JvmtiTagMap::entry_iterate(JvmtiTagHashmapEntryClosure* closure) {
   576   for (int i=0; i<n_hashmaps; i++) {
   513   hashmap()->entry_iterate(closure);
   577     JvmtiTagHashmap* hashmap = _hashmap[i];
       
   578     hashmap->entry_iterate(closure);
       
   579   }
       
   580 }
   514 }
   581 
   515 
   582 // returns true if the hashmaps are empty
   516 // returns true if the hashmaps are empty
   583 bool JvmtiTagMap::is_empty() {
   517 bool JvmtiTagMap::is_empty() {
   584   assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking");
   518   assert(SafepointSynchronize::is_at_safepoint() || is_locked(), "checking");
   585   assert(n_hashmaps == 2, "not implemented");
   519   return hashmap()->entry_count() == 0;
   586   return ((_hashmap[0]->entry_count() == 0) && (_hashmap[1]->entry_count() == 0));
       
   587 }
   520 }
   588 
   521 
   589 
   522 
   590 // Return the tag value for an object, or 0 if the object is
   523 // Return the tag value for an object, or 0 if the object is
   591 // not tagged
   524 // not tagged
   592 //
   525 //
   593 static inline jlong tag_for(JvmtiTagMap* tag_map, oop o) {
   526 static inline jlong tag_for(JvmtiTagMap* tag_map, oop o) {
   594   JvmtiTagHashmapEntry* entry = tag_map->hashmap_for(o)->find(o);
   527   JvmtiTagHashmapEntry* entry = tag_map->hashmap()->find(o);
   595   if (entry == NULL) {
   528   if (entry == NULL) {
   596     return 0;
   529     return 0;
   597   } else {
   530   } else {
   598     return entry->tag();
   531     return entry->tag();
   599   }
   532   }
   653     // object size
   586     // object size
   654     _obj_size = _o->size() * wordSize;
   587     _obj_size = _o->size() * wordSize;
   655 
   588 
   656     // record the context
   589     // record the context
   657     _tag_map = tag_map;
   590     _tag_map = tag_map;
   658     _hashmap = tag_map->hashmap_for(_o);
   591     _hashmap = tag_map->hashmap();
   659     _entry = _hashmap->find(_o);
   592     _entry = _hashmap->find(_o);
   660 
   593 
   661     // get object tag
   594     // get object tag
   662     _obj_tag = (_entry == NULL) ? 0 : _entry->tag();
   595     _obj_tag = (_entry == NULL) ? 0 : _entry->tag();
   663 
   596 
   692                                                       jlong obj_tag) {
   625                                                       jlong obj_tag) {
   693   if (entry == NULL) {
   626   if (entry == NULL) {
   694     if (obj_tag != 0) {
   627     if (obj_tag != 0) {
   695       // callback has tagged the object
   628       // callback has tagged the object
   696       assert(Thread::current()->is_VM_thread(), "must be VMThread");
   629       assert(Thread::current()->is_VM_thread(), "must be VMThread");
   697       HandleMark hm;
   630       entry = tag_map()->create_entry(o, obj_tag);
   698       Handle h(o);
       
   699       jweak ref = JNIHandles::make_weak_global(h);
       
   700       entry = tag_map()->create_entry(ref, obj_tag);
       
   701       hashmap->add(o, entry);
   631       hashmap->add(o, entry);
   702     }
   632     }
   703   } else {
   633   } else {
   704     // object was previously tagged - the callback may have untagged
   634     // object was previously tagged - the callback may have untagged
   705     // the object or changed the tag value
   635     // the object or changed the tag value
   706     if (obj_tag == 0) {
   636     if (obj_tag == 0) {
   707       jweak ref = entry->object();
       
   708 
   637 
   709       JvmtiTagHashmapEntry* entry_removed = hashmap->remove(o);
   638       JvmtiTagHashmapEntry* entry_removed = hashmap->remove(o);
   710       assert(entry_removed == entry, "checking");
   639       assert(entry_removed == entry, "checking");
   711       tag_map()->destroy_entry(entry);
   640       tag_map()->destroy_entry(entry);
   712 
   641 
   713       JNIHandles::destroy_weak_global(ref);
       
   714     } else {
   642     } else {
   715       if (obj_tag != entry->tag()) {
   643       if (obj_tag != entry->tag()) {
   716          entry->set_tag(obj_tag);
   644          entry->set_tag(obj_tag);
   717       }
   645       }
   718     }
   646     }
   758       _referrer_tag_p = obj_tag_p();
   686       _referrer_tag_p = obj_tag_p();
   759     } else {
   687     } else {
   760       // for Classes the klassOop is tagged
   688       // for Classes the klassOop is tagged
   761       _referrer = klassOop_if_java_lang_Class(referrer);
   689       _referrer = klassOop_if_java_lang_Class(referrer);
   762       // record the context
   690       // record the context
   763       _referrer_hashmap = tag_map->hashmap_for(_referrer);
   691       _referrer_hashmap = tag_map->hashmap();
   764       _referrer_entry = _referrer_hashmap->find(_referrer);
   692       _referrer_entry = _referrer_hashmap->find(_referrer);
   765 
   693 
   766       // get object tag
   694       // get object tag
   767       _referrer_obj_tag = (_referrer_entry == NULL) ? 0 : _referrer_entry->tag();
   695       _referrer_obj_tag = (_referrer_entry == NULL) ? 0 : _referrer_entry->tag();
   768       _referrer_tag_p = &_referrer_obj_tag;
   696       _referrer_tag_p = &_referrer_obj_tag;
   794 
   722 
   795 // tag an object
   723 // tag an object
   796 //
   724 //
   797 // This function is performance critical. If many threads attempt to tag objects
   725 // This function is performance critical. If many threads attempt to tag objects
   798 // around the same time then it's possible that the Mutex associated with the
   726 // around the same time then it's possible that the Mutex associated with the
   799 // tag map will be a hot lock. Eliminating this lock will not eliminate the issue
   727 // tag map will be a hot lock.
   800 // because creating a JNI weak reference requires acquiring a global lock also.
       
   801 void JvmtiTagMap::set_tag(jobject object, jlong tag) {
   728 void JvmtiTagMap::set_tag(jobject object, jlong tag) {
   802   MutexLocker ml(lock());
   729   MutexLocker ml(lock());
   803 
   730 
   804   // resolve the object
   731   // resolve the object
   805   oop o = JNIHandles::resolve_non_null(object);
   732   oop o = JNIHandles::resolve_non_null(object);
   806 
   733 
   807   // for Classes we tag the klassOop
   734   // for Classes we tag the klassOop
   808   o = klassOop_if_java_lang_Class(o);
   735   o = klassOop_if_java_lang_Class(o);
   809 
   736 
   810   // see if the object is already tagged
   737   // see if the object is already tagged
   811   JvmtiTagHashmap* hashmap = hashmap_for(o);
   738   JvmtiTagHashmap* hashmap = _hashmap;
   812   JvmtiTagHashmapEntry* entry = hashmap->find(o);
   739   JvmtiTagHashmapEntry* entry = hashmap->find(o);
   813 
   740 
   814   // if the object is not already tagged then we tag it
   741   // if the object is not already tagged then we tag it
   815   if (entry == NULL) {
   742   if (entry == NULL) {
   816     if (tag != 0) {
   743     if (tag != 0) {
   817       HandleMark hm;
   744       entry = create_entry(o, tag);
   818       Handle h(o);
   745       hashmap->add(o, entry);
   819       jweak ref = JNIHandles::make_weak_global(h);
       
   820 
       
   821       // the object may have moved because make_weak_global may
       
   822       // have blocked - thus it is necessary resolve the handle
       
   823       // and re-hash the object.
       
   824       o = h();
       
   825       entry = create_entry(ref, tag);
       
   826       hashmap_for(o)->add(o, entry);
       
   827     } else {
   746     } else {
   828       // no-op
   747       // no-op
   829     }
   748     }
   830   } else {
   749   } else {
   831     // if the object is already tagged then we either update
   750     // if the object is already tagged then we either update
   832     // the tag (if a new tag value has been provided)
   751     // the tag (if a new tag value has been provided)
   833     // or remove the object if the new tag value is 0.
   752     // or remove the object if the new tag value is 0.
   834     // Removing the object requires that we also delete the JNI
       
   835     // weak ref to the object.
       
   836     if (tag == 0) {
   753     if (tag == 0) {
   837       jweak ref = entry->object();
       
   838       hashmap->remove(o);
   754       hashmap->remove(o);
   839       destroy_entry(entry);
   755       destroy_entry(entry);
   840       JNIHandles::destroy_weak_global(ref);
       
   841     } else {
   756     } else {
   842       entry->set_tag(tag);
   757       entry->set_tag(tag);
   843     }
   758     }
   844   }
   759   }
   845 }
   760 }
  1624   // and record the reference and tag value.
  1539   // and record the reference and tag value.
  1625   //
  1540   //
  1626   void do_entry(JvmtiTagHashmapEntry* entry) {
  1541   void do_entry(JvmtiTagHashmapEntry* entry) {
  1627     for (int i=0; i<_tag_count; i++) {
  1542     for (int i=0; i<_tag_count; i++) {
  1628       if (_tags[i] == entry->tag()) {
  1543       if (_tags[i] == entry->tag()) {
  1629         oop o = JNIHandles::resolve(entry->object());
  1544         oop o = entry->object();
  1630         assert(o != NULL && o != JNIHandles::deleted_handle(), "sanity check");
  1545         assert(o != NULL, "sanity check");
  1631 
  1546 
  1632         // the mirror is tagged
  1547         // the mirror is tagged
  1633         if (o->is_klass()) {
  1548         if (o->is_klass()) {
  1634           klassOop k = (klassOop)o;
  1549           klassOop k = (klassOop)o;
  1635           o = Klass::cast(k)->java_mirror();
  1550           o = Klass::cast(k)->java_mirror();
  3372   VM_HeapWalkOperation op(this, initial_object, context, user_data);
  3287   VM_HeapWalkOperation op(this, initial_object, context, user_data);
  3373   VMThread::execute(&op);
  3288   VMThread::execute(&op);
  3374 }
  3289 }
  3375 
  3290 
  3376 
  3291 
  3377 // called post-GC
  3292 void JvmtiTagMap::weak_oops_do(BoolObjectClosure* is_alive, OopClosure* f) {
  3378 // - for each JVMTI environment with an object tag map, call its rehash
  3293   assert(SafepointSynchronize::is_at_safepoint(),
  3379 // function to re-sync with the new object locations.
  3294          "must be executed at a safepoint");
  3380 void JvmtiTagMap::gc_epilogue(bool full) {
       
  3381   assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
       
  3382   if (JvmtiEnv::environments_might_exist()) {
  3295   if (JvmtiEnv::environments_might_exist()) {
  3383     // re-obtain the memory region for the young generation (might
       
  3384     // changed due to adaptive resizing policy)
       
  3385     get_young_generation();
       
  3386 
       
  3387     JvmtiEnvIterator it;
  3296     JvmtiEnvIterator it;
  3388     for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
  3297     for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
  3389       JvmtiTagMap* tag_map = env->tag_map();
  3298       JvmtiTagMap* tag_map = env->tag_map();
  3390       if (tag_map != NULL && !tag_map->is_empty()) {
  3299       if (tag_map != NULL && !tag_map->is_empty()) {
  3391         TraceTime t(full ? "JVMTI Full Rehash " : "JVMTI Rehash ", TraceJVMTIObjectTagging);
  3300         tag_map->do_weak_oops(is_alive, f);
  3392         if (full) {
       
  3393           tag_map->rehash(0, n_hashmaps);
       
  3394         } else {
       
  3395           tag_map->rehash(0, 0);        // tag map for young gen only
       
  3396         }
       
  3397       }
  3301       }
  3398     }
  3302     }
  3399   }
  3303   }
  3400 }
  3304 }
  3401 
  3305 
  3402 // CMS has completed referencing processing so we may have JNI weak refs
  3306 void JvmtiTagMap::do_weak_oops(BoolObjectClosure* is_alive, OopClosure* f) {
  3403 // to objects in the CMS generation that have been GC'ed.
       
  3404 void JvmtiTagMap::cms_ref_processing_epilogue() {
       
  3405   assert(SafepointSynchronize::is_at_safepoint(), "must be executed at a safepoint");
       
  3406   assert(UseConcMarkSweepGC, "should only be used with CMS");
       
  3407   if (JvmtiEnv::environments_might_exist()) {
       
  3408     JvmtiEnvIterator it;
       
  3409     for (JvmtiEnvBase* env = it.first(); env != NULL; env = it.next(env)) {
       
  3410       JvmtiTagMap* tag_map = ((JvmtiEnvBase *)env)->tag_map();
       
  3411       if (tag_map != NULL && !tag_map->is_empty()) {
       
  3412         TraceTime t("JVMTI Rehash (CMS) ", TraceJVMTIObjectTagging);
       
  3413         tag_map->rehash(1, n_hashmaps);    // assume CMS not used in young gen
       
  3414       }
       
  3415     }
       
  3416   }
       
  3417 }
       
  3418 
       
  3419 
       
  3420 // For each entry in the hashmaps 'start' to 'end' :
       
  3421 //
       
  3422 // 1. resolve the JNI weak reference
       
  3423 //
       
  3424 // 2. If it resolves to NULL it means the object has been freed so the entry
       
  3425 //    is removed, the weak reference destroyed, and the object free event is
       
  3426 //    posted (if enabled).
       
  3427 //
       
  3428 // 3. If the weak reference resolves to an object then we re-hash the object
       
  3429 //    to see if it has moved or has been promoted (from the young to the old
       
  3430 //    generation for example).
       
  3431 //
       
  3432 void JvmtiTagMap::rehash(int start, int end) {
       
  3433 
  3307 
  3434   // does this environment have the OBJECT_FREE event enabled
  3308   // does this environment have the OBJECT_FREE event enabled
  3435   bool post_object_free = env()->is_enabled(JVMTI_EVENT_OBJECT_FREE);
  3309   bool post_object_free = env()->is_enabled(JVMTI_EVENT_OBJECT_FREE);
  3436 
  3310 
  3437   // counters used for trace message
  3311   // counters used for trace message
  3438   int freed = 0;
  3312   int freed = 0;
  3439   int moved = 0;
  3313   int moved = 0;
  3440   int promoted = 0;
  3314 
  3441 
  3315   JvmtiTagHashmap* hashmap = this->hashmap();
  3442   // we assume there are two hashmaps - one for the young generation
       
  3443   // and the other for all other spaces.
       
  3444   assert(n_hashmaps == 2, "not implemented");
       
  3445   JvmtiTagHashmap* young_hashmap = _hashmap[0];
       
  3446   JvmtiTagHashmap* other_hashmap = _hashmap[1];
       
  3447 
  3316 
  3448   // reenable sizing (if disabled)
  3317   // reenable sizing (if disabled)
  3449   young_hashmap->set_resizing_enabled(true);
  3318   hashmap->set_resizing_enabled(true);
  3450   other_hashmap->set_resizing_enabled(true);
  3319 
  3451 
  3320   // if the hashmap is empty then we can skip it
  3452   // when re-hashing the hashmap corresponding to the young generation we
  3321   if (hashmap->_entry_count == 0) {
  3453   // collect the entries corresponding to objects that have been promoted.
  3322     return;
  3454   JvmtiTagHashmapEntry* promoted_entries = NULL;
  3323   }
  3455 
  3324 
  3456   if (end >= n_hashmaps) {
  3325   // now iterate through each entry in the table
  3457     end = n_hashmaps - 1;
  3326 
  3458   }
  3327   JvmtiTagHashmapEntry** table = hashmap->table();
  3459 
  3328   int size = hashmap->size();
  3460   for (int i=start; i <= end; i++) {
  3329 
  3461     JvmtiTagHashmap* hashmap = _hashmap[i];
  3330   JvmtiTagHashmapEntry* delayed_add = NULL;
  3462 
  3331 
  3463     // if the hashmap is empty then we can skip it
  3332   for (int pos = 0; pos < size; ++pos) {
  3464     if (hashmap->_entry_count == 0) {
  3333     JvmtiTagHashmapEntry* entry = table[pos];
  3465       continue;
  3334     JvmtiTagHashmapEntry* prev = NULL;
  3466     }
  3335 
  3467 
  3336     while (entry != NULL) {
  3468     // now iterate through each entry in the table
  3337       JvmtiTagHashmapEntry* next = entry->next();
  3469 
  3338 
  3470     JvmtiTagHashmapEntry** table = hashmap->table();
  3339       oop* obj = entry->object_addr();
  3471     int size = hashmap->size();
  3340 
  3472 
  3341       // has object been GC'ed
  3473     for (int pos=0; pos<size; pos++) {
  3342       if (!is_alive->do_object_b(entry->object())) {
  3474       JvmtiTagHashmapEntry* entry = table[pos];
  3343         // grab the tag
  3475       JvmtiTagHashmapEntry* prev = NULL;
  3344         jlong tag = entry->tag();
  3476 
  3345         guarantee(tag != 0, "checking");
  3477       while (entry != NULL) {
  3346 
  3478         JvmtiTagHashmapEntry* next = entry->next();
  3347         // remove GC'ed entry from hashmap and return the
  3479 
  3348         // entry to the free list
  3480         jweak ref = entry->object();
  3349         hashmap->remove(prev, pos, entry);
  3481         oop oop = JNIHandles::resolve(ref);
  3350         destroy_entry(entry);
  3482 
  3351 
  3483         // has object been GC'ed
  3352         // post the event to the profiler
  3484         if (oop == NULL) {
  3353         if (post_object_free) {
  3485           // grab the tag
  3354           JvmtiExport::post_object_free(env(), tag);
  3486           jlong tag = entry->tag();
  3355         }
  3487           guarantee(tag != 0, "checking");
  3356 
  3488 
  3357         ++freed;
  3489           // remove GC'ed entry from hashmap and return the
  3358       } else {
  3490           // entry to the free list
  3359         f->do_oop(entry->object_addr());
  3491           hashmap->remove(prev, pos, entry);
  3360         oop new_oop = entry->object();
  3492           destroy_entry(entry);
  3361 
  3493 
  3362         // if the object has moved then re-hash it and move its
  3494           // destroy the weak ref
  3363         // entry to its new location.
  3495           JNIHandles::destroy_weak_global(ref);
  3364         unsigned int new_pos = JvmtiTagHashmap::hash(new_oop, size);
  3496 
  3365         if (new_pos != (unsigned int)pos) {
  3497           // post the event to the profiler
  3366           if (prev == NULL) {
  3498           if (post_object_free) {
  3367             table[pos] = next;
  3499             JvmtiExport::post_object_free(env(), tag);
  3368           } else {
       
  3369             prev->set_next(next);
  3500           }
  3370           }
  3501 
  3371           if (new_pos < (unsigned int)pos) {
  3502           freed++;
       
  3503           entry = next;
       
  3504           continue;
       
  3505         }
       
  3506 
       
  3507         // if this is the young hashmap then the object is either promoted
       
  3508         // or moved.
       
  3509         // if this is the other hashmap then the object is moved.
       
  3510 
       
  3511         bool same_gen;
       
  3512         if (i == 0) {
       
  3513           assert(hashmap == young_hashmap, "checking");
       
  3514           same_gen = is_in_young(oop);
       
  3515         } else {
       
  3516           same_gen = true;
       
  3517         }
       
  3518 
       
  3519 
       
  3520         if (same_gen) {
       
  3521           // if the object has moved then re-hash it and move its
       
  3522           // entry to its new location.
       
  3523           unsigned int new_pos = JvmtiTagHashmap::hash(oop, size);
       
  3524           if (new_pos != (unsigned int)pos) {
       
  3525             if (prev == NULL) {
       
  3526               table[pos] = next;
       
  3527             } else {
       
  3528               prev->set_next(next);
       
  3529             }
       
  3530             entry->set_next(table[new_pos]);
  3372             entry->set_next(table[new_pos]);
  3531             table[new_pos] = entry;
  3373             table[new_pos] = entry;
  3532             moved++;
       
  3533           } else {
  3374           } else {
  3534             // object didn't move
  3375             // Delay adding this entry to it's new position as we'd end up
  3535             prev = entry;
  3376             // hitting it again during this iteration.
       
  3377             entry->set_next(delayed_add);
       
  3378             delayed_add = entry;
  3536           }
  3379           }
       
  3380           moved++;
  3537         } else {
  3381         } else {
  3538           // object has been promoted so remove the entry from the
  3382           // object didn't move
  3539           // young hashmap
  3383           prev = entry;
  3540           assert(hashmap == young_hashmap, "checking");
       
  3541           hashmap->remove(prev, pos, entry);
       
  3542 
       
  3543           // move the entry to the promoted list
       
  3544           entry->set_next(promoted_entries);
       
  3545           promoted_entries = entry;
       
  3546         }
  3384         }
  3547 
       
  3548         entry = next;
       
  3549       }
  3385       }
  3550     }
  3386 
  3551   }
  3387       entry = next;
  3552 
  3388     }
  3553 
  3389   }
  3554   // add the entries, corresponding to the promoted objects, to the
  3390 
  3555   // other hashmap.
  3391   // Re-add all the entries which were kept aside
  3556   JvmtiTagHashmapEntry* entry = promoted_entries;
  3392   while (delayed_add != NULL) {
  3557   while (entry != NULL) {
  3393     JvmtiTagHashmapEntry* next = delayed_add->next();
  3558     oop o = JNIHandles::resolve(entry->object());
  3394     unsigned int pos = JvmtiTagHashmap::hash(delayed_add->object(), size);
  3559     assert(hashmap_for(o) == other_hashmap, "checking");
  3395     delayed_add->set_next(table[pos]);
  3560     JvmtiTagHashmapEntry* next = entry->next();
  3396     table[pos] = delayed_add;
  3561     other_hashmap->add(o, entry);
  3397     delayed_add = next;
  3562     entry = next;
       
  3563     promoted++;
       
  3564   }
  3398   }
  3565 
  3399 
  3566   // stats
  3400   // stats
  3567   if (TraceJVMTIObjectTagging) {
  3401   if (TraceJVMTIObjectTagging) {
  3568     int total_moves = promoted + moved;
  3402     int post_total = hashmap->_entry_count;
  3569 
       
  3570     int post_total = 0;
       
  3571     for (int i=0; i<n_hashmaps; i++) {
       
  3572       post_total += _hashmap[i]->_entry_count;
       
  3573     }
       
  3574     int pre_total = post_total + freed;
  3403     int pre_total = post_total + freed;
  3575 
  3404 
  3576     tty->print("(%d->%d, %d freed, %d promoted, %d total moves)",
  3405     tty->print_cr("(%d->%d, %d freed, %d total moves)",
  3577         pre_total, post_total, freed, promoted, total_moves);
  3406         pre_total, post_total, freed, moved);
  3578   }
  3407   }
  3579 }
  3408 }