Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8306767: Concurrent repacking of extra data in MethodData is potentially unsafe #16840

Closed
wants to merge 27 commits into from
Closed
Changes from 21 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
04e6522
8306767
eme64 Nov 28, 2023
9336c4f
add locks for jvmci calls to allocate_bci_to_data
eme64 Nov 28, 2023
5b819f1
adding more verification and more locking, WIP
eme64 Nov 30, 2023
54f2c49
more locking, still fails tho - WIP
eme64 Nov 30, 2023
83cda01
manual merge with master after JDK-8267532
eme64 Nov 30, 2023
c126f34
make lock not safepointing
eme64 Dec 5, 2023
465c381
missed a case where I need to lock
eme64 Dec 5, 2023
e0fc8d1
move a lock to earlier, to have order right with tty lock
eme64 Dec 5, 2023
70327d3
fix conflicts with tty lock
eme64 Dec 20, 2023
30e5aeb
remove more locking
eme64 Dec 20, 2023
0ec5371
removed some ttyl cases, which collided with the extra_data_lock
eme64 Dec 21, 2023
2bda9d7
Merge branch 'master' into JDK-8306767
eme64 Jan 3, 2024
68ca3bd
2024 copyright
eme64 Jan 3, 2024
1c19953
remove override marking, so I don not have to add it everywhere becau…
eme64 Jan 3, 2024
6647e11
jfr case with missing lock
eme64 Jan 3, 2024
b0ff5d1
refactor MethodData::bci_to_extra_data - remove redundant code
eme64 Jan 4, 2024
e1e9174
fixed typo
eme64 Jan 4, 2024
825a3d8
change patch to deoptimization.cpp case brought up by Roland
eme64 Jan 15, 2024
671ead2
Update src/hotspot/share/runtime/deoptimization.cpp
eme64 Jan 15, 2024
78a2cdb
NoSafepointMutexLocker
eme64 Jan 15, 2024
4dbfe9a
improved comment for Roland
eme64 Jan 17, 2024
f8a81cd
remove NoSafepointMutexLocker
eme64 Jan 18, 2024
c408f22
rm pause_no_safepoints
eme64 Jan 18, 2024
3dad293
add one nsv again
eme64 Jan 18, 2024
5f471ff
Merge branch 'master' into JDK-8306767
eme64 Jan 22, 2024
ff581b0
cleanup unnecessary changes
eme64 Jan 22, 2024
96af505
moving code for Coleen
eme64 Jan 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 29 additions & 9 deletions src/hotspot/share/ci/ciMethodData.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -82,13 +82,24 @@ class PrepareExtraDataClosure : public CleanExtraDataClosure {
return _safepoint_tracker.safepoint_state_changed();
}

