annotate src/hotspot/share/jfr/leakprofiler/checkpoint/eventEmitter.cpp @ 56006:90ead0febf56

8229258: Rework markOop and markOopDesc into a simpler mark word value carrier Reviewed-by: rkennke, coleenp, kbarrett, dcubed
author stefank
date Tue, 06 Aug 2019 10:48:21 +0200
parents 49102ba8cf14
children 947252a54b98
rev   line source
mgronlun@55571 1 /*
mgronlun@55571 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
mgronlun@55571 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
mgronlun@55571 4 *
mgronlun@55571 5 * This code is free software; you can redistribute it and/or modify it
mgronlun@55571 6 * under the terms of the GNU General Public License version 2 only, as
mgronlun@55571 7 * published by the Free Software Foundation.
mgronlun@55571 8 *
mgronlun@55571 9 * This code is distributed in the hope that it will be useful, but WITHOUT
mgronlun@55571 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
mgronlun@55571 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
mgronlun@55571 12 * version 2 for more details (a copy is included in the LICENSE file that
mgronlun@55571 13 * accompanied this code).
mgronlun@55571 14 *
mgronlun@55571 15 * You should have received a copy of the GNU General Public License version
mgronlun@55571 16 * 2 along with this work; if not, write to the Free Software Foundation,
mgronlun@55571 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
mgronlun@55571 18 *
mgronlun@55571 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
mgronlun@55571 20 * or visit www.oracle.com if you need additional information or have any
mgronlun@55571 21 * questions.
mgronlun@55571 22 *
mgronlun@55571 23 */
mgronlun@55571 24
mgronlun@55571 25 #include "precompiled.hpp"
mgronlun@55571 26 #include "jfr/jfrEvents.hpp"
mgronlun@55571 27 #include "jfr/leakprofiler/chains/edgeStore.hpp"
mgronlun@55571 28 #include "jfr/leakprofiler/chains/pathToGcRootsOperation.hpp"
mgronlun@55571 29 #include "jfr/leakprofiler/checkpoint/eventEmitter.hpp"
mgronlun@55571 30 #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"
mgronlun@55571 31 #include "jfr/leakprofiler/sampling/objectSample.hpp"
mgronlun@55571 32 #include "jfr/leakprofiler/sampling/objectSampler.hpp"
mgronlun@55571 33 #include "logging/log.hpp"
mgronlun@55571 34 #include "memory/resourceArea.hpp"
mgronlun@55571 35 #include "oops/markOop.hpp"
mgronlun@55571 36 #include "oops/oop.inline.hpp"
mgronlun@55571 37 #include "runtime/thread.inline.hpp"
mgronlun@55571 38 #include "runtime/vmThread.hpp"
mgronlun@55571 39
mgronlun@55571 40 EventEmitter::EventEmitter(const JfrTicks& start_time, const JfrTicks& end_time) :
mgronlun@55571 41 _start_time(start_time),
mgronlun@55571 42 _end_time(end_time),
mgronlun@55571 43 _thread(Thread::current()),
mgronlun@55571 44 _jfr_thread_local(_thread->jfr_thread_local()),
mgronlun@55571 45 _thread_id(_thread->jfr_thread_local()->thread_id()) {}
mgronlun@55571 46
mgronlun@55571 47 EventEmitter::~EventEmitter() {
mgronlun@55571 48 // restore / reset thread local stack trace and thread id
mgronlun@55571 49 _jfr_thread_local->set_thread_id(_thread_id);
mgronlun@55571 50 _jfr_thread_local->clear_cached_stack_trace();
mgronlun@55571 51 }
mgronlun@55571 52
mgronlun@55571 53 void EventEmitter::emit(ObjectSampler* sampler, int64_t cutoff_ticks, bool emit_all) {
mgronlun@55571 54 assert(sampler != NULL, "invariant");
mgronlun@55571 55
mgronlun@55571 56 ResourceMark rm;
mgronlun@55571 57 EdgeStore edge_store;
mgronlun@55571 58 if (cutoff_ticks <= 0) {
mgronlun@55571 59 // no reference chains
mgronlun@55571 60 JfrTicks time_stamp = JfrTicks::now();
mgronlun@55571 61 EventEmitter emitter(time_stamp, time_stamp);
mgronlun@55571 62 emitter.write_events(sampler, &edge_store, emit_all);
mgronlun@55571 63 return;
mgronlun@55571 64 }
mgronlun@55571 65 // events emitted with reference chains require a safepoint operation
mgronlun@55571 66 PathToGcRootsOperation op(sampler, &edge_store, cutoff_ticks, emit_all);
mgronlun@55571 67 VMThread::execute(&op);
mgronlun@55571 68 }
mgronlun@55571 69
mgronlun@55571 70 size_t EventEmitter::write_events(ObjectSampler* object_sampler, EdgeStore* edge_store, bool emit_all) {
mgronlun@55571 71 assert(_thread == Thread::current(), "invariant");
mgronlun@55571 72 assert(_thread->jfr_thread_local() == _jfr_thread_local, "invariant");
mgronlun@55571 73 assert(object_sampler != NULL, "invariant");
mgronlun@55571 74 assert(edge_store != NULL, "invariant");
mgronlun@55571 75
mgronlun@55571 76 const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value();
mgronlun@55571 77 size_t count = 0;
mgronlun@55571 78
mgronlun@55571 79 const ObjectSample* current = object_sampler->first();
mgronlun@55571 80 while (current != NULL) {
mgronlun@55571 81 ObjectSample* prev = current->prev();
mgronlun@55571 82 if (current->is_alive_and_older_than(last_sweep)) {
mgronlun@55571 83 write_event(current, edge_store);
mgronlun@55571 84 ++count;
mgronlun@55571 85 }
mgronlun@55571 86 current = prev;
mgronlun@55571 87 }
mgronlun@55571 88
mgronlun@55571 89 if (count > 0) {
mgronlun@55571 90 // serialize associated checkpoints and potential chains
mgronlun@55571 91 ObjectSampleCheckpoint::write(object_sampler, edge_store, emit_all, _thread);
mgronlun@55571 92 }
mgronlun@55571 93 return count;
mgronlun@55571 94 }
mgronlun@55571 95
mgronlun@55571 96 static int array_size(const oop object) {
mgronlun@55571 97 assert(object != NULL, "invariant");
mgronlun@55571 98 if (object->is_array()) {
mgronlun@55571 99 return arrayOop(object)->length();
mgronlun@55571 100 }
mgronlun@55571 101 return min_jint;
mgronlun@55571 102 }
mgronlun@55571 103
mgronlun@55571 104 void EventEmitter::write_event(const ObjectSample* sample, EdgeStore* edge_store) {
mgronlun@55571 105 assert(sample != NULL, "invariant");
mgronlun@55571 106 assert(!sample->is_dead(), "invariant");
mgronlun@55571 107 assert(edge_store != NULL, "invariant");
mgronlun@55571 108 assert(_jfr_thread_local != NULL, "invariant");
mgronlun@55571 109
mgronlun@55571 110 const oop* object_addr = sample->object_addr();
mgronlun@55571 111 traceid gc_root_id = 0;
mgronlun@55571 112 const Edge* edge = NULL;
mgronlun@55571 113 if (SafepointSynchronize::is_at_safepoint()) {
stefank@56006 114 edge = (const Edge*)(*object_addr)->mark().to_pointer();
mgronlun@55571 115 }
mgronlun@55571 116 if (edge == NULL) {
mgronlun@55571 117 // In order to dump out a representation of the event
mgronlun@55571 118 // even though it was not reachable / too long to reach,
mgronlun@55571 119 // we need to register a top level edge for this object.
mgronlun@55571 120 edge = edge_store->put(object_addr);
mgronlun@55571 121 } else {
mgronlun@55571 122 gc_root_id = edge_store->gc_root_id(edge);
mgronlun@55571 123 }
mgronlun@55571 124
mgronlun@55571 125 assert(edge != NULL, "invariant");
mgronlun@55571 126 const traceid object_id = edge_store->get_id(edge);
mgronlun@55571 127 assert(object_id != 0, "invariant");
mgronlun@55571 128
mgronlun@55571 129 EventOldObjectSample e(UNTIMED);
mgronlun@55571 130 e.set_starttime(_start_time);
mgronlun@55571 131 e.set_endtime(_end_time);
mgronlun@55571 132 e.set_allocationTime(sample->allocation_time());
mgronlun@55571 133 e.set_lastKnownHeapUsage(sample->heap_used_at_last_gc());
mgronlun@55571 134 e.set_object(object_id);
mgronlun@55571 135 e.set_arrayElements(array_size(edge->pointee()));
mgronlun@55571 136 e.set_root(gc_root_id);
mgronlun@55571 137
mgronlun@55571 138 // Temporarily assigning both the stack trace id and thread id
mgronlun@55571 139 // onto the thread local data structure of the emitter thread (for the duration
mgronlun@55571 140 // of the commit() call). This trick provides a means to override
mgronlun@55571 141 // the event generation mechanism by injecting externally provided id's.
mgronlun@55571 142 // At this particular location, it allows us to emit an old object event
mgronlun@55571 143 // supplying information from where the actual sampling occurred.
mgronlun@55571 144 _jfr_thread_local->set_cached_stack_trace_id(sample->stack_trace_id());
mgronlun@55571 145 assert(sample->has_thread(), "invariant");
mgronlun@55571 146 _jfr_thread_local->set_thread_id(sample->thread_id());
mgronlun@55571 147 e.commit();
mgronlun@55571 148 }