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 
 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 
258 public:
259   ZNMethodUnlinkClosure(bool unloading_occurred) :
260       _unloading_occurred(unloading_occurred) {}
261 
262   virtual void do_nmethod(nmethod* nm) {
263     if (!nm->is_alive()) {
264       return;
265     }
266 
267     ZLocker<ZReentrantLock> locker(ZNMethod::lock_for_nmethod(nm));
268 
269     if (nm->is_unloading()) {
270       // Unlinking of the dependencies must happen before the
271       // handshake separating unlink and purge.
272       nm->flush_dependencies(false /* delete_immediately */);
273 
274       // We don't need to take the lock when unlinking nmethods from
275       // the Method, because it is only concurrently unlinked by
276       // the entry barrier, which acquires the per nmethod lock.
277       nm->unlink_from_method(false /* acquire_lock */);
278       return;
279     }
280 
281     // Heal oops and disarm
282     ZNMethodOopClosure cl;
283     ZNMethod::nmethod_oops_do(nm, &cl);
284     ZNMethod::disarm_nmethod(nm);
285 
286     // Clear compiled ICs and exception caches
287     nm->unload_nmethod_caches(_unloading_occurred);
288   }
289 };
290 
291 class ZNMethodUnlinkTask : public ZTask {
292 private:
293   ZNMethodUnlinkClosure _cl;
294 
295 public:
296   ZNMethodUnlinkTask(bool unloading_occurred) :
297       ZTask("ZNMethodUnlinkTask"),
298       _cl(unloading_occurred) {
299     ZNMethodTable::nmethods_do_begin();
300   }
301 
302   ~ZNMethodUnlinkTask() {
303     ZNMethodTable::nmethods_do_end();
304   }
305 
306   virtual void work() {
307     ZNMethodTable::nmethods_do(&_cl);
308   }
309 };
310 
311 void ZNMethod::unlink(ZWorkers* workers, bool unloading_occurred) {
312   ZNMethodUnlinkTask task(unloading_occurred);
313   workers->run_concurrent(&task);
314 }
315 
316 class ZNMethodPurgeClosure : public NMethodClosure {
317 public:
318   virtual void do_nmethod(nmethod* nm) {
319     if (nm->is_alive() && nm->is_unloading()) {
320       nm->make_unloaded();
321     }
322   }
323 };
324 
325 class ZNMethodPurgeTask : public ZTask {
326 private:
327   ZNMethodPurgeClosure _cl;
328 
329 public:
330   ZNMethodPurgeTask() :
331       ZTask("ZNMethodPurgeTask"),
332       _cl() {
333     ZNMethodTable::nmethods_do_begin();
334   }
335 
336   ~ZNMethodPurgeTask() {
337     ZNMethodTable::nmethods_do_end();
338   }
339 
340   virtual void work() {
341     ZNMethodTable::nmethods_do(&_cl);
342   }
343 };
344 
345 void ZNMethod::purge(ZWorkers* workers) {
346   ZNMethodPurgeTask task;
347   workers->run_concurrent(&task);
348 }