1 /*
2  * Copyright (c) 2017, 2020, 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/shared/suspendibleThreadSet.hpp"
31 #include "gc/z/zBarrier.inline.hpp"
32 #include "gc/z/zGlobals.hpp"
33 #include "gc/z/zLock.inline.hpp"
34 #include "gc/z/zNMethod.hpp"
35 #include "gc/z/zNMethodData.hpp"
36 #include "gc/z/zNMethodTable.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/iterator.hpp"
42 #include "memory/resourceArea.hpp"
43 #include "memory/universe.hpp"
44 #include "oops/oop.inline.hpp"
45 #include "runtime/atomic.hpp"
46 #include "utilities/debug.hpp"
47 
gc_data(const nmethod * nm)48 static ZNMethodData* gc_data(const nmethod* nm) {
49   return nm->gc_data<ZNMethodData>();
50 }
51 
set_gc_data(nmethod * nm,ZNMethodData * data)52 static void set_gc_data(nmethod* nm, ZNMethodData* data) {
53   return nm->set_gc_data<ZNMethodData>(data);
54 }
55 
attach_gc_data(nmethod * nm)56 void ZNMethod::attach_gc_data(nmethod* nm) {
57   GrowableArray<oop*> immediate_oops;
58   bool non_immediate_oops = false;
59 
60   // Find all oop relocations
61   RelocIterator iter(nm);
62   while (iter.next()) {
63     if (iter.type() != relocInfo::oop_type) {
64       // Not an oop
65       continue;
66     }
67 
68     oop_Relocation* r = iter.oop_reloc();
69 
70     if (!r->oop_is_immediate()) {
71       // Non-immediate oop found
72       non_immediate_oops = true;
73       continue;
74     }
75 
76     if (r->oop_value() != NULL) {
77       // Non-NULL immediate oop found. NULL oops can safely be
78       // ignored since the method will be re-registered if they
79       // are later patched to be non-NULL.
80       immediate_oops.push(r->oop_addr());
81     }
82   }
83 
84   // Attach GC data to nmethod
85   ZNMethodData* data = gc_data(nm);
86   if (data == NULL) {
87     data = new ZNMethodData();
88     set_gc_data(nm, data);
89   }
90 
91   // Attach oops in GC data
92   ZNMethodDataOops* const new_oops = ZNMethodDataOops::create(immediate_oops, non_immediate_oops);
93   ZNMethodDataOops* const old_oops = data->swap_oops(new_oops);
94   ZNMethodDataOops::destroy(old_oops);
95 }
96 
lock_for_nmethod(nmethod * nm)97 ZReentrantLock* ZNMethod::lock_for_nmethod(nmethod* nm) {
98   return gc_data(nm)->lock();
99 }
100 
log_register(const nmethod * nm)101 void ZNMethod::log_register(const nmethod* nm) {
102   LogTarget(Trace, gc, nmethod) log;
103   if (!log.is_enabled()) {
104     return;
105   }
106 
107   const ZNMethodDataOops* const oops = gc_data(nm)->oops();
108 
109   log.print("Register NMethod: %s.%s (" PTR_FORMAT "), "
110             "Compiler: %s, Oops: %d, ImmediateOops: " SIZE_FORMAT ", NonImmediateOops: %s",
111             nm->method()->method_holder()->external_name(),
112             nm->method()->name()->as_C_string(),
113             p2i(nm),
114             nm->compiler_name(),
115             nm->oops_count() - 1,
116             oops->immediates_count(),
117             oops->has_non_immediates() ? "Yes" : "No");
118 
119   LogTarget(Trace, gc, nmethod, oops) log_oops;
120   if (!log_oops.is_enabled()) {
121     return;
122   }
123 
124   // Print nmethod oops table
125   {
126     oop* const begin = nm->oops_begin();
127     oop* const end = nm->oops_end();
128     for (oop* p = begin; p < end; p++) {
129       log_oops.print("           Oop[" SIZE_FORMAT "] " PTR_FORMAT " (%s)",
130                      (p - begin), p2i(*p), (*p)->klass()->external_name());
131     }
132   }
133 
134   // Print nmethod immediate oops
135   {
136     oop** const begin = oops->immediates_begin();
137     oop** const end = oops->immediates_end();
138     for (oop** p = begin; p < end; p++) {
139       log_oops.print("  ImmediateOop[" SIZE_FORMAT "] " PTR_FORMAT " @ " PTR_FORMAT " (%s)",
140                      (p - begin), p2i(**p), p2i(*p), (**p)->klass()->external_name());
141     }
142   }
143 }
144 
log_unregister(const nmethod * nm)145 void ZNMethod::log_unregister(const nmethod* nm) {
146   LogTarget(Debug, gc, nmethod) log;
147   if (!log.is_enabled()) {
148     return;
149   }
150 
151   log.print("Unregister NMethod: %s.%s (" PTR_FORMAT ")",
152             nm->method()->method_holder()->external_name(),
153             nm->method()->name()->as_C_string(),
154             p2i(nm));
155 }
156 
register_nmethod(nmethod * nm)157 void ZNMethod::register_nmethod(nmethod* nm) {
158   ResourceMark rm;
159 
160   // Create and attach gc data
161   attach_gc_data(nm);
162 
163   log_register(nm);
164 
165   ZNMethodTable::register_nmethod(nm);
166 
167   // Disarm nmethod entry barrier
168   disarm(nm);
169 }
170 
unregister_nmethod(nmethod * nm)171 void ZNMethod::unregister_nmethod(nmethod* nm) {
172   assert(CodeCache_lock->owned_by_self(), "Lock must be held");
173 
174   if (Thread::current()->is_Code_cache_sweeper_thread()) {
175     // The sweeper must wait for any ongoing iteration to complete
176     // before it can unregister an nmethod.
177     ZNMethodTable::wait_until_iteration_done();
178   }
179 
180   ResourceMark rm;
181 
182   log_unregister(nm);
183 
184   ZNMethodTable::unregister_nmethod(nm);
185 }
186 
flush_nmethod(nmethod * nm)187 void ZNMethod::flush_nmethod(nmethod* nm) {
188   // Destroy GC data
189   delete gc_data(nm);
190 }
191 
supports_entry_barrier(nmethod * nm)192 bool ZNMethod::supports_entry_barrier(nmethod* nm) {
193   BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
194   return bs->supports_entry_barrier(nm);
195 }
196 
is_armed(nmethod * nm)197 bool ZNMethod::is_armed(nmethod* nm) {
198   BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
199   return bs->is_armed(nm);
200 }
201 
disarm(nmethod * nm)202 void ZNMethod::disarm(nmethod* nm) {
203   BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod();
204   bs->disarm(nm);
205 }
206 
nmethod_oops_do(nmethod * nm,OopClosure * cl)207 void ZNMethod::nmethod_oops_do(nmethod* nm, OopClosure* cl) {
208   ZLocker<ZReentrantLock> locker(ZNMethod::lock_for_nmethod(nm));
209   if (!nm->is_alive()) {
210     return;
211   }
212 
213   ZNMethod::nmethod_oops_do_inner(nm, cl);
214 }
215 
nmethod_oops_do_inner(nmethod * nm,OopClosure * cl)216 void ZNMethod::nmethod_oops_do_inner(nmethod* nm, OopClosure* cl) {
217   // Process oops table
218   {
219     oop* const begin = nm->oops_begin();
220     oop* const end = nm->oops_end();
221     for (oop* p = begin; p < end; p++) {
222       if (*p != Universe::non_oop_word()) {
223         cl->do_oop(p);
224       }
225     }
226   }
227 
228   ZNMethodDataOops* const oops = gc_data(nm)->oops();
229 
230   // Process immediate oops
231   {
232     oop** const begin = oops->immediates_begin();
233     oop** const end = oops->immediates_end();
234     for (oop** p = begin; p < end; p++) {
235       if (**p != Universe::non_oop_word()) {
236         cl->do_oop(*p);
237       }
238     }
239   }
240 
241   // Process non-immediate oops
242   if (oops->has_non_immediates()) {
243     nm->fix_oop_relocations();
244   }
245 }
246 
247 class ZNMethodOopClosure : public OopClosure {
248 public:
do_oop(oop * p)249   virtual void do_oop(oop* p) {
250     if (ZResurrection::is_blocked()) {
251       ZBarrier::keep_alive_barrier_on_phantom_root_oop_field(p);
252     } else {
253       ZBarrier::load_barrier_on_root_oop_field(p);
254     }
255   }
256 
do_oop(narrowOop * p)257   virtual void do_oop(narrowOop* p) {
258     ShouldNotReachHere();
259   }
260 };
261 
nmethod_oops_barrier(nmethod * nm)262 void ZNMethod::nmethod_oops_barrier(nmethod* nm) {
263   ZNMethodOopClosure cl;
264   nmethod_oops_do_inner(nm, &cl);
265 }
266 
nmethods_do_begin()267 void ZNMethod::nmethods_do_begin() {
268   ZNMethodTable::nmethods_do_begin();
269 }
270 
nmethods_do_end()271 void ZNMethod::nmethods_do_end() {
272   ZNMethodTable::nmethods_do_end();
273 }
274 
nmethods_do(NMethodClosure * cl)275 void ZNMethod::nmethods_do(NMethodClosure* cl) {
276   ZNMethodTable::nmethods_do(cl);
277 }
278 
279 class ZNMethodUnlinkClosure : public NMethodClosure {
280 private:
281   bool          _unloading_occurred;
282   volatile bool _failed;
283 
set_failed()284   void set_failed() {
285     Atomic::store(&_failed, true);
286   }
287 
unlink(nmethod * nm)288   void unlink(nmethod* nm) {
289     // Unlinking of the dependencies must happen before the
290     // handshake separating unlink and purge.
291     nm->flush_dependencies(false /* delete_immediately */);
292 
293     // unlink_from_method will take the CompiledMethod_lock.
294     // In this case we don't strictly need it when unlinking nmethods from
295     // the Method, because it is only concurrently unlinked by
296     // the entry barrier, which acquires the per nmethod lock.
297     nm->unlink_from_method();
298 
299     if (nm->is_osr_method()) {
300       // Invalidate the osr nmethod before the handshake. The nmethod
301       // will be made unloaded after the handshake. Then invalidate_osr_method()
302       // will be called again, which will be a no-op.
303       nm->invalidate_osr_method();
304     }
305   }
306 
307 public:
ZNMethodUnlinkClosure(bool unloading_occurred)308   ZNMethodUnlinkClosure(bool unloading_occurred) :
309       _unloading_occurred(unloading_occurred),
310       _failed(false) {}
311 
do_nmethod(nmethod * nm)312   virtual void do_nmethod(nmethod* nm) {
313     if (failed()) {
314       return;
315     }
316 
317     if (!nm->is_alive()) {
318       return;
319     }
320 
321     if (nm->is_unloading()) {
322       ZLocker<ZReentrantLock> locker(ZNMethod::lock_for_nmethod(nm));
323       unlink(nm);
324       return;
325     }
326 
327     ZLocker<ZReentrantLock> locker(ZNMethod::lock_for_nmethod(nm));
328 
329     if (ZNMethod::is_armed(nm)) {
330       // Heal oops and disarm
331       ZNMethod::nmethod_oops_barrier(nm);
332       ZNMethod::disarm(nm);
333     }
334 
335     // Clear compiled ICs and exception caches
336     if (!nm->unload_nmethod_caches(_unloading_occurred)) {
337       set_failed();
338     }
339   }
340 
failed() const341   bool failed() const {
342     return Atomic::load(&_failed);
343   }
344 };
345 
346 class ZNMethodUnlinkTask : public ZTask {
347 private:
348   ZNMethodUnlinkClosure _cl;
349   ICRefillVerifier*     _verifier;
350 
351 public:
ZNMethodUnlinkTask(bool unloading_occurred,ICRefillVerifier * verifier)352   ZNMethodUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
353       ZTask("ZNMethodUnlinkTask"),
354       _cl(unloading_occurred),
355       _verifier(verifier) {
356     ZNMethodTable::nmethods_do_begin();
357   }
358 
~ZNMethodUnlinkTask()359   ~ZNMethodUnlinkTask() {
360     ZNMethodTable::nmethods_do_end();
361   }
362 
work()363   virtual void work() {
364     ICRefillVerifierMark mark(_verifier);
365     ZNMethodTable::nmethods_do(&_cl);
366   }
367 
success() const368   bool success() const {
369     return !_cl.failed();
370   }
371 };
372 
unlink(ZWorkers * workers,bool unloading_occurred)373 void ZNMethod::unlink(ZWorkers* workers, bool unloading_occurred) {
374   for (;;) {
375     ICRefillVerifier verifier;
376 
377     {
378       ZNMethodUnlinkTask task(unloading_occurred, &verifier);
379       workers->run_concurrent(&task);
380       if (task.success()) {
381         return;
382       }
383     }
384 
385     // Cleaning failed because we ran out of transitional IC stubs,
386     // so we have to refill and try again. Refilling requires taking
387     // a safepoint, so we temporarily leave the suspendible thread set.
388     SuspendibleThreadSetLeaver sts;
389     InlineCacheBuffer::refill_ic_stubs();
390   }
391 }
392 
393 class ZNMethodPurgeClosure : public NMethodClosure {
394 public:
do_nmethod(nmethod * nm)395   virtual void do_nmethod(nmethod* nm) {
396     if (nm->is_alive() && nm->is_unloading()) {
397       nm->make_unloaded();
398     }
399   }
400 };
401 
402 class ZNMethodPurgeTask : public ZTask {
403 private:
404   ZNMethodPurgeClosure _cl;
405 
406 public:
ZNMethodPurgeTask()407   ZNMethodPurgeTask() :
408       ZTask("ZNMethodPurgeTask"),
409       _cl() {
410     ZNMethodTable::nmethods_do_begin();
411   }
412 
~ZNMethodPurgeTask()413   ~ZNMethodPurgeTask() {
414     ZNMethodTable::nmethods_do_end();
415   }
416 
work()417   virtual void work() {
418     ZNMethodTable::nmethods_do(&_cl);
419   }
420 };
421 
purge(ZWorkers * workers)422 void ZNMethod::purge(ZWorkers* workers) {
423   ZNMethodPurgeTask task;
424   workers->run_concurrent(&task);
425 }
426