hotspot/src/share/vm/code/nmethod.cpp
Print this page
rev 611 : Merge
@@ -1,10 +1,10 @@
#ifdef USE_PRAGMA_IDENT_SRC
#pragma ident "@(#)nmethod.cpp 1.371 08/02/29 12:46:11 JVM"
#endif
/*
- * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2008 Sun Microsystems, Inc. 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.
@@ -28,11 +28,10 @@
# include "incls/_precompiled.incl"
# include "incls/_nmethod.cpp.incl"
#ifdef DTRACE_ENABLED
-
// Only bother with this argument setup if dtrace is available
HS_DTRACE_PROBE_DECL8(hotspot, compiled__method__load,
const char*, int, const char*, int, const char*, int, void*, size_t);
@@ -439,11 +438,10 @@
// create nmethod
nmethod* nm = NULL;
{
MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
int native_nmethod_size = allocation_size(code_buffer, sizeof(nmethod));
- const int dummy = -1; // Flag to force proper "operator new"
CodeOffsets offsets;
offsets.set_value(CodeOffsets::Verified_Entry, vep_offset);
offsets.set_value(CodeOffsets::Frame_Complete, frame_complete);
nm = new (native_nmethod_size)
nmethod(method(), native_nmethod_size, &offsets,
@@ -462,10 +460,45 @@
}
return nm;
}
+#ifdef HAVE_DTRACE_H
+nmethod* nmethod::new_dtrace_nmethod(methodHandle method,
+ CodeBuffer *code_buffer,
+ int vep_offset,
+ int trap_offset,
+ int frame_complete,
+ int frame_size) {
+ // create nmethod
+ nmethod* nm = NULL;
+ {
+ MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+ int nmethod_size = allocation_size(code_buffer, sizeof(nmethod));
+ CodeOffsets offsets;
+ offsets.set_value(CodeOffsets::Verified_Entry, vep_offset);
+ offsets.set_value(CodeOffsets::Dtrace_trap, trap_offset);
+ offsets.set_value(CodeOffsets::Frame_Complete, frame_complete);
+
+ nm = new (nmethod_size) nmethod(method(), nmethod_size, &offsets, code_buffer, frame_size);
+
+ NOT_PRODUCT(if (nm != NULL) nmethod_stats.note_nmethod(nm));
+ if (PrintAssembly && nm != NULL)
+ Disassembler::decode(nm);
+ }
+ // verify nmethod
+ debug_only(if (nm) nm->verify();) // might block
+
+ if (nm != NULL) {
+ nm->log_new_nmethod();
+ }
+
+ return nm;
+}
+
+#endif // def HAVE_DTRACE_H
+
nmethod* nmethod::new_nmethod(methodHandle method,
int compile_id,
int entry_bci,
CodeOffsets* offsets,
int orig_pc_offset,
@@ -559,10 +592,13 @@
// We have no exception handler or deopt handler make the
// values something that will never match a pc like the nmethod vtable entry
_exception_offset = 0;
_deoptimize_offset = 0;
_orig_pc_offset = 0;
+#ifdef HAVE_DTRACE_H
+ _trap_offset = 0;
+#endif // def HAVE_DTRACE_H
_stub_offset = data_offset();
_consts_offset = data_offset();
_scopes_data_offset = data_offset();
_scopes_pcs_offset = _scopes_data_offset;
_dependencies_offset = _scopes_pcs_offset;
@@ -616,10 +652,94 @@
}
}
Events::log("Create nmethod " INTPTR_FORMAT, this);
}
+// For dtrace wrappers
+#ifdef HAVE_DTRACE_H
+nmethod::nmethod(
+ methodOop method,
+ int nmethod_size,
+ CodeOffsets* offsets,
+ CodeBuffer* code_buffer,
+ int frame_size)
+ : CodeBlob("dtrace nmethod", code_buffer, sizeof(nmethod),
+ nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, NULL),
+ _compiled_synchronized_native_basic_lock_owner_sp_offset(in_ByteSize(-1)),
+ _compiled_synchronized_native_basic_lock_sp_offset(in_ByteSize(-1))
+{
+ {
+ debug_only(No_Safepoint_Verifier nsv;)
+ assert_locked_or_safepoint(CodeCache_lock);
+
+ NOT_PRODUCT(_has_debug_info = false; )
+ _method = method;
+ _entry_bci = InvocationEntryBci;
+ _link = NULL;
+ _compiler = NULL;
+ // We have no exception handler or deopt handler make the
+ // values something that will never match a pc like the nmethod vtable entry
+ _exception_offset = 0;
+ _deoptimize_offset = 0;
+ _trap_offset = offsets->value(CodeOffsets::Dtrace_trap);
+ _orig_pc_offset = 0;
+ _stub_offset = data_offset();
+ _consts_offset = data_offset();
+ _scopes_data_offset = data_offset();
+ _scopes_pcs_offset = _scopes_data_offset;
+ _dependencies_offset = _scopes_pcs_offset;
+ _handler_table_offset = _dependencies_offset;
+ _nul_chk_table_offset = _handler_table_offset;
+ _nmethod_end_offset = _nul_chk_table_offset;
+ _compile_id = 0; // default
+ _comp_level = CompLevel_none;
+ _entry_point = instructions_begin();
+ _verified_entry_point = instructions_begin() + offsets->value(CodeOffsets::Verified_Entry);
+ _osr_entry_point = NULL;
+ _exception_cache = NULL;
+ _pc_desc_cache.reset_to(NULL);
+
+ flags.clear();
+ flags.state = alive;
+ _markedForDeoptimization = 0;
+
+ _lock_count = 0;
+ _stack_traversal_mark = 0;
+
+ code_buffer->copy_oops_to(this);
+ debug_only(check_store();)
+ CodeCache::commit(this);
+ VTune::create_nmethod(this);
+ }
+
+ if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
+ ttyLocker ttyl; // keep the following output all in one block
+ // This output goes directly to the tty, not the compiler log.
+ // To enable tools to match it up with the compilation activity,
+ // be sure to tag this tty output with the compile ID.
+ if (xtty != NULL) {
+ xtty->begin_head("print_dtrace_nmethod");
+ xtty->method(_method);
+ xtty->stamp();
+ xtty->end_head(" address='" INTPTR_FORMAT "'", (intptr_t) this);
+ }
+ // print the header part first
+ print();
+ // then print the requested information
+ if (PrintNMethods) {
+ print_code();
+ }
+ if (PrintRelocations) {
+ print_relocations();
+ }
+ if (xtty != NULL) {
+ xtty->tail("print_dtrace_nmethod");
+ }
+ }
+ Events::log("Create nmethod " INTPTR_FORMAT, this);
+}
+#endif // def HAVE_DTRACE_H
void* nmethod::operator new(size_t size, int nmethod_size) {
// Always leave some room in the CodeCache for I2C/C2I adapters
if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) return NULL;
return CodeCache::allocate(nmethod_size);
@@ -659,10 +779,13 @@
_comp_level = comp_level;
_entry_bci = entry_bci;
_link = NULL;
_compiler = compiler;
_orig_pc_offset = orig_pc_offset;
+#ifdef HAVE_DTRACE_H
+ _trap_offset = 0;
+#endif // def HAVE_DTRACE_H
_stub_offset = instructions_offset() + code_buffer->total_offset_of(code_buffer->stubs()->start());
// Exception handler and deopt handler are in the stub section
_exception_offset = _stub_offset + offsets->value(CodeOffsets::Exceptions);
_deoptimize_offset = _stub_offset + offsets->value(CodeOffsets::Deopt);
@@ -708,11 +831,13 @@
assert(compiler->is_c2() ||
_method->is_static() == (entry_point() == _verified_entry_point),
" entry points must be same for static methods and vice versa");
}
- bool printnmethods = PrintNMethods || CompilerOracle::has_option_string(_method, "PrintNMethods");
+ bool printnmethods = PrintNMethods
+ || CompilerOracle::should_print(_method)
+ || CompilerOracle::has_option_string(_method, "PrintNMethods");
if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
print_nmethod(printnmethods);
}
// Note: Do not verify in here as the CodeCache_lock is
@@ -799,11 +924,10 @@
}
}
}
-#ifndef PRODUCT
void nmethod::print_nmethod(bool printmethod) {
ttyLocker ttyl; // keep the following output all in one block
if (xtty != NULL) {
xtty->begin_head("print_nmethod");
xtty->stamp();
@@ -832,11 +956,10 @@
}
if (xtty != NULL) {
xtty->tail("print_nmethod");
}
}
-#endif
void nmethod::set_version(int v) {
flags.version = v;
}
@@ -1228,15 +1351,11 @@
// The oop should be kept alive
keep_alive->do_oop(root);
return false;
}
}
- if (!UseParallelOldGC || !VerifyParallelOldWithMarkSweep) {
- // Cannot do this test if verification of the UseParallelOldGC
- // code using the PSMarkSweep code is being done.
assert(unloading_occurred, "Inconsistency in unloading");
- }
make_unloaded(is_alive, obj);
return true;
}
// ------------------------------------------------------------------
@@ -1871,10 +1990,11 @@
}
}
}
}
+#endif // PRODUCT
// Printing operations
void nmethod::print() const {
ResourceMark rm;
@@ -1885,11 +2005,10 @@
if (is_compiled_by_c1()) {
tty->print("(c1) ");
} else if (is_compiled_by_c2()) {
tty->print("(c2) ");
} else {
- assert(is_native_method(), "Who else?");
tty->print("(nm) ");
}
print_on(tty, "nmethod");
tty->cr();
@@ -1949,10 +2068,18 @@
oops_begin(),
oops_end(),
oops_size());
}
+void nmethod::print_code() {
+ HandleMark hm;
+ ResourceMark m;
+ Disassembler::decode(this);
+}
+
+
+#ifndef PRODUCT
void nmethod::print_scopes() {
// Find the first pc desc for all scopes in the code and print it.
ResourceMark rm;
for (PcDesc* p = scopes_pcs_begin(); p < scopes_pcs_end(); p++) {
@@ -1980,17 +2107,10 @@
deps.log_dependency(); // put it into the xml log also
}
}
-void nmethod::print_code() {
- HandleMark hm;
- ResourceMark m;
- Disassembler().decode(this);
-}
-
-
void nmethod::print_relocations() {
ResourceMark m; // in case methods get printed via the debugger
tty->print_cr("relocations:");
RelocIterator iter(this);
iter.print();
@@ -2022,10 +2142,11 @@
for (PcDesc* p = scopes_pcs_begin(); p < scopes_pcs_end(); p++) {
p->print(this);
}
}
+#endif // PRODUCT
const char* nmethod::reloc_string_for(u_char* begin, u_char* end) {
RelocIterator iter(this, begin, end);
bool have_one = false;
while (iter.next()) {
@@ -2056,11 +2177,10 @@
}
}
return have_one ? "other" : NULL;
}
-
// Return a the last scope in (begin..end]
ScopeDesc* nmethod::scope_desc_in(address begin, address end) {
PcDesc* p = pc_desc_near(begin+1);
if (p != NULL && p->real_pc(this) <= end) {
return new ScopeDesc(this, p->scope_decode_offset(),
@@ -2079,33 +2199,30 @@
for (int i = 0, imax = oms->size(); i < imax; i++) {
OopMap* om = oms->at(i);
address pc = base + om->offset();
if (pc > begin) {
if (pc <= end) {
- st->fill_to(column);
- if (st == tty) {
- st->print("; OopMap ");
- om->print();
- tty->cr();
- } else {
- st->print_cr("; OopMap #%d offset:%d", i, om->offset());
- }
+ st->move_to(column);
+ st->print("; ");
+ om->print_on(st);
}
break;
}
}
}
+
+ // Print any debug info present at this pc.
ScopeDesc* sd = scope_desc_in(begin, end);
if (sd != NULL) {
- st->fill_to(column);
+ st->move_to(column);
if (sd->bci() == SynchronizationEntryBCI) {
st->print(";*synchronization entry");
} else {
if (sd->method().is_null()) {
- tty->print("method is NULL");
+ st->print("method is NULL");
} else if (sd->method()->is_native()) {
- tty->print("method is native");
+ st->print("method is native");
} else {
address bcp = sd->method()->bcp_from(sd->bci());
Bytecodes::Code bc = Bytecodes::java_code_at(bcp);
st->print(";*%s", Bytecodes::name(bc));
switch (bc) {
@@ -2138,17 +2255,17 @@
st->print("<UNKNOWN>");
}
}
}
}
- st->cr();
+
// Print all scopes
for (;sd != NULL; sd = sd->sender()) {
- st->fill_to(column);
+ st->move_to(column);
st->print("; -");
if (sd->method().is_null()) {
- tty->print("method is NULL");
+ st->print("method is NULL");
} else {
sd->method()->print_short_name(st);
}
int lineno = sd->method()->line_number_from_bci(sd->bci());
if (lineno != -1) {
@@ -2162,21 +2279,23 @@
// Print relocation information
const char* str = reloc_string_for(begin, end);
if (str != NULL) {
if (sd != NULL) st->cr();
- st->fill_to(column);
+ st->move_to(column);
st->print("; {%s}", str);
}
int cont_offset = ImplicitExceptionTable(this).at(begin - instructions_begin());
if (cont_offset != 0) {
- st->fill_to(column);
+ st->move_to(column);
st->print("; implicit exception: dispatches to " INTPTR_FORMAT, instructions_begin() + cont_offset);
}
}
+#ifndef PRODUCT
+
void nmethod::print_value_on(outputStream* st) const {
print_on(st, "nmethod");
}
void nmethod::print_calls(outputStream* st) {