Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/jfr/leakprofiler/checkpoint/objectSampleCheckpoint.cpp
38922 views
/*1* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "jfr/jfrEvents.hpp"26#include "jfr/recorder/jfrRecorder.hpp"27#include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"28#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"29#include "jfr/recorder/stacktrace/jfrStackTraceRepository.hpp"30#include "jfr/leakprofiler/chains/edgeStore.hpp"31#include "jfr/leakprofiler/chains/objectSampleMarker.hpp"32#include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp"33#include "jfr/leakprofiler/checkpoint/objectSampleWriter.hpp"34#include "jfr/leakprofiler/leakProfiler.hpp"35#include "jfr/leakprofiler/sampling/objectSample.hpp"36#include "jfr/leakprofiler/sampling/objectSampler.hpp"37#include "jfr/leakprofiler/utilities/rootType.hpp"38#include "jfr/metadata/jfrSerializer.hpp"39#include "runtime/interfaceSupport.hpp"40#include "runtime/mutexLocker.hpp"41#include "runtime/thread.inline.hpp"4243template <typename SampleProcessor>44static void do_samples(ObjectSample* sample, const ObjectSample* const end, SampleProcessor& processor) {45assert(sample != NULL, "invariant");46while (sample != end) {47processor.sample_do(sample);48sample = sample->next();49}50}5152class RootSystemType : public JfrSerializer {53public:54void serialize(JfrCheckpointWriter& writer) {55const u4 nof_root_systems = OldObjectRoot::_number_of_systems;56writer.write_count(nof_root_systems);57for (u4 i = 0; i < nof_root_systems; ++i) {58writer.write_key(i);59writer.write(OldObjectRoot::system_description((OldObjectRoot::System)i));60}61}62};6364class RootType : public JfrSerializer {65public:66void serialize(JfrCheckpointWriter& writer) {67const u4 nof_root_types = OldObjectRoot::_number_of_types;68writer.write_count(nof_root_types);69for (u4 i = 0; i < nof_root_types; ++i) {70writer.write_key(i);71writer.write(OldObjectRoot::type_description((OldObjectRoot::Type)i));72}73}74};7576class CheckpointInstall {77private:78const JfrCheckpointBlobHandle& _cp;79public:80CheckpointInstall(const JfrCheckpointBlobHandle& cp) : _cp(cp) {}81void sample_do(ObjectSample* sample) {82assert(sample != NULL, "invariant");83if (!sample->is_dead()) {84sample->set_klass_checkpoint(_cp);85}86}87};8889class CheckpointWrite {90private:91JfrCheckpointWriter& _writer;92const jlong _last_sweep;93public:94CheckpointWrite(JfrCheckpointWriter& writer, jlong last_sweep) : _writer(writer), _last_sweep(last_sweep) {}95void sample_do(ObjectSample* sample) {96assert(sample != NULL, "invariant");97if (sample->is_alive_and_older_than(_last_sweep)) {98if (sample->has_thread_checkpoint()) {99const JfrCheckpointBlobHandle& thread_cp = sample->thread_checkpoint();100thread_cp->exclusive_write(_writer);101}102if (sample->has_klass_checkpoint()) {103const JfrCheckpointBlobHandle& klass_cp = sample->klass_checkpoint();104klass_cp->exclusive_write(_writer);105}106}107}108};109110class CheckpointStateReset {111private:112const jlong _last_sweep;113public:114CheckpointStateReset(jlong last_sweep) : _last_sweep(last_sweep) {}115void sample_do(ObjectSample* sample) {116assert(sample != NULL, "invariant");117if (sample->is_alive_and_older_than(_last_sweep)) {118if (sample->has_thread_checkpoint()) {119const JfrCheckpointBlobHandle& thread_cp = sample->thread_checkpoint();120thread_cp->reset_write_state();121}122if (sample->has_klass_checkpoint()) {123const JfrCheckpointBlobHandle& klass_cp = sample->klass_checkpoint();124klass_cp->reset_write_state();125}126}127}128};129130class StackTraceWrite {131private:132JfrStackTraceRepository& _stack_trace_repo;133JfrCheckpointWriter& _writer;134int _count;135public:136StackTraceWrite(JfrStackTraceRepository& stack_trace_repo, JfrCheckpointWriter& writer) :137_stack_trace_repo(stack_trace_repo), _writer(writer), _count(0) {138JfrStacktrace_lock->lock();139}140~StackTraceWrite() {141assert(JfrStacktrace_lock->owned_by_self(), "invariant");142JfrStacktrace_lock->unlock();143}144145void sample_do(ObjectSample* sample) {146assert(sample != NULL, "invariant");147if (!sample->is_dead()) {148if (sample->has_stack_trace()) {149JfrTraceId::use(sample->klass(), true);150_stack_trace_repo.write(_writer, sample->stack_trace_id(), sample->stack_trace_hash());151++_count;152}153}154}155156int count() const {157return _count;158}159};160161class SampleMark {162private:163ObjectSampleMarker& _marker;164jlong _last_sweep;165int _count;166public:167SampleMark(ObjectSampleMarker& marker, jlong last_sweep) : _marker(marker),168_last_sweep(last_sweep),169_count(0) {}170void sample_do(ObjectSample* sample) {171assert(sample != NULL, "invariant");172if (sample->is_alive_and_older_than(_last_sweep)) {173_marker.mark(sample->object());174++_count;175}176}177178int count() const {179return _count;180}181};182183void ObjectSampleCheckpoint::install(JfrCheckpointWriter& writer, bool class_unload, bool type_set) {184if (!writer.has_data()) {185return;186}187188assert(writer.has_data(), "invariant");189const JfrCheckpointBlobHandle h_cp = writer.checkpoint_blob();190CheckpointInstall install(h_cp);191192// Class unload implies a safepoint.193// Not class unload implies the object sampler is locked, because it was claimed exclusively earlier.194// Therefore: direct access the object sampler instance is safe.195ObjectSampler* const object_sampler = ObjectSampler::sampler();196assert(object_sampler != NULL, "invariant");197198ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());199const ObjectSample* const last_resolved = object_sampler->last_resolved();200201// install only to new samples since last resolved checkpoint202if (last != last_resolved) {203do_samples(last, last_resolved, install);204if (class_unload) {205return;206}207if (type_set) {208object_sampler->set_last_resolved(last);209}210}211}212213void ObjectSampleCheckpoint::write(ObjectSampler* sampler, EdgeStore* edge_store, bool emit_all, Thread* thread) {214assert(sampler != NULL, "invariant");215assert(edge_store != NULL, "invariant");216assert(thread != NULL, "invariant");217218static bool types_registered = false;219if (!types_registered) {220JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTSYSTEM, false, true, new RootSystemType());221JfrSerializer::register_serializer(TYPE_OLDOBJECTROOTTYPE, false, true, new RootType());222types_registered = true;223}224225const jlong last_sweep = emit_all ? max_jlong : sampler->last_sweep().value();226ObjectSample* const last = const_cast<ObjectSample*>(sampler->last());227{228JfrCheckpointWriter writer(false, false, thread);229CheckpointWrite checkpoint_write(writer, last_sweep);230do_samples(last, NULL, checkpoint_write);231}232233CheckpointStateReset state_reset(last_sweep);234do_samples(last, NULL, state_reset);235236if (!edge_store->is_empty()) {237// java object and chain representations238JfrCheckpointWriter writer(false, true, thread);239ObjectSampleWriter osw(writer, edge_store);240edge_store->iterate(osw);241}242}243244int ObjectSampleCheckpoint::mark(ObjectSampler* object_sampler, ObjectSampleMarker& marker, bool emit_all) {245assert(object_sampler != NULL, "invariant");246ObjectSample* const last = const_cast<ObjectSample*>(object_sampler->last());247if (last == NULL) {248return 0;249}250const jlong last_sweep = emit_all ? max_jlong : object_sampler->last_sweep().value();251SampleMark mark(marker, last_sweep);252do_samples(last, NULL, mark);253return mark.count();254}255256WriteObjectSampleStacktrace::WriteObjectSampleStacktrace(ObjectSampler* sampler, JfrStackTraceRepository& repo) :257_sampler(sampler), _stack_trace_repo(repo) {}258259bool WriteObjectSampleStacktrace::process() {260assert(LeakProfiler::is_running(), "invariant");261assert(_sampler != NULL, "invariant");262263ObjectSample* const last = const_cast<ObjectSample*>(_sampler->last());264const ObjectSample* const last_resolved = _sampler->last_resolved();265if (last == last_resolved) {266return true;267}268269JfrCheckpointWriter writer(false, true, Thread::current());270const JfrCheckpointContext ctx = writer.context();271272writer.write_type(TYPE_STACKTRACE);273const jlong count_offset = writer.reserve(sizeof(u4));274275int count = 0;276{277StackTraceWrite stack_trace_write(_stack_trace_repo, writer); // JfrStacktrace_lock278do_samples(last, last_resolved, stack_trace_write);279count = stack_trace_write.count();280}281if (count == 0) {282writer.set_context(ctx);283return true;284}285assert(count > 0, "invariant");286writer.write_count((u4)count, count_offset);287JfrStackTraceRepository::write_metadata(writer);288289// install the stacktrace checkpoint information to the candidates290ObjectSampleCheckpoint::install(writer, false, false);291return true;292}293294295