23 */ |
23 */ |
24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "classfile/classLoaderData.hpp" |
26 #include "classfile/classLoaderData.hpp" |
27 #include "classfile/systemDictionary.hpp" |
27 #include "classfile/systemDictionary.hpp" |
|
28 #include "jfr/leakprofiler/chains/bfsClosure.hpp" |
|
29 #include "jfr/leakprofiler/chains/dfsClosure.hpp" |
28 #include "jfr/leakprofiler/chains/edgeQueue.hpp" |
30 #include "jfr/leakprofiler/chains/edgeQueue.hpp" |
29 #include "jfr/leakprofiler/chains/rootSetClosure.hpp" |
31 #include "jfr/leakprofiler/chains/rootSetClosure.hpp" |
30 #include "jfr/leakprofiler/utilities/saveRestore.hpp" |
32 #include "jfr/leakprofiler/utilities/saveRestore.hpp" |
31 #include "jfr/leakprofiler/utilities/unifiedOop.hpp" |
33 #include "jfr/leakprofiler/utilities/unifiedOop.hpp" |
32 #include "memory/universe.hpp" |
34 #include "memory/universe.hpp" |
|
35 #include "oops/oop.inline.hpp" |
33 #include "prims/jvmtiExport.hpp" |
36 #include "prims/jvmtiExport.hpp" |
34 #include "runtime/jniHandles.hpp" |
37 #include "runtime/jniHandles.hpp" |
35 #include "runtime/synchronizer.hpp" |
38 #include "runtime/synchronizer.hpp" |
36 #include "runtime/thread.hpp" |
39 #include "runtime/thread.hpp" |
37 #include "services/management.hpp" |
40 #include "services/management.hpp" |
38 #include "utilities/align.hpp" |
41 #include "utilities/align.hpp" |
39 |
42 |
40 RootSetClosure::RootSetClosure(EdgeQueue* edge_queue) : |
43 template <typename Delegate> |
41 _edge_queue(edge_queue) { |
44 RootSetClosure<Delegate>::RootSetClosure(Delegate* delegate) : _delegate(delegate) {} |
42 } |
|
43 |
45 |
44 void RootSetClosure::do_oop(oop* ref) { |
46 template <typename Delegate> |
|
47 void RootSetClosure<Delegate>::do_oop(oop* ref) { |
45 assert(ref != NULL, "invariant"); |
48 assert(ref != NULL, "invariant"); |
46 // We discard unaligned root references because |
49 // We discard unaligned root references because |
47 // our reference tagging scheme will use |
50 // our reference tagging scheme will use |
48 // the lowest bit in a represented reference |
51 // the lowest bit in a represented reference |
49 // to indicate the reference is narrow. |
52 // to indicate the reference is narrow. |
53 if (!is_aligned(ref, HeapWordSize)) { |
56 if (!is_aligned(ref, HeapWordSize)) { |
54 return; |
57 return; |
55 } |
58 } |
56 |
59 |
57 assert(is_aligned(ref, HeapWordSize), "invariant"); |
60 assert(is_aligned(ref, HeapWordSize), "invariant"); |
58 const oop pointee = *ref; |
61 if (*ref != NULL) { |
59 if (pointee != NULL) { |
62 _delegate->do_root(ref); |
60 closure_impl(ref, pointee); |
|
61 } |
63 } |
62 } |
64 } |
63 |
65 |
64 void RootSetClosure::do_oop(narrowOop* ref) { |
66 template <typename Delegate> |
|
67 void RootSetClosure<Delegate>::do_oop(narrowOop* ref) { |
65 assert(ref != NULL, "invariant"); |
68 assert(ref != NULL, "invariant"); |
66 assert(is_aligned(ref, sizeof(narrowOop)), "invariant"); |
69 assert(is_aligned(ref, sizeof(narrowOop)), "invariant"); |
67 const oop pointee = oopDesc::load_decode_heap_oop(ref); |
70 const oop pointee = oopDesc::load_decode_heap_oop(ref); |
68 if (pointee != NULL) { |
71 if (pointee != NULL) { |
69 closure_impl(UnifiedOop::encode(ref), pointee); |
72 _delegate->do_root(UnifiedOop::encode(ref)); |
70 } |
73 } |
71 } |
74 } |
72 |
75 |
73 void RootSetClosure::closure_impl(const oop* reference, const oop pointee) { |
76 class RootSetClosureMarkScope : public MarkingCodeBlobClosure::MarkScope {}; |
74 if (!_edge_queue->is_full()) { |
77 |
75 _edge_queue->add(NULL, reference); |
78 template <typename Delegate> |
76 } |
79 void RootSetClosure<Delegate>::process() { |
|
80 RootSetClosureMarkScope mark_scope; |
|
81 CLDToOopClosure cldt_closure(this); |
|
82 ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure); |
|
83 CodeBlobToOopClosure blobs(this, false); |
|
84 Threads::oops_do(this, NULL, &blobs); // XXX set CLDClosure to NULL |
|
85 ObjectSynchronizer::oops_do(this); |
|
86 Universe::oops_do(this); |
|
87 JNIHandles::oops_do(this); |
|
88 JvmtiExport::oops_do(this); |
|
89 SystemDictionary::oops_do(this); |
|
90 Management::oops_do(this); |
|
91 StringTable::oops_do(this); |
77 } |
92 } |
78 |
93 |
79 void RootSetClosure::add_to_queue(EdgeQueue* edge_queue) { |
94 template class RootSetClosure<BFSClosure>; |
80 RootSetClosure rs(edge_queue); |
95 template class RootSetClosure<DFSClosure>; |
81 process_roots(&rs); |
|
82 } |
|
83 |
|
84 class RootSetClosureMarkScope : public MarkingCodeBlobClosure::MarkScope { |
|
85 }; |
|
86 |
|
87 void RootSetClosure::process_roots(OopClosure* closure) { |
|
88 SaveRestoreCLDClaimBits save_restore_cld_claim_bits; |
|
89 RootSetClosureMarkScope mark_scope; |
|
90 |
|
91 CLDToOopClosure cldt_closure(closure); |
|
92 ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure); |
|
93 CodeBlobToOopClosure blobs(closure, false); |
|
94 Threads::oops_do(closure, NULL, &blobs); // XXX set CLDClosure to NULL |
|
95 ObjectSynchronizer::oops_do(closure); |
|
96 Universe::oops_do(closure); |
|
97 JNIHandles::oops_do(closure); |
|
98 JvmtiExport::oops_do(closure); |
|
99 SystemDictionary::oops_do(closure); |
|
100 Management::oops_do(closure); |
|
101 StringTable::oops_do(closure); |
|
102 } |
|