提交 191e8e46 编写于 作者: K kamg

Merge

#
# @(#)mapfile-vers-debug 1.18 07/10/25 16:47:35
#
#
# Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
......@@ -75,6 +77,11 @@ SUNWprivate_1.1 {
JVM_DesiredAssertionStatus;
JVM_DisableCompiler;
JVM_DoPrivileged;
JVM_DTraceGetVersion;
JVM_DTraceActivate;
JVM_DTraceIsProbeEnabled;
JVM_DTraceIsSupported;
JVM_DTraceDispose;
JVM_DumpAllStacks;
JVM_DumpThreads;
JVM_EnableCompiler;
......
#
# @(#)mapfile-vers-product 1.19 08/02/12 10:56:37
#
#
# Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
......@@ -75,6 +77,11 @@ SUNWprivate_1.1 {
JVM_DesiredAssertionStatus;
JVM_DisableCompiler;
JVM_DoPrivileged;
JVM_DTraceGetVersion;
JVM_DTraceActivate;
JVM_DTraceIsProbeEnabled;
JVM_DTraceIsSupported;
JVM_DTraceDispose;
JVM_DumpAllStacks;
JVM_DumpThreads;
JVM_EnableCompiler;
......
......@@ -193,10 +193,16 @@ $(DTRACE.o): $(DTRACE).d $(JVMOFFS).h $(JVMOFFS)Index.h $(DTraced_Files)
.PHONY: dtraceCheck
SYSTEM_DTRACE_H = /usr/include/dtrace.h
SYSTEM_DTRACE_PROG = /usr/sbin/dtrace
PATCH_DTRACE_PROG = /opt/SUNWdtrd/sbin/dtrace
systemDtraceFound := $(wildcard ${SYSTEM_DTRACE_PROG})
patchDtraceFound := $(wildcard ${PATCH_DTRACE_PROG})
systemDtraceHdrFound := $(wildcard $(SYSTEM_DTRACE_H))
ifneq ("$(systemDtraceHdrFound)", "")
CFLAGS += -DHAVE_DTRACE_H
endif
ifneq ("$(patchDtraceFound)", "")
DTRACE_PROG=$(PATCH_DTRACE_PROG)
......
#
# @(#)mapfile-vers 1.32 07/10/25 16:47:36
#
#
# Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
......@@ -75,6 +77,11 @@ SUNWprivate_1.1 {
JVM_DesiredAssertionStatus;
JVM_DisableCompiler;
JVM_DoPrivileged;
JVM_DTraceGetVersion;
JVM_DTraceActivate;
JVM_DTraceIsProbeEnabled;
JVM_DTraceIsSupported;
JVM_DTraceDispose;
JVM_DumpAllStacks;
JVM_DumpThreads;
JVM_EnableCompiler;
......
......@@ -26,6 +26,10 @@
# include "incls/_nativeInst_sparc.cpp.incl"
bool NativeInstruction::is_dtrace_trap() {
return !is_nop();
}
void NativeInstruction::set_data64_sethi(address instaddr, intptr_t x) {
ResourceMark rm;
CodeBuffer buf(instaddr, 10 * BytesPerInstWord );
......
......@@ -43,6 +43,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
nop_instruction_size = 4
};
bool is_dtrace_trap();
bool is_nop() { return long_at(0) == nop_instruction(); }
bool is_call() { return is_op(long_at(0), Assembler::call_op); }
bool is_sethi() { return (is_op2(long_at(0), Assembler::sethi_op2)
......
......@@ -472,3 +472,7 @@ address NativeGeneralJump::jump_destination() const {
else
return addr_at(0) + length + sbyte_at(offset);
}
bool NativeInstruction::is_dtrace_trap() {
return (*(int32_t*)this & 0xff) == 0xcc;
}
......@@ -50,6 +50,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
};
bool is_nop() { return ubyte_at(0) == nop_instruction_code; }
bool is_dtrace_trap();
inline bool is_call();
inline bool is_illegal();
inline bool is_return();
......
......@@ -1880,6 +1880,379 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
}
#ifdef HAVE_DTRACE_H
// ---------------------------------------------------------------------------
// Generate a dtrace nmethod for a given signature. The method takes arguments
// in the Java compiled code convention, marshals them to the native
// abi and then leaves nops at the position you would expect to call a native
// function. When the probe is enabled the nops are replaced with a trap
// instruction that dtrace inserts and the trace will cause a notification
// to dtrace.
//
// The probes are only able to take primitive types and java/lang/String as
// arguments. No other java types are allowed. Strings are converted to utf8
// strings so that from dtrace point of view java strings are converted to C
// strings. There is an arbitrary fixed limit on the total space that a method
// can use for converting the strings. (256 chars per string in the signature).
// So any java string larger then this is truncated.
nmethod *SharedRuntime::generate_dtrace_nmethod(
MacroAssembler *masm, methodHandle method) {
// generate_dtrace_nmethod is guarded by a mutex so we are sure to
// be single threaded in this method.
assert(AdapterHandlerLibrary_lock->owned_by_self(), "must be");
// Fill in the signature array, for the calling-convention call.
int total_args_passed = method->size_of_parameters();
BasicType* in_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed);
VMRegPair *in_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed);
// The signature we are going to use for the trap that dtrace will see
// java/lang/String is converted. We drop "this" and any other object
// is converted to NULL. (A one-slot java/lang/Long object reference
// is converted to a two-slot long, which is why we double the allocation).
BasicType* out_sig_bt = NEW_RESOURCE_ARRAY(BasicType, total_args_passed * 2);
VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, total_args_passed * 2);
int i=0;
int total_strings = 0;
int first_arg_to_pass = 0;
int total_c_args = 0;
int box_offset = java_lang_boxing_object::value_offset_in_bytes();
if( !method->is_static() ) { // Pass in receiver first
in_sig_bt[i++] = T_OBJECT;
first_arg_to_pass = 1;
}
// We need to convert the java args to where a native (non-jni) function
// would expect them. To figure out where they go we convert the java
// signature to a C signature.
SignatureStream ss(method->signature());
for ( ; !ss.at_return_type(); ss.next()) {
BasicType bt = ss.type();
in_sig_bt[i++] = bt; // Collect remaining bits of signature
out_sig_bt[total_c_args++] = bt;
if( bt == T_OBJECT) {
symbolOop s = ss.as_symbol_or_null();
if (s == vmSymbols::java_lang_String()) {
total_strings++;
out_sig_bt[total_c_args-1] = T_ADDRESS;
} else if (s == vmSymbols::java_lang_Boolean() ||
s == vmSymbols::java_lang_Character() ||
s == vmSymbols::java_lang_Byte() ||
s == vmSymbols::java_lang_Short() ||
s == vmSymbols::java_lang_Integer() ||
s == vmSymbols::java_lang_Float()) {
out_sig_bt[total_c_args-1] = T_INT;
} else if (s == vmSymbols::java_lang_Long() ||
s == vmSymbols::java_lang_Double()) {
out_sig_bt[total_c_args-1] = T_LONG;
out_sig_bt[total_c_args++] = T_VOID;
}
} else if ( bt == T_LONG || bt == T_DOUBLE ) {
in_sig_bt[i++] = T_VOID; // Longs & doubles take 2 Java slots
out_sig_bt[total_c_args++] = T_VOID;
}
}
assert(i==total_args_passed, "validly parsed signature");
// Now get the compiled-Java layout as input arguments
int comp_args_on_stack;
comp_args_on_stack = SharedRuntime::java_calling_convention(
in_sig_bt, in_regs, total_args_passed, false);
// Now figure out where the args must be stored and how much stack space
// they require (neglecting out_preserve_stack_slots).
int out_arg_slots;
out_arg_slots = c_calling_convention(out_sig_bt, out_regs, total_c_args);
// Calculate the total number of stack slots we will need.
// First count the abi requirement plus all of the outgoing args
int stack_slots = SharedRuntime::out_preserve_stack_slots() + out_arg_slots;
// Now space for the string(s) we must convert
int* string_locs = NEW_RESOURCE_ARRAY(int, total_strings + 1);
for (i = 0; i < total_strings ; i++) {
string_locs[i] = stack_slots;
stack_slots += max_dtrace_string_size / VMRegImpl::stack_slot_size;
}
// + 2 for return address (which we own) and saved rbp,
stack_slots += 2;
// Ok The space we have allocated will look like:
//
//
// FP-> | |
// |---------------------|
// | string[n] |
// |---------------------| <- string_locs[n]
// | string[n-1] |
// |---------------------| <- string_locs[n-1]
// | ... |
// | ... |
// |---------------------| <- string_locs[1]
// | string[0] |
// |---------------------| <- string_locs[0]
// | outbound memory |
// | based arguments |
// | |
// |---------------------|
// | |
// SP-> | out_preserved_slots |
//
//
// Now compute actual number of stack words we need rounding to make
// stack properly aligned.
stack_slots = round_to(stack_slots, 2 * VMRegImpl::slots_per_word);
int stack_size = stack_slots * VMRegImpl::stack_slot_size;
intptr_t start = (intptr_t)__ pc();
// First thing make an ic check to see if we should even be here
// We are free to use all registers as temps without saving them and
// restoring them except rbp. rbp, is the only callee save register
// as far as the interpreter and the compiler(s) are concerned.
const Register ic_reg = rax;
const Register receiver = rcx;
Label hit;
Label exception_pending;
__ verify_oop(receiver);
__ cmpl(ic_reg, Address(receiver, oopDesc::klass_offset_in_bytes()));
__ jcc(Assembler::equal, hit);
__ jump(RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
// verified entry must be aligned for code patching.
// and the first 5 bytes must be in the same cache line
// if we align at 8 then we will be sure 5 bytes are in the same line
__ align(8);
__ bind(hit);
int vep_offset = ((intptr_t)__ pc()) - start;
// The instruction at the verified entry point must be 5 bytes or longer
// because it can be patched on the fly by make_non_entrant. The stack bang
// instruction fits that requirement.
// Generate stack overflow check
if (UseStackBanging) {
if (stack_size <= StackShadowPages*os::vm_page_size()) {
__ bang_stack_with_offset(StackShadowPages*os::vm_page_size());
} else {
__ movl(rax, stack_size);
__ bang_stack_size(rax, rbx);
}
} else {
// need a 5 byte instruction to allow MT safe patching to non-entrant
__ fat_nop();
}
assert(((int)__ pc() - start - vep_offset) >= 5,
"valid size for make_non_entrant");
// Generate a new frame for the wrapper.
__ enter();
// -2 because return address is already present and so is saved rbp,
if (stack_size - 2*wordSize != 0) {
__ subl(rsp, stack_size - 2*wordSize);
}
// Frame is now completed as far a size and linkage.
int frame_complete = ((intptr_t)__ pc()) - start;
// First thing we do store all the args as if we are doing the call.
// Since the C calling convention is stack based that ensures that
// all the Java register args are stored before we need to convert any
// string we might have.
int sid = 0;
int c_arg, j_arg;
int string_reg = 0;
for (j_arg = first_arg_to_pass, c_arg = 0 ;
j_arg < total_args_passed ; j_arg++, c_arg++ ) {
VMRegPair src = in_regs[j_arg];
VMRegPair dst = out_regs[c_arg];
assert(dst.first()->is_stack() || in_sig_bt[j_arg] == T_VOID,
"stack based abi assumed");
switch (in_sig_bt[j_arg]) {
case T_ARRAY:
case T_OBJECT:
if (out_sig_bt[c_arg] == T_ADDRESS) {
// Any register based arg for a java string after the first
// will be destroyed by the call to get_utf so we store
// the original value in the location the utf string address
// will eventually be stored.
if (src.first()->is_reg()) {
if (string_reg++ != 0) {
simple_move32(masm, src, dst);
}
}
} else if (out_sig_bt[c_arg] == T_INT || out_sig_bt[c_arg] == T_LONG) {
// need to unbox a one-word value
Register in_reg = rax;
if ( src.first()->is_reg() ) {
in_reg = src.first()->as_Register();
} else {
simple_move32(masm, src, in_reg->as_VMReg());
}
Label skipUnbox;
__ movl(Address(rsp, reg2offset_out(dst.first())), NULL_WORD);
if ( out_sig_bt[c_arg] == T_LONG ) {
__ movl(Address(rsp, reg2offset_out(dst.second())), NULL_WORD);
}
__ testl(in_reg, in_reg);
__ jcc(Assembler::zero, skipUnbox);
assert(dst.first()->is_stack() &&
(!dst.second()->is_valid() || dst.second()->is_stack()),
"value(s) must go into stack slots");
if ( out_sig_bt[c_arg] == T_LONG ) {
__ movl(rbx, Address(in_reg,
box_offset + VMRegImpl::stack_slot_size));
__ movl(Address(rsp, reg2offset_out(dst.second())), rbx);
}
__ movl(in_reg, Address(in_reg, box_offset));
__ movl(Address(rsp, reg2offset_out(dst.first())), in_reg);
__ bind(skipUnbox);
} else {
// Convert the arg to NULL
__ movl(Address(rsp, reg2offset_out(dst.first())), NULL_WORD);
}
if (out_sig_bt[c_arg] == T_LONG) {
assert(out_sig_bt[c_arg+1] == T_VOID, "must be");
++c_arg; // Move over the T_VOID To keep the loop indices in sync
}
break;
case T_VOID:
break;
case T_FLOAT:
float_move(masm, src, dst);
break;
case T_DOUBLE:
assert( j_arg + 1 < total_args_passed &&
in_sig_bt[j_arg + 1] == T_VOID, "bad arg list");
double_move(masm, src, dst);
break;
case T_LONG :
long_move(masm, src, dst);
break;
case T_ADDRESS: assert(false, "found T_ADDRESS in java args");
default:
simple_move32(masm, src, dst);
}
}
// Now we must convert any string we have to utf8
//
for (sid = 0, j_arg = first_arg_to_pass, c_arg = 0 ;
sid < total_strings ; j_arg++, c_arg++ ) {
if (out_sig_bt[c_arg] == T_ADDRESS) {
Address utf8_addr = Address(
rsp, string_locs[sid++] * VMRegImpl::stack_slot_size);
__ leal(rax, utf8_addr);
// The first string we find might still be in the original java arg
// register
VMReg orig_loc = in_regs[j_arg].first();
Register string_oop;
// This is where the argument will eventually reside
Address dest = Address(rsp, reg2offset_out(out_regs[c_arg].first()));
if (sid == 1 && orig_loc->is_reg()) {
string_oop = orig_loc->as_Register();
assert(string_oop != rax, "smashed arg");
} else {
if (orig_loc->is_reg()) {
// Get the copy of the jls object
__ movl(rcx, dest);
} else {
// arg is still in the original location
__ movl(rcx, Address(rbp, reg2offset_in(orig_loc)));
}
string_oop = rcx;
}
Label nullString;
__ movl(dest, NULL_WORD);
__ testl(string_oop, string_oop);
__ jcc(Assembler::zero, nullString);
// Now we can store the address of the utf string as the argument
__ movl(dest, rax);
// And do the conversion
__ call_VM_leaf(CAST_FROM_FN_PTR(
address, SharedRuntime::get_utf), string_oop, rax);
__ bind(nullString);
}
if (in_sig_bt[j_arg] == T_OBJECT && out_sig_bt[c_arg] == T_LONG) {
assert(out_sig_bt[c_arg+1] == T_VOID, "must be");
++c_arg; // Move over the T_VOID To keep the loop indices in sync
}
}
// Ok now we are done. Need to place the nop that dtrace wants in order to
// patch in the trap
int patch_offset = ((intptr_t)__ pc()) - start;
__ nop();
// Return
__ leave();
__ ret(0);
__ flush();
nmethod *nm = nmethod::new_dtrace_nmethod(
method, masm->code(), vep_offset, patch_offset, frame_complete,
stack_slots / VMRegImpl::slots_per_word);
return nm;
}
#endif // HAVE_DTRACE_H
// this function returns the adjust size (in number of words) to a c2i adapter
// activation for use during deoptimization
int Deoptimization::last_frame_adjust(int callee_parameters, int callee_locals ) {
......
/*
* Copyright 1997-2007 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.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
#include "incls/_precompiled.incl"
#include "incls/_dtraceJSDT_linux.cpp.incl"
int DTraceJSDT::pd_activate(
void* baseAddress, jstring module,
jint providers_count, JVM_DTraceProvider* providers) {
return -1;
}
void DTraceJSDT::pd_dispose(int handle) {
}
jboolean DTraceJSDT::pd_is_supported() {
return false;
}
此差异已折叠。
/*
* Copyright 1997-2007 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.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
#include "incls/_precompiled.incl"
#include "incls/_dtraceJSDT_windows.cpp.incl"
int DTraceJSDT::pd_activate(
void* baseAddress, jstring module,
jint providers_count, JVM_DTraceProvider* providers) {
return -1;
}
void DTraceJSDT::pd_dispose(int handle) {
}
jboolean DTraceJSDT::pd_is_supported() {
return false;
}
......@@ -36,6 +36,7 @@ public:
Verified_Entry,
Frame_Complete, // Offset in the code where the frame setup is (for forte stackwalks) is complete
OSR_Entry,
Dtrace_trap = OSR_Entry, // dtrace probes can never have an OSR entry so reuse it
Exceptions, // Offset where exception handler lives
Deopt, // Offset where deopt handler lives
max_Entries };
......
......@@ -27,7 +27,6 @@
#ifdef DTRACE_ENABLED
// Only bother with this argument setup if dtrace is available
HS_DTRACE_PROBE_DECL8(hotspot, compiled__method__load,
......@@ -438,7 +437,6 @@ nmethod* nmethod::new_native_nmethod(methodHandle method,
{
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);
......@@ -461,6 +459,41 @@ nmethod* nmethod::new_native_nmethod(methodHandle method,
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,
......@@ -558,6 +591,9 @@ nmethod::nmethod(
_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();
......@@ -615,6 +651,90 @@ nmethod::nmethod(
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
......@@ -658,6 +778,9 @@ nmethod::nmethod(
_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
......@@ -1885,7 +2008,6 @@ void nmethod::print() const {
} else if (is_compiled_by_c2()) {
tty->print("(c2) ");
} else {
assert(is_native_method(), "Who else?");
tty->print("(nm) ");
}
......
......@@ -140,6 +140,9 @@ class nmethod : public CodeBlob {
int _exception_offset;
// All deoptee's will resume execution at this location described by this offset
int _deoptimize_offset;
#ifdef HAVE_DTRACE_H
int _trap_offset;
#endif // def HAVE_DTRACE_H
int _stub_offset;
int _consts_offset;
int _scopes_data_offset;
......@@ -211,6 +214,15 @@ class nmethod : public CodeBlob {
ByteSize basic_lock_sp_offset, /* synchronized natives only */
OopMapSet* oop_maps);
#ifdef HAVE_DTRACE_H
// For native wrappers
nmethod(methodOop method,
int nmethod_size,
CodeOffsets* offsets,
CodeBuffer *code_buffer,
int frame_size);
#endif // def HAVE_DTRACE_H
// Creation support
nmethod(methodOop method,
int nmethod_size,
......@@ -272,6 +284,22 @@ class nmethod : public CodeBlob {
ByteSize basic_lock_sp_offset,
OopMapSet* oop_maps);
#ifdef HAVE_DTRACE_H
// The method we generate for a dtrace probe has to look
// like an nmethod as far as the rest of the system is concerned
// which is somewhat unfortunate.
static nmethod* new_dtrace_nmethod(methodHandle method,
CodeBuffer *code_buffer,
int vep_offset,
int trap_offset,
int frame_complete,
int frame_size);
int trap_offset() const { return _trap_offset; }
address trap_address() const { return code_begin() + _trap_offset; }
#endif // def HAVE_DTRACE_H
// accessors
methodOop method() const { return _method; }
AbstractCompiler* compiler() const { return _compiler; }
......
......@@ -1497,6 +1497,30 @@ dtraceAttacher.cpp resourceArea.hpp
dtraceAttacher.cpp vmThread.hpp
dtraceAttacher.cpp vm_operations.hpp
dtraceJSDT.cpp allocation.hpp
dtraceJSDT.cpp codeBlob.hpp
dtraceJSDT.cpp dtraceJSDT.hpp
dtraceJSDT.cpp exceptions.hpp
dtraceJSDT.cpp globalDefinitions.hpp
dtraceJSDT.cpp javaClasses.hpp
dtraceJSDT.cpp jniHandles.hpp
dtraceJSDT.cpp jvm.h
dtraceJSDT.cpp os.hpp
dtraceJSDT.cpp utf8.hpp
dtraceJSDT.hpp nativeInst_<arch>.hpp
dtraceJSDT.hpp nmethod.hpp
dtraceJSDT_<os_family>.cpp allocation.hpp
dtraceJSDT_<os_family>.cpp codeBlob.hpp
dtraceJSDT_<os_family>.cpp dtraceJSDT.hpp
dtraceJSDT_<os_family>.cpp globalDefinitions.hpp
dtraceJSDT_<os_family>.cpp javaClasses.hpp
dtraceJSDT_<os_family>.cpp jniHandles.hpp
dtraceJSDT_<os_family>.cpp jvm.h
dtraceJSDT_<os_family>.cpp os.hpp
dtraceJSDT_<os_family>.cpp signature.hpp
// dump is jck optional, put cpp deps in includeDB_features
events.cpp allocation.inline.hpp
......@@ -2400,6 +2424,7 @@ jvm.cpp classLoader.hpp
jvm.cpp collectedHeap.inline.hpp
jvm.cpp copy.hpp
jvm.cpp defaultStream.hpp
jvm.cpp dtraceJSDT.hpp
jvm.cpp events.hpp
jvm.cpp handles.inline.hpp
jvm.cpp histogram.hpp
......
......@@ -672,9 +672,6 @@ void methodOopDesc::link_method(methodHandle h_method, TRAPS) {
}
address methodOopDesc::make_adapters(methodHandle mh, TRAPS) {
// If running -Xint we need no adapters.
if (Arguments::mode() == Arguments::_int) return NULL;
// Adapters for compiled code are made eagerly here. They are fairly
// small (generally < 100 bytes) and quick to make (and cached and shared)
// so making them eagerly shouldn't be too expensive.
......
......@@ -4168,6 +4168,36 @@ JVM_ENTRY(jboolean, JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fid, jlong o
return res == oldVal;
JVM_END
// DTrace ///////////////////////////////////////////////////////////////////
JVM_ENTRY(jint, JVM_DTraceGetVersion(JNIEnv* env))
JVMWrapper("JVM_DTraceGetVersion");
return (jint)JVM_TRACING_DTRACE_VERSION;
JVM_END
JVM_ENTRY(jlong,JVM_DTraceActivate(
JNIEnv* env, jint version, jstring module_name, jint providers_count,
JVM_DTraceProvider* providers))
JVMWrapper("JVM_DTraceActivate");
return DTraceJSDT::activate(
version, module_name, providers_count, providers, CHECK_0);
JVM_END
JVM_ENTRY(jboolean,JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method))
JVMWrapper("JVM_DTraceIsProbeEnabled");
return DTraceJSDT::is_probe_enabled(method);
JVM_END
JVM_ENTRY(void,JVM_DTraceDispose(JNIEnv* env, jlong handle))
JVMWrapper("JVM_DTraceDispose");
DTraceJSDT::dispose(handle);
JVM_END
JVM_ENTRY(jboolean,JVM_DTraceIsSupported(JNIEnv* env))
JVMWrapper("JVM_DTraceIsSupported");
return DTraceJSDT::is_supported();
JVM_END
// Returns an array of all live Thread objects (VM internal JavaThreads,
// jvmti agent threads, and JNI attaching threads are skipped)
// See CR 6404306 regarding JNI attaching threads
......@@ -4496,3 +4526,4 @@ JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t i
#endif // KERNEL
}
JVM_END
......@@ -606,6 +606,83 @@ JVM_SupportsCX8(void);
JNIEXPORT jboolean JNICALL
JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fldID, jlong oldVal, jlong newVal);
/*
* com.sun.dtrace.jsdt support
*/
#define JVM_TRACING_DTRACE_VERSION 1
/*
* Structure to pass one probe description to JVM.
*
* The VM will overwrite the definition of the referenced method with
* code that will fire the probe.
*/
typedef struct {
jmethodID method;
jstring function;
jstring name;
void* reserved[4]; // for future use
} JVM_DTraceProbe;
/**
* Encapsulates the stability ratings for a DTrace provider field
*/
typedef struct {
jint nameStability;
jint dataStability;
jint dependencyClass;
} JVM_DTraceInterfaceAttributes;
/*
* Structure to pass one provider description to JVM
*/
typedef struct {
jstring name;
JVM_DTraceProbe* probes;
jint probe_count;
JVM_DTraceInterfaceAttributes providerAttributes;
JVM_DTraceInterfaceAttributes moduleAttributes;
JVM_DTraceInterfaceAttributes functionAttributes;
JVM_DTraceInterfaceAttributes nameAttributes;
JVM_DTraceInterfaceAttributes argsAttributes;
void* reserved[4]; // for future use
} JVM_DTraceProvider;
/*
* Get the version number the JVM was built with
*/
JNIEXPORT jint JNICALL
JVM_DTraceGetVersion(JNIEnv* env);
/*
* Register new probe with given signature, return global handle
*
* The version passed in is the version that the library code was
* built with.
*/
JNIEXPORT jlong JNICALL
JVM_DTraceActivate(JNIEnv* env, jint version, jstring module_name,
jint providers_count, JVM_DTraceProvider* providers);
/*
* Check JSDT probe
*/
JNIEXPORT jboolean JNICALL
JVM_DTraceIsProbeEnabled(JNIEnv* env, jmethodID method);
/*
* Destroy custom DOF
*/
JNIEXPORT void JNICALL
JVM_DTraceDispose(JNIEnv* env, jlong handle);
/*
* Check to see if DTrace is supported by OS
*/
JNIEXPORT jboolean JNICALL
JVM_DTraceIsSupported(JNIEnv* env);
/*************************************************************************
PART 2: Support for the Verifier and Class File Format Checker
************************************************************************/
......
/*
* Copyright 1997-2007 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.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
#include "incls/_precompiled.incl"
#include "incls/_dtraceJSDT.cpp.incl"
#ifdef HAVE_DTRACE_H
jlong DTraceJSDT::activate(
jint version, jstring module_name, jint providers_count,
JVM_DTraceProvider* providers, TRAPS) {
size_t count = 0;
RegisteredProbes* probes = NULL;
if (!is_supported()) {
return 0;
}
assert(module_name != NULL, "valid module name");
assert(providers != NULL, "valid provider array");
for (int i = 0; i < providers_count; ++i) {
count += providers[i].probe_count;
}
probes = new RegisteredProbes(count);
count = 0;
for (int i = 0; i < providers_count; ++i) {
assert(providers[i].name != NULL, "valid provider name");
assert(providers[i].probe_count == 0 || providers[i].probes != NULL,
"valid probe count");
for (int j = 0; j < providers[i].probe_count; ++j) {
JVM_DTraceProbe* probe = &(providers[i].probes[j]);
assert(probe != NULL, "valid probe");
assert(probe->method != NULL, "valid method");
assert(probe->name != NULL, "valid probe name");
assert(probe->function != NULL, "valid probe function spec");
methodHandle h_method =
methodHandle(THREAD, JNIHandles::resolve_jmethod_id(probe->method));
nmethod* nm = AdapterHandlerLibrary::create_dtrace_nmethod(h_method);
h_method()->set_not_compilable(CompLevel_highest_tier);
h_method()->set_code(h_method, nm);
probes->nmethod_at_put(count++, nm);
}
}
int handle = pd_activate((void*)probes,
module_name, providers_count, providers);
if (handle <= 0) {
delete probes;
THROW_MSG_0(vmSymbols::java_lang_RuntimeException(),
"Unable to register DTrace probes (internal error).");
}
probes->set_helper_handle(handle);
return RegisteredProbes::toOpaqueProbes(probes);
}
jboolean DTraceJSDT::is_probe_enabled(jmethodID method) {
methodOop m = JNIHandles::resolve_jmethod_id(method);
return nativeInstruction_at(m->code()->trap_address())->is_dtrace_trap();
}
void DTraceJSDT::dispose(OpaqueProbes probes) {
RegisteredProbes* p = RegisteredProbes::toRegisteredProbes(probes);
if (probes != -1 && p != NULL) {
pd_dispose(p->helper_handle());
delete p;
}
}
jboolean DTraceJSDT::is_supported() {
return pd_is_supported();
}
#else // HAVE_DTRACE_H
jlong DTraceJSDT::activate(
jint version, jstring module_name, jint providers_count,
JVM_DTraceProvider* providers, TRAPS) {
return 0;
}
jboolean DTraceJSDT::is_probe_enabled(jmethodID method) {
return false;
}
void DTraceJSDT::dispose(OpaqueProbes probes) {
return;
}
jboolean DTraceJSDT::is_supported() {
return false;
}
#endif // ndef HAVE_DTRACE_H
/*
* Copyright 1997-2007 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.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
class RegisteredProbes;
typedef jlong OpaqueProbes;
class DTraceJSDT : AllStatic {
private:
static int pd_activate(void* moduleBaseAddress, jstring module,
jint providers_count, JVM_DTraceProvider* providers);
static void pd_dispose(int handle);
static jboolean pd_is_supported();
public:
static OpaqueProbes activate(
jint version, jstring module_name, jint providers_count,
JVM_DTraceProvider* providers, TRAPS);
static jboolean is_probe_enabled(jmethodID method);
static void dispose(OpaqueProbes handle);
static jboolean is_supported();
};
class RegisteredProbes : public CHeapObj {
private:
nmethod** _nmethods; // all the probe methods
size_t _count; // number of probe methods
int _helper_handle; // DTrace-assigned identifier
public:
RegisteredProbes(size_t count) {
_count = count;
_nmethods = NEW_C_HEAP_ARRAY(nmethod*, count);
}
~RegisteredProbes() {
for (size_t i = 0; i < _count; ++i) {
// Let the sweeper reclaim it
_nmethods[i]->make_not_entrant();
_nmethods[i]->method()->clear_code();
}
FREE_C_HEAP_ARRAY(nmethod*, _nmethods);
_nmethods = NULL;
_count = 0;
}
static RegisteredProbes* toRegisteredProbes(OpaqueProbes p) {
return (RegisteredProbes*)(intptr_t)p;
}
static OpaqueProbes toOpaqueProbes(RegisteredProbes* p) {
return (OpaqueProbes)(intptr_t)p;
}
void set_helper_handle(int handle) { _helper_handle = handle; }
int helper_handle() const { return _helper_handle; }
nmethod* nmethod_at(size_t i) {
assert(i >= 0 && i < _count, "bad nmethod index");
return _nmethods[i];
}
void nmethod_at_put(size_t i, nmethod* nm) {
assert(i >= 0 && i < _count, "bad nmethod index");
_nmethods[i] = nm;
}
};
......@@ -3188,6 +3188,9 @@ class CommandLineFlags {
product(bool, RelaxAccessControlCheck, false, \
"Relax the access control checks in the verifier") \
\
diagnostic(bool, PrintDTraceDOF, false, \
"Print the DTrace DOF passed to the system for JSDT probes") \
\
product(bool, UseVMInterruptibleIO, true, \
"(Unstable, Solaris-specific) Thread interrupt before or with " \
"EINTR for I/O operations results in OS_INTRPT")
......
......@@ -500,7 +500,8 @@ bool Reflection::verify_field_access(klassOop current_class,
if (!protected_restriction) {
// See if current_class is a subclass of field_class
if (Klass::cast(current_class)->is_subclass_of(field_class)) {
if (current_class == resolved_class ||
if (access.is_static() || // static fields are ok, see 6622385
current_class == resolved_class ||
field_class == resolved_class ||
Klass::cast(current_class)->is_subclass_of(resolved_class) ||
Klass::cast(resolved_class)->is_subclass_of(current_class)) {
......
......@@ -1748,11 +1748,6 @@ int AdapterHandlerLibrary::get_create_adapter_index(methodHandle method) {
// _fingerprints array (it is not safe for concurrent readers and a single
// writer: this can be fixed if it becomes a problem).
// Shouldn't be here if running -Xint
if (Arguments::mode() == Arguments::_int) {
ShouldNotReachHere();
}
// Get the address of the ic_miss handlers before we grab the
// AdapterHandlerLibrary_lock. This fixes bug 6236259 which
// was caused by the initialization of the stubs happening
......@@ -1997,6 +1992,64 @@ nmethod *AdapterHandlerLibrary::create_native_wrapper(methodHandle method) {
return nm;
}
#ifdef HAVE_DTRACE_H
// Create a dtrace nmethod for this method. The wrapper converts the
// java compiled calling convention to the native convention, makes a dummy call
// (actually nops for the size of the call instruction, which become a trap if
// probe is enabled). The returns to the caller. Since this all looks like a
// leaf no thread transition is needed.
nmethod *AdapterHandlerLibrary::create_dtrace_nmethod(methodHandle method) {
ResourceMark rm;
nmethod* nm = NULL;
if (PrintCompilation) {
ttyLocker ttyl;
tty->print("--- n%s ");
method->print_short_name(tty);
if (method->is_static()) {
tty->print(" (static)");
}
tty->cr();
}
{
// perform the work while holding the lock, but perform any printing
// outside the lock
MutexLocker mu(AdapterHandlerLibrary_lock);
// See if somebody beat us to it
nm = method->code();
if (nm) {
return nm;
}
// Improve alignment slightly
u_char* buf = (u_char*)
(((intptr_t)_buffer + CodeEntryAlignment-1) & ~(CodeEntryAlignment-1));
CodeBuffer buffer(buf, AdapterHandlerLibrary_size);
// Need a few relocation entries
double locs_buf[20];
buffer.insts()->initialize_shared_locs(
(relocInfo*)locs_buf, sizeof(locs_buf) / sizeof(relocInfo));
MacroAssembler _masm(&buffer);
// Generate the compiled-to-native wrapper code
nm = SharedRuntime::generate_dtrace_nmethod(&_masm, method);
}
return nm;
}
// the dtrace method needs to convert java lang string to utf8 string.
void SharedRuntime::get_utf(oopDesc* src, address dst) {
typeArrayOop jlsValue = java_lang_String::value(src);
int jlsOffset = java_lang_String::offset(src);
int jlsLen = java_lang_String::length(src);
jchar* jlsPos = (jlsLen == 0) ? NULL :
jlsValue->char_at_addr(jlsOffset);
(void) UNICODE::as_utf8(jlsPos, jlsLen, (char *)dst, max_dtrace_string_size);
}
#endif // ndef HAVE_DTRACE_H
// -------------------------------------------------------------------------
// Java-Java calling convention
// (what you use when Java calls Java)
......
......@@ -59,6 +59,10 @@ class SharedRuntime: AllStatic {
#endif // !PRODUCT
public:
// max bytes for each dtrace string parameter
enum { max_dtrace_string_size = 256 };
// The following arithmetic routines are used on platforms that do
// not have machine instructions to implement their functionality.
// Do not remove these.
......@@ -258,9 +262,6 @@ class SharedRuntime: AllStatic {
public:
static void create_native_wrapper (JavaThread* thread, methodOop method);
// Read the array of BasicTypes from a Java signature, and compute where
// compiled Java code would like to put the results. Values in reg_lo and
// reg_hi refer to 4-byte quantities. Values less than SharedInfo::stack0 are
......@@ -354,6 +355,19 @@ class SharedRuntime: AllStatic {
VMRegPair *regs,
BasicType ret_type );
#ifdef HAVE_DTRACE_H
// Generate a dtrace wrapper for a given method. The method takes arguments
// in the Java compiled code convention, marshals them to the native
// convention (handlizes oops, etc), transitions to native, makes the call,
// returns to java state (possibly blocking), unhandlizes any result and
// returns.
static nmethod *generate_dtrace_nmethod(MacroAssembler* masm,
methodHandle method);
// dtrace support to convert a Java string to utf8
static void get_utf(oopDesc* src, address dst);
#endif // def HAVE_DTRACE_H
// A compiled caller has just called the interpreter, but compiled code
// exists. Patch the caller so he no longer calls into the interpreter.
static void fixup_callers_callsite(methodOopDesc* moop, address ret_pc);
......@@ -492,42 +506,55 @@ class AdapterHandlerEntry : public CHeapObj {
address _c2i_unverified_entry;
public:
// The name we give all buffer blobs
static const char* name;
AdapterHandlerEntry(address i2c_entry, address c2i_entry, address c2i_unverified_entry):
_i2c_entry(i2c_entry),
_c2i_entry(c2i_entry),
_c2i_unverified_entry(c2i_unverified_entry) {
}
// The name we give all buffer blobs
static const char* name;
address get_i2c_entry() { return _i2c_entry; }
address get_c2i_entry() { return _c2i_entry; }
address get_c2i_unverified_entry() { return _c2i_unverified_entry; }
void relocate(address new_base);
#ifndef PRODUCT
void print();
#endif /* PRODUCT */
};
class AdapterHandlerLibrary: public AllStatic {
private:
static u_char _buffer[]; // the temporary code buffer
static GrowableArray<uint64_t>* _fingerprints; // the fingerprint collection
static GrowableArray<AdapterHandlerEntry*> * _handlers; // the corresponding handlers
enum {
AbstractMethodHandler = 1 // special handler for abstract methods
};
static GrowableArray<uint64_t>* _fingerprints; // the fingerprint collection
static GrowableArray<AdapterHandlerEntry*> * _handlers; // the corresponding handlers
static u_char _buffer[]; // the temporary code buffer
static void initialize();
static AdapterHandlerEntry* get_entry( int index ) { return _handlers->at(index); }
static int get_create_adapter_index(methodHandle method);
static address get_i2c_entry( int index ) { return get_entry(index)->get_i2c_entry(); }
static address get_c2i_entry( int index ) { return get_entry(index)->get_c2i_entry(); }
static address get_c2i_unverified_entry( int index ) { return get_entry(index)->get_c2i_unverified_entry(); }
static address get_i2c_entry( int index ) {
return get_entry(index)->get_i2c_entry();
}
static address get_c2i_entry( int index ) {
return get_entry(index)->get_c2i_entry();
}
static address get_c2i_unverified_entry( int index ) {
return get_entry(index)->get_c2i_unverified_entry();
}
public:
static AdapterHandlerEntry* get_entry( int index ) { return _handlers->at(index); }
static nmethod* create_native_wrapper(methodHandle method);
static AdapterHandlerEntry* get_adapter(methodHandle method) { return get_entry(get_create_adapter_index(method)); }
static AdapterHandlerEntry* get_adapter(methodHandle method) {
return get_entry(get_create_adapter_index(method));
}
#ifdef HAVE_DTRACE_H
static nmethod* create_dtrace_nmethod (methodHandle method);
#endif // HAVE_DTRACE_H
#ifndef PRODUCT
static void print_handler(CodeBlob* b);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册