This commit is contained in:
Daniel D. Daugherty 2015-07-16 10:22:08 -07:00
commit 6f19e14049
50 changed files with 696 additions and 169 deletions

View File

@ -34,7 +34,6 @@
define_pd_global(bool, ConvertSleepToYield, true);
define_pd_global(bool, ShareVtableStubs, true);
define_pd_global(bool, CountInterpCalls, true);
define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this
define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks
@ -61,8 +60,6 @@ define_pd_global(intx, StackRedPages, 1);
define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5));
define_pd_global(intx, PreInflateSpin, 10);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, Red Hat Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@ -869,7 +869,7 @@ void InterpreterGenerator::bang_stack_shadow_pages(bool native_call) {
// native method than the typical interpreter frame setup.
address InterpreterGenerator::generate_native_entry(bool synchronized) {
// determine code generation flags
bool inc_counter = UseCompiler || CountCompiledCalls;
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
// r1: Method*
// rscratch1: sender sp
@ -1307,7 +1307,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
//
address InterpreterGenerator::generate_normal_entry(bool synchronized) {
// determine code generation flags
bool inc_counter = UseCompiler || CountCompiledCalls;
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
// rscratch1: sender sp
address entry_point = __ pc();

View File

@ -47,8 +47,6 @@ define_pd_global(intx, OptoLoopAlignment, 16);
define_pd_global(intx, InlineFrequencyCount, 100);
define_pd_global(intx, InlineSmallCode, 1500);
define_pd_global(intx, PreInflateSpin, 10);
// Flags for template interpreter.
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);

View File

@ -668,7 +668,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
address entry = __ pc();
const bool inc_counter = UseCompiler || CountCompiledCalls;
const bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
// -----------------------------------------------------------------------------
// Allocate a new frame that represents the native callee (i2n frame).
@ -1118,7 +1118,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) {
// Generic interpreted method entry to (asm) interpreter.
//
address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) {
bool inc_counter = UseCompiler || CountCompiledCalls;
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
address entry = __ pc();
// Generate the code to allocate the interpreter stack frame.
Register Rsize_of_parameters = R4_ARG2, // Written by generate_fixed_frame.

View File

@ -39,7 +39,6 @@
define_pd_global(bool, DontYieldALot, true); // yield no more than 100 times per second
define_pd_global(bool, ConvertSleepToYield, false); // do not convert sleep(0) to yield. Helps GUI
define_pd_global(bool, ShareVtableStubs, false); // improves performance markedly for mtrt and compress
define_pd_global(bool, CountInterpCalls, false); // not implemented in the interpreter
define_pd_global(bool, NeedsDeoptSuspend, true); // register window machines need this
define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks
@ -67,8 +66,6 @@ define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1));
define_pd_global(intx, StackYellowPages, 2);
define_pd_global(intx, StackRedPages, 1);
define_pd_global(intx, PreInflateSpin, 40); // Determined by running design center
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2015, 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
@ -801,7 +801,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
// the following temporary registers are used during frame creation
const Register Gtmp1 = G3_scratch ;
const Register Gtmp2 = G1_scratch;
bool inc_counter = UseCompiler || CountCompiledCalls;
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
// make sure registers are different!
assert_different_registers(G2_thread, G5_method, Gargs, Gtmp1, Gtmp2);
@ -1225,7 +1225,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
address InterpreterGenerator::generate_normal_entry(bool synchronized) {
address entry = __ pc();
bool inc_counter = UseCompiler || CountCompiledCalls;
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
// the following temporary registers are used during frame creation
const Register Gtmp1 = G3_scratch ;

View File

@ -33,7 +33,6 @@
define_pd_global(bool, ConvertSleepToYield, true);
define_pd_global(bool, ShareVtableStubs, true);
define_pd_global(bool, CountInterpCalls, true);
define_pd_global(bool, NeedsDeoptSuspend, false); // only register window machines need this
define_pd_global(bool, ImplicitNullChecks, true); // Generate code for implicit null checks
@ -66,8 +65,6 @@ define_pd_global(intx, StackShadowPages, NOT_WIN64(20) WIN64_ONLY(6) DEBUG_ONLY(
define_pd_global(intx, StackShadowPages, 4 DEBUG_ONLY(+5));
#endif // AMD64
define_pd_global(intx, PreInflateSpin, 10);
define_pd_global(bool, RewriteBytecodes, true);
define_pd_global(bool, RewriteFrequentPairs, true);

View File

@ -1781,6 +1781,7 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
cmpxchgptr(scrReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
} else
if ((EmitSync & 128) == 0) { // avoid ST-before-CAS
// register juggle because we need tmpReg for cmpxchgptr below
movptr(scrReg, boxReg);
movptr(boxReg, tmpReg); // consider: LEA box, [tmp-2]
@ -1814,7 +1815,10 @@ void MacroAssembler::fast_lock(Register objReg, Register boxReg, Register tmpReg
}
cmpxchgptr(scrReg, Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
movptr(Address(scrReg, 0), 3); // box->_displaced_header = 3
// If we weren't able to swing _owner from NULL to the BasicLock
// then take the slow path.
jccb (Assembler::notZero, DONE_LABEL);
// update _owner from BasicLock to thread
get_thread (scrReg); // beware: clobbers ICCs
movptr(Address(boxReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), scrReg);
xorptr(boxReg, boxReg); // set icc.ZFlag = 1 to indicate success
@ -2083,6 +2087,9 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
xorptr(boxReg, boxReg); // box is really EAX
if (os::is_MP()) { lock(); }
cmpxchgptr(rsp, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
// There's no successor so we tried to regrab the lock with the
// placeholder value. If that didn't work, then another thread
// grabbed the lock so we're done (and exit was a success).
jccb (Assembler::notEqual, LSuccess);
// Since we're low on registers we installed rsp as a placeholding in _owner.
// Now install Self over rsp. This is safe as we're transitioning from
@ -2190,6 +2197,9 @@ void MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register tmpR
movptr(boxReg, (int32_t)NULL_WORD);
if (os::is_MP()) { lock(); }
cmpxchgptr(r15_thread, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)));
// There's no successor so we tried to regrab the lock.
// If that didn't work, then another thread grabbed the
// lock so we're done (and exit was a success).
jccb (Assembler::notEqual, LSuccess);
// Intentional fall-through into slow-path

View File

@ -2456,7 +2456,8 @@ void SharedRuntime::generate_deopt_blob() {
// allocate space for the code
ResourceMark rm;
// setup code generation tools
CodeBuffer buffer("deopt_blob", 1024, 1024);
// note: the buffer code size must account for StackShadowPages=50
CodeBuffer buffer("deopt_blob", 1536, 1024);
MacroAssembler* masm = new MacroAssembler(&buffer);
int frame_size_in_words;
OopMap* map = NULL;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2015, 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
@ -849,7 +849,7 @@ address InterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpret
address InterpreterGenerator::generate_native_entry(bool synchronized) {
// determine code generation flags
bool inc_counter = UseCompiler || CountCompiledCalls;
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
// rbx,: Method*
// rsi: sender sp
@ -1265,7 +1265,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
//
address InterpreterGenerator::generate_normal_entry(bool synchronized) {
// determine code generation flags
bool inc_counter = UseCompiler || CountCompiledCalls;
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
// rbx,: Method*
// rsi: sender sp

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2015, 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
@ -809,7 +809,7 @@ address InterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractInterpret
// native method than the typical interpreter frame setup.
address InterpreterGenerator::generate_native_entry(bool synchronized) {
// determine code generation flags
bool inc_counter = UseCompiler || CountCompiledCalls;
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
// rbx: Method*
// r13: sender sp
@ -1256,7 +1256,7 @@ address InterpreterGenerator::generate_native_entry(bool synchronized) {
//
address InterpreterGenerator::generate_normal_entry(bool synchronized) {
// determine code generation flags
bool inc_counter = UseCompiler || CountCompiledCalls;
bool inc_counter = UseCompiler || CountCompiledCalls || LogTouchedMethods;
// ebx: Method*
// r13: sender sp

View File

@ -34,7 +34,6 @@
define_pd_global(bool, ConvertSleepToYield, true);
define_pd_global(bool, ShareVtableStubs, true);
define_pd_global(bool, CountInterpCalls, true);
define_pd_global(bool, NeedsDeoptSuspend, false);
define_pd_global(bool, ImplicitNullChecks, true);
@ -45,7 +44,6 @@ define_pd_global(intx, CodeEntryAlignment, 32);
define_pd_global(intx, OptoLoopAlignment, 16);
define_pd_global(intx, InlineFrequencyCount, 100);
define_pd_global(intx, InlineSmallCode, 1000 );
define_pd_global(intx, PreInflateSpin, 10);
define_pd_global(intx, StackYellowPages, 2);
define_pd_global(intx, StackRedPages, 1);

View File

@ -3740,15 +3740,6 @@ void os::win32::initialize_system_info() {
"stack size not a multiple of page size");
initialize_performance_counter();
// Win95/Win98 scheduler bug work-around. The Win95/98 scheduler is
// known to deadlock the system, if the VM issues to thread operations with
// a too high frequency, e.g., such as changing the priorities.
// The 6000 seems to work well - no deadlocks has been notices on the test
// programs that we have seen experience this problem.
if (!os::win32::is_nt()) {
StarvationMonitorInterval = 6000;
}
}

View File

@ -75,6 +75,9 @@ ciMethod::ciMethod(methodHandle h_m, ciInstanceKlass* holder) :
{
assert(h_m() != NULL, "no null method");
if (LogTouchedMethods) {
h_m()->log_touched(Thread::current());
}
// These fields are always filled in in loaded methods.
_flags = ciFlags(h_m()->access_flags());

View File

@ -2698,8 +2698,7 @@ u2 ClassFileParser::parse_classfile_inner_classes_attribute(u1* inner_classes_at
// Inner class index
u2 inner_class_info_index = cfs->get_u2_fast();
check_property(
inner_class_info_index == 0 ||
valid_klass_reference_at(inner_class_info_index),
valid_klass_reference_at(inner_class_info_index),
"inner_class_info_index %u has bad constant type in class file %s",
inner_class_info_index, CHECK_0);
// Outer class index
@ -5163,8 +5162,8 @@ int ClassFileParser::verify_legal_method_signature(Symbol* name, Symbol* signatu
// The first non-signature thing better be a ')'
if ((length > 0) && (*p++ == JVM_SIGNATURE_ENDFUNC)) {
length--;
if (name->utf8_length() > 0 && name->byte_at(0) == '<') {
// All internal methods must return void
if (name == vmSymbols::object_initializer_name()) {
// All "<init>" methods must return void
if ((length == 1) && (p[0] == JVM_SIGNATURE_VOID)) {
return args_size;
}

View File

@ -58,14 +58,14 @@ Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS
if (DumpSharedSpaces) {
// Allocate all symbols to CLD shared metaspace
sym = new (len, ClassLoaderData::the_null_class_loader_data(), THREAD) Symbol(name, len, -1);
sym = new (len, ClassLoaderData::the_null_class_loader_data(), THREAD) Symbol(name, len, PERM_REFCOUNT);
} else if (c_heap) {
// refcount starts as 1
sym = new (len, THREAD) Symbol(name, len, 1);
assert(sym != NULL, "new should call vm_exit_out_of_memory if C_HEAP is exhausted");
} else {
// Allocate to global arena
sym = new (len, arena(), THREAD) Symbol(name, len, -1);
sym = new (len, arena(), THREAD) Symbol(name, len, PERM_REFCOUNT);
}
return sym;
}

View File

@ -2846,7 +2846,7 @@ void ClassVerifier::verify_invoke_instructions(
if (sig_stream.type() != T_VOID) {
if (method_name == vmSymbols::object_initializer_name()) {
// <init> method must have a void return type
/* Unreachable? Class file parser verifies that methods with '<' have
/* Unreachable? Class file parser verifies that <init> methods have
* void return */
verify_error(ErrorContext::bad_code(bci),
"Return type must be void in <init> method");

View File

@ -848,7 +848,7 @@ void EvacuateFollowersClosureGeneral::do_void() {
_gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen,
_scan_cur_or_nonheap,
_scan_older);
} while (!_gch->no_allocs_since_save_marks(true /* include_young */));
} while (!_gch->no_allocs_since_save_marks());
}

View File

@ -96,7 +96,7 @@ EvacuateFollowersClosure(GenCollectedHeap* gch,
void DefNewGeneration::EvacuateFollowersClosure::do_void() {
do {
_gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older);
} while (!_gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen));
} while (!_gch->no_allocs_since_save_marks());
}
DefNewGeneration::FastEvacuateFollowersClosure::
@ -112,7 +112,7 @@ FastEvacuateFollowersClosure(GenCollectedHeap* gch,
void DefNewGeneration::FastEvacuateFollowersClosure::do_void() {
do {
_gch->oop_since_save_marks_iterate(GenCollectedHeap::YoungGen, _scan_cur_or_nonheap, _scan_older);
} while (!_gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen));
} while (!_gch->no_allocs_since_save_marks());
guarantee(_gen->promo_failure_scan_is_complete(), "Failed to finish scan");
}
@ -597,7 +597,7 @@ void DefNewGeneration::collect(bool full,
gch->rem_set()->prepare_for_younger_refs_iterate(false);
assert(gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen),
assert(gch->no_allocs_since_save_marks(),
"save marks have not been newly set.");
// Not very pretty.
@ -617,7 +617,7 @@ void DefNewGeneration::collect(bool full,
&fsc_with_no_gc_barrier,
&fsc_with_gc_barrier);
assert(gch->no_allocs_since_save_marks(GenCollectedHeap::YoungGen),
assert(gch->no_allocs_since_save_marks(),
"save marks have not been newly set.");
{

View File

@ -741,11 +741,9 @@ ALL_SINCE_SAVE_MARKS_CLOSURES(GCH_SINCE_SAVE_MARKS_ITERATE_DEFN)
#undef GCH_SINCE_SAVE_MARKS_ITERATE_DEFN
bool GenCollectedHeap::no_allocs_since_save_marks(bool include_young) {
if (include_young && !_young_gen->no_allocs_since_save_marks()) {
return false;
}
return _old_gen->no_allocs_since_save_marks();
bool GenCollectedHeap::no_allocs_since_save_marks() {
return _young_gen->no_allocs_since_save_marks() &&
_old_gen->no_allocs_since_save_marks();
}
bool GenCollectedHeap::supports_inline_contig_alloc() const {

View File

@ -436,7 +436,7 @@ public:
// Returns "true" iff no allocations have occurred since the last
// call to "save_marks".
bool no_allocs_since_save_marks(bool include_young);
bool no_allocs_since_save_marks();
// Returns true if an incremental collection is likely to fail.
// We optionally consult the young gen, if asked to do so;

View File

@ -32,26 +32,32 @@ PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
void markOopDesc::print_on(outputStream* st) const {
if (is_marked()) {
st->print(" marked(" INTPTR_FORMAT ")", value());
} else if (has_monitor()) {
// have to check has_monitor() before is_locked()
st->print(" monitor(" INTPTR_FORMAT ")=", value());
ObjectMonitor* mon = monitor();
if (mon == NULL) {
st->print("NULL (this should never be seen!)");
} else {
st->print("{count=" INTPTR_FORMAT ",waiters=" INTPTR_FORMAT
",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}",
mon->count(), mon->waiters(), mon->recursions(),
p2i(mon->owner()));
}
} else if (is_locked()) {
st->print(" locked(" INTPTR_FORMAT ")->", value());
if (is_neutral()) {
st->print("is_neutral");
if (has_no_hash()) st->print(" no_hash");
else st->print(" hash=" INTPTR_FORMAT, hash());
if (has_no_hash()) {
st->print(" no_hash");
} else {
st->print(" hash=" INTPTR_FORMAT, hash());
}
st->print(" age=%d", age());
} else if (has_bias_pattern()) {
st->print("is_biased");
JavaThread* jt = biased_locker();
st->print(" biased_locker=" INTPTR_FORMAT, p2i(jt));
} else if (has_monitor()) {
ObjectMonitor* mon = monitor();
if (mon == NULL)
st->print("monitor=NULL");
else {
BasicLock * bl = (BasicLock *) mon->owner();
st->print("monitor={count=" INTPTR_FORMAT ",waiters=" INTPTR_FORMAT ",recursions=" INTPTR_FORMAT ",owner=" INTPTR_FORMAT "}",
mon->count(), mon->waiters(), mon->recursions(), p2i(bl));
}
} else {
st->print("??");
}

View File

@ -422,6 +422,11 @@ MethodCounters* Method::build_method_counters(Method* m, TRAPS) {
if (!mh->init_method_counters(counters)) {
MetadataFactory::free_metadata(mh->method_holder()->class_loader_data(), counters);
}
if (LogTouchedMethods) {
mh->log_touched(CHECK_NULL);
}
return mh->method_counters();
}
@ -2130,6 +2135,85 @@ void Method::collect_statistics(KlassSizeStats *sz) const {
}
#endif // INCLUDE_SERVICES
// LogTouchedMethods and PrintTouchedMethods
// TouchedMethodRecord -- we can't use a HashtableEntry<Method*> because
// the Method may be garbage collected. Let's roll our own hash table.
class TouchedMethodRecord : CHeapObj<mtTracing> {
public:
// It's OK to store Symbols here because they will NOT be GC'ed if
// LogTouchedMethods is enabled.
TouchedMethodRecord* _next;
Symbol* _class_name;
Symbol* _method_name;
Symbol* _method_signature;
};
static const int TOUCHED_METHOD_TABLE_SIZE = 20011;
static TouchedMethodRecord** _touched_method_table = NULL;
void Method::log_touched(TRAPS) {
const int table_size = TOUCHED_METHOD_TABLE_SIZE;
Symbol* my_class = klass_name();
Symbol* my_name = name();
Symbol* my_sig = signature();
unsigned int hash = my_class->identity_hash() +
my_name->identity_hash() +
my_sig->identity_hash();
juint index = juint(hash) % table_size;
MutexLocker ml(TouchedMethodLog_lock, THREAD);
if (_touched_method_table == NULL) {
_touched_method_table = NEW_C_HEAP_ARRAY2(TouchedMethodRecord*, table_size,
mtTracing, CURRENT_PC);
memset(_touched_method_table, 0, sizeof(TouchedMethodRecord*)*table_size);
}
TouchedMethodRecord* ptr = _touched_method_table[index];
while (ptr) {
if (ptr->_class_name == my_class &&
ptr->_method_name == my_name &&
ptr->_method_signature == my_sig) {
return;
}
if (ptr->_next == NULL) break;
ptr = ptr->_next;
}
TouchedMethodRecord* nptr = NEW_C_HEAP_OBJ(TouchedMethodRecord, mtTracing);
my_class->set_permanent(); // prevent reclaimed by GC
my_name->set_permanent();
my_sig->set_permanent();
nptr->_class_name = my_class;
nptr->_method_name = my_name;
nptr->_method_signature = my_sig;
nptr->_next = NULL;
if (ptr == NULL) {
// first
_touched_method_table[index] = nptr;
} else {
ptr->_next = nptr;
}
}
void Method::print_touched_methods(outputStream* out) {
MutexLockerEx ml(Thread::current()->is_VM_thread() ? NULL : TouchedMethodLog_lock);
out->print_cr("# Method::print_touched_methods version 1");
if (_touched_method_table) {
for (int i = 0; i < TOUCHED_METHOD_TABLE_SIZE; i++) {
TouchedMethodRecord* ptr = _touched_method_table[i];
while(ptr) {
ptr->_class_name->print_symbol_on(out); out->print(".");
ptr->_method_name->print_symbol_on(out); out->print(":");
ptr->_method_signature->print_symbol_on(out); out->cr();
ptr = ptr->_next;
}
}
}
}
// Verification
void Method::verify_on(outputStream* st) {

View File

@ -625,6 +625,8 @@ class Method : public Metadata {
#if INCLUDE_SERVICES
void collect_statistics(KlassSizeStats *sz) const;
#endif
void log_touched(TRAPS);
static void print_touched_methods(outputStream* out);
// interpreter support
static ByteSize const_offset() { return byte_offset_of(Method, _constMethod ); }

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2015, 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
@ -96,12 +96,16 @@
// TempNewSymbol (passed in as a parameter) so the reference count on its symbol
// will be decremented when it goes out of scope.
// This cannot be inherited from ResourceObj because it cannot have a vtable.
// Since sometimes this is allocated from Metadata, pick a base allocation
// type without virtual functions.
class ClassLoaderData;
// Set _refcount to PERM_REFCOUNT to prevent the Symbol from being GC'ed.
#ifndef PERM_REFCOUNT
#define PERM_REFCOUNT -1
#endif
// We separate the fields in SymbolBase from Symbol::_body so that
// Symbol::size(int) can correctly calculate the space needed.
class SymbolBase : public MetaspaceObj {
@ -160,6 +164,13 @@ class Symbol : private SymbolBase {
int refcount() const { return _refcount; }
void increment_refcount();
void decrement_refcount();
// Set _refcount non zero to avoid being reclaimed by GC.
void set_permanent() {
assert(LogTouchedMethods, "Should not be called with LogTouchedMethods off");
if (_refcount != PERM_REFCOUNT) {
_refcount = PERM_REFCOUNT;
}
}
int byte_at(int index) const {
assert(index >=0 && index < _length, "symbol index overflow");

View File

@ -277,6 +277,8 @@ static ObsoleteFlag obsolete_jvm_flags[] = {
{ "ParallelGCRetainPLAB", JDK_Version::jdk(9), JDK_Version::jdk(10) },
{ "ThreadSafetyMargin", JDK_Version::jdk(9), JDK_Version::jdk(10) },
{ "LazyBootClassLoader", JDK_Version::jdk(9), JDK_Version::jdk(10) },
{ "StarvationMonitorInterval", JDK_Version::jdk(9), JDK_Version::jdk(10) },
{ "PreInflateSpin", JDK_Version::jdk(9), JDK_Version::jdk(10) },
{ NULL, JDK_Version(0), JDK_Version(0) }
};

View File

@ -1291,7 +1291,7 @@ public:
experimental(intx, hashCode, 5, \
"(Unstable) select hashCode generation algorithm") \
\
experimental(intx, WorkAroundNPTLTimedWaitHang, 1, \
experimental(intx, WorkAroundNPTLTimedWaitHang, 0, \
"(Unstable, Linux-specific) " \
"avoid NPTL-FUTEX hang pthread_cond_timedwait") \
\
@ -2717,6 +2717,12 @@ public:
develop(bool, EagerInitialization, false, \
"Eagerly initialize classes if possible") \
\
diagnostic(bool, LogTouchedMethods, false, \
"Log methods which have been ever touched in runtime") \
\
diagnostic(bool, PrintTouchedMethodsAtExit, false, \
"Print all methods that have been ever touched in runtime") \
\
develop(bool, TraceMethodReplacement, false, \
"Print when methods are replaced do to recompilation") \
\
@ -3282,9 +3288,6 @@ public:
develop(intx, ProfilerNodeSize, 1024, \
"Size in K to allocate for the Profile Nodes of each thread") \
\
product_pd(intx, PreInflateSpin, \
"Number of times to spin wait before inflation") \
\
/* gc parameters */ \
product(size_t, InitialHeapSize, 0, \
"Initial heap size (in bytes); zero means use ergonomics") \
@ -3725,9 +3728,6 @@ public:
develop(intx, LongCompileThreshold, 50, \
"Used with +TraceLongCompiles") \
\
product(intx, StarvationMonitorInterval, 200, \
"Pause between each check (in milliseconds)") \
\
/* recompilation */ \
product_pd(intx, CompileThreshold, \
"number of interpreted method invocations before (re-)compiling") \
@ -4080,9 +4080,6 @@ public:
develop(bool, TraceDefaultMethods, false, \
"Trace the default method processing steps") \
\
develop(bool, VerifyGenericSignatures, false, \
"Abort VM on erroneous or inconsistent generic signatures") \
\
diagnostic(bool, WhiteBoxAPI, false, \
"Enable internal testing APIs") \
\

View File

@ -330,6 +330,10 @@ void print_statistics() {
SystemDictionary::print();
}
if (LogTouchedMethods && PrintTouchedMethodsAtExit) {
Method::print_touched_methods(tty);
}
if (PrintBiasedLockingStatistics) {
BiasedLocking::print_counters();
}
@ -382,6 +386,10 @@ void print_statistics() {
if (PrintNMTStatistics) {
MemTracker::final_report(tty);
}
if (LogTouchedMethods && PrintTouchedMethodsAtExit) {
Method::print_touched_methods(tty);
}
}
#endif

View File

@ -63,6 +63,7 @@ Monitor* StringDedupQueue_lock = NULL;
Mutex* StringDedupTable_lock = NULL;
Monitor* CodeCache_lock = NULL;
Mutex* MethodData_lock = NULL;
Mutex* TouchedMethodLog_lock = NULL;
Mutex* RetData_lock = NULL;
Monitor* VMOperationQueue_lock = NULL;
Monitor* VMOperationRequest_lock = NULL;
@ -274,6 +275,7 @@ void mutex_init() {
def(Compile_lock , Mutex , nonleaf+3, true, Monitor::_safepoint_check_sometimes);
def(MethodData_lock , Mutex , nonleaf+3, false, Monitor::_safepoint_check_always);
def(TouchedMethodLog_lock , Mutex , nonleaf+3, false, Monitor::_safepoint_check_always);
def(MethodCompileQueue_lock , Monitor, nonleaf+4, true, Monitor::_safepoint_check_always);
def(Debug2_lock , Mutex , nonleaf+4, true, Monitor::_safepoint_check_never);

View File

@ -55,6 +55,7 @@ extern Monitor* StringDedupQueue_lock; // a lock on the string dedupli
extern Mutex* StringDedupTable_lock; // a lock on the string deduplication table
extern Monitor* CodeCache_lock; // a lock on the CodeCache, rank is special, use MutexLockerEx
extern Mutex* MethodData_lock; // a lock on installation of method data
extern Mutex* TouchedMethodLog_lock; // a lock on allocation of LogExecutedMethods info
extern Mutex* RetData_lock; // a lock on installation of RetData inside method data
extern Mutex* DerivedPointerTableGC_lock; // a lock to protect the derived pointer table
extern Monitor* VMOperationQueue_lock; // a lock on queue of vm_operations waiting to execute

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2015, 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
@ -103,8 +103,10 @@
// The knob* variables are effectively final. Once set they should
// never be modified hence. Consider using __read_mostly with GCC.
int ObjectMonitor::Knob_ExitRelease = 0;
int ObjectMonitor::Knob_Verbose = 0;
int ObjectMonitor::Knob_VerifyInUse = 0;
int ObjectMonitor::Knob_VerifyMatch = 0;
int ObjectMonitor::Knob_SpinLimit = 5000; // derived by an external tool -
static int Knob_LogSpins = 0; // enable jvmstat tally for spins
static int Knob_HandOff = 0;
@ -251,24 +253,6 @@ static volatile int InitDone = 0;
// -----------------------------------------------------------------------------
// Enter support
bool ObjectMonitor::try_enter(Thread* THREAD) {
if (THREAD != _owner) {
if (THREAD->is_lock_owned ((address)_owner)) {
assert(_recursions == 0, "internal state error");
_owner = THREAD;
_recursions = 1;
return true;
}
if (Atomic::cmpxchg_ptr (THREAD, &_owner, NULL) != NULL) {
return false;
}
return true;
} else {
_recursions++;
return true;
}
}
void NOINLINE ObjectMonitor::enter(TRAPS) {
// The following code is ordered to check the most common cases first
// and to reduce RTS->RTO cache line upgrades on SPARC and IA32 processors.
@ -2272,7 +2256,7 @@ void ObjectWaiter::wait_reenter_end(ObjectMonitor * const mon) {
}
inline void ObjectMonitor::AddWaiter(ObjectWaiter* node) {
assert(node != NULL, "should not dequeue NULL node");
assert(node != NULL, "should not add NULL node");
assert(node->_prev == NULL, "node already in list");
assert(node->_next == NULL, "node already in list");
// put node at end of queue (circular doubly linked list)
@ -2407,8 +2391,8 @@ static int kvGetInt(char * kvList, const char * Key, int Default) {
char * v = kvGet(kvList, Key);
int rslt = v ? ::strtol(v, NULL, 0) : Default;
if (Knob_ReportSettings && v != NULL) {
::printf (" SyncKnob: %s %d(%d)\n", Key, rslt, Default) ;
::fflush(stdout);
tty->print_cr("INFO: SyncKnob: %s %d(%d)", Key, rslt, Default) ;
tty->flush();
}
return rslt;
}
@ -2442,8 +2426,10 @@ void ObjectMonitor::DeferredInitialize() {
#define SETKNOB(x) { Knob_##x = kvGetInt(knobs, #x, Knob_##x); }
SETKNOB(ReportSettings);
SETKNOB(ExitRelease);
SETKNOB(Verbose);
SETKNOB(VerifyInUse);
SETKNOB(VerifyMatch);
SETKNOB(FixedSpin);
SETKNOB(SpinLimit);
SETKNOB(SpinBase);
@ -2477,7 +2463,9 @@ void ObjectMonitor::DeferredInitialize() {
if (os::is_MP()) {
BackOffMask = (1 << Knob_SpinBackOff) - 1;
if (Knob_ReportSettings) ::printf("BackOffMask=%X\n", BackOffMask);
if (Knob_ReportSettings) {
tty->print_cr("INFO: BackOffMask=0x%X", BackOffMask);
}
// CONSIDER: BackOffMask = ROUNDUP_NEXT_POWER2 (ncpus-1)
} else {
Knob_SpinLimit = 0;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2015, 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
@ -196,8 +196,10 @@ class ObjectMonitor {
static PerfCounter * _sync_Deflations;
static PerfLongVariable * _sync_MonExtant;
static int Knob_ExitRelease;
static int Knob_Verbose;
static int Knob_VerifyInUse;
static int Knob_VerifyMatch;
static int Knob_SpinLimit;
void* operator new (size_t size) throw() {
@ -317,7 +319,6 @@ class ObjectMonitor {
void print();
#endif
bool try_enter(TRAPS);
void enter(TRAPS);
void exit(bool not_suspended, TRAPS);
void wait(jlong millis, bool interruptable, TRAPS);
@ -354,14 +355,14 @@ class ObjectMonitor {
#undef TEVENT
#define TEVENT(nom) { if (SyncVerbose) FEVENT(nom); }
#define FEVENT(nom) \
{ \
static volatile int ctr = 0; \
int v = ++ctr; \
if ((v & (v - 1)) == 0) { \
::printf(#nom " : %d\n", v); \
::fflush(stdout); \
} \
#define FEVENT(nom) \
{ \
static volatile int ctr = 0; \
int v = ++ctr; \
if ((v & (v - 1)) == 0) { \
tty->print_cr("INFO: " #nom " : %d", v); \
tty->flush(); \
} \
}
#undef TEVENT

View File

@ -40,6 +40,7 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/synchronizer.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/vframe.hpp"
#include "utilities/dtrace.hpp"
#include "utilities/events.hpp"
#include "utilities/preserveException.hpp"
@ -927,8 +928,9 @@ static void InduceScavenge(Thread * Self, const char * Whence) {
if (ForceMonitorScavenge == 0 && Atomic::xchg (1, &ForceMonitorScavenge) == 0) {
if (ObjectMonitor::Knob_Verbose) {
::printf ("Monitor scavenge - Induced STW @%s (%d)\n", Whence, ForceMonitorScavenge) ;
::fflush(stdout);
tty->print_cr("INFO: Monitor scavenge - Induced STW @%s (%d)",
Whence, ForceMonitorScavenge) ;
tty->flush();
}
// Induce a 'null' safepoint to scavenge monitors
// Must VM_Operation instance be heap allocated as the op will be enqueue and posted
@ -937,8 +939,9 @@ static void InduceScavenge(Thread * Self, const char * Whence) {
VMThread::execute(new VM_ForceAsyncSafepoint());
if (ObjectMonitor::Knob_Verbose) {
::printf ("Monitor scavenge - STW posted @%s (%d)\n", Whence, ForceMonitorScavenge) ;
::fflush(stdout);
tty->print_cr("INFO: Monitor scavenge - STW posted @%s (%d)",
Whence, ForceMonitorScavenge) ;
tty->flush();
}
}
}
@ -1603,10 +1606,11 @@ void ObjectSynchronizer::deflate_idle_monitors() {
// Consider: audit gFreeList to ensure that gMonitorFreeCount and list agree.
if (ObjectMonitor::Knob_Verbose) {
::printf("Deflate: InCirc=%d InUse=%d Scavenged=%d ForceMonitorScavenge=%d : pop=%d free=%d\n",
nInCirculation, nInuse, nScavenged, ForceMonitorScavenge,
gMonitorPopulation, gMonitorFreeCount);
::fflush(stdout);
tty->print_cr("INFO: Deflate: InCirc=%d InUse=%d Scavenged=%d "
"ForceMonitorScavenge=%d : pop=%d free=%d",
nInCirculation, nInuse, nScavenged, ForceMonitorScavenge,
gMonitorPopulation, gMonitorFreeCount);
tty->flush();
}
ForceMonitorScavenge = 0; // Reset
@ -1643,6 +1647,14 @@ class ReleaseJavaMonitorsClosure: public MonitorClosure {
ReleaseJavaMonitorsClosure(Thread* thread) : THREAD(thread) {}
void do_monitor(ObjectMonitor* mid) {
if (mid->owner() == THREAD) {
if (ObjectMonitor::Knob_VerifyMatch != 0) {
Handle obj((oop) mid->object());
tty->print("INFO: unexpected locked object:");
javaVFrame::print_locked_object_class_name(tty, obj, "locked");
fatal(err_msg("exiting JavaThread=" INTPTR_FORMAT
" unexpectedly owns ObjectMonitor=" INTPTR_FORMAT,
THREAD, mid));
}
(void)mid->complete_exit(CHECK);
}
}

View File

@ -1802,14 +1802,25 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
assert(!this->has_pending_exception(), "ensure_join should have cleared");
// 6282335 JNI DetachCurrentThread spec states that all Java monitors
// held by this thread must be released. A detach operation must only
// get here if there are no Java frames on the stack. Therefore, any
// owned monitors at this point MUST be JNI-acquired monitors which are
// pre-inflated and in the monitor cache.
// held by this thread must be released. The spec does not distinguish
// between JNI-acquired and regular Java monitors. We can only see
// regular Java monitors here if monitor enter-exit matching is broken.
//
// ensure_join() ignores IllegalThreadStateExceptions, and so does this.
if (exit_type == jni_detach && JNIDetachReleasesMonitors) {
assert(!this->has_last_Java_frame(), "detaching with Java frames?");
// Optionally release any monitors for regular JavaThread exits. This
// is provided as a work around for any bugs in monitor enter-exit
// matching. This can be expensive so it is not enabled by default.
// ObjectMonitor::Knob_ExitRelease is a superset of the
// JNIDetachReleasesMonitors option.
//
// ensure_join() ignores IllegalThreadStateExceptions, and so does
// ObjectSynchronizer::release_monitors_owned_by_thread().
if ((exit_type == jni_detach && JNIDetachReleasesMonitors) ||
ObjectMonitor::Knob_ExitRelease) {
// Sanity check even though JNI DetachCurrentThread() would have
// returned JNI_ERR if there was a Java frame. JavaThread exit
// should be done executing Java code by the time we get here.
assert(!this->has_last_Java_frame(),
"should not have a Java frame when detaching or exiting");
ObjectSynchronizer::release_monitors_owned_by_thread(this);
assert(!this->has_pending_exception(), "release_monitors should have cleared");
}

View File

@ -144,7 +144,7 @@ GrowableArray<MonitorInfo*>* javaVFrame::locked_monitors() {
return result;
}
static void print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state) {
void javaVFrame::print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state) {
if (obj.not_null()) {
st->print("\t- %s <" INTPTR_FORMAT "> ", lock_state, (address)obj());
if (obj->klass() == SystemDictionary::Class_klass()) {
@ -160,17 +160,29 @@ static void print_locked_object_class_name(outputStream* st, Handle obj, const c
void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
ResourceMark rm;
// If this is the first frame, and java.lang.Object.wait(...) then print out the receiver.
// If this is the first frame and it is java.lang.Object.wait(...)
// then print out the receiver. Locals are not always available,
// e.g., compiled native frames have no scope so there are no locals.
if (frame_count == 0) {
if (method()->name() == vmSymbols::wait_name() &&
method()->method_holder()->name() == vmSymbols::java_lang_Object()) {
const char *wait_state = "waiting on"; // assume we are waiting
// If earlier in the output we reported java.lang.Thread.State ==
// "WAITING (on object monitor)" and now we report "waiting on", then
// we are still waiting for notification or timeout. Otherwise if
// we earlier reported java.lang.Thread.State == "BLOCKED (on object
// monitor)", then we are actually waiting to re-lock the monitor.
// At this level we can't distinguish the two cases to report
// "waited on" rather than "waiting on" for the second case.
StackValueCollection* locs = locals();
if (!locs->is_empty()) {
StackValue* sv = locs->at(0);
if (sv->type() == T_OBJECT) {
Handle o = locs->at(0)->get_obj();
print_locked_object_class_name(st, o, "waiting on");
print_locked_object_class_name(st, o, wait_state);
}
} else {
st->print_cr("\t- %s <no object reference available>", wait_state);
}
} else if (thread()->current_park_blocker() != NULL) {
oop obj = thread()->current_park_blocker();
@ -179,8 +191,8 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
}
}
// Print out all monitors that we have locked or are trying to lock
// Print out all monitors that we have locked, or are trying to lock,
// including re-locking after being notified or timing out in a wait().
GrowableArray<MonitorInfo*>* mons = monitors();
if (!mons->is_empty()) {
bool found_first_monitor = false;
@ -202,14 +214,14 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
if (monitor->owner() != NULL) {
// the monitor is associated with an object, i.e., it is locked
// First, assume we have the monitor locked. If we haven't found an
// owned monitor before and this is the first frame, then we need to
// see if we have completed the lock or we are blocked trying to
// acquire it - we can only be blocked if the monitor is inflated
markOop mark = NULL;
const char *lock_state = "locked"; // assume we have the monitor locked
if (!found_first_monitor && frame_count == 0) {
// If this is the first frame and we haven't found an owned
// monitor before, then we need to see if we have completed
// the lock or if we are blocked trying to acquire it. Only
// an inflated monitor that is first on the monitor list in
// the first frame can block us on a monitor enter.
mark = monitor->owner()->mark();
if (mark->has_monitor() &&
( // we have marked ourself as pending on this monitor
@ -219,13 +231,35 @@ void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) {
)) {
lock_state = "waiting to lock";
} else {
mark = NULL; // Disable printing below
// We own the monitor which is not as interesting so
// disable the extra printing below.
mark = NULL;
}
} else if (frame_count != 0 && ObjectMonitor::Knob_Verbose) {
// This is not the first frame so we either own this monitor
// or we owned the monitor before and called wait(). Because
// wait() could have been called on any monitor in a lower
// numbered frame on the stack, we have to check all the
// monitors on the list for this frame.
// Note: Only enable this new output line in verbose mode
// since existing tests are not ready for it.
mark = monitor->owner()->mark();
if (mark->has_monitor() &&
( // we have marked ourself as pending on this monitor
mark->monitor() == thread()->current_pending_monitor() ||
// we are not the owner of this monitor
!mark->monitor()->is_entered(thread())
)) {
lock_state = "waiting to re-lock in wait()";
} else {
// We own the monitor which is not as interesting so
// disable the extra printing below.
mark = NULL;
}
}
print_locked_object_class_name(st, monitor->owner(), lock_state);
if (Verbose && mark != NULL) {
// match with format above, replacing "-" with " ".
st->print("\t lockbits=");
if (ObjectMonitor::Knob_Verbose && mark != NULL) {
st->print("\t- lockbits=");
mark->print_on(st);
st->cr();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2015, 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
@ -135,7 +135,8 @@ class javaVFrame: public vframe {
// Return an array of monitors locked by this frame in the youngest to oldest order
GrowableArray<MonitorInfo*>* locked_monitors();
// printing used during stack dumps
// printing used during stack dumps and diagnostics
static void print_locked_object_class_name(outputStream* st, Handle obj, const char* lock_state);
void print_lock_info_on(outputStream* st, int frame_count);
void print_lock_info(int frame_count) { print_lock_info_on(tty, frame_count); }

View File

@ -101,6 +101,7 @@
template(WhiteBoxOperation) \
template(ClassLoaderStatsOperation) \
template(DumpHashtable) \
template(DumpTouchedMethods) \
template(MarkActiveNMethods) \
template(PrintCompileQueue) \
template(PrintCodeList) \

View File

@ -74,6 +74,7 @@ void DCmdRegistrant::register_dcmds(){
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CompileQueueDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeListDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<CodeCacheDCmd>(full_export, true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<TouchedMethodsDCmd>(full_export, true, false));
// Enhanced JMX Agent Support
// These commands won't be exported via the DiagnosticCommandMBean until an
@ -808,3 +809,35 @@ int ClassHierarchyDCmd::num_arguments() {
}
#endif
class VM_DumpTouchedMethods : public VM_Operation {
private:
outputStream* _out;
public:
VM_DumpTouchedMethods(outputStream* out) {
_out = out;
}
virtual VMOp_Type type() const { return VMOp_DumpTouchedMethods; }
virtual void doit() {
Method::print_touched_methods(_out);
}
};
TouchedMethodsDCmd::TouchedMethodsDCmd(outputStream* output, bool heap) :
DCmdWithParser(output, heap)
{}
void TouchedMethodsDCmd::execute(DCmdSource source, TRAPS) {
if (!UnlockDiagnosticVMOptions) {
output()->print_cr("VM.touched_methods command requires -XX:+UnlockDiagnosticVMOptions");
return;
}
VM_DumpTouchedMethods dumper(output());
VMThread::execute(&dumper);
}
int TouchedMethodsDCmd::num_arguments() {
return 0;
}

View File

@ -35,6 +35,7 @@
#include "services/diagnosticFramework.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
#include "oops/method.hpp"
class HelpDCmd : public DCmdWithParser {
protected:
@ -341,6 +342,22 @@ public:
virtual void execute(DCmdSource source, TRAPS);
};
class TouchedMethodsDCmd : public DCmdWithParser {
public:
TouchedMethodsDCmd(outputStream* output, bool heap);
static const char* name() {
return "VM.print_touched_methods";
}
static const char* description() {
return "Print all methods that have ever been touched during the lifetime of this JVM.";
}
static const char* impact() {
return "Medium: Depends on Java content.";
}
static int num_arguments();
virtual void execute(DCmdSource source, TRAPS);
};
// See also: thread_dump in attachListener.cpp
class ThreadDumpDCmd : public DCmdWithParser {
protected:

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2015, 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
* 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.
*/
/*
* @test
* @bug 8025692
* @modules java.base/sun.misc
* java.management
* @library /testlibrary
* @compile TestLogTouchedMethods.java PrintTouchedMethods.java
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+LogTouchedMethods PrintTouchedMethods
*/
import java.io.File;
import java.util.List;
import jdk.test.lib.*;
public class PrintTouchedMethods {
public static void main(String args[]) throws Exception {
String[] javaArgs1 = {"-XX:-UnlockDiagnosticVMOptions", "-XX:+LogTouchedMethods", "-XX:+PrintTouchedMethodsAtExit", "TestLogTouchedMethods"};
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(javaArgs1);
// UnlockDiagnostic turned off, should fail
OutputAnalyzer output = new OutputAnalyzer(pb.start());
output.shouldContain("Error: VM option 'LogTouchedMethods' is diagnostic and must be enabled via -XX:+UnlockDiagnosticVMOptions.");
output.shouldContain("Error: Could not create the Java Virtual Machine.");
String[] javaArgs2 = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+LogTouchedMethods", "-XX:+PrintTouchedMethodsAtExit", "TestLogTouchedMethods"};
pb = ProcessTools.createJavaProcessBuilder(javaArgs2);
output = new OutputAnalyzer(pb.start());
// check order:
// 1 "# Method::print_touched_methods version 1" is the first in first line
// 2 should contain TestLogMethods.methodA:()V
// 3 should not contain TestLogMethods.methodB:()V
// Repeat above for another run with -Xint
List<String> lines = output.asLines();
if (lines.size() < 1) {
throw new Exception("Empty output");
}
String first = lines.get(0);
if (!first.equals("# Method::print_touched_methods version 1")) {
throw new Exception("First line mismatch");
}
output.shouldContain("TestLogTouchedMethods.methodA:()V");
output.shouldNotContain("TestLogTouchedMethods.methodB:()V");
output.shouldHaveExitValue(0);
String[] javaArgs3 = {"-XX:+UnlockDiagnosticVMOptions", "-Xint", "-XX:+LogTouchedMethods", "-XX:+PrintTouchedMethodsAtExit", "TestLogTouchedMethods"};
pb = ProcessTools.createJavaProcessBuilder(javaArgs3);
output = new OutputAnalyzer(pb.start());
lines = output.asLines();
if (lines.size() < 1) {
throw new Exception("Empty output");
}
first = lines.get(0);
if (!first.equals("# Method::print_touched_methods version 1")) {
throw new Exception("First line mismatch");
}
output.shouldContain("TestLogTouchedMethods.methodA:()V");
output.shouldNotContain("TestLogTouchedMethods.methodB:()V");
output.shouldHaveExitValue(0);
// Test jcmd PrintTouchedMethods VM.print_touched_methods
String pid = Integer.toString(ProcessTools.getProcessId());
pb = new ProcessBuilder();
pb.command(new String[] {JDKToolFinder.getJDKTool("jcmd"), pid, "VM.print_touched_methods"});
output = new OutputAnalyzer(pb.start());
try {
output.shouldContain("PrintTouchedMethods.main:([Ljava/lang/String;)V");
} catch (RuntimeException e) {
output.shouldContain("Unknown diagnostic command");
}
}
}

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) 2015, 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
* 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.
*/
/* used by PrintTouchedMethods.java */
public class TestLogTouchedMethods {
public static void main(String[] args) {
new TestLogTouchedMethods().methodA();
}
public void methodA() {} // called
public void methodB() {} // this should not be called
}

View File

@ -46,16 +46,8 @@ public class CreateCoredumpOnCrash {
runTest("-XX:-CreateCoredumpOnCrash").shouldContain("CreateCoredumpOnCrash turned off, no core file dumped");
if (Platform.isWindows()) {
runTest("-XX:+CreateCoredumpOnCrash").shouldContain("Core dump will be written. Default location");
// The old CreateMinidumpOnCrash option should still work
runTest("-XX:+CreateMinidumpOnCrash").shouldContain("Core dump will be written. Default location");
runTest("-XX:-CreateMinidumpOnCrash").shouldContain("CreateCoredumpOnCrash turned off, no core file dumped");
if (Platform.isDebugBuild()) {
// Make sure we create dumps on Windows debug builds by default
runTest("-Ddummyopt=false").shouldContain("Core dump will be written. Default location");
}
} else {
runTest("-XX:+CreateCoredumpOnCrash").shouldNotContain("CreateCoredumpOnCrash turned off, no core file dumped");
}

View File

@ -45,6 +45,7 @@ public class TestOnError {
// Execute the VM so that a
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:-TransmitErrorReport",
"-XX:-CreateCoredumpOnCrash",
"-XX:ErrorHandlerTest=12", // trigger potential SEGV
"-XX:OnError=echo " + msg,
TestOnError.class.getName());

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2015, 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
* 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.
*
*/
/*
* @test
* @bug 8130669
* @summary VM prohibits <clinit> methods with return values
* @compile ignoredClinit.jasm
* @compile badInit.jasm
* @run main/othervm -Xverify:all BadInitMethod
*/
// Test that a non-void <clinit> method does not cause an exception to be
// thrown. But that a non-void <init> method causes a ClassFormatError
// exception.
public class BadInitMethod {
public static void main(String args[]) throws Throwable {
System.out.println("Regression test for bug 8130669");
try {
Class newClass = Class.forName("ignoredClinit");
} catch (java.lang.Throwable e) {
throw new RuntimeException("Unexpected exception: " + e.getMessage());
}
try {
Class newClass = Class.forName("badInit");
throw new RuntimeException("Expected ClassFormatError exception not thrown");
} catch (java.lang.ClassFormatError e) {
System.out.println("Test BadInitMethod passed");
}
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2015, 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
* 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.
*
*/
/*
* @test
* @bug 8130183
* @summary For InnerClasses attribute, VM permits inner_class_info_index value of zero
* @compile badEnclMthd.jcod
* @run main/othervm -Xverify:all EnclosingMethod
*/
// Test that an EnclosingMethod attribute with the value of 0 causes a ClassFormatError.
public class EnclosingMethod {
public static void main(String args[]) throws Throwable {
System.out.println("Regression test for bug 8130183");
try {
Class newClass = Class.forName("badEnclMthd");
throw new RuntimeException("Expected ClassFormatError exception not thrown");
} catch (java.lang.ClassFormatError e) {
System.out.println("Test EnclosingMethod passed");
}
}
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2015, 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
* 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.
*
*/
// Source: badEnclMthd
class badEnclMthd {
0xCAFEBABE;
0; // minor version
50; // major version
[] { // Constant Pool
; // first element is empty
Utf8 "badEnclMthd"; // #1
class #1; // #2
Utf8 "java/lang/Object"; // #3
class #3; // #4
Utf8 "InnerClasses"; // #5
Utf8 "badEnclMthd"; // #6
class #6; // #7
Utf8 "badEnclMthd"; // #8
class #8; // #9
} // Constant Pool
0x0001; // access public
#2;// this_cpx
#4;// super_cpx
[] { // interfaces
} // interfaces
[] { // fields
} // fields
[] { // methods
} // methods
[] { // attributes
Attr(#5) { // InnerClasses
[] { // InnerClasses
#0 #2 #6 1; // Bad inner_class_info_index of 0 !!!
#9 #0 #8 1;
}
} // end InnerClasses
;
} // attributes
} // end class badEnclMthd

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2015, 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
* 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.
*
*/
super public class badInit
version 52:0
{
// This <init> method has a non-void signature. It should cause a
// ClassFormatError exception.
Method "<init>":"(I)I"
stack 1 locals 2
{
aload_0;
invokespecial Method java/lang/Object."<init>":"()V";
iconst_4;
ireturn;
}
public static Method main:"([Ljava/lang/String;)V"
stack 0 locals 1
{
return;
}
} // end Class badInit

View File

@ -19,28 +19,21 @@
* 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.
*
*/
/*
* @test
* @bug 8076421
* @summary Test of hprof option crashes Zero
* @compile cpu002.java
* @run main/othervm -Xrunhprof:cpu=times,file=cpu002.hprof.out cpu002
*/
// This class contains a <clinit> method with signature: ()I. The JVM should
// not complain about this because methods named <clinit> that have arguments
// and/or are not void should be ignored by the JVM.
import java.io.*;
public class ignoredClinit version 51:0
{
public class cpu002 {
public static final int PASSED = 0;
public static final int FAILED = 2;
public static final int JCK_STATUS_BASE = 95;
public static void main (String argv[]) {
System.exit(run(argv,System.out) + JCK_STATUS_BASE);
public static Method "<clinit>":"()I"
stack 1 locals 1
{
iconst_0;
ireturn;
}
public static int run(String argv[], PrintStream out) {
return PASSED;
}
}
} // end Class ignoredClinit

View File

@ -60,6 +60,7 @@ public class ReserveMemory {
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-XX:-TransmitErrorReport",
"-XX:-CreateCoredumpOnCrash",
"-Xmx32m",
"ReserveMemory",
"test");

View File

@ -34,6 +34,7 @@ import jdk.test.lib.apps.LingeredApp;
* @test
* @library /../../test/lib/share/classes
* @library /testlibrary
* @ignore 8129971
* @build jdk.test.lib.*
* @build jdk.test.lib.apps.*
* @run main TestStackTrace