src/share/vm/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp

Mon, 12 Aug 2019 18:30:40 +0300

author
apetushkov
date
Mon, 12 Aug 2019 18:30:40 +0300
changeset 9858
b985cbb00e68
child 9885
8e875c964f41
permissions
-rw-r--r--

8223147: JFR Backport
8199712: Flight Recorder
8203346: JFR: Inconsistent signature of jfr_add_string_constant
8195817: JFR.stop should require name of recording
8195818: JFR.start should increase autogenerated name by one
8195819: Remove recording=x from jcmd JFR.check output
8203921: JFR thread sampling is missing fixes from JDK-8194552
8203929: Limit amount of data for JFR.dump
8203664: JFR start failure after AppCDS archive created with JFR StartFlightRecording
8003209: JFR events for network utilization
8207392: [PPC64] Implement JFR profiling
8202835: jfr/event/os/TestSystemProcess.java fails on missing events
Summary: Backport JFR from JDK11. Initial integration
Reviewed-by: neugens

apetushkov@9858 1 /*
apetushkov@9858 2 * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
apetushkov@9858 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
apetushkov@9858 4 *
apetushkov@9858 5 * This code is free software; you can redistribute it and/or modify it
apetushkov@9858 6 * under the terms of the GNU General Public License version 2 only, as
apetushkov@9858 7 * published by the Free Software Foundation.
apetushkov@9858 8 *
apetushkov@9858 9 * This code is distributed in the hope that it will be useful, but WITHOUT
apetushkov@9858 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
apetushkov@9858 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
apetushkov@9858 12 * version 2 for more details (a copy is included in the LICENSE file that
apetushkov@9858 13 * accompanied this code).
apetushkov@9858 14 *
apetushkov@9858 15 * You should have received a copy of the GNU General Public License version
apetushkov@9858 16 * 2 along with this work; if not, write to the Free Software Foundation,
apetushkov@9858 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
apetushkov@9858 18 *
apetushkov@9858 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
apetushkov@9858 20 * or visit www.oracle.com if you need additional information or have any
apetushkov@9858 21 * questions.
apetushkov@9858 22 *
apetushkov@9858 23 */
apetushkov@9858 24
apetushkov@9858 25 #include "precompiled.hpp"
apetushkov@9858 26 #include "jfr/jfrEvents.hpp"
apetushkov@9858 27 #include "jfr/recorder/jfrRecorder.hpp"
apetushkov@9858 28 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
apetushkov@9858 29 #include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
apetushkov@9858 30 #include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"
apetushkov@9858 31 #include "jfr/leakprofiler/chains/edgeStore.hpp"
apetushkov@9858 32 #include "jfr/leakprofiler/chains/objectSampleMarker.hpp"
apetushkov@9858 33 #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
apetushkov@9858 34 #include "jfr/leakprofiler/checkpoint/objectSampleWriter.hpp"
apetushkov@9858 35 #include "jfr/leakprofiler/leakProfiler.hpp"
apetushkov@9858 36 #include "jfr/leakprofiler/sampling/objectSample.hpp"
apetushkov@9858 37 #include "jfr/leakprofiler/sampling/objectSampler.hpp"
apetushkov@9858 38 #include "jfr/leakprofiler/utilities/rootType.hpp"
apetushkov@9858 39 #include "jfr/metadata/jfrSerializer.hpp"
apetushkov@9858 40 #include "runtime/interfaceSupport.hpp"
apetushkov@9858 41 #include "runtime/mutexLocker.hpp"
apetushkov@9858 42 #include "runtime/thread.inline.hpp"
apetushkov@9858 43
apetushkov@9858 44 template <typename SampleProcessor>
apetushkov@9858 45 static void do_samples(ObjectSample* sample, const ObjectSample* const end, SampleProcessor& processor) {
apetushkov@9858 46 assert(sample != NULL, "invariant");
apetushkov@9858 47 while (sample != end) {
apetushkov@9858 48 processor.sample_do(sample);
apetushkov@9858 49 sample = sample->next();
apetushkov@9858 50 }
apetushkov@9858 51 }
apetushkov@9858 52
apetushkov@9858 53 class RootSystemType : public JfrSerializer {
apetushkov@9858 54 public:
apetushkov@9858 55 void serialize(JfrCheckpointWriter& writer) {
apetushkov@9858 56 const u4 nof_root_systems = OldObjectRoot::_number_of_systems;
apetushkov@9858 57 writer.write_count(nof_root_systems);
apetushkov@9858 58 for (u4 i = 0; i < nof_root_systems; ++i) {
apetushkov@9858 59 writer.write_key(i);
apetushkov@9858 60 writer.write(OldObjectRoot::system_description((OldObjectRoot::System)i));
apetushkov@9858 61 }
apetushkov@9858 62 }
apetushkov@9858 63 };
apetushkov@9858 64
apetushkov@9858 65 class RootType : public JfrSerializer {
apetushkov@9858 66 public:
apetushkov@9858 67 void serialize(JfrCheckpointWriter& writer) {
apetushkov@9858 68 const u4 nof_root_types = OldObjectRoot::_number_of_types;
apetushkov@9858 69 writer.write_count(nof_root_types);
apetushkov@9858 70 for (u4 i = 0; i < nof_root_types; ++i) {
apetushkov@9858 71 writer.write_key(i);
apetushkov@9858 72 writer.write(OldObjectRoot::type_description((OldObjectRoot::Type)i));
apetushkov@9858 73 }
apetushkov@9858 74 }
apetushkov@9858 75 };
apetushkov@9858 76
apetushkov@9858 77 class CheckpointInstall {
apetushkov@9858 78 private:
apetushkov@9858 79 const JfrCheckpointBlobHandle& _cp;
apetushkov@9858 80 public:
apetushkov@9858 81 CheckpointInstall(const JfrCheckpointBlobHandle& cp) : _cp(cp) {}
apetushkov@9858 82 void sample_do(ObjectSample* sample) {
apetushkov@9858 83 assert(sample != NULL, "invariant");
apetushkov@9858 84 if (!sample->is_dead()) {
apetushkov@9858 85 sample->set_klass_checkpoint(_cp);
apetushkov@9858 86 }
apetushkov@9858 87 }
apetushkov@9858 88 };
apetushkov@9858 89
apetushkov@9858 90 class CheckpointWrite {
apetushkov@9858 91 private:
apetushkov@9858 92 JfrCheckpointWriter& _writer;
apetushkov@9858 93 const jlong _last_sweep;
apetushkov@9858 94 public:
apetushkov@9858 95 CheckpointWrite(JfrCheckpointWriter& writer, jlong last_sweep) : _writer(writer), _last_sweep(last_sweep) {}
apetushkov@9858 96 void sample_do(ObjectSample* sample) {
apetushkov@9858 97 assert(sample != NULL, "invariant");
apetushkov@9858 98 if (sample->is_alive_and_older_than(_last_sweep)) {
apetushkov@9858 99 if (sample->has_thread_checkpoint()) {
apetushkov@9858 100 const JfrCheckpointBlobHandle& thread_cp = sample->thread_checkpoint();
apetushkov@9858 101 thread_cp->exclusive_write(_writer);
apetushkov@9858 102 }
apetushkov@9858 103 if (sample->has_klass_checkpoint()) {
apetushkov@9858 104 const JfrCheckpointBlobHandle& klass_cp = sample->klass_checkpoint();
apetushkov@9858 105 klass_cp->exclusive_write(_writer);
apetushkov@9858 106 }
apetushkov@9858 107 }
apetushkov@9858 108 }
apetushkov@9858 109 };
apetushkov@9858 110
apetushkov@9858 111 class CheckpointStateReset {
apetushkov@9858 112 private:
apetushkov@9858 113 const jlong _last_sweep;
apetushkov@9858 114 public:
apetushkov@9858 115 CheckpointStateReset(jlong last_sweep) : _last_sweep(last_sweep) {}
apetushkov@9858 116 void sample_do(ObjectSample* sample) {
apetushkov@9858 117 assert(sample != NULL, "invariant");
apetushkov@9858 118 if (sample->is_alive_and_older_than(_last_sweep)) {
apetushkov@9858 119 if (sample->has_thread_checkpoint()) {
apetushkov@9858 120 const JfrCheckpointBlobHandle& thread_cp = sample->thread_checkpoint();
apetushkov@9858 121 thread_cp->reset_write_state();
apetushkov@9858 122 }
apetushkov@9858 123 if (sample->has_klass_checkpoint()) {
apetushkov@9858 124 const JfrCheckpointBlobHandle& klass_cp = sample->klass_checkpoint();
apetushkov@9858 125 klass_cp->reset_write_state();
apetushkov@9858 126 }
apetushkov@9858 127 }
apetushkov@9858 128 }
apetushkov@9858 129 };
apetushkov@9858 130
apetushkov@9858 131 class StackTraceWrite {
apetushkov@9858 132 private:
apetushkov@9858 133 JfrStackTraceRepository& _stack_trace_repo;
apetushkov@9858 134 JfrCheckpointWriter& _writer;
apetushkov@9858 135 int _count;
apetushkov@9858 136 public:
apetushkov@9858 137 StackTraceWrite(JfrStackTraceRepository& stack_trace_repo, JfrCheckpointWriter& writer) :
apetushkov@9858 138 _stack_trace_repo(stack_trace_repo), _writer(writer), _count(0) {
apetushkov@9858 139 JfrStacktrace_lock->lock();
apetushkov@9858 140 }
apetushkov@9858 141 ~StackTraceWrite() {
apetushkov@9858 142 assert(JfrStacktrace_lock->owned_by_self(), "invariant");
apetushkov@9858 143 JfrStacktrace_lock->unlock();
apetushkov@9858 144 }
apetushkov@9858 145
apetushkov@9858 146 void sample_do(ObjectSample* sample) {
apetushkov@9858 147 assert(sample != NULL, "invariant");
apetushkov@9858 148 if (!sample->is_dead()) {
apetushkov@9858 149 if (sample->has_stack_trace()) {
apetushkov@9858 150 JfrTraceId::use(sample->klass(), true);
apetushkov@9858 151 _stack_trace_repo.write(_writer, sample->stack_trace_id(), sample->stack_trace_hash());
apetushkov@9858 152 ++_count;
apetushkov@9858 153 }
apetushkov@9858 154 }
apetushkov@9858 155 }
apetushkov@9858 156
apetushkov@9858 157 int count() const {
apetushkov@9858 158 return _count;
apetushkov@9858 159 }
apetushkov@9858 160 };
apetushkov@9858 161
apetushkov@9858 162 class SampleMark {
apetushkov@9858 163 private:
apetushkov@9858 164 ObjectSampleMarker& _marker;
apetushkov@9858 165 jlong _last_sweep;
apetushkov@9858 166 int _count;
apetushkov@9858 167 public:
apetushkov@9858 168 SampleMark(ObjectSampleMarker& marker, jlong last_sweep) : _marker(marker),
apetushkov@9858 169 _last_sweep(last_sweep),
apetushkov@9858 170 _count(0) {}
apetushkov@9858 171 void sample_do(ObjectSample* sample) {
apetushkov@9858 172 assert(sample != NULL, "invariant");
apetushkov@9858 173 if (sample->is_alive_and_older_than(_last_sweep)) {
apetushkov@9858 174 _marker.mark(sample->object());
apetushkov@9858 175 ++_count;
apetushkov@9858 176 }
apetushkov@9858 177 }
apetushkov@9858 178
apetushkov@9858 179 int count() const {
apetushkov@9858 180 return _count;
apetushkov@9858 181 }
apetushkov@9858 182 };
apetushkov@9858 183
apetushkov@9858 184 void ObjectSampleCheckpoint::install(JfrCheckpointWriter& writer, bool class_unload, bool resume) {
apetushkov@9858 185 assert(class_unload ? SafepointSynchronize::is_at_safepoint() : LeakProfiler::is_suspended(), "invariant");
apetushkov@9858 186
apetushkov@9858 187 if (!writer.has_data()) {
apetushkov@9858 188 if (!class_unload) {
apetushkov@9858 189 LeakProfiler::resume();
apetushkov@9858 190 }
apetushkov@9858 191 assert(LeakProfiler::is_running(), "invariant");
apetushkov@9858 192 return;
apetushkov@9858 193 }
apetushkov@9858 194
apetushkov@9858 195 assert(writer.has_data(), "invariant");
apetushkov@9858 196 const JfrCheckpointBlobHandle h_cp = writer.checkpoint_blob();
apetushkov@9858 197
apetushkov@9858 198 const ObjectSampler* const object_sampler = LeakProfiler::object_sampler();
apetushkov@9858 199 assert(object_sampler != NULL, "invariant");
apetushkov@9858 200
apetushkov@9858 201 ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());
apetushkov@9858 202 const ObjectSample* const last_resolved = object_sampler->last_resolved();
apetushkov@9858 203 CheckpointInstall install(h_cp);
apetushkov@9858 204
apetushkov@9858 205 if (class_unload) {
apetushkov@9858 206 if (last != NULL) {
apetushkov@9858 207 // all samples need the class unload information
apetushkov@9858 208 do_samples(last, NULL, install);
apetushkov@9858 209 }
apetushkov@9858 210 assert(LeakProfiler::is_running(), "invariant");
apetushkov@9858 211 return;
apetushkov@9858 212 }
apetushkov@9858 213
apetushkov@9858 214 // only new samples since last resolved checkpoint
apetushkov@9858 215 if (last != last_resolved) {
apetushkov@9858 216 do_samples(last, last_resolved, install);
apetushkov@9858 217 if (resume) {
apetushkov@9858 218 const_cast<ObjectSampler*>(object_sampler)->set_last_resolved(last);
apetushkov@9858 219 }
apetushkov@9858 220 }
apetushkov@9858 221 assert(LeakProfiler::is_suspended(), "invariant");
apetushkov@9858 222 if (resume) {
apetushkov@9858 223 LeakProfiler::resume();
apetushkov@9858 224 assert(LeakProfiler::is_running(), "invariant");
apetushkov@9858 225 }
apetushkov@9858 226 }
apetushkov@9858 227
apetushkov@9858 228 void ObjectSampleCheckpoint::write(const EdgeStore* edge_store, bool emit_all, Thread* thread) {
apetushkov@9858 229 assert(edge_store != NULL, "invariant");
apetushkov@9858 230 assert(thread != NULL, "invariant");
apetushkov@9858 231 static bool types_registered = false;
apetushkov@9858 232 if (!types_registered) {
apetushkov@9858 233 JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTSYSTEM, false, true, new RootSystemType());
apetushkov@9858 234 JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTTYPE, false, true, new RootType());
apetushkov@9858 235 types_registered = true;
apetushkov@9858 236 }
apetushkov@9858 237 const ObjectSampler* const object_sampler = LeakProfiler::object_sampler();
apetushkov@9858 238 assert(object_sampler != NULL, "invariant");
apetushkov@9858 239 const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value();
apetushkov@9858 240 ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());
apetushkov@9858 241 {
apetushkov@9858 242 JfrCheckpointWriter writer(false, false, thread);
apetushkov@9858 243 CheckpointWrite checkpoint_write(writer, last_sweep);
apetushkov@9858 244 do_samples(last, NULL, checkpoint_write);
apetushkov@9858 245 }
apetushkov@9858 246 CheckpointStateReset state_reset(last_sweep);
apetushkov@9858 247 do_samples(last, NULL, state_reset);
apetushkov@9858 248 if (!edge_store->is_empty()) {
apetushkov@9858 249 // java object and chain representations
apetushkov@9858 250 JfrCheckpointWriter writer(false, true, thread);
apetushkov@9858 251 ObjectSampleWriter osw(writer, edge_store);
apetushkov@9858 252 edge_store->iterate_edges(osw);
apetushkov@9858 253 }
apetushkov@9858 254 }
apetushkov@9858 255
apetushkov@9858 256 WriteObjectSampleStacktrace::WriteObjectSampleStacktrace(JfrStackTraceRepository& repo) :
apetushkov@9858 257 _stack_trace_repo(repo) {
apetushkov@9858 258 }
apetushkov@9858 259
apetushkov@9858 260 bool WriteObjectSampleStacktrace::process() {
apetushkov@9858 261 assert(SafepointSynchronize::is_at_safepoint(), "invariant");
apetushkov@9858 262 if (!LeakProfiler::is_running()) {
apetushkov@9858 263 return true;
apetushkov@9858 264 }
apetushkov@9858 265 // Suspend the LeakProfiler subsystem
apetushkov@9858 266 // to ensure stable samples even
apetushkov@9858 267 // after we return from the safepoint.
apetushkov@9858 268 LeakProfiler::suspend();
apetushkov@9858 269 assert(!LeakProfiler::is_running(), "invariant");
apetushkov@9858 270 assert(LeakProfiler::is_suspended(), "invariant");
apetushkov@9858 271
apetushkov@9858 272 const ObjectSampler* object_sampler = LeakProfiler::object_sampler();
apetushkov@9858 273 assert(object_sampler != NULL, "invariant");
apetushkov@9858 274 assert(LeakProfiler::is_suspended(), "invariant");
apetushkov@9858 275
apetushkov@9858 276 ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());
apetushkov@9858 277 const ObjectSample* const last_resolved = object_sampler->last_resolved();
apetushkov@9858 278 if (last == last_resolved) {
apetushkov@9858 279 assert(LeakProfiler::is_suspended(), "invariant");
apetushkov@9858 280 return true;
apetushkov@9858 281 }
apetushkov@9858 282
apetushkov@9858 283 JfrCheckpointWriter writer(false, true, Thread::current());
apetushkov@9858 284 const JfrCheckpointContext ctx = writer.context();
apetushkov@9858 285
apetushkov@9858 286 writer.write_type(TYPE_STACKTRACE);
apetushkov@9858 287 const jlong count_offset = writer.reserve(sizeof(u4));
apetushkov@9858 288
apetushkov@9858 289 int count = 0;
apetushkov@9858 290 {
apetushkov@9858 291 StackTraceWrite stack_trace_write(_stack_trace_repo, writer); // JfrStacktrace_lock
apetushkov@9858 292 do_samples(last, last_resolved, stack_trace_write);
apetushkov@9858 293 count = stack_trace_write.count();
apetushkov@9858 294 }
apetushkov@9858 295 if (count == 0) {
apetushkov@9858 296 writer.set_context(ctx);
apetushkov@9858 297 assert(LeakProfiler::is_suspended(), "invariant");
apetushkov@9858 298 return true;
apetushkov@9858 299 }
apetushkov@9858 300 assert(count > 0, "invariant");
apetushkov@9858 301 writer.write_count((u4)count, count_offset);
apetushkov@9858 302 JfrStackTraceRepository::write_metadata(writer);
apetushkov@9858 303
apetushkov@9858 304 ObjectSampleCheckpoint::install(writer, false, false);
apetushkov@9858 305 assert(LeakProfiler::is_suspended(), "invariant");
apetushkov@9858 306 return true;
apetushkov@9858 307 }
apetushkov@9858 308
apetushkov@9858 309 int ObjectSampleCheckpoint::mark(ObjectSampleMarker& marker, bool emit_all) {
apetushkov@9858 310 const ObjectSampler* object_sampler = LeakProfiler::object_sampler();
apetushkov@9858 311 assert(object_sampler != NULL, "invariant");
apetushkov@9858 312 ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());
apetushkov@9858 313 if (last == NULL) {
apetushkov@9858 314 return 0;
apetushkov@9858 315 }
apetushkov@9858 316 const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value();
apetushkov@9858 317 SampleMark mark(marker, last_sweep);
apetushkov@9858 318 do_samples(last, NULL, mark);
apetushkov@9858 319 return mark.count();
apetushkov@9858 320 }

mercurial