1 /*
2  * Copyright (c) 2014, 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 
25 #include "precompiled.hpp"
26 #include "aot/aotLoader.hpp"
27 #include "classfile/stringTable.hpp"
28 #include "gc/shared/strongRootsScope.hpp"
29 #include "jfr/leakprofiler/utilities/unifiedOop.hpp"
30 #include "jfr/leakprofiler/checkpoint/rootResolver.hpp"
31 #include "memory/iterator.hpp"
32 #include "oops/klass.hpp"
33 #include "oops/oop.hpp"
34 #include "prims/jvmtiThreadState.hpp"
35 #include "prims/privilegedStack.hpp"
36 #include "runtime/frame.inline.hpp"
37 #include "runtime/mutexLocker.hpp"
38 #include "runtime/threadSMR.inline.hpp"
39 #include "runtime/vframe_hp.hpp"
40 #include "services/management.hpp"
41 #include "utilities/growableArray.hpp"
42 
43 class ReferenceLocateClosure : public OopClosure {
44  protected:
45   RootCallback& _callback;
46   RootCallbackInfo _info;
47   bool _complete;
48 
49   void do_oop_shared(const void* ref);
50 
51  public:
ReferenceLocateClosure(RootCallback & callback,OldObjectRoot::System system,OldObjectRoot::Type type,const void * context)52   ReferenceLocateClosure(RootCallback& callback,
53                          OldObjectRoot::System system,
54                          OldObjectRoot::Type type,
55                          const void* context) : _callback(callback),
56                                                 _info(),
57                                                 _complete(false) {
58     _info._high = NULL;
59     _info._low = NULL;
60     _info._system = system;
61     _info._type = type;
62     _info._context = context;
63   }
64 
65   virtual void do_oop(oop* ref);
66   virtual void do_oop(narrowOop* ref);
67 
complete() const68   bool complete() const {
69     return _complete;
70   }
71 };
72 
do_oop_shared(const void * ref)73 void ReferenceLocateClosure::do_oop_shared(const void* ref) {
74   assert(ref != NULL, "invariant");
75   if (!_complete) {
76     _info._high = ref;
77     _complete = _callback.process(_info);
78   }
79 }
80 
do_oop(oop * ref)81 void ReferenceLocateClosure::do_oop(oop* ref) {
82   do_oop_shared(ref);
83 }
84 
do_oop(narrowOop * ref)85 void ReferenceLocateClosure::do_oop(narrowOop* ref) {
86   do_oop_shared(ref);
87 }
88 
89 class ReferenceToRootClosure : public StackObj {
90  private:
91   RootCallback& _callback;
92   RootCallbackInfo _info;
93   bool _complete;
94 
95   bool do_cldg_roots();
96   bool do_object_synchronizer_roots();
97   bool do_universe_roots();
98   bool do_jni_handle_roots();
99   bool do_jvmti_roots();
100   bool do_system_dictionary_roots();
101   bool do_management_roots();
102   bool do_string_table_roots();
103   bool do_aot_loader_roots();
104 
105   bool do_roots();
106 
107  public:
ReferenceToRootClosure(RootCallback & callback)108   ReferenceToRootClosure(RootCallback& callback) : _callback(callback),
109                                                    _info(),
110                                                    _complete(false) {
111     _info._high = NULL;
112     _info._low = NULL;
113     _info._context = NULL;
114     _info._system = OldObjectRoot::_system_undetermined;
115     _info._type = OldObjectRoot::_type_undetermined;
116 
117     assert_locked_or_safepoint(Threads_lock);
118     do_roots();
119   }
120 
complete() const121   bool complete() const {
122     return _complete;
123   }
124 };
125 
do_cldg_roots()126 bool ReferenceToRootClosure::do_cldg_roots() {
127   assert(!complete(), "invariant");
128   ReferenceLocateClosure rlc(_callback, OldObjectRoot::_class_loader_data, OldObjectRoot::_type_undetermined, NULL);
129   CLDToOopClosure cldt_closure(&rlc);
130   ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
131   return rlc.complete();
132 }
133 
do_object_synchronizer_roots()134 bool ReferenceToRootClosure::do_object_synchronizer_roots() {
135   assert(!complete(), "invariant");
136   ReferenceLocateClosure rlc(_callback, OldObjectRoot::_object_synchronizer, OldObjectRoot::_type_undetermined, NULL);
137   ObjectSynchronizer::oops_do(&rlc);
138   return rlc.complete();
139 }
140 
do_universe_roots()141 bool ReferenceToRootClosure::do_universe_roots() {
142   assert(!complete(), "invariant");
143   ReferenceLocateClosure rlc(_callback, OldObjectRoot::_universe, OldObjectRoot::_type_undetermined, NULL);
144   Universe::oops_do(&rlc);
145   return rlc.complete();
146 }
147 
do_jni_handle_roots()148 bool ReferenceToRootClosure::do_jni_handle_roots() {
149   assert(!complete(), "invariant");
150   ReferenceLocateClosure rlc(_callback, OldObjectRoot::_global_jni_handles, OldObjectRoot::_global_jni_handle, NULL);
151   JNIHandles::oops_do(&rlc);
152   return rlc.complete();
153 }
154 
do_jvmti_roots()155 bool ReferenceToRootClosure::do_jvmti_roots() {
156   assert(!complete(), "invariant");
157   ReferenceLocateClosure rlc(_callback, OldObjectRoot::_jvmti, OldObjectRoot::_global_jni_handle, NULL);
158   JvmtiExport::oops_do(&rlc);
159   return rlc.complete();
160 }
161 
do_system_dictionary_roots()162 bool ReferenceToRootClosure::do_system_dictionary_roots() {
163   assert(!complete(), "invariant");
164   ReferenceLocateClosure rlc(_callback, OldObjectRoot::_system_dictionary, OldObjectRoot::_type_undetermined, NULL);
165   SystemDictionary::oops_do(&rlc);
166   return rlc.complete();
167 }
168 
do_management_roots()169 bool ReferenceToRootClosure::do_management_roots() {
170   assert(!complete(), "invariant");
171   ReferenceLocateClosure rlc(_callback, OldObjectRoot::_management, OldObjectRoot::_type_undetermined, NULL);
172   Management::oops_do(&rlc);
173   return rlc.complete();
174 }
175 
do_string_table_roots()176 bool ReferenceToRootClosure::do_string_table_roots() {
177   assert(!complete(), "invariant");
178   ReferenceLocateClosure rlc(_callback, OldObjectRoot::_string_table, OldObjectRoot::_type_undetermined, NULL);
179   StringTable::oops_do(&rlc);
180   return rlc.complete();
181 }
182 
do_aot_loader_roots()183 bool ReferenceToRootClosure::do_aot_loader_roots() {
184   assert(!complete(), "invariant");
185   ReferenceLocateClosure rcl(_callback, OldObjectRoot::_aot, OldObjectRoot::_type_undetermined, NULL);
186   AOTLoader::oops_do(&rcl);
187   return rcl.complete();
188 }
189 
do_roots()190 bool ReferenceToRootClosure::do_roots() {
191   assert(!complete(), "invariant");
192   assert(OldObjectRoot::_system_undetermined == _info._system, "invariant");
193   assert(OldObjectRoot::_type_undetermined == _info._type, "invariant");
194 
195   if (do_cldg_roots()) {
196     _complete = true;
197     return true;
198   }
199 
200   if (do_object_synchronizer_roots()) {
201    _complete = true;
202     return true;
203   }
204 
205   if (do_universe_roots()) {
206    _complete = true;
207     return true;
208   }
209 
210   if (do_jni_handle_roots()) {
211    _complete = true;
212     return true;
213   }
214 
215   if (do_jvmti_roots()) {
216    _complete = true;
217     return true;
218   }
219 
220   if (do_system_dictionary_roots()) {
221    _complete = true;
222     return true;
223   }
224 
225   if (do_management_roots()) {
226    _complete = true;
227     return true;
228   }
229 
230   if (do_string_table_roots()) {
231    _complete = true;
232     return true;
233   }
234 
235   if (do_aot_loader_roots()) {
236    _complete = true;
237     return true;
238   }
239 
240   return false;
241 }
242 
243 class ReferenceToThreadRootClosure : public StackObj {
244  private:
245   RootCallback& _callback;
246   bool _complete;
247 
248   bool do_java_threads_oops(JavaThread* jt);
249   bool do_thread_roots(JavaThread* jt);
250   bool do_thread_stack_fast(JavaThread* jt);
251   bool do_thread_stack_detailed(JavaThread* jt);
252   bool do_thread_jni_handles(JavaThread* jt);
253   bool do_thread_handle_area(JavaThread* jt);
254 
255  public:
ReferenceToThreadRootClosure(RootCallback & callback)256   ReferenceToThreadRootClosure(RootCallback& callback) :_callback(callback), _complete(false) {
257     assert_locked_or_safepoint(Threads_lock);
258     for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
259       if (do_thread_roots(jt)) {
260         return;
261       }
262     }
263   }
264 
complete() const265   bool complete() const {
266     return _complete;
267   }
268 };
269 
do_thread_handle_area(JavaThread * jt)270 bool ReferenceToThreadRootClosure::do_thread_handle_area(JavaThread* jt) {
271   assert(jt != NULL, "invariant");
272   assert(!complete(), "invariant");
273   ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_handle_area, jt);
274   jt->handle_area()->oops_do(&rcl);
275   return rcl.complete();
276 }
277 
do_thread_jni_handles(JavaThread * jt)278 bool ReferenceToThreadRootClosure::do_thread_jni_handles(JavaThread* jt) {
279   assert(jt != NULL, "invariant");
280   assert(!complete(), "invariant");
281 
282   ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_local_jni_handle, jt);
283   jt->active_handles()->oops_do(&rcl);
284   return rcl.complete();
285 }
286 
do_thread_stack_fast(JavaThread * jt)287 bool ReferenceToThreadRootClosure::do_thread_stack_fast(JavaThread* jt) {
288   assert(jt != NULL, "invariant");
289   assert(!complete(), "invariant");
290 
291   if (_callback.entries() == 0) {
292     _complete = true;
293     return true;
294   }
295 
296   RootCallbackInfo info;
297   info._high = NULL;
298   info._low = NULL;
299   info._context = jt;
300   info._system = OldObjectRoot::_threads;
301   info._type = OldObjectRoot::_stack_variable;
302 
303   for (int i = 0; i < _callback.entries(); ++i) {
304     const address adr = (address)_callback.at(i);
305     if (jt->is_in_usable_stack(adr)) {
306       info._high = adr;
307       _complete = _callback.process(info);
308       if (_complete) {
309         return true;
310       }
311     }
312   }
313   assert(!complete(), "invariant");
314   return false;
315 }
316 
do_thread_stack_detailed(JavaThread * jt)317 bool ReferenceToThreadRootClosure::do_thread_stack_detailed(JavaThread* jt) {
318   assert(jt != NULL, "invariant");
319   assert(!complete(), "invariant");
320 
321   ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_stack_variable, jt);
322 
323   if (jt->has_last_Java_frame()) {
324     PrivilegedElement* const pelem = jt->privileged_stack_top();
325     if (pelem != NULL) {
326       pelem->oops_do(&rcl);
327       if (rcl.complete()) {
328         return true;
329       }
330     }
331 
332     // traverse the registered growable array gc_array
333     // can't do this as it is not reachable from outside
334 
335     // Traverse the monitor chunks
336     MonitorChunk* chunk = jt->monitor_chunks();
337     for (; chunk != NULL; chunk = chunk->next()) {
338       chunk->oops_do(&rcl);
339     }
340 
341     if (rcl.complete()) {
342       return true;
343     }
344 
345     // Traverse the execution stack
346     for (StackFrameStream fst(jt); !fst.is_done(); fst.next()) {
347       fst.current()->oops_do(&rcl, NULL, fst.register_map());
348     }
349 
350   } // last java frame
351 
352   if (rcl.complete()) {
353     return true;
354   }
355 
356   GrowableArray<jvmtiDeferredLocalVariableSet*>* const list = jt->deferred_locals();
357   if (list != NULL) {
358     for (int i = 0; i < list->length(); i++) {
359       list->at(i)->oops_do(&rcl);
360     }
361   }
362 
363   if (rcl.complete()) {
364     return true;
365   }
366 
367   // Traverse instance variables at the end since the GC may be moving things
368   // around using this function
369   /*
370   * // can't reach these oop* from the outside
371   f->do_oop((oop*) &_threadObj);
372   f->do_oop((oop*) &_vm_result);
373   f->do_oop((oop*) &_exception_oop);
374   f->do_oop((oop*) &_pending_async_exception);
375   */
376 
377   JvmtiThreadState* const jvmti_thread_state = jt->jvmti_thread_state();
378   if (jvmti_thread_state != NULL) {
379     jvmti_thread_state->oops_do(&rcl, NULL);
380   }
381 
382   return rcl.complete();
383 }
384 
do_java_threads_oops(JavaThread * jt)385 bool ReferenceToThreadRootClosure::do_java_threads_oops(JavaThread* jt) {
386   assert(jt != NULL, "invariant");
387   assert(!complete(), "invariant");
388 
389   ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_global_jni_handle, jt);
390   jt->oops_do(&rcl, NULL);
391   return rcl.complete();
392 }
393 
do_thread_roots(JavaThread * jt)394 bool ReferenceToThreadRootClosure::do_thread_roots(JavaThread* jt) {
395   assert(jt != NULL, "invariant");
396 
397   if (do_thread_stack_fast(jt)) {
398     _complete = true;
399     return true;
400   }
401 
402   if (do_thread_jni_handles(jt)) {
403     _complete = true;
404     return true;
405   }
406 
407   if (do_thread_handle_area(jt)) {
408     _complete = true;
409     return true;
410   }
411 
412   if (do_thread_stack_detailed(jt)) {
413     _complete = true;
414     return true;
415   }
416 
417   return false;
418 }
419 
420 class RootResolverMarkScope : public MarkScope {
421 };
422 
resolve(RootCallback & callback)423 void RootResolver::resolve(RootCallback& callback) {
424 
425   // Need to clear cld claim bit before starting
426   ClassLoaderDataGraph::clear_claimed_marks();
427   RootResolverMarkScope mark_scope;
428 
429   // thread local roots
430   ReferenceToThreadRootClosure rtrc(callback);
431   if (rtrc.complete()) {
432     return;
433   }
434   // system global roots
435   ReferenceToRootClosure rrc(callback);
436 }
437