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 "memory/universe.hpp"
  43 #include "runtime/atomic.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(&_failed, true);
 261   }
 262 
 263   void unlink(nmethod* nm) {
 264     // Unlinking of the dependencies must happen before the
 265     // handshake separating unlink and purge.
 266     nm->flush_dependencies(false /* delete_immediately */);
 267 
 268     // unlink_from_method will take the CompiledMethod_lock.
 269     // In this case we don't strictly need it when unlinking nmethods from
 270     // the Method, because it is only concurrently unlinked by
 271     // the entry barrier, which acquires the per nmethod lock.
 272     nm->unlink_from_method();
 273 
 274     if (nm->is_osr_method()) {
 275       // Invalidate the osr nmethod before the handshake. The nmethod
 276       // will be made unloaded after the handshake. Then invalidate_osr_method()
 277       // will be called again, which will be a no-op.
 278       nm->invalidate_osr_method();
 279     }
 280   }
 281 
 282 public:
 283   ZNMethodUnlinkClosure(bool unloading_occurred) :
 284       _unloading_occurred(unloading_occurred),
 285       _failed(false) {}
 286 
 287   virtual void do_nmethod(nmethod* nm) {
 288     if (failed()) {
 289       return;
 290     }
 291 
 292     if (!nm->is_alive()) {
 293       return;
 294     }
 295 
 296     if (nm->is_unloading()) {
 297       ZLocker<ZReentrantLock> locker(ZNMethod::lock_for_nmethod(nm));
 298       unlink(nm);
 299       return;
 300     }
 301 
 302     ZLocker<ZReentrantLock> locker(ZNMethod::lock_for_nmethod(nm));
 303 
 304     // Heal oops and disarm
 305     ZNMethodOopClosure cl;
 306     ZNMethod::nmethod_oops_do(nm, &cl);
 307     ZNMethod::disarm_nmethod(nm);
 308 
 309     // Clear compiled ICs and exception caches
 310     if (!nm->unload_nmethod_caches(_unloading_occurred)) {
 311       set_failed();
 312     }
 313   }
 314 
 315   bool failed() const {
 316     return Atomic::load(&_failed);
 317   }
 318 };
 319 
 320 class ZNMethodUnlinkTask : public ZTask {
 321 private:
 322   ZNMethodUnlinkClosure _cl;
 323   ICRefillVerifier*     _verifier;
 324 
 325 public:
 326   ZNMethodUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
 327       ZTask("ZNMethodUnlinkTask"),
 328       _cl(unloading_occurred),
 329       _verifier(verifier) {
 330     ZNMethodTable::nmethods_do_begin();
 331   }
 332 
 333   ~ZNMethodUnlinkTask() {
 334     ZNMethodTable::nmethods_do_end();
 335   }
 336 
 337   virtual void work() {
 338     ICRefillVerifierMark mark(_verifier);
 339     ZNMethodTable::nmethods_do(&_cl);
 340   }
 341 
 342   bool success() const {
 343     return !_cl.failed();
 344   }
 345 };
 346 
 347 void ZNMethod::unlink(ZWorkers* workers, bool unloading_occurred) {
 348   for (;;) {
 349     ICRefillVerifier verifier;
 350 
 351     {
 352       ZNMethodUnlinkTask task(unloading_occurred, &verifier);
 353       workers->run_concurrent(&task);
 354       if (task.success()) {
 355         return;
 356       }
 357     }
 358 
 359     // Cleaning failed because we ran out of transitional IC stubs,
 360     // so we have to refill and try again. Refilling requires taking
 361     // a safepoint, so we temporarily leave the suspendible thread set.
 362     SuspendibleThreadSetLeaver sts;
 363     InlineCacheBuffer::refill_ic_stubs();
 364   }
 365 }
 366 
 367 class ZNMethodPurgeClosure : public NMethodClosure {
 368 public:
 369   virtual void do_nmethod(nmethod* nm) {
 370     if (nm->is_alive() && nm->is_unloading()) {
 371       nm->make_unloaded();
 372     }
 373   }
 374 };
 375 
 376 class ZNMethodPurgeTask : public ZTask {
 377 private:
 378   ZNMethodPurgeClosure _cl;
 379 
 380 public:
 381   ZNMethodPurgeTask() :
 382       ZTask("ZNMethodPurgeTask"),
 383       _cl() {
 384     ZNMethodTable::nmethods_do_begin();
 385   }
 386 
 387   ~ZNMethodPurgeTask() {
 388     ZNMethodTable::nmethods_do_end();
 389   }
 390 
 391   virtual void work() {
 392     ZNMethodTable::nmethods_do(&_cl);
 393   }
 394 };
 395 
 396 void ZNMethod::purge(ZWorkers* workers) {
 397   ZNMethodPurgeTask task;
 398   workers->run_concurrent(&task);
 399 }