Path: blob/master/src/hotspot/share/jfr/leakprofiler/checkpoint/rootResolver.cpp
41155 views
/*1* Copyright (c) 2014, 2021, 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 "classfile/classLoaderDataGraph.hpp"26#include "classfile/stringTable.hpp"27#include "gc/shared/oopStorage.inline.hpp"28#include "gc/shared/oopStorageSet.hpp"29#include "gc/shared/strongRootsScope.hpp"30#include "jfr/leakprofiler/utilities/unifiedOopRef.inline.hpp"31#include "jfr/leakprofiler/checkpoint/rootResolver.hpp"32#include "jfr/utilities/jfrThreadIterator.hpp"33#include "memory/iterator.hpp"34#include "prims/jvmtiDeferredUpdates.hpp"35#include "oops/klass.hpp"36#include "oops/oop.hpp"37#include "prims/jvmtiThreadState.hpp"38#include "runtime/frame.inline.hpp"39#include "runtime/jniHandles.hpp"40#include "runtime/mutexLocker.hpp"41#include "runtime/stackFrameStream.inline.hpp"42#include "runtime/vframe_hp.hpp"43#include "services/management.hpp"44#include "utilities/enumIterator.hpp"45#include "utilities/growableArray.hpp"4647class ReferenceLocateClosure : public OopClosure {48protected:49RootCallback& _callback;50RootCallbackInfo _info;51bool _complete;5253void do_oop_shared(UnifiedOopRef ref);5455public:56ReferenceLocateClosure(RootCallback& callback,57OldObjectRoot::System system,58OldObjectRoot::Type type,59const void* context) : _callback(callback),60_info(),61_complete(false) {62_info._high = NULL;63_info._low = NULL;64_info._system = system;65_info._type = type;66_info._context = context;67}6869virtual void do_oop(oop* ref);70virtual void do_oop(narrowOop* ref);7172bool complete() const {73return _complete;74}75};7677void ReferenceLocateClosure::do_oop_shared(UnifiedOopRef ref) {78assert(!ref.is_null(), "invariant");79if (!_complete) {80_info._high = ref.addr<address>();81_complete = _callback.process(_info);82}83}8485void ReferenceLocateClosure::do_oop(oop* ref) {86do_oop_shared(UnifiedOopRef::encode_in_native(ref));87}8889void ReferenceLocateClosure::do_oop(narrowOop* ref) {90do_oop_shared(UnifiedOopRef::encode_in_native(ref));91}9293class ReferenceToRootClosure : public StackObj {94private:95RootCallback& _callback;96RootCallbackInfo _info;97bool _complete;9899bool do_cldg_roots();100bool do_oop_storage_roots();101bool do_string_table_roots();102103bool do_roots();104105public:106ReferenceToRootClosure(RootCallback& callback) : _callback(callback),107_info(),108_complete(false) {109_info._high = NULL;110_info._low = NULL;111_info._context = NULL;112_info._system = OldObjectRoot::_system_undetermined;113_info._type = OldObjectRoot::_type_undetermined;114115assert_locked_or_safepoint(Threads_lock);116do_roots();117}118119bool complete() const {120return _complete;121}122};123124bool ReferenceToRootClosure::do_cldg_roots() {125assert(!complete(), "invariant");126ReferenceLocateClosure rlc(_callback, OldObjectRoot::_class_loader_data, OldObjectRoot::_type_undetermined, NULL);127CLDToOopClosure cldt_closure(&rlc, ClassLoaderData::_claim_none);128ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);129return rlc.complete();130}131132bool ReferenceToRootClosure::do_oop_storage_roots() {133using Range = EnumRange<OopStorageSet::StrongId>;134for (auto id : Range()) {135assert(!complete(), "invariant");136OopStorage* oop_storage = OopStorageSet::storage(id);137OldObjectRoot::Type type = JNIHandles::is_global_storage(oop_storage) ?138OldObjectRoot::_global_jni_handle :139OldObjectRoot::_global_oop_handle;140OldObjectRoot::System system = OldObjectRoot::System(OldObjectRoot::_strong_oop_storage_set_first + Range().index(id));141ReferenceLocateClosure rlc(_callback, system, type, NULL);142oop_storage->oops_do(&rlc);143if (rlc.complete()) {144return true;145}146}147return false;148}149150bool ReferenceToRootClosure::do_roots() {151assert(!complete(), "invariant");152assert(OldObjectRoot::_system_undetermined == _info._system, "invariant");153assert(OldObjectRoot::_type_undetermined == _info._type, "invariant");154155if (do_cldg_roots()) {156_complete = true;157return true;158}159160if (do_oop_storage_roots()) {161_complete = true;162return true;163}164165return false;166}167168class ReferenceToThreadRootClosure : public StackObj {169private:170RootCallback& _callback;171bool _complete;172173bool do_java_threads_oops(JavaThread* jt);174bool do_thread_roots(JavaThread* jt);175bool do_thread_stack_fast(JavaThread* jt);176bool do_thread_stack_detailed(JavaThread* jt);177bool do_thread_jni_handles(JavaThread* jt);178bool do_thread_handle_area(JavaThread* jt);179180public:181ReferenceToThreadRootClosure(RootCallback& callback) :_callback(callback), _complete(false) {182assert_locked_or_safepoint(Threads_lock);183JfrJavaThreadIterator iter;184while (iter.has_next()) {185if (do_thread_roots(iter.next())) {186return;187}188}189}190191bool complete() const {192return _complete;193}194};195196bool ReferenceToThreadRootClosure::do_thread_handle_area(JavaThread* jt) {197assert(jt != NULL, "invariant");198assert(!complete(), "invariant");199ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_handle_area, jt);200jt->handle_area()->oops_do(&rcl);201return rcl.complete();202}203204bool ReferenceToThreadRootClosure::do_thread_jni_handles(JavaThread* jt) {205assert(jt != NULL, "invariant");206assert(!complete(), "invariant");207208ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_local_jni_handle, jt);209jt->active_handles()->oops_do(&rcl);210return rcl.complete();211}212213bool ReferenceToThreadRootClosure::do_thread_stack_fast(JavaThread* jt) {214assert(jt != NULL, "invariant");215assert(!complete(), "invariant");216217if (_callback.entries() == 0) {218_complete = true;219return true;220}221222RootCallbackInfo info;223info._high = NULL;224info._low = NULL;225info._context = jt;226info._system = OldObjectRoot::_threads;227info._type = OldObjectRoot::_stack_variable;228229for (int i = 0; i < _callback.entries(); ++i) {230const address adr = _callback.at(i).addr<address>();231if (jt->is_in_usable_stack(adr)) {232info._high = adr;233_complete = _callback.process(info);234if (_complete) {235return true;236}237}238}239assert(!complete(), "invariant");240return false;241}242243bool ReferenceToThreadRootClosure::do_thread_stack_detailed(JavaThread* jt) {244assert(jt != NULL, "invariant");245assert(!complete(), "invariant");246247ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_stack_variable, jt);248249if (jt->has_last_Java_frame()) {250// Traverse the monitor chunks251MonitorChunk* chunk = jt->monitor_chunks();252for (; chunk != NULL; chunk = chunk->next()) {253chunk->oops_do(&rcl);254}255256if (rcl.complete()) {257return true;258}259260// Traverse the execution stack261for (StackFrameStream fst(jt, true /* update */, true /* process_frames */); !fst.is_done(); fst.next()) {262fst.current()->oops_do(&rcl, NULL, fst.register_map());263}264265} // last java frame266267if (rcl.complete()) {268return true;269}270271GrowableArray<jvmtiDeferredLocalVariableSet*>* const list = JvmtiDeferredUpdates::deferred_locals(jt);272if (list != NULL) {273for (int i = 0; i < list->length(); i++) {274list->at(i)->oops_do(&rcl);275}276}277278if (rcl.complete()) {279return true;280}281282// Traverse instance variables at the end since the GC may be moving things283// around using this function284/*285* // can't reach these oop* from the outside286f->do_oop((oop*) &_vm_result);287f->do_oop((oop*) &_exception_oop);288f->do_oop((oop*) &_pending_async_exception);289*/290291JvmtiThreadState* const jvmti_thread_state = jt->jvmti_thread_state();292if (jvmti_thread_state != NULL) {293jvmti_thread_state->oops_do(&rcl, NULL);294}295296return rcl.complete();297}298299bool ReferenceToThreadRootClosure::do_java_threads_oops(JavaThread* jt) {300assert(jt != NULL, "invariant");301assert(!complete(), "invariant");302303ReferenceLocateClosure rcl(_callback, OldObjectRoot::_threads, OldObjectRoot::_global_jni_handle, jt);304jt->oops_do(&rcl, NULL);305return rcl.complete();306}307308bool ReferenceToThreadRootClosure::do_thread_roots(JavaThread* jt) {309assert(jt != NULL, "invariant");310311if (do_thread_stack_fast(jt)) {312_complete = true;313return true;314}315316if (do_thread_jni_handles(jt)) {317_complete = true;318return true;319}320321if (do_thread_handle_area(jt)) {322_complete = true;323return true;324}325326if (do_thread_stack_detailed(jt)) {327_complete = true;328return true;329}330331return false;332}333334class RootResolverMarkScope : public MarkScope {335};336337void RootResolver::resolve(RootCallback& callback) {338RootResolverMarkScope mark_scope;339340// thread local roots341ReferenceToThreadRootClosure rtrc(callback);342if (rtrc.complete()) {343return;344}345// system global roots346ReferenceToRootClosure rrc(callback);347}348349350