/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "classfile/classLoader.hpp"
#include "code/vtableStubs.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "interpreter/interpreter.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/universe.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/oop.inline2.hpp"
#include "oops/symbol.hpp"
#include "runtime/deoptimization.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/vframe.hpp"
#include "utilities/macros.hpp"
// Static fields of FlatProfiler
// Space for the ProfilerNodes
// ProfilerNode pointer table
initialize();
engaged = false;
}
ThreadProfiler::~ThreadProfiler() {
area_bottom = NULL;
area_limit = NULL;
}
// Statics for ThreadProfiler
return value % table_size;
}
_r = r;
assert(((r > ThreadProfilerMark::noRegion) && (r < ThreadProfilerMark::maxRegion)), "ThreadProfilerMark::Region out of bounds");
pp->region_flag[r] = true;
}
}
}
}
}
// Random other statics
// Used for detailed profiling of nmethods.
private:
static int* counters;
enum {
};
static int size() {
}
public:
}
static void init();
static void print();
};
int s = size();
}
}
}
}
}
tty->print_cr("Printing compiled methods with PC buckets having more than %d ticks", ProfilerPCTickThreshold);
int s;
{
s = size();
}
if (count > ProfilerPCTickThreshold) {
}
}
}
for (int i = 0; i < candidates->length(); i++) {
}
}
if (cb->is_nmethod()) {
}
} else {
}
}
public:
int ticks_in_code;
int ticks_in_native;
int total() const {
return (ticks_in_code + ticks_in_native);
}
ticks_in_code += a->ticks_in_code;
ticks_in_native += a->ticks_in_native;
}
switch(where) {
case tp_code: ticks_in_code++; break;
case tp_native: ticks_in_native++; break;
}
}
}
}
};
class ProfilerNode {
private:
public:
public:
void operator delete(void* p);
ProfilerNode() {
}
virtual ~ProfilerNode() {
if (_next)
delete _next;
}
virtual bool is_interpreted() const { return false; }
virtual bool is_compiled() const { return false; }
virtual bool is_stub() const { return false; }
virtual bool is_runtime_stub() const{ return false; }
virtual void oops_do(OopClosure* f) = 0;
virtual bool adapter_match() const { return false; }
}
t->print_native(st);
}
int limit;
int i;
Symbol* k = m->klass_name();
// Print the class name with dots instead of slashes
limit = k->utf8_length();
for (i = 0 ; i < limit ; i += 1) {
char c = (char) k->byte_at(i);
if (c == '/') {
c = '.';
}
}
if (limit > 0) {
}
limit = n->utf8_length();
for (i = 0 ; i < limit ; i += 1) {
char c = (char) n->byte_at(i);
}
if (Verbose || WizardMode) {
// Disambiguate overloaded methods
// compare with methodOopDesc::print_short_name
}
}
// for hashing into the table
// The point here is to try to make something fairly unique
// out of the fields we can read without grabbing any locks
// since the method may be locked when we need the hash.
return (
method->max_locals() ^
method->size_of_parameters());
}
// for sorting
return (*b)->total_ticks() - (*a)->total_ticks();
}
};
fatal("flat profiler buffer overflow");
}
return result;
}
void ProfilerNode::operator delete(void* p){
}
private:
public:
}
bool is_interpreted() const { return true; }
return _method == m;
}
}
}
}
}
};
private:
public:
}
bool is_compiled() const { return true; }
return _method == m;
}
}
}
}
}
};
private:
const char* _symbol; // The name of the nearest VM symbol (for +ProfileVM). Points to a unique string
public:
}
bool is_stub() const { return true; }
}
}
}
}
}
if(_symbol) {
}
}
};
public:
}
bool is_compiled() const { return true; }
bool adapter_match() const { return true; }
;
}
}
}
};
private:
const char* _symbol; // The name of the nearest VM symbol when ProfileVM is on. Points to a unique string.
public:
runtimeStubNode(const CodeBlob* stub, const char* name, TickPosition where) : ProfilerNode(), _stub(stub), _symbol(name) {
}
bool is_runtime_stub() const { return true; }
}
}
;
}
}
}
if(_symbol) {
}
}
};
const char *_name;
public:
if ( cb->is_buffer_blob() )
else
}
bool is_compiled() const { return true; }
if ( cb->is_buffer_blob() )
else
}
;
}
}
}
};
private:
public:
}
}
bool is_compiled() const { return true; }
// Compute a simple hash
int h = 0;
while(*cp != '\0'){
h = (h << 1) ^ *cp;
cp++;
}
}
return h;
}
;
}
}
}
else {
}
}
};
} else {
return;
}
}
}
}
} else {
return;
}
}
}
}
} else {
return;
}
}
}
}
int index = 0;
} else {
if (node->adapter_match()) {
return;
}
}
}
}
void ThreadProfiler::runtime_stub_update(const CodeBlob* stub, const char* name, TickPosition where) {
int index = 0;
} else {
return;
}
}
}
}
int index = 0;
} else {
return;
}
}
}
}
}
// Note that we call strdup below since the symbol may be resource allocated
} else {
return;
}
}
}
}
public:
void task();
};
return;
}
if (DeoptimizationMarker::is_active()) {
return;
}
}
// Profile the VM Thread itself if needed
// This is done without getting the Threads_lock and we can go deep
// inside Safepoint, etc.
if( ProfileVM ) {
buf[0] = '\0';
// Get a snapshot of a current VMThread pc (and leave it running!)
// The call may fail if, for instance the VM thread is interrupted while
// holding the Interrupt_lock or for other reasons.
}
}
}
}
}
bool interval_expired = false;
if (ProfileIntervals &&
interval_expired = true;
}
// Try not to wait for the Threads_lock
if (Threads_lock->try_lock()) {
{ // Threads_lock scope
suspendedthreadcount = 0;
if (tp->is_Compiler_thread()) {
// Only record ticks for active compiler threads
// The compiler is active. If we need to access any of the fields
// of the compiler task we should suspend the CompilerThread first.
continue;
}
}
// First externally suspend all threads by marking each for
// external suspension - so it will stop at its next transition
// Then do a safepoint
}
}
}
Threads_lock->unlock();
}
// Suspend each thread. This call should just return
// for any threads that have already self-suspended
// Net result should be one safepoint
for (int j = 0; j < suspendedthreadcount; j++) {
if (tp) {
tp->java_suspend();
}
}
// We are responsible for resuming any thread on this list
for (int i = 0; i < suspendedthreadcount; i++) {
if (tp) {
if (interval_expired) {
}
// This is the place where we check to see if a user thread is
// blocked waiting for compilation.
if (tp->blocked_on_compilation()) {
} else {
}
}
tp->java_resume();
}
}
if (interval_expired) {
}
} else {
// Couldn't get the threads lock, just record that rather than blocking
}
}
if (ProfileVM) {
}
if (SafepointSynchronize::is_at_safepoint()) {
return;
}
}
}
void ThreadProfiler::record_interpreted_tick(JavaThread* thread, frame fr, TickPosition where, int* ticks) {
if (!FlatProfiler::full_profile()) {
return;
}
// tick came at a bad time
interpreter_ticks += 1;
return;
}
// The frame has been fully validated so we can trust the method and bci
// update byte code table
}
}
if (!FlatProfiler::full_profile()) return;
// For runtime stubs, record as native rather than as compiled
if (cb->is_runtime_stub()) {
}
if (cb->is_runtime_stub())
else
}
else {
} else {
}
}
}
extern "C" void find(int x);
// The tick happened in real code -> non VM code
if (fr.is_interpreted_frame()) {
return;
}
return;
}
return;
}
return;
}
}
// The tick happened in VM code
interval_data_ref()->inc_native();
if (fr.is_interpreted_frame()) {
return;
}
return;
}
return;
}
}
thread_ticks += 1;
// Here's another way to track global state changes.
// When the class loader starts it marks the ThreadProfiler to tell it it is in the class loader
// and we check that here.
// This is more direct, and more than one thread can be in the class loader at a time,
// but it does mean the class loader has to know about the profiler.
class_loader_ticks += 1;
return;
extra_ticks += 1;
return;
}
// Note that the WatcherThread can now stop for safepoints
SuspendRetryDelay, &debug_bits)) {
return;
}
switch (thread->thread_state()) {
case _thread_in_native:
case _thread_in_native_trans:
case _thread_in_vm:
case _thread_in_vm_trans:
if (fr.is_runtime_frame()) {
}
} else {
}
break;
// handle_special_runtime_exit_condition self-suspends threads in Java
case _thread_in_Java:
case _thread_in_Java_trans:
if (fr.is_safepoint_blob_frame()) {
}
} else {
}
break;
case _thread_blocked:
case _thread_blocked_trans:
if (fr.is_safepoint_blob_frame()) {
} else {
}
} else {
}
} else {
blocked_ticks += 1;
}
break;
case _thread_uninitialized:
case _thread_new:
// not used, included for completeness
case _thread_new_trans:
break;
default:
break;
}
return;
}
engaged = true;
}
engaged = false;
}
}
thread_ticks = 0;
blocked_ticks = 0;
compiler_ticks = 0;
interpreter_ticks = 0;
unknown_ticks_array[ut] = 0;
}
class_loader_ticks = 0;
extra_ticks = 0;
interval_data_ref()->reset();
}
if (n != NULL) {
delete n;
}
}
}
initialize();
}
{ // Bytecode table
bytecode_ticks[index] = 0;
bytecode_ticks_stub[index] = 0;
}
}
}
if (bytecode_ticks == NULL) {
}
vm_thread_profiler = new ThreadProfiler();
}
}
if (mainThread != NULL) {
// When mainThread was created, it might not have a ThreadProfiler
} else {
}
}
// This is where we would assign thread_profiler
// if we wanted only one thread_profiler for all threads.
}
if (!task) {
return;
}
delete task;
if (thread_profiler != NULL) {
} else {
}
}
}
}
if (task) {
disengage();
}
class_loader_ticks = 0;
extra_ticks = 0;
received_gc_ticks = 0;
vm_operation_ticks = 0;
compiler_ticks = 0;
deopt_ticks = 0;
interpreter_ticks = 0;
blocked_ticks = 0;
unknown_ticks = 0;
received_ticks = 0;
delivered_ticks = 0;
}
}
}
}
}
if (ticks > 0) {
}
}
return;
}
if (thread_ticks <= 0) {
return;
}
}
// compute total (sanity check)
int active =
}
if (total != thread_ticks) {
}
// print interpreted methods
bool has_interpreted_ticks = false;
int print_count = 0;
if (n->is_interpreted()) {
if (!has_interpreted_ticks) {
has_interpreted_ticks = true;
}
if (print_count++ < ProfilerNumberOfInterpretedMethods) {
}
}
}
if (has_interpreted_ticks) {
title = "Total interpreted";
} else {
title = "Total interpreted (including elided)";
}
}
// print compiled methods
bool has_compiled_ticks = false;
print_count = 0;
if (n->is_compiled()) {
if (!has_compiled_ticks) {
has_compiled_ticks = true;
}
if (print_count++ < ProfilerNumberOfCompiledMethods) {
}
}
}
if (has_compiled_ticks) {
if (print_count <= ProfilerNumberOfCompiledMethods) {
title = "Total compiled";
} else {
title = "Total compiled (including elided)";
}
}
// print stub methods
bool has_stub_ticks = false;
print_count = 0;
if (n->is_stub()) {
if (!has_stub_ticks) {
has_stub_ticks = true;
}
if (print_count++ < ProfilerNumberOfStubMethods) {
}
}
}
if (has_stub_ticks) {
if (print_count <= ProfilerNumberOfStubMethods) {
title = "Total stub";
} else {
title = "Total stub (including elided)";
}
}
// print runtime stubs
bool has_runtime_stub_ticks = false;
print_count = 0;
if (n->is_runtime_stub()) {
if (!has_runtime_stub_ticks) {
has_runtime_stub_ticks = true;
}
if (print_count++ < ProfilerNumberOfRuntimeStubNodes) {
}
}
}
if (has_runtime_stub_ticks) {
if (print_count <= ProfilerNumberOfRuntimeStubNodes) {
title = "Total runtime stubs";
} else {
title = "Total runtime stubs (including elided)";
}
}
if (blocked_ticks + class_loader_ticks + interpreter_ticks + compiler_ticks + unknown_ticks() != 0) {
}
if (WizardMode) {
}
reset();
}
/*
ThreadProfiler::print_unknown(){
if (table == NULL) {
return;
}
if (thread_ticks <= 0) {
return;
}
} */
if (thread_profiler != NULL) {
} else {
}
}
}
}
if (non_method_ticks() > 0) {
#ifndef PRODUCT
#endif
}
PCRecorder::print();
if(ProfileVM){
}
}
}
}
// Insertion sort the data, if it's relevant.
for (int i = 0; i < interval_print_size; i += 1) {
}
interval_data[i] = id;
break;
}
}
}
if ((interval_data[0].total() > 0)) {
for (int i = 0; i < interval_print_size; i += 1) {
if (interval_data[i].total() > 0) {
}
}
}
}
for (int i = 0; i < interval_print_size; i += 1) {
interval_data[i].reset();
}
}
}
}
if (thread_profiler != NULL) {
thread_profiler->oops_do(f);
} else {
}
}
}
}