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/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 #include "utilities/globalCounter.inline.hpp"
 46 
 47 static ZNMethodData* gc_data(const nmethod* nm) {
 48   return nm->gc_data<ZNMethodData>();
 49 }
 50 
 51 static void set_gc_data(nmethod* nm, ZNMethodData* data) {
 52   return nm->set_gc_data<ZNMethodData>(data);
 53 }
 54 
 55 void ZNMethod::attach_gc_data(nmethod* nm) {
 56   GrowableArray<oop*> immediate_oops;
 57   bool non_immediate_oops = false;
 58 
 59   // Find all oops relocations
 60   RelocIterator iter(nm);
 61   while (iter.next()) {
 62     if (iter.type() != relocInfo::oop_type) {
 63       // Not an oop
 64       continue;
 65     }
 66 
 67     oop_Relocation* r = iter.oop_reloc();
 68 
 69     if (!r->oop_is_immediate()) {
 70       // Non-immediate oop found
 71       non_immediate_oops = true;
 72       continue;
 73     }
 74 
 75     if (r->oop_value() != NULL) {
 76       // Non-NULL immediate oop found. NULL oops can safely be
 77       // ignored since the method will be re-registered if they
 78       // are later patched to be non-NULL.
 79       immediate_oops.push(r->oop_addr());
 80     }
 81   }
 82 
 83   // Attach GC data to nmethod
 84   ZNMethodData* data = gc_data(nm);
 85   if (data == NULL) {
 86     data = new ZNMethodData();
 87     set_gc_data(nm, data);
 88   }
 89 
 90   // Attach oops in GC data
 91   ZNMethodDataOops* const new_oops = ZNMethodDataOops::create(immediate_oops, non_immediate_oops);
 92   ZNMethodDataOops* const old_oops = data->swap_oops(new_oops);
 93   ZNMethodDataOops::destroy(old_oops);
 94 }
 95 
 96 ZReentrantLock* ZNMethod::lock_for_nmethod(nmethod* nm) {
 97   return gc_data(nm)->lock();
 98 }
 99 
