gcTrace.cpp revision 8413:92457dfb91bd
1/*
2 * Copyright (c) 2012, 2015, 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 "gc/shared/copyFailedInfo.hpp"
27#include "gc/shared/gcHeapSummary.hpp"
28#include "gc/shared/gcId.hpp"
29#include "gc/shared/gcTimer.hpp"
30#include "gc/shared/gcTrace.hpp"
31#include "gc/shared/objectCountEventSender.hpp"
32#include "gc/shared/referenceProcessorStats.hpp"
33#include "memory/heapInspection.hpp"
34#include "memory/resourceArea.hpp"
35#include "runtime/os.hpp"
36#include "utilities/globalDefinitions.hpp"
37#include "utilities/macros.hpp"
38#include "utilities/ticks.inline.hpp"
39#if INCLUDE_ALL_GCS
40#include "gc/g1/evacuationInfo.hpp"
41#endif
42
43#define assert_unset_gc_id() assert(_shared_gc_info.gc_id().is_undefined(), "GC already started?")
44#define assert_set_gc_id() assert(!_shared_gc_info.gc_id().is_undefined(), "GC not started?")
45
46void GCTracer::report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp) {
47  assert_unset_gc_id();
48
49  GCId gc_id = GCId::create();
50  _shared_gc_info.set_gc_id(gc_id);
51  _shared_gc_info.set_cause(cause);
52  _shared_gc_info.set_start_timestamp(timestamp);
53}
54
55void GCTracer::report_gc_start(GCCause::Cause cause, const Ticks& timestamp) {
56  assert_unset_gc_id();
57
58  report_gc_start_impl(cause, timestamp);
59}
60
61bool GCTracer::has_reported_gc_start() const {
62  return !_shared_gc_info.gc_id().is_undefined();
63}
64
65void GCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
66  assert_set_gc_id();
67
68  _shared_gc_info.set_sum_of_pauses(time_partitions->sum_of_pauses());
69  _shared_gc_info.set_longest_pause(time_partitions->longest_pause());
70  _shared_gc_info.set_end_timestamp(timestamp);
71
72  send_phase_events(time_partitions);
73  send_garbage_collection_event();
74}
75
76void GCTracer::report_gc_end(const Ticks& timestamp, TimePartitions* time_partitions) {
77  assert_set_gc_id();
78
79  report_gc_end_impl(timestamp, time_partitions);
80
81  _shared_gc_info.set_gc_id(GCId::undefined());
82}
83
84void GCTracer::report_gc_reference_stats(const ReferenceProcessorStats& rps) const {
85  assert_set_gc_id();
86
87  send_reference_stats_event(REF_SOFT, rps.soft_count());
88  send_reference_stats_event(REF_WEAK, rps.weak_count());
89  send_reference_stats_event(REF_FINAL, rps.final_count());
90  send_reference_stats_event(REF_PHANTOM, rps.phantom_count());
91}
92
93#if INCLUDE_SERVICES
94class ObjectCountEventSenderClosure : public KlassInfoClosure {
95  const GCId _gc_id;
96  const double _size_threshold_percentage;
97  const size_t _total_size_in_words;
98  const Ticks _timestamp;
99
100 public:
101  ObjectCountEventSenderClosure(GCId gc_id, size_t total_size_in_words, const Ticks& timestamp) :
102    _gc_id(gc_id),
103    _size_threshold_percentage(ObjectCountCutOffPercent / 100),
104    _total_size_in_words(total_size_in_words),
105    _timestamp(timestamp)
106  {}
107
108  virtual void do_cinfo(KlassInfoEntry* entry) {
109    if (should_send_event(entry)) {
110      ObjectCountEventSender::send(entry, _gc_id, _timestamp);
111    }
112  }
113
114 private:
115  bool should_send_event(const KlassInfoEntry* entry) const {
116    double percentage_of_heap = ((double) entry->words()) / _total_size_in_words;
117    return percentage_of_heap >= _size_threshold_percentage;
118  }
119};
120
121void GCTracer::report_object_count_after_gc(BoolObjectClosure* is_alive_cl) {
122  assert_set_gc_id();
123  assert(is_alive_cl != NULL, "Must supply function to check liveness");
124
125  if (ObjectCountEventSender::should_send_event()) {
126    ResourceMark rm;
127
128    KlassInfoTable cit(false);
129    if (!cit.allocation_failed()) {
130      HeapInspection hi(false, false, false, NULL);
131      hi.populate_table(&cit, is_alive_cl);
132      ObjectCountEventSenderClosure event_sender(_shared_gc_info.gc_id(), cit.size_of_instances_in_words(), Ticks::now());
133      cit.iterate(&event_sender);
134    }
135  }
136}
137#endif // INCLUDE_SERVICES
138
139void GCTracer::report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary) const {
140  assert_set_gc_id();
141
142  send_gc_heap_summary_event(when, heap_summary);
143}
144
145void GCTracer::report_metaspace_summary(GCWhen::Type when, const MetaspaceSummary& summary) const {
146  assert_set_gc_id();
147
148  send_meta_space_summary_event(when, summary);
149
150  send_metaspace_chunk_free_list_summary(when, Metaspace::NonClassType, summary.metaspace_chunk_free_list_summary());
151  if (UseCompressedClassPointers) {
152    send_metaspace_chunk_free_list_summary(when, Metaspace::ClassType, summary.class_chunk_free_list_summary());
153  }
154}
155
156void YoungGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
157  assert_set_gc_id();
158  assert(_tenuring_threshold != UNSET_TENURING_THRESHOLD, "Tenuring threshold has not been reported");
159
160  GCTracer::report_gc_end_impl(timestamp, time_partitions);
161  send_young_gc_event();
162
163  _tenuring_threshold = UNSET_TENURING_THRESHOLD;
164}
165
166void YoungGCTracer::report_promotion_failed(const PromotionFailedInfo& pf_info) const {
167  assert_set_gc_id();
168
169  send_promotion_failed_event(pf_info);
170}
171
172void YoungGCTracer::report_tenuring_threshold(const uint tenuring_threshold) {
173  _tenuring_threshold = tenuring_threshold;
174}
175
176bool YoungGCTracer::should_report_promotion_in_new_plab_event() const {
177  return should_send_promotion_in_new_plab_event();
178}
179
180bool YoungGCTracer::should_report_promotion_outside_plab_event() const {
181  return should_send_promotion_outside_plab_event();
182}
183
184void YoungGCTracer::report_promotion_in_new_plab_event(Klass* klass, size_t obj_size,
185                                                       uint age, bool tenured,
186                                                       size_t plab_size) const {
187  assert_set_gc_id();
188  send_promotion_in_new_plab_event(klass, obj_size, age, tenured, plab_size);
189}
190
191void YoungGCTracer::report_promotion_outside_plab_event(Klass* klass, size_t obj_size,
192                                                        uint age, bool tenured) const {
193  assert_set_gc_id();
194  send_promotion_outside_plab_event(klass, obj_size, age, tenured);
195}
196
197void OldGCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
198  assert_set_gc_id();
199
200  GCTracer::report_gc_end_impl(timestamp, time_partitions);
201  send_old_gc_event();
202}
203
204void ParallelOldTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
205  assert_set_gc_id();
206
207  OldGCTracer::report_gc_end_impl(timestamp, time_partitions);
208  send_parallel_old_event();
209}
210
211void ParallelOldTracer::report_dense_prefix(void* dense_prefix) {
212  assert_set_gc_id();
213
214  _parallel_old_gc_info.report_dense_prefix(dense_prefix);
215}
216
217void OldGCTracer::report_concurrent_mode_failure() {
218  assert_set_gc_id();
219
220  send_concurrent_mode_failure_event();
221}
222
223#if INCLUDE_ALL_GCS
224void G1NewTracer::report_yc_type(G1YCType type) {
225  assert_set_gc_id();
226
227  _g1_young_gc_info.set_type(type);
228}
229
230void G1NewTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
231  assert_set_gc_id();
232
233  YoungGCTracer::report_gc_end_impl(timestamp, time_partitions);
234  send_g1_young_gc_event();
235}
236
237void G1NewTracer::report_evacuation_info(EvacuationInfo* info) {
238  assert_set_gc_id();
239
240  send_evacuation_info_event(info);
241}
242
243void G1NewTracer::report_evacuation_failed(EvacuationFailedInfo& ef_info) {
244  assert_set_gc_id();
245
246  send_evacuation_failed_event(ef_info);
247  ef_info.reset();
248}
249#endif
250