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