1 /*
   2  * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  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 #include "precompiled.hpp"
  25 #include "code/relocInfo.hpp"
  26 #include "code/nmethod.hpp"
  27 #include "code/icBuffer.hpp"
  28 #include "gc/shared/barrierSet.hpp"
  29 #include "gc/shared/barrierSetNMethod.hpp"
  30 #include "gc/z/zGlobals.hpp"
  31 #include "gc/z/zLock.inline.hpp"
  32 #include "gc/z/zNMethod.hpp"
  33 #include "gc/z/zNMethodData.hpp"
  34 #include "gc/z/zNMethodTable.hpp"
  35 #include "gc/z/zOopClosures.inline.hpp"
  36 #include "gc/z/zTask.hpp"
  37 #include "gc/z/zWorkers.hpp"
  38 #include "logging/log.hpp"
  39 #include "memory/allocation.inline.hpp"
  40 #include "memory/iterator.hpp"
  41 #include "memory/resourceArea.hpp"
  42 #include "runtime/atomic.hpp"
  43 #include "runtime/orderAccess.hpp"
  44 #include "utilities/debug.hpp"
  45 
  46 static ZNMethodData* gc_data(const nmethod* nm) {
  47   return nm->gc_data<ZNMethodData>();
  48 }
  49 
  50 static void set_gc_data(nmethod* nm, ZNMethodData* data) {
  51   return nm->set_gc_data<ZNMethodData>(data);
  52 }
  53 
  54 void ZNMethod::attach_gc_data(nmethod* nm) {
  55   GrowableArray<oop*> immediate_oops;
  56   bool non_immediate_oops = false;
  57 
  58   // Find all oops relocations
  59   RelocIterator iter(nm);
  60   while (iter.next()) {
  61     if (iter.type() != relocInfo::oop_type) {
  62       // Not an oop
  63       continue;
  64     }
  65 
  66     oop_Relocation* r = iter.oop_reloc();
  67 
  68     if (!r->oop_is_immediate()) {
  69       // Non-immediate oop found
  70       non_immediate_oops = true;
  71       continue;
  72     }
  73 
  74     if (r->oop_value() != NULL) {
  75       // Non-NULL immediate oop found. NULL oops can safely be
  76       // ignored since the method will be re-registered if they
  77       // are later patched to be non-NULL.
  78       immediate_oops.push(r->oop_addr());
  79     }
  80   }
  81 
  82   // Attach GC data to nmethod
  83   ZNMethodData* data = gc_data(nm);
  84   if (data == NULL) {
  85     data = new ZNMethodData();
  86     set_gc_data(nm, data);
  87   }
  88 
  89   // Attach oops in GC data
  90   ZNMethodDataOops* const new_oops = ZNMethodDataOops::create(immediate_oops, non_immediate_oops);
  91   ZNMethodDataOops* const old_oops = data->swap_oops(new_oops);
  92   ZNMethodDataOops::destroy(old_oops);
  93 }
  94 
  95 ZReentrantLock* ZNMethod::lock_for_nmethod(nmethod* nm) {
  96   return gc_data(nm)->lock();
  97 }
  98 
  99 void ZNMethod::log_register(const nmethod* nm) {
 100   LogTarget(Trace, gc, nmethod) log;
 101   if (!log.is_enabled()) {
 102     return;
 103   }
 104 
 105   const ZNMethodDataOops* const oops = gc_data(nm)->oops();
 106 
 107   log.print("Register NMethod: %s.%s (" PTR_FORMAT "), "
 108             "Compiler: %s, Oops: %d, ImmediateOops: " SIZE_FORMAT ", NonImmediateOops: %s",
 109             nm->method()->method_holder()->external_name(),
 110             nm->method()->name()->as_C_string(),
 111             p2i(nm),
 112             nm->compiler_name(),
 113             nm->oops_count() - 1,
 114             oops->immediates_count(),
 115             oops->has_non_immediates() ? "Yes" : "No");
 116 
 117   LogTarget(Trace, gc, nmethod, oops) log_oops;
 118   if (!log_oops.is_enabled()) {
 119     return;
 120   }
 121 
 122   // Print nmethod oops table
 123   {
 124     oop* const begin = nm->oops_begin();
 125     oop* const end = nm->oops_end();
 126     for (oop* p = begin; p < end; p++) {
 127       log_oops.print("           Oop[" SIZE_FORMAT "] " PTR_FORMAT " (%s)",
 128                      (p - begin), p2i(*p), (*p)->klass()->external_name());
 129     }
 130   }
 131 
 132   // Print nmethod immediate oops
 133   {
 134     oop** const begin = oops->immediates_begin();
 135     oop** const end = oops->immediates_end();
 136     for (oop** p = begin; p < end; p++) {
 137       log_oops.print("  ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)",
 138                      (p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name());
 139     }
 140   }
 141 }
 142 
 143 void ZNMethod::log_unregister(const nmethod* nm) {
 144   LogTarget(Debug, gc, nmethod) log;
 145   if (!log.is_enabled()) {
 146     return;
 147   }
 148 
 149   log.print("Unregister NMethod: %s.%s (" PTR_FORMAT ")",
 150             nm->method()->method_holder()->external_name(),
 151             nm->method()->name()->as_C_string(),
 152             p2i(nm));
 153 }
 154 
 155 void ZNMethod::register_nmethod(nmethod* nm) {
 156   ResourceMark rm;
 157 
 158   // Create and attach gc data
 159   attach_gc_data(nm);
 160 
 161   log_register(nm);
 162 
 163   ZNMethodTable::register_nmethod(nm);
 164 
 165   // Disarm nmethod entry barrier
 166   disarm_nmethod(nm);
 167 }
 168 
 169 void ZNMethod::unregister_nmethod(nmethod* nm) {
 170   assert(CodeCache_lock->owned_by_self(), "Lock must be held");
 171 
 172   if (Thread::current()->is_Code_cache_sweeper_thread()) {
 173     // The sweeper must wait for any ongoing iteration to complete
 174     // before it can unregister an nmethod.
 175     ZNMethodTable::wait_until_iteration_done();
 176   }
 177 
 178   ResourceMark rm;
 179 
 180   log_unregister(nm);
 181 
 182   ZNMethodTable::unregister_nmethod(nm);
 183 }
 184 
 185 void ZNMethod::flush_nmethod(nmethod* nm) {
 186   // Destroy GC data
 187   delete gc_data(nm);
 188 }
 189 
 190 void ZNMethod::disarm_nmethod(nmethod* nm) {
 191   BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
 192   if (bs != NULL) {
 193     bs->disarm(nm);
 194   }
 195 }
 196 
 197 void ZNMethod::nmethod_oops_do(nmethod* nm, OopClosure* cl) {
 198   // Process oops table
 199   {
 200     oop* const begin = nm->oops_begin();
 201     oop* const end = nm->oops_end();
 202     for (oop* p = begin; p < end; p++) {
 203       if (*p != Universe::non_oop_word()) {
 204         cl->do_oop(p);
 205       }
 206     }
 207   }
 208 
 209   ZNMethodDataOops* const oops = gc_data(nm)->oops();
 210 
 211   // Process immediate oops
 212   {
 213     oop** const begin = oops->immediates_begin();
 214     oop** const end = oops->immediates_end();
 215     for (oop** p = begin; p < end; p++) {
 216       if (**p != Universe::non_oop_word()) {
 217         cl->do_oop(*p);
 218       }
 219     }
 220   }
 221 
 222   // Process non-immediate oops
 223   if (oops->has_non_immediates()) {
 224     nm->fix_oop_relocations();
 225   }
 226 }
 227 
 228 class ZNMethodToOopsDoClosure : public NMethodClosure {
 229 private:
 230   OopClosure* _cl;
 231 
 232 public:
 233   ZNMethodToOopsDoClosure(OopClosure* cl) :
 234       _cl(cl) {}
 235 
 236   virtual void do_nmethod(nmethod* nm) {
 237     ZNMethod::nmethod_oops_do(nm, _cl);
 238   }
 239 };
 240 
 241 void ZNMethod::oops_do_begin() {
 242   ZNMethodTable::nmethods_do_begin();
 243 }
 244 
 245 void ZNMethod::oops_do_end() {
 246   ZNMethodTable::nmethods_do_end();
 247 }
 248 
 249 void ZNMethod::oops_do(OopClosure* cl) {
 250   ZNMethodToOopsDoClosure nmethod_cl(cl);
 251   ZNMethodTable::nmethods_do(&nmethod_cl);
 252 }
 253 
 254 class ZNMethodUnlinkClosure : public NMethodClosure {
 255 private:
 256   bool          _unloading_occurred;
 257   volatile bool _failed;
 258 
 259   void set_failed() {
 260     Atomic::store(true, &_failed);
 261   }
 262 
 263 public:
 264   ZNMethodUnlinkClosure(bool unloading_occurred) :
 265       _unloading_occurred(unloading_occurred),
 266       _failed(false) {}
 267 
 268   virtual void do_nmethod(nmethod* nm) {
 269     if (failed()) {
 270       return;
 271     }
 272 
 273     if (!nm->is_alive()) {
 274       return;
 275     }
 276 
 277     ZLocker<ZReentrantLock> locker(ZNMethod::lock_for_nmethod(nm));
 278 
 279     if (nm->is_unloading()) {
 280       // Unlinking of the dependencies must happen before the
 281       // handshake separating unlink and purge.
 282       nm->flush_dependencies(false /* delete_immediately */);
 283 
 284       // We don't need to take the lock when unlinking nmethods from
 285       // the Method, because it is only concurrently unlinked by
 286       // the entry barrier, which acquires the per nmethod lock.
 287       nm->unlink_from_method();
 288       return;
 289     }
 290 
 291     // Heal oops and disarm
 292     ZNMethodOopClosure cl;
 293     ZNMethod::nmethod_oops_do(nm, &cl);
 294     ZNMethod::disarm_nmethod(nm);
 295 
 296     // Clear compiled ICs and exception caches
 297     if (!nm->unload_nmethod_caches(_unloading_occurred)) {
 298       set_failed();
 299     }
 300   }
 301 
 302   bool failed() const {
 303     return Atomic::load(&_failed);
 304   }
 305 };
 306 
 307 class ZNMethodUnlinkTask : public ZTask {
 308 private:
 309   ZNMethodUnlinkClosure _cl;
 310   ICRefillVerifier*     _verifier;
 311 
 312 public:
 313   ZNMethodUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
 314       ZTask("ZNMethodUnlinkTask"),
 315       _cl(unloading_occurred),
 316       _verifier(verifier) {
 317     ZNMethodTable::nmethods_do_begin();
 318   }
 319 
 320   ~ZNMethodUnlinkTask() {
 321     ZNMethodTable::nmethods_do_end();
 322   }
 323 
 324   virtual void work() {
 325     ICRefillVerifierMark mark(_verifier);
 326     ZNMethodTable::nmethods_do(&_cl);
 327   }
 328 
 329   bool success() const {
 330     return !_cl.failed();
 331   }
 332 };
 333 
 334 void ZNMethod::unlink(ZWorkers* workers, bool unloading_occurred) {
 335   for (;;) {
 336     ICRefillVerifier verifier;
 337 
 338     {
 339       ZNMethodUnlinkTask task(unloading_occurred, &verifier);
 340       workers->run_concurrent(&task);
 341       if (task.success()) {
 342         return;
 343       }
 344     }
 345 
 346     // Cleaning failed because we ran out of transitional IC stubs,
 347     // so we have to refill and try again. Refilling requires taking
 348     // a safepoint, so we temporarily leave the suspendible thread set.
 349     SuspendibleThreadSetLeaver sts;
 350     InlineCacheBuffer::refill_ic_stubs();
 351   }
 352 }
 353 
 354 class ZNMethodPurgeClosure : public NMethodClosure {
 355 public:
 356   virtual void do_nmethod(nmethod* nm) {
 357     if (nm->is_alive() && nm->is_unloading()) {
 358       nm->make_unloaded();
 359     }
 360   }
 361 };
 362 
 363 class ZNMethodPurgeTask : public ZTask {
 364 private:
 365   ZNMethodPurgeClosure _cl;
 366 
 367 public:
 368   ZNMethodPurgeTask() :
 369       ZTask("ZNMethodPurgeTask"),
 370       _cl() {
 371     ZNMethodTable::nmethods_do_begin();
 372   }
 373 
 374   ~ZNMethodPurgeTask() {
 375     ZNMethodTable::nmethods_do_end();
 376   }
 377 
 378   virtual void work() {
 379     ZNMethodTable::nmethods_do(&_cl);
 380   }
 381 };
 382 
 383 void ZNMethod::purge(ZWorkers* workers) {
 384   ZNMethodPurgeTask task;
 385   workers->run_concurrent(&task);
 386 }