100 void ZNMethod::log_register(const nmethod* nm) {
101   LogTarget(Trace, gc, nmethod) log;
102   if (!log.is_enabled()) {
103     return;
104   }
105 
106   const ZNMethodDataOops* const oops = gc_data(nm)->oops();
107 
108   log.print("Register NMethod: %s.%s (" PTR_FORMAT "), "
109             "Compiler: %s, Oops: %d, ImmediateOops: " SIZE_FORMAT ", NonImmediateOops: %s",
110             nm->method()->method_holder()->external_name(),
111             nm->method()->name()->as_C_string(),
112             p2i(nm),
113             nm->compiler_name(),
114             nm->oops_count() - 1,
115             oops->immediates_count(),
116             oops->has_non_immediates() ? "Yes" : "No");
117 
118   LogTarget(Trace, gc, nmethod, oops) log_oops;
119   if (!log_oops.is_enabled()) {
120     return;
121   }
122 
123   // Print nmethod oops table
124   {
125     oop* const begin = nm->oops_begin();
126     oop* const end = nm->oops_end();
127     for (oop* p = begin; p < end; p++) {
128       log_oops.print("           Oop[" SIZE_FORMAT "] " PTR_FORMAT " (%s)",
129                      (p - begin), p2i(*p), (*p)->klass()->external_name());
130     }
131   }
132 
133   // Print nmethod immediate oops
134   {
135     oop** const begin = oops->immediates_begin();
136     oop** const end = oops->immediates_end();
137     for (oop** p = begin; p < end; p++) {
138       log_oops.print("  ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)",
139                      (p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name());
140     }
141   }
142 }
143 
144 void ZNMethod::log_unregister(const nmethod* nm) {
145   LogTarget(Debug, gc, nmethod) log;
146   if (!log.is_enabled()) {
147     return;
148   }
149 
150   log.print("Unregister NMethod: %s.%s (" PTR_FORMAT ")",
151             nm->method()->method_holder()->external_name(),
152             nm->method()->name()->as_C_string(),
153             p2i(nm));
154 }
155 
156 void ZNMethod::register_nmethod(nmethod* nm) {
157   ResourceMark rm;
158 
159   // Create and attach gc data
160   attach_gc_data(nm);
161 
162   log_register(nm);
163 
164   ZNMethodTable::register_nmethod(nm);
165 
166   // Disarm nmethod entry barrier
167   disarm_nmethod(nm);
168 }
169 
170 void ZNMethod::unregister_nmethod(nmethod* nm) {
171   assert(CodeCache_lock->owned_by_self(), "Lock must be held");
172 
173   if (Thread::current()->is_Code_cache_sweeper_thread()) {
174     // The sweeper must wait for any ongoing iteration to complete
175     // before it can unregister an nmethod.
176     ZNMethodTable::wait_until_iteration_done();
177   }
178 
179   ResourceMark rm;
180 
181   log_unregister(nm);
182 
183   ZNMethodTable::unregister_nmethod(nm);
184 }
185 
186 void ZNMethod::flush_nmethod(nmethod* nm) {
187   // Destroy GC data
188   delete gc_data(nm);
189 }
190 
191 void ZNMethod::disarm_nmethod(nmethod* nm) {
192   BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
193   if (bs != NULL) {
194     bs->disarm(nm);
195   }
196 }
197 
198 void ZNMethod::nmethod_oops_do(nmethod* nm, OopClosure* cl) {
199   // Process oops table
200   {
201     oop* const begin = nm->oops_begin();
202     oop* const end = nm->oops_end();
203     for (oop* p = begin; p < end; p++) {
204       if (*p != Universe::non_oop_word()) {
205         cl->do_oop(p);
206       }
207     }
208   }
209 
210   GlobalCounter::CriticalSection cs(Thread::current());
211   ZNMethodDataOops* const oops = gc_data(nm)->oops();
212 
213   // Process immediate oops
214   {
215     oop** const begin = oops->immediates_begin();
216     oop** const end = oops->immediates_end();
217     for (oop** p = begin; p < end; p++) {
218       if (**p != Universe::non_oop_word()) {
219         cl->do_oop(*p);
220       }
221     }
222   }
223 
224   // Process non-immediate oops
225   if (oops->has_non_immediates()) {
226     nm->fix_oop_relocations();
227   }
228 }
229 
230 class ZNMethodToOopsDoClosure : public NMethodClosure {
231 private:
232   OopClosure* _cl;
233 
234 public:
235   ZNMethodToOopsDoClosure(OopClosure* cl) :
236       _cl(cl) {}
237 
238   virtual void do_nmethod(nmethod* nm) {
239     ZNMethod::nmethod_oops_do(nm, _cl);
240   }
241 };
242 
243 void ZNMethod::oops_do_begin() {
244   ZNMethodTable::nmethods_do_begin();
245 }
246 
247 void ZNMethod::oops_do_end() {
248   ZNMethodTable::nmethods_do_end();
249 }
250 
251 void ZNMethod::oops_do(OopClosure* cl) {
252   ZNMethodToOopsDoClosure nmethod_cl(cl);
253   ZNMethodTable::nmethods_do(&nmethod_cl);
254 }
255 
256 class ZNMethodUnlinkClosure : public NMethodClosure {
257 private:
258   bool _unloading_occurred;
259 
260 public:
261   ZNMethodUnlinkClosure(bool unloading_occurred) :
262       _unloading_occurred(unloading_occurred) {}
263 
264   virtual void do_nmethod(nmethod* nm) {
265     if (!nm->is_alive()) {
266       return;
267     }
268 
269     ZLocker<ZReentrantLock> locker(ZNMethod::lock_for_nmethod(nm));
270 
271     if (nm->is_unloading()) {
272       // Unlinking of the dependencies must happen before the
273       // handshake separating unlink and purge.
274       nm->flush_dependencies(false /* delete_immediately */);
275 
276       // We don't need to take the lock when unlinking nmethods from
277       // the Method, because it is only concurrently unlinked by
278       // the entry barrier, which acquires the per nmethod lock.
279       nm->unlink_from_method(false /* acquire_lock */);
280       return;
281     }
282 
283     // Heal oops and disarm
284     ZNMethodOopClosure cl;
285     ZNMethod::nmethod_oops_do(nm, &cl);
286     ZNMethod::disarm_nmethod(nm);
287 
288     // Clear compiled ICs and exception caches
289     nm->unload_nmethod_caches(_unloading_occurred);
290   }
291 };
292 
293 class ZNMethodUnlinkTask : public ZTask {
294 private:
295   ZNMethodUnlinkClosure _cl;
296 
297 public:
298   ZNMethodUnlinkTask(bool unloading_occurred) :
299       ZTask("ZNMethodUnlinkTask"),
300       _cl(unloading_occurred) {
301     ZNMethodTable::nmethods_do_begin();
302   }
303 
304   ~ZNMethodUnlinkTask() {
305     ZNMethodTable::nmethods_do_end();
306   }
307 
308   virtual void work() {
309     ZNMethodTable::nmethods_do(&_cl);
310   }
311 };
312 
313 void ZNMethod::unlink(ZWorkers* workers, bool unloading_occurred) {
314   ZNMethodUnlinkTask task(unloading_occurred);
315   workers->run_concurrent(&task);
316 }
317 
318 class ZNMethodPurgeClosure : public NMethodClosure {
319 public:
320   virtual void do_nmethod(nmethod* nm) {
321     if (nm->is_alive() && nm->is_unloading()) {
322       nm->make_unloaded();
323     }
324   }
325 };
326 
327 class ZNMethodPurgeTask : public ZTask {
328 private:
329   ZNMethodPurgeClosure _cl;
330 
331 public:
332   ZNMethodPurgeTask() :
333       ZTask("ZNMethodPurgeTask"),
334       _cl() {
335     ZNMethodTable::nmethods_do_begin();
336   }
337 
338   ~ZNMethodPurgeTask() {
339     ZNMethodTable::nmethods_do_end();
340   }
341 
342   virtual void work() {
343     ZNMethodTable::nmethods_do(&_cl);
344   }
345 };
346 
347 void ZNMethod::purge(ZWorkers* workers) {
348   ZNMethodPurgeTask task;
349   workers->run_concurrent(&task);
350 }