bool finish() {
bool finish(NoSafepointVerifier* no_safepoint) {
if (_uncached_methods.length() == 0) {
// Preparation finished iff all Methods* were already cached.
return true;
}
// Holding locks through safepoints is bad practice.
MutexUnlocker mu(_mdo->extra_data_lock());
// We are currently holding the extra_data_lock and ensuring
// no safepoint breaks the lock.
_mdo->check_extra_data_locked();

// We now want to cache some method data. This could cause a safepoint.
// We temporarily release the lock and allow safepoints, and revert that
// at the end of the scope. This is safe, since we currently do not hold
// any extra_method_data: finish is called only after clean_extra_data,
// and the outer scope that first aquired the lock should not hold any
// extra_method_data while cleaning is performed, as the offsets can change.
MutexUnlocker mu(_mdo->extra_data_lock(), Mutex::_no_safepoint_check_flag);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this safe?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only do this in the finish method, where we hold no reference to any profiled-data anymore. We only really need to hold the lock during clean_extra_data and is_live. But after those are done, we can quickly release the lock so that we can call get_method.
Does that make sense to you? I'm not super happy with the general pattern here... I basically kept the old pattern.

I wonder, maybe there is a way to move the scope of the lock, such that we only need to lock inside of clean_extra_data, and do not hold it before we enter clean_extra_data. Do you think that would be preferable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rwestrel I still believe this is safe. But maybe also ugly.

I looked into making the locking more fine-grained, so that we could avoid unlocking the lock temporarily.
The biggest problem is in ciMethodData::load_remaining_extra_data. Here we first (iteratively) clean, and then assume that we still hold the lock when we copy it for the ciMethodData. Hence, it seems the lock has to be held at this outer scope, but then temporarily unlocked to allow calls to get_method in PrepareExtraDataClosure::finish.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatives to make it prettier:
Make prepare_metadata lock, and pass out an object that holds that lock, i.e. widen the scope of the MutexLocker. Maybe this can be done with return-value-optimization? But I'm not sure this is a great idea. Another idea @chhagedorn and I thought about was having some Locker object that you can call lock/unlock on, repeatedly. But once the Locker goes out of scope, it checks if it is in the locked state, and only unlocks then. Or maybe it asserts that it is in the locked state, and then unlocks.

Because essencially we need to allow the retry-logic to unlock in between tries. But we also still need to access the uncached_methods array that is filled inside the locked region.

I'm not sure such a refactoring is worth it. Let me know what you think @rwestrel

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that logic existed, I think you can leave it as is but a comment that explains why it is safe would be useful.

PauseNoSafepointVerifier pause_no_safepoints(no_safepoint);

for (int i = 0; i < _uncached_methods.length(); ++i) {
if (has_safepointed()) {
// The metadata in the growable array might contain stale
@@ -104,14 +115,14 @@ class PrepareExtraDataClosure : public CleanExtraDataClosure {
}
};

void ciMethodData::prepare_metadata() {
void ciMethodData::prepare_metadata(NoSafepointVerifier* no_safepoint) {
MethodData* mdo = get_MethodData();

for (;;) {
ResourceMark rm;
PrepareExtraDataClosure cl(mdo);
mdo->clean_extra_data(&cl);
if (cl.finish()) {
if (cl.finish(no_safepoint)) {
// When encountering uncached metadata, the Compile_lock might be
// acquired when creating ciMetadata handles, causing safepoints
// which requires a new round of preparation to clean out potentially
@@ -123,12 +134,15 @@ void ciMethodData::prepare_metadata() {

void ciMethodData::load_remaining_extra_data() {
MethodData* mdo = get_MethodData();
MutexLocker ml(mdo->extra_data_lock());

// Lock to read ProfileData, and ensure lock is not unintentionally broken by a safepoint
MutexLocker ml(mdo->extra_data_lock(), Mutex::_no_safepoint_check_flag);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there anyway to have MutexLocker take care of verifying that the there's no safepoint? It would be nice to replace:

MutexLocker ml();
NoSafepointVerifier no_safepoint;

by:

MutexLocker ml();

only.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fisk @tkrodriguez what do you suggest for that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I create a wrapper object for it? Maybe a MutexLockerAndNoSafepointVerifier? Would I place that simply in methodData.hpp? Or make it available more widely?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rwestrel I introduced a NoSafepointMutexLocker, which is composed of both a ConditionalMutexLocker and a NoSafepointVerifier.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But in this specific instance I keep them separate, because I need to pass the NoSafepointVerifier down, so that I can pass it to the PauseNoSafepointVerifier.

NoSafepointVerifier no_safepoint;

// Deferred metadata cleaning due to concurrent class unloading.
prepare_metadata();
prepare_metadata(&no_safepoint);
// After metadata preparation, there is no stale metadata,
// and no safepoints can introduce more stale metadata.
NoSafepointVerifier no_safepoint;

assert((mdo->data_size() == _data_size) && (mdo->extra_data_size() == _extra_data_size), "sanity, unchanged");
assert(extra_data_base() == (DataLayout*)((address) _data + _data_size), "sanity");
@@ -562,6 +576,9 @@ void ciMethodData::set_argument_type(int bci, int i, ciKlass* k) {
VM_ENTRY_MARK;
MethodData* mdo = get_MethodData();
if (mdo != nullptr) {
// Lock to read ProfileData, and ensure lock is not broken by a safepoint
NoSafepointMutexLocker ml(mdo->extra_data_lock(), Mutex::_no_safepoint_check_flag);

ProfileData* data = mdo->bci_to_data(bci);
if (data != nullptr) {
if (data->is_CallTypeData()) {
@@ -586,6 +603,9 @@ void ciMethodData::set_return_type(int bci, ciKlass* k) {
VM_ENTRY_MARK;
MethodData* mdo = get_MethodData();
if (mdo != nullptr) {
// Lock to read ProfileData, and ensure lock is not broken by a safepoint
NoSafepointMutexLocker ml(mdo->extra_data_lock(), Mutex::_no_safepoint_check_flag);

ProfileData* data = mdo->bci_to_data(bci);
if (data != nullptr) {
if (data->is_CallTypeData()) {
4 changes: 2 additions & 2 deletions src/hotspot/share/ci/ciMethodData.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -461,7 +461,7 @@ class ciMethodData : public ciMetadata {

ciArgInfoData *arg_info() const;

void prepare_metadata();
void prepare_metadata(NoSafepointVerifier* no_safepoint);
void load_remaining_extra_data();
ciProfileData* bci_to_extra_data(int bci, ciMethod* m, bool& two_free_slots);

6 changes: 3 additions & 3 deletions src/hotspot/share/code/codeBlob.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -236,9 +236,9 @@ const ImmutableOopMap* CodeBlob::oop_map_for_return_address(address return_addre
return _oop_maps->find_map_at_offset((intptr_t) return_address - (intptr_t) code_begin());
}

void CodeBlob::print_code() {
void CodeBlob::print_code_on(outputStream* st) {
ResourceMark m;
Disassembler::decode(this, tty);
Disassembler::decode(this, st);
}

//----------------------------------------------------------------------------------------------------
4 changes: 2 additions & 2 deletions src/hotspot/share/code/codeBlob.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -240,7 +240,7 @@ class CodeBlob {
virtual void print_on(outputStream* st) const;
virtual void print_value_on(outputStream* st) const;
void dump_for_addr(address addr, outputStream* st, bool verbose) const;
void print_code();
void print_code_on(outputStream* st);

// Print to stream, any comments associated with offset.
virtual void print_block_comment(outputStream* stream, address block_begin) const {
17 changes: 10 additions & 7 deletions src/hotspot/share/code/compiledMethod.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -687,12 +687,15 @@ address CompiledMethod::continuation_for_implicit_exception(address pc, bool for
ResourceMark rm(thread);
CodeBlob* cb = CodeCache::find_blob(pc);
assert(cb != nullptr && cb == this, "");
ttyLocker ttyl;
tty->print_cr("implicit exception happened at " INTPTR_FORMAT, p2i(pc));
print();
method()->print_codes();
print_code();
print_pcs();

// Keep tty output consistent. To avoid ttyLocker, we buffer in stream, and print all at once.
stringStream ss;
ss.print_cr("implicit exception happened at " INTPTR_FORMAT, p2i(pc));
print_on(&ss);
method()->print_codes_on(&ss);
print_code_on(&ss);
print_pcs_on(&ss);
tty->print("%s", ss.as_string()); // print all at once
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like these ttyLocker changes should be checked in as a different cleanup, ie removing ttyLocker is a really good thing. Can you make these changes a separate patch?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I filed the RFE:
JDK-8324129 C2: Remove some ttyLocker usages in preparation for JDK-8306767
#17486

}
#endif
if (cont_offset == 0) {
4 changes: 2 additions & 2 deletions src/hotspot/share/code/compiledMethod.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -227,7 +227,7 @@ class CompiledMethod : public CodeBlob {
virtual bool is_osr_method() const = 0;
virtual int osr_entry_bci() const = 0;
Method* method() const { return _method; }
virtual void print_pcs() = 0;
virtual void print_pcs_on(outputStream* st) = 0;
bool is_native_method() const { return _method != nullptr && _method->is_native(); }
bool is_java_method() const { return _method != nullptr && !_method->is_native(); }

4 changes: 2 additions & 2 deletions src/hotspot/share/code/nmethod.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1021,7 +1021,7 @@ void nmethod::print_nmethod(bool printmethod) {
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
print_metadata(tty);
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
print_pcs();
print_pcs_on(tty);
tty->print_cr("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");
if (oop_maps() != nullptr) {
tty->print("oop maps:"); // oop_maps()->print_on(tty) outputs a cr() at the beginning
6 changes: 2 additions & 4 deletions src/hotspot/share/code/nmethod.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -621,7 +621,6 @@ class nmethod : public CompiledMethod {
#if defined(SUPPORT_DATA_STRUCTS)
// print output in opt build for disassembler library
void print_relocations() PRODUCT_RETURN;
void print_pcs() { print_pcs_on(tty); }
void print_pcs_on(outputStream* st);
void print_scopes() { print_scopes_on(tty); }
void print_scopes_on(outputStream* st) PRODUCT_RETURN;
@@ -635,8 +634,7 @@ class nmethod : public CompiledMethod {
void print_oops(outputStream* st); // oops from the underlying CodeBlob.
void print_metadata(outputStream* st); // metadata in metadata pool.
#else
// void print_pcs() PRODUCT_RETURN;
void print_pcs() { return; }
void print_pcs_on(outputStream* st) { return; }
#endif

void print_calls(outputStream* st) PRODUCT_RETURN;
14 changes: 11 additions & 3 deletions src/hotspot/share/interpreter/bytecodeTracer.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -41,6 +41,7 @@
#include "runtime/handles.inline.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/osThread.hpp"
#include "runtime/safepointVerifiers.hpp"
#include "runtime/timer.hpp"
#include "utilities/align.hpp"

@@ -192,10 +193,13 @@ void BytecodeTracer::print_method_codes(const methodHandle& method, int from, in
BytecodeStream s(method);
s.set_interval(from, to);

ttyLocker ttyl; // keep the following output coherent
// Keep output to st coherent: collect all lines and print at once.
ResourceMark rm;
stringStream ss;
while (s.next() >= 0) {
method_printer.trace(method, s.bcp(), st);
method_printer.trace(method, s.bcp(), &ss);
}
st->print("%s", ss.as_string());
}

void BytecodePrinter::print_constant(int cp_index, outputStream* st) {
@@ -589,6 +593,10 @@ void BytecodePrinter::print_attributes(int bci, outputStream* st) {
void BytecodePrinter::bytecode_epilog(int bci, outputStream* st) {
MethodData* mdo = method()->method_data();
if (mdo != nullptr) {

// Lock to read ProfileData, and ensure lock is not broken by a safepoint
NoSafepointMutexLocker ml(mdo->extra_data_lock(), Mutex::_no_safepoint_check_flag);

ProfileData* data = mdo->bci_to_data(bci);
if (data != nullptr) {
st->print(" %d ", mdo->dp_to_di(data->dp()));
9 changes: 7 additions & 2 deletions src/hotspot/share/interpreter/interpreterRuntime.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -547,7 +547,12 @@ JRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea
#if INCLUDE_JVMCI
if (EnableJVMCI && h_method->method_data() != nullptr) {
ResourceMark rm(current);
ProfileData* pdata = h_method->method_data()->allocate_bci_to_data(current_bci, nullptr);
MethodData* mdo = h_method->method_data();

// Lock to read ProfileData, and ensure lock is not broken by a safepoint
NoSafepointMutexLocker ml(mdo->extra_data_lock(), Mutex::_no_safepoint_check_flag);

ProfileData* pdata = mdo->allocate_bci_to_data(current_bci, nullptr);
if (pdata != nullptr && pdata->is_BitData()) {
BitData* bit_data = (BitData*) pdata;
bit_data->set_exception_seen();
4 changes: 4 additions & 0 deletions src/hotspot/share/jfr/support/jfrMethodData.cpp
Original file line number Diff line number Diff line change
@@ -56,6 +56,10 @@ static bool mark_mdo(Method* method, int bci, JavaThread* jt) {
assert(jt != nullptr, "invariant");
MethodData* const mdo = get_mdo(method, jt);
assert(mdo != nullptr, "invariant");

// Lock to access ProfileData, and ensure lock is not broken by a safepoint
NoSafepointMutexLocker ml(mdo->extra_data_lock(), Mutex::_no_safepoint_check_flag);

// Get the datalayout for the invocation bci.
BitData* const bit_data = get_bit_data(mdo, bci);
// Returns true if this callsite is not yet linked and
7 changes: 5 additions & 2 deletions src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1889,7 +1889,10 @@ C2V_END

C2V_VMENTRY_0(jint, methodDataExceptionSeen, (JNIEnv* env, jobject, jlong method_data_pointer, jint bci))
MethodData* mdo = (MethodData*) method_data_pointer;
MutexLocker mu(mdo->extra_data_lock());

// Lock to read ProfileData, and ensure lock is not broken by a safepoint
NoSafepointMutexLocker mu(mdo->extra_data_lock(), Mutex::_no_safepoint_check_flag);

DataLayout* data = mdo->extra_data_base();
DataLayout* end = mdo->args_data_limit();
for (;; data = mdo->next_extra(data)) {
3 changes: 1 addition & 2 deletions src/hotspot/share/oops/instanceKlass.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -2531,7 +2531,6 @@ void InstanceKlass::clean_method_data() {
for (int m = 0; m < methods()->length(); m++) {
MethodData* mdo = methods()->at(m)->method_data();
if (mdo != nullptr) {
ConditionalMutexLocker ml(mdo->extra_data_lock(), !SafepointSynchronize::is_at_safepoint());
mdo->clean_method_data(/*always_clean*/false);
}
}
30 changes: 15 additions & 15 deletions src/hotspot/share/oops/method.cpp
Original file line number Diff line number Diff line change
@@ -540,38 +540,38 @@ bool Method::was_executed_more_than(int n) {
}
}

void Method::print_invocation_count() {
void Method::print_invocation_count(outputStream* st) {
//---< compose+print method return type, klass, name, and signature >---
if (is_static()) tty->print("static ");
if (is_final()) tty->print("final ");
if (is_synchronized()) tty->print("synchronized ");
if (is_native()) tty->print("native ");
tty->print("%s::", method_holder()->external_name());
name()->print_symbol_on(tty);
signature()->print_symbol_on(tty);
if (is_static()) { st->print("static "); }
if (is_final()) { st->print("final "); }
if (is_synchronized()) { st->print("synchronized "); }
if (is_native()) { st->print("native "); }
st->print("%s::", method_holder()->external_name());
name()->print_symbol_on(st);
signature()->print_symbol_on(st);

if (WizardMode) {
// dump the size of the byte codes
tty->print(" {%d}", code_size());
st->print(" {%d}", code_size());
}
tty->cr();
st->cr();

// Counting based on signed int counters tends to overflow with
// longer-running workloads on fast machines. The counters under
// consideration here, however, are limited in range by counting
// logic. See InvocationCounter:count_limit for example.
// No "overflow precautions" need to be implemented here.
tty->print_cr (" interpreter_invocation_count: " INT32_FORMAT_W(11), interpreter_invocation_count());
tty->print_cr (" invocation_counter: " INT32_FORMAT_W(11), invocation_count());
tty->print_cr (" backedge_counter: " INT32_FORMAT_W(11), backedge_count());
st->print_cr (" interpreter_invocation_count: " INT32_FORMAT_W(11), interpreter_invocation_count());
st->print_cr (" invocation_counter: " INT32_FORMAT_W(11), invocation_count());
st->print_cr (" backedge_counter: " INT32_FORMAT_W(11), backedge_count());

if (method_data() != nullptr) {
tty->print_cr (" decompile_count: " UINT32_FORMAT_W(11), method_data()->decompile_count());
st->print_cr (" decompile_count: " UINT32_FORMAT_W(11), method_data()->decompile_count());
}

#ifndef PRODUCT
if (CountCompiledCalls) {
tty->print_cr (" compiled_invocation_count: " INT64_FORMAT_W(11), compiled_invocation_count());
st->print_cr (" compiled_invocation_count: " INT64_FORMAT_W(11), compiled_invocation_count());
}
#endif
}
Loading