1 /*
   2  * Copyright (c) 2017, 2018, 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/zNMethodClosure.hpp"
  34 #include "gc/z/zNMethodData.hpp"
  35 #include "gc/z/zNMethodTable.hpp"
  36 #include "gc/z/zOopClosures.inline.hpp"
  37 #include "gc/z/zTask.hpp"
  38 #include "gc/z/zWorkers.hpp"
  39 #include "logging/log.hpp"
  40 #include "memory/allocation.inline.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 = ZNMethodData::create(nm);
  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 void ZNMethod::detach_gc_data(nmethod* nm) {
  96   // Destroy GC data
  97   ZNMethodData::destroy(gc_data(nm));
  98   set_gc_data(nm, NULL);
  99 }
 100 
 101 ZReentrantLock* ZNMethod::lock_for_nmethod(nmethod* nm) {
 102   ZNMethodData* const data = gc_data(nm);
 103   if (data == NULL) {
 104     return NULL;
 105   }
 106   return data->lock();
 107 }
 108 
 109 void ZNMethod::log_register(const nmethod* nm) {
 110   LogTarget(Trace, gc, nmethod) log;
 111   if (!log.is_enabled()) {
 112     return;
 113   }
 114 
 115   const ZNMethodDataOops* const oops = gc_data(nm)->oops();
 116 
 117   log.print("Register NMethod: %s.%s (" PTR_FORMAT "), "
 118             "Compiler: %s, Oops: %d, ImmediateOops: " SIZE_FORMAT ", NonImmediateOops: %s",
 119             nm->method()->method_holder()->external_name(),
 120             nm->method()->name()->as_C_string(),
 121             p2i(nm),
 122             nm->compiler_name(),
 123             nm->oops_count() - 1,
 124             oops->immediates_count(),
 125             oops->has_non_immediates() ? "Yes" : "No");
 126 
 127   LogTarget(Trace, gc, nmethod, oops) log_oops;
 128   if (!log_oops.is_enabled()) {
 129     return;
 130   }
 131 
 132   // Print nmethod oops table
 133   oop* const begin = nm->oops_begin();
 134   oop* const end = nm->oops_end();
 135   for (oop* p = begin; p < end; p++) {
 136     log_oops.print("           Oop[" SIZE_FORMAT "] " PTR_FORMAT " (%s)",
 137                    (p - begin), p2i(*p), (*p)->klass()->external_name());
 138   }
 139 
 140   // Print nmethod immediate oops
 141   if (oops->immediates_count() > 0) {
 142     oop** const begin = oops->immediates_begin();
 143     oop** const end = oops->immediates_end();
 144     for (oop** p = begin; p < end; p++) {
 145       log_oops.print("  ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)",
 146                      (p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name());
 147     }
 148   }
 149 }
 150 
 151 void ZNMethod::log_unregister(const nmethod* nm) {
 152   LogTarget(Debug, gc, nmethod) log;
 153   if (!log.is_enabled()) {
 154     return;
 155   }
 156 
 157   log.print("Unregister NMethod: %s.%s (" PTR_FORMAT ")",
 158             nm->method()->method_holder()->external_name(),
 159             nm->method()->name()->as_C_string(),
 160             p2i(nm));
 161 }
 162 
 163 void ZNMethod::register_nmethod(nmethod* nm) {
 164   ResourceMark rm;
 165 
 166   // Create and attach gc data
 167   attach_gc_data(nm);
 168 
 169   log_register(nm);
 170 
 171   ZNMethodTable::register_nmethod(nm);
 172 
 173   // Disarm nmethod entry barrier
 174   disarm_nmethod(nm);
 175 }
 176 
 177 void ZNMethod::unregister_nmethod(nmethod* nm) {
 178   assert(CodeCache_lock->owned_by_self(), "Lock must be held");
 179 
 180   if (Thread::current()->is_Code_cache_sweeper_thread()) {
 181     // The sweeper must wait for any ongoing iteration to complete
 182     // before it can unregister an nmethod.
 183     ZNMethodTable::wait_until_iteration_done();
 184   }
 185 
 186   ResourceMark rm;
 187 
 188   log_unregister(nm);
 189 
 190   ZNMethodTable::unregister_nmethod(nm);
 191 
 192   // Destroy and detach gc data
 193   detach_gc_data(nm);
 194 }
 195 
 196 void ZNMethod::disarm_nmethod(nmethod* nm) {
 197   BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
 198   if (bs != NULL) {
 199     bs->disarm(nm);
 200   }
 201 }
 202 
 203 void ZNMethod::nmethod_oops_do(nmethod* nm, OopClosure* cl) {
 204   // Process oops table
 205   oop* const begin = nm->oops_begin();
 206   oop* const end = nm->oops_end();
 207   for (oop* p = begin; p < end; p++) {
 208     if (*p != Universe::non_oop_word()) {
 209       cl->do_oop(p);
 210     }
 211   }
 212 
 213   ZNMethodDataOops* const oops = gc_data(nm)->oops();
 214 
 215   // Process immediate oops
 216   if (oops->immediates_count() > 0) {
 217     oop** const begin = oops->immediates_begin();
 218     oop** const end = oops->immediates_end();
 219     for (oop** p = begin; p < end; p++) {
 220       if (**p != Universe::non_oop_word()) {
 221         cl->do_oop(*p);
 222       }
 223     }
 224   }
 225 
 226   // Process non-immediate oops
 227   if (oops->has_non_immediates()) {
 228     nm->fix_oop_relocations();
 229   }
 230 }
 231 
 232 class ZNMethodToOopsDo : public ZNMethodClosure {
 233 private:
 234   OopClosure* _cl;
 235 
 236 public:
 237   ZNMethodToOopsDo(OopClosure* cl) :
 238       _cl(cl) {}
 239 
 240   void do_nmethod(nmethod* nm) {
 241     ZNMethod::nmethod_oops_do(nm, _cl);
 242   }
 243 };
 244 
 245 void ZNMethod::oops_do_begin() {
 246   ZNMethodTable::nmethods_do_begin();
 247 }
 248 
 249 void ZNMethod::oops_do_end() {
 250   ZNMethodTable::nmethods_do_end();
 251 }
 252 
 253 void ZNMethod::oops_do(OopClosure* cl) {
 254   ZNMethodToOopsDo nmethod_cl(cl);
 255   ZNMethodTable::nmethods_do(&nmethod_cl);
 256 }
 257 
 258 class ZNMethodUnlinkClosure : public ZNMethodClosure {
 259 private:
 260   bool          _unloading_occurred;
 261   volatile bool _failed;
 262 
 263   void set_failed() {
 264     Atomic::store(true, &_failed);
 265   }
 266 
 267 public:
 268   ZNMethodUnlinkClosure(bool unloading_occurred) :
 269       _unloading_occurred(unloading_occurred),
 270       _failed(false) {}
 271 
 272   virtual void do_nmethod(nmethod* nm) {
 273     if (failed()) {
 274       return;
 275     }
 276 
 277     if (!nm->is_alive()) {
 278       return;
 279     }
 280 
 281     ZLocker<ZReentrantLock> locker(ZNMethod::lock_for_nmethod(nm));
 282 
 283     if (nm->is_unloading()) {
 284       // Unlinking of the dependencies must happen before the
 285       // handshake separating unlink and purge.
 286       nm->flush_dependencies(false /* delete_immediately */);
 287 
 288       // We don't need to take the lock when unlinking nmethods from
 289       // the Method, because it is only concurrently unlinked by
 290       // the entry barrier, which acquires the per nmethod lock.
 291       nm->unlink_from_method(false /* acquire_lock */);
 292       return;
 293     }
 294 
 295     // Heal oops and disarm
 296     ZNMethodOopClosure cl;
 297     ZNMethod::nmethod_oops_do(nm, &cl);
 298     ZNMethod::disarm_nmethod(nm);
 299 
 300     // Clear compiled ICs and exception caches
 301     if (!nm->unload_nmethod_caches(_unloading_occurred)) {
 302       set_failed();
 303     }
 304   }
 305 
 306   bool failed() const {
 307     return Atomic::load(&_failed);
 308   }
 309 };
 310 
 311 class ZNMethodUnlinkTask : public ZTask {
 312 private:
 313   ZNMethodUnlinkClosure _cl;
 314   ICRefillVerifier*     _verifier;
 315 
 316 public:
 317   ZNMethodUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
 318       ZTask("ZNMethodUnlinkTask"),
 319       _cl(unloading_occurred),
 320       _verifier(verifier) {
 321     ZNMethodTable::nmethods_do_begin();
 322   }
 323 
 324   ~ZNMethodUnlinkTask() {
 325     ZNMethodTable::nmethods_do_end();
 326   }
 327 
 328   virtual void work() {
 329     ICRefillVerifierMark mark(_verifier);
 330     ZNMethodTable::nmethods_do(&_cl);
 331   }
 332 
 333   bool success() const {
 334     return !_cl.failed();
 335   }
 336 };
 337 
 338 void ZNMethod::unlink(ZWorkers* workers, bool unloading_occurred) {
 339   for (;;) {
 340     ICRefillVerifier verifier;
 341 
 342     {
 343       ZNMethodUnlinkTask task(unloading_occurred, &verifier);
 344       workers->run_concurrent(&task);
 345       if (task.success()) {
 346         return;
 347       }
 348     }
 349 
 350     // Cleaning failed because we ran out of transitional IC stubs,
 351     // so we have to refill and try again. Refilling requires taking
 352     // a safepoint, so we temporarily leave the suspendible thread set.
 353     SuspendibleThreadSetLeaver sts;
 354     InlineCacheBuffer::refill_ic_stubs();
 355   }
 356 }
 357 
 358 class ZNMethodPurgeClosure : public ZNMethodClosure {
 359 public:
 360   virtual void do_nmethod(nmethod* nm) {
 361     if (nm->is_alive() && nm->is_unloading()) {
 362       nm->make_unloaded();
 363     }
 364   }
 365 };
 366 
 367 class ZNMethodPurgeTask : public ZTask {
 368 private:
 369   ZNMethodPurgeClosure _cl;
 370 
 371 public:
 372   ZNMethodPurgeTask() :
 373       ZTask("ZNMethodPurgeTask"),
 374       _cl() {
 375     ZNMethodTable::nmethods_do_begin();
 376   }
 377 
 378   ~ZNMethodPurgeTask() {
 379     ZNMethodTable::nmethods_do_end();
 380   }
 381 
 382   virtual void work() {
 383     ZNMethodTable::nmethods_do(&_cl);
 384   }
 385 };
 386 
 387 void ZNMethod::purge(ZWorkers* workers) {
 388   ZNMethodPurgeTask task;
 389   workers->run_concurrent(&task);
 390 }