Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
34551e5c
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看板
提交
34551e5c
编写于
11月 02, 2012
作者:
A
amurillo
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
eaefb664
979de2be
变更
50
显示空白变更内容
内联
并排
Showing
50 changed file
with
423 addition
and
2390 deletion
+423
-2390
make/Makefile
make/Makefile
+16
-0
make/hotspot_version
make/hotspot_version
+1
-1
src/cpu/zero/vm/cppInterpreterGenerator_zero.hpp
src/cpu/zero/vm/cppInterpreterGenerator_zero.hpp
+9
-4
src/cpu/zero/vm/cppInterpreter_zero.cpp
src/cpu/zero/vm/cppInterpreter_zero.cpp
+18
-549
src/cpu/zero/vm/cppInterpreter_zero.hpp
src/cpu/zero/vm/cppInterpreter_zero.hpp
+0
-2
src/cpu/zero/vm/frame_zero.cpp
src/cpu/zero/vm/frame_zero.cpp
+3
-4
src/cpu/zero/vm/frame_zero.inline.hpp
src/cpu/zero/vm/frame_zero.inline.hpp
+2
-0
src/cpu/zero/vm/icBuffer_zero.cpp
src/cpu/zero/vm/icBuffer_zero.cpp
+2
-3
src/cpu/zero/vm/methodHandles_zero.cpp
src/cpu/zero/vm/methodHandles_zero.cpp
+151
-18
src/cpu/zero/vm/methodHandles_zero.hpp
src/cpu/zero/vm/methodHandles_zero.hpp
+9
-1
src/cpu/zero/vm/register_zero.hpp
src/cpu/zero/vm/register_zero.hpp
+3
-0
src/cpu/zero/vm/relocInfo_zero.cpp
src/cpu/zero/vm/relocInfo_zero.cpp
+4
-0
src/cpu/zero/vm/sharedRuntime_zero.cpp
src/cpu/zero/vm/sharedRuntime_zero.cpp
+19
-12
src/os/bsd/vm/attachListener_bsd.cpp
src/os/bsd/vm/attachListener_bsd.cpp
+0
-12
src/os/bsd/vm/osThread_bsd.hpp
src/os/bsd/vm/osThread_bsd.hpp
+0
-6
src/os/bsd/vm/os_bsd.cpp
src/os/bsd/vm/os_bsd.cpp
+10
-1293
src/os/bsd/vm/os_bsd.hpp
src/os/bsd/vm/os_bsd.hpp
+0
-84
src/os/windows/vm/os_windows.cpp
src/os/windows/vm/os_windows.cpp
+9
-69
src/os_cpu/bsd_x86/vm/bytes_bsd_x86.inline.hpp
src/os_cpu/bsd_x86/vm/bytes_bsd_x86.inline.hpp
+0
-4
src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp
src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp
+0
-2
src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
+2
-125
src/os_cpu/bsd_zero/vm/globals_bsd_zero.hpp
src/os_cpu/bsd_zero/vm/globals_bsd_zero.hpp
+0
-1
src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp
src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp
+2
-93
src/os_cpu/linux_sparc/vm/globals_linux_sparc.hpp
src/os_cpu/linux_sparc/vm/globals_linux_sparc.hpp
+0
-2
src/os_cpu/linux_x86/vm/globals_linux_x86.hpp
src/os_cpu/linux_x86/vm/globals_linux_x86.hpp
+0
-2
src/os_cpu/linux_zero/vm/globals_linux_zero.hpp
src/os_cpu/linux_zero/vm/globals_linux_zero.hpp
+0
-1
src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp
src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp
+0
-2
src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp
src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp
+0
-2
src/os_cpu/windows_x86/vm/globals_windows_x86.hpp
src/os_cpu/windows_x86/vm/globals_windows_x86.hpp
+0
-2
src/os_cpu/windows_x86/vm/os_windows_x86.cpp
src/os_cpu/windows_x86/vm/os_windows_x86.cpp
+0
-3
src/share/vm/asm/codeBuffer.cpp
src/share/vm/asm/codeBuffer.cpp
+1
-1
src/share/vm/classfile/vmSymbols.hpp
src/share/vm/classfile/vmSymbols.hpp
+1
-0
src/share/vm/interpreter/abstractInterpreter.hpp
src/share/vm/interpreter/abstractInterpreter.hpp
+1
-0
src/share/vm/interpreter/bytecodeInterpreter.cpp
src/share/vm/interpreter/bytecodeInterpreter.cpp
+52
-17
src/share/vm/interpreter/bytecodeInterpreter.hpp
src/share/vm/interpreter/bytecodeInterpreter.hpp
+4
-1
src/share/vm/interpreter/cppInterpreter.cpp
src/share/vm/interpreter/cppInterpreter.cpp
+5
-1
src/share/vm/interpreter/interpreter.cpp
src/share/vm/interpreter/interpreter.cpp
+8
-0
src/share/vm/interpreter/templateInterpreter.cpp
src/share/vm/interpreter/templateInterpreter.cpp
+1
-5
src/share/vm/memory/collectorPolicy.cpp
src/share/vm/memory/collectorPolicy.cpp
+2
-1
src/share/vm/prims/jvmti.xml
src/share/vm/prims/jvmti.xml
+28
-19
src/share/vm/prims/jvmtiEnvBase.hpp
src/share/vm/prims/jvmtiEnvBase.hpp
+1
-1
src/share/vm/runtime/arguments.cpp
src/share/vm/runtime/arguments.cpp
+7
-0
src/share/vm/runtime/globals.hpp
src/share/vm/runtime/globals.hpp
+0
-3
src/share/vm/runtime/java.cpp
src/share/vm/runtime/java.cpp
+1
-0
src/share/vm/runtime/java.hpp
src/share/vm/runtime/java.hpp
+8
-0
src/share/vm/runtime/thread.cpp
src/share/vm/runtime/thread.cpp
+23
-0
src/share/vm/runtime/vmStructs.cpp
src/share/vm/runtime/vmStructs.cpp
+1
-1
src/share/vm/utilities/macros.hpp
src/share/vm/utilities/macros.hpp
+16
-0
src/share/vm/utilities/taskqueue.hpp
src/share/vm/utilities/taskqueue.hpp
+0
-42
src/share/vm/utilities/vmError.cpp
src/share/vm/utilities/vmError.cpp
+3
-1
未找到文件。
make/Makefile
浏览文件 @
34551e5c
...
@@ -453,14 +453,30 @@ ifneq ($(OSNAME),windows)
...
@@ -453,14 +453,30 @@ ifneq ($(OSNAME),windows)
ifeq
($(JVM_VARIANT_ZEROSHARK), true)
ifeq
($(JVM_VARIANT_ZEROSHARK), true)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX)
:
$(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX)
:
$(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
$
(
install-file
)
$
(
install-file
)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo)
:
$(SHARK_DIR)/%.debuginfo
$
(
install-file
)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz
:
$(SHARK_DIR)/%.diz
$
(
install-file
)
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX)
:
$(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX)
:
$(SHARK_DIR)/%.$(LIBRARY_SUFFIX)
$
(
install-file
)
$
(
install-file
)
$(EXPORT_SERVER_DIR)/%.debuginfo
:
$(SHARK_DIR)/%.debuginfo
$
(
install-file
)
$(EXPORT_SERVER_DIR)/%.diz
:
$(SHARK_DIR)/%.diz
$
(
install-file
)
endif
endif
ifeq
($(JVM_VARIANT_ZERO), true)
ifeq
($(JVM_VARIANT_ZERO), true)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX)
:
$(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX)
:
$(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
$
(
install-file
)
$
(
install-file
)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.debuginfo
:
$(ZERO_DIR)/%.debuginfo
$
(
install-file
)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.diz
:
$(ZERO_DIR)/%.diz
$
(
install-file
)
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX)
:
$(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
$(EXPORT_SERVER_DIR)/%.$(LIBRARY_SUFFIX)
:
$(ZERO_DIR)/%.$(LIBRARY_SUFFIX)
$
(
install-file
)
$
(
install-file
)
$(EXPORT_SERVER_DIR)/%.debuginfo
:
$(ZERO_DIR)/%.debuginfo
$
(
install-file
)
$(EXPORT_SERVER_DIR)/%.diz
:
$(ZERO_DIR)/%.diz
$
(
install-file
)
endif
endif
ifeq
($(JVM_VARIANT_MINIMAL1), true)
ifeq
($(JVM_VARIANT_MINIMAL1), true)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX)
:
$(MINIMAL1_DIR)/%.$(LIBRARY_SUFFIX)
$(EXPORT_JRE_LIB_ARCH_DIR)/%.$(LIBRARY_SUFFIX)
:
$(MINIMAL1_DIR)/%.$(LIBRARY_SUFFIX)
...
...
make/hotspot_version
浏览文件 @
34551e5c
...
@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2012
...
@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2012
HS_MAJOR_VER=25
HS_MAJOR_VER=25
HS_MINOR_VER=0
HS_MINOR_VER=0
HS_BUILD_NUMBER=0
7
HS_BUILD_NUMBER=0
8
JDK_MAJOR_VER=1
JDK_MAJOR_VER=1
JDK_MINOR_VER=8
JDK_MINOR_VER=8
...
...
src/cpu/zero/vm/cppInterpreterGenerator_zero.hpp
浏览文件 @
34551e5c
...
@@ -31,12 +31,17 @@
...
@@ -31,12 +31,17 @@
return
_masm
;
return
_masm
;
}
}
p
rotected
:
p
ublic
:
address
generate_entry
(
address
entry_point
)
{
static
address
generate_entry_impl
(
MacroAssembler
*
masm
,
address
entry_point
)
{
ZeroEntry
*
entry
=
(
ZeroEntry
*
)
assembler
()
->
pc
();
ZeroEntry
*
entry
=
(
ZeroEntry
*
)
masm
->
pc
();
assembler
()
->
advance
(
sizeof
(
ZeroEntry
));
masm
->
advance
(
sizeof
(
ZeroEntry
));
entry
->
set_entry_point
(
entry_point
);
entry
->
set_entry_point
(
entry_point
);
return
(
address
)
entry
;
return
(
address
)
entry
;
}
}
protected
:
address
generate_entry
(
address
entry_point
)
{
return
generate_entry_impl
(
assembler
(),
entry_point
);
}
#endif // CPU_ZERO_VM_CPPINTERPRETERGENERATOR_ZERO_HPP
#endif // CPU_ZERO_VM_CPPINTERPRETERGENERATOR_ZERO_HPP
src/cpu/zero/vm/cppInterpreter_zero.cpp
浏览文件 @
34551e5c
...
@@ -180,25 +180,6 @@ void CppInterpreter::main_loop(int recurse, TRAPS) {
...
@@ -180,25 +180,6 @@ void CppInterpreter::main_loop(int recurse, TRAPS) {
method
,
istate
->
osr_entry
(),
istate
->
osr_buf
(),
THREAD
);
method
,
istate
->
osr_entry
(),
istate
->
osr_buf
(),
THREAD
);
return
;
return
;
}
}
else
if
(
istate
->
msg
()
==
BytecodeInterpreter
::
call_method_handle
)
{
oop
method_handle
=
istate
->
callee
();
// Trim back the stack to put the parameters at the top
stack
->
set_sp
(
istate
->
stack
()
+
1
);
// Make the call
process_method_handle
(
method_handle
,
THREAD
);
fixup_after_potential_safepoint
();
// Convert the result
istate
->
set_stack
(
stack
->
sp
()
-
1
);
// Restore the stack
stack
->
set_sp
(
istate
->
stack_limit
()
+
1
);
// Resume the interpreter
istate
->
set_msg
(
BytecodeInterpreter
::
method_resume
);
}
else
{
else
{
ShouldNotReachHere
();
ShouldNotReachHere
();
}
}
...
@@ -535,35 +516,35 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) {
...
@@ -535,35 +516,35 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) {
if
(
entry
->
is_volatile
())
{
if
(
entry
->
is_volatile
())
{
switch
(
entry
->
flag_state
())
{
switch
(
entry
->
flag_state
())
{
case
ctos
:
case
ctos
:
SET_LOCALS_INT
(
object
->
char_field_acquire
(
entry
->
f2
()),
0
);
SET_LOCALS_INT
(
object
->
char_field_acquire
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
btos
:
case
btos
:
SET_LOCALS_INT
(
object
->
byte_field_acquire
(
entry
->
f2
()),
0
);
SET_LOCALS_INT
(
object
->
byte_field_acquire
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
stos
:
case
stos
:
SET_LOCALS_INT
(
object
->
short_field_acquire
(
entry
->
f2
()),
0
);
SET_LOCALS_INT
(
object
->
short_field_acquire
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
itos
:
case
itos
:
SET_LOCALS_INT
(
object
->
int_field_acquire
(
entry
->
f2
()),
0
);
SET_LOCALS_INT
(
object
->
int_field_acquire
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
ltos
:
case
ltos
:
SET_LOCALS_LONG
(
object
->
long_field_acquire
(
entry
->
f2
()),
0
);
SET_LOCALS_LONG
(
object
->
long_field_acquire
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
ftos
:
case
ftos
:
SET_LOCALS_FLOAT
(
object
->
float_field_acquire
(
entry
->
f2
()),
0
);
SET_LOCALS_FLOAT
(
object
->
float_field_acquire
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
dtos
:
case
dtos
:
SET_LOCALS_DOUBLE
(
object
->
double_field_acquire
(
entry
->
f2
()),
0
);
SET_LOCALS_DOUBLE
(
object
->
double_field_acquire
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
atos
:
case
atos
:
SET_LOCALS_OBJECT
(
object
->
obj_field_acquire
(
entry
->
f2
()),
0
);
SET_LOCALS_OBJECT
(
object
->
obj_field_acquire
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
default:
default:
...
@@ -573,35 +554,35 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) {
...
@@ -573,35 +554,35 @@ int CppInterpreter::accessor_entry(Method* method, intptr_t UNUSED, TRAPS) {
else
{
else
{
switch
(
entry
->
flag_state
())
{
switch
(
entry
->
flag_state
())
{
case
ctos
:
case
ctos
:
SET_LOCALS_INT
(
object
->
char_field
(
entry
->
f2
()),
0
);
SET_LOCALS_INT
(
object
->
char_field
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
btos
:
case
btos
:
SET_LOCALS_INT
(
object
->
byte_field
(
entry
->
f2
()),
0
);
SET_LOCALS_INT
(
object
->
byte_field
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
stos
:
case
stos
:
SET_LOCALS_INT
(
object
->
short_field
(
entry
->
f2
()),
0
);
SET_LOCALS_INT
(
object
->
short_field
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
itos
:
case
itos
:
SET_LOCALS_INT
(
object
->
int_field
(
entry
->
f2
()),
0
);
SET_LOCALS_INT
(
object
->
int_field
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
ltos
:
case
ltos
:
SET_LOCALS_LONG
(
object
->
long_field
(
entry
->
f2
()),
0
);
SET_LOCALS_LONG
(
object
->
long_field
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
ftos
:
case
ftos
:
SET_LOCALS_FLOAT
(
object
->
float_field
(
entry
->
f2
()),
0
);
SET_LOCALS_FLOAT
(
object
->
float_field
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
dtos
:
case
dtos
:
SET_LOCALS_DOUBLE
(
object
->
double_field
(
entry
->
f2
()),
0
);
SET_LOCALS_DOUBLE
(
object
->
double_field
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
case
atos
:
case
atos
:
SET_LOCALS_OBJECT
(
object
->
obj_field
(
entry
->
f2
()),
0
);
SET_LOCALS_OBJECT
(
object
->
obj_field
(
entry
->
f2
_as_index
()),
0
);
break
;
break
;
default:
default:
...
@@ -629,516 +610,6 @@ int CppInterpreter::empty_entry(Method* method, intptr_t UNUSED, TRAPS) {
...
@@ -629,516 +610,6 @@ int CppInterpreter::empty_entry(Method* method, intptr_t UNUSED, TRAPS) {
return
0
;
return
0
;
}
}
int
CppInterpreter
::
method_handle_entry
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
)
{
JavaThread
*
thread
=
(
JavaThread
*
)
THREAD
;
ZeroStack
*
stack
=
thread
->
zero_stack
();
int
argument_slots
=
method
->
size_of_parameters
();
int
result_slots
=
type2size
[
result_type_of
(
method
)];
intptr_t
*
vmslots
=
stack
->
sp
();
intptr_t
*
unwind_sp
=
vmslots
+
argument_slots
;
// Find the MethodType
address
p
=
(
address
)
method
;
for
(
jint
*
pc
=
method
->
method_type_offsets_chain
();
(
*
pc
)
!=
-
1
;
pc
++
)
{
p
=
*
(
address
*
)(
p
+
(
*
pc
));
}
oop
method_type
=
(
oop
)
p
;
// The MethodHandle is in the slot after the arguments
int
num_vmslots
=
argument_slots
-
1
;
oop
method_handle
=
VMSLOTS_OBJECT
(
num_vmslots
);
// InvokeGeneric requires some extra shuffling
oop
mhtype
=
java_lang_invoke_MethodHandle
::
type
(
method_handle
);
bool
is_exact
=
mhtype
==
method_type
;
if
(
!
is_exact
)
{
if
(
true
||
// FIXME
method
->
intrinsic_id
()
==
vmIntrinsics
::
_invokeExact
)
{
CALL_VM_NOCHECK_NOFIX
(
SharedRuntime
::
throw_WrongMethodTypeException
(
thread
,
method_type
,
mhtype
));
// NB all oops trashed!
assert
(
HAS_PENDING_EXCEPTION
,
"should do"
);
stack
->
set_sp
(
unwind_sp
);
return
0
;
}
assert
(
method
->
intrinsic_id
()
==
vmIntrinsics
::
_invokeGeneric
,
"should be"
);
// Load up an adapter from the calling type
// NB the x86 code for this (in methodHandles_x86.cpp, search for
// "genericInvoker") is really really odd. I'm hoping it's trying
// to accomodate odd VM/class library combinations I can ignore.
oop
adapter
=
NULL
;
//FIXME: load the adapter from the CP cache
IF
(
adapter
==
NULL
)
{
CALL_VM_NOCHECK_NOFIX
(
SharedRuntime
::
throw_WrongMethodTypeException
(
thread
,
method_type
,
mhtype
));
// NB all oops trashed!
assert
(
HAS_PENDING_EXCEPTION
,
"should do"
);
stack
->
set_sp
(
unwind_sp
);
return
0
;
}
// Adapters are shared among form-families of method-type. The
// type being called is passed as a trusted first argument so that
// the adapter knows the actual types of its arguments and return
// values.
insert_vmslots
(
num_vmslots
+
1
,
1
,
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
// NB all oops trashed!
stack
->
set_sp
(
unwind_sp
);
return
0
;
}
vmslots
=
stack
->
sp
();
num_vmslots
++
;
SET_VMSLOTS_OBJECT
(
method_type
,
num_vmslots
);
method_handle
=
adapter
;
}
// Start processing
process_method_handle
(
method_handle
,
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
result_slots
=
0
;
// If this is an invokeExact then the eventual callee will not
// have unwound the method handle argument so we have to do it.
// If a result is being returned the it will be above the method
// handle argument we're unwinding.
if
(
is_exact
)
{
intptr_t
result
[
2
];
for
(
int
i
=
0
;
i
<
result_slots
;
i
++
)
result
[
i
]
=
stack
->
pop
();
stack
->
pop
();
for
(
int
i
=
result_slots
-
1
;
i
>=
0
;
i
--
)
stack
->
push
(
result
[
i
]);
}
// Check
assert
(
stack
->
sp
()
==
unwind_sp
-
result_slots
,
"should be"
);
// No deoptimized frames on the stack
return
0
;
}
void
CppInterpreter
::
process_method_handle
(
oop
method_handle
,
TRAPS
)
{
JavaThread
*
thread
=
(
JavaThread
*
)
THREAD
;
ZeroStack
*
stack
=
thread
->
zero_stack
();
intptr_t
*
vmslots
=
stack
->
sp
();
bool
direct_to_method
=
false
;
BasicType
src_rtype
=
T_ILLEGAL
;
BasicType
dst_rtype
=
T_ILLEGAL
;
MethodHandleEntry
*
entry
=
java_lang_invoke_MethodHandle
::
vmentry
(
method_handle
);
MethodHandles
::
EntryKind
entry_kind
=
(
MethodHandles
::
EntryKind
)
(((
intptr_t
)
entry
)
&
0xffffffff
);
Method
*
method
=
NULL
;
switch
(
entry_kind
)
{
case
MethodHandles
::
_invokestatic_mh
:
direct_to_method
=
true
;
break
;
case
MethodHandles
::
_invokespecial_mh
:
case
MethodHandles
::
_invokevirtual_mh
:
case
MethodHandles
::
_invokeinterface_mh
:
{
oop
receiver
=
VMSLOTS_OBJECT
(
java_lang_invoke_MethodHandle
::
vmslots
(
method_handle
)
-
1
);
if
(
receiver
==
NULL
)
{
stack
->
set_sp
(
calculate_unwind_sp
(
stack
,
method_handle
));
CALL_VM_NOCHECK_NOFIX
(
throw_exception
(
thread
,
vmSymbols
::
java_lang_NullPointerException
()));
// NB all oops trashed!
assert
(
HAS_PENDING_EXCEPTION
,
"should do"
);
return
;
}
if
(
entry_kind
!=
MethodHandles
::
_invokespecial_mh
)
{
intptr_t
index
=
java_lang_invoke_DirectMethodHandle
::
vmindex
(
method_handle
);
InstanceKlass
*
rcvrKlass
=
(
InstanceKlass
*
)
receiver
->
klass
();
if
(
entry_kind
==
MethodHandles
::
_invokevirtual_mh
)
{
method
=
(
Method
*
)
rcvrKlass
->
start_of_vtable
()[
index
];
}
else
{
oop
iclass
=
java_lang_invoke_MethodHandle
::
next_target
(
method_handle
);
itableOffsetEntry
*
ki
=
(
itableOffsetEntry
*
)
rcvrKlass
->
start_of_itable
();
int
i
,
length
=
rcvrKlass
->
itable_length
();
for
(
i
=
0
;
i
<
length
;
i
++
,
ki
++
)
{
if
(
ki
->
interface_klass
()
==
iclass
)
break
;
}
if
(
i
==
length
)
{
stack
->
set_sp
(
calculate_unwind_sp
(
stack
,
method_handle
));
CALL_VM_NOCHECK_NOFIX
(
throw_exception
(
thread
,
vmSymbols
::
java_lang_IncompatibleClassChangeError
()));
// NB all oops trashed!
assert
(
HAS_PENDING_EXCEPTION
,
"should do"
);
return
;
}
itableMethodEntry
*
im
=
ki
->
first_method_entry
(
receiver
->
klass
());
method
=
im
[
index
].
method
();
if
(
method
==
NULL
)
{
stack
->
set_sp
(
calculate_unwind_sp
(
stack
,
method_handle
));
CALL_VM_NOCHECK_NOFIX
(
throw_exception
(
thread
,
vmSymbols
::
java_lang_AbstractMethodError
()));
// NB all oops trashed!
assert
(
HAS_PENDING_EXCEPTION
,
"should do"
);
return
;
}
}
}
}
direct_to_method
=
true
;
break
;
case
MethodHandles
::
_bound_ref_direct_mh
:
case
MethodHandles
::
_bound_int_direct_mh
:
case
MethodHandles
::
_bound_long_direct_mh
:
direct_to_method
=
true
;
// fall through
case
MethodHandles
::
_bound_ref_mh
:
case
MethodHandles
::
_bound_int_mh
:
case
MethodHandles
::
_bound_long_mh
:
{
BasicType
arg_type
=
T_ILLEGAL
;
int
arg_mask
=
-
1
;
int
arg_slots
=
-
1
;
MethodHandles
::
get_ek_bound_mh_info
(
entry_kind
,
arg_type
,
arg_mask
,
arg_slots
);
int
arg_slot
=
java_lang_invoke_BoundMethodHandle
::
vmargslot
(
method_handle
);
// Create the new slot(s)
intptr_t
*
unwind_sp
=
calculate_unwind_sp
(
stack
,
method_handle
);
insert_vmslots
(
arg_slot
,
arg_slots
,
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
// all oops trashed
stack
->
set_sp
(
unwind_sp
);
return
;
}
vmslots
=
stack
->
sp
();
// Store bound argument into new stack slot
oop
arg
=
java_lang_invoke_BoundMethodHandle
::
argument
(
method_handle
);
if
(
arg_type
==
T_OBJECT
)
{
assert
(
arg_slots
==
1
,
"should be"
);
SET_VMSLOTS_OBJECT
(
arg
,
arg_slot
);
}
else
{
jvalue
arg_value
;
arg_type
=
java_lang_boxing_object
::
get_value
(
arg
,
&
arg_value
);
switch
(
arg_type
)
{
case
T_BOOLEAN
:
SET_VMSLOTS_INT
(
arg_value
.
z
,
arg_slot
);
break
;
case
T_CHAR
:
SET_VMSLOTS_INT
(
arg_value
.
c
,
arg_slot
);
break
;
case
T_BYTE
:
SET_VMSLOTS_INT
(
arg_value
.
b
,
arg_slot
);
break
;
case
T_SHORT
:
SET_VMSLOTS_INT
(
arg_value
.
s
,
arg_slot
);
break
;
case
T_INT
:
SET_VMSLOTS_INT
(
arg_value
.
i
,
arg_slot
);
break
;
case
T_FLOAT
:
SET_VMSLOTS_FLOAT
(
arg_value
.
f
,
arg_slot
);
break
;
case
T_LONG
:
SET_VMSLOTS_LONG
(
arg_value
.
j
,
arg_slot
+
1
);
break
;
case
T_DOUBLE
:
SET_VMSLOTS_DOUBLE
(
arg_value
.
d
,
arg_slot
+
1
);
break
;
default:
tty
->
print_cr
(
"unhandled type %s"
,
type2name
(
arg_type
));
ShouldNotReachHere
();
}
}
}
break
;
case
MethodHandles
::
_adapter_retype_only
:
case
MethodHandles
::
_adapter_retype_raw
:
src_rtype
=
result_type_of_handle
(
java_lang_invoke_MethodHandle
::
next_target
(
method_handle
));
dst_rtype
=
result_type_of_handle
(
method_handle
);
break
;
case
MethodHandles
::
_adapter_check_cast
:
{
int
arg_slot
=
java_lang_invoke_AdapterMethodHandle
::
vmargslot
(
method_handle
);
oop
arg
=
VMSLOTS_OBJECT
(
arg_slot
);
if
(
arg
!=
NULL
)
{
Klass
*
objKlassOop
=
arg
->
klass
();
Klass
*
klassOf
=
java_lang_Class
::
as_Klass
(
java_lang_invoke_AdapterMethodHandle
::
argument
(
method_handle
));
if
(
objKlassOop
!=
klassOf
&&
!
objKlassOop
->
is_subtype_of
(
klassOf
))
{
ResourceMark
rm
(
THREAD
);
const
char
*
objName
=
Klass
::
cast
(
objKlassOop
)
->
external_name
();
const
char
*
klassName
=
Klass
::
cast
(
klassOf
)
->
external_name
();
char
*
message
=
SharedRuntime
::
generate_class_cast_message
(
objName
,
klassName
);
stack
->
set_sp
(
calculate_unwind_sp
(
stack
,
method_handle
));
CALL_VM_NOCHECK_NOFIX
(
throw_exception
(
thread
,
vmSymbols
::
java_lang_ClassCastException
(),
message
));
// NB all oops trashed!
assert
(
HAS_PENDING_EXCEPTION
,
"should do"
);
return
;
}
}
}
break
;
case
MethodHandles
::
_adapter_dup_args
:
{
int
arg_slot
=
java_lang_invoke_AdapterMethodHandle
::
vmargslot
(
method_handle
);
int
conv
=
java_lang_invoke_AdapterMethodHandle
::
conversion
(
method_handle
);
int
num_slots
=
-
MethodHandles
::
adapter_conversion_stack_move
(
conv
);
assert
(
num_slots
>
0
,
"should be"
);
// Create the new slot(s)
intptr_t
*
unwind_sp
=
calculate_unwind_sp
(
stack
,
method_handle
);
stack
->
overflow_check
(
num_slots
,
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
// all oops trashed
stack
->
set_sp
(
unwind_sp
);
return
;
}
// Duplicate the arguments
for
(
int
i
=
num_slots
-
1
;
i
>=
0
;
i
--
)
stack
->
push
(
*
VMSLOTS_SLOT
(
arg_slot
+
i
));
vmslots
=
stack
->
sp
();
// unused, but let the compiler figure that out
}
break
;
case
MethodHandles
::
_adapter_drop_args
:
{
int
arg_slot
=
java_lang_invoke_AdapterMethodHandle
::
vmargslot
(
method_handle
);
int
conv
=
java_lang_invoke_AdapterMethodHandle
::
conversion
(
method_handle
);
int
num_slots
=
MethodHandles
::
adapter_conversion_stack_move
(
conv
);
assert
(
num_slots
>
0
,
"should be"
);
remove_vmslots
(
arg_slot
,
num_slots
,
THREAD
);
// doesn't trap
vmslots
=
stack
->
sp
();
// unused, but let the compiler figure that out
}
break
;
case
MethodHandles
::
_adapter_opt_swap_1
:
case
MethodHandles
::
_adapter_opt_swap_2
:
case
MethodHandles
::
_adapter_opt_rot_1_up
:
case
MethodHandles
::
_adapter_opt_rot_1_down
:
case
MethodHandles
::
_adapter_opt_rot_2_up
:
case
MethodHandles
::
_adapter_opt_rot_2_down
:
{
int
arg1
=
java_lang_invoke_AdapterMethodHandle
::
vmargslot
(
method_handle
);
int
conv
=
java_lang_invoke_AdapterMethodHandle
::
conversion
(
method_handle
);
int
arg2
=
MethodHandles
::
adapter_conversion_vminfo
(
conv
);
int
swap_bytes
=
0
,
rotate
=
0
;
MethodHandles
::
get_ek_adapter_opt_swap_rot_info
(
entry_kind
,
swap_bytes
,
rotate
);
int
swap_slots
=
swap_bytes
>>
LogBytesPerWord
;
intptr_t
tmp
;
switch
(
rotate
)
{
case
0
:
// swap
for
(
int
i
=
0
;
i
<
swap_slots
;
i
++
)
{
tmp
=
*
VMSLOTS_SLOT
(
arg1
+
i
);
SET_VMSLOTS_SLOT
(
VMSLOTS_SLOT
(
arg2
+
i
),
arg1
+
i
);
SET_VMSLOTS_SLOT
(
&
tmp
,
arg2
+
i
);
}
break
;
case
1
:
// up
assert
(
arg1
-
swap_slots
>
arg2
,
"should be"
);
tmp
=
*
VMSLOTS_SLOT
(
arg1
);
for
(
int
i
=
arg1
-
swap_slots
;
i
>=
arg2
;
i
--
)
SET_VMSLOTS_SLOT
(
VMSLOTS_SLOT
(
i
),
i
+
swap_slots
);
SET_VMSLOTS_SLOT
(
&
tmp
,
arg2
);
break
;
case
-
1
:
// down
assert
(
arg2
-
swap_slots
>
arg1
,
"should be"
);
tmp
=
*
VMSLOTS_SLOT
(
arg1
);
for
(
int
i
=
arg1
+
swap_slots
;
i
<=
arg2
;
i
++
)
SET_VMSLOTS_SLOT
(
VMSLOTS_SLOT
(
i
),
i
-
swap_slots
);
SET_VMSLOTS_SLOT
(
&
tmp
,
arg2
);
break
;
default:
ShouldNotReachHere
();
}
}
break
;
case
MethodHandles
::
_adapter_opt_i2l
:
{
int
arg_slot
=
java_lang_invoke_AdapterMethodHandle
::
vmargslot
(
method_handle
);
int
arg
=
VMSLOTS_INT
(
arg_slot
);
intptr_t
*
unwind_sp
=
calculate_unwind_sp
(
stack
,
method_handle
);
insert_vmslots
(
arg_slot
,
1
,
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
// all oops trashed
stack
->
set_sp
(
unwind_sp
);
return
;
}
vmslots
=
stack
->
sp
();
arg_slot
++
;
SET_VMSLOTS_LONG
(
arg
,
arg_slot
);
}
break
;
case
MethodHandles
::
_adapter_opt_unboxi
:
case
MethodHandles
::
_adapter_opt_unboxl
:
{
int
arg_slot
=
java_lang_invoke_AdapterMethodHandle
::
vmargslot
(
method_handle
);
oop
arg
=
VMSLOTS_OBJECT
(
arg_slot
);
jvalue
arg_value
;
if
(
arg
==
NULL
)
{
// queue a nullpointer exception for the caller
stack
->
set_sp
(
calculate_unwind_sp
(
stack
,
method_handle
));
CALL_VM_NOCHECK_NOFIX
(
throw_exception
(
thread
,
vmSymbols
::
java_lang_NullPointerException
()));
// NB all oops trashed!
assert
(
HAS_PENDING_EXCEPTION
,
"should do"
);
return
;
}
BasicType
arg_type
=
java_lang_boxing_object
::
get_value
(
arg
,
&
arg_value
);
if
(
arg_type
==
T_LONG
||
arg_type
==
T_DOUBLE
)
{
intptr_t
*
unwind_sp
=
calculate_unwind_sp
(
stack
,
method_handle
);
insert_vmslots
(
arg_slot
,
1
,
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
// all oops trashed
stack
->
set_sp
(
unwind_sp
);
return
;
}
vmslots
=
stack
->
sp
();
arg_slot
++
;
}
switch
(
arg_type
)
{
case
T_BOOLEAN
:
SET_VMSLOTS_INT
(
arg_value
.
z
,
arg_slot
);
break
;
case
T_CHAR
:
SET_VMSLOTS_INT
(
arg_value
.
c
,
arg_slot
);
break
;
case
T_BYTE
:
SET_VMSLOTS_INT
(
arg_value
.
b
,
arg_slot
);
break
;
case
T_SHORT
:
SET_VMSLOTS_INT
(
arg_value
.
s
,
arg_slot
);
break
;
case
T_INT
:
SET_VMSLOTS_INT
(
arg_value
.
i
,
arg_slot
);
break
;
case
T_FLOAT
:
SET_VMSLOTS_FLOAT
(
arg_value
.
f
,
arg_slot
);
break
;
case
T_LONG
:
SET_VMSLOTS_LONG
(
arg_value
.
j
,
arg_slot
);
break
;
case
T_DOUBLE
:
SET_VMSLOTS_DOUBLE
(
arg_value
.
d
,
arg_slot
);
break
;
default:
tty
->
print_cr
(
"unhandled type %s"
,
type2name
(
arg_type
));
ShouldNotReachHere
();
}
}
break
;
default:
tty
->
print_cr
(
"unhandled entry_kind %s"
,
MethodHandles
::
entry_name
(
entry_kind
));
ShouldNotReachHere
();
}
// Continue along the chain
if
(
direct_to_method
)
{
if
(
method
==
NULL
)
{
method
=
(
Method
*
)
java_lang_invoke_MethodHandle
::
vmtarget
(
method_handle
);
}
address
entry_point
=
method
->
from_interpreted_entry
();
Interpreter
::
invoke_method
(
method
,
entry_point
,
THREAD
);
}
else
{
process_method_handle
(
java_lang_invoke_MethodHandle
::
next_target
(
method_handle
),
THREAD
);
}
// NB all oops now trashed
// Adapt the result type, if necessary
if
(
src_rtype
!=
dst_rtype
&&
!
HAS_PENDING_EXCEPTION
)
{
switch
(
dst_rtype
)
{
case
T_VOID
:
for
(
int
i
=
0
;
i
<
type2size
[
src_rtype
];
i
++
)
stack
->
pop
();
return
;
case
T_INT
:
switch
(
src_rtype
)
{
case
T_VOID
:
stack
->
overflow_check
(
1
,
CHECK
);
stack
->
push
(
0
);
return
;
case
T_BOOLEAN
:
case
T_CHAR
:
case
T_BYTE
:
case
T_SHORT
:
return
;
}
// INT results sometimes need narrowing
case
T_BOOLEAN
:
case
T_CHAR
:
case
T_BYTE
:
case
T_SHORT
:
switch
(
src_rtype
)
{
case
T_INT
:
return
;
}
}
tty
->
print_cr
(
"unhandled conversion:"
);
tty
->
print_cr
(
"src_rtype = %s"
,
type2name
(
src_rtype
));
tty
->
print_cr
(
"dst_rtype = %s"
,
type2name
(
dst_rtype
));
ShouldNotReachHere
();
}
}
// The new slots will be inserted before slot insert_before.
// The new slots will be inserted before slot insert_before.
// Slots < insert_before will have the same slot number after the insert.
// Slots < insert_before will have the same slot number after the insert.
// Slots >= insert_before will become old_slot + num_slots.
// Slots >= insert_before will become old_slot + num_slots.
...
@@ -1380,10 +851,6 @@ address AbstractInterpreterGenerator::generate_method_entry(
...
@@ -1380,10 +851,6 @@ address AbstractInterpreterGenerator::generate_method_entry(
entry_point
=
((
InterpreterGenerator
*
)
this
)
->
generate_abstract_entry
();
entry_point
=
((
InterpreterGenerator
*
)
this
)
->
generate_abstract_entry
();
break
;
break
;
case
Interpreter
::
method_handle
:
entry_point
=
((
InterpreterGenerator
*
)
this
)
->
generate_method_handle_entry
();
break
;
case
Interpreter
::
java_lang_math_sin
:
case
Interpreter
::
java_lang_math_sin
:
case
Interpreter
::
java_lang_math_cos
:
case
Interpreter
::
java_lang_math_cos
:
case
Interpreter
::
java_lang_math_tan
:
case
Interpreter
::
java_lang_math_tan
:
...
@@ -1391,6 +858,8 @@ address AbstractInterpreterGenerator::generate_method_entry(
...
@@ -1391,6 +858,8 @@ address AbstractInterpreterGenerator::generate_method_entry(
case
Interpreter
::
java_lang_math_log
:
case
Interpreter
::
java_lang_math_log
:
case
Interpreter
::
java_lang_math_log10
:
case
Interpreter
::
java_lang_math_log10
:
case
Interpreter
::
java_lang_math_sqrt
:
case
Interpreter
::
java_lang_math_sqrt
:
case
Interpreter
::
java_lang_math_pow
:
case
Interpreter
::
java_lang_math_exp
:
entry_point
=
((
InterpreterGenerator
*
)
this
)
->
generate_math_entry
(
kind
);
entry_point
=
((
InterpreterGenerator
*
)
this
)
->
generate_math_entry
(
kind
);
break
;
break
;
...
...
src/cpu/zero/vm/cppInterpreter_zero.hpp
浏览文件 @
34551e5c
...
@@ -36,7 +36,6 @@
...
@@ -36,7 +36,6 @@
static
int
native_entry
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
);
static
int
native_entry
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
);
static
int
accessor_entry
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
);
static
int
accessor_entry
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
);
static
int
empty_entry
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
);
static
int
empty_entry
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
);
static
int
method_handle_entry
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
);
public
:
public
:
// Main loop of normal_entry
// Main loop of normal_entry
...
@@ -44,7 +43,6 @@
...
@@ -44,7 +43,6 @@
private
:
private
:
// Helpers for method_handle_entry
// Helpers for method_handle_entry
static
void
process_method_handle
(
oop
method_handle
,
TRAPS
);
static
void
insert_vmslots
(
int
insert_before
,
int
num_slots
,
TRAPS
);
static
void
insert_vmslots
(
int
insert_before
,
int
num_slots
,
TRAPS
);
static
void
remove_vmslots
(
int
first_slot
,
int
num_slots
,
TRAPS
);
static
void
remove_vmslots
(
int
first_slot
,
int
num_slots
,
TRAPS
);
static
BasicType
result_type_of_handle
(
oop
method_handle
);
static
BasicType
result_type_of_handle
(
oop
method_handle
);
...
...
src/cpu/zero/vm/frame_zero.cpp
浏览文件 @
34551e5c
...
@@ -351,7 +351,7 @@ void SharkFrame::identify_word(int frame_index,
...
@@ -351,7 +351,7 @@ void SharkFrame::identify_word(int frame_index,
switch
(
offset
)
{
switch
(
offset
)
{
case
pc_off
:
case
pc_off
:
strncpy
(
fieldbuf
,
"pc"
,
buflen
);
strncpy
(
fieldbuf
,
"pc"
,
buflen
);
if
(
method
()
->
is_
oop
())
{
if
(
method
()
->
is_
method
())
{
nmethod
*
code
=
method
()
->
code
();
nmethod
*
code
=
method
()
->
code
();
if
(
code
&&
code
->
pc_desc_at
(
pc
()))
{
if
(
code
&&
code
->
pc_desc_at
(
pc
()))
{
SimpleScopeDesc
ssd
(
code
,
pc
());
SimpleScopeDesc
ssd
(
code
,
pc
());
...
@@ -367,7 +367,7 @@ void SharkFrame::identify_word(int frame_index,
...
@@ -367,7 +367,7 @@ void SharkFrame::identify_word(int frame_index,
case
method_off
:
case
method_off
:
strncpy
(
fieldbuf
,
"method"
,
buflen
);
strncpy
(
fieldbuf
,
"method"
,
buflen
);
if
(
method
()
->
is_
oop
())
{
if
(
method
()
->
is_
method
())
{
method
()
->
name_and_sig_as_C_string
(
valuebuf
,
buflen
);
method
()
->
name_and_sig_as_C_string
(
valuebuf
,
buflen
);
}
}
return
;
return
;
...
@@ -378,7 +378,7 @@ void SharkFrame::identify_word(int frame_index,
...
@@ -378,7 +378,7 @@ void SharkFrame::identify_word(int frame_index,
}
}
// Variable part
// Variable part
if
(
method
()
->
is_
oop
())
{
if
(
method
()
->
is_
method
())
{
identify_vp_word
(
frame_index
,
addr_of_word
(
offset
),
identify_vp_word
(
frame_index
,
addr_of_word
(
offset
),
addr_of_word
(
header_words
+
1
),
addr_of_word
(
header_words
+
1
),
unextended_sp
()
+
method
()
->
max_stack
(),
unextended_sp
()
+
method
()
->
max_stack
(),
...
@@ -430,4 +430,3 @@ intptr_t *frame::initial_deoptimization_info() {
...
@@ -430,4 +430,3 @@ intptr_t *frame::initial_deoptimization_info() {
// unused... but returns fp() to minimize changes introduced by 7087445
// unused... but returns fp() to minimize changes introduced by 7087445
return
fp
();
return
fp
();
}
}
src/cpu/zero/vm/frame_zero.inline.hpp
浏览文件 @
34551e5c
...
@@ -36,6 +36,8 @@ inline frame::frame() {
...
@@ -36,6 +36,8 @@ inline frame::frame() {
_deopt_state
=
unknown
;
_deopt_state
=
unknown
;
}
}
inline
address
frame
::
sender_pc
()
const
{
ShouldNotCallThis
();
}
inline
frame
::
frame
(
ZeroFrame
*
zf
,
intptr_t
*
sp
)
{
inline
frame
::
frame
(
ZeroFrame
*
zf
,
intptr_t
*
sp
)
{
_zeroframe
=
zf
;
_zeroframe
=
zf
;
_sp
=
sp
;
_sp
=
sp
;
...
...
src/cpu/zero/vm/icBuffer_zero.cpp
浏览文件 @
34551e5c
...
@@ -40,7 +40,7 @@ int InlineCacheBuffer::ic_stub_code_size() {
...
@@ -40,7 +40,7 @@ int InlineCacheBuffer::ic_stub_code_size() {
}
}
void
InlineCacheBuffer
::
assemble_ic_buffer_code
(
address
code_begin
,
void
InlineCacheBuffer
::
assemble_ic_buffer_code
(
address
code_begin
,
Metadata
*
cached_oop
,
void
*
cached_oop
,
address
entry_point
)
{
address
entry_point
)
{
// NB ic_stub_code_size() must return the size of the code we generate
// NB ic_stub_code_size() must return the size of the code we generate
ShouldNotCallThis
();
ShouldNotCallThis
();
...
@@ -51,7 +51,6 @@ address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
...
@@ -51,7 +51,6 @@ address InlineCacheBuffer::ic_buffer_entry_point(address code_begin) {
ShouldNotCallThis
();
ShouldNotCallThis
();
}
}
Metadata
*
InlineCacheBuffer
::
ic_buffer_cached_oop
(
address
code_begin
)
{
void
*
InlineCacheBuffer
::
ic_buffer_cached_value
(
address
code_begin
)
{
// NB ic_stub_code_size() must return the size of the code we generate
ShouldNotCallThis
();
ShouldNotCallThis
();
}
}
src/cpu/zero/vm/methodHandles_zero.cpp
浏览文件 @
34551e5c
...
@@ -24,26 +24,159 @@
...
@@ -24,26 +24,159 @@
*/
*/
#include "precompiled.hpp"
#include "precompiled.hpp"
#include "interpreter/interpreterGenerator.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreter.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/allocation.inline.hpp"
#include "prims/methodHandles.hpp"
#include "prims/methodHandles.hpp"
int
MethodHandles
::
adapter_conversion_ops_supported_mask
()
{
void
MethodHandles
::
invoke_target
(
Method
*
method
,
TRAPS
)
{
return
((
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_RETYPE_ONLY
)
|
(
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_RETYPE_RAW
)
JavaThread
*
thread
=
(
JavaThread
*
)
THREAD
;
|
(
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_CHECK_CAST
)
ZeroStack
*
stack
=
thread
->
zero_stack
();
|
(
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_PRIM_TO_PRIM
)
InterpreterFrame
*
frame
=
thread
->
top_zero_frame
()
->
as_interpreter_frame
();
|
(
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_REF_TO_PRIM
)
interpreterState
istate
=
frame
->
interpreter_state
();
|
(
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_SWAP_ARGS
)
|
(
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_ROT_ARGS
)
// Trim back the stack to put the parameters at the top
|
(
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_DUP_ARGS
)
stack
->
set_sp
(
istate
->
stack
()
+
1
);
|
(
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_DROP_ARGS
)
//|(1<<java_lang_invoke_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG!
Interpreter
::
invoke_method
(
method
,
method
->
from_interpreted_entry
(),
THREAD
);
);
// FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS.
// Convert the result
}
istate
->
set_stack
(
stack
->
sp
()
-
1
);
void
MethodHandles
::
generate_method_handle_stub
(
MacroAssembler
*
masm
,
}
MethodHandles
::
EntryKind
ek
)
{
init_entry
(
ek
,
(
MethodHandleEntry
*
)
ek
);
oop
MethodHandles
::
popFromStack
(
TRAPS
)
{
JavaThread
*
thread
=
(
JavaThread
*
)
THREAD
;
InterpreterFrame
*
frame
=
thread
->
top_zero_frame
()
->
as_interpreter_frame
();
interpreterState
istate
=
frame
->
interpreter_state
();
intptr_t
*
topOfStack
=
istate
->
stack
();
oop
top
=
STACK_OBJECT
(
-
1
);
MORE_STACK
(
-
1
);
istate
->
set_stack
(
topOfStack
);
return
top
;
}
int
MethodHandles
::
method_handle_entry_invokeBasic
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
)
{
JavaThread
*
thread
=
(
JavaThread
*
)
THREAD
;
InterpreterFrame
*
frame
=
thread
->
top_zero_frame
()
->
as_interpreter_frame
();
interpreterState
istate
=
frame
->
interpreter_state
();
intptr_t
*
topOfStack
=
istate
->
stack
();
// 'this' is a MethodHandle. We resolve the target method by accessing this.form.vmentry.vmtarget.
int
numArgs
=
method
->
size_of_parameters
();
oop
lform1
=
java_lang_invoke_MethodHandle
::
form
(
STACK_OBJECT
(
-
numArgs
));
// this.form
oop
vmEntry1
=
java_lang_invoke_LambdaForm
::
vmentry
(
lform1
);
Method
*
vmtarget
=
(
Method
*
)
java_lang_invoke_MemberName
::
vmtarget
(
vmEntry1
);
invoke_target
(
vmtarget
,
THREAD
);
// No deoptimized frames on the stack
return
0
;
}
int
MethodHandles
::
method_handle_entry_linkToStaticOrSpecial
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
)
{
// Pop appendix argument from stack. This is a MemberName which we resolve to the
// target method.
oop
vmentry
=
popFromStack
(
THREAD
);
Method
*
vmtarget
=
(
Method
*
)
java_lang_invoke_MemberName
::
vmtarget
(
vmentry
);
invoke_target
(
vmtarget
,
THREAD
);
return
0
;
}
int
MethodHandles
::
method_handle_entry_linkToInterface
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
)
{
JavaThread
*
thread
=
(
JavaThread
*
)
THREAD
;
InterpreterFrame
*
frame
=
thread
->
top_zero_frame
()
->
as_interpreter_frame
();
interpreterState
istate
=
frame
->
interpreter_state
();
// Pop appendix argument from stack. This is a MemberName which we resolve to the
// target method.
oop
vmentry
=
popFromStack
(
THREAD
);
intptr_t
*
topOfStack
=
istate
->
stack
();
// Resolve target method by looking up in the receiver object's itable.
Klass
*
clazz
=
java_lang_Class
::
as_Klass
(
java_lang_invoke_MemberName
::
clazz
(
vmentry
));
intptr_t
vmindex
=
java_lang_invoke_MemberName
::
vmindex
(
vmentry
);
Method
*
target
=
(
Method
*
)
java_lang_invoke_MemberName
::
vmtarget
(
vmentry
);
int
numArgs
=
target
->
size_of_parameters
();
oop
recv
=
STACK_OBJECT
(
-
numArgs
);
InstanceKlass
*
klass_part
=
InstanceKlass
::
cast
(
recv
->
klass
());
itableOffsetEntry
*
ki
=
(
itableOffsetEntry
*
)
klass_part
->
start_of_itable
();
int
i
;
for
(
i
=
0
;
i
<
klass_part
->
itable_length
()
;
i
++
,
ki
++
)
{
if
(
ki
->
interface_klass
()
==
clazz
)
break
;
}
itableMethodEntry
*
im
=
ki
->
first_method_entry
(
recv
->
klass
());
Method
*
vmtarget
=
im
[
vmindex
].
method
();
invoke_target
(
vmtarget
,
THREAD
);
return
0
;
}
int
MethodHandles
::
method_handle_entry_linkToVirtual
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
)
{
JavaThread
*
thread
=
(
JavaThread
*
)
THREAD
;
InterpreterFrame
*
frame
=
thread
->
top_zero_frame
()
->
as_interpreter_frame
();
interpreterState
istate
=
frame
->
interpreter_state
();
// Pop appendix argument from stack. This is a MemberName which we resolve to the
// target method.
oop
vmentry
=
popFromStack
(
THREAD
);
intptr_t
*
topOfStack
=
istate
->
stack
();
// Resolve target method by looking up in the receiver object's vtable.
intptr_t
vmindex
=
java_lang_invoke_MemberName
::
vmindex
(
vmentry
);
Method
*
target
=
(
Method
*
)
java_lang_invoke_MemberName
::
vmtarget
(
vmentry
);
int
numArgs
=
target
->
size_of_parameters
();
oop
recv
=
STACK_OBJECT
(
-
numArgs
);
Klass
*
clazz
=
recv
->
klass
();
Klass
*
klass_part
=
InstanceKlass
::
cast
(
clazz
);
klassVtable
*
vtable
=
klass_part
->
vtable
();
Method
*
vmtarget
=
vtable
->
method_at
(
vmindex
);
invoke_target
(
vmtarget
,
THREAD
);
return
0
;
}
int
MethodHandles
::
method_handle_entry_invalid
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
)
{
ShouldNotReachHere
();
return
0
;
}
address
MethodHandles
::
generate_method_handle_interpreter_entry
(
MacroAssembler
*
masm
,
vmIntrinsics
::
ID
iid
)
{
switch
(
iid
)
{
case
vmIntrinsics
::
_invokeGeneric
:
case
vmIntrinsics
::
_compiledLambdaForm
:
// Perhaps surprisingly, the symbolic references visible to Java are not directly used.
// They are linked to Java-generated adapters via MethodHandleNatives.linkMethod.
// They all allow an appendix argument.
return
InterpreterGenerator
::
generate_entry_impl
(
masm
,
(
address
)
MethodHandles
::
method_handle_entry_invalid
);
case
vmIntrinsics
::
_invokeBasic
:
return
InterpreterGenerator
::
generate_entry_impl
(
masm
,
(
address
)
MethodHandles
::
method_handle_entry_invokeBasic
);
case
vmIntrinsics
::
_linkToStatic
:
case
vmIntrinsics
::
_linkToSpecial
:
return
InterpreterGenerator
::
generate_entry_impl
(
masm
,
(
address
)
MethodHandles
::
method_handle_entry_linkToStaticOrSpecial
);
case
vmIntrinsics
::
_linkToInterface
:
return
InterpreterGenerator
::
generate_entry_impl
(
masm
,
(
address
)
MethodHandles
::
method_handle_entry_linkToInterface
);
case
vmIntrinsics
::
_linkToVirtual
:
return
InterpreterGenerator
::
generate_entry_impl
(
masm
,
(
address
)
MethodHandles
::
method_handle_entry_linkToVirtual
);
default:
ShouldNotReachHere
();
return
NULL
;
}
}
}
src/cpu/zero/vm/methodHandles_zero.hpp
浏览文件 @
34551e5c
...
@@ -26,6 +26,14 @@
...
@@ -26,6 +26,14 @@
// Adapters
// Adapters
enum
/* platform_dependent_constants */
{
enum
/* platform_dependent_constants */
{
adapter_code_size
=
0
adapter_code_size
=
sizeof
(
ZeroEntry
)
*
(
Interpreter
::
method_handle_invoke_LAST
-
Interpreter
::
method_handle_invoke_FIRST
+
1
)
};
};
private
:
static
oop
popFromStack
(
TRAPS
);
static
void
invoke_target
(
Method
*
method
,
TRAPS
);
static
int
method_handle_entry_invokeBasic
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
);
static
int
method_handle_entry_linkToStaticOrSpecial
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
);
static
int
method_handle_entry_linkToVirtual
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
);
static
int
method_handle_entry_linkToInterface
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
);
static
int
method_handle_entry_invalid
(
Method
*
method
,
intptr_t
UNUSED
,
TRAPS
);
src/cpu/zero/vm/register_zero.hpp
浏览文件 @
34551e5c
...
@@ -114,5 +114,8 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl {
...
@@ -114,5 +114,8 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl {
};
};
CONSTANT_REGISTER_DECLARATION
(
Register
,
noreg
,
(
-
1
));
CONSTANT_REGISTER_DECLARATION
(
Register
,
noreg
,
(
-
1
));
#ifndef DONT_USE_REGISTER_DEFINES
#define noreg ((Register)(noreg_RegisterEnumValue))
#endif
#endif // CPU_ZERO_VM_REGISTER_ZERO_HPP
#endif // CPU_ZERO_VM_REGISTER_ZERO_HPP
src/cpu/zero/vm/relocInfo_zero.cpp
浏览文件 @
34551e5c
...
@@ -77,3 +77,7 @@ void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src,
...
@@ -77,3 +77,7 @@ void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src,
CodeBuffer
*
dst
)
{
CodeBuffer
*
dst
)
{
ShouldNotCallThis
();
ShouldNotCallThis
();
}
}
void
metadata_Relocation
::
pd_fix_value
(
address
x
)
{
ShouldNotCallThis
();
}
src/cpu/zero/vm/sharedRuntime_zero.cpp
浏览文件 @
34551e5c
...
@@ -35,6 +35,7 @@
...
@@ -35,6 +35,7 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/vframeArray.hpp"
#include "runtime/vframeArray.hpp"
#include "vmreg_zero.inline.hpp"
#include "vmreg_zero.inline.hpp"
#ifdef COMPILER1
#ifdef COMPILER1
#include "c1/c1_Runtime1.hpp"
#include "c1/c1_Runtime1.hpp"
#endif
#endif
...
@@ -47,6 +48,12 @@
...
@@ -47,6 +48,12 @@
#endif
#endif
static
address
zero_null_code_stub
()
{
address
start
=
ShouldNotCallThisStub
();
return
start
;
}
int
SharedRuntime
::
java_calling_convention
(
const
BasicType
*
sig_bt
,
int
SharedRuntime
::
java_calling_convention
(
const
BasicType
*
sig_bt
,
VMRegPair
*
regs
,
VMRegPair
*
regs
,
int
total_args_passed
,
int
total_args_passed
,
...
@@ -63,16 +70,14 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(
...
@@ -63,16 +70,14 @@ AdapterHandlerEntry* SharedRuntime::generate_i2c2i_adapters(
AdapterFingerPrint
*
fingerprint
)
{
AdapterFingerPrint
*
fingerprint
)
{
return
AdapterHandlerLibrary
::
new_entry
(
return
AdapterHandlerLibrary
::
new_entry
(
fingerprint
,
fingerprint
,
ShouldNotCallThisStub
(
),
CAST_FROM_FN_PTR
(
address
,
zero_null_code_stub
),
ShouldNotCallThisStub
(
),
CAST_FROM_FN_PTR
(
address
,
zero_null_code_stub
),
ShouldNotCallThisStub
(
));
CAST_FROM_FN_PTR
(
address
,
zero_null_code_stub
));
}
}
nmethod
*
SharedRuntime
::
generate_native_wrapper
(
MacroAssembler
*
masm
,
nmethod
*
SharedRuntime
::
generate_native_wrapper
(
MacroAssembler
*
masm
,
methodHandle
method
,
methodHandle
method
,
int
compile_id
,
int
compile_id
,
int
total_args_passed
,
int
max_arg
,
BasicType
*
sig_bt
,
BasicType
*
sig_bt
,
VMRegPair
*
regs
,
VMRegPair
*
regs
,
BasicType
ret_type
)
{
BasicType
ret_type
)
{
...
@@ -96,19 +101,20 @@ uint SharedRuntime::out_preserve_stack_slots() {
...
@@ -96,19 +101,20 @@ uint SharedRuntime::out_preserve_stack_slots() {
ShouldNotCallThis
();
ShouldNotCallThis
();
}
}
JRT_LEAF
(
void
,
zero_stub
())
ShouldNotCallThis
();
JRT_END
static
RuntimeStub
*
generate_empty_runtime_stub
(
const
char
*
name
)
{
static
RuntimeStub
*
generate_empty_runtime_stub
(
const
char
*
name
)
{
CodeBuffer
buffer
(
name
,
0
,
0
);
return
CAST_FROM_FN_PTR
(
RuntimeStub
*
,
zero_stub
);
return
RuntimeStub
::
new_runtime_stub
(
name
,
&
buffer
,
0
,
0
,
NULL
,
false
);
}
}
static
SafepointBlob
*
generate_empty_safepoint_blob
()
{
static
SafepointBlob
*
generate_empty_safepoint_blob
()
{
CodeBuffer
buffer
(
"handler_blob"
,
0
,
0
);
return
CAST_FROM_FN_PTR
(
SafepointBlob
*
,
zero_stub
);
return
SafepointBlob
::
create
(
&
buffer
,
NULL
,
0
);
}
}
static
DeoptimizationBlob
*
generate_empty_deopt_blob
()
{
static
DeoptimizationBlob
*
generate_empty_deopt_blob
()
{
CodeBuffer
buffer
(
"handler_blob"
,
0
,
0
);
return
CAST_FROM_FN_PTR
(
DeoptimizationBlob
*
,
zero_stub
);
return
DeoptimizationBlob
::
create
(
&
buffer
,
NULL
,
0
,
0
,
0
,
0
);
}
}
...
@@ -116,7 +122,7 @@ void SharedRuntime::generate_deopt_blob() {
...
@@ -116,7 +122,7 @@ void SharedRuntime::generate_deopt_blob() {
_deopt_blob
=
generate_empty_deopt_blob
();
_deopt_blob
=
generate_empty_deopt_blob
();
}
}
SafepointBlob
*
SharedRuntime
::
generate_handler_blob
(
address
call_ptr
,
bool
cause_return
)
{
SafepointBlob
*
SharedRuntime
::
generate_handler_blob
(
address
call_ptr
,
int
poll_type
)
{
return
generate_empty_safepoint_blob
();
return
generate_empty_safepoint_blob
();
}
}
...
@@ -124,6 +130,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
...
@@ -124,6 +130,7 @@ RuntimeStub* SharedRuntime::generate_resolve_blob(address destination, const cha
return
generate_empty_runtime_stub
(
"resolve_blob"
);
return
generate_empty_runtime_stub
(
"resolve_blob"
);
}
}
int
SharedRuntime
::
c_calling_convention
(
const
BasicType
*
sig_bt
,
int
SharedRuntime
::
c_calling_convention
(
const
BasicType
*
sig_bt
,
VMRegPair
*
regs
,
VMRegPair
*
regs
,
int
total_args_passed
)
{
int
total_args_passed
)
{
...
...
src/os/bsd/vm/attachListener_bsd.cpp
浏览文件 @
34551e5c
...
@@ -342,7 +342,6 @@ BsdAttachOperation* BsdAttachListener::dequeue() {
...
@@ -342,7 +342,6 @@ BsdAttachOperation* BsdAttachListener::dequeue() {
// get the credentials of the peer and check the effective uid/guid
// get the credentials of the peer and check the effective uid/guid
// - check with jeff on this.
// - check with jeff on this.
#ifdef _ALLBSD_SOURCE
uid_t
puid
;
uid_t
puid
;
gid_t
pgid
;
gid_t
pgid
;
if
(
::
getpeereid
(
s
,
&
puid
,
&
pgid
)
!=
0
)
{
if
(
::
getpeereid
(
s
,
&
puid
,
&
pgid
)
!=
0
)
{
...
@@ -350,17 +349,6 @@ BsdAttachOperation* BsdAttachListener::dequeue() {
...
@@ -350,17 +349,6 @@ BsdAttachOperation* BsdAttachListener::dequeue() {
RESTARTABLE
(
::
close
(
s
),
res
);
RESTARTABLE
(
::
close
(
s
),
res
);
continue
;
continue
;
}
}
#else
struct
ucred
cred_info
;
socklen_t
optlen
=
sizeof
(
cred_info
);
if
(
::
getsockopt
(
s
,
SOL_SOCKET
,
SO_PEERCRED
,
(
void
*
)
&
cred_info
,
&
optlen
)
==
-
1
)
{
int
res
;
RESTARTABLE
(
::
close
(
s
),
res
);
continue
;
}
uid_t
puid
=
cred_info
.
uid
;
gid_t
pgid
=
cred_info
.
gid
;
#endif
uid_t
euid
=
geteuid
();
uid_t
euid
=
geteuid
();
gid_t
egid
=
getegid
();
gid_t
egid
=
getegid
();
...
...
src/os/bsd/vm/osThread_bsd.hpp
浏览文件 @
34551e5c
...
@@ -39,18 +39,12 @@
...
@@ -39,18 +39,12 @@
private
:
private
:
#ifdef _ALLBSD_SOURCE
#ifdef __APPLE__
#ifdef __APPLE__
typedef
thread_t
thread_id_t
;
typedef
thread_t
thread_id_t
;
#else
#else
typedef
pthread_t
thread_id_t
;
typedef
pthread_t
thread_id_t
;
#endif
#endif
#else
typedef
pid_t
thread_id_t
;
#endif
// _pthread_id is the pthread id, which is used by library calls
// _pthread_id is the pthread id, which is used by library calls
// (e.g. pthread_kill).
// (e.g. pthread_kill).
pthread_t
_pthread_id
;
pthread_t
_pthread_id
;
...
...
src/os/bsd/vm/os_bsd.cpp
浏览文件 @
34551e5c
...
@@ -108,14 +108,8 @@
...
@@ -108,14 +108,8 @@
# include <semaphore.h>
# include <semaphore.h>
# include <fcntl.h>
# include <fcntl.h>
# include <string.h>
# include <string.h>
#ifdef _ALLBSD_SOURCE
# include <sys/param.h>
# include <sys/param.h>
# include <sys/sysctl.h>
# include <sys/sysctl.h>
#else
# include <syscall.h>
# include <sys/sysinfo.h>
# include <gnu/libc-version.h>
#endif
# include <sys/ipc.h>
# include <sys/ipc.h>
# include <sys/shm.h>
# include <sys/shm.h>
#ifndef __APPLE__
#ifndef __APPLE__
...
@@ -150,25 +144,10 @@
...
@@ -150,25 +144,10 @@
// global variables
// global variables
julong
os
::
Bsd
::
_physical_memory
=
0
;
julong
os
::
Bsd
::
_physical_memory
=
0
;
#ifndef _ALLBSD_SOURCE
address
os
::
Bsd
::
_initial_thread_stack_bottom
=
NULL
;
uintptr_t
os
::
Bsd
::
_initial_thread_stack_size
=
0
;
#endif
int
(
*
os
::
Bsd
::
_clock_gettime
)(
clockid_t
,
struct
timespec
*
)
=
NULL
;
int
(
*
os
::
Bsd
::
_clock_gettime
)(
clockid_t
,
struct
timespec
*
)
=
NULL
;
#ifndef _ALLBSD_SOURCE
int
(
*
os
::
Bsd
::
_pthread_getcpuclockid
)(
pthread_t
,
clockid_t
*
)
=
NULL
;
Mutex
*
os
::
Bsd
::
_createThread_lock
=
NULL
;
#endif
pthread_t
os
::
Bsd
::
_main_thread
;
pthread_t
os
::
Bsd
::
_main_thread
;
int
os
::
Bsd
::
_page_size
=
-
1
;
int
os
::
Bsd
::
_page_size
=
-
1
;
#ifndef _ALLBSD_SOURCE
bool
os
::
Bsd
::
_is_floating_stack
=
false
;
bool
os
::
Bsd
::
_is_NPTL
=
false
;
bool
os
::
Bsd
::
_supports_fast_thread_cpu_time
=
false
;
const
char
*
os
::
Bsd
::
_glibc_version
=
NULL
;
const
char
*
os
::
Bsd
::
_libpthread_version
=
NULL
;
#endif
static
jlong
initial_time_count
=
0
;
static
jlong
initial_time_count
=
0
;
...
@@ -176,7 +155,7 @@ static int clock_tics_per_sec = 100;
...
@@ -176,7 +155,7 @@ static int clock_tics_per_sec = 100;
// For diagnostics to print a message once. see run_periodic_checks
// For diagnostics to print a message once. see run_periodic_checks
static
sigset_t
check_signal_done
;
static
sigset_t
check_signal_done
;
static
bool
check_signals
=
true
;
;
static
bool
check_signals
=
true
;
static
pid_t
_initial_pid
=
0
;
static
pid_t
_initial_pid
=
0
;
...
@@ -198,16 +177,8 @@ julong os::available_memory() {
...
@@ -198,16 +177,8 @@ julong os::available_memory() {
}
}
julong
os
::
Bsd
::
available_memory
()
{
julong
os
::
Bsd
::
available_memory
()
{
#ifdef _ALLBSD_SOURCE
// XXXBSD: this is just a stopgap implementation
// XXXBSD: this is just a stopgap implementation
return
physical_memory
()
>>
2
;
return
physical_memory
()
>>
2
;
#else
// values in struct sysinfo are "unsigned long"
struct
sysinfo
si
;
sysinfo
(
&
si
);
return
(
julong
)
si
.
freeram
*
si
.
mem_unit
;
#endif
}
}
julong
os
::
physical_memory
()
{
julong
os
::
physical_memory
()
{
...
@@ -255,22 +226,6 @@ bool os::have_special_privileges() {
...
@@ -255,22 +226,6 @@ bool os::have_special_privileges() {
}
}
#ifndef _ALLBSD_SOURCE
#ifndef SYS_gettid
// i386: 224, ia64: 1105, amd64: 186, sparc 143
#ifdef __ia64__
#define SYS_gettid 1105
#elif __i386__
#define SYS_gettid 224
#elif __amd64__
#define SYS_gettid 186
#elif __sparc__
#define SYS_gettid 143
#else
#error define gettid for the arch
#endif
#endif
#endif
// Cpu architecture string
// Cpu architecture string
#if defined(ZERO)
#if defined(ZERO)
...
@@ -302,36 +257,7 @@ static char cpu_arch[] = "sparc";
...
@@ -302,36 +257,7 @@ static char cpu_arch[] = "sparc";
#define COMPILER_VARIANT "client"
#define COMPILER_VARIANT "client"
#endif
#endif
#ifndef _ALLBSD_SOURCE
// pid_t gettid()
//
// Returns the kernel thread id of the currently running thread. Kernel
// thread id is used to access /proc.
//
// (Note that getpid() on BsdThreads returns kernel thread id too; but
// on NPTL, it returns the same pid for all threads, as required by POSIX.)
//
pid_t
os
::
Bsd
::
gettid
()
{
int
rslt
=
syscall
(
SYS_gettid
);
if
(
rslt
==
-
1
)
{
// old kernel, no NPTL support
return
getpid
();
}
else
{
return
(
pid_t
)
rslt
;
}
}
// Most versions of bsd have a bug where the number of processors are
// determined by looking at the /proc file system. In a chroot environment,
// the system call returns 1. This causes the VM to act as if it is
// a single processor and elide locking (see is_MP() call).
static
bool
unsafe_chroot_detected
=
false
;
static
const
char
*
unstable_chroot_error
=
"/proc file system not found.
\n
"
"Java may be unstable running multithreaded in a chroot "
"environment on Bsd when /proc filesystem is not mounted."
;
#endif
#ifdef _ALLBSD_SOURCE
void
os
::
Bsd
::
initialize_system_info
()
{
void
os
::
Bsd
::
initialize_system_info
()
{
int
mib
[
2
];
int
mib
[
2
];
size_t
len
;
size_t
len
;
...
@@ -370,24 +296,6 @@ void os::Bsd::initialize_system_info() {
...
@@ -370,24 +296,6 @@ void os::Bsd::initialize_system_info() {
}
}
#endif
#endif
}
}
#else
void
os
::
Bsd
::
initialize_system_info
()
{
set_processor_count
(
sysconf
(
_SC_NPROCESSORS_CONF
));
if
(
processor_count
()
==
1
)
{
pid_t
pid
=
os
::
Bsd
::
gettid
();
char
fname
[
32
];
jio_snprintf
(
fname
,
sizeof
(
fname
),
"/proc/%d"
,
pid
);
FILE
*
fp
=
fopen
(
fname
,
"r"
);
if
(
fp
==
NULL
)
{
unsafe_chroot_detected
=
true
;
}
else
{
fclose
(
fp
);
}
}
_physical_memory
=
(
julong
)
sysconf
(
_SC_PHYS_PAGES
)
*
(
julong
)
sysconf
(
_SC_PAGESIZE
);
assert
(
processor_count
()
>
0
,
"bsd error"
);
}
#endif
#ifdef __APPLE__
#ifdef __APPLE__
static
const
char
*
get_home
()
{
static
const
char
*
get_home
()
{
...
@@ -744,171 +652,6 @@ void os::Bsd::hotspot_sigmask(Thread* thread) {
...
@@ -744,171 +652,6 @@ void os::Bsd::hotspot_sigmask(Thread* thread) {
}
}
}
}
#ifndef _ALLBSD_SOURCE
//////////////////////////////////////////////////////////////////////////////
// detecting pthread library
void
os
::
Bsd
::
libpthread_init
()
{
// Save glibc and pthread version strings. Note that _CS_GNU_LIBC_VERSION
// and _CS_GNU_LIBPTHREAD_VERSION are supported in glibc >= 2.3.2. Use a
// generic name for earlier versions.
// Define macros here so we can build HotSpot on old systems.
# ifndef _CS_GNU_LIBC_VERSION
# define _CS_GNU_LIBC_VERSION 2
# endif
# ifndef _CS_GNU_LIBPTHREAD_VERSION
# define _CS_GNU_LIBPTHREAD_VERSION 3
# endif
size_t
n
=
confstr
(
_CS_GNU_LIBC_VERSION
,
NULL
,
0
);
if
(
n
>
0
)
{
char
*
str
=
(
char
*
)
malloc
(
n
);
confstr
(
_CS_GNU_LIBC_VERSION
,
str
,
n
);
os
::
Bsd
::
set_glibc_version
(
str
);
}
else
{
// _CS_GNU_LIBC_VERSION is not supported, try gnu_get_libc_version()
static
char
_gnu_libc_version
[
32
];
jio_snprintf
(
_gnu_libc_version
,
sizeof
(
_gnu_libc_version
),
"glibc %s %s"
,
gnu_get_libc_version
(),
gnu_get_libc_release
());
os
::
Bsd
::
set_glibc_version
(
_gnu_libc_version
);
}
n
=
confstr
(
_CS_GNU_LIBPTHREAD_VERSION
,
NULL
,
0
);
if
(
n
>
0
)
{
char
*
str
=
(
char
*
)
malloc
(
n
);
confstr
(
_CS_GNU_LIBPTHREAD_VERSION
,
str
,
n
);
// Vanilla RH-9 (glibc 2.3.2) has a bug that confstr() always tells
// us "NPTL-0.29" even we are running with BsdThreads. Check if this
// is the case. BsdThreads has a hard limit on max number of threads.
// So sysconf(_SC_THREAD_THREADS_MAX) will return a positive value.
// On the other hand, NPTL does not have such a limit, sysconf()
// will return -1 and errno is not changed. Check if it is really NPTL.
if
(
strcmp
(
os
::
Bsd
::
glibc_version
(),
"glibc 2.3.2"
)
==
0
&&
strstr
(
str
,
"NPTL"
)
&&
sysconf
(
_SC_THREAD_THREADS_MAX
)
>
0
)
{
free
(
str
);
os
::
Bsd
::
set_libpthread_version
(
"bsdthreads"
);
}
else
{
os
::
Bsd
::
set_libpthread_version
(
str
);
}
}
else
{
// glibc before 2.3.2 only has BsdThreads.
os
::
Bsd
::
set_libpthread_version
(
"bsdthreads"
);
}
if
(
strstr
(
libpthread_version
(),
"NPTL"
))
{
os
::
Bsd
::
set_is_NPTL
();
}
else
{
os
::
Bsd
::
set_is_BsdThreads
();
}
// BsdThreads have two flavors: floating-stack mode, which allows variable
// stack size; and fixed-stack mode. NPTL is always floating-stack.
if
(
os
::
Bsd
::
is_NPTL
()
||
os
::
Bsd
::
supports_variable_stack_size
())
{
os
::
Bsd
::
set_is_floating_stack
();
}
}
/////////////////////////////////////////////////////////////////////////////
// thread stack
// Force Bsd kernel to expand current thread stack. If "bottom" is close
// to the stack guard, caller should block all signals.
//
// MAP_GROWSDOWN:
// A special mmap() flag that is used to implement thread stacks. It tells
// kernel that the memory region should extend downwards when needed. This
// allows early versions of BsdThreads to only mmap the first few pages
// when creating a new thread. Bsd kernel will automatically expand thread
// stack as needed (on page faults).
//
// However, because the memory region of a MAP_GROWSDOWN stack can grow on
// demand, if a page fault happens outside an already mapped MAP_GROWSDOWN
// region, it's hard to tell if the fault is due to a legitimate stack
// access or because of reading/writing non-exist memory (e.g. buffer
// overrun). As a rule, if the fault happens below current stack pointer,
// Bsd kernel does not expand stack, instead a SIGSEGV is sent to the
// application (see Bsd kernel fault.c).
//
// This Bsd feature can cause SIGSEGV when VM bangs thread stack for
// stack overflow detection.
//
// Newer version of BsdThreads (since glibc-2.2, or, RH-7.x) and NPTL do
// not use this flag. However, the stack of initial thread is not created
// by pthread, it is still MAP_GROWSDOWN. Also it's possible (though
// unlikely) that user code can create a thread with MAP_GROWSDOWN stack
// and then attach the thread to JVM.
//
// To get around the problem and allow stack banging on Bsd, we need to
// manually expand thread stack after receiving the SIGSEGV.
//
// There are two ways to expand thread stack to address "bottom", we used
// both of them in JVM before 1.5:
// 1. adjust stack pointer first so that it is below "bottom", and then
// touch "bottom"
// 2. mmap() the page in question
//
// Now alternate signal stack is gone, it's harder to use 2. For instance,
// if current sp is already near the lower end of page 101, and we need to
// call mmap() to map page 100, it is possible that part of the mmap() frame
// will be placed in page 100. When page 100 is mapped, it is zero-filled.
// That will destroy the mmap() frame and cause VM to crash.
//
// The following code works by adjusting sp first, then accessing the "bottom"
// page to force a page fault. Bsd kernel will then automatically expand the
// stack mapping.
//
// _expand_stack_to() assumes its frame size is less than page size, which
// should always be true if the function is not inlined.
#if __GNUC__ < 3 // gcc 2.x does not support noinline attribute
#define NOINLINE
#else
#define NOINLINE __attribute__ ((noinline))
#endif
static
void
_expand_stack_to
(
address
bottom
)
NOINLINE
;
static
void
_expand_stack_to
(
address
bottom
)
{
address
sp
;
size_t
size
;
volatile
char
*
p
;
// Adjust bottom to point to the largest address within the same page, it
// gives us a one-page buffer if alloca() allocates slightly more memory.
bottom
=
(
address
)
align_size_down
((
uintptr_t
)
bottom
,
os
::
Bsd
::
page_size
());
bottom
+=
os
::
Bsd
::
page_size
()
-
1
;
// sp might be slightly above current stack pointer; if that's the case, we
// will alloca() a little more space than necessary, which is OK. Don't use
// os::current_stack_pointer(), as its result can be slightly below current
// stack pointer, causing us to not alloca enough to reach "bottom".
sp
=
(
address
)
&
sp
;
if
(
sp
>
bottom
)
{
size
=
sp
-
bottom
;
p
=
(
volatile
char
*
)
alloca
(
size
);
assert
(
p
!=
NULL
&&
p
<=
(
volatile
char
*
)
bottom
,
"alloca problem?"
);
p
[
0
]
=
'\0'
;
}
}
bool
os
::
Bsd
::
manually_expand_stack
(
JavaThread
*
t
,
address
addr
)
{
assert
(
t
!=
NULL
,
"just checking"
);
assert
(
t
->
osthread
()
->
expanding_stack
(),
"expand should be set"
);
assert
(
t
->
stack_base
()
!=
NULL
,
"stack_base was not initialized"
);
if
(
addr
<
t
->
stack_base
()
&&
addr
>=
t
->
stack_yellow_zone_base
())
{
sigset_t
mask_all
,
old_sigset
;
sigfillset
(
&
mask_all
);
pthread_sigmask
(
SIG_SETMASK
,
&
mask_all
,
&
old_sigset
);
_expand_stack_to
(
addr
);
pthread_sigmask
(
SIG_SETMASK
,
&
old_sigset
,
NULL
);
return
true
;
}
return
false
;
}
#endif
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// create new thread
// create new thread
...
@@ -917,43 +660,7 @@ static address highest_vm_reserved_address();
...
@@ -917,43 +660,7 @@ static address highest_vm_reserved_address();
// check if it's safe to start a new thread
// check if it's safe to start a new thread
static
bool
_thread_safety_check
(
Thread
*
thread
)
{
static
bool
_thread_safety_check
(
Thread
*
thread
)
{
#ifdef _ALLBSD_SOURCE
return
true
;
#else
if
(
os
::
Bsd
::
is_BsdThreads
()
&&
!
os
::
Bsd
::
is_floating_stack
())
{
// Fixed stack BsdThreads (SuSE Bsd/x86, and some versions of Redhat)
// Heap is mmap'ed at lower end of memory space. Thread stacks are
// allocated (MAP_FIXED) from high address space. Every thread stack
// occupies a fixed size slot (usually 2Mbytes, but user can change
// it to other values if they rebuild BsdThreads).
//
// Problem with MAP_FIXED is that mmap() can still succeed even part of
// the memory region has already been mmap'ed. That means if we have too
// many threads and/or very large heap, eventually thread stack will
// collide with heap.
//
// Here we try to prevent heap/stack collision by comparing current
// stack bottom with the highest address that has been mmap'ed by JVM
// plus a safety margin for memory maps created by native code.
//
// This feature can be disabled by setting ThreadSafetyMargin to 0
//
if
(
ThreadSafetyMargin
>
0
)
{
address
stack_bottom
=
os
::
current_stack_base
()
-
os
::
current_stack_size
();
// not safe if our stack extends below the safety margin
return
stack_bottom
-
ThreadSafetyMargin
>=
highest_vm_reserved_address
();
}
else
{
return
true
;
}
}
else
{
// Floating stack BsdThreads or NPTL:
// Unlike fixed stack BsdThreads, thread stacks are not MAP_FIXED. When
// there's not enough space left, pthread_create() will fail. If we come
// here, that means enough space has been reserved for stack.
return
true
;
return
true
;
}
#endif
}
}
#ifdef __APPLE__
#ifdef __APPLE__
...
@@ -991,24 +698,12 @@ static void *java_start(Thread *thread) {
...
@@ -991,24 +698,12 @@ static void *java_start(Thread *thread) {
return
NULL
;
return
NULL
;
}
}
#ifdef _ALLBSD_SOURCE
#ifdef __APPLE__
#ifdef __APPLE__
// thread_id is mach thread on macos
// thread_id is mach thread on macos
osthread
->
set_thread_id
(
::
mach_thread_self
());
osthread
->
set_thread_id
(
::
mach_thread_self
());
#else
#else
// thread_id is pthread_id on BSD
// thread_id is pthread_id on BSD
osthread
->
set_thread_id
(
::
pthread_self
());
osthread
->
set_thread_id
(
::
pthread_self
());
#endif
#else
// thread_id is kernel thread id (similar to Solaris LWP id)
osthread
->
set_thread_id
(
os
::
Bsd
::
gettid
());
if
(
UseNUMA
)
{
int
lgrp_id
=
os
::
numa_get_group_id
();
if
(
lgrp_id
!=
-
1
)
{
thread
->
set_lgrp_id
(
lgrp_id
);
}
}
#endif
#endif
// initialize signal mask for this thread
// initialize signal mask for this thread
os
::
Bsd
::
hotspot_sigmask
(
thread
);
os
::
Bsd
::
hotspot_sigmask
(
thread
);
...
@@ -1099,23 +794,9 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
...
@@ -1099,23 +794,9 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
// let pthread_create() pick the default value.
// let pthread_create() pick the default value.
}
}
#ifndef _ALLBSD_SOURCE
// glibc guard page
pthread_attr_setguardsize
(
&
attr
,
os
::
Bsd
::
default_guard_size
(
thr_type
));
#endif
ThreadState
state
;
ThreadState
state
;
{
{
#ifndef _ALLBSD_SOURCE
// Serialize thread creation if we are running with fixed stack BsdThreads
bool
lock
=
os
::
Bsd
::
is_BsdThreads
()
&&
!
os
::
Bsd
::
is_floating_stack
();
if
(
lock
)
{
os
::
Bsd
::
createThread_lock
()
->
lock_without_safepoint_check
();
}
#endif
pthread_t
tid
;
pthread_t
tid
;
int
ret
=
pthread_create
(
&
tid
,
&
attr
,
(
void
*
(
*
)(
void
*
))
java_start
,
thread
);
int
ret
=
pthread_create
(
&
tid
,
&
attr
,
(
void
*
(
*
)(
void
*
))
java_start
,
thread
);
...
@@ -1128,9 +809,6 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
...
@@ -1128,9 +809,6 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
// Need to clean up stuff we've allocated so far
// Need to clean up stuff we've allocated so far
thread
->
set_osthread
(
NULL
);
thread
->
set_osthread
(
NULL
);
delete
osthread
;
delete
osthread
;
#ifndef _ALLBSD_SOURCE
if
(
lock
)
os
::
Bsd
::
createThread_lock
()
->
unlock
();
#endif
return
false
;
return
false
;
}
}
...
@@ -1146,11 +824,6 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
...
@@ -1146,11 +824,6 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) {
}
}
}
}
#ifndef _ALLBSD_SOURCE
if
(
lock
)
{
os
::
Bsd
::
createThread_lock
()
->
unlock
();
}
#endif
}
}
// Aborted due to thread limit being reached
// Aborted due to thread limit being reached
...
@@ -1188,14 +861,10 @@ bool os::create_attached_thread(JavaThread* thread) {
...
@@ -1188,14 +861,10 @@ bool os::create_attached_thread(JavaThread* thread) {
}
}
// Store pthread info into the OSThread
// Store pthread info into the OSThread
#ifdef _ALLBSD_SOURCE
#ifdef __APPLE__
#ifdef __APPLE__
osthread
->
set_thread_id
(
::
mach_thread_self
());
osthread
->
set_thread_id
(
::
mach_thread_self
());
#else
#else
osthread
->
set_thread_id
(
::
pthread_self
());
osthread
->
set_thread_id
(
::
pthread_self
());
#endif
#else
osthread
->
set_thread_id
(
os
::
Bsd
::
gettid
());
#endif
#endif
osthread
->
set_pthread_id
(
::
pthread_self
());
osthread
->
set_pthread_id
(
::
pthread_self
());
...
@@ -1207,35 +876,6 @@ bool os::create_attached_thread(JavaThread* thread) {
...
@@ -1207,35 +876,6 @@ bool os::create_attached_thread(JavaThread* thread) {
thread
->
set_osthread
(
osthread
);
thread
->
set_osthread
(
osthread
);
#ifndef _ALLBSD_SOURCE
if
(
UseNUMA
)
{
int
lgrp_id
=
os
::
numa_get_group_id
();
if
(
lgrp_id
!=
-
1
)
{
thread
->
set_lgrp_id
(
lgrp_id
);
}
}
if
(
os
::
Bsd
::
is_initial_thread
())
{
// If current thread is initial thread, its stack is mapped on demand,
// see notes about MAP_GROWSDOWN. Here we try to force kernel to map
// the entire stack region to avoid SEGV in stack banging.
// It is also useful to get around the heap-stack-gap problem on SuSE
// kernel (see 4821821 for details). We first expand stack to the top
// of yellow zone, then enable stack yellow zone (order is significant,
// enabling yellow zone first will crash JVM on SuSE Bsd), so there
// is no gap between the last two virtual memory regions.
JavaThread
*
jt
=
(
JavaThread
*
)
thread
;
address
addr
=
jt
->
stack_yellow_zone_base
();
assert
(
addr
!=
NULL
,
"initialization problem?"
);
assert
(
jt
->
stack_available
(
addr
)
>
0
,
"stack guard should not be enabled"
);
osthread
->
set_expanding_stack
();
os
::
Bsd
::
manually_expand_stack
(
jt
,
addr
);
osthread
->
clear_expanding_stack
();
}
#endif
// initialize signal mask for this thread
// initialize signal mask for this thread
// and save the caller's signal mask
// and save the caller's signal mask
os
::
Bsd
::
hotspot_sigmask
(
thread
);
os
::
Bsd
::
hotspot_sigmask
(
thread
);
...
@@ -1290,247 +930,6 @@ extern "C" Thread* get_thread() {
...
@@ -1290,247 +930,6 @@ extern "C" Thread* get_thread() {
return
ThreadLocalStorage
::
thread
();
return
ThreadLocalStorage
::
thread
();
}
}
//////////////////////////////////////////////////////////////////////////////
// initial thread
#ifndef _ALLBSD_SOURCE
// Check if current thread is the initial thread, similar to Solaris thr_main.
bool
os
::
Bsd
::
is_initial_thread
(
void
)
{
char
dummy
;
// If called before init complete, thread stack bottom will be null.
// Can be called if fatal error occurs before initialization.
if
(
initial_thread_stack_bottom
()
==
NULL
)
return
false
;
assert
(
initial_thread_stack_bottom
()
!=
NULL
&&
initial_thread_stack_size
()
!=
0
,
"os::init did not locate initial thread's stack region"
);
if
((
address
)
&
dummy
>=
initial_thread_stack_bottom
()
&&
(
address
)
&
dummy
<
initial_thread_stack_bottom
()
+
initial_thread_stack_size
())
return
true
;
else
return
false
;
}
// Find the virtual memory area that contains addr
static
bool
find_vma
(
address
addr
,
address
*
vma_low
,
address
*
vma_high
)
{
FILE
*
fp
=
fopen
(
"/proc/self/maps"
,
"r"
);
if
(
fp
)
{
address
low
,
high
;
while
(
!
feof
(
fp
))
{
if
(
fscanf
(
fp
,
"%p-%p"
,
&
low
,
&
high
)
==
2
)
{
if
(
low
<=
addr
&&
addr
<
high
)
{
if
(
vma_low
)
*
vma_low
=
low
;
if
(
vma_high
)
*
vma_high
=
high
;
fclose
(
fp
);
return
true
;
}
}
for
(;;)
{
int
ch
=
fgetc
(
fp
);
if
(
ch
==
EOF
||
ch
==
(
int
)
'\n'
)
break
;
}
}
fclose
(
fp
);
}
return
false
;
}
// Locate initial thread stack. This special handling of initial thread stack
// is needed because pthread_getattr_np() on most (all?) Bsd distros returns
// bogus value for initial thread.
void
os
::
Bsd
::
capture_initial_stack
(
size_t
max_size
)
{
// stack size is the easy part, get it from RLIMIT_STACK
size_t
stack_size
;
struct
rlimit
rlim
;
getrlimit
(
RLIMIT_STACK
,
&
rlim
);
stack_size
=
rlim
.
rlim_cur
;
// 6308388: a bug in ld.so will relocate its own .data section to the
// lower end of primordial stack; reduce ulimit -s value a little bit
// so we won't install guard page on ld.so's data section.
stack_size
-=
2
*
page_size
();
// 4441425: avoid crash with "unlimited" stack size on SuSE 7.1 or Redhat
// 7.1, in both cases we will get 2G in return value.
// 4466587: glibc 2.2.x compiled w/o "--enable-kernel=2.4.0" (RH 7.0,
// SuSE 7.2, Debian) can not handle alternate signal stack correctly
// for initial thread if its stack size exceeds 6M. Cap it at 2M,
// in case other parts in glibc still assumes 2M max stack size.
// FIXME: alt signal stack is gone, maybe we can relax this constraint?
#ifndef IA64
if
(
stack_size
>
2
*
K
*
K
)
stack_size
=
2
*
K
*
K
;
#else
// Problem still exists RH7.2 (IA64 anyway) but 2MB is a little small
if
(
stack_size
>
4
*
K
*
K
)
stack_size
=
4
*
K
*
K
;
#endif
// Try to figure out where the stack base (top) is. This is harder.
//
// When an application is started, glibc saves the initial stack pointer in
// a global variable "__libc_stack_end", which is then used by system
// libraries. __libc_stack_end should be pretty close to stack top. The
// variable is available since the very early days. However, because it is
// a private interface, it could disappear in the future.
//
// Bsd kernel saves start_stack information in /proc/<pid>/stat. Similar
// to __libc_stack_end, it is very close to stack top, but isn't the real
// stack top. Note that /proc may not exist if VM is running as a chroot
// program, so reading /proc/<pid>/stat could fail. Also the contents of
// /proc/<pid>/stat could change in the future (though unlikely).
//
// We try __libc_stack_end first. If that doesn't work, look for
// /proc/<pid>/stat. If neither of them works, we use current stack pointer
// as a hint, which should work well in most cases.
uintptr_t
stack_start
;
// try __libc_stack_end first
uintptr_t
*
p
=
(
uintptr_t
*
)
dlsym
(
RTLD_DEFAULT
,
"__libc_stack_end"
);
if
(
p
&&
*
p
)
{
stack_start
=
*
p
;
}
else
{
// see if we can get the start_stack field from /proc/self/stat
FILE
*
fp
;
int
pid
;
char
state
;
int
ppid
;
int
pgrp
;
int
session
;
int
nr
;
int
tpgrp
;
unsigned
long
flags
;
unsigned
long
minflt
;
unsigned
long
cminflt
;
unsigned
long
majflt
;
unsigned
long
cmajflt
;
unsigned
long
utime
;
unsigned
long
stime
;
long
cutime
;
long
cstime
;
long
prio
;
long
nice
;
long
junk
;
long
it_real
;
uintptr_t
start
;
uintptr_t
vsize
;
intptr_t
rss
;
uintptr_t
rsslim
;
uintptr_t
scodes
;
uintptr_t
ecode
;
int
i
;
// Figure what the primordial thread stack base is. Code is inspired
// by email from Hans Boehm. /proc/self/stat begins with current pid,
// followed by command name surrounded by parentheses, state, etc.
char
stat
[
2048
];
int
statlen
;
fp
=
fopen
(
"/proc/self/stat"
,
"r"
);
if
(
fp
)
{
statlen
=
fread
(
stat
,
1
,
2047
,
fp
);
stat
[
statlen
]
=
'\0'
;
fclose
(
fp
);
// Skip pid and the command string. Note that we could be dealing with
// weird command names, e.g. user could decide to rename java launcher
// to "java 1.4.2 :)", then the stat file would look like
// 1234 (java 1.4.2 :)) R ... ...
// We don't really need to know the command string, just find the last
// occurrence of ")" and then start parsing from there. See bug 4726580.
char
*
s
=
strrchr
(
stat
,
')'
);
i
=
0
;
if
(
s
)
{
// Skip blank chars
do
s
++
;
while
(
isspace
(
*
s
));
#define _UFM UINTX_FORMAT
#define _DFM INTX_FORMAT
/* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 */
/* 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 */
i
=
sscanf
(
s
,
"%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld %ld %ld %ld "
_UFM
_UFM
_DFM
_UFM
_UFM
_UFM
_UFM
,
&
state
,
/* 3 %c */
&
ppid
,
/* 4 %d */
&
pgrp
,
/* 5 %d */
&
session
,
/* 6 %d */
&
nr
,
/* 7 %d */
&
tpgrp
,
/* 8 %d */
&
flags
,
/* 9 %lu */
&
minflt
,
/* 10 %lu */
&
cminflt
,
/* 11 %lu */
&
majflt
,
/* 12 %lu */
&
cmajflt
,
/* 13 %lu */
&
utime
,
/* 14 %lu */
&
stime
,
/* 15 %lu */
&
cutime
,
/* 16 %ld */
&
cstime
,
/* 17 %ld */
&
prio
,
/* 18 %ld */
&
nice
,
/* 19 %ld */
&
junk
,
/* 20 %ld */
&
it_real
,
/* 21 %ld */
&
start
,
/* 22 UINTX_FORMAT */
&
vsize
,
/* 23 UINTX_FORMAT */
&
rss
,
/* 24 INTX_FORMAT */
&
rsslim
,
/* 25 UINTX_FORMAT */
&
scodes
,
/* 26 UINTX_FORMAT */
&
ecode
,
/* 27 UINTX_FORMAT */
&
stack_start
);
/* 28 UINTX_FORMAT */
}
#undef _UFM
#undef _DFM
if
(
i
!=
28
-
2
)
{
assert
(
false
,
"Bad conversion from /proc/self/stat"
);
// product mode - assume we are the initial thread, good luck in the
// embedded case.
warning
(
"Can't detect initial thread stack location - bad conversion"
);
stack_start
=
(
uintptr_t
)
&
rlim
;
}
}
else
{
// For some reason we can't open /proc/self/stat (for example, running on
// FreeBSD with a Bsd emulator, or inside chroot), this should work for
// most cases, so don't abort:
warning
(
"Can't detect initial thread stack location - no /proc/self/stat"
);
stack_start
=
(
uintptr_t
)
&
rlim
;
}
}
// Now we have a pointer (stack_start) very close to the stack top, the
// next thing to do is to figure out the exact location of stack top. We
// can find out the virtual memory area that contains stack_start by
// reading /proc/self/maps, it should be the last vma in /proc/self/maps,
// and its upper limit is the real stack top. (again, this would fail if
// running inside chroot, because /proc may not exist.)
uintptr_t
stack_top
;
address
low
,
high
;
if
(
find_vma
((
address
)
stack_start
,
&
low
,
&
high
))
{
// success, "high" is the true stack top. (ignore "low", because initial
// thread stack grows on demand, its real bottom is high - RLIMIT_STACK.)
stack_top
=
(
uintptr_t
)
high
;
}
else
{
// failed, likely because /proc/self/maps does not exist
warning
(
"Can't detect initial thread stack location - find_vma failed"
);
// best effort: stack_start is normally within a few pages below the real
// stack top, use it as stack top, and reduce stack size so we won't put
// guard page outside stack.
stack_top
=
stack_start
;
stack_size
-=
16
*
page_size
();
}
// stack_top could be partially down the page so align it
stack_top
=
align_size_up
(
stack_top
,
page_size
());
if
(
max_size
&&
stack_size
>
max_size
)
{
_initial_thread_stack_size
=
max_size
;
}
else
{
_initial_thread_stack_size
=
stack_size
;
}
_initial_thread_stack_size
=
align_size_down
(
_initial_thread_stack_size
,
page_size
());
_initial_thread_stack_bottom
=
(
address
)
stack_top
-
_initial_thread_stack_size
;
}
#endif
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// time support
// time support
...
@@ -1576,7 +975,7 @@ jlong os::javaTimeMillis() {
...
@@ -1576,7 +975,7 @@ jlong os::javaTimeMillis() {
void
os
::
Bsd
::
clock_init
()
{
void
os
::
Bsd
::
clock_init
()
{
// XXXDARWIN: Investigate replacement monotonic clock
// XXXDARWIN: Investigate replacement monotonic clock
}
}
#el
if defined(_ALLBSD_SOURCE)
#el
se
void
os
::
Bsd
::
clock_init
()
{
void
os
::
Bsd
::
clock_init
()
{
struct
timespec
res
;
struct
timespec
res
;
struct
timespec
tp
;
struct
timespec
tp
;
...
@@ -1586,86 +985,8 @@ void os::Bsd::clock_init() {
...
@@ -1586,86 +985,8 @@ void os::Bsd::clock_init() {
_clock_gettime
=
::
clock_gettime
;
_clock_gettime
=
::
clock_gettime
;
}
}
}
}
#else
void
os
::
Bsd
::
clock_init
()
{
// we do dlopen's in this particular order due to bug in bsd
// dynamical loader (see 6348968) leading to crash on exit
void
*
handle
=
dlopen
(
"librt.so.1"
,
RTLD_LAZY
);
if
(
handle
==
NULL
)
{
handle
=
dlopen
(
"librt.so"
,
RTLD_LAZY
);
}
if
(
handle
)
{
int
(
*
clock_getres_func
)(
clockid_t
,
struct
timespec
*
)
=
(
int
(
*
)(
clockid_t
,
struct
timespec
*
))
dlsym
(
handle
,
"clock_getres"
);
int
(
*
clock_gettime_func
)(
clockid_t
,
struct
timespec
*
)
=
(
int
(
*
)(
clockid_t
,
struct
timespec
*
))
dlsym
(
handle
,
"clock_gettime"
);
if
(
clock_getres_func
&&
clock_gettime_func
)
{
// See if monotonic clock is supported by the kernel. Note that some
// early implementations simply return kernel jiffies (updated every
// 1/100 or 1/1000 second). It would be bad to use such a low res clock
// for nano time (though the monotonic property is still nice to have).
// It's fixed in newer kernels, however clock_getres() still returns
// 1/HZ. We check if clock_getres() works, but will ignore its reported
// resolution for now. Hopefully as people move to new kernels, this
// won't be a problem.
struct
timespec
res
;
struct
timespec
tp
;
if
(
clock_getres_func
(
CLOCK_MONOTONIC
,
&
res
)
==
0
&&
clock_gettime_func
(
CLOCK_MONOTONIC
,
&
tp
)
==
0
)
{
// yes, monotonic clock is supported
_clock_gettime
=
clock_gettime_func
;
}
else
{
// close librt if there is no monotonic clock
dlclose
(
handle
);
}
}
}
}
#endif
#endif
#ifndef _ALLBSD_SOURCE
#ifndef SYS_clock_getres
#if defined(IA32) || defined(AMD64)
#define SYS_clock_getres IA32_ONLY(266) AMD64_ONLY(229)
#define sys_clock_getres(x,y) ::syscall(SYS_clock_getres, x, y)
#else
#warning "SYS_clock_getres not defined for this platform, disabling fast_thread_cpu_time"
#define sys_clock_getres(x,y) -1
#endif
#else
#define sys_clock_getres(x,y) ::syscall(SYS_clock_getres, x, y)
#endif
void
os
::
Bsd
::
fast_thread_clock_init
()
{
if
(
!
UseBsdPosixThreadCPUClocks
)
{
return
;
}
clockid_t
clockid
;
struct
timespec
tp
;
int
(
*
pthread_getcpuclockid_func
)(
pthread_t
,
clockid_t
*
)
=
(
int
(
*
)(
pthread_t
,
clockid_t
*
))
dlsym
(
RTLD_DEFAULT
,
"pthread_getcpuclockid"
);
// Switch to using fast clocks for thread cpu time if
// the sys_clock_getres() returns 0 error code.
// Note, that some kernels may support the current thread
// clock (CLOCK_THREAD_CPUTIME_ID) but not the clocks
// returned by the pthread_getcpuclockid().
// If the fast Posix clocks are supported then the sys_clock_getres()
// must return at least tp.tv_sec == 0 which means a resolution
// better than 1 sec. This is extra check for reliability.
if
(
pthread_getcpuclockid_func
&&
pthread_getcpuclockid_func
(
_main_thread
,
&
clockid
)
==
0
&&
sys_clock_getres
(
clockid
,
&
tp
)
==
0
&&
tp
.
tv_sec
==
0
)
{
_supports_fast_thread_cpu_time
=
true
;
_pthread_getcpuclockid
=
pthread_getcpuclockid_func
;
}
}
#endif
jlong
os
::
javaTimeNanos
()
{
jlong
os
::
javaTimeNanos
()
{
if
(
Bsd
::
supports_monotonic_clock
())
{
if
(
Bsd
::
supports_monotonic_clock
())
{
...
@@ -1978,7 +1299,6 @@ bool os::dll_address_to_function_name(address addr, char *buf,
...
@@ -1978,7 +1299,6 @@ bool os::dll_address_to_function_name(address addr, char *buf,
return
false
;
return
false
;
}
}
#ifdef _ALLBSD_SOURCE
// ported from solaris version
// ported from solaris version
bool
os
::
dll_address_to_library_name
(
address
addr
,
char
*
buf
,
bool
os
::
dll_address_to_library_name
(
address
addr
,
char
*
buf
,
int
buflen
,
int
*
offset
)
{
int
buflen
,
int
*
offset
)
{
...
@@ -1994,86 +1314,10 @@ bool os::dll_address_to_library_name(address addr, char* buf,
...
@@ -1994,86 +1314,10 @@ bool os::dll_address_to_library_name(address addr, char* buf,
return
false
;
return
false
;
}
}
}
}
#else
struct
_address_to_library_name
{
address
addr
;
// input : memory address
size_t
buflen
;
// size of fname
char
*
fname
;
// output: library name
address
base
;
// library base addr
};
static
int
address_to_library_name_callback
(
struct
dl_phdr_info
*
info
,
// Loads .dll/.so and
size_t
size
,
void
*
data
)
{
// in case of error it checks if .dll/.so was built for the
int
i
;
// same architecture as Hotspot is running on
bool
found
=
false
;
address
libbase
=
NULL
;
struct
_address_to_library_name
*
d
=
(
struct
_address_to_library_name
*
)
data
;
// iterate through all loadable segments
for
(
i
=
0
;
i
<
info
->
dlpi_phnum
;
i
++
)
{
address
segbase
=
(
address
)(
info
->
dlpi_addr
+
info
->
dlpi_phdr
[
i
].
p_vaddr
);
if
(
info
->
dlpi_phdr
[
i
].
p_type
==
PT_LOAD
)
{
// base address of a library is the lowest address of its loaded
// segments.
if
(
libbase
==
NULL
||
libbase
>
segbase
)
{
libbase
=
segbase
;
}
// see if 'addr' is within current segment
if
(
segbase
<=
d
->
addr
&&
d
->
addr
<
segbase
+
info
->
dlpi_phdr
[
i
].
p_memsz
)
{
found
=
true
;
}
}
}
// dlpi_name is NULL or empty if the ELF file is executable, return 0
// so dll_address_to_library_name() can fall through to use dladdr() which
// can figure out executable name from argv[0].
if
(
found
&&
info
->
dlpi_name
&&
info
->
dlpi_name
[
0
])
{
d
->
base
=
libbase
;
if
(
d
->
fname
)
{
jio_snprintf
(
d
->
fname
,
d
->
buflen
,
"%s"
,
info
->
dlpi_name
);
}
return
1
;
}
return
0
;
}
bool
os
::
dll_address_to_library_name
(
address
addr
,
char
*
buf
,
int
buflen
,
int
*
offset
)
{
Dl_info
dlinfo
;
struct
_address_to_library_name
data
;
// There is a bug in old glibc dladdr() implementation that it could resolve
// to wrong library name if the .so file has a base address != NULL. Here
// we iterate through the program headers of all loaded libraries to find
// out which library 'addr' really belongs to. This workaround can be
// removed once the minimum requirement for glibc is moved to 2.3.x.
data
.
addr
=
addr
;
data
.
fname
=
buf
;
data
.
buflen
=
buflen
;
data
.
base
=
NULL
;
int
rslt
=
dl_iterate_phdr
(
address_to_library_name_callback
,
(
void
*
)
&
data
);
if
(
rslt
)
{
// buf already contains library name
if
(
offset
)
*
offset
=
addr
-
data
.
base
;
return
true
;
}
else
if
(
dladdr
((
void
*
)
addr
,
&
dlinfo
)){
if
(
buf
)
jio_snprintf
(
buf
,
buflen
,
"%s"
,
dlinfo
.
dli_fname
);
if
(
offset
)
*
offset
=
addr
-
(
address
)
dlinfo
.
dli_fbase
;
return
true
;
}
else
{
if
(
buf
)
buf
[
0
]
=
'\0'
;
if
(
offset
)
*
offset
=
-
1
;
return
false
;
}
}
#endif
// Loads .dll/.so and
// in case of error it checks if .dll/.so was built for the
// same architecture as Hotspot is running on
#ifdef __APPLE__
#ifdef __APPLE__
void
*
os
::
dll_load
(
const
char
*
filename
,
char
*
ebuf
,
int
ebuflen
)
{
void
*
os
::
dll_load
(
const
char
*
filename
,
char
*
ebuf
,
int
ebuflen
)
{
...
@@ -2292,7 +1536,6 @@ static bool _print_ascii_file(const char* filename, outputStream* st) {
...
@@ -2292,7 +1536,6 @@ static bool _print_ascii_file(const char* filename, outputStream* st) {
void
os
::
print_dll_info
(
outputStream
*
st
)
{
void
os
::
print_dll_info
(
outputStream
*
st
)
{
st
->
print_cr
(
"Dynamic libraries:"
);
st
->
print_cr
(
"Dynamic libraries:"
);
#ifdef _ALLBSD_SOURCE
#ifdef RTLD_DI_LINKMAP
#ifdef RTLD_DI_LINKMAP
Dl_info
dli
;
Dl_info
dli
;
void
*
handle
;
void
*
handle
;
...
@@ -2336,16 +1579,6 @@ void os::print_dll_info(outputStream *st) {
...
@@ -2336,16 +1579,6 @@ void os::print_dll_info(outputStream *st) {
#else
#else
st
->
print_cr
(
"Error: Cannot print dynamic libraries."
);
st
->
print_cr
(
"Error: Cannot print dynamic libraries."
);
#endif
#endif
#else
char
fname
[
32
];
pid_t
pid
=
os
::
Bsd
::
gettid
();
jio_snprintf
(
fname
,
sizeof
(
fname
),
"/proc/%d/maps"
,
pid
);
if
(
!
_print_ascii_file
(
fname
,
st
))
{
st
->
print
(
"Can not get library information for pid = %d
\n
"
,
pid
);
}
#endif
}
}
void
os
::
print_os_info_brief
(
outputStream
*
st
)
{
void
os
::
print_os_info_brief
(
outputStream
*
st
)
{
...
@@ -2374,22 +1607,10 @@ void os::print_memory_info(outputStream* st) {
...
@@ -2374,22 +1607,10 @@ void os::print_memory_info(outputStream* st) {
st
->
print
(
"Memory:"
);
st
->
print
(
"Memory:"
);
st
->
print
(
" %dk page"
,
os
::
vm_page_size
()
>>
10
);
st
->
print
(
" %dk page"
,
os
::
vm_page_size
()
>>
10
);
#ifndef _ALLBSD_SOURCE
// values in struct sysinfo are "unsigned long"
struct
sysinfo
si
;
sysinfo
(
&
si
);
#endif
st
->
print
(
", physical "
UINT64_FORMAT
"k"
,
st
->
print
(
", physical "
UINT64_FORMAT
"k"
,
os
::
physical_memory
()
>>
10
);
os
::
physical_memory
()
>>
10
);
st
->
print
(
"("
UINT64_FORMAT
"k free)"
,
st
->
print
(
"("
UINT64_FORMAT
"k free)"
,
os
::
available_memory
()
>>
10
);
os
::
available_memory
()
>>
10
);
#ifndef _ALLBSD_SOURCE
st
->
print
(
", swap "
UINT64_FORMAT
"k"
,
((
jlong
)
si
.
totalswap
*
si
.
mem_unit
)
>>
10
);
st
->
print
(
"("
UINT64_FORMAT
"k free)"
,
((
jlong
)
si
.
freeswap
*
si
.
mem_unit
)
>>
10
);
#endif
st
->
cr
();
st
->
cr
();
// meminfo
// meminfo
...
@@ -2786,42 +2007,13 @@ bool os::pd_commit_memory(char* addr, size_t size, bool exec) {
...
@@ -2786,42 +2007,13 @@ bool os::pd_commit_memory(char* addr, size_t size, bool exec) {
#endif
#endif
}
}
#ifndef _ALLBSD_SOURCE
// Define MAP_HUGETLB here so we can build HotSpot on old systems.
#ifndef MAP_HUGETLB
#define MAP_HUGETLB 0x40000
#endif
// Define MADV_HUGEPAGE here so we can build HotSpot on old systems.
#ifndef MADV_HUGEPAGE
#define MADV_HUGEPAGE 14
#endif
#endif
bool
os
::
pd_commit_memory
(
char
*
addr
,
size_t
size
,
size_t
alignment_hint
,
bool
os
::
pd_commit_memory
(
char
*
addr
,
size_t
size
,
size_t
alignment_hint
,
bool
exec
)
{
bool
exec
)
{
#ifndef _ALLBSD_SOURCE
if
(
UseHugeTLBFS
&&
alignment_hint
>
(
size_t
)
vm_page_size
())
{
int
prot
=
exec
?
PROT_READ
|
PROT_WRITE
|
PROT_EXEC
:
PROT_READ
|
PROT_WRITE
;
uintptr_t
res
=
(
uintptr_t
)
::
mmap
(
addr
,
size
,
prot
,
MAP_PRIVATE
|
MAP_FIXED
|
MAP_ANONYMOUS
|
MAP_HUGETLB
,
-
1
,
0
);
return
res
!=
(
uintptr_t
)
MAP_FAILED
;
}
#endif
return
commit_memory
(
addr
,
size
,
exec
);
return
commit_memory
(
addr
,
size
,
exec
);
}
}
void
os
::
pd_realign_memory
(
char
*
addr
,
size_t
bytes
,
size_t
alignment_hint
)
{
void
os
::
pd_realign_memory
(
char
*
addr
,
size_t
bytes
,
size_t
alignment_hint
)
{
#ifndef _ALLBSD_SOURCE
if
(
UseHugeTLBFS
&&
alignment_hint
>
(
size_t
)
vm_page_size
())
{
// We don't check the return value: madvise(MADV_HUGEPAGE) may not
// be supported or the memory may already be backed by huge pages.
::
madvise
(
addr
,
bytes
,
MADV_HUGEPAGE
);
}
#endif
}
}
void
os
::
pd_free_memory
(
char
*
addr
,
size_t
bytes
,
size_t
alignment_hint
)
{
void
os
::
pd_free_memory
(
char
*
addr
,
size_t
bytes
,
size_t
alignment_hint
)
{
...
@@ -2860,111 +2052,6 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info
...
@@ -2860,111 +2052,6 @@ char *os::scan_pages(char *start, char* end, page_info* page_expected, page_info
return
end
;
return
end
;
}
}
#ifndef _ALLBSD_SOURCE
// Something to do with the numa-aware allocator needs these symbols
extern
"C"
JNIEXPORT
void
numa_warn
(
int
number
,
char
*
where
,
...)
{
}
extern
"C"
JNIEXPORT
void
numa_error
(
char
*
where
)
{
}
extern
"C"
JNIEXPORT
int
fork1
()
{
return
fork
();
}
// If we are running with libnuma version > 2, then we should
// be trying to use symbols with versions 1.1
// If we are running with earlier version, which did not have symbol versions,
// we should use the base version.
void
*
os
::
Bsd
::
libnuma_dlsym
(
void
*
handle
,
const
char
*
name
)
{
void
*
f
=
dlvsym
(
handle
,
name
,
"libnuma_1.1"
);
if
(
f
==
NULL
)
{
f
=
dlsym
(
handle
,
name
);
}
return
f
;
}
bool
os
::
Bsd
::
libnuma_init
()
{
// sched_getcpu() should be in libc.
set_sched_getcpu
(
CAST_TO_FN_PTR
(
sched_getcpu_func_t
,
dlsym
(
RTLD_DEFAULT
,
"sched_getcpu"
)));
if
(
sched_getcpu
()
!=
-
1
)
{
// Does it work?
void
*
handle
=
dlopen
(
"libnuma.so.1"
,
RTLD_LAZY
);
if
(
handle
!=
NULL
)
{
set_numa_node_to_cpus
(
CAST_TO_FN_PTR
(
numa_node_to_cpus_func_t
,
libnuma_dlsym
(
handle
,
"numa_node_to_cpus"
)));
set_numa_max_node
(
CAST_TO_FN_PTR
(
numa_max_node_func_t
,
libnuma_dlsym
(
handle
,
"numa_max_node"
)));
set_numa_available
(
CAST_TO_FN_PTR
(
numa_available_func_t
,
libnuma_dlsym
(
handle
,
"numa_available"
)));
set_numa_tonode_memory
(
CAST_TO_FN_PTR
(
numa_tonode_memory_func_t
,
libnuma_dlsym
(
handle
,
"numa_tonode_memory"
)));
set_numa_interleave_memory
(
CAST_TO_FN_PTR
(
numa_interleave_memory_func_t
,
libnuma_dlsym
(
handle
,
"numa_interleave_memory"
)));
if
(
numa_available
()
!=
-
1
)
{
set_numa_all_nodes
((
unsigned
long
*
)
libnuma_dlsym
(
handle
,
"numa_all_nodes"
));
// Create a cpu -> node mapping
_cpu_to_node
=
new
(
ResourceObj
::
C_HEAP
)
GrowableArray
<
int
>
(
0
,
true
);
rebuild_cpu_to_node_map
();
return
true
;
}
}
}
return
false
;
}
// rebuild_cpu_to_node_map() constructs a table mapping cpud id to node id.
// The table is later used in get_node_by_cpu().
void
os
::
Bsd
::
rebuild_cpu_to_node_map
()
{
const
size_t
NCPUS
=
32768
;
// Since the buffer size computation is very obscure
// in libnuma (possible values are starting from 16,
// and continuing up with every other power of 2, but less
// than the maximum number of CPUs supported by kernel), and
// is a subject to change (in libnuma version 2 the requirements
// are more reasonable) we'll just hardcode the number they use
// in the library.
const
size_t
BitsPerCLong
=
sizeof
(
long
)
*
CHAR_BIT
;
size_t
cpu_num
=
os
::
active_processor_count
();
size_t
cpu_map_size
=
NCPUS
/
BitsPerCLong
;
size_t
cpu_map_valid_size
=
MIN2
((
cpu_num
+
BitsPerCLong
-
1
)
/
BitsPerCLong
,
cpu_map_size
);
cpu_to_node
()
->
clear
();
cpu_to_node
()
->
at_grow
(
cpu_num
-
1
);
size_t
node_num
=
numa_get_groups_num
();
unsigned
long
*
cpu_map
=
NEW_C_HEAP_ARRAY
(
unsigned
long
,
cpu_map_size
);
for
(
size_t
i
=
0
;
i
<
node_num
;
i
++
)
{
if
(
numa_node_to_cpus
(
i
,
cpu_map
,
cpu_map_size
*
sizeof
(
unsigned
long
))
!=
-
1
)
{
for
(
size_t
j
=
0
;
j
<
cpu_map_valid_size
;
j
++
)
{
if
(
cpu_map
[
j
]
!=
0
)
{
for
(
size_t
k
=
0
;
k
<
BitsPerCLong
;
k
++
)
{
if
(
cpu_map
[
j
]
&
(
1UL
<<
k
))
{
cpu_to_node
()
->
at_put
(
j
*
BitsPerCLong
+
k
,
i
);
}
}
}
}
}
}
FREE_C_HEAP_ARRAY
(
unsigned
long
,
cpu_map
);
}
int
os
::
Bsd
::
get_node_by_cpu
(
int
cpu_id
)
{
if
(
cpu_to_node
()
!=
NULL
&&
cpu_id
>=
0
&&
cpu_id
<
cpu_to_node
()
->
length
())
{
return
cpu_to_node
()
->
at
(
cpu_id
);
}
return
-
1
;
}
GrowableArray
<
int
>*
os
::
Bsd
::
_cpu_to_node
;
os
::
Bsd
::
sched_getcpu_func_t
os
::
Bsd
::
_sched_getcpu
;
os
::
Bsd
::
numa_node_to_cpus_func_t
os
::
Bsd
::
_numa_node_to_cpus
;
os
::
Bsd
::
numa_max_node_func_t
os
::
Bsd
::
_numa_max_node
;
os
::
Bsd
::
numa_available_func_t
os
::
Bsd
::
_numa_available
;
os
::
Bsd
::
numa_tonode_memory_func_t
os
::
Bsd
::
_numa_tonode_memory
;
os
::
Bsd
::
numa_interleave_memory_func_t
os
::
Bsd
::
_numa_interleave_memory
;
unsigned
long
*
os
::
Bsd
::
_numa_all_nodes
;
#endif
bool
os
::
pd_uncommit_memory
(
char
*
addr
,
size_t
size
)
{
bool
os
::
pd_uncommit_memory
(
char
*
addr
,
size_t
size
)
{
#ifdef __OpenBSD__
#ifdef __OpenBSD__
...
@@ -3084,42 +2171,7 @@ bool os::unguard_memory(char* addr, size_t size) {
...
@@ -3084,42 +2171,7 @@ bool os::unguard_memory(char* addr, size_t size) {
}
}
bool
os
::
Bsd
::
hugetlbfs_sanity_check
(
bool
warn
,
size_t
page_size
)
{
bool
os
::
Bsd
::
hugetlbfs_sanity_check
(
bool
warn
,
size_t
page_size
)
{
bool
result
=
false
;
return
false
;
#ifndef _ALLBSD_SOURCE
void
*
p
=
mmap
(
NULL
,
page_size
,
PROT_READ
|
PROT_WRITE
,
MAP_ANONYMOUS
|
MAP_PRIVATE
|
MAP_HUGETLB
,
-
1
,
0
);
if
(
p
!=
(
void
*
)
-
1
)
{
// We don't know if this really is a huge page or not.
FILE
*
fp
=
fopen
(
"/proc/self/maps"
,
"r"
);
if
(
fp
)
{
while
(
!
feof
(
fp
))
{
char
chars
[
257
];
long
x
=
0
;
if
(
fgets
(
chars
,
sizeof
(
chars
),
fp
))
{
if
(
sscanf
(
chars
,
"%lx-%*x"
,
&
x
)
==
1
&&
x
==
(
long
)
p
)
{
if
(
strstr
(
chars
,
"hugepage"
))
{
result
=
true
;
break
;
}
}
}
}
fclose
(
fp
);
}
munmap
(
p
,
page_size
);
if
(
result
)
return
true
;
}
if
(
warn
)
{
warning
(
"HugeTLBFS is not supported by the operating system."
);
}
#endif
return
result
;
}
}
/*
/*
...
@@ -3164,92 +2216,8 @@ static void set_coredump_filter(void) {
...
@@ -3164,92 +2216,8 @@ static void set_coredump_filter(void) {
static
size_t
_large_page_size
=
0
;
static
size_t
_large_page_size
=
0
;
void
os
::
large_page_init
()
{
void
os
::
large_page_init
()
{
#ifndef _ALLBSD_SOURCE
if
(
!
UseLargePages
)
{
UseHugeTLBFS
=
false
;
UseSHM
=
false
;
return
;
}
if
(
FLAG_IS_DEFAULT
(
UseHugeTLBFS
)
&&
FLAG_IS_DEFAULT
(
UseSHM
))
{
// If UseLargePages is specified on the command line try both methods,
// if it's default, then try only HugeTLBFS.
if
(
FLAG_IS_DEFAULT
(
UseLargePages
))
{
UseHugeTLBFS
=
true
;
}
else
{
UseHugeTLBFS
=
UseSHM
=
true
;
}
}
if
(
LargePageSizeInBytes
)
{
_large_page_size
=
LargePageSizeInBytes
;
}
else
{
// large_page_size on Bsd is used to round up heap size. x86 uses either
// 2M or 4M page, depending on whether PAE (Physical Address Extensions)
// mode is enabled. AMD64/EM64T uses 2M page in 64bit mode. IA64 can use
// page as large as 256M.
//
// Here we try to figure out page size by parsing /proc/meminfo and looking
// for a line with the following format:
// Hugepagesize: 2048 kB
//
// If we can't determine the value (e.g. /proc is not mounted, or the text
// format has been changed), we'll use the largest page size supported by
// the processor.
#ifndef ZERO
_large_page_size
=
IA32_ONLY
(
4
*
M
)
AMD64_ONLY
(
2
*
M
)
IA64_ONLY
(
256
*
M
)
SPARC_ONLY
(
4
*
M
)
ARM_ONLY
(
2
*
M
)
PPC_ONLY
(
4
*
M
);
#endif // ZERO
FILE
*
fp
=
fopen
(
"/proc/meminfo"
,
"r"
);
if
(
fp
)
{
while
(
!
feof
(
fp
))
{
int
x
=
0
;
char
buf
[
16
];
if
(
fscanf
(
fp
,
"Hugepagesize: %d"
,
&
x
)
==
1
)
{
if
(
x
&&
fgets
(
buf
,
sizeof
(
buf
),
fp
)
&&
strcmp
(
buf
,
" kB
\n
"
)
==
0
)
{
_large_page_size
=
x
*
K
;
break
;
}
}
else
{
// skip to next line
for
(;;)
{
int
ch
=
fgetc
(
fp
);
if
(
ch
==
EOF
||
ch
==
(
int
)
'\n'
)
break
;
}
}
}
fclose
(
fp
);
}
}
// print a warning if any large page related flag is specified on command line
bool
warn_on_failure
=
!
FLAG_IS_DEFAULT
(
UseHugeTLBFS
);
const
size_t
default_page_size
=
(
size_t
)
Bsd
::
page_size
();
if
(
_large_page_size
>
default_page_size
)
{
_page_sizes
[
0
]
=
_large_page_size
;
_page_sizes
[
1
]
=
default_page_size
;
_page_sizes
[
2
]
=
0
;
}
UseHugeTLBFS
=
UseHugeTLBFS
&&
Bsd
::
hugetlbfs_sanity_check
(
warn_on_failure
,
_large_page_size
);
if
(
UseHugeTLBFS
)
UseSHM
=
false
;
UseLargePages
=
UseHugeTLBFS
||
UseSHM
;
set_coredump_filter
();
#endif
}
}
#ifndef _ALLBSD_SOURCE
#ifndef SHM_HUGETLB
#define SHM_HUGETLB 04000
#endif
#endif
char
*
os
::
reserve_memory_special
(
size_t
bytes
,
char
*
req_addr
,
bool
exec
)
{
char
*
os
::
reserve_memory_special
(
size_t
bytes
,
char
*
req_addr
,
bool
exec
)
{
// "exec" is passed in but not used. Creating the shared image for
// "exec" is passed in but not used. Creating the shared image for
...
@@ -3267,11 +2235,7 @@ char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) {
...
@@ -3267,11 +2235,7 @@ char* os::reserve_memory_special(size_t bytes, char* req_addr, bool exec) {
// Create a large shared memory region to attach to based on size.
// Create a large shared memory region to attach to based on size.
// Currently, size is the total size of the heap
// Currently, size is the total size of the heap
#ifndef _ALLBSD_SOURCE
int
shmid
=
shmget
(
key
,
bytes
,
SHM_HUGETLB
|
IPC_CREAT
|
SHM_R
|
SHM_W
);
#else
int
shmid
=
shmget
(
key
,
bytes
,
IPC_CREAT
|
SHM_R
|
SHM_W
);
int
shmid
=
shmget
(
key
,
bytes
,
IPC_CREAT
|
SHM_R
|
SHM_W
);
#endif
if
(
shmid
==
-
1
)
{
if
(
shmid
==
-
1
)
{
// Possible reasons for shmget failure:
// Possible reasons for shmget failure:
// 1. shmmax is too small for Java heap.
// 1. shmmax is too small for Java heap.
...
@@ -3558,7 +2522,7 @@ void os::loop_breaker(int attempts) {
...
@@ -3558,7 +2522,7 @@ void os::loop_breaker(int attempts) {
// this reason, the code should not be used as default (ThreadPriorityPolicy=0).
// this reason, the code should not be used as default (ThreadPriorityPolicy=0).
// It is only used when ThreadPriorityPolicy=1 and requires root privilege.
// It is only used when ThreadPriorityPolicy=1 and requires root privilege.
#if
defined(_ALLBSD_SOURCE) &&
!defined(__APPLE__)
#if !defined(__APPLE__)
int
os
::
java_to_os_priority
[
CriticalPriority
+
1
]
=
{
int
os
::
java_to_os_priority
[
CriticalPriority
+
1
]
=
{
19
,
// 0 Entry should never be used
19
,
// 0 Entry should never be used
...
@@ -3578,7 +2542,7 @@ int os::java_to_os_priority[CriticalPriority + 1] = {
...
@@ -3578,7 +2542,7 @@ int os::java_to_os_priority[CriticalPriority + 1] = {
31
// 11 CriticalPriority
31
// 11 CriticalPriority
};
};
#el
if defined(__APPLE__)
#el
se
/* Using Mach high-level priority assignments */
/* Using Mach high-level priority assignments */
int
os
::
java_to_os_priority
[
CriticalPriority
+
1
]
=
{
int
os
::
java_to_os_priority
[
CriticalPriority
+
1
]
=
{
0
,
// 0 Entry should never be used (MINPRI_USER)
0
,
// 0 Entry should never be used (MINPRI_USER)
...
@@ -3599,26 +2563,6 @@ int os::java_to_os_priority[CriticalPriority + 1] = {
...
@@ -3599,26 +2563,6 @@ int os::java_to_os_priority[CriticalPriority + 1] = {
36
// 11 CriticalPriority
36
// 11 CriticalPriority
};
};
#else
int
os
::
java_to_os_priority
[
CriticalPriority
+
1
]
=
{
19
,
// 0 Entry should never be used
4
,
// 1 MinPriority
3
,
// 2
2
,
// 3
1
,
// 4
0
,
// 5 NormPriority
-
1
,
// 6
-
2
,
// 7
-
3
,
// 8
-
4
,
// 9 NearMaxPriority
-
5
,
// 10 MaxPriority
-
5
// 11 CriticalPriority
};
#endif
#endif
static
int
prio_init
()
{
static
int
prio_init
()
{
...
@@ -4179,22 +3123,6 @@ void os::Bsd::install_signal_handlers() {
...
@@ -4179,22 +3123,6 @@ void os::Bsd::install_signal_handlers() {
}
}
}
}
#ifndef _ALLBSD_SOURCE
// This is the fastest way to get thread cpu time on Bsd.
// Returns cpu time (user+sys) for any thread, not only for current.
// POSIX compliant clocks are implemented in the kernels 2.6.16+.
// It might work on 2.6.10+ with a special kernel/glibc patch.
// For reference, please, see IEEE Std 1003.1-2004:
// http://www.unix.org/single_unix_specification
jlong
os
::
Bsd
::
fast_thread_cpu_time
(
clockid_t
clockid
)
{
struct
timespec
tp
;
int
rc
=
os
::
Bsd
::
clock_gettime
(
clockid
,
&
tp
);
assert
(
rc
==
0
,
"clock_gettime is expected to return 0 code"
);
return
(
tp
.
tv_sec
*
NANOSECS_PER_SEC
)
+
tp
.
tv_nsec
;
}
#endif
/////
/////
// glibc on Bsd platform uses non-documented flag
// glibc on Bsd platform uses non-documented flag
...
@@ -4458,10 +3386,6 @@ extern "C" {
...
@@ -4458,10 +3386,6 @@ extern "C" {
// this is called _after_ the global arguments have been parsed
// this is called _after_ the global arguments have been parsed
jint
os
::
init_2
(
void
)
jint
os
::
init_2
(
void
)
{
{
#ifndef _ALLBSD_SOURCE
Bsd
::
fast_thread_clock_init
();
#endif
// Allocate a single page and mark it as readable for safepoint polling
// Allocate a single page and mark it as readable for safepoint polling
address
polling_page
=
(
address
)
::
mmap
(
NULL
,
Bsd
::
page_size
(),
PROT_READ
,
MAP_PRIVATE
|
MAP_ANONYMOUS
,
-
1
,
0
);
address
polling_page
=
(
address
)
::
mmap
(
NULL
,
Bsd
::
page_size
(),
PROT_READ
,
MAP_PRIVATE
|
MAP_ANONYMOUS
,
-
1
,
0
);
guarantee
(
polling_page
!=
MAP_FAILED
,
"os::init_2: failed to allocate polling page"
);
guarantee
(
polling_page
!=
MAP_FAILED
,
"os::init_2: failed to allocate polling page"
);
...
@@ -4518,48 +3442,6 @@ jint os::init_2(void)
...
@@ -4518,48 +3442,6 @@ jint os::init_2(void)
JavaThread
::
set_stack_size_at_create
(
round_to
(
threadStackSizeInBytes
,
JavaThread
::
set_stack_size_at_create
(
round_to
(
threadStackSizeInBytes
,
vm_page_size
()));
vm_page_size
()));
#ifndef _ALLBSD_SOURCE
Bsd
::
capture_initial_stack
(
JavaThread
::
stack_size_at_create
());
Bsd
::
libpthread_init
();
if
(
PrintMiscellaneous
&&
(
Verbose
||
WizardMode
))
{
tty
->
print_cr
(
"[HotSpot is running with %s, %s(%s)]
\n
"
,
Bsd
::
glibc_version
(),
Bsd
::
libpthread_version
(),
Bsd
::
is_floating_stack
()
?
"floating stack"
:
"fixed stack"
);
}
if
(
UseNUMA
)
{
if
(
!
Bsd
::
libnuma_init
())
{
UseNUMA
=
false
;
}
else
{
if
((
Bsd
::
numa_max_node
()
<
1
))
{
// There's only one node(they start from 0), disable NUMA.
UseNUMA
=
false
;
}
}
// With SHM large pages we cannot uncommit a page, so there's not way
// we can make the adaptive lgrp chunk resizing work. If the user specified
// both UseNUMA and UseLargePages (or UseSHM) on the command line - warn and
// disable adaptive resizing.
if
(
UseNUMA
&&
UseLargePages
&&
UseSHM
)
{
if
(
!
FLAG_IS_DEFAULT
(
UseNUMA
))
{
if
(
FLAG_IS_DEFAULT
(
UseLargePages
)
&&
FLAG_IS_DEFAULT
(
UseSHM
))
{
UseLargePages
=
false
;
}
else
{
warning
(
"UseNUMA is not fully compatible with SHM large pages, disabling adaptive resizing"
);
UseAdaptiveSizePolicy
=
false
;
UseAdaptiveNUMAChunkSizing
=
false
;
}
}
else
{
UseNUMA
=
false
;
}
}
if
(
!
UseNUMA
&&
ForceNUMA
)
{
UseNUMA
=
true
;
}
}
#endif
if
(
MaxFDLimit
)
{
if
(
MaxFDLimit
)
{
// set the number of file descriptors to max. print out error
// set the number of file descriptors to max. print out error
// if getrlimit/setrlimit fails but continue regardless.
// if getrlimit/setrlimit fails but continue regardless.
...
@@ -4586,11 +3468,6 @@ jint os::init_2(void)
...
@@ -4586,11 +3468,6 @@ jint os::init_2(void)
}
}
}
}
#ifndef _ALLBSD_SOURCE
// Initialize lock used to serialize thread creation (see os::create_thread)
Bsd
::
set_createThread_lock
(
new
Mutex
(
Mutex
::
leaf
,
"createThread_lock"
,
false
));
#endif
// at-exit methods are called in the reverse order of their registration.
// at-exit methods are called in the reverse order of their registration.
// atexit functions are called on return from main or as a result of a
// atexit functions are called on return from main or as a result of a
// call to exit(3C). There can be only 32 of these functions registered
// call to exit(3C). There can be only 32 of these functions registered
...
@@ -4641,15 +3518,7 @@ void os::make_polling_page_readable(void) {
...
@@ -4641,15 +3518,7 @@ void os::make_polling_page_readable(void) {
};
};
int
os
::
active_processor_count
()
{
int
os
::
active_processor_count
()
{
#ifdef _ALLBSD_SOURCE
return
_processor_count
;
return
_processor_count
;
#else
// Bsd doesn't yet have a (official) notion of processor sets,
// so just return the number of online processors.
int
online_cpus
=
::
sysconf
(
_SC_NPROCESSORS_ONLN
);
assert
(
online_cpus
>
0
&&
online_cpus
<=
processor_count
(),
"sanity check"
);
return
online_cpus
;
#endif
}
}
void
os
::
set_native_thread_name
(
const
char
*
name
)
{
void
os
::
set_native_thread_name
(
const
char
*
name
)
{
...
@@ -4703,25 +3572,7 @@ ExtendedPC os::get_thread_pc(Thread* thread) {
...
@@ -4703,25 +3572,7 @@ ExtendedPC os::get_thread_pc(Thread* thread) {
int
os
::
Bsd
::
safe_cond_timedwait
(
pthread_cond_t
*
_cond
,
pthread_mutex_t
*
_mutex
,
const
struct
timespec
*
_abstime
)
int
os
::
Bsd
::
safe_cond_timedwait
(
pthread_cond_t
*
_cond
,
pthread_mutex_t
*
_mutex
,
const
struct
timespec
*
_abstime
)
{
{
#ifdef _ALLBSD_SOURCE
return
pthread_cond_timedwait
(
_cond
,
_mutex
,
_abstime
);
return
pthread_cond_timedwait
(
_cond
,
_mutex
,
_abstime
);
#else
if
(
is_NPTL
())
{
return
pthread_cond_timedwait
(
_cond
,
_mutex
,
_abstime
);
}
else
{
#ifndef IA64
// 6292965: BsdThreads pthread_cond_timedwait() resets FPU control
// word back to default 64bit precision if condvar is signaled. Java
// wants 53bit precision. Save and restore current value.
int
fpu
=
get_fpu_control_word
();
#endif // IA64
int
status
=
pthread_cond_timedwait
(
_cond
,
_mutex
,
_abstime
);
#ifndef IA64
set_fpu_control_word
(
fpu
);
#endif // IA64
return
status
;
}
#endif
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
...
@@ -5041,20 +3892,6 @@ bool os::pd_unmap_memory(char* addr, size_t bytes) {
...
@@ -5041,20 +3892,6 @@ bool os::pd_unmap_memory(char* addr, size_t bytes) {
return
munmap
(
addr
,
bytes
)
==
0
;
return
munmap
(
addr
,
bytes
)
==
0
;
}
}
#ifndef _ALLBSD_SOURCE
static
jlong
slow_thread_cpu_time
(
Thread
*
thread
,
bool
user_sys_cpu_time
);
static
clockid_t
thread_cpu_clockid
(
Thread
*
thread
)
{
pthread_t
tid
=
thread
->
osthread
()
->
pthread_id
();
clockid_t
clockid
;
// Get thread clockid
int
rc
=
os
::
Bsd
::
pthread_getcpuclockid
(
tid
,
&
clockid
);
assert
(
rc
==
0
,
"pthread_getcpuclockid is expected to return 0 code"
);
return
clockid
;
}
#endif
// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
// current_thread_cpu_time(bool) and thread_cpu_time(Thread*, bool)
// are used by JVM M&M and JVMTI to get user+sys or user CPU time
// are used by JVM M&M and JVMTI to get user+sys or user CPU time
// of a thread.
// of a thread.
...
@@ -5065,36 +3902,15 @@ static clockid_t thread_cpu_clockid(Thread* thread) {
...
@@ -5065,36 +3902,15 @@ static clockid_t thread_cpu_clockid(Thread* thread) {
jlong
os
::
current_thread_cpu_time
()
{
jlong
os
::
current_thread_cpu_time
()
{
#ifdef __APPLE__
#ifdef __APPLE__
return
os
::
thread_cpu_time
(
Thread
::
current
(),
true
/* user + sys */
);
return
os
::
thread_cpu_time
(
Thread
::
current
(),
true
/* user + sys */
);
#elif !defined(_ALLBSD_SOURCE)
if
(
os
::
Bsd
::
supports_fast_thread_cpu_time
())
{
return
os
::
Bsd
::
fast_thread_cpu_time
(
CLOCK_THREAD_CPUTIME_ID
);
}
else
{
// return user + sys since the cost is the same
return
slow_thread_cpu_time
(
Thread
::
current
(),
true
/* user + sys */
);
}
#endif
#endif
}
}
jlong
os
::
thread_cpu_time
(
Thread
*
thread
)
{
jlong
os
::
thread_cpu_time
(
Thread
*
thread
)
{
#ifndef _ALLBSD_SOURCE
// consistent with what current_thread_cpu_time() returns
if
(
os
::
Bsd
::
supports_fast_thread_cpu_time
())
{
return
os
::
Bsd
::
fast_thread_cpu_time
(
thread_cpu_clockid
(
thread
));
}
else
{
return
slow_thread_cpu_time
(
thread
,
true
/* user + sys */
);
}
#endif
}
}
jlong
os
::
current_thread_cpu_time
(
bool
user_sys_cpu_time
)
{
jlong
os
::
current_thread_cpu_time
(
bool
user_sys_cpu_time
)
{
#ifdef __APPLE__
#ifdef __APPLE__
return
os
::
thread_cpu_time
(
Thread
::
current
(),
user_sys_cpu_time
);
return
os
::
thread_cpu_time
(
Thread
::
current
(),
user_sys_cpu_time
);
#elif !defined(_ALLBSD_SOURCE)
if
(
user_sys_cpu_time
&&
os
::
Bsd
::
supports_fast_thread_cpu_time
())
{
return
os
::
Bsd
::
fast_thread_cpu_time
(
CLOCK_THREAD_CPUTIME_ID
);
}
else
{
return
slow_thread_cpu_time
(
Thread
::
current
(),
user_sys_cpu_time
);
}
#endif
#endif
}
}
...
@@ -5118,106 +3934,9 @@ jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
...
@@ -5118,106 +3934,9 @@ jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
}
else
{
}
else
{
return
((
jlong
)
tinfo
.
user_time
.
seconds
*
1000000000
)
+
((
jlong
)
tinfo
.
user_time
.
microseconds
*
(
jlong
)
1000
);
return
((
jlong
)
tinfo
.
user_time
.
seconds
*
1000000000
)
+
((
jlong
)
tinfo
.
user_time
.
microseconds
*
(
jlong
)
1000
);
}
}
#elif !defined(_ALLBSD_SOURCE)
if
(
user_sys_cpu_time
&&
os
::
Bsd
::
supports_fast_thread_cpu_time
())
{
return
os
::
Bsd
::
fast_thread_cpu_time
(
thread_cpu_clockid
(
thread
));
}
else
{
return
slow_thread_cpu_time
(
thread
,
user_sys_cpu_time
);
}
#endif
#endif
}
}
#ifndef _ALLBSD_SOURCE
//
// -1 on error.
//
static
jlong
slow_thread_cpu_time
(
Thread
*
thread
,
bool
user_sys_cpu_time
)
{
static
bool
proc_pid_cpu_avail
=
true
;
static
bool
proc_task_unchecked
=
true
;
static
const
char
*
proc_stat_path
=
"/proc/%d/stat"
;
pid_t
tid
=
thread
->
osthread
()
->
thread_id
();
int
i
;
char
*
s
;
char
stat
[
2048
];
int
statlen
;
char
proc_name
[
64
];
int
count
;
long
sys_time
,
user_time
;
char
string
[
64
];
char
cdummy
;
int
idummy
;
long
ldummy
;
FILE
*
fp
;
// We first try accessing /proc/<pid>/cpu since this is faster to
// process. If this file is not present (bsd kernels 2.5 and above)
// then we open /proc/<pid>/stat.
if
(
proc_pid_cpu_avail
)
{
sprintf
(
proc_name
,
"/proc/%d/cpu"
,
tid
);
fp
=
fopen
(
proc_name
,
"r"
);
if
(
fp
!=
NULL
)
{
count
=
fscanf
(
fp
,
"%s %lu %lu
\n
"
,
string
,
&
user_time
,
&
sys_time
);
fclose
(
fp
);
if
(
count
!=
3
)
return
-
1
;
if
(
user_sys_cpu_time
)
{
return
((
jlong
)
sys_time
+
(
jlong
)
user_time
)
*
(
1000000000
/
clock_tics_per_sec
);
}
else
{
return
(
jlong
)
user_time
*
(
1000000000
/
clock_tics_per_sec
);
}
}
else
proc_pid_cpu_avail
=
false
;
}
// The /proc/<tid>/stat aggregates per-process usage on
// new Bsd kernels 2.6+ where NPTL is supported.
// The /proc/self/task/<tid>/stat still has the per-thread usage.
// See bug 6328462.
// There can be no directory /proc/self/task on kernels 2.4 with NPTL
// and possibly in some other cases, so we check its availability.
if
(
proc_task_unchecked
&&
os
::
Bsd
::
is_NPTL
())
{
// This is executed only once
proc_task_unchecked
=
false
;
fp
=
fopen
(
"/proc/self/task"
,
"r"
);
if
(
fp
!=
NULL
)
{
proc_stat_path
=
"/proc/self/task/%d/stat"
;
fclose
(
fp
);
}
}
sprintf
(
proc_name
,
proc_stat_path
,
tid
);
fp
=
fopen
(
proc_name
,
"r"
);
if
(
fp
==
NULL
)
return
-
1
;
statlen
=
fread
(
stat
,
1
,
2047
,
fp
);
stat
[
statlen
]
=
'\0'
;
fclose
(
fp
);
// Skip pid and the command string. Note that we could be dealing with
// weird command names, e.g. user could decide to rename java launcher
// to "java 1.4.2 :)", then the stat file would look like
// 1234 (java 1.4.2 :)) R ... ...
// We don't really need to know the command string, just find the last
// occurrence of ")" and then start parsing from there. See bug 4726580.
s
=
strrchr
(
stat
,
')'
);
i
=
0
;
if
(
s
==
NULL
)
return
-
1
;
// Skip blank chars
do
s
++
;
while
(
isspace
(
*
s
));
count
=
sscanf
(
s
,
"%c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu"
,
&
cdummy
,
&
idummy
,
&
idummy
,
&
idummy
,
&
idummy
,
&
idummy
,
&
ldummy
,
&
ldummy
,
&
ldummy
,
&
ldummy
,
&
ldummy
,
&
user_time
,
&
sys_time
);
if
(
count
!=
13
)
return
-
1
;
if
(
user_sys_cpu_time
)
{
return
((
jlong
)
sys_time
+
(
jlong
)
user_time
)
*
(
1000000000
/
clock_tics_per_sec
);
}
else
{
return
(
jlong
)
user_time
*
(
1000000000
/
clock_tics_per_sec
);
}
}
#endif
void
os
::
current_thread_cpu_time_info
(
jvmtiTimerInfo
*
info_ptr
)
{
void
os
::
current_thread_cpu_time_info
(
jvmtiTimerInfo
*
info_ptr
)
{
info_ptr
->
max_value
=
ALL_64_BITS
;
// will not wrap in less than 64 bits
info_ptr
->
max_value
=
ALL_64_BITS
;
// will not wrap in less than 64 bits
...
@@ -5236,10 +3955,8 @@ void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
...
@@ -5236,10 +3955,8 @@ void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) {
bool
os
::
is_thread_cpu_time_supported
()
{
bool
os
::
is_thread_cpu_time_supported
()
{
#ifdef __APPLE__
#ifdef __APPLE__
return
true
;
return
true
;
#elif defined(_ALLBSD_SOURCE)
return
false
;
#else
#else
return
tru
e
;
return
fals
e
;
#endif
#endif
}
}
...
...
src/os/bsd/vm/os_bsd.hpp
浏览文件 @
34551e5c
...
@@ -56,19 +56,6 @@ class Bsd {
...
@@ -56,19 +56,6 @@ class Bsd {
static
int
sigflags
[
MAXSIGNUM
];
static
int
sigflags
[
MAXSIGNUM
];
static
int
(
*
_clock_gettime
)(
clockid_t
,
struct
timespec
*
);
static
int
(
*
_clock_gettime
)(
clockid_t
,
struct
timespec
*
);
#ifndef _ALLBSD_SOURCE
static
int
(
*
_pthread_getcpuclockid
)(
pthread_t
,
clockid_t
*
);
static
address
_initial_thread_stack_bottom
;
static
uintptr_t
_initial_thread_stack_size
;
static
const
char
*
_glibc_version
;
static
const
char
*
_libpthread_version
;
static
bool
_is_floating_stack
;
static
bool
_is_NPTL
;
static
bool
_supports_fast_thread_cpu_time
;
#endif
static
GrowableArray
<
int
>*
_cpu_to_node
;
static
GrowableArray
<
int
>*
_cpu_to_node
;
...
@@ -76,28 +63,14 @@ class Bsd {
...
@@ -76,28 +63,14 @@ class Bsd {
static
julong
_physical_memory
;
static
julong
_physical_memory
;
static
pthread_t
_main_thread
;
static
pthread_t
_main_thread
;
#ifndef _ALLBSD_SOURCE
static
Mutex
*
_createThread_lock
;
#endif
static
int
_page_size
;
static
int
_page_size
;
static
julong
available_memory
();
static
julong
available_memory
();
static
julong
physical_memory
()
{
return
_physical_memory
;
}
static
julong
physical_memory
()
{
return
_physical_memory
;
}
static
void
initialize_system_info
();
static
void
initialize_system_info
();
#ifndef _ALLBSD_SOURCE
static
void
set_glibc_version
(
const
char
*
s
)
{
_glibc_version
=
s
;
}
static
void
set_libpthread_version
(
const
char
*
s
)
{
_libpthread_version
=
s
;
}
#endif
static
bool
supports_variable_stack_size
();
static
bool
supports_variable_stack_size
();
#ifndef _ALLBSD_SOURCE
static
void
set_is_NPTL
()
{
_is_NPTL
=
true
;
}
static
void
set_is_BsdThreads
()
{
_is_NPTL
=
false
;
}
static
void
set_is_floating_stack
()
{
_is_floating_stack
=
true
;
}
#endif
static
void
rebuild_cpu_to_node_map
();
static
void
rebuild_cpu_to_node_map
();
static
GrowableArray
<
int
>*
cpu_to_node
()
{
return
_cpu_to_node
;
}
static
GrowableArray
<
int
>*
cpu_to_node
()
{
return
_cpu_to_node
;
}
...
@@ -106,25 +79,10 @@ class Bsd {
...
@@ -106,25 +79,10 @@ class Bsd {
public:
public:
static
void
init_thread_fpu_state
();
static
void
init_thread_fpu_state
();
#ifndef _ALLBSD_SOURCE
static
int
get_fpu_control_word
();
static
void
set_fpu_control_word
(
int
fpu_control
);
#endif
static
pthread_t
main_thread
(
void
)
{
return
_main_thread
;
}
static
pthread_t
main_thread
(
void
)
{
return
_main_thread
;
}
#ifndef _ALLBSD_SOURCE
// returns kernel thread id (similar to LWP id on Solaris), which can be
// used to access /proc
static
pid_t
gettid
();
static
void
set_createThread_lock
(
Mutex
*
lk
)
{
_createThread_lock
=
lk
;
}
static
Mutex
*
createThread_lock
(
void
)
{
return
_createThread_lock
;
}
#endif
static
void
hotspot_sigmask
(
Thread
*
thread
);
static
void
hotspot_sigmask
(
Thread
*
thread
);
#ifndef _ALLBSD_SOURCE
static
address
initial_thread_stack_bottom
(
void
)
{
return
_initial_thread_stack_bottom
;
}
static
uintptr_t
initial_thread_stack_size
(
void
)
{
return
_initial_thread_stack_size
;
}
#endif
static
bool
is_initial_thread
(
void
);
static
bool
is_initial_thread
(
void
);
static
int
page_size
(
void
)
{
return
_page_size
;
}
static
int
page_size
(
void
)
{
return
_page_size
;
}
...
@@ -161,23 +119,6 @@ class Bsd {
...
@@ -161,23 +119,6 @@ class Bsd {
static
struct
sigaction
*
get_chained_signal_action
(
int
sig
);
static
struct
sigaction
*
get_chained_signal_action
(
int
sig
);
static
bool
chained_handler
(
int
sig
,
siginfo_t
*
siginfo
,
void
*
context
);
static
bool
chained_handler
(
int
sig
,
siginfo_t
*
siginfo
,
void
*
context
);
#ifndef _ALLBSD_SOURCE
// GNU libc and libpthread version strings
static
const
char
*
glibc_version
()
{
return
_glibc_version
;
}
static
const
char
*
libpthread_version
()
{
return
_libpthread_version
;
}
// NPTL or BsdThreads?
static
bool
is_BsdThreads
()
{
return
!
_is_NPTL
;
}
static
bool
is_NPTL
()
{
return
_is_NPTL
;
}
// NPTL is always floating stack. BsdThreads could be using floating
// stack or fixed stack.
static
bool
is_floating_stack
()
{
return
_is_floating_stack
;
}
static
void
libpthread_init
();
static
bool
libnuma_init
();
static
void
*
libnuma_dlsym
(
void
*
handle
,
const
char
*
name
);
#endif
// Minimum stack size a thread can be created with (allowing
// Minimum stack size a thread can be created with (allowing
// the VM to completely create the thread and enter user code)
// the VM to completely create the thread and enter user code)
static
size_t
min_stack_allowed
;
static
size_t
min_stack_allowed
;
...
@@ -186,22 +127,9 @@ class Bsd {
...
@@ -186,22 +127,9 @@ class Bsd {
static
size_t
default_stack_size
(
os
::
ThreadType
thr_type
);
static
size_t
default_stack_size
(
os
::
ThreadType
thr_type
);
static
size_t
default_guard_size
(
os
::
ThreadType
thr_type
);
static
size_t
default_guard_size
(
os
::
ThreadType
thr_type
);
#ifndef _ALLBSD_SOURCE
static
void
capture_initial_stack
(
size_t
max_size
);
// Stack overflow handling
static
bool
manually_expand_stack
(
JavaThread
*
t
,
address
addr
);
static
int
max_register_window_saves_before_flushing
();
#endif
// Real-time clock functions
// Real-time clock functions
static
void
clock_init
(
void
);
static
void
clock_init
(
void
);
#ifndef _ALLBSD_SOURCE
// fast POSIX clocks support
static
void
fast_thread_clock_init
(
void
);
#endif
static
inline
bool
supports_monotonic_clock
()
{
static
inline
bool
supports_monotonic_clock
()
{
return
_clock_gettime
!=
NULL
;
return
_clock_gettime
!=
NULL
;
}
}
...
@@ -210,18 +138,6 @@ class Bsd {
...
@@ -210,18 +138,6 @@ class Bsd {
return
_clock_gettime
?
_clock_gettime
(
clock_id
,
tp
)
:
-
1
;
return
_clock_gettime
?
_clock_gettime
(
clock_id
,
tp
)
:
-
1
;
}
}
#ifndef _ALLBSD_SOURCE
static
int
pthread_getcpuclockid
(
pthread_t
tid
,
clockid_t
*
clock_id
)
{
return
_pthread_getcpuclockid
?
_pthread_getcpuclockid
(
tid
,
clock_id
)
:
-
1
;
}
static
bool
supports_fast_thread_cpu_time
()
{
return
_supports_fast_thread_cpu_time
;
}
static
jlong
fast_thread_cpu_time
(
clockid_t
clockid
);
#endif
// Stack repair handling
// Stack repair handling
// none present
// none present
...
...
src/os/windows/vm/os_windows.cpp
浏览文件 @
34551e5c
...
@@ -22,7 +22,7 @@
...
@@ -22,7 +22,7 @@
*
*
*/
*/
// Must be at least Windows 2000 or XP to use
VectoredExceptions and
IsDebuggerPresent
// Must be at least Windows 2000 or XP to use IsDebuggerPresent
#define _WIN32_WINNT 0x500
#define _WIN32_WINNT 0x500
// no precompiled headers
// no precompiled headers
...
@@ -110,10 +110,6 @@ static FILETIME process_exit_time;
...
@@ -110,10 +110,6 @@ static FILETIME process_exit_time;
static
FILETIME
process_user_time
;
static
FILETIME
process_user_time
;
static
FILETIME
process_kernel_time
;
static
FILETIME
process_kernel_time
;
#ifdef _WIN64
PVOID
topLevelVectoredExceptionHandler
=
NULL
;
#endif
#ifdef _M_IA64
#ifdef _M_IA64
#define __CPU__ ia64
#define __CPU__ ia64
#elif _M_AMD64
#elif _M_AMD64
...
@@ -136,12 +132,6 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {
...
@@ -136,12 +132,6 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {
case
DLL_PROCESS_DETACH
:
case
DLL_PROCESS_DETACH
:
if
(
ForceTimeHighResolution
)
if
(
ForceTimeHighResolution
)
timeEndPeriod
(
1L
);
timeEndPeriod
(
1L
);
#ifdef _WIN64
if
(
topLevelVectoredExceptionHandler
!=
NULL
)
{
RemoveVectoredExceptionHandler
(
topLevelVectoredExceptionHandler
);
topLevelVectoredExceptionHandler
=
NULL
;
}
#endif
break
;
break
;
default:
default:
break
;
break
;
...
@@ -408,11 +398,6 @@ static unsigned __stdcall java_start(Thread* thread) {
...
@@ -408,11 +398,6 @@ static unsigned __stdcall java_start(Thread* thread) {
}
}
if
(
UseVectoredExceptions
)
{
// If we are using vectored exception we don't need to set a SEH
thread
->
run
();
}
else
{
// Install a win32 structured exception handler around every thread created
// Install a win32 structured exception handler around every thread created
// by VM, so VM can genrate error dump when an exception occurred in non-
// by VM, so VM can genrate error dump when an exception occurred in non-
// Java thread (e.g. VM thread).
// Java thread (e.g. VM thread).
...
@@ -422,7 +407,6 @@ static unsigned __stdcall java_start(Thread* thread) {
...
@@ -422,7 +407,6 @@ static unsigned __stdcall java_start(Thread* thread) {
(
_EXCEPTION_POINTERS
*
)
_exception_info
()))
{
(
_EXCEPTION_POINTERS
*
)
_exception_info
()))
{
// Nothing to do.
// Nothing to do.
}
}
}
// One less thread is executing
// One less thread is executing
// When the VMThread gets here, the main thread may have already exited
// When the VMThread gets here, the main thread may have already exited
...
@@ -2489,16 +2473,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
...
@@ -2489,16 +2473,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
}
}
#endif
#endif
#ifdef _WIN64
// Windows will sometimes generate an access violation
// when we call malloc. Since we use VectoredExceptions
// on 64 bit platforms, we see this exception. We must
// pass this exception on so Windows can recover.
// We check to see if the pc of the fault is in NTDLL.DLL
// if so, we pass control on to Windows for handling.
if
(
UseVectoredExceptions
&&
_addr_in_ntdll
(
pc
))
return
EXCEPTION_CONTINUE_SEARCH
;
#endif
// Stack overflow or null pointer exception in native code.
// Stack overflow or null pointer exception in native code.
report_error
(
t
,
exception_code
,
pc
,
exceptionInfo
->
ExceptionRecord
,
report_error
(
t
,
exception_code
,
pc
,
exceptionInfo
->
ExceptionRecord
,
exceptionInfo
->
ContextRecord
);
exceptionInfo
->
ContextRecord
);
...
@@ -2527,30 +2501,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
...
@@ -2527,30 +2501,8 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
}
}
if
(
exception_code
!=
EXCEPTION_BREAKPOINT
)
{
if
(
exception_code
!=
EXCEPTION_BREAKPOINT
)
{
#ifndef _WIN64
report_error
(
t
,
exception_code
,
pc
,
exceptionInfo
->
ExceptionRecord
,
report_error
(
t
,
exception_code
,
pc
,
exceptionInfo
->
ExceptionRecord
,
exceptionInfo
->
ContextRecord
);
exceptionInfo
->
ContextRecord
);
#else
// Itanium Windows uses a VectoredExceptionHandler
// Which means that C++ programatic exception handlers (try/except)
// will get here. Continue the search for the right except block if
// the exception code is not a fatal code.
switch
(
exception_code
)
{
case
EXCEPTION_ACCESS_VIOLATION
:
case
EXCEPTION_STACK_OVERFLOW
:
case
EXCEPTION_ILLEGAL_INSTRUCTION
:
case
EXCEPTION_ILLEGAL_INSTRUCTION_2
:
case
EXCEPTION_INT_OVERFLOW
:
case
EXCEPTION_INT_DIVIDE_BY_ZERO
:
case
EXCEPTION_UNCAUGHT_CXX_EXCEPTION
:
{
report_error
(
t
,
exception_code
,
pc
,
exceptionInfo
->
ExceptionRecord
,
exceptionInfo
->
ContextRecord
);
}
break
;
default:
break
;
}
#endif
}
}
return
EXCEPTION_CONTINUE_SEARCH
;
return
EXCEPTION_CONTINUE_SEARCH
;
}
}
...
@@ -3706,18 +3658,6 @@ jint os::init_2(void) {
...
@@ -3706,18 +3658,6 @@ jint os::init_2(void) {
// Setup Windows Exceptions
// Setup Windows Exceptions
// On Itanium systems, Structured Exception Handling does not
// work since stack frames must be walkable by the OS. Since
// much of our code is dynamically generated, and we do not have
// proper unwind .xdata sections, the system simply exits
// rather than delivering the exception. To work around
// this we use VectorExceptions instead.
#ifdef _WIN64
if
(
UseVectoredExceptions
)
{
topLevelVectoredExceptionHandler
=
AddVectoredExceptionHandler
(
1
,
topLevelExceptionFilter
);
}
#endif
// for debugging float code generation bugs
// for debugging float code generation bugs
if
(
ForceFloatExceptions
)
{
if
(
ForceFloatExceptions
)
{
#ifndef _WIN64
#ifndef _WIN64
...
...
src/os_cpu/bsd_x86/vm/bytes_bsd_x86.inline.hpp
浏览文件 @
34551e5c
...
@@ -25,10 +25,6 @@
...
@@ -25,10 +25,6 @@
#ifndef OS_CPU_BSD_X86_VM_BYTES_BSD_X86_INLINE_HPP
#ifndef OS_CPU_BSD_X86_VM_BYTES_BSD_X86_INLINE_HPP
#define OS_CPU_BSD_X86_VM_BYTES_BSD_X86_INLINE_HPP
#define OS_CPU_BSD_X86_VM_BYTES_BSD_X86_INLINE_HPP
#ifndef _ALLBSD_SOURCE
#include <byteswap.h>
#endif
#ifdef __APPLE__
#ifdef __APPLE__
#include <libkern/OSByteOrder.h>
#include <libkern/OSByteOrder.h>
#endif
#endif
...
...
src/os_cpu/bsd_x86/vm/globals_bsd_x86.hpp
浏览文件 @
34551e5c
...
@@ -48,7 +48,5 @@ define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
...
@@ -48,7 +48,5 @@ define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
// Used on 64 bit platforms for UseCompressedOops base address or CDS
// Used on 64 bit platforms for UseCompressedOops base address or CDS
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
2
*
G
);
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
2
*
G
);
// Only used on 64 bit Windows platforms
define_pd_global
(
bool
,
UseVectoredExceptions
,
false
);
#endif // OS_CPU_BSD_X86_VM_GLOBALS_BSD_X86_HPP
#endif // OS_CPU_BSD_X86_VM_GLOBALS_BSD_X86_HPP
src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
浏览文件 @
34551e5c
...
@@ -76,7 +76,7 @@
...
@@ -76,7 +76,7 @@
# include <ucontext.h>
# include <ucontext.h>
#endif
#endif
#if
defined(_ALLBSD_SOURCE) &&
!defined(__APPLE__) && !defined(__NetBSD__)
#if !defined(__APPLE__) && !defined(__NetBSD__)
# include <pthread_np.h>
# include <pthread_np.h>
#endif
#endif
...
@@ -489,23 +489,6 @@ JVM_handle_bsd_signal(int sig,
...
@@ -489,23 +489,6 @@ JVM_handle_bsd_signal(int sig,
// to handle_unexpected_exception way down below.
// to handle_unexpected_exception way down below.
thread
->
disable_stack_red_zone
();
thread
->
disable_stack_red_zone
();
tty
->
print_raw_cr
(
"An irrecoverable stack overflow has occurred."
);
tty
->
print_raw_cr
(
"An irrecoverable stack overflow has occurred."
);
#ifndef _ALLBSD_SOURCE
}
else
{
// Accessing stack address below sp may cause SEGV if current
// thread has MAP_GROWSDOWN stack. This should only happen when
// current thread was created by user code with MAP_GROWSDOWN flag
// and then attached to VM. See notes in os_bsd.cpp.
if
(
thread
->
osthread
()
->
expanding_stack
()
==
0
)
{
thread
->
osthread
()
->
set_expanding_stack
();
if
(
os
::
Bsd
::
manually_expand_stack
(
thread
,
addr
))
{
thread
->
osthread
()
->
clear_expanding_stack
();
return
1
;
}
thread
->
osthread
()
->
clear_expanding_stack
();
}
else
{
fatal
(
"recursive segv. expanding stack."
);
}
#endif
}
}
}
}
}
}
...
@@ -744,61 +727,21 @@ JVM_handle_bsd_signal(int sig,
...
@@ -744,61 +727,21 @@ JVM_handle_bsd_signal(int sig,
ShouldNotReachHere
();
ShouldNotReachHere
();
}
}
#ifdef _ALLBSD_SOURCE
// From solaris_i486.s ported to bsd_i486.s
// From solaris_i486.s ported to bsd_i486.s
extern
"C"
void
fixcw
();
extern
"C"
void
fixcw
();
#endif
void
os
::
Bsd
::
init_thread_fpu_state
(
void
)
{
void
os
::
Bsd
::
init_thread_fpu_state
(
void
)
{
#ifndef AMD64
#ifndef AMD64
# ifdef _ALLBSD_SOURCE
// Set fpu to 53 bit precision. This happens too early to use a stub.
// Set fpu to 53 bit precision. This happens too early to use a stub.
fixcw
();
fixcw
();
# else
// set fpu to 53 bit precision
set_fpu_control_word
(
0x27f
);
# endif
#endif // !AMD64
#endif // !AMD64
}
}
#ifndef _ALLBSD_SOURCE
int
os
::
Bsd
::
get_fpu_control_word
(
void
)
{
#ifdef AMD64
return
0
;
#else
int
fpu_control
;
_FPU_GETCW
(
fpu_control
);
return
fpu_control
&
0xffff
;
#endif // AMD64
}
void
os
::
Bsd
::
set_fpu_control_word
(
int
fpu_control
)
{
#ifndef AMD64
_FPU_SETCW
(
fpu_control
);
#endif // !AMD64
}
#endif
// Check that the bsd kernel version is 2.4 or higher since earlier
// Check that the bsd kernel version is 2.4 or higher since earlier
// versions do not support SSE without patches.
// versions do not support SSE without patches.
bool
os
::
supports_sse
()
{
bool
os
::
supports_sse
()
{
#if defined(AMD64) || defined(_ALLBSD_SOURCE)
return
true
;
return
true
;
#else
struct
utsname
uts
;
if
(
uname
(
&
uts
)
!=
0
)
return
false
;
// uname fails?
char
*
minor_string
;
int
major
=
strtol
(
uts
.
release
,
&
minor_string
,
10
);
int
minor
=
strtol
(
minor_string
+
1
,
NULL
,
10
);
bool
result
=
(
major
>
2
||
(
major
==
2
&&
minor
>=
4
));
#ifndef PRODUCT
if
(
PrintMiscellaneous
&&
Verbose
)
{
tty
->
print
(
"OS version is %d.%d, which %s support SSE/SSE2
\n
"
,
major
,
minor
,
result
?
"DOES"
:
"does NOT"
);
}
#endif
return
result
;
#endif // AMD64
}
}
bool
os
::
is_allocatable
(
size_t
bytes
)
{
bool
os
::
is_allocatable
(
size_t
bytes
)
{
...
@@ -836,46 +779,7 @@ size_t os::Bsd::min_stack_allowed = (48 DEBUG_ONLY(+4))*K;
...
@@ -836,46 +779,7 @@ size_t os::Bsd::min_stack_allowed = (48 DEBUG_ONLY(+4))*K;
#define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;})
#define GET_GS() ({int gs; __asm__ volatile("movw %%gs, %w0":"=q"(gs)); gs&0xffff;})
#endif
#endif
#ifdef _ALLBSD_SOURCE
bool
os
::
Bsd
::
supports_variable_stack_size
()
{
return
true
;
}
bool
os
::
Bsd
::
supports_variable_stack_size
()
{
return
true
;
}
#else
// Test if pthread library can support variable thread stack size. BsdThreads
// in fixed stack mode allocates 2M fixed slot for each thread. BsdThreads
// in floating stack mode and NPTL support variable stack size.
bool
os
::
Bsd
::
supports_variable_stack_size
()
{
if
(
os
::
Bsd
::
is_NPTL
())
{
// NPTL, yes
return
true
;
}
else
{
// Note: We can't control default stack size when creating a thread.
// If we use non-default stack size (pthread_attr_setstacksize), both
// floating stack and non-floating stack BsdThreads will return the
// same value. This makes it impossible to implement this function by
// detecting thread stack size directly.
//
// An alternative approach is to check %gs. Fixed-stack BsdThreads
// do not use %gs, so its value is 0. Floating-stack BsdThreads use
// %gs (either as LDT selector or GDT selector, depending on kernel)
// to access thread specific data.
//
// Note that %gs is a reserved glibc register since early 2001, so
// applications are not allowed to change its value (Ulrich Drepper from
// Redhat confirmed that all known offenders have been modified to use
// either %fs or TSD). In the worst case scenario, when VM is embedded in
// a native application that plays with %gs, we might see non-zero %gs
// even BsdThreads is running in fixed stack mode. As the result, we'll
// return true and skip _thread_safety_check(), so we may not be able to
// detect stack-heap collisions. But otherwise it's harmless.
//
#ifdef __GNUC__
return
(
GET_GS
()
!=
0
);
#else
return
false
;
#endif
}
}
#endif
#endif // AMD64
#endif // AMD64
// return default stack size for thr_type
// return default stack size for thr_type
...
@@ -943,7 +847,7 @@ static void current_stack_region(address * bottom, size_t * size) {
...
@@ -943,7 +847,7 @@ static void current_stack_region(address * bottom, size_t * size) {
*
bottom
=
(
address
)((
char
*
)
ss
.
ss_sp
-
ss
.
ss_size
);
*
bottom
=
(
address
)((
char
*
)
ss
.
ss_sp
-
ss
.
ss_size
);
*
size
=
ss
.
ss_size
;
*
size
=
ss
.
ss_size
;
#el
if defined(_ALLBSD_SOURCE)
#el
se
pthread_attr_t
attr
;
pthread_attr_t
attr
;
int
rslt
=
pthread_attr_init
(
&
attr
);
int
rslt
=
pthread_attr_init
(
&
attr
);
...
@@ -963,33 +867,6 @@ static void current_stack_region(address * bottom, size_t * size) {
...
@@ -963,33 +867,6 @@ static void current_stack_region(address * bottom, size_t * size) {
}
}
pthread_attr_destroy
(
&
attr
);
pthread_attr_destroy
(
&
attr
);
#else
if
(
os
::
Bsd
::
is_initial_thread
())
{
// initial thread needs special handling because pthread_getattr_np()
// may return bogus value.
*
bottom
=
os
::
Bsd
::
initial_thread_stack_bottom
();
*
size
=
os
::
Bsd
::
initial_thread_stack_size
();
}
else
{
pthread_attr_t
attr
;
int
rslt
=
pthread_getattr_np
(
pthread_self
(),
&
attr
);
// JVM needs to know exact stack location, abort if it fails
if
(
rslt
!=
0
)
{
if
(
rslt
==
ENOMEM
)
{
vm_exit_out_of_memory
(
0
,
"pthread_getattr_np"
);
}
else
{
fatal
(
err_msg
(
"pthread_getattr_np failed with errno = %d"
,
rslt
));
}
}
if
(
pthread_attr_getstack
(
&
attr
,
(
void
**
)
bottom
,
size
)
!=
0
)
{
fatal
(
"Can not locate current stack attributes!"
);
}
pthread_attr_destroy
(
&
attr
);
}
#endif
#endif
assert
(
os
::
current_stack_pointer
()
>=
*
bottom
&&
assert
(
os
::
current_stack_pointer
()
>=
*
bottom
&&
os
::
current_stack_pointer
()
<
*
bottom
+
*
size
,
"just checking"
);
os
::
current_stack_pointer
()
<
*
bottom
+
*
size
,
"just checking"
);
...
...
src/os_cpu/bsd_zero/vm/globals_bsd_zero.hpp
浏览文件 @
34551e5c
...
@@ -41,7 +41,6 @@ define_pd_global(intx, VMThreadStackSize, 512);
...
@@ -41,7 +41,6 @@ define_pd_global(intx, VMThreadStackSize, 512);
define_pd_global
(
intx
,
CompilerThreadStackSize
,
0
);
define_pd_global
(
intx
,
CompilerThreadStackSize
,
0
);
define_pd_global
(
uintx
,
JVMInvokeMethodSlack
,
8192
);
define_pd_global
(
uintx
,
JVMInvokeMethodSlack
,
8192
);
define_pd_global
(
bool
,
UseVectoredExceptions
,
false
);
// Used on 64 bit platforms for UseCompressedOops base address or CDS
// Used on 64 bit platforms for UseCompressedOops base address or CDS
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
2
*
G
);
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
2
*
G
);
...
...
src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp
浏览文件 @
34551e5c
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
*
*
*/
*/
#if
defined(_ALLBSD_SOURCE) &&
!defined(__APPLE__) && !defined(__NetBSD__)
#if !defined(__APPLE__) && !defined(__NetBSD__)
#include <pthread.h>
#include <pthread.h>
# include <pthread_np.h>
/* For pthread_attr_get_np */
# include <pthread_np.h>
/* For pthread_attr_get_np */
#endif
#endif
...
@@ -178,26 +178,6 @@ JVM_handle_bsd_signal(int sig,
...
@@ -178,26 +178,6 @@ JVM_handle_bsd_signal(int sig,
thread
->
disable_stack_red_zone
();
thread
->
disable_stack_red_zone
();
ShouldNotCallThis
();
ShouldNotCallThis
();
}
}
#ifndef _ALLBSD_SOURCE
else
{
// Accessing stack address below sp may cause SEGV if
// current thread has MAP_GROWSDOWN stack. This should
// only happen when current thread was created by user
// code with MAP_GROWSDOWN flag and then attached to VM.
// See notes in os_bsd.cpp.
if
(
thread
->
osthread
()
->
expanding_stack
()
==
0
)
{
thread
->
osthread
()
->
set_expanding_stack
();
if
(
os
::
Bsd
::
manually_expand_stack
(
thread
,
addr
))
{
thread
->
osthread
()
->
clear_expanding_stack
();
return
true
;
}
thread
->
osthread
()
->
clear_expanding_stack
();
}
else
{
fatal
(
"recursive segv. expanding stack."
);
}
}
#endif
}
}
}
}
...
@@ -266,16 +246,6 @@ void os::Bsd::init_thread_fpu_state(void) {
...
@@ -266,16 +246,6 @@ void os::Bsd::init_thread_fpu_state(void) {
// Nothing to do
// Nothing to do
}
}
#ifndef _ALLBSD_SOURCE
int
os
::
Bsd
::
get_fpu_control_word
()
{
ShouldNotCallThis
();
}
void
os
::
Bsd
::
set_fpu_control_word
(
int
fpu
)
{
ShouldNotCallThis
();
}
#endif
bool
os
::
is_allocatable
(
size_t
bytes
)
{
bool
os
::
is_allocatable
(
size_t
bytes
)
{
#ifdef _LP64
#ifdef _LP64
return
true
;
return
true
;
...
@@ -339,7 +309,7 @@ static void current_stack_region(address *bottom, size_t *size) {
...
@@ -339,7 +309,7 @@ static void current_stack_region(address *bottom, size_t *size) {
stack_top
=
(
address
)
ss
.
ss_sp
;
stack_top
=
(
address
)
ss
.
ss_sp
;
stack_bytes
=
ss
.
ss_size
;
stack_bytes
=
ss
.
ss_size
;
stack_bottom
=
stack_top
-
stack_bytes
;
stack_bottom
=
stack_top
-
stack_bytes
;
#el
if defined(_ALLBSD_SOURCE)
#el
se
pthread_attr_t
attr
;
pthread_attr_t
attr
;
int
rslt
=
pthread_attr_init
(
&
attr
);
int
rslt
=
pthread_attr_init
(
&
attr
);
...
@@ -362,67 +332,6 @@ static void current_stack_region(address *bottom, size_t *size) {
...
@@ -362,67 +332,6 @@ static void current_stack_region(address *bottom, size_t *size) {
pthread_attr_destroy
(
&
attr
);
pthread_attr_destroy
(
&
attr
);
stack_top
=
stack_bottom
+
stack_bytes
;
stack_top
=
stack_bottom
+
stack_bytes
;
#else
/* Linux */
pthread_attr_t
attr
;
int
res
=
pthread_getattr_np
(
pthread_self
(),
&
attr
);
if
(
res
!=
0
)
{
if
(
res
==
ENOMEM
)
{
vm_exit_out_of_memory
(
0
,
"pthread_getattr_np"
);
}
else
{
fatal
(
err_msg
(
"pthread_getattr_np failed with errno = "
INT32_FORMAT
,
res
));
}
}
res
=
pthread_attr_getstack
(
&
attr
,
(
void
**
)
&
stack_bottom
,
&
stack_bytes
);
if
(
res
!=
0
)
{
fatal
(
err_msg
(
"pthread_attr_getstack failed with errno = "
INT32_FORMAT
,
res
));
}
stack_top
=
stack_bottom
+
stack_bytes
;
// The block of memory returned by pthread_attr_getstack() includes
// guard pages where present. We need to trim these off.
size_t
page_bytes
=
os
::
Bsd
::
page_size
();
assert
(((
intptr_t
)
stack_bottom
&
(
page_bytes
-
1
))
==
0
,
"unaligned stack"
);
size_t
guard_bytes
;
res
=
pthread_attr_getguardsize
(
&
attr
,
&
guard_bytes
);
if
(
res
!=
0
)
{
fatal
(
err_msg
(
"pthread_attr_getguardsize failed with errno = "
INT32_FORMAT
,
res
));
}
int
guard_pages
=
align_size_up
(
guard_bytes
,
page_bytes
)
/
page_bytes
;
assert
(
guard_bytes
==
guard_pages
*
page_bytes
,
"unaligned guard"
);
#ifdef IA64
// IA64 has two stacks sharing the same area of memory, a normal
// stack growing downwards and a register stack growing upwards.
// Guard pages, if present, are in the centre. This code splits
// the stack in two even without guard pages, though in theory
// there's nothing to stop us allocating more to the normal stack
// or more to the register stack if one or the other were found
// to grow faster.
int
total_pages
=
align_size_down
(
stack_bytes
,
page_bytes
)
/
page_bytes
;
stack_bottom
+=
(
total_pages
-
guard_pages
)
/
2
*
page_bytes
;
#endif // IA64
stack_bottom
+=
guard_bytes
;
pthread_attr_destroy
(
&
attr
);
// The initial thread has a growable stack, and the size reported
// by pthread_attr_getstack is the maximum size it could possibly
// be given what currently mapped. This can be huge, so we cap it.
if
(
os
::
Bsd
::
is_initial_thread
())
{
stack_bytes
=
stack_top
-
stack_bottom
;
if
(
stack_bytes
>
JavaThread
::
stack_size_at_create
())
stack_bytes
=
JavaThread
::
stack_size_at_create
();
stack_bottom
=
stack_top
-
stack_bytes
;
}
#endif
#endif
assert
(
os
::
current_stack_pointer
()
>=
stack_bottom
,
"should do"
);
assert
(
os
::
current_stack_pointer
()
>=
stack_bottom
,
"should do"
);
...
...
src/os_cpu/linux_sparc/vm/globals_linux_sparc.hpp
浏览文件 @
34551e5c
...
@@ -35,7 +35,5 @@ define_pd_global(intx, CompilerThreadStackSize, 0);
...
@@ -35,7 +35,5 @@ define_pd_global(intx, CompilerThreadStackSize, 0);
// Used on 64 bit platforms for UseCompressedOops base address or CDS
// Used on 64 bit platforms for UseCompressedOops base address or CDS
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
CONST64
(
4
)
*
G
);
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
CONST64
(
4
)
*
G
);
// Only used on 64 bit Windows platforms
define_pd_global
(
bool
,
UseVectoredExceptions
,
false
);
#endif // OS_CPU_LINUX_SPARC_VM_GLOBALS_LINUX_SPARC_HPP
#endif // OS_CPU_LINUX_SPARC_VM_GLOBALS_LINUX_SPARC_HPP
src/os_cpu/linux_x86/vm/globals_linux_x86.hpp
浏览文件 @
34551e5c
...
@@ -46,7 +46,5 @@ define_pd_global(uintx,JVMInvokeMethodSlack, 8192);
...
@@ -46,7 +46,5 @@ define_pd_global(uintx,JVMInvokeMethodSlack, 8192);
// Used on 64 bit platforms for UseCompressedOops base address or CDS
// Used on 64 bit platforms for UseCompressedOops base address or CDS
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
2
*
G
);
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
2
*
G
);
// Only used on 64 bit Windows platforms
define_pd_global
(
bool
,
UseVectoredExceptions
,
false
);
#endif // OS_CPU_LINUX_X86_VM_GLOBALS_LINUX_X86_HPP
#endif // OS_CPU_LINUX_X86_VM_GLOBALS_LINUX_X86_HPP
src/os_cpu/linux_zero/vm/globals_linux_zero.hpp
浏览文件 @
34551e5c
...
@@ -41,7 +41,6 @@ define_pd_global(intx, VMThreadStackSize, 512);
...
@@ -41,7 +41,6 @@ define_pd_global(intx, VMThreadStackSize, 512);
define_pd_global
(
intx
,
CompilerThreadStackSize
,
0
);
define_pd_global
(
intx
,
CompilerThreadStackSize
,
0
);
define_pd_global
(
uintx
,
JVMInvokeMethodSlack
,
8192
);
define_pd_global
(
uintx
,
JVMInvokeMethodSlack
,
8192
);
define_pd_global
(
bool
,
UseVectoredExceptions
,
false
);
// Used on 64 bit platforms for UseCompressedOops base address or CDS
// Used on 64 bit platforms for UseCompressedOops base address or CDS
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
2
*
G
);
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
2
*
G
);
...
...
src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp
浏览文件 @
34551e5c
...
@@ -39,8 +39,6 @@ define_pd_global(uintx, HeapBaseMinAddress, CONST64(4)*G);
...
@@ -39,8 +39,6 @@ define_pd_global(uintx, HeapBaseMinAddress, CONST64(4)*G);
#else
#else
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
2
*
G
);
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
2
*
G
);
#endif
#endif
// Only used on 64 bit Windows platforms
define_pd_global
(
bool
,
UseVectoredExceptions
,
false
);
...
...
src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp
浏览文件 @
34551e5c
...
@@ -45,7 +45,5 @@ define_pd_global(intx, CompilerThreadStackSize, 0);
...
@@ -45,7 +45,5 @@ define_pd_global(intx, CompilerThreadStackSize, 0);
// Used on 64 bit platforms for UseCompressedOops base address or CDS
// Used on 64 bit platforms for UseCompressedOops base address or CDS
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
256
*
M
);
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
256
*
M
);
// Only used on 64 bit Windows platforms
define_pd_global
(
bool
,
UseVectoredExceptions
,
false
);
#endif // OS_CPU_SOLARIS_X86_VM_GLOBALS_SOLARIS_X86_HPP
#endif // OS_CPU_SOLARIS_X86_VM_GLOBALS_SOLARIS_X86_HPP
src/os_cpu/windows_x86/vm/globals_windows_x86.hpp
浏览文件 @
34551e5c
...
@@ -47,7 +47,5 @@ define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
...
@@ -47,7 +47,5 @@ define_pd_global(uintx, JVMInvokeMethodSlack, 8192);
// Used on 64 bit platforms for UseCompressedOops base address or CDS
// Used on 64 bit platforms for UseCompressedOops base address or CDS
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
2
*
G
);
define_pd_global
(
uintx
,
HeapBaseMinAddress
,
2
*
G
);
// Only used on 64 bit Windows platforms
define_pd_global
(
bool
,
UseVectoredExceptions
,
false
);
#endif // OS_CPU_WINDOWS_X86_VM_GLOBALS_WINDOWS_X86_HPP
#endif // OS_CPU_WINDOWS_X86_VM_GLOBALS_WINDOWS_X86_HPP
src/os_cpu/windows_x86/vm/os_windows_x86.cpp
浏览文件 @
34551e5c
...
@@ -175,9 +175,6 @@ bool os::register_code_area(char *low, char *high) {
...
@@ -175,9 +175,6 @@ bool os::register_code_area(char *low, char *high) {
PRUNTIME_FUNCTION
prt
;
PRUNTIME_FUNCTION
prt
;
PUNWIND_INFO_EH_ONLY
punwind
;
PUNWIND_INFO_EH_ONLY
punwind
;
// If we are using Vectored Exceptions we don't need this registration
if
(
UseVectoredExceptions
)
return
true
;
BufferBlob
*
blob
=
BufferBlob
::
create
(
"CodeCache Exception Handler"
,
sizeof
(
DynamicCodeData
));
BufferBlob
*
blob
=
BufferBlob
::
create
(
"CodeCache Exception Handler"
,
sizeof
(
DynamicCodeData
));
CodeBuffer
cb
(
blob
);
CodeBuffer
cb
(
blob
);
MacroAssembler
*
masm
=
new
MacroAssembler
(
&
cb
);
MacroAssembler
*
masm
=
new
MacroAssembler
(
&
cb
);
...
...
src/share/vm/asm/codeBuffer.cpp
浏览文件 @
34551e5c
...
@@ -758,7 +758,7 @@ void CodeBuffer::relocate_code_to(CodeBuffer* dest) const {
...
@@ -758,7 +758,7 @@ void CodeBuffer::relocate_code_to(CodeBuffer* dest) const {
}
}
}
}
if
(
dest
->
blob
()
==
NULL
)
{
if
(
dest
->
blob
()
==
NULL
&&
dest_filled
!=
NULL
)
{
// Destination is a final resting place, not just another buffer.
// Destination is a final resting place, not just another buffer.
// Normalize uninitialized bytes in the final padding.
// Normalize uninitialized bytes in the final padding.
Copy
::
fill_to_bytes
(
dest_filled
,
dest_end
-
dest_filled
,
Copy
::
fill_to_bytes
(
dest_filled
,
dest_end
-
dest_filled
,
...
...
src/share/vm/classfile/vmSymbols.hpp
浏览文件 @
34551e5c
...
@@ -115,6 +115,7 @@
...
@@ -115,6 +115,7 @@
/* Java runtime version access */
\
/* Java runtime version access */
\
template(sun_misc_Version, "sun/misc/Version") \
template(sun_misc_Version, "sun/misc/Version") \
template(java_runtime_name_name, "java_runtime_name") \
template(java_runtime_name_name, "java_runtime_name") \
template(java_runtime_version_name, "java_runtime_version") \
\
\
/* class file format tags */
\
/* class file format tags */
\
template(tag_source_file, "SourceFile") \
template(tag_source_file, "SourceFile") \
...
...
src/share/vm/interpreter/abstractInterpreter.hpp
浏览文件 @
34551e5c
...
@@ -320,6 +320,7 @@ class AbstractInterpreterGenerator: public StackObj {
...
@@ -320,6 +320,7 @@ class AbstractInterpreterGenerator: public StackObj {
void
bang_stack_shadow_pages
(
bool
native_call
);
void
bang_stack_shadow_pages
(
bool
native_call
);
void
generate_all
();
void
generate_all
();
void
initialize_method_handle_entries
();
public:
public:
AbstractInterpreterGenerator
(
StubQueue
*
_code
);
AbstractInterpreterGenerator
(
StubQueue
*
_code
);
...
...
src/share/vm/interpreter/bytecodeInterpreter.cpp
浏览文件 @
34551e5c
...
@@ -235,10 +235,6 @@
...
@@ -235,10 +235,6 @@
#endif
#endif
#endif
#endif
// JavaStack Implementation
#define MORE_STACK(count) \
(topOfStack -= ((count) * Interpreter::stackElementWords))
#define UPDATE_PC(opsize) {pc += opsize; }
#define UPDATE_PC(opsize) {pc += opsize; }
/*
/*
...
@@ -575,7 +571,7 @@ BytecodeInterpreter::run(interpreterState istate) {
...
@@ -575,7 +571,7 @@ BytecodeInterpreter::run(interpreterState istate) {
/* 0xE0 */
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
/* 0xE0 */
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
/* 0xE4 */
&&
opc_default
,
&&
opc_fast_aldc
,
&&
opc_fast_aldc_w
,
&&
opc_return_register_finalizer
,
/* 0xE4 */
&&
opc_default
,
&&
opc_fast_aldc
,
&&
opc_fast_aldc_w
,
&&
opc_return_register_finalizer
,
/* 0xE8 */
&&
opc_
default
,
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
/* 0xE8 */
&&
opc_
invokehandle
,
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
/* 0xEC */
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
/* 0xEC */
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
/* 0xF0 */
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
/* 0xF0 */
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
&&
opc_default
,
...
@@ -1773,7 +1769,7 @@ run:
...
@@ -1773,7 +1769,7 @@ run:
oop
obj
;
oop
obj
;
if
((
Bytecodes
::
Code
)
opcode
==
Bytecodes
::
_getstatic
)
{
if
((
Bytecodes
::
Code
)
opcode
==
Bytecodes
::
_getstatic
)
{
Klass
*
k
=
(
Klass
*
)
cache
->
f1
();
Klass
*
k
=
cache
->
f1_as_klass
();
obj
=
k
->
java_mirror
();
obj
=
k
->
java_mirror
();
MORE_STACK
(
1
);
// Assume single slot push
MORE_STACK
(
1
);
// Assume single slot push
}
else
{
}
else
{
...
@@ -1885,7 +1881,7 @@ run:
...
@@ -1885,7 +1881,7 @@ run:
--
count
;
--
count
;
}
}
if
((
Bytecodes
::
Code
)
opcode
==
Bytecodes
::
_putstatic
)
{
if
((
Bytecodes
::
Code
)
opcode
==
Bytecodes
::
_putstatic
)
{
Klass
*
k
=
(
Klass
*
)
cache
->
f1
();
Klass
*
k
=
cache
->
f1_as_klass
();
obj
=
k
->
java_mirror
();
obj
=
k
->
java_mirror
();
}
else
{
}
else
{
--
count
;
--
count
;
...
@@ -2190,6 +2186,7 @@ run:
...
@@ -2190,6 +2186,7 @@ run:
}
}
CASE
(
_invokedynamic
)
:
{
CASE
(
_invokedynamic
)
:
{
if
(
!
EnableInvokeDynamic
)
{
if
(
!
EnableInvokeDynamic
)
{
// We should not encounter this bytecode if !EnableInvokeDynamic.
// We should not encounter this bytecode if !EnableInvokeDynamic.
// The verifier will stop it. However, if we get past the verifier,
// The verifier will stop it. However, if we get past the verifier,
...
@@ -2199,30 +2196,68 @@ run:
...
@@ -2199,30 +2196,68 @@ run:
ShouldNotReachHere
();
ShouldNotReachHere
();
}
}
int
index
=
Bytes
::
get_native_u4
(
pc
+
1
);
u4
index
=
Bytes
::
get_native_u4
(
pc
+
1
);
ConstantPoolCacheEntry
*
cache
=
cp
->
constant_pool
()
->
invokedynamic_cp_cache_entry_at
(
index
);
// We are resolved if the resolved_references field contains a non-null object (CallSite, etc.)
// We are resolved if the resolved_references field contains a non-null object (CallSite, etc.)
// This kind of CP cache entry does not need to match the flags byte, because
// This kind of CP cache entry does not need to match the flags byte, because
// there is a 1-1 relation between bytecode type and CP entry type.
// there is a 1-1 relation between bytecode type and CP entry type.
ConstantPool
*
constants
=
METHOD
->
constants
();
if
(
!
cache
->
is_resolved
((
Bytecodes
::
Code
)
opcode
))
{
oop
result
=
constants
->
resolved_references
()
->
obj_at
(
index
);
if
(
result
==
NULL
)
{
CALL_VM
(
InterpreterRuntime
::
resolve_invokedynamic
(
THREAD
),
CALL_VM
(
InterpreterRuntime
::
resolve_invokedynamic
(
THREAD
),
handle_exception
);
handle_exception
);
result
=
THREAD
->
vm_result
(
);
cache
=
cp
->
constant_pool
()
->
invokedynamic_cp_cache_entry_at
(
index
);
}
}
VERIFY_OOP
(
result
);
Method
*
method
=
cache
->
f1_as_method
();
oop
method_handle
=
java_lang_invoke_CallSite
::
target
(
result
);
VERIFY_OOP
(
method
);
CHECK_NULL
(
method_handle
);
if
(
cache
->
has_appendix
())
{
ConstantPool
*
constants
=
METHOD
->
constants
();
SET_STACK_OBJECT
(
cache
->
appendix_if_resolved
(
constants
),
0
);
MORE_STACK
(
1
);
}
istate
->
set_msg
(
call_method_handle
);
istate
->
set_msg
(
call_method
);
istate
->
set_callee
((
Method
*
)
method_handle
);
istate
->
set_callee
(
method
);
istate
->
set_callee_entry_point
(
method
->
from_interpreted_entry
());
istate
->
set_bcp_advance
(
5
);
istate
->
set_bcp_advance
(
5
);
UPDATE_PC_AND_RETURN
(
0
);
// I'll be back...
UPDATE_PC_AND_RETURN
(
0
);
// I'll be back...
}
}
CASE
(
_invokehandle
)
:
{
if
(
!
EnableInvokeDynamic
)
{
ShouldNotReachHere
();
}
u2
index
=
Bytes
::
get_native_u2
(
pc
+
1
);
ConstantPoolCacheEntry
*
cache
=
cp
->
entry_at
(
index
);
if
(
!
cache
->
is_resolved
((
Bytecodes
::
Code
)
opcode
))
{
CALL_VM
(
InterpreterRuntime
::
resolve_invokehandle
(
THREAD
),
handle_exception
);
cache
=
cp
->
entry_at
(
index
);
}
Method
*
method
=
cache
->
f1_as_method
();
VERIFY_OOP
(
method
);
if
(
cache
->
has_appendix
())
{
ConstantPool
*
constants
=
METHOD
->
constants
();
SET_STACK_OBJECT
(
cache
->
appendix_if_resolved
(
constants
),
0
);
MORE_STACK
(
1
);
}
istate
->
set_msg
(
call_method
);
istate
->
set_callee
(
method
);
istate
->
set_callee_entry_point
(
method
->
from_interpreted_entry
());
istate
->
set_bcp_advance
(
3
);
UPDATE_PC_AND_RETURN
(
0
);
// I'll be back...
}
CASE
(
_invokeinterface
)
:
{
CASE
(
_invokeinterface
)
:
{
u2
index
=
Bytes
::
get_native_u2
(
pc
+
1
);
u2
index
=
Bytes
::
get_native_u2
(
pc
+
1
);
...
...
src/share/vm/interpreter/bytecodeInterpreter.hpp
浏览文件 @
34551e5c
...
@@ -50,6 +50,10 @@
...
@@ -50,6 +50,10 @@
#ifdef CC_INTERP
#ifdef CC_INTERP
// JavaStack Implementation
#define MORE_STACK(count) \
(topOfStack -= ((count) * Interpreter::stackElementWords))
// CVM definitions find hotspot equivalents...
// CVM definitions find hotspot equivalents...
union
VMJavaVal64
{
union
VMJavaVal64
{
...
@@ -107,7 +111,6 @@ public:
...
@@ -107,7 +111,6 @@ public:
rethrow_exception
,
// unwinding and throwing exception
rethrow_exception
,
// unwinding and throwing exception
// requests to frame manager from C++ interpreter
// requests to frame manager from C++ interpreter
call_method
,
// request for new frame from interpreter, manager responds with method_entry
call_method
,
// request for new frame from interpreter, manager responds with method_entry
call_method_handle
,
// like the above, except the callee is a method handle
return_from_method
,
// request from interpreter to unwind, manager responds with method_continue
return_from_method
,
// request from interpreter to unwind, manager responds with method_continue
more_monitors
,
// need a new monitor
more_monitors
,
// need a new monitor
throwing_exception
,
// unwind stack and rethrow
throwing_exception
,
// unwind stack and rethrow
...
...
src/share/vm/interpreter/cppInterpreter.cpp
浏览文件 @
34551e5c
...
@@ -117,7 +117,6 @@ void CppInterpreterGenerator::generate_all() {
...
@@ -117,7 +117,6 @@ void CppInterpreterGenerator::generate_all() {
method_entry
(
empty
);
method_entry
(
empty
);
method_entry
(
accessor
);
method_entry
(
accessor
);
method_entry
(
abstract
);
method_entry
(
abstract
);
method_entry
(
method_handle
);
method_entry
(
java_lang_math_sin
);
method_entry
(
java_lang_math_sin
);
method_entry
(
java_lang_math_cos
);
method_entry
(
java_lang_math_cos
);
method_entry
(
java_lang_math_tan
);
method_entry
(
java_lang_math_tan
);
...
@@ -125,7 +124,12 @@ void CppInterpreterGenerator::generate_all() {
...
@@ -125,7 +124,12 @@ void CppInterpreterGenerator::generate_all() {
method_entry
(
java_lang_math_sqrt
);
method_entry
(
java_lang_math_sqrt
);
method_entry
(
java_lang_math_log
);
method_entry
(
java_lang_math_log
);
method_entry
(
java_lang_math_log10
);
method_entry
(
java_lang_math_log10
);
method_entry
(
java_lang_math_pow
);
method_entry
(
java_lang_math_exp
);
method_entry
(
java_lang_ref_reference_get
);
method_entry
(
java_lang_ref_reference_get
);
initialize_method_handle_entries
();
Interpreter
::
_native_entry_begin
=
Interpreter
::
code
()
->
code_end
();
Interpreter
::
_native_entry_begin
=
Interpreter
::
code
()
->
code_end
();
method_entry
(
native
);
method_entry
(
native
);
method_entry
(
native_synchronized
);
method_entry
(
native_synchronized
);
...
...
src/share/vm/interpreter/interpreter.cpp
浏览文件 @
34551e5c
...
@@ -464,3 +464,11 @@ void AbstractInterpreterGenerator::bang_stack_shadow_pages(bool native_call) {
...
@@ -464,3 +464,11 @@ void AbstractInterpreterGenerator::bang_stack_shadow_pages(bool native_call) {
}
}
}
}
}
}
void
AbstractInterpreterGenerator
::
initialize_method_handle_entries
()
{
// method handle entry kinds are generated later in MethodHandlesAdapterGenerator::generate:
for
(
int
i
=
Interpreter
::
method_handle_invoke_FIRST
;
i
<=
Interpreter
::
method_handle_invoke_LAST
;
i
++
)
{
Interpreter
::
MethodKind
kind
=
(
Interpreter
::
MethodKind
)
i
;
Interpreter
::
_entry_table
[
kind
]
=
Interpreter
::
_entry_table
[
Interpreter
::
abstract
];
}
}
src/share/vm/interpreter/templateInterpreter.cpp
浏览文件 @
34551e5c
...
@@ -373,11 +373,7 @@ void TemplateInterpreterGenerator::generate_all() {
...
@@ -373,11 +373,7 @@ void TemplateInterpreterGenerator::generate_all() {
method_entry
(
java_lang_math_pow
)
method_entry
(
java_lang_math_pow
)
method_entry
(
java_lang_ref_reference_get
)
method_entry
(
java_lang_ref_reference_get
)
// method handle entry kinds are generated later in MethodHandlesAdapterGenerator::generate:
initialize_method_handle_entries
();
for
(
int
i
=
Interpreter
::
method_handle_invoke_FIRST
;
i
<=
Interpreter
::
method_handle_invoke_LAST
;
i
++
)
{
Interpreter
::
MethodKind
kind
=
(
Interpreter
::
MethodKind
)
i
;
Interpreter
::
_entry_table
[
kind
]
=
Interpreter
::
_entry_table
[
Interpreter
::
abstract
];
}
// all native method kinds (must be one contiguous block)
// all native method kinds (must be one contiguous block)
Interpreter
::
_native_entry_begin
=
Interpreter
::
code
()
->
code_end
();
Interpreter
::
_native_entry_begin
=
Interpreter
::
code
()
->
code_end
();
...
...
src/share/vm/memory/collectorPolicy.cpp
浏览文件 @
34551e5c
...
@@ -742,6 +742,8 @@ MetaWord* CollectorPolicy::satisfy_failed_metadata_allocation(
...
@@ -742,6 +742,8 @@ MetaWord* CollectorPolicy::satisfy_failed_metadata_allocation(
uint
gc_count
=
0
;
uint
gc_count
=
0
;
uint
full_gc_count
=
0
;
uint
full_gc_count
=
0
;
assert
(
!
Heap_lock
->
owned_by_self
(),
"Should not be holding the Heap_lock"
);
do
{
do
{
MetaWord
*
result
=
NULL
;
MetaWord
*
result
=
NULL
;
if
(
GC_locker
::
is_active_and_needs_gc
())
{
if
(
GC_locker
::
is_active_and_needs_gc
())
{
...
@@ -756,7 +758,6 @@ MetaWord* CollectorPolicy::satisfy_failed_metadata_allocation(
...
@@ -756,7 +758,6 @@ MetaWord* CollectorPolicy::satisfy_failed_metadata_allocation(
}
}
JavaThread
*
jthr
=
JavaThread
::
current
();
JavaThread
*
jthr
=
JavaThread
::
current
();
if
(
!
jthr
->
in_critical
())
{
if
(
!
jthr
->
in_critical
())
{
MutexUnlocker
mul
(
Heap_lock
);
// Wait for JNI critical section to be exited
// Wait for JNI critical section to be exited
GC_locker
::
stall_until_clear
();
GC_locker
::
stall_until_clear
();
// The GC invoked by the last thread leaving the critical
// The GC invoked by the last thread leaving the critical
...
...
src/share/vm/prims/jvmti.xml
浏览文件 @
34551e5c
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="jvmti.xsl"?>
<?xml-stylesheet type="text/xsl" href="jvmti.xsl"?>
<!--
<!--
Copyright (c) 2002, 201
1
, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2002, 201
2
, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
This code is free software; you can redistribute it and/or modify it
...
@@ -358,7 +358,7 @@
...
@@ -358,7 +358,7 @@
<specification
label=
"JVM(TM) Tool Interface"
<specification
label=
"JVM(TM) Tool Interface"
majorversion=
"1"
majorversion=
"1"
minorversion=
"2"
minorversion=
"2"
microversion=
"
1
"
>
microversion=
"
2
"
>
<title
subtitle=
"Version"
>
<title
subtitle=
"Version"
>
<tm>
JVM
</tm>
Tool Interface
<tm>
JVM
</tm>
Tool Interface
</title>
</title>
...
@@ -405,7 +405,7 @@
...
@@ -405,7 +405,7 @@
interfaces are more appropriate than
<jvmti/>
for many tools.
interfaces are more appropriate than
<jvmti/>
for many tools.
For more information on the Java Platform Debugger Architecture,
For more information on the Java Platform Debugger Architecture,
see the
see the
<externallink
id=
"http://
java.sun.com/products/jpda/
"
>
Java
<externallink
id=
"http://
docs.oracle.com/javase/7/docs/technotes/guides/jpda/architecture.html
"
>
Java
Platform Debugger Architecture website
</externallink>
.
Platform Debugger Architecture website
</externallink>
.
</intro>
</intro>
...
@@ -693,7 +693,7 @@ Agent_OnUnload(JavaVM *vm)</example>
...
@@ -693,7 +693,7 @@ Agent_OnUnload(JavaVM *vm)</example>
An agent creates a
<jvmti/>
environment
An agent creates a
<jvmti/>
environment
by passing a
<jvmti/>
version
by passing a
<jvmti/>
version
as the interface ID to the JNI Invocation API function
as the interface ID to the JNI Invocation API function
<externallink
id=
"http://
java.sun.com/javase/6
/docs/technotes/guides/jni/spec/invocation.html#GetEnv"
><code>
GetEnv
</code></externallink>
.
<externallink
id=
"http://
docs.oracle.com/javase/7
/docs/technotes/guides/jni/spec/invocation.html#GetEnv"
><code>
GetEnv
</code></externallink>
.
See
<internallink
id=
"jvmtiEnvAccess"
>
Accessing
<jvmti/>
Functions
</internallink>
See
<internallink
id=
"jvmtiEnvAccess"
>
Accessing
<jvmti/>
Functions
</internallink>
for more details on the creation and use of
for more details on the creation and use of
<jvmti/>
environments.
<jvmti/>
environments.
...
@@ -797,7 +797,7 @@ Agent_OnUnload(JavaVM *vm)</example>
...
@@ -797,7 +797,7 @@ Agent_OnUnload(JavaVM *vm)</example>
Modified UTF-8 differs
Modified UTF-8 differs
from standard UTF-8 in the representation of supplementary characters
from standard UTF-8 in the representation of supplementary characters
and of the null character. See the
and of the null character. See the
<externallink
id=
"http://
java.sun.com/javase/6
/docs/technotes/guides/jni/spec/types.html#wp16542"
>
<externallink
id=
"http://
docs.oracle.com/javase/7
/docs/technotes/guides/jni/spec/types.html#wp16542"
>
Modified UTF-8 Strings
</externallink>
Modified UTF-8 Strings
</externallink>
section of the JNI specification for details.
section of the JNI specification for details.
</intro>
</intro>
...
@@ -827,7 +827,7 @@ Agent_OnUnload(JavaVM *vm)</example>
...
@@ -827,7 +827,7 @@ Agent_OnUnload(JavaVM *vm)</example>
by calling
<jvmti/>
functions.
by calling
<jvmti/>
functions.
Access to
<jvmti/>
functions is by use of an interface pointer
Access to
<jvmti/>
functions is by use of an interface pointer
in the same manner as
in the same manner as
<externallink
id=
"http://
java.sun.com/javase/6
/docs/technotes/guides/jni/spec/design.html"
>
Java
<externallink
id=
"http://
docs.oracle.com/javase/7
/docs/technotes/guides/jni/spec/design.html"
>
Java
Native Interface (JNI) functions
</externallink>
are accessed.
Native Interface (JNI) functions
</externallink>
are accessed.
The
<jvmti/>
interface pointer is called the
The
<jvmti/>
interface pointer is called the
<i>
environment pointer
</i>
.
<i>
environment pointer
</i>
.
...
@@ -919,7 +919,7 @@ jvmtiEnv *jvmti;
...
@@ -919,7 +919,7 @@ jvmtiEnv *jvmti;
local references--these local references are created
local references--these local references are created
during the
<jvmti/>
call.
during the
<jvmti/>
call.
Local references are a resource that must be managed (see the
Local references are a resource that must be managed (see the
<externallink
id=
"http://
java.sun.com/javase/6/docs/guide
/jni/spec/functions.html#wp18654"
>
JNI Documentation
</externallink>
).
<externallink
id=
"http://
docs.oracle.com/javase/7/docs/technotes/guides
/jni/spec/functions.html#wp18654"
>
JNI Documentation
</externallink>
).
When threads return from native code all local references
When threads return from native code all local references
are freed. Note that some threads, including typical
are freed. Note that some threads, including typical
agent threads, will never return from native code.
agent threads, will never return from native code.
...
@@ -954,7 +954,7 @@ jvmtiEnv *jvmti;
...
@@ -954,7 +954,7 @@ jvmtiEnv *jvmti;
<jvmti/>
function.
<jvmti/>
function.
See the
See the
<externallink
<externallink
id=
"http://
java.sun.com/javase/6
/docs/technotes/guides/jni/spec/design.html#wp770"
id=
"http://
docs.oracle.com/javase/7
/docs/technotes/guides/jni/spec/design.html#wp770"
>
Java Exceptions
</externallink>
>
Java Exceptions
</externallink>
section of the JNI specification for information on handling exceptions.
section of the JNI specification for information on handling exceptions.
</intro>
</intro>
...
@@ -2024,7 +2024,7 @@ jvmtiEnv *jvmti;
...
@@ -2024,7 +2024,7 @@ jvmtiEnv *jvmti;
<p/>
<p/>
Upon execution of
<code>
proc
</code>
, the new thread will be attached to the
Upon execution of
<code>
proc
</code>
, the new thread will be attached to the
VM--see the JNI documentation on
VM--see the JNI documentation on
<externallink
id=
"http://
java.sun.com/javase/6
/docs/technotes/guides/jni/spec/invocation.html#wp1060"
<externallink
id=
"http://
docs.oracle.com/javase/7
/docs/technotes/guides/jni/spec/invocation.html#wp1060"
>
Attaching to the VM
</externallink>
.
>
Attaching to the VM
</externallink>
.
</description>
</description>
<origin>
jvmdiClone
</origin>
<origin>
jvmdiClone
</origin>
...
@@ -4010,7 +4010,7 @@ class C2 extends C1 implements I2 {
...
@@ -4010,7 +4010,7 @@ class C2 extends C1 implements I2 {
</inptr>
</inptr>
<description>
<description>
Details about the reference.
Details about the reference.
Set when the
<
paramlink
id=
"reference_kind"
/
>
is
Set when the
<
datalink
id=
"jvmtiHeapReferenceCallback.reference_kind"
>
reference_kind
</datalink
>
is
<datalink
id=
"JVMTI_HEAP_REFERENCE_FIELD"
/>
,
<datalink
id=
"JVMTI_HEAP_REFERENCE_FIELD"
/>
,
<datalink
id=
"JVMTI_HEAP_REFERENCE_STATIC_FIELD"
/>
,
<datalink
id=
"JVMTI_HEAP_REFERENCE_STATIC_FIELD"
/>
,
<datalink
id=
"JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT"
/>
,
<datalink
id=
"JVMTI_HEAP_REFERENCE_ARRAY_ELEMENT"
/>
,
...
@@ -4378,7 +4378,7 @@ class C2 extends C1 implements I2 {
...
@@ -4378,7 +4378,7 @@ class C2 extends C1 implements I2 {
do not control which objects are visited but they do control which
do not control which objects are visited but they do control which
objects and primitive values are reported by the callbacks.
objects and primitive values are reported by the callbacks.
For example, if the only callback that was set is
For example, if the only callback that was set is
<
paramlink
id=
"array_primitive_value_callback
"
/>
and
<code>
klass
</code>
<
fieldlink
id=
"array_primitive_value_callback"
struct=
"jvmtiHeapCallbacks
"
/>
and
<code>
klass
</code>
is set to the array of bytes class, then only arrays of byte will be
is set to the array of bytes class, then only arrays of byte will be
reported.
reported.
The table below summarizes this:
The table below summarizes this:
...
@@ -4414,7 +4414,7 @@ class C2 extends C1 implements I2 {
...
@@ -4414,7 +4414,7 @@ class C2 extends C1 implements I2 {
</tr>
</tr>
<tr>
<tr>
<th
align=
"left"
>
<th
align=
"left"
>
<fieldlink
id=
"
object_referenc
e_callback"
struct=
"jvmtiHeapCallbacks"
/>
<fieldlink
id=
"
array_primitive_valu
e_callback"
struct=
"jvmtiHeapCallbacks"
/>
in
<paramlink
id=
"callbacks"
/>
set
in
<paramlink
id=
"callbacks"
/>
set
</th>
</th>
<td>
<td>
...
@@ -4570,7 +4570,7 @@ class C2 extends C1 implements I2 {
...
@@ -4570,7 +4570,7 @@ class C2 extends C1 implements I2 {
do not control which objects are visited but they do control which
do not control which objects are visited but they do control which
objects and primitive values are reported by the callbacks.
objects and primitive values are reported by the callbacks.
For example, if the only callback that was set is
For example, if the only callback that was set is
<
paramlink
id=
"array_primitive_value_callback
"
/>
and
<code>
klass
</code>
<
fieldlink
id=
"array_primitive_value_callback"
struct=
"jvmtiHeapCallbacks
"
/>
and
<code>
klass
</code>
is set to the array of bytes class, then only arrays of byte will be
is set to the array of bytes class, then only arrays of byte will be
reported. The table below summarizes this (contrast this with
reported. The table below summarizes this (contrast this with
<functionlink
id=
"FollowReferences"
/>
):
<functionlink
id=
"FollowReferences"
/>
):
...
@@ -4606,7 +4606,7 @@ class C2 extends C1 implements I2 {
...
@@ -4606,7 +4606,7 @@ class C2 extends C1 implements I2 {
</tr>
</tr>
<tr>
<tr>
<th
align=
"left"
>
<th
align=
"left"
>
<fieldlink
id=
"
object
_callback"
struct=
"jvmtiHeapCallbacks"
/>
<fieldlink
id=
"
array_primitive_value
_callback"
struct=
"jvmtiHeapCallbacks"
/>
in
<paramlink
id=
"callbacks"
/>
set
in
<paramlink
id=
"callbacks"
/>
set
</th>
</th>
<td>
<td>
...
@@ -6478,7 +6478,7 @@ class C2 extends C1 implements I2 {
...
@@ -6478,7 +6478,7 @@ class C2 extends C1 implements I2 {
<synopsis>
Get Class Signature
</synopsis>
<synopsis>
Get Class Signature
</synopsis>
<description>
<description>
For the class indicated by
<code>
klass
</code>
, return the
For the class indicated by
<code>
klass
</code>
, return the
<externallink
id=
"http://
java.sun.com/javase/6/docs/guide
/jni/spec/types.html#wp16432"
>
JNI
<externallink
id=
"http://
docs.oracle.com/javase/7/docs/technotes/guides
/jni/spec/types.html#wp16432"
>
JNI
type signature
</externallink>
type signature
</externallink>
and the generic signature of the class.
and the generic signature of the class.
For example,
<code>
java.util.List
</code>
is
<code>
"Ljava/util/List;"
</code>
For example,
<code>
java.util.List
</code>
is
<code>
"Ljava/util/List;"
</code>
...
@@ -8763,7 +8763,7 @@ method(wrapped_foo) -> nativeImplementation(foo)</example>
...
@@ -8763,7 +8763,7 @@ method(wrapped_foo) -> nativeImplementation(foo)</example>
Provides the ability to intercept and resend
Provides the ability to intercept and resend
Java Native Interface (JNI) function calls
Java Native Interface (JNI) function calls
by manipulating the JNI function table.
by manipulating the JNI function table.
See
<externallink
id=
"http://
java.sun.com/javase/6/docs/guide
/jni/spec/functions.html"
>
JNI
See
<externallink
id=
"http://
docs.oracle.com/javase/7/docs/technotes/guides
/jni/spec/functions.html"
>
JNI
Functions
</externallink>
in the
<i>
Java Native Interface Specification
</i>
.
Functions
</externallink>
in the
<i>
Java Native Interface Specification
</i>
.
<p/>
<p/>
The following example illustrates intercepting the
The following example illustrates intercepting the
...
@@ -10446,7 +10446,7 @@ myInit() {
...
@@ -10446,7 +10446,7 @@ myInit() {
for a class. The segment is typically a directory or JAR file.
for a class. The segment is typically a directory or JAR file.
<p/>
<p/>
In the live phase the
<paramlink
id=
"segment"
/>
may be used to specify any platform-dependent
In the live phase the
<paramlink
id=
"segment"
/>
may be used to specify any platform-dependent
path to a
<externallink
id=
"http://
java.sun.com/javase/6/docs/guide
/jar/jar.html"
>
path to a
<externallink
id=
"http://
docs.oracle.com/javase/7/docs/technotes/guides
/jar/jar.html"
>
JAR file
</externallink>
. The agent should take care that the JAR file does not
JAR file
</externallink>
. The agent should take care that the JAR file does not
contain any classes or resources other than those to be defined by the bootstrap
contain any classes or resources other than those to be defined by the bootstrap
class loader for the purposes of instrumentation.
class loader for the purposes of instrumentation.
...
@@ -10494,7 +10494,7 @@ myInit() {
...
@@ -10494,7 +10494,7 @@ myInit() {
for a class. The segment is typically a directory or JAR file.
for a class. The segment is typically a directory or JAR file.
<p/>
<p/>
In the live phase the
<paramlink
id=
"segment"
/>
is a platform-dependent path to a
<externallink
In the live phase the
<paramlink
id=
"segment"
/>
is a platform-dependent path to a
<externallink
id=
"http://
java.sun.com/javase/6/docs/guide
/jar/jar.html"
>
JAR file
</externallink>
to be
id=
"http://
docs.oracle.com/javase/7/docs/technotes/guides
/jar/jar.html"
>
JAR file
</externallink>
to be
searched after the system class loader unsuccessfully searches for a class. The agent should
searched after the system class loader unsuccessfully searches for a class. The agent should
take care that the JAR file does not contain any classes or resources other than those to be
take care that the JAR file does not contain any classes or resources other than those to be
defined by the system class loader for the purposes of instrumentation.
defined by the system class loader for the purposes of instrumentation.
...
@@ -13128,6 +13128,12 @@ myInit() {
...
@@ -13128,6 +13128,12 @@ myInit() {
Unsigned 8 bits.
Unsigned 8 bits.
</description>
</description>
</basetype>
</basetype>
<basetype
id=
"jchar"
>
<description>
Holds a Java programming language
<code>
char
</code>
.
Unsigned 16 bits.
</description>
</basetype>
<basetype
id=
"jint"
>
<basetype
id=
"jint"
>
<description>
<description>
Holds a Java programming language
<code>
int
</code>
.
Holds a Java programming language
<code>
int
</code>
.
...
@@ -13285,7 +13291,7 @@ typedef void (JNICALL *jvmtiEventVMInit)
...
@@ -13285,7 +13291,7 @@ typedef void (JNICALL *jvmtiEventVMInit)
<description>
<description>
Typedef for the JNI function table
<code>
JNINativeInterface
</code>
Typedef for the JNI function table
<code>
JNINativeInterface
</code>
defined in the
defined in the
<externallink
id=
"http://
java.sun.com/javase/6/docs/guide
/jni/spec/functions.html#wp23720"
>
JNI Specification
</externallink>
.
<externallink
id=
"http://
docs.oracle.com/javase/7/docs/technotes/guides
/jni/spec/functions.html#wp23720"
>
JNI Specification
</externallink>
.
The JNI reference implementation defines this with an underscore.
The JNI reference implementation defines this with an underscore.
</description>
</description>
</basetype>
</basetype>
...
@@ -14252,6 +14258,9 @@ typedef void (JNICALL *jvmtiEventVMInit)
...
@@ -14252,6 +14258,9 @@ typedef void (JNICALL *jvmtiEventVMInit)
<change
date=
"6 August 2006"
version=
"1.1.102"
>
<change
date=
"6 August 2006"
version=
"1.1.102"
>
Add ResourceExhaustedEvent.
Add ResourceExhaustedEvent.
</change>
</change>
<change
date=
"11 October 2012"
version=
"1.2.2"
>
Fixed the "HTTP" and "Missing Anchor" errors reported by the LinkCheck tool.
</change>
</changehistory>
</changehistory>
</specification>
</specification>
...
...
src/share/vm/prims/jvmtiEnvBase.hpp
浏览文件 @
34551e5c
...
@@ -69,7 +69,7 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
...
@@ -69,7 +69,7 @@ class JvmtiEnvBase : public CHeapObj<mtInternal> {
enum
{
enum
{
JDK15_JVMTI_VERSION
=
JVMTI_VERSION_1_0
+
33
,
/* version: 1.0.33 */
JDK15_JVMTI_VERSION
=
JVMTI_VERSION_1_0
+
33
,
/* version: 1.0.33 */
JDK16_JVMTI_VERSION
=
JVMTI_VERSION_1_1
+
102
,
/* version: 1.1.102 */
JDK16_JVMTI_VERSION
=
JVMTI_VERSION_1_1
+
102
,
/* version: 1.1.102 */
JDK17_JVMTI_VERSION
=
JVMTI_VERSION_1_2
+
1
/* version: 1.2.1
*/
JDK17_JVMTI_VERSION
=
JVMTI_VERSION_1_2
+
2
/* version: 1.2.2
*/
};
};
static
jvmtiPhase
get_phase
()
{
return
_phase
;
}
static
jvmtiPhase
get_phase
()
{
return
_phase
;
}
...
...
src/share/vm/runtime/arguments.cpp
浏览文件 @
34551e5c
...
@@ -257,6 +257,7 @@ static ObsoleteFlag obsolete_jvm_flags[] = {
...
@@ -257,6 +257,7 @@ static ObsoleteFlag obsolete_jvm_flags[] = {
{
"MaxPermHeapExpansion"
,
JDK_Version
::
jdk
(
8
),
JDK_Version
::
jdk
(
9
)
},
{
"MaxPermHeapExpansion"
,
JDK_Version
::
jdk
(
8
),
JDK_Version
::
jdk
(
9
)
},
{
"CMSRevisitStackSize"
,
JDK_Version
::
jdk
(
8
),
JDK_Version
::
jdk
(
9
)
},
{
"CMSRevisitStackSize"
,
JDK_Version
::
jdk
(
8
),
JDK_Version
::
jdk
(
9
)
},
{
"PrintRevisitStats"
,
JDK_Version
::
jdk
(
8
),
JDK_Version
::
jdk
(
9
)
},
{
"PrintRevisitStats"
,
JDK_Version
::
jdk
(
8
),
JDK_Version
::
jdk
(
9
)
},
{
"UseVectoredExceptions"
,
JDK_Version
::
jdk
(
8
),
JDK_Version
::
jdk
(
9
)
},
#ifdef PRODUCT
#ifdef PRODUCT
{
"DesiredMethodLimit"
,
{
"DesiredMethodLimit"
,
JDK_Version
::
jdk_update
(
7
,
2
),
JDK_Version
::
jdk
(
8
)
},
JDK_Version
::
jdk_update
(
7
,
2
),
JDK_Version
::
jdk
(
8
)
},
...
@@ -2568,7 +2569,9 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
...
@@ -2568,7 +2569,9 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
FLAG_SET_CMDLINE
(
uintx
,
MaxNewSize
,
NewSize
);
FLAG_SET_CMDLINE
(
uintx
,
MaxNewSize
,
NewSize
);
}
}
#ifndef _ALLBSD_SOURCE // UseLargePages is not yet supported on BSD.
FLAG_SET_DEFAULT
(
UseLargePages
,
true
);
FLAG_SET_DEFAULT
(
UseLargePages
,
true
);
#endif
// Increase some data structure sizes for efficiency
// Increase some data structure sizes for efficiency
FLAG_SET_CMDLINE
(
uintx
,
BaseFootPrintEstimate
,
MaxHeapSize
);
FLAG_SET_CMDLINE
(
uintx
,
BaseFootPrintEstimate
,
MaxHeapSize
);
...
@@ -3133,6 +3136,10 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
...
@@ -3133,6 +3136,10 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
UNSUPPORTED_OPTION
(
UseG1GC
,
"G1 GC"
);
UNSUPPORTED_OPTION
(
UseG1GC
,
"G1 GC"
);
#endif
#endif
#ifdef _ALLBSD_SOURCE // UseLargePages is not yet supported on BSD.
UNSUPPORTED_OPTION
(
UseLargePages
,
"-XX:+UseLargePages"
);
#endif
#if !INCLUDE_ALTERNATE_GCS
#if !INCLUDE_ALTERNATE_GCS
if
(
UseParallelGC
)
{
if
(
UseParallelGC
)
{
warning
(
"Parallel GC is not supported in this VM. Using Serial GC."
);
warning
(
"Parallel GC is not supported in this VM. Using Serial GC."
);
...
...
src/share/vm/runtime/globals.hpp
浏览文件 @
34551e5c
...
@@ -857,9 +857,6 @@ class CommandLineFlags {
...
@@ -857,9 +857,6 @@ class CommandLineFlags {
develop(bool, BreakAtWarning, false, \
develop(bool, BreakAtWarning, false, \
"Execute breakpoint upon encountering VM warning") \
"Execute breakpoint upon encountering VM warning") \
\
\
product_pd(bool, UseVectoredExceptions, \
"Temp Flag - Use Vectored Exceptions rather than SEH (Windows Only)") \
\
develop(bool, TraceVMOperation, false, \
develop(bool, TraceVMOperation, false, \
"Trace vm operations") \
"Trace vm operations") \
\
\
...
...
src/share/vm/runtime/java.cpp
浏览文件 @
34551e5c
...
@@ -688,6 +688,7 @@ void vm_shutdown_during_initialization(const char* error, const char* message) {
...
@@ -688,6 +688,7 @@ void vm_shutdown_during_initialization(const char* error, const char* message) {
JDK_Version
JDK_Version
::
_current
;
JDK_Version
JDK_Version
::
_current
;
const
char
*
JDK_Version
::
_runtime_name
;
const
char
*
JDK_Version
::
_runtime_name
;
const
char
*
JDK_Version
::
_runtime_version
;
void
JDK_Version
::
initialize
()
{
void
JDK_Version
::
initialize
()
{
jdk_version_info
info
;
jdk_version_info
info
;
...
...
src/share/vm/runtime/java.hpp
浏览文件 @
34551e5c
...
@@ -75,6 +75,7 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC {
...
@@ -75,6 +75,7 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC {
static
JDK_Version
_current
;
static
JDK_Version
_current
;
static
const
char
*
_runtime_name
;
static
const
char
*
_runtime_name
;
static
const
char
*
_runtime_version
;
// In this class, we promote the minor version of release to be the
// In this class, we promote the minor version of release to be the
// major version for releases >= 5 in anticipation of the JDK doing the
// major version for releases >= 5 in anticipation of the JDK doing the
...
@@ -189,6 +190,13 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC {
...
@@ -189,6 +190,13 @@ class JDK_Version VALUE_OBJ_CLASS_SPEC {
_runtime_name
=
name
;
_runtime_name
=
name
;
}
}
static
const
char
*
runtime_version
()
{
return
_runtime_version
;
}
static
void
set_runtime_version
(
const
char
*
version
)
{
_runtime_version
=
version
;
}
// Convenience methods for queries on the current major/minor version
// Convenience methods for queries on the current major/minor version
static
bool
is_jdk12x_version
()
{
static
bool
is_jdk12x_version
()
{
return
current
().
compare_major
(
2
)
==
0
;
return
current
().
compare_major
(
2
)
==
0
;
...
...
src/share/vm/runtime/thread.cpp
浏览文件 @
34551e5c
...
@@ -1042,6 +1042,7 @@ static void call_initializeSystemClass(TRAPS) {
...
@@ -1042,6 +1042,7 @@ static void call_initializeSystemClass(TRAPS) {
}
}
char
java_runtime_name
[
128
]
=
""
;
char
java_runtime_name
[
128
]
=
""
;
char
java_runtime_version
[
128
]
=
""
;
// extract the JRE name from sun.misc.Version.java_runtime_name
// extract the JRE name from sun.misc.Version.java_runtime_name
static
const
char
*
get_java_runtime_name
(
TRAPS
)
{
static
const
char
*
get_java_runtime_name
(
TRAPS
)
{
...
@@ -1064,6 +1065,27 @@ static const char* get_java_runtime_name(TRAPS) {
...
@@ -1064,6 +1065,27 @@ static const char* get_java_runtime_name(TRAPS) {
}
}
}
}
// extract the JRE version from sun.misc.Version.java_runtime_version
static
const
char
*
get_java_runtime_version
(
TRAPS
)
{
Klass
*
k
=
SystemDictionary
::
find
(
vmSymbols
::
sun_misc_Version
(),
Handle
(),
Handle
(),
CHECK_AND_CLEAR_NULL
);
fieldDescriptor
fd
;
bool
found
=
k
!=
NULL
&&
InstanceKlass
::
cast
(
k
)
->
find_local_field
(
vmSymbols
::
java_runtime_version_name
(),
vmSymbols
::
string_signature
(),
&
fd
);
if
(
found
)
{
oop
name_oop
=
k
->
java_mirror
()
->
obj_field
(
fd
.
offset
());
if
(
name_oop
==
NULL
)
return
NULL
;
const
char
*
name
=
java_lang_String
::
as_utf8_string
(
name_oop
,
java_runtime_version
,
sizeof
(
java_runtime_version
));
return
name
;
}
else
{
return
NULL
;
}
}
// General purpose hook into Java code, run once when the VM is initialized.
// General purpose hook into Java code, run once when the VM is initialized.
// The Java library method itself may be changed independently from the VM.
// The Java library method itself may be changed independently from the VM.
static
void
call_postVMInitHook
(
TRAPS
)
{
static
void
call_postVMInitHook
(
TRAPS
)
{
...
@@ -3473,6 +3495,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
...
@@ -3473,6 +3495,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
// get the Java runtime name after java.lang.System is initialized
// get the Java runtime name after java.lang.System is initialized
JDK_Version
::
set_runtime_name
(
get_java_runtime_name
(
THREAD
));
JDK_Version
::
set_runtime_name
(
get_java_runtime_name
(
THREAD
));
JDK_Version
::
set_runtime_version
(
get_java_runtime_version
(
THREAD
));
}
else
{
}
else
{
warning
(
"java.lang.System not initialized"
);
warning
(
"java.lang.System not initialized"
);
}
}
...
...
src/share/vm/runtime/vmStructs.cpp
浏览文件 @
34551e5c
...
@@ -2474,7 +2474,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
...
@@ -2474,7 +2474,7 @@ typedef BinaryTreeDictionary<Metablock, FreeList> MetablockTreeDictionary;
/* frame */
\
/* frame */
\
/**********************/
\
/**********************/
\
\
\
X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset
)) \
NOT_ZERO(X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset)
)) \
declare_constant(frame::pc_return_offset) \
declare_constant(frame::pc_return_offset) \
\
\
/*************/
\
/*************/
\
...
...
src/share/vm/utilities/macros.hpp
浏览文件 @
34551e5c
...
@@ -282,6 +282,22 @@
...
@@ -282,6 +282,22 @@
#define NOT_WIN64(code) code
#define NOT_WIN64(code) code
#endif
#endif
#if defined(ZERO)
#define ZERO_ONLY(code) code
#define NOT_ZERO(code)
#else
#define ZERO_ONLY(code)
#define NOT_ZERO(code) code
#endif
#if defined(SHARK)
#define SHARK_ONLY(code) code
#define NOT_SHARK(code)
#else
#define SHARK_ONLY(code)
#define NOT_SHARK(code) code
#endif
#if defined(IA32) || defined(AMD64)
#if defined(IA32) || defined(AMD64)
#define X86
#define X86
#define X86_ONLY(code) code
#define X86_ONLY(code) code
...
...
src/share/vm/utilities/taskqueue.hpp
浏览文件 @
34551e5c
...
@@ -496,9 +496,7 @@ public:
...
@@ -496,9 +496,7 @@ public:
}
}
}
}
bool
steal_1_random
(
uint
queue_num
,
int
*
seed
,
E
&
t
);
bool
steal_best_of_2
(
uint
queue_num
,
int
*
seed
,
E
&
t
);
bool
steal_best_of_2
(
uint
queue_num
,
int
*
seed
,
E
&
t
);
bool
steal_best_of_all
(
uint
queue_num
,
int
*
seed
,
E
&
t
);
void
register_queue
(
uint
i
,
T
*
q
);
void
register_queue
(
uint
i
,
T
*
q
);
...
@@ -537,46 +535,6 @@ GenericTaskQueueSet<T, F>::steal(uint queue_num, int* seed, E& t) {
...
@@ -537,46 +535,6 @@ GenericTaskQueueSet<T, F>::steal(uint queue_num, int* seed, E& t) {
return
false
;
return
false
;
}
}
template
<
class
T
,
MEMFLAGS
F
>
bool
GenericTaskQueueSet
<
T
,
F
>::
steal_best_of_all
(
uint
queue_num
,
int
*
seed
,
E
&
t
)
{
if
(
_n
>
2
)
{
int
best_k
;
uint
best_sz
=
0
;
for
(
uint
k
=
0
;
k
<
_n
;
k
++
)
{
if
(
k
==
queue_num
)
continue
;
uint
sz
=
_queues
[
k
]
->
size
();
if
(
sz
>
best_sz
)
{
best_sz
=
sz
;
best_k
=
k
;
}
}
return
best_sz
>
0
&&
_queues
[
best_k
]
->
pop_global
(
t
);
}
else
if
(
_n
==
2
)
{
// Just try the other one.
int
k
=
(
queue_num
+
1
)
%
2
;
return
_queues
[
k
]
->
pop_global
(
t
);
}
else
{
assert
(
_n
==
1
,
"can't be zero."
);
return
false
;
}
}
template
<
class
T
,
MEMFLAGS
F
>
bool
GenericTaskQueueSet
<
T
,
F
>::
steal_1_random
(
uint
queue_num
,
int
*
seed
,
E
&
t
)
{
if
(
_n
>
2
)
{
uint
k
=
queue_num
;
while
(
k
==
queue_num
)
k
=
TaskQueueSetSuper
::
randomParkAndMiller
(
seed
)
%
_n
;
return
_queues
[
2
]
->
pop_global
(
t
);
}
else
if
(
_n
==
2
)
{
// Just try the other one.
int
k
=
(
queue_num
+
1
)
%
2
;
return
_queues
[
k
]
->
pop_global
(
t
);
}
else
{
assert
(
_n
==
1
,
"can't be zero."
);
return
false
;
}
}
template
<
class
T
,
MEMFLAGS
F
>
bool
template
<
class
T
,
MEMFLAGS
F
>
bool
GenericTaskQueueSet
<
T
,
F
>::
steal_best_of_2
(
uint
queue_num
,
int
*
seed
,
E
&
t
)
{
GenericTaskQueueSet
<
T
,
F
>::
steal_best_of_2
(
uint
queue_num
,
int
*
seed
,
E
&
t
)
{
if
(
_n
>
2
)
{
if
(
_n
>
2
)
{
...
...
src/share/vm/utilities/vmError.cpp
浏览文件 @
34551e5c
...
@@ -453,7 +453,9 @@ void VMError::report(outputStream* st) {
...
@@ -453,7 +453,9 @@ void VMError::report(outputStream* st) {
JDK_Version
::
current
().
to_string
(
buf
,
sizeof
(
buf
));
JDK_Version
::
current
().
to_string
(
buf
,
sizeof
(
buf
));
const
char
*
runtime_name
=
JDK_Version
::
runtime_name
()
!=
NULL
?
const
char
*
runtime_name
=
JDK_Version
::
runtime_name
()
!=
NULL
?
JDK_Version
::
runtime_name
()
:
""
;
JDK_Version
::
runtime_name
()
:
""
;
st
->
print_cr
(
"# JRE version: %s (%s)"
,
runtime_name
,
buf
);
const
char
*
runtime_version
=
JDK_Version
::
runtime_version
()
!=
NULL
?
JDK_Version
::
runtime_version
()
:
""
;
st
->
print_cr
(
"# JRE version: %s (%s) (build %s)"
,
runtime_name
,
buf
,
runtime_version
);
st
->
print_cr
(
"# Java VM: %s (%s %s %s %s)"
,
st
->
print_cr
(
"# Java VM: %s (%s %s %s %s)"
,
Abstract_VM_Version
::
vm_name
(),
Abstract_VM_Version
::
vm_name
(),
Abstract_VM_Version
::
vm_release
(),
Abstract_VM_Version
::
vm_release
(),
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录