Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
15eb4e64
D
dragonwell8_hotspot
项目概览
openanolis
/
dragonwell8_hotspot
通知
2
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_hotspot
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
15eb4e64
编写于
4月 17, 2008
作者:
K
kamg
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
Summary: Initial checkin of JSDT code Reviewed-by: acorn, sbohne
上级
058d3774
变更
26
隐藏空白更改
内联
并排
Showing
26 changed file
with
2935 addition
and
26 deletion
+2935
-26
make/linux/makefiles/mapfile-vers-debug
make/linux/makefiles/mapfile-vers-debug
+7
-0
make/linux/makefiles/mapfile-vers-product
make/linux/makefiles/mapfile-vers-product
+7
-0
make/solaris/makefiles/dtrace.make
make/solaris/makefiles/dtrace.make
+6
-0
make/solaris/makefiles/mapfile-vers
make/solaris/makefiles/mapfile-vers
+7
-0
src/cpu/sparc/vm/nativeInst_sparc.cpp
src/cpu/sparc/vm/nativeInst_sparc.cpp
+4
-0
src/cpu/sparc/vm/nativeInst_sparc.hpp
src/cpu/sparc/vm/nativeInst_sparc.hpp
+1
-0
src/cpu/sparc/vm/sharedRuntime_sparc.cpp
src/cpu/sparc/vm/sharedRuntime_sparc.cpp
+546
-1
src/cpu/x86/vm/nativeInst_x86.cpp
src/cpu/x86/vm/nativeInst_x86.cpp
+4
-0
src/cpu/x86/vm/nativeInst_x86.hpp
src/cpu/x86/vm/nativeInst_x86.hpp
+1
-0
src/cpu/x86/vm/sharedRuntime_x86_32.cpp
src/cpu/x86/vm/sharedRuntime_x86_32.cpp
+373
-0
src/cpu/x86/vm/sharedRuntime_x86_64.cpp
src/cpu/x86/vm/sharedRuntime_x86_64.cpp
+621
-0
src/os/linux/vm/dtraceJSDT_linux.cpp
src/os/linux/vm/dtraceJSDT_linux.cpp
+39
-0
src/os/solaris/vm/dtraceJSDT_solaris.cpp
src/os/solaris/vm/dtraceJSDT_solaris.cpp
+685
-0
src/os/windows/vm/dtraceJSDT_windows.cpp
src/os/windows/vm/dtraceJSDT_windows.cpp
+39
-0
src/share/vm/asm/codeBuffer.hpp
src/share/vm/asm/codeBuffer.hpp
+1
-0
src/share/vm/code/nmethod.cpp
src/share/vm/code/nmethod.cpp
+125
-3
src/share/vm/code/nmethod.hpp
src/share/vm/code/nmethod.hpp
+28
-0
src/share/vm/includeDB_core
src/share/vm/includeDB_core
+25
-0
src/share/vm/oops/methodOop.cpp
src/share/vm/oops/methodOop.cpp
+0
-3
src/share/vm/prims/jvm.cpp
src/share/vm/prims/jvm.cpp
+31
-0
src/share/vm/prims/jvm.h
src/share/vm/prims/jvm.h
+77
-0
src/share/vm/runtime/dtraceJSDT.cpp
src/share/vm/runtime/dtraceJSDT.cpp
+117
-0
src/share/vm/runtime/dtraceJSDT.hpp
src/share/vm/runtime/dtraceJSDT.hpp
+89
-0
src/share/vm/runtime/globals.hpp
src/share/vm/runtime/globals.hpp
+3
-0
src/share/vm/runtime/sharedRuntime.cpp
src/share/vm/runtime/sharedRuntime.cpp
+58
-5
src/share/vm/runtime/sharedRuntime.hpp
src/share/vm/runtime/sharedRuntime.hpp
+41
-14
未找到文件。
make/linux/makefiles/mapfile-vers-debug
浏览文件 @
15eb4e64
#
#
# @(#)mapfile-vers-debug 1.18 07/10/25 16:47:35
#
#
#
# Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
# Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
...
@@ -75,6 +77,11 @@ SUNWprivate_1.1 {
...
@@ -75,6 +77,11 @@ SUNWprivate_1.1 {
JVM_DesiredAssertionStatus;
JVM_DesiredAssertionStatus;
JVM_DisableCompiler;
JVM_DisableCompiler;
JVM_DoPrivileged;
JVM_DoPrivileged;
JVM_DTraceGetVersion;
JVM_DTraceActivate;
JVM_DTraceIsProbeEnabled;
JVM_DTraceIsSupported;
JVM_DTraceDispose;
JVM_DumpAllStacks;
JVM_DumpAllStacks;
JVM_DumpThreads;
JVM_DumpThreads;
JVM_EnableCompiler;
JVM_EnableCompiler;
...
...
make/linux/makefiles/mapfile-vers-product
浏览文件 @
15eb4e64
#
#
# @(#)mapfile-vers-product 1.19 08/02/12 10:56:37
#
#
#
# Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
# Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved.
...
@@ -75,6 +77,11 @@ SUNWprivate_1.1 {
...
@@ -75,6 +77,11 @@ SUNWprivate_1.1 {
JVM_DesiredAssertionStatus;
JVM_DesiredAssertionStatus;
JVM_DisableCompiler;
JVM_DisableCompiler;
JVM_DoPrivileged;
JVM_DoPrivileged;
JVM_DTraceGetVersion;
JVM_DTraceActivate;
JVM_DTraceIsProbeEnabled;
JVM_DTraceIsSupported;
JVM_DTraceDispose;
JVM_DumpAllStacks;
JVM_DumpAllStacks;
JVM_DumpThreads;
JVM_DumpThreads;
JVM_EnableCompiler;
JVM_EnableCompiler;
...
...
make/solaris/makefiles/dtrace.make
浏览文件 @
15eb4e64
...
@@ -193,10 +193,16 @@ $(DTRACE.o): $(DTRACE).d $(JVMOFFS).h $(JVMOFFS)Index.h $(DTraced_Files)
...
@@ -193,10 +193,16 @@ $(DTRACE.o): $(DTRACE).d $(JVMOFFS).h $(JVMOFFS)Index.h $(DTraced_Files)
.PHONY
:
dtraceCheck
.PHONY
:
dtraceCheck
SYSTEM_DTRACE_H
=
/usr/include/dtrace.h
SYSTEM_DTRACE_PROG
=
/usr/sbin/dtrace
SYSTEM_DTRACE_PROG
=
/usr/sbin/dtrace
PATCH_DTRACE_PROG
=
/opt/SUNWdtrd/sbin/dtrace
PATCH_DTRACE_PROG
=
/opt/SUNWdtrd/sbin/dtrace
systemDtraceFound
:=
$(
wildcard
${SYSTEM_DTRACE_PROG}
)
systemDtraceFound
:=
$(
wildcard
${SYSTEM_DTRACE_PROG}
)
patchDtraceFound
:=
$(
wildcard
${PATCH_DTRACE_PROG}
)
patchDtraceFound
:=
$(
wildcard
${PATCH_DTRACE_PROG}
)
systemDtraceHdrFound
:=
$(
wildcard
$(SYSTEM_DTRACE_H)
)
ifneq
("$(systemDtraceHdrFound)", "")
CFLAGS
+=
-DHAVE_DTRACE_H
endif
ifneq
("$(patchDtraceFound)", "")
ifneq
("$(patchDtraceFound)", "")
DTRACE_PROG
=
$(PATCH_DTRACE_PROG)
DTRACE_PROG
=
$(PATCH_DTRACE_PROG)
...
...
make/solaris/makefiles/mapfile-vers
浏览文件 @
15eb4e64
#
#
# @(#)mapfile-vers 1.32 07/10/25 16:47:36
#
#
#
# Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
# Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
...
@@ -75,6 +77,11 @@ SUNWprivate_1.1 {
...
@@ -75,6 +77,11 @@ SUNWprivate_1.1 {
JVM_DesiredAssertionStatus;
JVM_DesiredAssertionStatus;
JVM_DisableCompiler;
JVM_DisableCompiler;
JVM_DoPrivileged;
JVM_DoPrivileged;
JVM_DTraceGetVersion;
JVM_DTraceActivate;
JVM_DTraceIsProbeEnabled;
JVM_DTraceIsSupported;
JVM_DTraceDispose;
JVM_DumpAllStacks;
JVM_DumpAllStacks;
JVM_DumpThreads;
JVM_DumpThreads;
JVM_EnableCompiler;
JVM_EnableCompiler;
...
...
src/cpu/sparc/vm/nativeInst_sparc.cpp
浏览文件 @
15eb4e64
...
@@ -26,6 +26,10 @@
...
@@ -26,6 +26,10 @@
# include "incls/_nativeInst_sparc.cpp.incl"
# include "incls/_nativeInst_sparc.cpp.incl"
bool
NativeInstruction
::
is_dtrace_trap
()
{
return
!
is_nop
();
}
void
NativeInstruction
::
set_data64_sethi
(
address
instaddr
,
intptr_t
x
)
{
void
NativeInstruction
::
set_data64_sethi
(
address
instaddr
,
intptr_t
x
)
{
ResourceMark
rm
;
ResourceMark
rm
;
CodeBuffer
buf
(
instaddr
,
10
*
BytesPerInstWord
);
CodeBuffer
buf
(
instaddr
,
10
*
BytesPerInstWord
);
...
...
src/cpu/sparc/vm/nativeInst_sparc.hpp
浏览文件 @
15eb4e64
...
@@ -43,6 +43,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
...
@@ -43,6 +43,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
nop_instruction_size
=
4
nop_instruction_size
=
4
};
};
bool
is_dtrace_trap
();
bool
is_nop
()
{
return
long_at
(
0
)
==
nop_instruction
();
}
bool
is_nop
()
{
return
long_at
(
0
)
==
nop_instruction
();
}
bool
is_call
()
{
return
is_op
(
long_at
(
0
),
Assembler
::
call_op
);
}
bool
is_call
()
{
return
is_op
(
long_at
(
0
),
Assembler
::
call_op
);
}
bool
is_sethi
()
{
return
(
is_op2
(
long_at
(
0
),
Assembler
::
sethi_op2
)
bool
is_sethi
()
{
return
(
is_op2
(
long_at
(
0
),
Assembler
::
sethi_op2
)
...
...
src/cpu/sparc/vm/sharedRuntime_sparc.cpp
浏览文件 @
15eb4e64
...
@@ -1637,7 +1637,7 @@ static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
...
@@ -1637,7 +1637,7 @@ static void long_move(MacroAssembler* masm, VMRegPair src, VMRegPair dst) {
}
}
}
else
if
(
dst
.
is_single_phys_reg
())
{
}
else
if
(
dst
.
is_single_phys_reg
())
{
if
(
src
.
is_adjacent_aligned_on_stack
(
2
))
{
if
(
src
.
is_adjacent_aligned_on_stack
(
2
))
{
__
ld
d
(
FP
,
reg2offset
(
src
.
first
())
+
STACK_BIAS
,
dst
.
first
()
->
as_Register
());
__
ld
_long
(
FP
,
reg2offset
(
src
.
first
())
+
STACK_BIAS
,
dst
.
first
()
->
as_Register
());
}
else
{
}
else
{
// dst is a single reg.
// dst is a single reg.
// Remember lo is low address not msb for stack slots
// Remember lo is low address not msb for stack slots
...
@@ -2501,6 +2501,551 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
...
@@ -2501,6 +2501,551 @@ 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.
static
int
fp_offset
[
ConcreteRegisterImpl
::
number_of_registers
]
=
{
0
};
static
bool
offsets_initialized
=
false
;
static
VMRegPair
reg64_to_VMRegPair
(
Register
r
)
{
VMRegPair
ret
;
if
(
wordSize
==
8
)
{
ret
.
set2
(
r
->
as_VMReg
());
}
else
{
ret
.
set_pair
(
r
->
successor
()
->
as_VMReg
(),
r
->
as_VMReg
());
}
return
ret
;
}
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
();
// Skip the receiver as dtrace doesn't want to see it
if
(
!
method
->
is_static
()
)
{
in_sig_bt
[
i
++
]
=
T_OBJECT
;
first_arg_to_pass
=
1
;
}
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_Byte
())
{
out_sig_bt
[
total_c_args
-
1
]
=
T_BYTE
;
}
else
if
(
s
==
vmSymbols
::
java_lang_Character
()
||
s
==
vmSymbols
::
java_lang_Short
())
{
out_sig_bt
[
total_c_args
-
1
]
=
T_SHORT
;
}
else
if
(
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
// We convert double to long
out_sig_bt
[
total_c_args
-
1
]
=
T_LONG
;
out_sig_bt
[
total_c_args
++
]
=
T_VOID
;
}
else
if
(
bt
==
T_FLOAT
)
{
// We convert float to int
out_sig_bt
[
total_c_args
-
1
]
=
T_INT
;
}
}
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
);
// We have received a description of where all the java arg are located
// on entry to the wrapper. We need to convert these args to where
// the a native (non-jni) function would expect them. To figure out
// where they go we convert the java signature to a C signature and remove
// T_VOID for any long/double we might have received.
// Now figure out where the args must be stored and how much stack space
// they require (neglecting out_preserve_stack_slots but space for storing
// the 1st six register arguments). It's weird see int_stk_helper.
//
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
;
// Plus a temp for possible converion of float/double/long register args
int
conversion_temp
=
stack_slots
;
stack_slots
+=
2
;
// Now space for the string(s) we must convert
int
string_locs
=
stack_slots
;
stack_slots
+=
total_strings
*
(
max_dtrace_string_size
/
VMRegImpl
::
stack_slot_size
);
// 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]
// | temp |
// |---------------------| <- conversion_temp
// | 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
,
4
*
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
{
Label
L
;
const
Register
temp_reg
=
G3_scratch
;
Address
ic_miss
(
temp_reg
,
SharedRuntime
::
get_ic_miss_stub
());
__
verify_oop
(
O0
);
__
ld_ptr
(
O0
,
oopDesc
::
klass_offset_in_bytes
(),
temp_reg
);
__
cmp
(
temp_reg
,
G5_inline_cache_reg
);
__
brx
(
Assembler
::
equal
,
true
,
Assembler
::
pt
,
L
);
__
delayed
()
->
nop
();
__
jump_to
(
ic_miss
,
0
);
__
delayed
()
->
nop
();
__
align
(
CodeEntryAlignment
);
__
bind
(
L
);
}
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 before creating frame
__
generate_stack_overflow_check
(
stack_size
);
assert
(((
intptr_t
)
__
pc
()
-
start
-
vep_offset
)
>=
5
,
"valid size for make_non_entrant"
);
// Generate a new frame for the wrapper.
__
save
(
SP
,
-
stack_size
,
SP
);
// Frame is now completed as far a size and linkage.
int
frame_complete
=
((
intptr_t
)
__
pc
())
-
start
;
#ifdef ASSERT
bool
reg_destroyed
[
RegisterImpl
::
number_of_registers
];
bool
freg_destroyed
[
FloatRegisterImpl
::
number_of_registers
];
for
(
int
r
=
0
;
r
<
RegisterImpl
::
number_of_registers
;
r
++
)
{
reg_destroyed
[
r
]
=
false
;
}
for
(
int
f
=
0
;
f
<
FloatRegisterImpl
::
number_of_registers
;
f
++
)
{
freg_destroyed
[
f
]
=
false
;
}
#endif
/* ASSERT */
VMRegPair
zero
;
zero
.
set2
(
G0
->
as_VMReg
());
int
c_arg
,
j_arg
;
Register
conversion_off
=
noreg
;
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
];
#ifdef ASSERT
if
(
src
.
first
()
->
is_Register
())
{
assert
(
!
reg_destroyed
[
src
.
first
()
->
as_Register
()
->
encoding
()],
"ack!"
);
}
else
if
(
src
.
first
()
->
is_FloatRegister
())
{
assert
(
!
freg_destroyed
[
src
.
first
()
->
as_FloatRegister
()
->
encoding
(
FloatRegisterImpl
::
S
)],
"ack!"
);
}
if
(
dst
.
first
()
->
is_Register
())
{
reg_destroyed
[
dst
.
first
()
->
as_Register
()
->
encoding
()]
=
true
;
}
else
if
(
dst
.
first
()
->
is_FloatRegister
())
{
freg_destroyed
[
dst
.
first
()
->
as_FloatRegister
()
->
encoding
(
FloatRegisterImpl
::
S
)]
=
true
;
}
#endif
/* ASSERT */
switch
(
in_sig_bt
[
j_arg
])
{
case
T_ARRAY
:
case
T_OBJECT
:
{
if
(
out_sig_bt
[
c_arg
]
==
T_BYTE
||
out_sig_bt
[
c_arg
]
==
T_SHORT
||
out_sig_bt
[
c_arg
]
==
T_INT
||
out_sig_bt
[
c_arg
]
==
T_LONG
)
{
// need to unbox a one-slot value
Register
in_reg
=
L0
;
Register
tmp
=
L2
;
if
(
src
.
first
()
->
is_reg
()
)
{
in_reg
=
src
.
first
()
->
as_Register
();
}
else
{
assert
(
Assembler
::
is_simm13
(
reg2offset
(
src
.
first
())
+
STACK_BIAS
),
"must be"
);
__
ld_ptr
(
FP
,
reg2offset
(
src
.
first
())
+
STACK_BIAS
,
in_reg
);
}
// If the final destination is an acceptable register
if
(
dst
.
first
()
->
is_reg
()
)
{
if
(
dst
.
is_single_phys_reg
()
||
out_sig_bt
[
c_arg
]
!=
T_LONG
)
{
tmp
=
dst
.
first
()
->
as_Register
();
}
}
Label
skipUnbox
;
if
(
wordSize
==
4
&&
out_sig_bt
[
c_arg
]
==
T_LONG
)
{
__
mov
(
G0
,
tmp
->
successor
());
}
__
br_null
(
in_reg
,
true
,
Assembler
::
pn
,
skipUnbox
);
__
delayed
()
->
mov
(
G0
,
tmp
);
switch
(
out_sig_bt
[
c_arg
])
{
case
T_BYTE
:
__
ldub
(
in_reg
,
box_offset
,
tmp
);
break
;
case
T_SHORT
:
__
lduh
(
in_reg
,
box_offset
,
tmp
);
break
;
case
T_INT
:
__
ld
(
in_reg
,
box_offset
,
tmp
);
break
;
case
T_LONG
:
__
ld_long
(
in_reg
,
box_offset
,
tmp
);
break
;
default:
ShouldNotReachHere
();
}
__
bind
(
skipUnbox
);
// If tmp wasn't final destination copy to final destination
if
(
tmp
==
L2
)
{
VMRegPair
tmp_as_VM
=
reg64_to_VMRegPair
(
L2
);
if
(
out_sig_bt
[
c_arg
]
==
T_LONG
)
{
long_move
(
masm
,
tmp_as_VM
,
dst
);
}
else
{
move32_64
(
masm
,
tmp_as_VM
,
out_regs
[
c_arg
]);
}
}
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
}
}
else
if
(
out_sig_bt
[
c_arg
]
==
T_ADDRESS
)
{
Register
s
=
src
.
first
()
->
is_reg
()
?
src
.
first
()
->
as_Register
()
:
L2
;
Register
d
=
dst
.
first
()
->
is_reg
()
?
dst
.
first
()
->
as_Register
()
:
L2
;
// We store the oop now so that the conversion pass can reach
// while in the inner frame. This will be the only store if
// the oop is NULL.
if
(
s
!=
L2
)
{
// src is register
if
(
d
!=
L2
)
{
// dst is register
__
mov
(
s
,
d
);
}
else
{
assert
(
Assembler
::
is_simm13
(
reg2offset
(
dst
.
first
())
+
STACK_BIAS
),
"must be"
);
__
st_ptr
(
s
,
SP
,
reg2offset
(
dst
.
first
())
+
STACK_BIAS
);
}
}
else
{
// src not a register
assert
(
Assembler
::
is_simm13
(
reg2offset
(
src
.
first
())
+
STACK_BIAS
),
"must be"
);
__
ld_ptr
(
FP
,
reg2offset
(
src
.
first
())
+
STACK_BIAS
,
d
);
if
(
d
==
L2
)
{
assert
(
Assembler
::
is_simm13
(
reg2offset
(
dst
.
first
())
+
STACK_BIAS
),
"must be"
);
__
st_ptr
(
d
,
SP
,
reg2offset
(
dst
.
first
())
+
STACK_BIAS
);
}
}
}
else
if
(
out_sig_bt
[
c_arg
]
!=
T_VOID
)
{
// Convert the arg to NULL
if
(
dst
.
first
()
->
is_reg
())
{
__
mov
(
G0
,
dst
.
first
()
->
as_Register
());
}
else
{
assert
(
Assembler
::
is_simm13
(
reg2offset
(
dst
.
first
())
+
STACK_BIAS
),
"must be"
);
__
st_ptr
(
G0
,
SP
,
reg2offset
(
dst
.
first
())
+
STACK_BIAS
);
}
}
}
break
;
case
T_VOID
:
break
;
case
T_FLOAT
:
if
(
src
.
first
()
->
is_stack
())
{
// Stack to stack/reg is simple
move32_64
(
masm
,
src
,
dst
);
}
else
{
if
(
dst
.
first
()
->
is_reg
())
{
// freg -> reg
int
off
=
STACK_BIAS
+
conversion_temp
*
VMRegImpl
::
stack_slot_size
;
Register
d
=
dst
.
first
()
->
as_Register
();
if
(
Assembler
::
is_simm13
(
off
))
{
__
stf
(
FloatRegisterImpl
::
S
,
src
.
first
()
->
as_FloatRegister
(),
SP
,
off
);
__
ld
(
SP
,
off
,
d
);
}
else
{
if
(
conversion_off
==
noreg
)
{
__
set
(
off
,
L6
);
conversion_off
=
L6
;
}
__
stf
(
FloatRegisterImpl
::
S
,
src
.
first
()
->
as_FloatRegister
(),
SP
,
conversion_off
);
__
ld
(
SP
,
conversion_off
,
d
);
}
}
else
{
// freg -> mem
int
off
=
STACK_BIAS
+
reg2offset
(
dst
.
first
());
if
(
Assembler
::
is_simm13
(
off
))
{
__
stf
(
FloatRegisterImpl
::
S
,
src
.
first
()
->
as_FloatRegister
(),
SP
,
off
);
}
else
{
if
(
conversion_off
==
noreg
)
{
__
set
(
off
,
L6
);
conversion_off
=
L6
;
}
__
stf
(
FloatRegisterImpl
::
S
,
src
.
first
()
->
as_FloatRegister
(),
SP
,
conversion_off
);
}
}
}
break
;
case
T_DOUBLE
:
assert
(
j_arg
+
1
<
total_args_passed
&&
in_sig_bt
[
j_arg
+
1
]
==
T_VOID
&&
out_sig_bt
[
c_arg
+
1
]
==
T_VOID
,
"bad arg list"
);
if
(
src
.
first
()
->
is_stack
())
{
// Stack to stack/reg is simple
long_move
(
masm
,
src
,
dst
);
}
else
{
Register
d
=
dst
.
first
()
->
is_reg
()
?
dst
.
first
()
->
as_Register
()
:
L2
;
// Destination could be an odd reg on 32bit in which case
// we can't load direct to the destination.
if
(
!
d
->
is_even
()
&&
wordSize
==
4
)
{
d
=
L2
;
}
int
off
=
STACK_BIAS
+
conversion_temp
*
VMRegImpl
::
stack_slot_size
;
if
(
Assembler
::
is_simm13
(
off
))
{
__
stf
(
FloatRegisterImpl
::
D
,
src
.
first
()
->
as_FloatRegister
(),
SP
,
off
);
__
ld_long
(
SP
,
off
,
d
);
}
else
{
if
(
conversion_off
==
noreg
)
{
__
set
(
off
,
L6
);
conversion_off
=
L6
;
}
__
stf
(
FloatRegisterImpl
::
D
,
src
.
first
()
->
as_FloatRegister
(),
SP
,
conversion_off
);
__
ld_long
(
SP
,
conversion_off
,
d
);
}
if
(
d
==
L2
)
{
long_move
(
masm
,
reg64_to_VMRegPair
(
L2
),
dst
);
}
}
break
;
case
T_LONG
:
// 32bit can't do a split move of something like g1 -> O0, O1
// so use a memory temp
if
(
src
.
is_single_phys_reg
()
&&
wordSize
==
4
)
{
Register
tmp
=
L2
;
if
(
dst
.
first
()
->
is_reg
()
&&
(
wordSize
==
8
||
dst
.
first
()
->
as_Register
()
->
is_even
()))
{
tmp
=
dst
.
first
()
->
as_Register
();
}
int
off
=
STACK_BIAS
+
conversion_temp
*
VMRegImpl
::
stack_slot_size
;
if
(
Assembler
::
is_simm13
(
off
))
{
__
stx
(
src
.
first
()
->
as_Register
(),
SP
,
off
);
__
ld_long
(
SP
,
off
,
tmp
);
}
else
{
if
(
conversion_off
==
noreg
)
{
__
set
(
off
,
L6
);
conversion_off
=
L6
;
}
__
stx
(
src
.
first
()
->
as_Register
(),
SP
,
conversion_off
);
__
ld_long
(
SP
,
conversion_off
,
tmp
);
}
if
(
tmp
==
L2
)
{
long_move
(
masm
,
reg64_to_VMRegPair
(
L2
),
dst
);
}
}
else
{
long_move
(
masm
,
src
,
dst
);
}
break
;
case
T_ADDRESS
:
assert
(
false
,
"found T_ADDRESS in java args"
);
default:
move32_64
(
masm
,
src
,
dst
);
}
}
// If we have any strings we must store any register based arg to the stack
// This includes any still live xmm registers too.
if
(
total_strings
>
0
)
{
// protect all the arg registers
__
save_frame
(
0
);
__
mov
(
G2_thread
,
L7_thread_cache
);
const
Register
L2_string_off
=
L2
;
// Get first string offset
__
set
(
string_locs
*
VMRegImpl
::
stack_slot_size
,
L2_string_off
);
for
(
c_arg
=
0
;
c_arg
<
total_c_args
;
c_arg
++
)
{
if
(
out_sig_bt
[
c_arg
]
==
T_ADDRESS
)
{
VMRegPair
dst
=
out_regs
[
c_arg
];
const
Register
d
=
dst
.
first
()
->
is_reg
()
?
dst
.
first
()
->
as_Register
()
->
after_save
()
:
noreg
;
// It's a string the oop and it was already copied to the out arg
// position
if
(
d
!=
noreg
)
{
__
mov
(
d
,
O0
);
}
else
{
assert
(
Assembler
::
is_simm13
(
reg2offset
(
dst
.
first
())
+
STACK_BIAS
),
"must be"
);
__
ld_ptr
(
FP
,
reg2offset
(
dst
.
first
())
+
STACK_BIAS
,
O0
);
}
Label
skip
;
__
br_null
(
O0
,
false
,
Assembler
::
pn
,
skip
);
__
delayed
()
->
add
(
FP
,
L2_string_off
,
O1
);
if
(
d
!=
noreg
)
{
__
mov
(
O1
,
d
);
}
else
{
assert
(
Assembler
::
is_simm13
(
reg2offset
(
dst
.
first
())
+
STACK_BIAS
),
"must be"
);
__
st_ptr
(
O1
,
FP
,
reg2offset
(
dst
.
first
())
+
STACK_BIAS
);
}
__
call
(
CAST_FROM_FN_PTR
(
address
,
SharedRuntime
::
get_utf
),
relocInfo
::
runtime_call_type
);
__
delayed
()
->
add
(
L2_string_off
,
max_dtrace_string_size
,
L2_string_off
);
__
bind
(
skip
);
}
}
__
mov
(
L7_thread_cache
,
G2_thread
);
__
restore
();
}
// 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
__
ret
();
__
delayed
()
->
restore
();
__
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
// this function returns the adjust size (in number of words) to a c2i adapter
// activation for use during deoptimization
// activation for use during deoptimization
int
Deoptimization
::
last_frame_adjust
(
int
callee_parameters
,
int
callee_locals
)
{
int
Deoptimization
::
last_frame_adjust
(
int
callee_parameters
,
int
callee_locals
)
{
...
...
src/cpu/x86/vm/nativeInst_x86.cpp
浏览文件 @
15eb4e64
...
@@ -472,3 +472,7 @@ address NativeGeneralJump::jump_destination() const {
...
@@ -472,3 +472,7 @@ address NativeGeneralJump::jump_destination() const {
else
else
return
addr_at
(
0
)
+
length
+
sbyte_at
(
offset
);
return
addr_at
(
0
)
+
length
+
sbyte_at
(
offset
);
}
}
bool
NativeInstruction
::
is_dtrace_trap
()
{
return
(
*
(
int32_t
*
)
this
&
0xff
)
==
0xcc
;
}
src/cpu/x86/vm/nativeInst_x86.hpp
浏览文件 @
15eb4e64
...
@@ -50,6 +50,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
...
@@ -50,6 +50,7 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC {
};
};
bool
is_nop
()
{
return
ubyte_at
(
0
)
==
nop_instruction_code
;
}
bool
is_nop
()
{
return
ubyte_at
(
0
)
==
nop_instruction_code
;
}
bool
is_dtrace_trap
();
inline
bool
is_call
();
inline
bool
is_call
();
inline
bool
is_illegal
();
inline
bool
is_illegal
();
inline
bool
is_return
();
inline
bool
is_return
();
...
...
src/cpu/x86/vm/sharedRuntime_x86_32.cpp
浏览文件 @
15eb4e64
...
@@ -1880,6 +1880,379 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
...
@@ -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
// this function returns the adjust size (in number of words) to a c2i adapter
// activation for use during deoptimization
// activation for use during deoptimization
int
Deoptimization
::
last_frame_adjust
(
int
callee_parameters
,
int
callee_locals
)
{
int
Deoptimization
::
last_frame_adjust
(
int
callee_parameters
,
int
callee_locals
)
{
...
...
src/cpu/x86/vm/sharedRuntime_x86_64.cpp
浏览文件 @
15eb4e64
...
@@ -1886,6 +1886,627 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
...
@@ -1886,6 +1886,627 @@ 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.
static
int
fp_offset
[
ConcreteRegisterImpl
::
number_of_registers
]
=
{
0
};
static
bool
offsets_initialized
=
false
;
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"
);
if
(
!
offsets_initialized
)
{
fp_offset
[
c_rarg0
->
as_VMReg
()
->
value
()]
=
-
1
*
wordSize
;
fp_offset
[
c_rarg1
->
as_VMReg
()
->
value
()]
=
-
2
*
wordSize
;
fp_offset
[
c_rarg2
->
as_VMReg
()
->
value
()]
=
-
3
*
wordSize
;
fp_offset
[
c_rarg3
->
as_VMReg
()
->
value
()]
=
-
4
*
wordSize
;
fp_offset
[
c_rarg4
->
as_VMReg
()
->
value
()]
=
-
5
*
wordSize
;
fp_offset
[
c_rarg5
->
as_VMReg
()
->
value
()]
=
-
6
*
wordSize
;
fp_offset
[
c_farg0
->
as_VMReg
()
->
value
()]
=
-
7
*
wordSize
;
fp_offset
[
c_farg1
->
as_VMReg
()
->
value
()]
=
-
8
*
wordSize
;
fp_offset
[
c_farg2
->
as_VMReg
()
->
value
()]
=
-
9
*
wordSize
;
fp_offset
[
c_farg3
->
as_VMReg
()
->
value
()]
=
-
10
*
wordSize
;
fp_offset
[
c_farg4
->
as_VMReg
()
->
value
()]
=
-
11
*
wordSize
;
fp_offset
[
c_farg5
->
as_VMReg
()
->
value
()]
=
-
12
*
wordSize
;
fp_offset
[
c_farg6
->
as_VMReg
()
->
value
()]
=
-
13
*
wordSize
;
fp_offset
[
c_farg7
->
as_VMReg
()
->
value
()]
=
-
14
*
wordSize
;
offsets_initialized
=
true
;
}
// 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
();
// Skip the receiver as dtrace doesn't want to see it
if
(
!
method
->
is_static
()
)
{
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
// We convert double to long
out_sig_bt
[
total_c_args
-
1
]
=
T_LONG
;
out_sig_bt
[
total_c_args
++
]
=
T_VOID
;
}
else
if
(
bt
==
T_FLOAT
)
{
// We convert float to int
out_sig_bt
[
total_c_args
-
1
]
=
T_INT
;
}
}
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 but space for storing
// the 1st six register arguments). It's weird see int_stk_helper.
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
;
}
// Plus the temps we might need to juggle register args
// regs take two slots each
stack_slots
+=
(
Argument
::
n_int_register_parameters_c
+
Argument
::
n_float_register_parameters_c
)
*
2
;
// + 4 for return address (which we own) and saved rbp,
stack_slots
+=
4
;
// 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
,
4
*
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
(((
uintptr_t
)
__
pc
()
-
start
-
vep_offset
)
>=
5
,
"valid size for make_non_entrant"
);
// Generate a new frame for the wrapper.
__
enter
();
// -4 because return address is already present and so is saved rbp,
if
(
stack_size
-
2
*
wordSize
!=
0
)
{
__
subq
(
rsp
,
stack_size
-
2
*
wordSize
);
}
// Frame is now completed as far a size and linkage.
int
frame_complete
=
((
intptr_t
)
__
pc
())
-
start
;
int
c_arg
,
j_arg
;
// State of input register args
bool
live
[
ConcreteRegisterImpl
::
number_of_registers
];
live
[
j_rarg0
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_rarg1
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_rarg2
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_rarg3
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_rarg4
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_rarg5
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_farg0
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_farg1
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_farg2
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_farg3
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_farg4
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_farg5
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_farg6
->
as_VMReg
()
->
value
()]
=
false
;
live
[
j_farg7
->
as_VMReg
()
->
value
()]
=
false
;
bool
rax_is_zero
=
false
;
// All args (except strings) destined for the stack are moved first
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
];
// Get the real reg value or a dummy (rsp)
int
src_reg
=
src
.
first
()
->
is_reg
()
?
src
.
first
()
->
value
()
:
rsp
->
as_VMReg
()
->
value
();
bool
useless
=
in_sig_bt
[
j_arg
]
==
T_ARRAY
||
(
in_sig_bt
[
j_arg
]
==
T_OBJECT
&&
out_sig_bt
[
c_arg
]
!=
T_INT
&&
out_sig_bt
[
c_arg
]
!=
T_ADDRESS
&&
out_sig_bt
[
c_arg
]
!=
T_LONG
);
live
[
src_reg
]
=
!
useless
;
if
(
dst
.
first
()
->
is_stack
())
{
// Even though a string arg in a register is still live after this loop
// after the string conversion loop (next) it will be dead so we take
// advantage of that now for simpler code to manage live.
live
[
src_reg
]
=
false
;
switch
(
in_sig_bt
[
j_arg
])
{
case
T_ARRAY
:
case
T_OBJECT
:
{
Address
stack_dst
(
rsp
,
reg2offset_out
(
dst
.
first
()));
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
{
__
movq
(
rax
,
Address
(
rbp
,
reg2offset_in
(
src
.
first
())));
rax_is_zero
=
false
;
}
Label
skipUnbox
;
__
movptr
(
Address
(
rsp
,
reg2offset_out
(
dst
.
first
())),
(
int32_t
)
NULL_WORD
);
__
testq
(
in_reg
,
in_reg
);
__
jcc
(
Assembler
::
zero
,
skipUnbox
);
Address
src1
(
in_reg
,
box_offset
);
if
(
out_sig_bt
[
c_arg
]
==
T_LONG
)
{
__
movq
(
in_reg
,
src1
);
__
movq
(
stack_dst
,
in_reg
);
assert
(
out_sig_bt
[
c_arg
+
1
]
==
T_VOID
,
"must be"
);
++
c_arg
;
// skip over T_VOID to keep the loop indices in sync
}
else
{
__
movl
(
in_reg
,
src1
);
__
movl
(
stack_dst
,
in_reg
);
}
__
bind
(
skipUnbox
);
}
else
if
(
out_sig_bt
[
c_arg
]
!=
T_ADDRESS
)
{
// Convert the arg to NULL
if
(
!
rax_is_zero
)
{
__
xorq
(
rax
,
rax
);
rax_is_zero
=
true
;
}
__
movq
(
stack_dst
,
rax
);
}
}
break
;
case
T_VOID
:
break
;
case
T_FLOAT
:
// This does the right thing since we know it is destined for the
// stack
float_move
(
masm
,
src
,
dst
);
break
;
case
T_DOUBLE
:
// This does the right thing since we know it is destined for the
// stack
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:
move32_64
(
masm
,
src
,
dst
);
}
}
}
// If we have any strings we must store any register based arg to the stack
// This includes any still live xmm registers too.
int
sid
=
0
;
if
(
total_strings
>
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
];
if
(
src
.
first
()
->
is_reg
())
{
Address
src_tmp
(
rbp
,
fp_offset
[
src
.
first
()
->
value
()]);
// string oops were left untouched by the previous loop even if the
// eventual (converted) arg is destined for the stack so park them
// away now (except for first)
if
(
out_sig_bt
[
c_arg
]
==
T_ADDRESS
)
{
Address
utf8_addr
=
Address
(
rsp
,
string_locs
[
sid
++
]
*
VMRegImpl
::
stack_slot_size
);
if
(
sid
!=
1
)
{
// The first string arg won't be killed until after the utf8
// conversion
__
movq
(
utf8_addr
,
src
.
first
()
->
as_Register
());
}
}
else
if
(
dst
.
first
()
->
is_reg
())
{
if
(
in_sig_bt
[
j_arg
]
==
T_FLOAT
||
in_sig_bt
[
j_arg
]
==
T_DOUBLE
)
{
// Convert the xmm register to an int and store it in the reserved
// location for the eventual c register arg
XMMRegister
f
=
src
.
first
()
->
as_XMMRegister
();
if
(
in_sig_bt
[
j_arg
]
==
T_FLOAT
)
{
__
movflt
(
src_tmp
,
f
);
}
else
{
__
movdbl
(
src_tmp
,
f
);
}
}
else
{
// If the arg is an oop type we don't support don't bother to store
// it remember string was handled above.
bool
useless
=
in_sig_bt
[
j_arg
]
==
T_ARRAY
||
(
in_sig_bt
[
j_arg
]
==
T_OBJECT
&&
out_sig_bt
[
c_arg
]
!=
T_INT
&&
out_sig_bt
[
c_arg
]
!=
T_LONG
);
if
(
!
useless
)
{
__
movq
(
src_tmp
,
src
.
first
()
->
as_Register
());
}
}
}
}
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
;
// skip over T_VOID to keep the loop indices in sync
}
}
// Now that the volatile registers are safe, convert all the strings
sid
=
0
;
for
(
j_arg
=
first_arg_to_pass
,
c_arg
=
0
;
j_arg
<
total_args_passed
;
j_arg
++
,
c_arg
++
)
{
if
(
out_sig_bt
[
c_arg
]
==
T_ADDRESS
)
{
// It's a string
Address
utf8_addr
=
Address
(
rsp
,
string_locs
[
sid
++
]
*
VMRegImpl
::
stack_slot_size
);
// The first string we find might still be in the original java arg
// register
VMReg
src
=
in_regs
[
j_arg
].
first
();
// We will need to eventually save the final argument to the trap
// in the von-volatile location dedicated to src. This is the offset
// from fp we will use.
int
src_off
=
src
->
is_reg
()
?
fp_offset
[
src
->
value
()]
:
reg2offset_in
(
src
);
// This is where the argument will eventually reside
VMRegPair
dst
=
out_regs
[
c_arg
];
if
(
src
->
is_reg
())
{
if
(
sid
==
1
)
{
__
movq
(
c_rarg0
,
src
->
as_Register
());
}
else
{
__
movq
(
c_rarg0
,
utf8_addr
);
}
}
else
{
// arg is still in the original location
__
movq
(
c_rarg0
,
Address
(
rbp
,
reg2offset_in
(
src
)));
}
Label
done
,
convert
;
// see if the oop is NULL
__
testq
(
c_rarg0
,
c_rarg0
);
__
jcc
(
Assembler
::
notEqual
,
convert
);
if
(
dst
.
first
()
->
is_reg
())
{
// Save the ptr to utf string in the origina src loc or the tmp
// dedicated to it
__
movq
(
Address
(
rbp
,
src_off
),
c_rarg0
);
}
else
{
__
movq
(
Address
(
rsp
,
reg2offset_out
(
dst
.
first
())),
c_rarg0
);
}
__
jmp
(
done
);
__
bind
(
convert
);
__
lea
(
c_rarg1
,
utf8_addr
);
if
(
dst
.
first
()
->
is_reg
())
{
__
movq
(
Address
(
rbp
,
src_off
),
c_rarg1
);
}
else
{
__
movq
(
Address
(
rsp
,
reg2offset_out
(
dst
.
first
())),
c_rarg1
);
}
// And do the conversion
__
call
(
RuntimeAddress
(
CAST_FROM_FN_PTR
(
address
,
SharedRuntime
::
get_utf
)));
__
bind
(
done
);
}
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
;
// skip over T_VOID to keep the loop indices in sync
}
}
// The get_utf call killed all the c_arg registers
live
[
c_rarg0
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_rarg1
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_rarg2
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_rarg3
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_rarg4
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_rarg5
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_farg0
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_farg1
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_farg2
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_farg3
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_farg4
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_farg5
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_farg6
->
as_VMReg
()
->
value
()]
=
false
;
live
[
c_farg7
->
as_VMReg
()
->
value
()]
=
false
;
}
// Now we can finally move the register args to their desired locations
rax_is_zero
=
false
;
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
];
// Only need to look for args destined for the interger registers (since we
// convert float/double args to look like int/long outbound)
if
(
dst
.
first
()
->
is_reg
())
{
Register
r
=
dst
.
first
()
->
as_Register
();
// Check if the java arg is unsupported and thereofre useless
bool
useless
=
in_sig_bt
[
j_arg
]
==
T_ARRAY
||
(
in_sig_bt
[
j_arg
]
==
T_OBJECT
&&
out_sig_bt
[
c_arg
]
!=
T_INT
&&
out_sig_bt
[
c_arg
]
!=
T_ADDRESS
&&
out_sig_bt
[
c_arg
]
!=
T_LONG
);
// If we're going to kill an existing arg save it first
if
(
live
[
dst
.
first
()
->
value
()])
{
// you can't kill yourself
if
(
src
.
first
()
!=
dst
.
first
())
{
__
movq
(
Address
(
rbp
,
fp_offset
[
dst
.
first
()
->
value
()]),
r
);
}
}
if
(
src
.
first
()
->
is_reg
())
{
if
(
live
[
src
.
first
()
->
value
()]
)
{
if
(
in_sig_bt
[
j_arg
]
==
T_FLOAT
)
{
__
movdl
(
r
,
src
.
first
()
->
as_XMMRegister
());
}
else
if
(
in_sig_bt
[
j_arg
]
==
T_DOUBLE
)
{
__
movdq
(
r
,
src
.
first
()
->
as_XMMRegister
());
}
else
if
(
r
!=
src
.
first
()
->
as_Register
())
{
if
(
!
useless
)
{
__
movq
(
r
,
src
.
first
()
->
as_Register
());
}
}
}
else
{
// If the arg is an oop type we don't support don't bother to store
// it
if
(
!
useless
)
{
if
(
in_sig_bt
[
j_arg
]
==
T_DOUBLE
||
in_sig_bt
[
j_arg
]
==
T_LONG
||
in_sig_bt
[
j_arg
]
==
T_OBJECT
)
{
__
movq
(
r
,
Address
(
rbp
,
fp_offset
[
src
.
first
()
->
value
()]));
}
else
{
__
movl
(
r
,
Address
(
rbp
,
fp_offset
[
src
.
first
()
->
value
()]));
}
}
}
live
[
src
.
first
()
->
value
()]
=
false
;
}
else
if
(
!
useless
)
{
// full sized move even for int should be ok
__
movq
(
r
,
Address
(
rbp
,
reg2offset_in
(
src
.
first
())));
}
// At this point r has the original java arg in the final location
// (assuming it wasn't useless). If the java arg was an oop
// we have a bit more to do
if
(
in_sig_bt
[
j_arg
]
==
T_ARRAY
||
in_sig_bt
[
j_arg
]
==
T_OBJECT
)
{
if
(
out_sig_bt
[
c_arg
]
==
T_INT
||
out_sig_bt
[
c_arg
]
==
T_LONG
)
{
// need to unbox a one-word value
Label
skip
;
__
testq
(
r
,
r
);
__
jcc
(
Assembler
::
equal
,
skip
);
Address
src1
(
r
,
box_offset
);
if
(
out_sig_bt
[
c_arg
]
==
T_LONG
)
{
__
movq
(
r
,
src1
);
}
else
{
__
movl
(
r
,
src1
);
}
__
bind
(
skip
);
}
else
if
(
out_sig_bt
[
c_arg
]
!=
T_ADDRESS
)
{
// Convert the arg to NULL
__
xorq
(
r
,
r
);
}
}
// dst can longer be holding an input value
live
[
dst
.
first
()
->
value
()]
=
false
;
}
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
;
// skip over 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
// this function returns the adjust size (in number of words) to a c2i adapter
// activation for use during deoptimization
// activation for use during deoptimization
int
Deoptimization
::
last_frame_adjust
(
int
callee_parameters
,
int
callee_locals
)
{
int
Deoptimization
::
last_frame_adjust
(
int
callee_parameters
,
int
callee_locals
)
{
...
...
src/os/linux/vm/dtraceJSDT_linux.cpp
0 → 100644
浏览文件 @
15eb4e64
/*
* 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
;
}
src/os/solaris/vm/dtraceJSDT_solaris.cpp
0 → 100644
浏览文件 @
15eb4e64
/*
* Copyright 2005-2006 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_solaris.cpp.incl"
#ifdef HAVE_DTRACE_H
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dtrace.h>
static
const
char
*
devname
=
"/dev/dtrace/helper"
;
static
const
char
*
olddevname
=
"/devices/pseudo/dtrace@0:helper"
;
static
const
char
*
string_sig
=
"uintptr_t"
;
static
const
char
*
int_sig
=
"long"
;
static
const
char
*
long_sig
=
"long long"
;
static
void
printDOFHelper
(
dof_helper_t
*
helper
);
static
int
dofhelper_open
()
{
int
fd
;
if
((
fd
=
open64
(
devname
,
O_RDWR
))
<
0
)
{
// Optimize next calls
devname
=
olddevname
;
if
((
fd
=
open64
(
devname
,
O_RDWR
))
<
0
)
{
return
-
1
;
}
}
return
fd
;
}
static
jint
dof_register
(
jstring
module
,
uint8_t
*
dof
,
void
*
modaddr
)
{
int
probe
;
dof_helper_t
dh
;
int
fd
;
memset
(
&
dh
,
0
,
sizeof
(
dh
));
char
*
module_name
=
java_lang_String
::
as_utf8_string
(
JNIHandles
::
resolve_non_null
(
module
));
jio_snprintf
(
dh
.
dofhp_mod
,
sizeof
(
dh
.
dofhp_mod
),
"%s"
,
module_name
);
dh
.
dofhp_dof
=
(
uint64_t
)
dof
;
dh
.
dofhp_addr
=
(
uint64_t
)
modaddr
;
fd
=
dofhelper_open
();
if
(
fd
<
0
)
return
-
1
;
probe
=
ioctl
(
fd
,
DTRACEHIOC_ADDDOF
,
&
dh
);
close
(
fd
);
if
(
PrintDTraceDOF
)
{
printDOFHelper
(
&
dh
);
tty
->
print_cr
(
"DOF helper id = %d"
,
probe
);
}
return
probe
;
}
int
DTraceJSDT
::
pd_activate
(
void
*
moduleBaseAddress
,
jstring
module
,
jint
providers_count
,
JVM_DTraceProvider
*
providers
)
{
// We need sections:
// (1) STRTAB
// (
// (2) PROVIDER
// (3) PROBES
// (4) PROBOFFS
// (5) PROBARGS
// ) * Number of Providers
// Type of sections we create
enum
{
STRTAB
=
0
,
PROVIDERS
=
1
,
PROBES
=
2
,
PROBE_OFFSETS
=
3
,
ARG_OFFSETS
=
4
,
NUM_SECTIONS
=
5
};
static
int
alignment_for
[
NUM_SECTIONS
]
=
{
1
,
4
,
8
,
4
,
1
};
ResourceMark
rm
;
uint32_t
num_sections
=
1
+
4
*
providers_count
;
uint32_t
offset
=
sizeof
(
dof_hdr_t
)
+
(
num_sections
*
sizeof
(
dof_sec_t
));
uint32_t
*
secoffs
=
NEW_RESOURCE_ARRAY
(
uint32_t
,
num_sections
);
uint32_t
*
secsize
=
NEW_RESOURCE_ARRAY
(
uint32_t
,
num_sections
);
// Store offsets of all strings here in such order:
// zero-string (always 0)
// provider1-name
// probe1-function
// probe1-name
// arg-1
// arg-2
// ...
// probe2-function
// probe2-name
// arg-1
// arg-2
// provider2-name
// ...
uint32_t
strcount
=
0
;
// Count the number of strings we'll need
for
(
int
prvc
=
0
;
prvc
<
providers_count
;
++
prvc
)
{
JVM_DTraceProvider
*
provider
=
&
providers
[
prvc
];
// Provider name
++
strcount
;
for
(
int
prbc
=
0
;
prbc
<
provider
->
probe_count
;
++
prbc
)
{
JVM_DTraceProbe
*
p
=
&
(
provider
->
probes
[
prbc
]);
symbolOop
sig
=
JNIHandles
::
resolve_jmethod_id
(
p
->
method
)
->
signature
();
// function + name + one per argument
strcount
+=
2
+
ArgumentCount
(
sig
).
size
();
}
}
// Create place for string offsets
uint32_t
*
stroffs
=
NEW_RESOURCE_ARRAY
(
uint32_t
,
strcount
+
1
);
uint32_t
string_index
=
0
;
uint32_t
curstr
=
0
;
// First we need an empty string: ""
stroffs
[
curstr
++
]
=
string_index
;
string_index
+=
strlen
(
""
)
+
1
;
for
(
int
prvc
=
0
;
prvc
<
providers_count
;
++
prvc
)
{
JVM_DTraceProvider
*
provider
=
&
providers
[
prvc
];
char
*
provider_name
=
java_lang_String
::
as_utf8_string
(
JNIHandles
::
resolve_non_null
(
provider
->
name
));
stroffs
[
curstr
++
]
=
string_index
;
string_index
+=
strlen
(
provider_name
)
+
1
;
// All probes
for
(
int
prbc
=
0
;
prbc
<
provider
->
probe_count
;
++
prbc
)
{
JVM_DTraceProbe
*
p
=
&
(
provider
->
probes
[
prbc
]);
char
*
function
=
java_lang_String
::
as_utf8_string
(
JNIHandles
::
resolve_non_null
(
p
->
function
));
stroffs
[
curstr
++
]
=
string_index
;
string_index
+=
strlen
(
function
)
+
1
;
char
*
name
=
java_lang_String
::
as_utf8_string
(
JNIHandles
::
resolve_non_null
(
p
->
name
));
stroffs
[
curstr
++
]
=
string_index
;
string_index
+=
strlen
(
name
)
+
1
;
symbolOop
sig
=
JNIHandles
::
resolve_jmethod_id
(
p
->
method
)
->
signature
();
SignatureStream
ss
(
sig
);
for
(
;
!
ss
.
at_return_type
();
ss
.
next
())
{
BasicType
bt
=
ss
.
type
();
const
char
*
t
=
NULL
;
if
(
bt
==
T_OBJECT
&&
ss
.
as_symbol_or_null
()
==
vmSymbols
::
java_lang_String
())
{
t
=
string_sig
;
}
else
if
(
bt
==
T_LONG
)
{
t
=
long_sig
;
}
else
{
t
=
int_sig
;
}
stroffs
[
curstr
++
]
=
string_index
;
string_index
+=
strlen
(
t
)
+
1
;
}
}
}
secoffs
[
STRTAB
]
=
offset
;
secsize
[
STRTAB
]
=
string_index
;
offset
+=
string_index
;
// Calculate the size of the rest
for
(
int
prvc
=
0
;
prvc
<
providers_count
;
++
prvc
)
{
JVM_DTraceProvider
*
provider
=
&
providers
[
prvc
];
size_t
provider_sec
=
PROVIDERS
+
prvc
*
4
;
size_t
probe_sec
=
PROBES
+
prvc
*
4
;
size_t
probeoffs_sec
=
PROBE_OFFSETS
+
prvc
*
4
;
size_t
argoffs_sec
=
ARG_OFFSETS
+
prvc
*
4
;
// Allocate space for the provider data struction
secoffs
[
provider_sec
]
=
align_size_up
(
offset
,
alignment_for
[
PROVIDERS
]);
secsize
[
provider_sec
]
=
sizeof
(
dof_provider_t
);
offset
=
secoffs
[
provider_sec
]
+
secsize
[
provider_sec
];
// Allocate space for all the probes
secoffs
[
probe_sec
]
=
align_size_up
(
offset
,
alignment_for
[
PROBES
]);
secsize
[
probe_sec
]
=
sizeof
(
dof_probe_t
)
*
provider
->
probe_count
;
offset
=
secoffs
[
probe_sec
]
+
secsize
[
probe_sec
];
// Allocate space for the probe offsets
secoffs
[
probeoffs_sec
]
=
align_size_up
(
offset
,
alignment_for
[
PROBE_OFFSETS
]);
secsize
[
probeoffs_sec
]
=
sizeof
(
uint32_t
)
*
provider
->
probe_count
;
offset
=
secoffs
[
probeoffs_sec
]
+
secsize
[
probeoffs_sec
];
// We need number of arguments argoffs
uint32_t
argscount
=
0
;
for
(
int
prbc
=
0
;
prbc
<
provider
->
probe_count
;
++
prbc
)
{
JVM_DTraceProbe
*
p
=
&
(
provider
->
probes
[
prbc
]);
symbolOop
sig
=
JNIHandles
::
resolve_jmethod_id
(
p
->
method
)
->
signature
();
argscount
+=
ArgumentCount
(
sig
).
size
();
}
secoffs
[
argoffs_sec
]
=
align_size_up
(
offset
,
alignment_for
[
ARG_OFFSETS
]);
secsize
[
argoffs_sec
]
=
sizeof
(
uint8_t
)
*
argscount
;
offset
=
secoffs
[
argoffs_sec
]
+
secsize
[
argoffs_sec
];
}
uint32_t
size
=
offset
;
uint8_t
*
dof
=
NEW_RESOURCE_ARRAY
(
uint8_t
,
size
);
if
(
!
dof
)
{
return
-
1
;
}
memset
((
void
*
)
dof
,
0
,
size
);
// Fill memory with proper values
dof_hdr_t
*
hdr
=
(
dof_hdr_t
*
)
dof
;
hdr
->
dofh_ident
[
DOF_ID_MAG0
]
=
DOF_MAG_MAG0
;
hdr
->
dofh_ident
[
DOF_ID_MAG1
]
=
DOF_MAG_MAG1
;
hdr
->
dofh_ident
[
DOF_ID_MAG2
]
=
DOF_MAG_MAG2
;
hdr
->
dofh_ident
[
DOF_ID_MAG3
]
=
DOF_MAG_MAG3
;
hdr
->
dofh_ident
[
DOF_ID_MODEL
]
=
DOF_MODEL_NATIVE
;
// No variants
hdr
->
dofh_ident
[
DOF_ID_ENCODING
]
=
DOF_ENCODE_NATIVE
;
// No variants
hdr
->
dofh_ident
[
DOF_ID_VERSION
]
=
DOF_VERSION_1
;
// No variants
hdr
->
dofh_ident
[
DOF_ID_DIFVERS
]
=
DIF_VERSION_2
;
// No variants
// all other fields of ident to zero
hdr
->
dofh_flags
=
0
;
hdr
->
dofh_hdrsize
=
sizeof
(
dof_hdr_t
);
hdr
->
dofh_secsize
=
sizeof
(
dof_sec_t
);
hdr
->
dofh_secnum
=
num_sections
;
hdr
->
dofh_secoff
=
sizeof
(
dof_hdr_t
);
hdr
->
dofh_loadsz
=
size
;
hdr
->
dofh_filesz
=
size
;
// First section: STRTAB
dof_sec_t
*
sec
=
(
dof_sec_t
*
)(
dof
+
sizeof
(
dof_hdr_t
));
sec
->
dofs_type
=
DOF_SECT_STRTAB
;
sec
->
dofs_align
=
alignment_for
[
STRTAB
];
sec
->
dofs_flags
=
DOF_SECF_LOAD
;
sec
->
dofs_entsize
=
0
;
sec
->
dofs_offset
=
secoffs
[
STRTAB
];
sec
->
dofs_size
=
secsize
[
STRTAB
];
// Make data for this section
char
*
str
=
(
char
*
)(
dof
+
sec
->
dofs_offset
);
*
str
=
0
;
str
+=
1
;
// ""
// Run through all strings again
for
(
int
prvc
=
0
;
prvc
<
providers_count
;
++
prvc
)
{
JVM_DTraceProvider
*
provider
=
&
providers
[
prvc
];
char
*
provider_name
=
java_lang_String
::
as_utf8_string
(
JNIHandles
::
resolve_non_null
(
provider
->
name
));
strcpy
(
str
,
provider_name
);
str
+=
strlen
(
provider_name
)
+
1
;
// All probes
for
(
int
prbc
=
0
;
prbc
<
provider
->
probe_count
;
++
prbc
)
{
JVM_DTraceProbe
*
p
=
&
(
provider
->
probes
[
prbc
]);
char
*
function
=
java_lang_String
::
as_utf8_string
(
JNIHandles
::
resolve_non_null
(
p
->
function
));
strcpy
(
str
,
function
);
str
+=
strlen
(
str
)
+
1
;
char
*
name
=
java_lang_String
::
as_utf8_string
(
JNIHandles
::
resolve_non_null
(
p
->
name
));
strcpy
(
str
,
name
);
str
+=
strlen
(
name
)
+
1
;
symbolOop
sig
=
JNIHandles
::
resolve_jmethod_id
(
p
->
method
)
->
signature
();
SignatureStream
ss
(
sig
);
for
(
;
!
ss
.
at_return_type
();
ss
.
next
())
{
BasicType
bt
=
ss
.
type
();
const
char
*
t
;
if
(
bt
==
T_OBJECT
&&
ss
.
as_symbol_or_null
()
==
vmSymbols
::
java_lang_String
())
{
t
=
string_sig
;
}
else
if
(
bt
==
T_LONG
)
{
t
=
long_sig
;
}
else
{
t
=
int_sig
;
}
strcpy
(
str
,
t
);
str
+=
strlen
(
t
)
+
1
;
}
}
}
curstr
=
1
;
for
(
int
prvc
=
0
;
prvc
<
providers_count
;
++
prvc
)
{
JVM_DTraceProvider
*
provider
=
&
providers
[
prvc
];
size_t
provider_sec
=
PROVIDERS
+
prvc
*
4
;
size_t
probe_sec
=
PROBES
+
prvc
*
4
;
size_t
probeoffs_sec
=
PROBE_OFFSETS
+
prvc
*
4
;
size_t
argoffs_sec
=
ARG_OFFSETS
+
prvc
*
4
;
// PROVIDER ///////////////////////////////////////////////////////////////
// Section header
sec
=
(
dof_sec_t
*
)
(
dof
+
sizeof
(
dof_hdr_t
)
+
sizeof
(
dof_sec_t
)
*
provider_sec
);
sec
->
dofs_type
=
DOF_SECT_PROVIDER
;
sec
->
dofs_align
=
alignment_for
[
PROVIDERS
];
sec
->
dofs_flags
=
DOF_SECF_LOAD
;
sec
->
dofs_entsize
=
0
;
sec
->
dofs_offset
=
secoffs
[
provider_sec
];
sec
->
dofs_size
=
secsize
[
provider_sec
];
// Make provider decriiption
dof_provider_t
*
prv
=
(
dof_provider_t
*
)(
dof
+
sec
->
dofs_offset
);
prv
->
dofpv_strtab
=
STRTAB
;
prv
->
dofpv_probes
=
probe_sec
;
prv
->
dofpv_prargs
=
argoffs_sec
;
prv
->
dofpv_proffs
=
probeoffs_sec
;
prv
->
dofpv_name
=
stroffs
[
curstr
++
];
// Index in string table
prv
->
dofpv_provattr
=
DOF_ATTR
(
provider
->
providerAttributes
.
nameStability
,
provider
->
providerAttributes
.
dataStability
,
provider
->
providerAttributes
.
dependencyClass
);
prv
->
dofpv_modattr
=
DOF_ATTR
(
provider
->
moduleAttributes
.
nameStability
,
provider
->
moduleAttributes
.
dataStability
,
provider
->
moduleAttributes
.
dependencyClass
);
prv
->
dofpv_funcattr
=
DOF_ATTR
(
provider
->
functionAttributes
.
nameStability
,
provider
->
functionAttributes
.
dataStability
,
provider
->
functionAttributes
.
dependencyClass
);
prv
->
dofpv_nameattr
=
DOF_ATTR
(
provider
->
nameAttributes
.
nameStability
,
provider
->
nameAttributes
.
dataStability
,
provider
->
nameAttributes
.
dependencyClass
);
prv
->
dofpv_argsattr
=
DOF_ATTR
(
provider
->
argsAttributes
.
nameStability
,
provider
->
argsAttributes
.
dataStability
,
provider
->
argsAttributes
.
dependencyClass
);
// PROBES /////////////////////////////////////////////////////////////////
// Section header
sec
=
(
dof_sec_t
*
)
(
dof
+
sizeof
(
dof_hdr_t
)
+
sizeof
(
dof_sec_t
)
*
probe_sec
);
sec
->
dofs_type
=
DOF_SECT_PROBES
;
sec
->
dofs_align
=
alignment_for
[
PROBES
];
sec
->
dofs_flags
=
DOF_SECF_LOAD
;
sec
->
dofs_entsize
=
sizeof
(
dof_probe_t
);
sec
->
dofs_offset
=
secoffs
[
probe_sec
];
sec
->
dofs_size
=
secsize
[
probe_sec
];
// Make probes descriptions
uint32_t
argsoffs
=
0
;
for
(
int
prbc
=
0
;
prbc
<
provider
->
probe_count
;
++
prbc
)
{
JVM_DTraceProbe
*
probe
=
&
(
provider
->
probes
[
prbc
]);
methodOop
m
=
JNIHandles
::
resolve_jmethod_id
(
probe
->
method
);
int
arg_count
=
ArgumentCount
(
m
->
signature
()).
size
();
assert
(
m
->
code
()
!=
NULL
,
"must have an nmethod"
);
dof_probe_t
*
prb
=
(
dof_probe_t
*
)(
dof
+
sec
->
dofs_offset
+
prbc
*
sizeof
(
dof_probe_t
));
prb
->
dofpr_addr
=
(
uint64_t
)
m
->
code
()
->
entry_point
();
prb
->
dofpr_func
=
stroffs
[
curstr
++
];
// Index in string table
prb
->
dofpr_name
=
stroffs
[
curstr
++
];
// Index in string table
prb
->
dofpr_nargv
=
stroffs
[
curstr
];
// Index in string table
// We spent siglen strings here
curstr
+=
arg_count
;
prb
->
dofpr_xargv
=
prb
->
dofpr_nargv
;
// Same bunch of strings
prb
->
dofpr_argidx
=
argsoffs
;
prb
->
dofpr_offidx
=
prbc
;
prb
->
dofpr_nargc
=
arg_count
;
prb
->
dofpr_xargc
=
arg_count
;
prb
->
dofpr_noffs
=
1
;
// Number of offsets
// Next bunch of offsets
argsoffs
+=
arg_count
;
}
// PROFFS /////////////////////////////////////////////////////////////////
// Section header
sec
=
(
dof_sec_t
*
)
(
dof
+
sizeof
(
dof_hdr_t
)
+
sizeof
(
dof_sec_t
)
*
probeoffs_sec
);
sec
->
dofs_type
=
DOF_SECT_PROFFS
;
sec
->
dofs_align
=
alignment_for
[
PROBE_OFFSETS
];
sec
->
dofs_flags
=
DOF_SECF_LOAD
;
sec
->
dofs_entsize
=
sizeof
(
uint32_t
);
sec
->
dofs_offset
=
secoffs
[
probeoffs_sec
];
sec
->
dofs_size
=
secsize
[
probeoffs_sec
];
// Make offsets
for
(
int
prbc
=
0
;
prbc
<
provider
->
probe_count
;
++
prbc
)
{
uint32_t
*
pof
=
(
uint32_t
*
)(
dof
+
sec
->
dofs_offset
+
sizeof
(
uint32_t
)
*
prbc
);
JVM_DTraceProbe
*
probe
=
&
(
provider
->
probes
[
prbc
]);
methodOop
m
=
JNIHandles
::
resolve_jmethod_id
(
probe
->
method
);
*
pof
=
m
->
code
()
->
trap_offset
();
}
// PRARGS /////////////////////////////////////////////////////////////////
// Section header
sec
=
(
dof_sec_t
*
)
(
dof
+
sizeof
(
dof_hdr_t
)
+
sizeof
(
dof_sec_t
)
*
argoffs_sec
);
sec
->
dofs_type
=
DOF_SECT_PRARGS
;
sec
->
dofs_align
=
alignment_for
[
ARG_OFFSETS
];
sec
->
dofs_flags
=
DOF_SECF_LOAD
;
sec
->
dofs_entsize
=
sizeof
(
uint8_t
);
sec
->
dofs_offset
=
secoffs
[
argoffs_sec
];
sec
->
dofs_size
=
secsize
[
argoffs_sec
];
// Make arguments
uint8_t
*
par
=
(
uint8_t
*
)(
dof
+
sec
->
dofs_offset
);
for
(
int
prbc
=
0
;
prbc
<
provider
->
probe_count
;
++
prbc
)
{
JVM_DTraceProbe
*
p
=
&
(
provider
->
probes
[
prbc
]);
symbolOop
sig
=
JNIHandles
::
resolve_jmethod_id
(
p
->
method
)
->
signature
();
uint8_t
count
=
(
uint8_t
)
ArgumentCount
(
sig
).
size
();
for
(
uint8_t
i
=
0
;
i
<
count
;
++
i
)
{
*
par
++
=
i
;
}
}
}
// Register module
return
dof_register
(
module
,
dof
,
moduleBaseAddress
);
}
void
DTraceJSDT
::
pd_dispose
(
int
handle
)
{
int
fd
;
if
(
handle
==
-
1
)
{
return
;
}
fd
=
dofhelper_open
();
if
(
fd
<
0
)
return
;
ioctl
(
fd
,
DTRACEHIOC_REMOVE
,
handle
);
close
(
fd
);
}
jboolean
DTraceJSDT
::
pd_is_supported
()
{
int
fd
=
dofhelper_open
();
if
(
fd
<
0
)
{
return
false
;
}
close
(
fd
);
return
true
;
}
static
const
char
*
dofSecTypeFor
(
uint32_t
type
)
{
switch
(
type
)
{
case
0
:
return
"DOF_SECT_NONE"
;
case
1
:
return
"DOF_SECT_COMMENTS"
;
case
2
:
return
"DOF_SECT_SOURCE"
;
case
3
:
return
"DOF_SECT_ECBDESC"
;
case
4
:
return
"DOF_SECT_PROBEDESC"
;
case
5
:
return
"DOF_SECT_ACTDESC"
;
case
6
:
return
"DOF_SECT_DIFOHDR"
;
case
7
:
return
"DOF_SECT_DIF"
;
case
8
:
return
"DOF_SECT_STRTAB"
;
case
9
:
return
"DOF_SECT_VARTAB"
;
case
10
:
return
"DOF_SECT_RELTAB"
;
case
11
:
return
"DOF_SECT_TYPETAB"
;
case
12
:
return
"DOF_SECT_URELHDR"
;
case
13
:
return
"DOF_SECT_KRELHDR"
;
case
14
:
return
"DOF_SECT_OPTDESC"
;
case
15
:
return
"DOF_SECT_PROVIDER"
;
case
16
:
return
"DOF_SECT_PROBES"
;
case
17
:
return
"DOF_SECT_PRARGS"
;
case
18
:
return
"DOF_SECT_PROFFS"
;
case
19
:
return
"DOF_SECT_INTTAB"
;
case
20
:
return
"DOF_SECT_UTSNAME"
;
case
21
:
return
"DOF_SECT_XLTAB"
;
case
22
:
return
"DOF_SECT_XLMEMBERS"
;
case
23
:
return
"DOF_SECT_XLIMPORT"
;
case
24
:
return
"DOF_SECT_XLEXPORT"
;
case
25
:
return
"DOF_SECT_PREXPORT"
;
case
26
:
return
"DOF_SECT_PRENOFFS"
;
default:
return
"<unknown>"
;
}
}
static
void
printDOFStringTabSec
(
void
*
dof
,
dof_sec_t
*
sec
)
{
size_t
tab
=
sec
->
dofs_offset
;
size_t
limit
=
sec
->
dofs_size
;
tty
->
print_cr
(
"// String Table:"
);
for
(
size_t
idx
=
0
;
idx
<
limit
;
/*empty*/
)
{
char
*
str
=
((
char
*
)
dof
)
+
tab
+
idx
;
tty
->
print_cr
(
"// [0x%x + 0x%x] '%s'"
,
tab
,
idx
,
str
);
idx
+=
strlen
(
str
)
+
1
;
}
}
static
void
printDOFProviderSec
(
void
*
dof
,
dof_sec_t
*
sec
)
{
dof_provider_t
*
prov
=
(
dof_provider_t
*
)((
char
*
)
dof
+
sec
->
dofs_offset
);
tty
->
print_cr
(
"// dof_provider_t {"
);
tty
->
print_cr
(
"// dofpv_strtab = %d"
,
prov
->
dofpv_strtab
);
tty
->
print_cr
(
"// dofpv_probes = %d"
,
prov
->
dofpv_probes
);
tty
->
print_cr
(
"// dofpv_prargs = %d"
,
prov
->
dofpv_prargs
);
tty
->
print_cr
(
"// dofpv_proffs = %d"
,
prov
->
dofpv_proffs
);
tty
->
print_cr
(
"// dofpv_name = 0x%x"
,
prov
->
dofpv_name
);
tty
->
print_cr
(
"// dofpv_provattr = 0x%08x"
,
prov
->
dofpv_provattr
);
tty
->
print_cr
(
"// dofpv_modattr = 0x%08x"
,
prov
->
dofpv_modattr
);
tty
->
print_cr
(
"// dofpv_funcattr = 0x%08x"
,
prov
->
dofpv_funcattr
);
tty
->
print_cr
(
"// dofpv_nameattr = 0x%08x"
,
prov
->
dofpv_nameattr
);
tty
->
print_cr
(
"// dofpv_argsattr = 0x%08x"
,
prov
->
dofpv_argsattr
);
tty
->
print_cr
(
"// }"
);
}
static
void
printDOFProbesSec
(
void
*
dof
,
dof_sec_t
*
sec
)
{
size_t
idx
=
sec
->
dofs_offset
;
size_t
limit
=
idx
+
sec
->
dofs_size
;
for
(
size_t
idx
=
sec
->
dofs_offset
;
idx
<
limit
;
idx
+=
sec
->
dofs_entsize
)
{
dof_probe_t
*
prb
=
(
dof_probe_t
*
)((
char
*
)
dof
+
idx
);
tty
->
print_cr
(
"// dof_probe_t {"
);
tty
->
print_cr
(
"// dofpr_addr = 0x%016llx"
,
prb
->
dofpr_addr
);
tty
->
print_cr
(
"// dofpr_func = 0x%x"
,
prb
->
dofpr_func
);
tty
->
print_cr
(
"// dofpr_name = 0x%x"
,
prb
->
dofpr_name
);
tty
->
print_cr
(
"// dofpr_nargv = 0x%x"
,
prb
->
dofpr_nargv
);
tty
->
print_cr
(
"// dofpr_xargv = 0x%x"
,
prb
->
dofpr_xargv
);
tty
->
print_cr
(
"// dofpr_argidx = 0x%x"
,
prb
->
dofpr_argidx
);
tty
->
print_cr
(
"// dofpr_offidx = 0x%x"
,
prb
->
dofpr_offidx
);
tty
->
print_cr
(
"// dofpr_nargc = %d"
,
prb
->
dofpr_nargc
);
tty
->
print_cr
(
"// dofpr_xargc = %d"
,
prb
->
dofpr_xargc
);
tty
->
print_cr
(
"// dofpr_noffs = %d"
,
prb
->
dofpr_noffs
);
tty
->
print_cr
(
"// }"
);
}
}
static
void
printDOFOffsetsSec
(
void
*
dof
,
dof_sec_t
*
sec
)
{
size_t
tab
=
sec
->
dofs_offset
;
size_t
limit
=
sec
->
dofs_size
;
tty
->
print_cr
(
"// Offsets:"
);
for
(
size_t
idx
=
0
;
idx
<
limit
;
idx
+=
sec
->
dofs_entsize
)
{
uint32_t
*
off
=
(
uint32_t
*
)((
char
*
)
dof
+
tab
+
idx
);
tty
->
print_cr
(
"// [0x%x + 0x%x]: %d"
,
tab
,
idx
,
*
off
);
}
}
static
void
printDOFArgsSec
(
void
*
dof
,
dof_sec_t
*
sec
)
{
size_t
tab
=
sec
->
dofs_offset
;
size_t
limit
=
sec
->
dofs_size
;
tty
->
print_cr
(
"// Arguments:"
);
for
(
size_t
idx
=
0
;
idx
<
limit
;
idx
+=
sec
->
dofs_entsize
)
{
uint8_t
*
arg
=
(
uint8_t
*
)((
char
*
)
dof
+
tab
+
idx
);
tty
->
print_cr
(
"// [0x%x + 0x%x]: %d"
,
tab
,
idx
,
*
arg
);
}
}
static
void
printDOFSection
(
void
*
dof
,
dof_sec_t
*
sec
)
{
tty
->
print_cr
(
"// dof_sec_t {"
);
tty
->
print_cr
(
"// dofs_type = 0x%x /* %s */"
,
sec
->
dofs_type
,
dofSecTypeFor
(
sec
->
dofs_type
));
tty
->
print_cr
(
"// dofs_align = %d"
,
sec
->
dofs_align
);
tty
->
print_cr
(
"// dofs_flags = 0x%x"
,
sec
->
dofs_flags
);
tty
->
print_cr
(
"// dofs_entsize = %d"
,
sec
->
dofs_entsize
);
tty
->
print_cr
(
"// dofs_offset = 0x%llx"
,
sec
->
dofs_offset
);
tty
->
print_cr
(
"// dofs_size = %lld"
,
sec
->
dofs_size
);
tty
->
print_cr
(
"// }"
);
switch
(
sec
->
dofs_type
)
{
case
DOF_SECT_STRTAB
:
printDOFStringTabSec
(
dof
,
sec
);
break
;
case
DOF_SECT_PROVIDER
:
printDOFProviderSec
(
dof
,
sec
);
break
;
case
DOF_SECT_PROBES
:
printDOFProbesSec
(
dof
,
sec
);
break
;
case
DOF_SECT_PROFFS
:
printDOFOffsetsSec
(
dof
,
sec
);
break
;
case
DOF_SECT_PRARGS
:
printDOFArgsSec
(
dof
,
sec
);
break
;
default:
tty
->
print_cr
(
"// <section type not recognized>"
);
}
}
static
void
printDOFHeader
(
dof_hdr_t
*
hdr
)
{
tty
->
print_cr
(
"// dof_hdr_t {"
);
tty
->
print_cr
(
"// dofh_ident[DOF_ID_MAG0] = 0x%x"
,
hdr
->
dofh_ident
[
DOF_ID_MAG0
]);
tty
->
print_cr
(
"// dofh_ident[DOF_ID_MAG1] = 0x%x"
,
hdr
->
dofh_ident
[
DOF_ID_MAG1
]);
tty
->
print_cr
(
"// dofh_ident[DOF_ID_MAG2] = 0x%x"
,
hdr
->
dofh_ident
[
DOF_ID_MAG2
]);
tty
->
print_cr
(
"// dofh_ident[DOF_ID_MAG3] = 0x%x"
,
hdr
->
dofh_ident
[
DOF_ID_MAG3
]);
tty
->
print_cr
(
"// dofh_ident[DOF_ID_MODEL] = 0x%x"
,
hdr
->
dofh_ident
[
DOF_ID_MODEL
]);
tty
->
print_cr
(
"// dofh_ident[DOF_ID_ENCODING] = 0x%x"
,
hdr
->
dofh_ident
[
DOF_ID_ENCODING
]);
tty
->
print_cr
(
"// dofh_ident[DOF_ID_VERSION] = 0x%x"
,
hdr
->
dofh_ident
[
DOF_ID_VERSION
]);
tty
->
print_cr
(
"// dofh_ident[DOF_ID_DIFVERS] = 0x%x"
,
hdr
->
dofh_ident
[
DOF_ID_DIFVERS
]);
tty
->
print_cr
(
"// dofh_flags = 0x%x"
,
hdr
->
dofh_flags
);
tty
->
print_cr
(
"// dofh_hdrsize = %d"
,
hdr
->
dofh_hdrsize
);
tty
->
print_cr
(
"// dofh_secsize = %d"
,
hdr
->
dofh_secsize
);
tty
->
print_cr
(
"// dofh_secnum = %d"
,
hdr
->
dofh_secnum
);
tty
->
print_cr
(
"// dofh_secoff = %lld"
,
hdr
->
dofh_secoff
);
tty
->
print_cr
(
"// dofh_loadsz = %lld"
,
hdr
->
dofh_loadsz
);
tty
->
print_cr
(
"// dofh_filesz = %lld"
,
hdr
->
dofh_filesz
);
tty
->
print_cr
(
"// }"
);
}
static
void
printDOF
(
void
*
dof
)
{
dof_hdr_t
*
hdr
=
(
dof_hdr_t
*
)
dof
;
printDOFHeader
(
hdr
);
for
(
int
i
=
0
;
i
<
hdr
->
dofh_secnum
;
++
i
)
{
dof_sec_t
*
sec
=
(
dof_sec_t
*
)((
char
*
)
dof
+
sizeof
(
dof_hdr_t
)
+
i
*
sizeof
(
dof_sec_t
));
tty
->
print_cr
(
"// [Section #%d]"
,
i
);
printDOFSection
(
dof
,
sec
);
}
}
/**
* This prints out hex data in a 'windbg' or 'xxd' form, where each line is:
* <hex-address>: 8 * <hex-halfword> <ascii translation>
* example:
* 0000000: 7f44 4f46 0102 0102 0000 0000 0000 0000 .DOF............
* 0000010: 0000 0000 0000 0040 0000 0020 0000 0005 .......@... ....
* 0000020: 0000 0000 0000 0040 0000 0000 0000 015d .......@.......]
* ...
*/
static
void
printDOFRawData
(
void
*
dof
)
{
size_t
size
=
((
dof_hdr_t
*
)
dof
)
->
dofh_loadsz
;
size_t
limit
=
(
size
+
16
)
/
16
*
16
;
for
(
size_t
i
=
0
;
i
<
limit
;
++
i
)
{
if
(
i
%
16
==
0
)
{
tty
->
print
(
"%07x:"
,
i
);
}
if
(
i
%
2
==
0
)
{
tty
->
print
(
" "
);
}
if
(
i
<
size
)
{
tty
->
print
(
"%02x"
,
((
unsigned
char
*
)
dof
)[
i
]);
}
else
{
tty
->
print
(
" "
);
}
if
((
i
+
1
)
%
16
==
0
)
{
tty
->
print
(
" "
);
for
(
size_t
j
=
0
;
j
<
16
;
++
j
)
{
size_t
idx
=
i
+
j
-
15
;
char
c
=
((
char
*
)
dof
)[
idx
];
if
(
idx
<
size
)
{
tty
->
print
(
"%c"
,
c
>=
32
&&
c
<=
126
?
c
:
'.'
);
}
}
tty
->
print_cr
(
""
);
}
}
tty
->
print_cr
(
""
);
}
static
void
printDOFHelper
(
dof_helper_t
*
helper
)
{
tty
->
print_cr
(
"// dof_helper_t {"
);
tty
->
print_cr
(
"// dofhp_mod =
\"
%s
\"
"
,
helper
->
dofhp_mod
);
tty
->
print_cr
(
"// dofhp_addr = 0x%016llx"
,
helper
->
dofhp_addr
);
tty
->
print_cr
(
"// dofhp_dof = 0x%016llx"
,
helper
->
dofhp_dof
);
printDOF
((
void
*
)
helper
->
dofhp_dof
);
tty
->
print_cr
(
"// }"
);
printDOFRawData
((
void
*
)
helper
->
dofhp_dof
);
}
#else // ndef HAVE_DTRACE_H
// Get here if we're not building on at least Solaris 10
int
DTraceJSDT
::
pd_activate
(
void
*
baseAddress
,
jstring
module
,
jint
provider_count
,
JVM_DTraceProvider
*
providers
)
{
return
-
1
;
}
void
DTraceJSDT
::
pd_dispose
(
int
handle
)
{
}
jboolean
DTraceJSDT
::
pd_is_supported
()
{
return
false
;
}
#endif
src/os/windows/vm/dtraceJSDT_windows.cpp
0 → 100644
浏览文件 @
15eb4e64
/*
* 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
;
}
src/share/vm/asm/codeBuffer.hpp
浏览文件 @
15eb4e64
...
@@ -36,6 +36,7 @@ public:
...
@@ -36,6 +36,7 @@ public:
Verified_Entry
,
Verified_Entry
,
Frame_Complete
,
// Offset in the code where the frame setup is (for forte stackwalks) is complete
Frame_Complete
,
// Offset in the code where the frame setup is (for forte stackwalks) is complete
OSR_Entry
,
OSR_Entry
,
Dtrace_trap
=
OSR_Entry
,
// dtrace probes can never have an OSR entry so reuse it
Exceptions
,
// Offset where exception handler lives
Exceptions
,
// Offset where exception handler lives
Deopt
,
// Offset where deopt handler lives
Deopt
,
// Offset where deopt handler lives
max_Entries
};
max_Entries
};
...
...
src/share/vm/code/nmethod.cpp
浏览文件 @
15eb4e64
...
@@ -27,7 +27,6 @@
...
@@ -27,7 +27,6 @@
#ifdef DTRACE_ENABLED
#ifdef DTRACE_ENABLED
// Only bother with this argument setup if dtrace is available
// Only bother with this argument setup if dtrace is available
HS_DTRACE_PROBE_DECL8
(
hotspot
,
compiled__method__load
,
HS_DTRACE_PROBE_DECL8
(
hotspot
,
compiled__method__load
,
...
@@ -438,7 +437,6 @@ nmethod* nmethod::new_native_nmethod(methodHandle method,
...
@@ -438,7 +437,6 @@ nmethod* nmethod::new_native_nmethod(methodHandle method,
{
{
MutexLockerEx
mu
(
CodeCache_lock
,
Mutex
::
_no_safepoint_check_flag
);
MutexLockerEx
mu
(
CodeCache_lock
,
Mutex
::
_no_safepoint_check_flag
);
int
native_nmethod_size
=
allocation_size
(
code_buffer
,
sizeof
(
nmethod
));
int
native_nmethod_size
=
allocation_size
(
code_buffer
,
sizeof
(
nmethod
));
const
int
dummy
=
-
1
;
// Flag to force proper "operator new"
CodeOffsets
offsets
;
CodeOffsets
offsets
;
offsets
.
set_value
(
CodeOffsets
::
Verified_Entry
,
vep_offset
);
offsets
.
set_value
(
CodeOffsets
::
Verified_Entry
,
vep_offset
);
offsets
.
set_value
(
CodeOffsets
::
Frame_Complete
,
frame_complete
);
offsets
.
set_value
(
CodeOffsets
::
Frame_Complete
,
frame_complete
);
...
@@ -461,6 +459,41 @@ nmethod* nmethod::new_native_nmethod(methodHandle method,
...
@@ -461,6 +459,41 @@ nmethod* nmethod::new_native_nmethod(methodHandle method,
return
nm
;
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
,
nmethod
*
nmethod
::
new_nmethod
(
methodHandle
method
,
int
compile_id
,
int
compile_id
,
int
entry_bci
,
int
entry_bci
,
...
@@ -558,6 +591,9 @@ nmethod::nmethod(
...
@@ -558,6 +591,9 @@ nmethod::nmethod(
_exception_offset
=
0
;
_exception_offset
=
0
;
_deoptimize_offset
=
0
;
_deoptimize_offset
=
0
;
_orig_pc_offset
=
0
;
_orig_pc_offset
=
0
;
#ifdef HAVE_DTRACE_H
_trap_offset
=
0
;
#endif // def HAVE_DTRACE_H
_stub_offset
=
data_offset
();
_stub_offset
=
data_offset
();
_consts_offset
=
data_offset
();
_consts_offset
=
data_offset
();
_scopes_data_offset
=
data_offset
();
_scopes_data_offset
=
data_offset
();
...
@@ -615,6 +651,90 @@ nmethod::nmethod(
...
@@ -615,6 +651,90 @@ nmethod::nmethod(
Events
::
log
(
"Create nmethod "
INTPTR_FORMAT
,
this
);
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
)
{
void
*
nmethod
::
operator
new
(
size_t
size
,
int
nmethod_size
)
{
// Always leave some room in the CodeCache for I2C/C2I adapters
// Always leave some room in the CodeCache for I2C/C2I adapters
...
@@ -658,6 +778,9 @@ nmethod::nmethod(
...
@@ -658,6 +778,9 @@ nmethod::nmethod(
_link
=
NULL
;
_link
=
NULL
;
_compiler
=
compiler
;
_compiler
=
compiler
;
_orig_pc_offset
=
orig_pc_offset
;
_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
());
_stub_offset
=
instructions_offset
()
+
code_buffer
->
total_offset_of
(
code_buffer
->
stubs
()
->
start
());
// Exception handler and deopt handler are in the stub section
// Exception handler and deopt handler are in the stub section
...
@@ -1885,7 +2008,6 @@ void nmethod::print() const {
...
@@ -1885,7 +2008,6 @@ void nmethod::print() const {
}
else
if
(
is_compiled_by_c2
())
{
}
else
if
(
is_compiled_by_c2
())
{
tty
->
print
(
"(c2) "
);
tty
->
print
(
"(c2) "
);
}
else
{
}
else
{
assert
(
is_native_method
(),
"Who else?"
);
tty
->
print
(
"(nm) "
);
tty
->
print
(
"(nm) "
);
}
}
...
...
src/share/vm/code/nmethod.hpp
浏览文件 @
15eb4e64
...
@@ -140,6 +140,9 @@ class nmethod : public CodeBlob {
...
@@ -140,6 +140,9 @@ class nmethod : public CodeBlob {
int
_exception_offset
;
int
_exception_offset
;
// All deoptee's will resume execution at this location described by this offset
// All deoptee's will resume execution at this location described by this offset
int
_deoptimize_offset
;
int
_deoptimize_offset
;
#ifdef HAVE_DTRACE_H
int
_trap_offset
;
#endif // def HAVE_DTRACE_H
int
_stub_offset
;
int
_stub_offset
;
int
_consts_offset
;
int
_consts_offset
;
int
_scopes_data_offset
;
int
_scopes_data_offset
;
...
@@ -211,6 +214,15 @@ class nmethod : public CodeBlob {
...
@@ -211,6 +214,15 @@ class nmethod : public CodeBlob {
ByteSize
basic_lock_sp_offset
,
/* synchronized natives only */
ByteSize
basic_lock_sp_offset
,
/* synchronized natives only */
OopMapSet
*
oop_maps
);
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
// Creation support
nmethod
(
methodOop
method
,
nmethod
(
methodOop
method
,
int
nmethod_size
,
int
nmethod_size
,
...
@@ -272,6 +284,22 @@ class nmethod : public CodeBlob {
...
@@ -272,6 +284,22 @@ class nmethod : public CodeBlob {
ByteSize
basic_lock_sp_offset
,
ByteSize
basic_lock_sp_offset
,
OopMapSet
*
oop_maps
);
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
// accessors
methodOop
method
()
const
{
return
_method
;
}
methodOop
method
()
const
{
return
_method
;
}
AbstractCompiler
*
compiler
()
const
{
return
_compiler
;
}
AbstractCompiler
*
compiler
()
const
{
return
_compiler
;
}
...
...
src/share/vm/includeDB_core
浏览文件 @
15eb4e64
...
@@ -1497,6 +1497,30 @@ dtraceAttacher.cpp resourceArea.hpp
...
@@ -1497,6 +1497,30 @@ dtraceAttacher.cpp resourceArea.hpp
dtraceAttacher.cpp vmThread.hpp
dtraceAttacher.cpp vmThread.hpp
dtraceAttacher.cpp vm_operations.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
// dump is jck optional, put cpp deps in includeDB_features
events.cpp allocation.inline.hpp
events.cpp allocation.inline.hpp
...
@@ -2400,6 +2424,7 @@ jvm.cpp classLoader.hpp
...
@@ -2400,6 +2424,7 @@ jvm.cpp classLoader.hpp
jvm.cpp collectedHeap.inline.hpp
jvm.cpp collectedHeap.inline.hpp
jvm.cpp copy.hpp
jvm.cpp copy.hpp
jvm.cpp defaultStream.hpp
jvm.cpp defaultStream.hpp
jvm.cpp dtraceJSDT.hpp
jvm.cpp events.hpp
jvm.cpp events.hpp
jvm.cpp handles.inline.hpp
jvm.cpp handles.inline.hpp
jvm.cpp histogram.hpp
jvm.cpp histogram.hpp
...
...
src/share/vm/oops/methodOop.cpp
浏览文件 @
15eb4e64
...
@@ -672,9 +672,6 @@ void methodOopDesc::link_method(methodHandle h_method, TRAPS) {
...
@@ -672,9 +672,6 @@ void methodOopDesc::link_method(methodHandle h_method, TRAPS) {
}
}
address
methodOopDesc
::
make_adapters
(
methodHandle
mh
,
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
// Adapters for compiled code are made eagerly here. They are fairly
// small (generally < 100 bytes) and quick to make (and cached and shared)
// small (generally < 100 bytes) and quick to make (and cached and shared)
// so making them eagerly shouldn't be too expensive.
// so making them eagerly shouldn't be too expensive.
...
...
src/share/vm/prims/jvm.cpp
浏览文件 @
15eb4e64
...
@@ -4168,6 +4168,36 @@ JVM_ENTRY(jboolean, JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fid, jlong o
...
@@ -4168,6 +4168,36 @@ JVM_ENTRY(jboolean, JVM_CX8Field(JNIEnv *env, jobject obj, jfieldID fid, jlong o
return
res
==
oldVal
;
return
res
==
oldVal
;
JVM_END
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,
// Returns an array of all live Thread objects (VM internal JavaThreads,
// jvmti agent threads, and JNI attaching threads are skipped)
// jvmti agent threads, and JNI attaching threads are skipped)
// See CR 6404306 regarding JNI attaching threads
// 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
...
@@ -4496,3 +4526,4 @@ JVM_ENTRY(void, JVM_GetVersionInfo(JNIEnv* env, jvm_version_info* info, size_t i
#endif // KERNEL
#endif // KERNEL
}
}
JVM_END
JVM_END
src/share/vm/prims/jvm.h
浏览文件 @
15eb4e64
...
@@ -606,6 +606,83 @@ JVM_SupportsCX8(void);
...
@@ -606,6 +606,83 @@ JVM_SupportsCX8(void);
JNIEXPORT
jboolean
JNICALL
JNIEXPORT
jboolean
JNICALL
JVM_CX8Field
(
JNIEnv
*
env
,
jobject
obj
,
jfieldID
fldID
,
jlong
oldVal
,
jlong
newVal
);
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
PART 2: Support for the Verifier and Class File Format Checker
************************************************************************/
************************************************************************/
...
...
src/share/vm/runtime/dtraceJSDT.cpp
0 → 100644
浏览文件 @
15eb4e64
/*
* 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
src/share/vm/runtime/dtraceJSDT.hpp
0 → 100644
浏览文件 @
15eb4e64
/*
* 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
;
}
};
src/share/vm/runtime/globals.hpp
浏览文件 @
15eb4e64
...
@@ -3188,6 +3188,9 @@ class CommandLineFlags {
...
@@ -3188,6 +3188,9 @@ class CommandLineFlags {
product(bool, RelaxAccessControlCheck, false, \
product(bool, RelaxAccessControlCheck, false, \
"Relax the access control checks in the verifier") \
"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, \
product(bool, UseVMInterruptibleIO, true, \
"(Unstable, Solaris-specific) Thread interrupt before or with " \
"(Unstable, Solaris-specific) Thread interrupt before or with " \
"EINTR for I/O operations results in OS_INTRPT")
"EINTR for I/O operations results in OS_INTRPT")
...
...
src/share/vm/runtime/sharedRuntime.cpp
浏览文件 @
15eb4e64
...
@@ -1748,11 +1748,6 @@ int AdapterHandlerLibrary::get_create_adapter_index(methodHandle method) {
...
@@ -1748,11 +1748,6 @@ int AdapterHandlerLibrary::get_create_adapter_index(methodHandle method) {
// _fingerprints array (it is not safe for concurrent readers and a single
// _fingerprints array (it is not safe for concurrent readers and a single
// writer: this can be fixed if it becomes a problem).
// 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
// Get the address of the ic_miss handlers before we grab the
// AdapterHandlerLibrary_lock. This fixes bug 6236259 which
// AdapterHandlerLibrary_lock. This fixes bug 6236259 which
// was caused by the initialization of the stubs happening
// was caused by the initialization of the stubs happening
...
@@ -1997,6 +1992,64 @@ nmethod *AdapterHandlerLibrary::create_native_wrapper(methodHandle method) {
...
@@ -1997,6 +1992,64 @@ nmethod *AdapterHandlerLibrary::create_native_wrapper(methodHandle method) {
return
nm
;
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
// Java-Java calling convention
// (what you use when Java calls Java)
// (what you use when Java calls Java)
...
...
src/share/vm/runtime/sharedRuntime.hpp
浏览文件 @
15eb4e64
...
@@ -59,6 +59,10 @@ class SharedRuntime: AllStatic {
...
@@ -59,6 +59,10 @@ class SharedRuntime: AllStatic {
#endif // !PRODUCT
#endif // !PRODUCT
public:
public:
// max bytes for each dtrace string parameter
enum
{
max_dtrace_string_size
=
256
};
// The following arithmetic routines are used on platforms that do
// The following arithmetic routines are used on platforms that do
// not have machine instructions to implement their functionality.
// not have machine instructions to implement their functionality.
// Do not remove these.
// Do not remove these.
...
@@ -258,9 +262,6 @@ class SharedRuntime: AllStatic {
...
@@ -258,9 +262,6 @@ class SharedRuntime: AllStatic {
public:
public:
static
void
create_native_wrapper
(
JavaThread
*
thread
,
methodOop
method
);
// Read the array of BasicTypes from a Java signature, and compute where
// 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
// 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
// reg_hi refer to 4-byte quantities. Values less than SharedInfo::stack0 are
...
@@ -354,6 +355,19 @@ class SharedRuntime: AllStatic {
...
@@ -354,6 +355,19 @@ class SharedRuntime: AllStatic {
VMRegPair
*
regs
,
VMRegPair
*
regs
,
BasicType
ret_type
);
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
// A compiled caller has just called the interpreter, but compiled code
// exists. Patch the caller so he no longer calls into the interpreter.
// exists. Patch the caller so he no longer calls into the interpreter.
static
void
fixup_callers_callsite
(
methodOopDesc
*
moop
,
address
ret_pc
);
static
void
fixup_callers_callsite
(
methodOopDesc
*
moop
,
address
ret_pc
);
...
@@ -492,42 +506,55 @@ class AdapterHandlerEntry : public CHeapObj {
...
@@ -492,42 +506,55 @@ class AdapterHandlerEntry : public CHeapObj {
address
_c2i_unverified_entry
;
address
_c2i_unverified_entry
;
public:
public:
// The name we give all buffer blobs
static
const
char
*
name
;
AdapterHandlerEntry
(
address
i2c_entry
,
address
c2i_entry
,
address
c2i_unverified_entry
)
:
AdapterHandlerEntry
(
address
i2c_entry
,
address
c2i_entry
,
address
c2i_unverified_entry
)
:
_i2c_entry
(
i2c_entry
),
_i2c_entry
(
i2c_entry
),
_c2i_entry
(
c2i_entry
),
_c2i_entry
(
c2i_entry
),
_c2i_unverified_entry
(
c2i_unverified_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_i2c_entry
()
{
return
_i2c_entry
;
}
address
get_c2i_entry
()
{
return
_c2i_entry
;
}
address
get_c2i_entry
()
{
return
_c2i_entry
;
}
address
get_c2i_unverified_entry
()
{
return
_c2i_unverified_entry
;
}
address
get_c2i_unverified_entry
()
{
return
_c2i_unverified_entry
;
}
void
relocate
(
address
new_base
);
void
relocate
(
address
new_base
);
#ifndef PRODUCT
#ifndef PRODUCT
void
print
();
void
print
();
#endif
/* PRODUCT */
#endif
/* PRODUCT */
};
};
class
AdapterHandlerLibrary
:
public
AllStatic
{
class
AdapterHandlerLibrary
:
public
AllStatic
{
private:
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
{
enum
{
AbstractMethodHandler
=
1
// special handler for abstract methods
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
void
initialize
();
static
AdapterHandlerEntry
*
get_entry
(
int
index
)
{
return
_handlers
->
at
(
index
);
}
static
int
get_create_adapter_index
(
methodHandle
method
);
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_i2c_entry
(
int
index
)
{
static
address
get_c2i_entry
(
int
index
)
{
return
get_entry
(
index
)
->
get_c2i_entry
();
}
return
get_entry
(
index
)
->
get_i2c_entry
();
static
address
get_c2i_unverified_entry
(
int
index
)
{
return
get_entry
(
index
)
->
get_c2i_unverified_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:
public:
static
AdapterHandlerEntry
*
get_entry
(
int
index
)
{
return
_handlers
->
at
(
index
);
}
static
nmethod
*
create_native_wrapper
(
methodHandle
method
);
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
#ifndef PRODUCT
static
void
print_handler
(
CodeBlob
*
b
);
static
void
print_handler
(
CodeBlob
*
b
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录