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