src/hotspot/share/gc/z/zNMethodTable.cpp
changeset 53894 bf1133e7dfba
parent 53893 ad56513c7e07
child 54175 36e0665773e7
equal deleted inserted replaced
53893:ad56513c7e07 53894:bf1133e7dfba
    31 #include "gc/z/zHash.inline.hpp"
    31 #include "gc/z/zHash.inline.hpp"
    32 #include "gc/z/zLock.inline.hpp"
    32 #include "gc/z/zLock.inline.hpp"
    33 #include "gc/z/zNMethodAllocator.hpp"
    33 #include "gc/z/zNMethodAllocator.hpp"
    34 #include "gc/z/zNMethodData.hpp"
    34 #include "gc/z/zNMethodData.hpp"
    35 #include "gc/z/zNMethodTable.hpp"
    35 #include "gc/z/zNMethodTable.hpp"
       
    36 #include "gc/z/zNMethodTableEntry.hpp"
    36 #include "gc/z/zNMethodTableIteration.hpp"
    37 #include "gc/z/zNMethodTableIteration.hpp"
    37 #include "gc/z/zOopClosures.inline.hpp"
    38 #include "gc/z/zOopClosures.inline.hpp"
    38 #include "gc/z/zTask.hpp"
    39 #include "gc/z/zTask.hpp"
    39 #include "gc/z/zWorkers.hpp"
    40 #include "gc/z/zWorkers.hpp"
    40 #include "logging/log.hpp"
    41 #include "logging/log.hpp"
    49 size_t ZNMethodTable::_size = 0;
    50 size_t ZNMethodTable::_size = 0;
    50 size_t ZNMethodTable::_nregistered = 0;
    51 size_t ZNMethodTable::_nregistered = 0;
    51 size_t ZNMethodTable::_nunregistered = 0;
    52 size_t ZNMethodTable::_nunregistered = 0;
    52 ZNMethodTableIteration ZNMethodTable::_iteration;
    53 ZNMethodTableIteration ZNMethodTable::_iteration;
    53 
    54 
    54 static ZNMethodData* gc_data(const nmethod* nm) {
       
    55   return nm->gc_data<ZNMethodData>();
       
    56 }
       
    57 
       
    58 static void set_gc_data(nmethod* nm, ZNMethodData* data) {
       
    59   return nm->set_gc_data<ZNMethodData>(data);
       
    60 }
       
    61 
       
    62 ZNMethodTableEntry* ZNMethodTable::create(size_t size) {
    55 ZNMethodTableEntry* ZNMethodTable::create(size_t size) {
    63   void* const mem = ZNMethodAllocator::allocate(size * sizeof(ZNMethodTableEntry));
    56   void* const mem = ZNMethodAllocator::allocate(size * sizeof(ZNMethodTableEntry));
    64   return ::new (mem) ZNMethodTableEntry[size];
    57   return ::new (mem) ZNMethodTableEntry[size];
    65 }
    58 }
    66 
    59 
    67 void ZNMethodTable::destroy(ZNMethodTableEntry* table) {
    60 void ZNMethodTable::destroy(ZNMethodTableEntry* table) {
    68   ZNMethodAllocator::free(table);
    61   ZNMethodAllocator::free(table);
    69 }
       
    70 
       
    71 void ZNMethodTable::attach_gc_data(nmethod* nm) {
       
    72   GrowableArray<oop*> immediate_oops;
       
    73   bool non_immediate_oops = false;
       
    74 
       
    75   // Find all oops relocations
       
    76   RelocIterator iter(nm);
       
    77   while (iter.next()) {
       
    78     if (iter.type() != relocInfo::oop_type) {
       
    79       // Not an oop
       
    80       continue;
       
    81     }
       
    82 
       
    83     oop_Relocation* r = iter.oop_reloc();
       
    84 
       
    85     if (!r->oop_is_immediate()) {
       
    86       // Non-immediate oop found
       
    87       non_immediate_oops = true;
       
    88       continue;
       
    89     }
       
    90 
       
    91     if (r->oop_value() != NULL) {
       
    92       // Non-NULL immediate oop found. NULL oops can safely be
       
    93       // ignored since the method will be re-registered if they
       
    94       // are later patched to be non-NULL.
       
    95       immediate_oops.push(r->oop_addr());
       
    96     }
       
    97   }
       
    98 
       
    99   // Attach GC data to nmethod
       
   100   ZNMethodData* data = gc_data(nm);
       
   101   if (data == NULL) {
       
   102     data = ZNMethodData::create(nm);
       
   103     set_gc_data(nm, data);
       
   104   }
       
   105 
       
   106   // Attach oops in GC data
       
   107   ZNMethodDataOops* const new_oops = ZNMethodDataOops::create(immediate_oops, non_immediate_oops);
       
   108   ZNMethodDataOops* const old_oops = data->swap_oops(new_oops);
       
   109   ZNMethodDataOops::destroy(old_oops);
       
   110 }
       
   111 
       
   112 void ZNMethodTable::detach_gc_data(nmethod* nm) {
       
   113   // Destroy GC data
       
   114   ZNMethodData::destroy(gc_data(nm));
       
   115   set_gc_data(nm, NULL);
       
   116 }
       
   117 
       
   118 ZReentrantLock* ZNMethodTable::lock_for_nmethod(nmethod* nm) {
       
   119   ZNMethodData* const data = gc_data(nm);
       
   120   if (data == NULL) {
       
   121     return NULL;
       
   122   }
       
   123   return data->lock();
       
   124 }
    62 }
   125 
    63 
   126 size_t ZNMethodTable::first_index(const nmethod* nm, size_t size) {
    64 size_t ZNMethodTable::first_index(const nmethod* nm, size_t size) {
   127   assert(is_power_of_2(size), "Invalid size");
    65   assert(is_power_of_2(size), "Invalid size");
   128   const size_t mask = size - 1;
    66   const size_t mask = size - 1;
   236       rebuild(_size * 2);
   174       rebuild(_size * 2);
   237     }
   175     }
   238   }
   176   }
   239 }
   177 }
   240 
   178 
   241 void ZNMethodTable::log_register(const nmethod* nm) {
       
   242   LogTarget(Trace, gc, nmethod) log;
       
   243   if (!log.is_enabled()) {
       
   244     return;
       
   245   }
       
   246 
       
   247   const ZNMethodDataOops* const oops = gc_data(nm)->oops();
       
   248 
       
   249   log.print("Register NMethod: %s.%s (" PTR_FORMAT "), "
       
   250             "Compiler: %s, Oops: %d, ImmediateOops: " SIZE_FORMAT ", NonImmediateOops: %s",
       
   251             nm->method()->method_holder()->external_name(),
       
   252             nm->method()->name()->as_C_string(),
       
   253             p2i(nm),
       
   254             nm->compiler_name(),
       
   255             nm->oops_count() - 1,
       
   256             oops->immediates_count(),
       
   257             oops->has_non_immediates() ? "Yes" : "No");
       
   258 
       
   259   LogTarget(Trace, gc, nmethod, oops) log_oops;
       
   260   if (!log_oops.is_enabled()) {
       
   261     return;
       
   262   }
       
   263 
       
   264   // Print nmethod oops table
       
   265   {
       
   266     oop* const begin = nm->oops_begin();
       
   267     oop* const end = nm->oops_end();
       
   268     for (oop* p = begin; p < end; p++) {
       
   269       log_oops.print("           Oop[" SIZE_FORMAT "] " PTR_FORMAT " (%s)",
       
   270                      (p - begin), p2i(*p), (*p)->klass()->external_name());
       
   271     }
       
   272   }
       
   273 
       
   274   // Print nmethod immediate oops
       
   275   {
       
   276     oop** const begin = oops->immediates_begin();
       
   277     oop** const end = oops->immediates_end();
       
   278     for (oop** p = begin; p < end; p++) {
       
   279       log_oops.print("  ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)",
       
   280                      (p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name());
       
   281     }
       
   282   }
       
   283 }
       
   284 
       
   285 void ZNMethodTable::log_unregister(const nmethod* nm) {
       
   286   LogTarget(Debug, gc, nmethod) log;
       
   287   if (!log.is_enabled()) {
       
   288     return;
       
   289   }
       
   290 
       
   291   log.print("Unregister NMethod: %s.%s (" PTR_FORMAT ")",
       
   292             nm->method()->method_holder()->external_name(),
       
   293             nm->method()->name()->as_C_string(),
       
   294             p2i(nm));
       
   295 }
       
   296 
       
   297 size_t ZNMethodTable::registered_nmethods() {
   179 size_t ZNMethodTable::registered_nmethods() {
   298   return _nregistered;
   180   return _nregistered;
   299 }
   181 }
   300 
   182 
   301 size_t ZNMethodTable::unregistered_nmethods() {
   183 size_t ZNMethodTable::unregistered_nmethods() {
   302   return _nunregistered;
   184   return _nunregistered;
   303 }
   185 }
   304 
   186 
   305 void ZNMethodTable::register_nmethod(nmethod* nm) {
   187 void ZNMethodTable::register_nmethod(nmethod* nm) {
   306   assert(CodeCache_lock->owned_by_self(), "Lock must be held");
   188   assert(CodeCache_lock->owned_by_self(), "Lock must be held");
   307   ResourceMark rm;
       
   308 
   189 
   309   // Grow/Shrink/Prune table if needed
   190   // Grow/Shrink/Prune table if needed
   310   rebuild_if_needed();
   191   rebuild_if_needed();
   311 
       
   312   // Create and attach gc data
       
   313   attach_gc_data(nm);
       
   314 
       
   315   log_register(nm);
       
   316 
   192 
   317   // Insert new entry
   193   // Insert new entry
   318   if (register_entry(_table, _size, nm)) {
   194   if (register_entry(_table, _size, nm)) {
   319     // New entry registered. When register_entry() instead returns
   195     // New entry registered. When register_entry() instead returns
   320     // false the nmethod was already in the table so we do not want
   196     // false the nmethod was already in the table so we do not want
   321     // to increase number of registered entries in that case.
   197     // to increase number of registered entries in that case.
   322     _nregistered++;
   198     _nregistered++;
   323   }
   199   }
   324 
       
   325   // Disarm nmethod entry barrier
       
   326   disarm_nmethod(nm);
       
   327 }
   200 }
   328 
   201 
   329 void ZNMethodTable::wait_until_iteration_done() {
   202 void ZNMethodTable::wait_until_iteration_done() {
   330   assert(CodeCache_lock->owned_by_self(), "Lock must be held");
   203   assert(CodeCache_lock->owned_by_self(), "Lock must be held");
   331 
   204 
   334   }
   207   }
   335 }
   208 }
   336 
   209 
   337 void ZNMethodTable::unregister_nmethod(nmethod* nm) {
   210 void ZNMethodTable::unregister_nmethod(nmethod* nm) {
   338   assert(CodeCache_lock->owned_by_self(), "Lock must be held");
   211   assert(CodeCache_lock->owned_by_self(), "Lock must be held");
   339 
       
   340   if (Thread::current()->is_Code_cache_sweeper_thread()) {
       
   341     // The sweeper must wait for any ongoing iteration to complete
       
   342     // before it can unregister an nmethod.
       
   343     ZNMethodTable::wait_until_iteration_done();
       
   344   }
       
   345 
       
   346   ResourceMark rm;
       
   347 
       
   348   log_unregister(nm);
       
   349 
   212 
   350   // Remove entry
   213   // Remove entry
   351   unregister_entry(_table, _size, nm);
   214   unregister_entry(_table, _size, nm);
   352   _nunregistered++;
   215   _nunregistered++;
   353   _nregistered--;
   216   _nregistered--;
   354 
       
   355   detach_gc_data(nm);
       
   356 }
       
   357 
       
   358 void ZNMethodTable::disarm_nmethod(nmethod* nm) {
       
   359   BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
       
   360   if (bs != NULL) {
       
   361     bs->disarm(nm);
       
   362   }
       
   363 }
   217 }
   364 
   218 
   365 void ZNMethodTable::nmethods_do_begin() {
   219 void ZNMethodTable::nmethods_do_begin() {
   366   MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   220   MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   367 
   221 
   383 
   237 
   384   // Notify iteration done
   238   // Notify iteration done
   385   CodeCache_lock->notify_all();
   239   CodeCache_lock->notify_all();
   386 }
   240 }
   387 
   241 
   388 void ZNMethodTable::oops_do(nmethod* nm, OopClosure* cl) {
       
   389   // Process oops table
       
   390   {
       
   391     oop* const begin = nm->oops_begin();
       
   392     oop* const end = nm->oops_end();
       
   393     for (oop* p = begin; p < end; p++) {
       
   394       if (*p != Universe::non_oop_word()) {
       
   395         cl->do_oop(p);
       
   396       }
       
   397     }
       
   398   }
       
   399 
       
   400   ZNMethodDataOops* const oops = gc_data(nm)->oops();
       
   401 
       
   402   // Process immediate oops
       
   403   {
       
   404     oop** const begin = oops->immediates_begin();
       
   405     oop** const end = oops->immediates_end();
       
   406     for (oop** p = begin; p < end; p++) {
       
   407       if (**p != Universe::non_oop_word()) {
       
   408         cl->do_oop(*p);
       
   409       }
       
   410     }
       
   411   }
       
   412 
       
   413   // Process non-immediate oops
       
   414   if (oops->has_non_immediates()) {
       
   415     nm->fix_oop_relocations();
       
   416   }
       
   417 }
       
   418 
       
   419 class ZNMethodToOopsDoClosure : public NMethodClosure {
       
   420 private:
       
   421   OopClosure* _cl;
       
   422 
       
   423 public:
       
   424   ZNMethodToOopsDoClosure(OopClosure* cl) :
       
   425       _cl(cl) {}
       
   426 
       
   427   virtual void do_nmethod(nmethod* nm) {
       
   428     ZNMethodTable::oops_do(nm, _cl);
       
   429   }
       
   430 };
       
   431 
       
   432 void ZNMethodTable::oops_do(OopClosure* cl) {
       
   433   ZNMethodToOopsDoClosure nm_cl(cl);
       
   434   nmethods_do(&nm_cl);
       
   435 }
       
   436 
       
   437 void ZNMethodTable::nmethods_do(NMethodClosure* cl) {
   242 void ZNMethodTable::nmethods_do(NMethodClosure* cl) {
   438   _iteration.nmethods_do(cl);
   243   _iteration.nmethods_do(cl);
   439 }
   244 }
   440 
       
   441 class ZNMethodTableUnlinkClosure : public NMethodClosure {
       
   442 private:
       
   443   bool          _unloading_occurred;
       
   444   volatile bool _failed;
       
   445 
       
   446   void set_failed() {
       
   447     Atomic::store(true, &_failed);
       
   448   }
       
   449 
       
   450 public:
       
   451   ZNMethodTableUnlinkClosure(bool unloading_occurred) :
       
   452       _unloading_occurred(unloading_occurred),
       
   453       _failed(false) {}
       
   454 
       
   455   virtual void do_nmethod(nmethod* nm) {
       
   456     if (failed()) {
       
   457       return;
       
   458     }
       
   459 
       
   460     if (!nm->is_alive()) {
       
   461       return;
       
   462     }
       
   463 
       
   464     ZLocker<ZReentrantLock> locker(ZNMethodTable::lock_for_nmethod(nm));
       
   465 
       
   466     if (nm->is_unloading()) {
       
   467       // Unlinking of the dependencies must happen before the
       
   468       // handshake separating unlink and purge.
       
   469       nm->flush_dependencies(false /* delete_immediately */);
       
   470 
       
   471       // We don't need to take the lock when unlinking nmethods from
       
   472       // the Method, because it is only concurrently unlinked by
       
   473       // the entry barrier, which acquires the per nmethod lock.
       
   474       nm->unlink_from_method(false /* acquire_lock */);
       
   475       return;
       
   476     }
       
   477 
       
   478     // Heal oops and disarm
       
   479     ZNMethodOopClosure cl;
       
   480     ZNMethodTable::oops_do(nm, &cl);
       
   481     ZNMethodTable::disarm_nmethod(nm);
       
   482 
       
   483     // Clear compiled ICs and exception caches
       
   484     if (!nm->unload_nmethod_caches(_unloading_occurred)) {
       
   485       set_failed();
       
   486     }
       
   487   }
       
   488 
       
   489   bool failed() const {
       
   490     return Atomic::load(&_failed);
       
   491   }
       
   492 };
       
   493 
       
   494 class ZNMethodTableUnlinkTask : public ZTask {
       
   495 private:
       
   496   ZNMethodTableUnlinkClosure _cl;
       
   497   ICRefillVerifier*          _verifier;
       
   498 
       
   499 public:
       
   500   ZNMethodTableUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
       
   501       ZTask("ZNMethodTableUnlinkTask"),
       
   502       _cl(unloading_occurred),
       
   503       _verifier(verifier) {
       
   504     ZNMethodTable::nmethods_do_begin();
       
   505   }
       
   506 
       
   507   ~ZNMethodTableUnlinkTask() {
       
   508     ZNMethodTable::nmethods_do_end();
       
   509   }
       
   510 
       
   511   virtual void work() {
       
   512     ICRefillVerifierMark mark(_verifier);
       
   513     ZNMethodTable::nmethods_do(&_cl);
       
   514   }
       
   515 
       
   516   bool success() const {
       
   517     return !_cl.failed();
       
   518   }
       
   519 };
       
   520 
       
   521 void ZNMethodTable::unlink(ZWorkers* workers, bool unloading_occurred) {
       
   522   for (;;) {
       
   523     ICRefillVerifier verifier;
       
   524 
       
   525     {
       
   526       ZNMethodTableUnlinkTask task(unloading_occurred, &verifier);
       
   527       workers->run_concurrent(&task);
       
   528       if (task.success()) {
       
   529         return;
       
   530       }
       
   531     }
       
   532 
       
   533     // Cleaning failed because we ran out of transitional IC stubs,
       
   534     // so we have to refill and try again. Refilling requires taking
       
   535     // a safepoint, so we temporarily leave the suspendible thread set.
       
   536     SuspendibleThreadSetLeaver sts;
       
   537     InlineCacheBuffer::refill_ic_stubs();
       
   538   }
       
   539 }
       
   540 
       
   541 class ZNMethodTablePurgeClosure : public NMethodClosure {
       
   542 public:
       
   543   virtual void do_nmethod(nmethod* nm) {
       
   544     if (nm->is_alive() && nm->is_unloading()) {
       
   545       nm->make_unloaded();
       
   546     }
       
   547   }
       
   548 };
       
   549 
       
   550 class ZNMethodTablePurgeTask : public ZTask {
       
   551 private:
       
   552   ZNMethodTablePurgeClosure _cl;
       
   553 
       
   554 public:
       
   555   ZNMethodTablePurgeTask() :
       
   556       ZTask("ZNMethodTablePurgeTask"),
       
   557       _cl() {
       
   558     ZNMethodTable::nmethods_do_begin();
       
   559   }
       
   560 
       
   561   ~ZNMethodTablePurgeTask() {
       
   562     ZNMethodTable::nmethods_do_end();
       
   563   }
       
   564 
       
   565   virtual void work() {
       
   566     ZNMethodTable::nmethods_do(&_cl);
       
   567   }
       
   568 };
       
   569 
       
   570 void ZNMethodTable::purge(ZWorkers* workers) {
       
   571   ZNMethodTablePurgeTask task;
       
   572   workers->run_concurrent(&task);
       
   573 }