Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
730a6a98
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看板
提交
730a6a98
编写于
5月 26, 2011
作者:
N
never
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
7047961: JSR 292 MethodHandleWalk swap args doesn't handle T_LONG and T_DOUBLE properly
Reviewed-by: kvn, jrose
上级
7c843ca5
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
300 addition
and
111 deletion
+300
-111
src/share/vm/prims/methodHandleWalk.cpp
src/share/vm/prims/methodHandleWalk.cpp
+253
-62
src/share/vm/prims/methodHandleWalk.hpp
src/share/vm/prims/methodHandleWalk.hpp
+35
-37
src/share/vm/prims/methodHandles.cpp
src/share/vm/prims/methodHandles.cpp
+12
-12
未找到文件。
src/share/vm/prims/methodHandleWalk.cpp
浏览文件 @
730a6a98
...
@@ -141,6 +141,12 @@ BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int
...
@@ -141,6 +141,12 @@ BasicType MethodHandleChain::compute_bound_arg_type(oop target, methodOop m, int
void
MethodHandleChain
::
lose
(
const
char
*
msg
,
TRAPS
)
{
void
MethodHandleChain
::
lose
(
const
char
*
msg
,
TRAPS
)
{
_lose_message
=
msg
;
_lose_message
=
msg
;
#ifdef ASSERT
if
(
Verbose
)
{
tty
->
print_cr
(
INTPTR_FORMAT
" lose: %s"
,
_method_handle
(),
msg
);
print
();
}
#endif
if
(
!
THREAD
->
is_Java_thread
()
||
((
JavaThread
*
)
THREAD
)
->
thread_state
()
!=
_thread_in_vm
)
{
if
(
!
THREAD
->
is_Java_thread
()
||
((
JavaThread
*
)
THREAD
)
->
thread_state
()
!=
_thread_in_vm
)
{
// throw a preallocated exception
// throw a preallocated exception
THROW_OOP
(
Universe
::
virtual_machine_error_instance
());
THROW_OOP
(
Universe
::
virtual_machine_error_instance
());
...
@@ -149,6 +155,145 @@ void MethodHandleChain::lose(const char* msg, TRAPS) {
...
@@ -149,6 +155,145 @@ void MethodHandleChain::lose(const char* msg, TRAPS) {
}
}
#ifdef ASSERT
static
const
char
*
adapter_ops
[]
=
{
"retype_only"
,
"retype_raw"
,
"check_cast"
,
"prim_to_prim"
,
"ref_to_prim"
,
"prim_to_ref"
,
"swap_args"
,
"rot_args"
,
"dup_args"
,
"drop_args"
,
"collect_args"
,
"spread_args"
,
"fold_args"
};
static
const
char
*
adapter_op_to_string
(
int
op
)
{
if
(
op
>=
0
&&
op
<
(
int
)
ARRAY_SIZE
(
adapter_ops
))
return
adapter_ops
[
op
];
return
"unknown_op"
;
}
void
MethodHandleChain
::
print
(
Handle
mh
)
{
EXCEPTION_MARK
;
MethodHandleChain
mhc
(
mh
,
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
oop
ex
=
THREAD
->
pending_exception
();
CLEAR_PENDING_EXCEPTION
;
ex
->
print
();
return
;
}
mhc
.
print
();
}
void
MethodHandleChain
::
print
()
{
EXCEPTION_MARK
;
print_impl
(
THREAD
);
if
(
HAS_PENDING_EXCEPTION
)
{
oop
ex
=
THREAD
->
pending_exception
();
CLEAR_PENDING_EXCEPTION
;
ex
->
print
();
}
}
void
MethodHandleChain
::
print_impl
(
TRAPS
)
{
ResourceMark
rm
;
MethodHandleChain
chain
(
_root
,
CHECK
);
for
(;;)
{
tty
->
print
(
INTPTR_FORMAT
": "
,
chain
.
method_handle
()());
if
(
chain
.
is_bound
())
{
tty
->
print
(
"bound: arg_type %s arg_slot %d"
,
type2name
(
chain
.
bound_arg_type
()),
chain
.
bound_arg_slot
());
oop
o
=
chain
.
bound_arg_oop
();
if
(
o
!=
NULL
)
{
if
(
o
->
is_instance
())
{
tty
->
print
(
" instance %s"
,
o
->
klass
()
->
klass_part
()
->
internal_name
());
}
else
{
o
->
print
();
}
}
}
else
if
(
chain
.
is_adapter
())
{
tty
->
print
(
"adapter: arg_slot %d conversion op %s"
,
chain
.
adapter_arg_slot
(),
adapter_op_to_string
(
chain
.
adapter_conversion_op
()));
switch
(
chain
.
adapter_conversion_op
())
{
case
java_lang_invoke_AdapterMethodHandle
::
OP_RETYPE_ONLY
:
case
java_lang_invoke_AdapterMethodHandle
::
OP_RETYPE_RAW
:
case
java_lang_invoke_AdapterMethodHandle
::
OP_CHECK_CAST
:
case
java_lang_invoke_AdapterMethodHandle
::
OP_PRIM_TO_PRIM
:
case
java_lang_invoke_AdapterMethodHandle
::
OP_REF_TO_PRIM
:
case
java_lang_invoke_AdapterMethodHandle
::
OP_PRIM_TO_REF
:
break
;
case
java_lang_invoke_AdapterMethodHandle
::
OP_SWAP_ARGS
:
case
java_lang_invoke_AdapterMethodHandle
::
OP_ROT_ARGS
:
{
int
dest_arg_slot
=
chain
.
adapter_conversion_vminfo
();
tty
->
print
(
" dest_arg_slot %d type %s"
,
dest_arg_slot
,
type2name
(
chain
.
adapter_conversion_src_type
()));
break
;
}
case
java_lang_invoke_AdapterMethodHandle
::
OP_DUP_ARGS
:
case
java_lang_invoke_AdapterMethodHandle
::
OP_DROP_ARGS
:
{
int
dup_slots
=
chain
.
adapter_conversion_stack_pushes
();
tty
->
print
(
" pushes %d"
,
dup_slots
);
break
;
}
case
java_lang_invoke_AdapterMethodHandle
::
OP_FOLD_ARGS
:
case
java_lang_invoke_AdapterMethodHandle
::
OP_COLLECT_ARGS
:
{
int
coll_slots
=
chain
.
MethodHandle_vmslots
();
tty
->
print
(
" coll_slots %d"
,
coll_slots
);
break
;
}
case
java_lang_invoke_AdapterMethodHandle
::
OP_SPREAD_ARGS
:
{
// Check the required length.
int
spread_slots
=
1
+
chain
.
adapter_conversion_stack_pushes
();
tty
->
print
(
" spread_slots %d"
,
spread_slots
);
break
;
}
default:
tty
->
print_cr
(
"bad adapter conversion"
);
break
;
}
}
else
{
// DMH
tty
->
print
(
"direct: "
);
chain
.
last_method_oop
()
->
print_short_name
(
tty
);
}
tty
->
print
(
" ("
);
objArrayOop
ptypes
=
java_lang_invoke_MethodType
::
ptypes
(
chain
.
method_type_oop
());
for
(
int
i
=
ptypes
->
length
()
-
1
;
i
>=
0
;
i
--
)
{
BasicType
t
=
java_lang_Class
::
as_BasicType
(
ptypes
->
obj_at
(
i
));
if
(
t
==
T_ARRAY
)
t
=
T_OBJECT
;
tty
->
print
(
"%c"
,
type2char
(
t
));
if
(
t
==
T_LONG
||
t
==
T_DOUBLE
)
tty
->
print
(
"_"
);
}
tty
->
print
(
")"
);
BasicType
rtype
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
rtype
(
chain
.
method_type_oop
()));
if
(
rtype
==
T_ARRAY
)
rtype
=
T_OBJECT
;
tty
->
print
(
"%c"
,
type2char
(
rtype
));
tty
->
cr
();
if
(
!
chain
.
is_last
())
{
chain
.
next
(
CHECK
);
}
else
{
break
;
}
}
}
#endif
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// MethodHandleWalker
// MethodHandleWalker
...
@@ -205,10 +350,16 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -205,10 +350,16 @@ MethodHandleWalker::walk(TRAPS) {
if
(
chain
().
is_adapter
())
{
if
(
chain
().
is_adapter
())
{
int
conv_op
=
chain
().
adapter_conversion_op
();
int
conv_op
=
chain
().
adapter_conversion_op
();
int
arg_slot
=
chain
().
adapter_arg_slot
();
int
arg_slot
=
chain
().
adapter_arg_slot
();
SlotState
*
arg_state
=
slot_state
(
arg_slot
);
if
(
arg_state
==
NULL
// Check that the arg_slot is valid. In most cases it must be
&&
conv_op
>
java_lang_invoke_AdapterMethodHandle
::
OP_RETYPE_RAW
)
{
// within range of the current arguments but there are some
lose
(
"bad argument index"
,
CHECK_
(
empty
));
// exceptions. Those are sanity checked in their implemention
// below.
if
((
arg_slot
<
0
||
arg_slot
>=
_outgoing
.
length
())
&&
conv_op
>
java_lang_invoke_AdapterMethodHandle
::
OP_RETYPE_RAW
&&
conv_op
!=
java_lang_invoke_AdapterMethodHandle
::
OP_COLLECT_ARGS
&&
conv_op
!=
java_lang_invoke_AdapterMethodHandle
::
OP_FOLD_ARGS
)
{
lose
(
err_msg
(
"bad argument index %d"
,
arg_slot
),
CHECK_
(
empty
));
}
}
bool
retain_original_args
=
false
;
// used by fold/collect logic
bool
retain_original_args
=
false
;
// used by fold/collect logic
...
@@ -237,8 +388,7 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -237,8 +388,7 @@ MethodHandleWalker::walk(TRAPS) {
// Argument types.
// Argument types.
for
(
int
i
=
0
,
slot
=
_outgoing
.
length
()
-
1
;
slot
>=
0
;
slot
--
)
{
for
(
int
i
=
0
,
slot
=
_outgoing
.
length
()
-
1
;
slot
>=
0
;
slot
--
)
{
SlotState
*
arg_state
=
slot_state
(
slot
);
if
(
arg_type
(
slot
)
==
T_VOID
)
continue
;
if
(
arg_state
->
_type
==
T_VOID
)
continue
;
klassOop
src_klass
=
NULL
;
klassOop
src_klass
=
NULL
;
klassOop
dst_klass
=
NULL
;
klassOop
dst_klass
=
NULL
;
...
@@ -262,8 +412,8 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -262,8 +412,8 @@ MethodHandleWalker::walk(TRAPS) {
klassOop
dest_klass
=
NULL
;
klassOop
dest_klass
=
NULL
;
BasicType
dest
=
java_lang_Class
::
as_BasicType
(
chain
().
adapter_arg_oop
(),
&
dest_klass
);
BasicType
dest
=
java_lang_Class
::
as_BasicType
(
chain
().
adapter_arg_oop
(),
&
dest_klass
);
assert
(
dest
==
T_OBJECT
,
""
);
assert
(
dest
==
T_OBJECT
,
""
);
assert
(
dest
==
arg_state
->
_type
,
""
);
ArgToken
arg
=
_outgoing
.
at
(
arg_slot
);
ArgToken
arg
=
arg_state
->
_arg
;
assert
(
dest
==
arg
.
basic_type
(),
""
)
;
ArgToken
new_arg
=
make_conversion
(
T_OBJECT
,
dest_klass
,
Bytecodes
::
_checkcast
,
arg
,
CHECK_
(
empty
));
ArgToken
new_arg
=
make_conversion
(
T_OBJECT
,
dest_klass
,
Bytecodes
::
_checkcast
,
arg
,
CHECK_
(
empty
));
assert
(
!
arg
.
has_index
()
||
arg
.
index
()
==
new_arg
.
index
(),
"should be the same index"
);
assert
(
!
arg
.
has_index
()
||
arg
.
index
()
==
new_arg
.
index
(),
"should be the same index"
);
debug_only
(
dest_klass
=
(
klassOop
)
badOop
);
debug_only
(
dest_klass
=
(
klassOop
)
badOop
);
...
@@ -274,8 +424,8 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -274,8 +424,8 @@ MethodHandleWalker::walk(TRAPS) {
// i2l, etc., on the Nth outgoing argument in place
// i2l, etc., on the Nth outgoing argument in place
BasicType
src
=
chain
().
adapter_conversion_src_type
(),
BasicType
src
=
chain
().
adapter_conversion_src_type
(),
dest
=
chain
().
adapter_conversion_dest_type
();
dest
=
chain
().
adapter_conversion_dest_type
();
ArgToken
arg
=
_outgoing
.
at
(
arg_slot
);
Bytecodes
::
Code
bc
=
conversion_code
(
src
,
dest
);
Bytecodes
::
Code
bc
=
conversion_code
(
src
,
dest
);
ArgToken
arg
=
arg_state
->
_arg
;
if
(
bc
==
Bytecodes
::
_nop
)
{
if
(
bc
==
Bytecodes
::
_nop
)
{
break
;
break
;
}
else
if
(
bc
!=
Bytecodes
::
_illegal
)
{
}
else
if
(
bc
!=
Bytecodes
::
_illegal
)
{
...
@@ -289,7 +439,7 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -289,7 +439,7 @@ MethodHandleWalker::walk(TRAPS) {
}
}
}
}
if
(
bc
==
Bytecodes
::
_illegal
)
{
if
(
bc
==
Bytecodes
::
_illegal
)
{
lose
(
"bad primitive conversion"
,
CHECK_
(
empty
));
lose
(
err_msg
(
"bad primitive conversion for %s -> %s"
,
type2name
(
src
),
type2name
(
dest
))
,
CHECK_
(
empty
));
}
}
change_argument
(
src
,
arg_slot
,
dest
,
arg
);
change_argument
(
src
,
arg_slot
,
dest
,
arg
);
break
;
break
;
...
@@ -298,7 +448,7 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -298,7 +448,7 @@ MethodHandleWalker::walk(TRAPS) {
case
java_lang_invoke_AdapterMethodHandle
::
OP_REF_TO_PRIM
:
{
case
java_lang_invoke_AdapterMethodHandle
::
OP_REF_TO_PRIM
:
{
// checkcast to wrapper type & call intValue, etc.
// checkcast to wrapper type & call intValue, etc.
BasicType
dest
=
chain
().
adapter_conversion_dest_type
();
BasicType
dest
=
chain
().
adapter_conversion_dest_type
();
ArgToken
arg
=
arg_state
->
_arg
;
ArgToken
arg
=
_outgoing
.
at
(
arg_slot
)
;
arg
=
make_conversion
(
T_OBJECT
,
SystemDictionary
::
box_klass
(
dest
),
arg
=
make_conversion
(
T_OBJECT
,
SystemDictionary
::
box_klass
(
dest
),
Bytecodes
::
_checkcast
,
arg
,
CHECK_
(
empty
));
Bytecodes
::
_checkcast
,
arg
,
CHECK_
(
empty
));
vmIntrinsics
::
ID
unboxer
=
vmIntrinsics
::
for_unboxing
(
dest
);
vmIntrinsics
::
ID
unboxer
=
vmIntrinsics
::
for_unboxing
(
dest
);
...
@@ -316,11 +466,11 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -316,11 +466,11 @@ MethodHandleWalker::walk(TRAPS) {
case
java_lang_invoke_AdapterMethodHandle
::
OP_PRIM_TO_REF
:
{
case
java_lang_invoke_AdapterMethodHandle
::
OP_PRIM_TO_REF
:
{
// call wrapper type.valueOf
// call wrapper type.valueOf
BasicType
src
=
chain
().
adapter_conversion_src_type
();
BasicType
src
=
chain
().
adapter_conversion_src_type
();
ArgToken
arg
=
arg_state
->
_arg
;
vmIntrinsics
::
ID
boxer
=
vmIntrinsics
::
for_boxing
(
src
);
vmIntrinsics
::
ID
boxer
=
vmIntrinsics
::
for_boxing
(
src
);
if
(
boxer
==
vmIntrinsics
::
_none
)
{
if
(
boxer
==
vmIntrinsics
::
_none
)
{
lose
(
"no boxing method"
,
CHECK_
(
empty
));
lose
(
"no boxing method"
,
CHECK_
(
empty
));
}
}
ArgToken
arg
=
_outgoing
.
at
(
arg_slot
);
ArgToken
arglist
[
2
];
ArgToken
arglist
[
2
];
arglist
[
0
]
=
arg
;
// outgoing value
arglist
[
0
]
=
arg
;
// outgoing value
arglist
[
1
]
=
ArgToken
();
// sentinel
arglist
[
1
]
=
ArgToken
();
// sentinel
...
@@ -331,40 +481,45 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -331,40 +481,45 @@ MethodHandleWalker::walk(TRAPS) {
case
java_lang_invoke_AdapterMethodHandle
::
OP_SWAP_ARGS
:
{
case
java_lang_invoke_AdapterMethodHandle
::
OP_SWAP_ARGS
:
{
int
dest_arg_slot
=
chain
().
adapter_conversion_vminfo
();
int
dest_arg_slot
=
chain
().
adapter_conversion_vminfo
();
if
(
!
slot_
has_argument
(
dest_arg_slot
))
{
if
(
!
has_argument
(
dest_arg_slot
))
{
lose
(
"bad swap index"
,
CHECK_
(
empty
));
lose
(
"bad swap index"
,
CHECK_
(
empty
));
}
}
// a simple swap between two arguments
// a simple swap between two arguments
SlotState
*
dest_arg_state
=
slot_state
(
dest_arg_slot
);
if
(
arg_slot
>
dest_arg_slot
)
{
SlotState
temp
=
(
*
dest_arg_state
);
int
tmp
=
arg_slot
;
(
*
dest_arg_state
)
=
(
*
arg_state
);
arg_slot
=
dest_arg_slot
;
(
*
arg_state
)
=
temp
;
dest_arg_slot
=
tmp
;
}
ArgToken
a1
=
_outgoing
.
at
(
arg_slot
);
ArgToken
a2
=
_outgoing
.
at
(
dest_arg_slot
);
change_argument
(
a2
.
basic_type
(),
dest_arg_slot
,
a1
);
change_argument
(
a1
.
basic_type
(),
arg_slot
,
a2
);
break
;
break
;
}
}
case
java_lang_invoke_AdapterMethodHandle
::
OP_ROT_ARGS
:
{
case
java_lang_invoke_AdapterMethodHandle
::
OP_ROT_ARGS
:
{
int
dest_arg_slot
=
chain
().
adapter_conversion_vminfo
();
int
dest_arg_slot
=
chain
().
adapter_conversion_vminfo
();
if
(
!
slot_
has_argument
(
dest_arg_slot
)
||
arg_slot
==
dest_arg_slot
)
{
if
(
!
has_argument
(
dest_arg_slot
)
||
arg_slot
==
dest_arg_slot
)
{
lose
(
"bad rotate index"
,
CHECK_
(
empty
));
lose
(
"bad rotate index"
,
CHECK_
(
empty
));
}
}
SlotState
*
dest_arg_state
=
slot_state
(
dest_arg_slot
);
// Rotate the source argument (plus following N slots) into the
// Rotate the source argument (plus following N slots) into the
// position occupied by the dest argument (plus following N slots).
// position occupied by the dest argument (plus following N slots).
int
rotate_count
=
type2size
[
dest_arg_state
->
_type
];
int
rotate_count
=
type2size
[
chain
().
adapter_conversion_src_type
()
];
// (no other rotate counts are currently supported)
// (no other rotate counts are currently supported)
if
(
arg_slot
<
dest_arg_slot
)
{
if
(
arg_slot
<
dest_arg_slot
)
{
for
(
int
i
=
0
;
i
<
rotate_count
;
i
++
)
{
for
(
int
i
=
0
;
i
<
rotate_count
;
i
++
)
{
SlotState
temp
=
_outgoing
.
at
(
arg_slot
);
ArgToken
temp
=
_outgoing
.
at
(
arg_slot
);
_outgoing
.
remove_at
(
arg_slot
);
_outgoing
.
remove_at
(
arg_slot
);
_outgoing
.
insert_before
(
dest_arg_slot
+
rotate_count
-
1
,
temp
);
_outgoing
.
insert_before
(
dest_arg_slot
+
rotate_count
-
1
,
temp
);
}
}
}
else
{
// arg_slot > dest_arg_slot
}
else
{
// arg_slot > dest_arg_slot
for
(
int
i
=
0
;
i
<
rotate_count
;
i
++
)
{
for
(
int
i
=
0
;
i
<
rotate_count
;
i
++
)
{
SlotState
temp
=
_outgoing
.
at
(
arg_slot
+
rotate_count
-
1
);
ArgToken
temp
=
_outgoing
.
at
(
arg_slot
+
rotate_count
-
1
);
_outgoing
.
remove_at
(
arg_slot
+
rotate_count
-
1
);
_outgoing
.
remove_at
(
arg_slot
+
rotate_count
-
1
);
_outgoing
.
insert_before
(
dest_arg_slot
,
temp
);
_outgoing
.
insert_before
(
dest_arg_slot
,
temp
);
}
}
}
}
assert
(
_outgoing_argc
==
argument_count_slow
(),
"empty slots under control"
);
break
;
break
;
}
}
...
@@ -374,11 +529,11 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -374,11 +529,11 @@ MethodHandleWalker::walk(TRAPS) {
lose
(
"bad dup count"
,
CHECK_
(
empty
));
lose
(
"bad dup count"
,
CHECK_
(
empty
));
}
}
for
(
int
i
=
0
;
i
<
dup_slots
;
i
++
)
{
for
(
int
i
=
0
;
i
<
dup_slots
;
i
++
)
{
SlotState
*
dup
=
slot_state
(
arg_slot
+
2
*
i
);
ArgToken
dup
=
_outgoing
.
at
(
arg_slot
+
2
*
i
);
if
(
dup
==
NULL
)
break
;
// safety net
if
(
dup
.
basic_type
()
!=
T_VOID
)
_outgoing_argc
+=
1
;
if
(
dup
->
_type
!=
T_VOID
)
_outgoing_argc
+=
1
;
_outgoing
.
insert_before
(
i
,
dup
);
_outgoing
.
insert_before
(
i
,
(
*
dup
));
}
}
assert
(
_outgoing_argc
==
argument_count_slow
(),
"empty slots under control"
);
break
;
break
;
}
}
...
@@ -388,11 +543,11 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -388,11 +543,11 @@ MethodHandleWalker::walk(TRAPS) {
lose
(
"bad drop count"
,
CHECK_
(
empty
));
lose
(
"bad drop count"
,
CHECK_
(
empty
));
}
}
for
(
int
i
=
0
;
i
<
drop_slots
;
i
++
)
{
for
(
int
i
=
0
;
i
<
drop_slots
;
i
++
)
{
SlotState
*
drop
=
slot_state
(
arg_slot
);
ArgToken
drop
=
_outgoing
.
at
(
arg_slot
);
if
(
drop
==
NULL
)
break
;
// safety net
if
(
drop
.
basic_type
()
!=
T_VOID
)
_outgoing_argc
-=
1
;
if
(
drop
->
_type
!=
T_VOID
)
_outgoing_argc
-=
1
;
_outgoing
.
remove_at
(
arg_slot
);
_outgoing
.
remove_at
(
arg_slot
);
}
}
assert
(
_outgoing_argc
==
argument_count_slow
(),
"empty slots under control"
);
break
;
break
;
}
}
...
@@ -415,10 +570,10 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -415,10 +570,10 @@ MethodHandleWalker::walk(TRAPS) {
lose
(
"bad fold/collect arg slot"
,
CHECK_
(
empty
));
lose
(
"bad fold/collect arg slot"
,
CHECK_
(
empty
));
}
}
for
(
int
i
=
0
,
slot
=
arg_slot
+
coll_slots
-
1
;
slot
>=
arg_slot
;
slot
--
)
{
for
(
int
i
=
0
,
slot
=
arg_slot
+
coll_slots
-
1
;
slot
>=
arg_slot
;
slot
--
)
{
SlotState
*
arg_state
=
slot_state
(
slot
);
ArgToken
arg_state
=
_outgoing
.
at
(
slot
);
BasicType
arg_type
=
arg_state
->
_type
;
BasicType
arg_type
=
arg_state
.
basic_type
()
;
if
(
arg_type
==
T_VOID
)
continue
;
if
(
arg_type
==
T_VOID
)
continue
;
ArgToken
arg
=
_outgoing
.
at
(
slot
)
.
_arg
;
ArgToken
arg
=
_outgoing
.
at
(
slot
);
if
(
i
>=
argc
)
{
lose
(
"bad fold/collect arg"
,
CHECK_
(
empty
));
}
if
(
i
>=
argc
)
{
lose
(
"bad fold/collect arg"
,
CHECK_
(
empty
));
}
arglist
[
1
+
i
]
=
arg
;
arglist
[
1
+
i
]
=
arg
;
if
(
!
retain_original_args
)
if
(
!
retain_original_args
)
...
@@ -466,8 +621,9 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -466,8 +621,9 @@ MethodHandleWalker::walk(TRAPS) {
debug_only
(
element_klass_oop
=
(
klassOop
)
badOop
);
debug_only
(
element_klass_oop
=
(
klassOop
)
badOop
);
// Fetch the argument, which we will cast to the required array type.
// Fetch the argument, which we will cast to the required array type.
assert
(
arg_state
->
_type
==
T_OBJECT
,
""
);
ArgToken
arg
=
_outgoing
.
at
(
arg_slot
);
ArgToken
array_arg
=
arg_state
->
_arg
;
assert
(
arg
.
basic_type
()
==
T_OBJECT
,
""
);
ArgToken
array_arg
=
arg
;
array_arg
=
make_conversion
(
T_OBJECT
,
array_klass
(),
Bytecodes
::
_checkcast
,
array_arg
,
CHECK_
(
empty
));
array_arg
=
make_conversion
(
T_OBJECT
,
array_klass
(),
Bytecodes
::
_checkcast
,
array_arg
,
CHECK_
(
empty
));
change_argument
(
T_OBJECT
,
arg_slot
,
T_VOID
,
ArgToken
(
tt_void
));
change_argument
(
T_OBJECT
,
arg_slot
,
T_VOID
,
ArgToken
(
tt_void
));
...
@@ -534,10 +690,10 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -534,10 +690,10 @@ MethodHandleWalker::walk(TRAPS) {
}
else
{
}
else
{
jvalue
arg_value
;
jvalue
arg_value
;
BasicType
bt
=
java_lang_boxing_object
::
get_value
(
arg_oop
,
&
arg_value
);
BasicType
bt
=
java_lang_boxing_object
::
get_value
(
arg_oop
,
&
arg_value
);
if
(
bt
==
arg_type
)
{
if
(
bt
==
arg_type
||
(
bt
==
T_INT
&&
is_subword_type
(
arg_type
))
)
{
arg
=
make_prim_constant
(
arg_type
,
&
arg_value
,
CHECK_
(
empty
));
arg
=
make_prim_constant
(
arg_type
,
&
arg_value
,
CHECK_
(
empty
));
}
else
{
}
else
{
lose
(
"bad bound value"
,
CHECK_
(
empty
));
lose
(
err_msg
(
"bad bound value: arg_type %s boxing %s"
,
type2name
(
arg_type
),
type2name
(
bt
))
,
CHECK_
(
empty
));
}
}
}
}
DEBUG_ONLY
(
arg_oop
=
badOop
);
DEBUG_ONLY
(
arg_oop
=
badOop
);
...
@@ -557,9 +713,9 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -557,9 +713,9 @@ MethodHandleWalker::walk(TRAPS) {
ArgToken
*
arglist
=
NEW_RESOURCE_ARRAY
(
ArgToken
,
_outgoing
.
length
()
+
1
);
ArgToken
*
arglist
=
NEW_RESOURCE_ARRAY
(
ArgToken
,
_outgoing
.
length
()
+
1
);
int
ap
=
0
;
int
ap
=
0
;
for
(
int
i
=
_outgoing
.
length
()
-
1
;
i
>=
0
;
i
--
)
{
for
(
int
i
=
_outgoing
.
length
()
-
1
;
i
>=
0
;
i
--
)
{
SlotState
*
arg_state
=
slot_state
(
i
);
ArgToken
arg_state
=
_outgoing
.
at
(
i
);
if
(
arg_state
->
_type
==
T_VOID
)
continue
;
if
(
arg_state
.
basic_type
()
==
T_VOID
)
continue
;
arglist
[
ap
++
]
=
_outgoing
.
at
(
i
)
.
_arg
;
arglist
[
ap
++
]
=
_outgoing
.
at
(
i
);
}
}
assert
(
ap
==
_outgoing_argc
,
""
);
assert
(
ap
==
_outgoing_argc
,
""
);
arglist
[
ap
]
=
ArgToken
();
// add a sentinel, for the sake of asserts
arglist
[
ap
]
=
ArgToken
();
// add a sentinel, for the sake of asserts
...
@@ -579,7 +735,7 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
...
@@ -579,7 +735,7 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
_outgoing_argc
=
nptypes
;
_outgoing_argc
=
nptypes
;
int
argp
=
nptypes
-
1
;
int
argp
=
nptypes
-
1
;
if
(
argp
>=
0
)
{
if
(
argp
>=
0
)
{
_outgoing
.
at_grow
(
argp
,
make_state
(
T_VOID
,
ArgToken
(
tt_void
)
));
// presize
_outgoing
.
at_grow
(
argp
,
ArgToken
(
tt_void
));
// presize
}
}
for
(
int
i
=
0
;
i
<
nptypes
;
i
++
)
{
for
(
int
i
=
0
;
i
<
nptypes
;
i
++
)
{
klassOop
arg_type_klass
=
NULL
;
klassOop
arg_type_klass
=
NULL
;
...
@@ -587,10 +743,10 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
...
@@ -587,10 +743,10 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
int
index
=
new_local_index
(
arg_type
);
int
index
=
new_local_index
(
arg_type
);
ArgToken
arg
=
make_parameter
(
arg_type
,
arg_type_klass
,
index
,
CHECK
);
ArgToken
arg
=
make_parameter
(
arg_type
,
arg_type_klass
,
index
,
CHECK
);
DEBUG_ONLY
(
arg_type_klass
=
(
klassOop
)
NULL
);
DEBUG_ONLY
(
arg_type_klass
=
(
klassOop
)
NULL
);
_outgoing
.
at_put
(
argp
,
make_state
(
arg_type
,
arg
)
);
_outgoing
.
at_put
(
argp
,
arg
);
if
(
type2size
[
arg_type
]
==
2
)
{
if
(
type2size
[
arg_type
]
==
2
)
{
// add the extra slot, so we can model the JVM stack
// add the extra slot, so we can model the JVM stack
_outgoing
.
insert_before
(
argp
+
1
,
make_state
(
T_VOID
,
ArgToken
(
tt_void
)
));
_outgoing
.
insert_before
(
argp
+
1
,
ArgToken
(
tt_void
));
}
}
--
argp
;
--
argp
;
}
}
...
@@ -599,7 +755,29 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
...
@@ -599,7 +755,29 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
BasicType
ret_type
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
rtype
(
mtype
()),
&
ret_type_klass
);
BasicType
ret_type
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
rtype
(
mtype
()),
&
ret_type_klass
);
ArgToken
ret
=
make_parameter
(
ret_type
,
ret_type_klass
,
-
1
,
CHECK
);
ArgToken
ret
=
make_parameter
(
ret_type
,
ret_type_klass
,
-
1
,
CHECK
);
// ignore ret; client can catch it if needed
// ignore ret; client can catch it if needed
assert
(
_outgoing_argc
==
argument_count_slow
(),
"empty slots under control"
);
verify_args_and_signature
(
CHECK
);
}
#ifdef ASSERT
void
MethodHandleWalker
::
verify_args_and_signature
(
TRAPS
)
{
int
index
=
_outgoing
.
length
()
-
1
;
objArrayOop
ptypes
=
java_lang_invoke_MethodType
::
ptypes
(
chain
().
method_type_oop
());
for
(
int
i
=
0
,
limit
=
ptypes
->
length
();
i
<
limit
;
i
++
)
{
BasicType
t
=
java_lang_Class
::
as_BasicType
(
ptypes
->
obj_at
(
i
));
if
(
t
==
T_ARRAY
)
t
=
T_OBJECT
;
if
(
t
==
T_LONG
||
t
==
T_DOUBLE
)
{
assert
(
T_VOID
==
_outgoing
.
at
(
index
).
basic_type
(),
"types must match"
);
index
--
;
}
assert
(
t
==
_outgoing
.
at
(
index
).
basic_type
(),
"types must match"
);
index
--
;
}
}
}
#endif
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
...
@@ -607,30 +785,31 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
...
@@ -607,30 +785,31 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
//
//
// This is messy because some kinds of arguments are paired with
// This is messy because some kinds of arguments are paired with
// companion slots containing an empty value.
// companion slots containing an empty value.
void
MethodHandleWalker
::
change_argument
(
BasicType
old_type
,
int
slot
,
BasicType
new_type
,
void
MethodHandleWalker
::
change_argument
(
BasicType
old_type
,
int
slot
,
const
ArgToken
&
new_arg
)
{
const
ArgToken
&
new_arg
)
{
BasicType
new_type
=
new_arg
.
basic_type
();
int
old_size
=
type2size
[
old_type
];
int
old_size
=
type2size
[
old_type
];
int
new_size
=
type2size
[
new_type
];
int
new_size
=
type2size
[
new_type
];
if
(
old_size
==
new_size
)
{
if
(
old_size
==
new_size
)
{
// simple case first
// simple case first
_outgoing
.
at_put
(
slot
,
make_state
(
new_type
,
new_arg
)
);
_outgoing
.
at_put
(
slot
,
new_arg
);
}
else
if
(
old_size
>
new_size
)
{
}
else
if
(
old_size
>
new_size
)
{
for
(
int
i
=
old_size
-
1
;
i
>=
new_size
;
i
--
)
{
for
(
int
i
=
old_size
-
1
;
i
>=
new_size
;
i
--
)
{
assert
((
i
!=
0
)
==
(
_outgoing
.
at
(
slot
+
i
).
_type
==
T_VOID
),
""
);
assert
((
i
!=
0
)
==
(
_outgoing
.
at
(
slot
+
i
).
basic_type
()
==
T_VOID
),
""
);
_outgoing
.
remove_at
(
slot
+
i
);
_outgoing
.
remove_at
(
slot
+
i
);
}
}
if
(
new_size
>
0
)
if
(
new_size
>
0
)
_outgoing
.
at_put
(
slot
,
make_state
(
new_type
,
new_arg
)
);
_outgoing
.
at_put
(
slot
,
new_arg
);
else
else
_outgoing_argc
-=
1
;
// deleted a real argument
_outgoing_argc
-=
1
;
// deleted a real argument
}
else
{
}
else
{
for
(
int
i
=
old_size
;
i
<
new_size
;
i
++
)
{
for
(
int
i
=
old_size
;
i
<
new_size
;
i
++
)
{
_outgoing
.
insert_before
(
slot
+
i
,
make_state
(
T_VOID
,
ArgToken
(
tt_void
)
));
_outgoing
.
insert_before
(
slot
+
i
,
ArgToken
(
tt_void
));
}
}
_outgoing
.
at_put
(
slot
,
make_state
(
new_type
,
new_arg
)
);
_outgoing
.
at_put
(
slot
,
new_arg
);
if
(
old_size
==
0
)
if
(
old_size
==
0
)
_outgoing_argc
+=
1
;
// inserted a real argument
_outgoing_argc
+=
1
;
// inserted a real argument
}
}
assert
(
_outgoing_argc
==
argument_count_slow
(),
"empty slots under control"
);
}
}
...
@@ -638,8 +817,15 @@ void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType
...
@@ -638,8 +817,15 @@ void MethodHandleWalker::change_argument(BasicType old_type, int slot, BasicType
int
MethodHandleWalker
::
argument_count_slow
()
{
int
MethodHandleWalker
::
argument_count_slow
()
{
int
args_seen
=
0
;
int
args_seen
=
0
;
for
(
int
i
=
_outgoing
.
length
()
-
1
;
i
>=
0
;
i
--
)
{
for
(
int
i
=
_outgoing
.
length
()
-
1
;
i
>=
0
;
i
--
)
{
if
(
_outgoing
.
at
(
i
).
_type
!=
T_VOID
)
{
if
(
_outgoing
.
at
(
i
).
basic_type
()
!=
T_VOID
)
{
++
args_seen
;
++
args_seen
;
if
(
_outgoing
.
at
(
i
).
basic_type
()
==
T_LONG
||
_outgoing
.
at
(
i
).
basic_type
()
==
T_DOUBLE
)
{
assert
(
_outgoing
.
at
(
i
+
1
).
basic_type
()
==
T_VOID
,
"should only follow two word"
);
}
}
else
{
assert
(
_outgoing
.
at
(
i
-
1
).
basic_type
()
==
T_LONG
||
_outgoing
.
at
(
i
-
1
).
basic_type
()
==
T_DOUBLE
,
"should only follow two word"
);
}
}
}
}
return
args_seen
;
return
args_seen
;
...
@@ -663,7 +849,7 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo
...
@@ -663,7 +849,7 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo
ArgToken
arglist
[
2
];
ArgToken
arglist
[
2
];
if
(
!
for_return
)
{
if
(
!
for_return
)
{
// argument type conversion
// argument type conversion
ArgToken
arg
=
_outgoing
.
at
(
slot
)
.
_arg
;
ArgToken
arg
=
_outgoing
.
at
(
slot
);
assert
(
arg
.
token_type
()
>=
tt_symbolic
||
src
==
arg
.
basic_type
(),
"sanity"
);
assert
(
arg
.
token_type
()
>=
tt_symbolic
||
src
==
arg
.
basic_type
(),
"sanity"
);
arglist
[
0
]
=
arg
;
// outgoing 'this'
arglist
[
0
]
=
arg
;
// outgoing 'this'
arglist
[
1
]
=
ArgToken
();
// sentinel
arglist
[
1
]
=
ArgToken
();
// sentinel
...
@@ -683,7 +869,7 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo
...
@@ -683,7 +869,7 @@ void MethodHandleWalker::retype_raw_conversion(BasicType src, BasicType dst, boo
// ref-to-prim: discard ref, push zero
// ref-to-prim: discard ref, push zero
lose
(
"requested ref-to-prim conversion not expected"
,
CHECK
);
lose
(
"requested ref-to-prim conversion not expected"
,
CHECK
);
}
else
{
}
else
{
lose
(
"requested raw conversion not allowed"
,
CHECK
);
lose
(
err_msg
(
"requested raw conversion not allowed: %s -> %s"
,
type2name
(
src
),
type2name
(
dst
))
,
CHECK
);
}
}
}
}
}
}
...
@@ -963,6 +1149,7 @@ void MethodHandleCompiler::emit_store(BasicType bt, int index) {
...
@@ -963,6 +1149,7 @@ void MethodHandleCompiler::emit_store(BasicType bt, int index) {
void
MethodHandleCompiler
::
emit_load_constant
(
ArgToken
arg
)
{
void
MethodHandleCompiler
::
emit_load_constant
(
ArgToken
arg
)
{
BasicType
bt
=
arg
.
basic_type
();
BasicType
bt
=
arg
.
basic_type
();
if
(
is_subword_type
(
bt
))
bt
=
T_INT
;
switch
(
bt
)
{
switch
(
bt
)
{
case
T_INT
:
{
case
T_INT
:
{
jint
value
=
arg
.
get_jint
();
jint
value
=
arg
.
get_jint
();
...
@@ -1066,11 +1253,15 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co
...
@@ -1066,11 +1253,15 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co
emit_store
(
srctype
,
index
);
emit_store
(
srctype
,
index
);
break
;
break
;
case
Bytecodes
::
_nop
:
// nothing to do
return
src
;
default:
default:
if
(
op
==
Bytecodes
::
_illegal
)
if
(
op
==
Bytecodes
::
_illegal
)
lose
(
"no such primitive conversion"
,
THREAD
);
lose
(
err_msg
(
"no such primitive conversion: %s -> %s"
,
type2name
(
src
.
basic_type
()),
type2name
(
type
))
,
THREAD
);
else
else
lose
(
"bad primitive conversion op"
,
THREAD
);
lose
(
err_msg
(
"bad primitive conversion op: %s"
,
Bytecodes
::
name
(
op
))
,
THREAD
);
return
make_prim_constant
(
type
,
&
zero_jvalue
,
THREAD
);
return
make_prim_constant
(
type
,
&
zero_jvalue
,
THREAD
);
}
}
...
@@ -1300,7 +1491,7 @@ int MethodHandleCompiler::cpool_primitive_put(BasicType bt, jvalue* con) {
...
@@ -1300,7 +1491,7 @@ int MethodHandleCompiler::cpool_primitive_put(BasicType bt, jvalue* con) {
// for (int i = 1, imax = _constants.length(); i < imax; i++) {
// for (int i = 1, imax = _constants.length(); i < imax; i++) {
// ConstantValue* con = _constants.at(i);
// ConstantValue* con = _constants.at(i);
// if (con != NULL && con->is_primitive() && con
->_type
== bt) {
// if (con != NULL && con->is_primitive() && con
.basic_type()
== bt) {
// bool match = false;
// bool match = false;
// switch (type2size[bt]) {
// switch (type2size[bt]) {
// case 1: if (pcon->_value.i == con->i) match = true; break;
// case 1: if (pcon->_value.i == con->i) match = true; break;
...
@@ -1451,8 +1642,8 @@ private:
...
@@ -1451,8 +1642,8 @@ private:
_strbuf
.
reset
();
_strbuf
.
reset
();
return
s
;
return
s
;
}
}
ArgToken
token
(
const
char
*
str
)
{
ArgToken
token
(
const
char
*
str
,
BasicType
type
)
{
return
ArgToken
(
str
);
return
ArgToken
(
str
,
type
);
}
}
const
char
*
string
(
ArgToken
token
)
{
const
char
*
string
(
ArgToken
token
)
{
return
token
.
str
();
return
token
.
str
();
...
@@ -1474,12 +1665,12 @@ private:
...
@@ -1474,12 +1665,12 @@ private:
}
}
ArgToken
maybe_make_temp
(
const
char
*
statement_op
,
BasicType
type
,
const
char
*
temp_name
)
{
ArgToken
maybe_make_temp
(
const
char
*
statement_op
,
BasicType
type
,
const
char
*
temp_name
)
{
const
char
*
value
=
strbuf
();
const
char
*
value
=
strbuf
();
if
(
!
_verbose
)
return
token
(
value
);
if
(
!
_verbose
)
return
token
(
value
,
type
);
// make an explicit binding for each separate value
// make an explicit binding for each separate value
_strbuf
.
print
(
"%s%d"
,
temp_name
,
++
_temp_num
);
_strbuf
.
print
(
"%s%d"
,
temp_name
,
++
_temp_num
);
const
char
*
temp
=
strbuf
();
const
char
*
temp
=
strbuf
();
_out
->
print
(
"
\n
%s %s %s = %s;"
,
statement_op
,
type2name
(
type
),
temp
,
value
);
_out
->
print
(
"
\n
%s %s %s = %s;"
,
statement_op
,
type2name
(
type
),
temp
,
value
);
return
token
(
temp
);
return
token
(
temp
,
type
);
}
}
public:
public:
...
@@ -1495,7 +1686,7 @@ public:
...
@@ -1495,7 +1686,7 @@ public:
virtual
ArgToken
make_parameter
(
BasicType
type
,
klassOop
tk
,
int
argnum
,
TRAPS
)
{
virtual
ArgToken
make_parameter
(
BasicType
type
,
klassOop
tk
,
int
argnum
,
TRAPS
)
{
if
(
argnum
<
0
)
{
if
(
argnum
<
0
)
{
end_params
();
end_params
();
return
token
(
"return"
);
return
token
(
"return"
,
type
);
}
}
if
((
_param_state
&
1
)
==
0
)
{
if
((
_param_state
&
1
)
==
0
)
{
_param_state
|=
1
;
_param_state
|=
1
;
...
@@ -1510,7 +1701,7 @@ public:
...
@@ -1510,7 +1701,7 @@ public:
const
char
*
arg
=
strbuf
();
const
char
*
arg
=
strbuf
();
put_type_name
(
type
,
tk
,
_out
);
put_type_name
(
type
,
tk
,
_out
);
_out
->
print
(
" %s"
,
arg
);
_out
->
print
(
" %s"
,
arg
);
return
token
(
arg
);
return
token
(
arg
,
type
);
}
}
virtual
ArgToken
make_oop_constant
(
oop
con
,
TRAPS
)
{
virtual
ArgToken
make_oop_constant
(
oop
con
,
TRAPS
)
{
if
(
con
==
NULL
)
if
(
con
==
NULL
)
...
@@ -1597,7 +1788,7 @@ public:
...
@@ -1597,7 +1788,7 @@ public:
out
->
print
(
"
\n
"
);
out
->
print
(
"
\n
"
);
}
}
static
void
print
(
Handle
root
,
bool
verbose
=
Verbose
,
outputStream
*
out
=
tty
)
{
static
void
print
(
Handle
root
,
bool
verbose
=
Verbose
,
outputStream
*
out
=
tty
)
{
EXCEPTION_MARK
;
Thread
*
THREAD
=
Thread
::
current
()
;
ResourceMark
rm
;
ResourceMark
rm
;
MethodHandlePrinter
printer
(
root
,
verbose
,
out
,
THREAD
);
MethodHandlePrinter
printer
(
root
,
verbose
,
out
,
THREAD
);
if
(
!
HAS_PENDING_EXCEPTION
)
if
(
!
HAS_PENDING_EXCEPTION
)
...
...
src/share/vm/prims/methodHandleWalk.hpp
浏览文件 @
730a6a98
...
@@ -56,6 +56,10 @@ private:
...
@@ -56,6 +56,10 @@ private:
int
BoundMethodHandle_vmargslot
()
{
return
java_lang_invoke_BoundMethodHandle
::
vmargslot
(
method_handle_oop
());
}
int
BoundMethodHandle_vmargslot
()
{
return
java_lang_invoke_BoundMethodHandle
::
vmargslot
(
method_handle_oop
());
}
int
AdapterMethodHandle_conversion
()
{
return
java_lang_invoke_AdapterMethodHandle
::
conversion
(
method_handle_oop
());
}
int
AdapterMethodHandle_conversion
()
{
return
java_lang_invoke_AdapterMethodHandle
::
conversion
(
method_handle_oop
());
}
#ifdef ASSERT
void
print_impl
(
TRAPS
);
#endif
public:
public:
MethodHandleChain
(
Handle
root
,
TRAPS
)
MethodHandleChain
(
Handle
root
,
TRAPS
)
:
_root
(
root
)
:
_root
(
root
)
...
@@ -99,6 +103,14 @@ public:
...
@@ -99,6 +103,14 @@ public:
void
lose
(
const
char
*
msg
,
TRAPS
);
void
lose
(
const
char
*
msg
,
TRAPS
);
const
char
*
lose_message
()
{
return
_lose_message
;
}
const
char
*
lose_message
()
{
return
_lose_message
;
}
#ifdef ASSERT
// Print a symbolic description of a method handle chain, including
// the signature for each method. The signatures are printed in
// slot order to make it easier to understand.
void
print
();
static
void
print
(
Handle
mh
);
#endif
};
};
...
@@ -126,7 +138,7 @@ public:
...
@@ -126,7 +138,7 @@ public:
Handle
_handle
;
Handle
_handle
;
public:
public:
ArgToken
(
TokenType
tt
=
tt_illegal
)
:
_tt
(
tt
)
{
ArgToken
(
TokenType
tt
=
tt_illegal
)
:
_tt
(
tt
)
,
_bt
(
tt
==
tt_void
?
T_VOID
:
T_ILLEGAL
)
{
assert
(
tt
==
tt_illegal
||
tt
==
tt_void
,
"invalid token type"
);
assert
(
tt
==
tt_illegal
||
tt
==
tt_void
,
"invalid token type"
);
}
}
...
@@ -135,11 +147,11 @@ public:
...
@@ -135,11 +147,11 @@ public:
_value
.
i
=
index
;
_value
.
i
=
index
;
}
}
ArgToken
(
BasicType
bt
,
jvalue
value
)
:
_tt
(
tt_constant
),
_bt
(
bt
),
_value
(
value
)
{}
ArgToken
(
BasicType
bt
,
jvalue
value
)
:
_tt
(
tt_constant
),
_bt
(
bt
),
_value
(
value
)
{
assert
(
_bt
!=
T_OBJECT
,
"wrong constructor"
);
}
ArgToken
(
BasicType
bt
,
Handle
value
)
:
_tt
(
tt_constant
),
_bt
(
bt
),
_handle
(
valu
e
)
{}
ArgToken
(
Handle
handle
)
:
_tt
(
tt_constant
),
_bt
(
T_OBJECT
),
_handle
(
handl
e
)
{}
ArgToken
(
const
char
*
str
)
:
_tt
(
tt_symbolic
),
_bt
(
T_LONG
)
{
ArgToken
(
const
char
*
str
,
BasicType
type
)
:
_tt
(
tt_symbolic
),
_bt
(
type
)
{
_value
.
j
=
(
intptr_t
)
str
;
_value
.
j
=
(
intptr_t
)
str
;
}
}
...
@@ -147,27 +159,15 @@ public:
...
@@ -147,27 +159,15 @@ public:
BasicType
basic_type
()
const
{
return
_bt
;
}
BasicType
basic_type
()
const
{
return
_bt
;
}
bool
has_index
()
const
{
return
_tt
==
tt_parameter
||
_tt
==
tt_temporary
;
}
bool
has_index
()
const
{
return
_tt
==
tt_parameter
||
_tt
==
tt_temporary
;
}
int
index
()
const
{
assert
(
has_index
(),
"must have index"
);;
return
_value
.
i
;
}
int
index
()
const
{
assert
(
has_index
(),
"must have index"
);;
return
_value
.
i
;
}
Handle
object
()
const
{
assert
(
_tt
==
tt_constant
,
"value type"
);
return
_handle
;
}
Handle
object
()
const
{
assert
(
_
bt
==
T_OBJECT
,
"wrong accessor"
);
assert
(
_
tt
==
tt_constant
,
"value type"
);
return
_handle
;
}
const
char
*
str
()
const
{
assert
(
_tt
==
tt_symbolic
,
"string type"
);
return
(
const
char
*
)
_value
.
j
;
}
const
char
*
str
()
const
{
assert
(
_tt
==
tt_symbolic
,
"string type"
);
return
(
const
char
*
)
(
intptr_t
)
_value
.
j
;
}
jint
get_jint
()
const
{
assert
(
_tt
==
tt_constant
,
"value types"
);
return
_value
.
i
;
}
jint
get_jint
()
const
{
assert
(
_
bt
==
T_INT
||
is_subword_type
(
_bt
),
"wrong accessor"
);
assert
(
_
tt
==
tt_constant
,
"value types"
);
return
_value
.
i
;
}
jlong
get_jlong
()
const
{
assert
(
_tt
==
tt_constant
,
"value types"
);
return
_value
.
j
;
}
jlong
get_jlong
()
const
{
assert
(
_
bt
==
T_LONG
,
"wrong accessor"
);
assert
(
_
tt
==
tt_constant
,
"value types"
);
return
_value
.
j
;
}
jfloat
get_jfloat
()
const
{
assert
(
_tt
==
tt_constant
,
"value types"
);
return
_value
.
f
;
}
jfloat
get_jfloat
()
const
{
assert
(
_
bt
==
T_FLOAT
,
"wrong accessor"
);
assert
(
_
tt
==
tt_constant
,
"value types"
);
return
_value
.
f
;
}
jdouble
get_jdouble
()
const
{
assert
(
_tt
==
tt_constant
,
"value types"
);
return
_value
.
d
;
}
jdouble
get_jdouble
()
const
{
assert
(
_
bt
==
T_DOUBLE
,
"wrong accessor"
);
assert
(
_
tt
==
tt_constant
,
"value types"
);
return
_value
.
d
;
}
};
};
// Abstract interpretation state:
struct
SlotState
{
BasicType
_type
;
ArgToken
_arg
;
SlotState
()
:
_type
(),
_arg
()
{}
};
static
SlotState
make_state
(
BasicType
type
,
ArgToken
arg
)
{
SlotState
ss
;
ss
.
_type
=
type
;
ss
.
_arg
=
arg
;
return
ss
;
}
private:
private:
MethodHandleChain
_chain
;
MethodHandleChain
_chain
;
bool
_for_invokedynamic
;
bool
_for_invokedynamic
;
...
@@ -177,33 +177,29 @@ private:
...
@@ -177,33 +177,29 @@ private:
// TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array.
// TOS is always _outgoing.at(0), so simple pushes and pops shift the whole _outgoing array.
// If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1).
// If there is a receiver in the current argument list, it is at _outgoing.at(_outgoing.length()-1).
// If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID.
// If a value at _outgoing.at(n) is T_LONG or T_DOUBLE, the value at _outgoing.at(n+1) is T_VOID.
GrowableArray
<
SlotState
>
_outgoing
;
// current outgoing parameter slots
GrowableArray
<
ArgToken
>
_outgoing
;
// current outgoing parameter slots
int
_outgoing_argc
;
// # non-empty outgoing slots
int
_outgoing_argc
;
// # non-empty outgoing slots
// Replace a value of type old_type at slot (and maybe slot+1) with the new value.
// Replace a value of type old_type at slot (and maybe slot+1) with the new value.
// If old_type != T_VOID, remove the old argument at that point.
// If old_type != T_VOID, remove the old argument at that point.
// If new_type != T_VOID, insert the new argument at that point.
// If new_type != T_VOID, insert the new argument at that point.
// Insert or delete a second empty slot as needed.
// Insert or delete a second empty slot as needed.
void
change_argument
(
BasicType
old_type
,
int
slot
,
BasicType
new_type
,
const
ArgToken
&
new_arg
);
void
change_argument
(
BasicType
old_type
,
int
slot
,
const
ArgToken
&
new_arg
);
void
change_argument
(
BasicType
old_type
,
int
slot
,
BasicType
type
,
const
ArgToken
&
new_arg
)
{
assert
(
type
==
new_arg
.
basic_type
(),
"must agree"
);
change_argument
(
old_type
,
slot
,
new_arg
);
}
// Raw retype conversions for OP_RAW_RETYPE.
// Raw retype conversions for OP_RAW_RETYPE.
void
retype_raw_conversion
(
BasicType
src
,
BasicType
dst
,
bool
for_return
,
int
slot
,
TRAPS
);
void
retype_raw_conversion
(
BasicType
src
,
BasicType
dst
,
bool
for_return
,
int
slot
,
TRAPS
);
void
retype_raw_argument_type
(
BasicType
src
,
BasicType
dst
,
int
slot
,
TRAPS
)
{
retype_raw_conversion
(
src
,
dst
,
false
,
slot
,
CHECK
);
}
void
retype_raw_argument_type
(
BasicType
src
,
BasicType
dst
,
int
slot
,
TRAPS
)
{
retype_raw_conversion
(
src
,
dst
,
false
,
slot
,
CHECK
);
}
void
retype_raw_return_type
(
BasicType
src
,
BasicType
dst
,
TRAPS
)
{
retype_raw_conversion
(
src
,
dst
,
true
,
-
1
,
CHECK
);
}
void
retype_raw_return_type
(
BasicType
src
,
BasicType
dst
,
TRAPS
)
{
retype_raw_conversion
(
src
,
dst
,
true
,
-
1
,
CHECK
);
}
SlotState
*
slot_state
(
int
slot
)
{
BasicType
arg_type
(
int
slot
)
{
if
(
slot
<
0
||
slot
>=
_outgoing
.
length
())
return
_outgoing
.
at
(
slot
).
basic_type
();
return
NULL
;
return
_outgoing
.
adr_at
(
slot
);
}
BasicType
slot_type
(
int
slot
)
{
SlotState
*
ss
=
slot_state
(
slot
);
if
(
ss
==
NULL
)
return
T_ILLEGAL
;
return
ss
->
_type
;
}
}
bool
slot_
has_argument
(
int
slot
)
{
bool
has_argument
(
int
slot
)
{
return
slot
_type
(
slot
)
<
T_VOID
;
return
arg
_type
(
slot
)
<
T_VOID
;
}
}
#ifdef ASSERT
#ifdef ASSERT
...
@@ -215,6 +211,8 @@ private:
...
@@ -215,6 +211,8 @@ private:
void
walk_incoming_state
(
TRAPS
);
void
walk_incoming_state
(
TRAPS
);
void
verify_args_and_signature
(
TRAPS
)
NOT_DEBUG_RETURN
;
public:
public:
MethodHandleWalker
(
Handle
root
,
bool
for_invokedynamic
,
TRAPS
)
MethodHandleWalker
(
Handle
root
,
bool
for_invokedynamic
,
TRAPS
)
:
_chain
(
root
,
THREAD
),
:
_chain
(
root
,
THREAD
),
...
@@ -421,7 +419,7 @@ private:
...
@@ -421,7 +419,7 @@ private:
}
}
virtual
ArgToken
make_oop_constant
(
oop
con
,
TRAPS
)
{
virtual
ArgToken
make_oop_constant
(
oop
con
,
TRAPS
)
{
Handle
h
(
THREAD
,
con
);
Handle
h
(
THREAD
,
con
);
return
ArgToken
(
T_OBJECT
,
h
);
return
ArgToken
(
h
);
}
}
virtual
ArgToken
make_prim_constant
(
BasicType
type
,
jvalue
*
con
,
TRAPS
)
{
virtual
ArgToken
make_prim_constant
(
BasicType
type
,
jvalue
*
con
,
TRAPS
)
{
return
ArgToken
(
type
,
*
con
);
return
ArgToken
(
type
,
*
con
);
...
...
src/share/vm/prims/methodHandles.cpp
浏览文件 @
730a6a98
...
@@ -1305,6 +1305,7 @@ void MethodHandles::verify_vmargslot(Handle mh, int argnum, int argslot, TRAPS)
...
@@ -1305,6 +1305,7 @@ void MethodHandles::verify_vmargslot(Handle mh, int argnum, int argslot, TRAPS)
// Verify that argslot points at the given argnum.
// Verify that argslot points at the given argnum.
int
check_slot
=
argument_slot
(
java_lang_invoke_MethodHandle
::
type
(
mh
()),
argnum
);
int
check_slot
=
argument_slot
(
java_lang_invoke_MethodHandle
::
type
(
mh
()),
argnum
);
if
(
argslot
!=
check_slot
||
argslot
<
0
)
{
if
(
argslot
!=
check_slot
||
argslot
<
0
)
{
ResourceMark
rm
;
const
char
*
fmt
=
"for argnum of %d, vmargslot is %d, should be %d"
;
const
char
*
fmt
=
"for argnum of %d, vmargslot is %d, should be %d"
;
size_t
msglen
=
strlen
(
fmt
)
+
3
*
11
+
1
;
size_t
msglen
=
strlen
(
fmt
)
+
3
*
11
+
1
;
char
*
msg
=
NEW_RESOURCE_ARRAY
(
char
,
msglen
);
char
*
msg
=
NEW_RESOURCE_ARRAY
(
char
,
msglen
);
...
@@ -1829,6 +1830,7 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum,
...
@@ -1829,6 +1830,7 @@ void MethodHandles::init_BoundMethodHandle(Handle mh, Handle target, int argnum,
bool
direct_to_method
=
false
;
bool
direct_to_method
=
false
;
if
(
OptimizeMethodHandles
&&
if
(
OptimizeMethodHandles
&&
target
->
klass
()
==
SystemDictionary
::
DirectMethodHandle_klass
()
&&
target
->
klass
()
==
SystemDictionary
::
DirectMethodHandle_klass
()
&&
(
argnum
!=
0
||
java_lang_invoke_BoundMethodHandle
::
argument
(
mh
())
!=
NULL
)
&&
(
argnum
==
0
||
java_lang_invoke_DirectMethodHandle
::
vmindex
(
target
())
<
0
))
{
(
argnum
==
0
||
java_lang_invoke_DirectMethodHandle
::
vmindex
(
target
())
<
0
))
{
KlassHandle
receiver_limit
;
int
decode_flags
=
0
;
KlassHandle
receiver_limit
;
int
decode_flags
=
0
;
methodHandle
m
=
decode_method
(
target
(),
receiver_limit
,
decode_flags
);
methodHandle
m
=
decode_method
(
target
(),
receiver_limit
,
decode_flags
);
...
@@ -1980,7 +1982,6 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
...
@@ -1980,7 +1982,6 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
err
=
"adapter requires src/dest conversion subfields for swap"
;
break
;
err
=
"adapter requires src/dest conversion subfields for swap"
;
break
;
}
}
int
swap_size
=
type2size
[
src
];
int
swap_size
=
type2size
[
src
];
int
slot_limit
=
java_lang_invoke_MethodHandle
::
vmslots
(
target
());
int
src_slot
=
argslot
;
int
src_slot
=
argslot
;
int
dest_slot
=
vminfo
;
int
dest_slot
=
vminfo
;
bool
rotate_up
=
(
src_slot
>
dest_slot
);
// upward rotation
bool
rotate_up
=
(
src_slot
>
dest_slot
);
// upward rotation
...
@@ -2333,7 +2334,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
...
@@ -2333,7 +2334,6 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
case
_adapter_rot_args
:
case
_adapter_rot_args
:
{
{
int
swap_slots
=
type2size
[
src
];
int
swap_slots
=
type2size
[
src
];
int
slot_limit
=
java_lang_invoke_AdapterMethodHandle
::
vmslots
(
mh
());
int
src_slot
=
argslot
;
int
src_slot
=
argslot
;
int
dest_slot
=
vminfo
;
int
dest_slot
=
vminfo
;
int
rotate
=
(
ek_orig
==
_adapter_swap_args
)
?
0
:
(
src_slot
>
dest_slot
)
?
1
:
-
1
;
int
rotate
=
(
ek_orig
==
_adapter_swap_args
)
?
0
:
(
src_slot
>
dest_slot
)
?
1
:
-
1
;
...
@@ -2661,14 +2661,14 @@ JVM_ENTRY(void, MHN_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh,
...
@@ -2661,14 +2661,14 @@ JVM_ENTRY(void, MHN_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh,
ResourceMark
rm
;
// for error messages
ResourceMark
rm
;
// for error messages
// This is the guy we are initializing:
// This is the guy we are initializing:
if
(
mh_jh
==
NULL
)
{
THROW
(
vmSymbols
::
java_lang_InternalError
()
);
}
if
(
mh_jh
==
NULL
)
{
THROW
_MSG
(
vmSymbols
::
java_lang_InternalError
(),
"self is null"
);
}
Handle
mh
(
THREAD
,
JNIHandles
::
resolve_non_null
(
mh_jh
));
Handle
mh
(
THREAD
,
JNIHandles
::
resolve_non_null
(
mh_jh
));
// Early returns out of this method leave the DMH in an unfinished state.
// Early returns out of this method leave the DMH in an unfinished state.
assert
(
java_lang_invoke_MethodHandle
::
vmentry
(
mh
())
==
NULL
,
"must be safely null"
);
assert
(
java_lang_invoke_MethodHandle
::
vmentry
(
mh
())
==
NULL
,
"must be safely null"
);
// which method are we really talking about?
// which method are we really talking about?
if
(
target_jh
==
NULL
)
{
THROW
(
vmSymbols
::
java_lang_InternalError
()
);
}
if
(
target_jh
==
NULL
)
{
THROW
_MSG
(
vmSymbols
::
java_lang_InternalError
(),
"target is null"
);
}
Handle
target
(
THREAD
,
JNIHandles
::
resolve_non_null
(
target_jh
));
Handle
target
(
THREAD
,
JNIHandles
::
resolve_non_null
(
target_jh
));
if
(
java_lang_invoke_MemberName
::
is_instance
(
target
())
&&
if
(
java_lang_invoke_MemberName
::
is_instance
(
target
())
&&
java_lang_invoke_MemberName
::
vmindex
(
target
())
==
VM_INDEX_UNINITIALIZED
)
{
java_lang_invoke_MemberName
::
vmindex
(
target
())
==
VM_INDEX_UNINITIALIZED
)
{
...
@@ -2722,13 +2722,13 @@ JVM_ENTRY(void, MHN_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh,
...
@@ -2722,13 +2722,13 @@ JVM_ENTRY(void, MHN_init_BMH(JNIEnv *env, jobject igcls, jobject mh_jh,
ResourceMark
rm
;
// for error messages
ResourceMark
rm
;
// for error messages
// This is the guy we are initializing:
// This is the guy we are initializing:
if
(
mh_jh
==
NULL
)
{
THROW
(
vmSymbols
::
java_lang_InternalError
()
);
}
if
(
mh_jh
==
NULL
)
{
THROW
_MSG
(
vmSymbols
::
java_lang_InternalError
(),
"self is null"
);
}
Handle
mh
(
THREAD
,
JNIHandles
::
resolve_non_null
(
mh_jh
));
Handle
mh
(
THREAD
,
JNIHandles
::
resolve_non_null
(
mh_jh
));
// Early returns out of this method leave the BMH in an unfinished state.
// Early returns out of this method leave the BMH in an unfinished state.
assert
(
java_lang_invoke_MethodHandle
::
vmentry
(
mh
())
==
NULL
,
"must be safely null"
);
assert
(
java_lang_invoke_MethodHandle
::
vmentry
(
mh
())
==
NULL
,
"must be safely null"
);
if
(
target_jh
==
NULL
)
{
THROW
(
vmSymbols
::
java_lang_InternalError
()
);
}
if
(
target_jh
==
NULL
)
{
THROW
_MSG
(
vmSymbols
::
java_lang_InternalError
(),
"target is null"
);
}
Handle
target
(
THREAD
,
JNIHandles
::
resolve_non_null
(
target_jh
));
Handle
target
(
THREAD
,
JNIHandles
::
resolve_non_null
(
target_jh
));
if
(
!
java_lang_invoke_MethodHandle
::
is_instance
(
target
()))
{
if
(
!
java_lang_invoke_MethodHandle
::
is_instance
(
target
()))
{
...
@@ -2753,9 +2753,8 @@ JVM_END
...
@@ -2753,9 +2753,8 @@ JVM_END
JVM_ENTRY
(
void
,
MHN_init_AMH
(
JNIEnv
*
env
,
jobject
igcls
,
jobject
mh_jh
,
JVM_ENTRY
(
void
,
MHN_init_AMH
(
JNIEnv
*
env
,
jobject
igcls
,
jobject
mh_jh
,
jobject
target_jh
,
int
argnum
))
{
jobject
target_jh
,
int
argnum
))
{
// This is the guy we are initializing:
// This is the guy we are initializing:
if
(
mh_jh
==
NULL
||
target_jh
==
NULL
)
{
if
(
mh_jh
==
NULL
)
{
THROW_MSG
(
vmSymbols
::
java_lang_InternalError
(),
"self is null"
);
}
THROW
(
vmSymbols
::
java_lang_InternalError
());
if
(
target_jh
==
NULL
)
{
THROW_MSG
(
vmSymbols
::
java_lang_InternalError
(),
"target is null"
);
}
}
Handle
mh
(
THREAD
,
JNIHandles
::
resolve_non_null
(
mh_jh
));
Handle
mh
(
THREAD
,
JNIHandles
::
resolve_non_null
(
mh_jh
));
Handle
target
(
THREAD
,
JNIHandles
::
resolve_non_null
(
target_jh
));
Handle
target
(
THREAD
,
JNIHandles
::
resolve_non_null
(
target_jh
));
...
@@ -2890,7 +2889,8 @@ JVM_END
...
@@ -2890,7 +2889,8 @@ JVM_END
// void init(MemberName self, AccessibleObject ref)
// void init(MemberName self, AccessibleObject ref)
JVM_ENTRY
(
void
,
MHN_init_Mem
(
JNIEnv
*
env
,
jobject
igcls
,
jobject
mname_jh
,
jobject
target_jh
))
{
JVM_ENTRY
(
void
,
MHN_init_Mem
(
JNIEnv
*
env
,
jobject
igcls
,
jobject
mname_jh
,
jobject
target_jh
))
{
if
(
mname_jh
==
NULL
||
target_jh
==
NULL
)
{
THROW
(
vmSymbols
::
java_lang_InternalError
());
}
if
(
mname_jh
==
NULL
)
{
THROW_MSG
(
vmSymbols
::
java_lang_InternalError
(),
"mname is null"
);
}
if
(
target_jh
==
NULL
)
{
THROW_MSG
(
vmSymbols
::
java_lang_InternalError
(),
"target is null"
);
}
Handle
mname
(
THREAD
,
JNIHandles
::
resolve_non_null
(
mname_jh
));
Handle
mname
(
THREAD
,
JNIHandles
::
resolve_non_null
(
mname_jh
));
oop
target_oop
=
JNIHandles
::
resolve_non_null
(
target_jh
);
oop
target_oop
=
JNIHandles
::
resolve_non_null
(
target_jh
);
MethodHandles
::
init_MemberName
(
mname
(),
target_oop
);
MethodHandles
::
init_MemberName
(
mname
(),
target_oop
);
...
@@ -2899,7 +2899,7 @@ JVM_END
...
@@ -2899,7 +2899,7 @@ JVM_END
// void expand(MemberName self)
// void expand(MemberName self)
JVM_ENTRY
(
void
,
MHN_expand_Mem
(
JNIEnv
*
env
,
jobject
igcls
,
jobject
mname_jh
))
{
JVM_ENTRY
(
void
,
MHN_expand_Mem
(
JNIEnv
*
env
,
jobject
igcls
,
jobject
mname_jh
))
{
if
(
mname_jh
==
NULL
)
{
THROW
(
vmSymbols
::
java_lang_InternalError
()
);
}
if
(
mname_jh
==
NULL
)
{
THROW
_MSG
(
vmSymbols
::
java_lang_InternalError
(),
"mname is null"
);
}
Handle
mname
(
THREAD
,
JNIHandles
::
resolve_non_null
(
mname_jh
));
Handle
mname
(
THREAD
,
JNIHandles
::
resolve_non_null
(
mname_jh
));
MethodHandles
::
expand_MemberName
(
mname
,
0
,
CHECK
);
MethodHandles
::
expand_MemberName
(
mname
,
0
,
CHECK
);
}
}
...
@@ -2907,7 +2907,7 @@ JVM_END
...
@@ -2907,7 +2907,7 @@ JVM_END
// void resolve(MemberName self, Class<?> caller)
// void resolve(MemberName self, Class<?> caller)
JVM_ENTRY
(
void
,
MHN_resolve_Mem
(
JNIEnv
*
env
,
jobject
igcls
,
jobject
mname_jh
,
jclass
caller_jh
))
{
JVM_ENTRY
(
void
,
MHN_resolve_Mem
(
JNIEnv
*
env
,
jobject
igcls
,
jobject
mname_jh
,
jclass
caller_jh
))
{
if
(
mname_jh
==
NULL
)
{
THROW
(
vmSymbols
::
java_lang_InternalError
()
);
}
if
(
mname_jh
==
NULL
)
{
THROW
_MSG
(
vmSymbols
::
java_lang_InternalError
(),
"mname is null"
);
}
Handle
mname
(
THREAD
,
JNIHandles
::
resolve_non_null
(
mname_jh
));
Handle
mname
(
THREAD
,
JNIHandles
::
resolve_non_null
(
mname_jh
));
// The trusted Java code that calls this method should already have performed
// The trusted Java code that calls this method should already have performed
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录