Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
79bbc02e
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看板
提交
79bbc02e
编写于
5月 12, 2011
作者:
T
twisti
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6998541: JSR 292 implement missing return-type conversion for OP_RETYPE_RAW
Reviewed-by: jrose, kvn, never
上级
e1b99956
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
355 addition
and
197 deletion
+355
-197
src/cpu/sparc/vm/methodHandles_sparc.cpp
src/cpu/sparc/vm/methodHandles_sparc.cpp
+2
-18
src/cpu/x86/vm/methodHandles_x86.cpp
src/cpu/x86/vm/methodHandles_x86.cpp
+28
-31
src/share/vm/ci/ciMethodData.hpp
src/share/vm/ci/ciMethodData.hpp
+5
-2
src/share/vm/ci/ciMethodHandle.cpp
src/share/vm/ci/ciMethodHandle.cpp
+19
-2
src/share/vm/ci/ciMethodHandle.hpp
src/share/vm/ci/ciMethodHandle.hpp
+14
-13
src/share/vm/opto/doCall.cpp
src/share/vm/opto/doCall.cpp
+11
-7
src/share/vm/prims/methodHandleWalk.cpp
src/share/vm/prims/methodHandleWalk.cpp
+199
-87
src/share/vm/prims/methodHandleWalk.hpp
src/share/vm/prims/methodHandleWalk.hpp
+21
-7
src/share/vm/prims/methodHandles.cpp
src/share/vm/prims/methodHandles.cpp
+54
-30
src/share/vm/prims/methodHandles.hpp
src/share/vm/prims/methodHandles.hpp
+2
-0
未找到文件。
src/cpu/sparc/vm/methodHandles_sparc.cpp
浏览文件 @
79bbc02e
...
@@ -142,18 +142,8 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
...
@@ -142,18 +142,8 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
Register
O2_form
=
O2_scratch
;
Register
O2_form
=
O2_scratch
;
Register
O3_adapter
=
O3_scratch
;
Register
O3_adapter
=
O3_scratch
;
__
load_heap_oop
(
Address
(
O0_mtype
,
__
delayed_value
(
java_lang_invoke_MethodType
::
form_offset_in_bytes
,
O1_scratch
)),
O2_form
);
__
load_heap_oop
(
Address
(
O0_mtype
,
__
delayed_value
(
java_lang_invoke_MethodType
::
form_offset_in_bytes
,
O1_scratch
)),
O2_form
);
// load_heap_oop(Address(O2_form, __ delayed_value(java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes, O1_scratch)), O3_adapter);
__
load_heap_oop
(
Address
(
O2_form
,
__
delayed_value
(
java_lang_invoke_MethodTypeForm
::
genericInvoker_offset_in_bytes
,
O1_scratch
)),
O3_adapter
);
// deal with old JDK versions:
__
verify_oop
(
O3_adapter
);
__
add
(
Address
(
O2_form
,
__
delayed_value
(
java_lang_invoke_MethodTypeForm
::
genericInvoker_offset_in_bytes
,
O1_scratch
)),
O3_adapter
);
__
cmp
(
O3_adapter
,
O2_form
);
Label
sorry_no_invoke_generic
;
__
brx
(
Assembler
::
lessUnsigned
,
false
,
Assembler
::
pn
,
sorry_no_invoke_generic
);
__
delayed
()
->
nop
();
__
load_heap_oop
(
Address
(
O3_adapter
,
0
),
O3_adapter
);
__
tst
(
O3_adapter
);
__
brx
(
Assembler
::
zero
,
false
,
Assembler
::
pn
,
sorry_no_invoke_generic
);
__
delayed
()
->
nop
();
__
st_ptr
(
O3_adapter
,
Address
(
O4_argbase
,
1
*
Interpreter
::
stackElementSize
));
__
st_ptr
(
O3_adapter
,
Address
(
O4_argbase
,
1
*
Interpreter
::
stackElementSize
));
// As a trusted first argument, pass the type being called, so the adapter knows
// As a trusted first argument, pass the type being called, so the adapter knows
// the actual types of the arguments and return values.
// the actual types of the arguments and return values.
...
@@ -164,12 +154,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
...
@@ -164,12 +154,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
trace_method_handle
(
_masm
,
"invokeGeneric"
);
trace_method_handle
(
_masm
,
"invokeGeneric"
);
__
jump_to_method_handle_entry
(
G3_method_handle
,
O1_scratch
);
__
jump_to_method_handle_entry
(
G3_method_handle
,
O1_scratch
);
__
bind
(
sorry_no_invoke_generic
);
// no invokeGeneric implementation available!
__
mov
(
O0_mtype
,
G5_method_type
);
// required by throw_WrongMethodType
// mov(G3_method_handle, G3_method_handle); // already in this register
__
jump_to
(
AddressLiteral
(
Interpreter
::
throw_WrongMethodType_entry
()),
O1_scratch
);
__
delayed
()
->
nop
();
return
entry_point
;
return
entry_point
;
}
}
...
...
src/cpu/x86/vm/methodHandles_x86.cpp
浏览文件 @
79bbc02e
...
@@ -163,7 +163,7 @@ void MethodHandles::RicochetFrame::generate_ricochet_blob(MacroAssembler* _masm,
...
@@ -163,7 +163,7 @@ void MethodHandles::RicochetFrame::generate_ricochet_blob(MacroAssembler* _masm,
BLOCK_COMMENT
(
"ricochet_blob.bounce"
);
BLOCK_COMMENT
(
"ricochet_blob.bounce"
);
if
(
VerifyMethodHandles
)
RicochetFrame
::
verify_clean
(
_masm
);
if
(
VerifyMethodHandles
)
RicochetFrame
::
verify_clean
(
_masm
);
trace_method_handle
(
_masm
,
"ricochet_blob.bounce"
);
trace_method_handle
(
_masm
,
"r
eturn/r
icochet_blob.bounce"
);
__
jmp
(
frame_address
(
continuation_offset_in_bytes
()));
__
jmp
(
frame_address
(
continuation_offset_in_bytes
()));
__
hlt
();
__
hlt
();
...
@@ -615,18 +615,10 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
...
@@ -615,18 +615,10 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
rcx_argslot
,
rbx_temp
,
rdx_temp
);
rcx_argslot
,
rbx_temp
,
rdx_temp
);
// load up an adapter from the calling type (Java weaves this)
// load up an adapter from the calling type (Java weaves this)
__
load_heap_oop
(
rdx_temp
,
Address
(
rax_mtype
,
__
delayed_value
(
java_lang_invoke_MethodType
::
form_offset_in_bytes
,
rdi_temp
)));
Register
rdx_adapter
=
rdx_temp
;
Register
rdx_adapter
=
rdx_temp
;
// __ load_heap_oop(rdx_adapter, Address(rdx_temp, java_lang_invoke_MethodTypeForm::genericInvoker_offset_in_bytes()));
__
load_heap_oop
(
rdx_temp
,
Address
(
rax_mtype
,
__
delayed_value
(
java_lang_invoke_MethodType
::
form_offset_in_bytes
,
rdi_temp
)));
// deal with old JDK versions:
__
load_heap_oop
(
rdx_adapter
,
Address
(
rdx_temp
,
__
delayed_value
(
java_lang_invoke_MethodTypeForm
::
genericInvoker_offset_in_bytes
,
rdi_temp
)));
__
lea
(
rdi_temp
,
Address
(
rdx_temp
,
__
delayed_value
(
java_lang_invoke_MethodTypeForm
::
genericInvoker_offset_in_bytes
,
rdi_temp
)));
__
verify_oop
(
rdx_adapter
);
__
cmpptr
(
rdi_temp
,
rdx_temp
);
Label
sorry_no_invoke_generic
;
__
jcc
(
Assembler
::
below
,
sorry_no_invoke_generic
);
__
load_heap_oop
(
rdx_adapter
,
Address
(
rdi_temp
,
0
));
__
testptr
(
rdx_adapter
,
rdx_adapter
);
__
jcc
(
Assembler
::
zero
,
sorry_no_invoke_generic
);
__
movptr
(
Address
(
rcx_argslot
,
1
*
Interpreter
::
stackElementSize
),
rdx_adapter
);
__
movptr
(
Address
(
rcx_argslot
,
1
*
Interpreter
::
stackElementSize
),
rdx_adapter
);
// As a trusted first argument, pass the type being called, so the adapter knows
// As a trusted first argument, pass the type being called, so the adapter knows
// the actual types of the arguments and return values.
// the actual types of the arguments and return values.
...
@@ -637,12 +629,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
...
@@ -637,12 +629,6 @@ address MethodHandles::generate_method_handle_interpreter_entry(MacroAssembler*
trace_method_handle
(
_masm
,
"invokeGeneric"
);
trace_method_handle
(
_masm
,
"invokeGeneric"
);
__
jump_to_method_handle_entry
(
rcx
,
rdi_temp
);
__
jump_to_method_handle_entry
(
rcx
,
rdi_temp
);
__
bind
(
sorry_no_invoke_generic
);
// no invokeGeneric implementation available!
__
movptr
(
rcx_recv
,
Address
(
rcx_argslot
,
-
1
*
Interpreter
::
stackElementSize
));
// recover original MH
__
push
(
rax_mtype
);
// required mtype
__
push
(
rcx_recv
);
// bad mh (1st stacked argument)
__
jump
(
ExternalAddress
(
Interpreter
::
throw_WrongMethodType_entry
()));
return
entry_point
;
return
entry_point
;
}
}
...
@@ -688,7 +674,7 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
...
@@ -688,7 +674,7 @@ void MethodHandles::insert_arg_slots(MacroAssembler* _masm,
__
movptr
(
Address
(
rdx_temp
,
arg_slots
,
Interpreter
::
stackElementScale
()),
rbx_temp
);
__
movptr
(
Address
(
rdx_temp
,
arg_slots
,
Interpreter
::
stackElementScale
()),
rbx_temp
);
__
addptr
(
rdx_temp
,
wordSize
);
__
addptr
(
rdx_temp
,
wordSize
);
__
cmpptr
(
rdx_temp
,
rax_argslot
);
__
cmpptr
(
rdx_temp
,
rax_argslot
);
__
jcc
(
Assembler
::
less
,
loop
);
__
jcc
(
Assembler
::
below
,
loop
);
}
}
// Now move the argslot down, to point to the opened-up space.
// Now move the argslot down, to point to the opened-up space.
...
@@ -731,7 +717,7 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
...
@@ -731,7 +717,7 @@ void MethodHandles::remove_arg_slots(MacroAssembler* _masm,
__
movptr
(
Address
(
rdx_temp
,
arg_slots
,
Interpreter
::
stackElementScale
()),
rbx_temp
);
__
movptr
(
Address
(
rdx_temp
,
arg_slots
,
Interpreter
::
stackElementScale
()),
rbx_temp
);
__
addptr
(
rdx_temp
,
-
wordSize
);
__
addptr
(
rdx_temp
,
-
wordSize
);
__
cmpptr
(
rdx_temp
,
rsp
);
__
cmpptr
(
rdx_temp
,
rsp
);
__
jcc
(
Assembler
::
greater
Equal
,
loop
);
__
jcc
(
Assembler
::
above
Equal
,
loop
);
}
}
// Now move the argslot up, to point to the just-copied block.
// Now move the argslot up, to point to the just-copied block.
...
@@ -980,12 +966,21 @@ void trace_method_handle_stub(const char* adaptername,
...
@@ -980,12 +966,21 @@ void trace_method_handle_stub(const char* adaptername,
intptr_t
*
saved_sp
,
intptr_t
*
saved_sp
,
intptr_t
*
saved_bp
)
{
intptr_t
*
saved_bp
)
{
// called as a leaf from native code: do not block the JVM!
// called as a leaf from native code: do not block the JVM!
bool
has_mh
=
(
strstr
(
adaptername
,
"return/"
)
==
NULL
);
// return adapters don't have rcx_mh
intptr_t
*
last_sp
=
(
intptr_t
*
)
saved_bp
[
frame
::
interpreter_frame_last_sp_offset
];
intptr_t
*
last_sp
=
(
intptr_t
*
)
saved_bp
[
frame
::
interpreter_frame_last_sp_offset
];
intptr_t
*
base_sp
=
(
intptr_t
*
)
saved_bp
[
frame
::
interpreter_frame_monitor_block_top_offset
];
intptr_t
*
base_sp
=
last_sp
;
tty
->
print_cr
(
"MH %s mh="
INTPTR_FORMAT
" sp=("
INTPTR_FORMAT
"+"
INTX_FORMAT
") stack_size="
INTX_FORMAT
" bp="
INTPTR_FORMAT
,
typedef
MethodHandles
::
RicochetFrame
RicochetFrame
;
adaptername
,
(
intptr_t
)
mh
,
(
intptr_t
)
entry_sp
,
(
intptr_t
)(
saved_sp
-
entry_sp
),
(
intptr_t
)(
base_sp
-
last_sp
),
(
intptr_t
)
saved_bp
);
RicochetFrame
*
rfp
=
(
RicochetFrame
*
)((
address
)
saved_bp
-
RicochetFrame
::
sender_link_offset_in_bytes
());
if
(
last_sp
!=
saved_sp
&&
last_sp
!=
NULL
)
if
(
!
UseRicochetFrames
||
Universe
::
heap
()
->
is_in
((
address
)
rfp
->
saved_args_base
()))
{
tty
->
print_cr
(
"*** last_sp="
INTPTR_FORMAT
,
(
intptr_t
)
last_sp
);
// Probably an interpreter frame.
base_sp
=
(
intptr_t
*
)
saved_bp
[
frame
::
interpreter_frame_monitor_block_top_offset
];
}
intptr_t
mh_reg
=
(
intptr_t
)
mh
;
const
char
*
mh_reg_name
=
"rcx_mh"
;
if
(
!
has_mh
)
mh_reg_name
=
"rcx"
;
tty
->
print_cr
(
"MH %s %s="
PTR_FORMAT
" sp=("
PTR_FORMAT
"+"
INTX_FORMAT
") stack_size="
INTX_FORMAT
" bp="
PTR_FORMAT
,
adaptername
,
mh_reg_name
,
mh_reg
,
(
intptr_t
)
entry_sp
,
(
intptr_t
)(
saved_sp
-
entry_sp
),
(
intptr_t
)(
base_sp
-
last_sp
),
(
intptr_t
)
saved_bp
);
if
(
Verbose
)
{
if
(
Verbose
)
{
tty
->
print
(
" reg dump: "
);
tty
->
print
(
" reg dump: "
);
int
saved_regs_count
=
(
entry_sp
-
1
)
-
saved_regs
;
int
saved_regs_count
=
(
entry_sp
-
1
)
-
saved_regs
;
...
@@ -996,18 +991,21 @@ void trace_method_handle_stub(const char* adaptername,
...
@@ -996,18 +991,21 @@ void trace_method_handle_stub(const char* adaptername,
tty
->
cr
();
tty
->
cr
();
tty
->
print
(
" + dump: "
);
tty
->
print
(
" + dump: "
);
}
}
tty
->
print
(
" %d: "
INT
PTR_FORMAT
,
i
,
saved_regs
[
i
]);
tty
->
print
(
" %d: "
PTR_FORMAT
,
i
,
saved_regs
[
i
]);
}
}
tty
->
cr
();
tty
->
cr
();
if
(
last_sp
!=
saved_sp
&&
last_sp
!=
NULL
)
tty
->
print_cr
(
"*** last_sp="
PTR_FORMAT
,
(
intptr_t
)
last_sp
);
int
stack_dump_count
=
16
;
int
stack_dump_count
=
16
;
if
(
stack_dump_count
<
(
int
)(
saved_bp
+
2
-
saved_sp
))
if
(
stack_dump_count
<
(
int
)(
saved_bp
+
2
-
saved_sp
))
stack_dump_count
=
(
int
)(
saved_bp
+
2
-
saved_sp
);
stack_dump_count
=
(
int
)(
saved_bp
+
2
-
saved_sp
);
if
(
stack_dump_count
>
64
)
stack_dump_count
=
48
;
if
(
stack_dump_count
>
64
)
stack_dump_count
=
48
;
for
(
i
=
0
;
i
<
stack_dump_count
;
i
+=
4
)
{
for
(
i
=
0
;
i
<
stack_dump_count
;
i
+=
4
)
{
tty
->
print_cr
(
" dump at SP[%d] "
INTPTR_FORMAT
": "
INTPTR_FORMAT
" "
INTPTR_FORMAT
" "
INTPTR_FORMAT
" "
INT
PTR_FORMAT
,
tty
->
print_cr
(
" dump at SP[%d] "
PTR_FORMAT
": "
PTR_FORMAT
" "
PTR_FORMAT
" "
PTR_FORMAT
" "
PTR_FORMAT
,
i
,
(
intptr_t
)
&
entry_sp
[
i
+
0
],
entry_sp
[
i
+
0
],
entry_sp
[
i
+
1
],
entry_sp
[
i
+
2
],
entry_sp
[
i
+
3
]);
i
,
(
intptr_t
)
&
entry_sp
[
i
+
0
],
entry_sp
[
i
+
0
],
entry_sp
[
i
+
1
],
entry_sp
[
i
+
2
],
entry_sp
[
i
+
3
]);
}
}
print_method_handle
(
mh
);
if
(
has_mh
)
print_method_handle
(
mh
);
}
}
}
}
...
@@ -1073,7 +1071,6 @@ int MethodHandles::adapter_conversion_ops_supported_mask() {
...
@@ -1073,7 +1071,6 @@ int MethodHandles::adapter_conversion_ops_supported_mask() {
//OP_COLLECT_ARGS is below...
//OP_COLLECT_ARGS is below...
|
(
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_SPREAD_ARGS
)
|
(
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_SPREAD_ARGS
)
|
(
!
UseRicochetFrames
?
0
:
|
(
!
UseRicochetFrames
?
0
:
LP64_ONLY
(
FLAG_IS_DEFAULT
(
UseRicochetFrames
)
?
0
:
)
java_lang_invoke_MethodTypeForm
::
vmlayout_offset_in_bytes
()
<=
0
?
0
:
java_lang_invoke_MethodTypeForm
::
vmlayout_offset_in_bytes
()
<=
0
?
0
:
((
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_PRIM_TO_REF
)
((
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_PRIM_TO_REF
)
|
(
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_COLLECT_ARGS
)
|
(
1
<<
java_lang_invoke_AdapterMethodHandle
::
OP_COLLECT_ARGS
)
...
@@ -1546,7 +1543,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
...
@@ -1546,7 +1543,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
#else //_LP64
#else //_LP64
if
(
ek
==
_adapter_opt_f2d
)
{
if
(
ek
==
_adapter_opt_f2d
)
{
__
fld_s
(
vmarg
);
// load float to ST0
__
fld_s
(
vmarg
);
// load float to ST0
__
fstp_
s
(
vmarg
);
// store sing
le
__
fstp_
d
(
vmarg
);
// store doub
le
}
else
{
}
else
{
__
fld_d
(
vmarg
);
// load double to ST0
__
fld_d
(
vmarg
);
// load double to ST0
__
fstp_s
(
vmarg
);
// store single
__
fstp_s
(
vmarg
);
// store single
...
@@ -2353,7 +2350,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
...
@@ -2353,7 +2350,7 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
rbx_temp
,
rdi_temp
);
rbx_temp
,
rdi_temp
);
__
addptr
(
rsi_source
,
type2aelembytes
(
elem_type
));
__
addptr
(
rsi_source
,
type2aelembytes
(
elem_type
));
__
cmpptr
(
rdx_fill_ptr
,
rax_argslot
);
__
cmpptr
(
rdx_fill_ptr
,
rax_argslot
);
__
jcc
(
Assembler
::
greater
,
loop
);
__
jcc
(
Assembler
::
above
,
loop
);
}
else
if
(
length_constant
==
0
)
{
}
else
if
(
length_constant
==
0
)
{
// nothing to copy
// nothing to copy
}
else
{
}
else
{
...
...
src/share/vm/ci/ciMethodData.hpp
浏览文件 @
79bbc02e
/*
/*
* Copyright (c) 2001, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 201
1
, 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
...
@@ -233,7 +233,10 @@ private:
...
@@ -233,7 +233,10 @@ private:
public:
public:
bool
is_method_data
()
{
return
true
;
}
bool
is_method_data
()
{
return
true
;
}
bool
is_empty
()
{
return
_state
==
empty_state
;
}
void
set_mature
()
{
_state
=
mature_state
;
}
bool
is_empty
()
{
return
_state
==
empty_state
;
}
bool
is_mature
()
{
return
_state
==
mature_state
;
}
bool
is_mature
()
{
return
_state
==
mature_state
;
}
int
creation_mileage
()
{
return
_orig
.
creation_mileage
();
}
int
creation_mileage
()
{
return
_orig
.
creation_mileage
();
}
...
...
src/share/vm/ci/ciMethodHandle.cpp
浏览文件 @
79bbc02e
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
#include "precompiled.hpp"
#include "precompiled.hpp"
#include "ci/ciClassList.hpp"
#include "ci/ciClassList.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciMethodData.hpp"
#include "ci/ciMethodHandle.hpp"
#include "ci/ciMethodHandle.hpp"
#include "ci/ciUtilities.hpp"
#include "ci/ciUtilities.hpp"
#include "prims/methodHandleWalk.hpp"
#include "prims/methodHandleWalk.hpp"
...
@@ -36,13 +37,13 @@
...
@@ -36,13 +37,13 @@
// ciMethodHandle::get_adapter
// ciMethodHandle::get_adapter
//
//
// Return an adapter for this MethodHandle.
// Return an adapter for this MethodHandle.
ciMethod
*
ciMethodHandle
::
get_adapter
(
bool
is_invokedynamic
)
const
{
ciMethod
*
ciMethodHandle
::
get_adapter
_impl
(
bool
is_invokedynamic
)
const
{
VM_ENTRY_MARK
;
VM_ENTRY_MARK
;
Handle
h
(
get_oop
());
Handle
h
(
get_oop
());
methodHandle
callee
(
_callee
->
get_methodOop
());
methodHandle
callee
(
_callee
->
get_methodOop
());
// We catch all exceptions here that could happen in the method
// We catch all exceptions here that could happen in the method
// handle compiler and stop the VM.
// handle compiler and stop the VM.
MethodHandleCompiler
mhc
(
h
,
callee
,
call_profile
()
->
count
(),
is_invokedynamic
,
THREAD
);
MethodHandleCompiler
mhc
(
h
,
callee
,
_profile
->
count
(),
is_invokedynamic
,
THREAD
);
if
(
!
HAS_PENDING_EXCEPTION
)
{
if
(
!
HAS_PENDING_EXCEPTION
)
{
methodHandle
m
=
mhc
.
compile
(
THREAD
);
methodHandle
m
=
mhc
.
compile
(
THREAD
);
if
(
!
HAS_PENDING_EXCEPTION
)
{
if
(
!
HAS_PENDING_EXCEPTION
)
{
...
@@ -58,6 +59,22 @@ ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const {
...
@@ -58,6 +59,22 @@ ciMethod* ciMethodHandle::get_adapter(bool is_invokedynamic) const {
return
NULL
;
return
NULL
;
}
}
// ------------------------------------------------------------------
// ciMethodHandle::get_adapter
//
// Return an adapter for this MethodHandle.
ciMethod
*
ciMethodHandle
::
get_adapter
(
bool
is_invokedynamic
)
const
{
ciMethod
*
result
=
get_adapter_impl
(
is_invokedynamic
);
if
(
result
)
{
// Fake up the MDO maturity.
ciMethodData
*
mdo
=
result
->
method_data
();
if
(
mdo
!=
NULL
&&
_caller
->
method_data
()
!=
NULL
&&
_caller
->
method_data
()
->
is_mature
())
{
mdo
->
set_mature
();
}
}
return
result
;
}
// ------------------------------------------------------------------
// ------------------------------------------------------------------
// ciMethodHandle::print_impl
// ciMethodHandle::print_impl
...
...
src/share/vm/ci/ciMethodHandle.hpp
浏览文件 @
79bbc02e
...
@@ -35,35 +35,36 @@
...
@@ -35,35 +35,36 @@
class
ciMethodHandle
:
public
ciInstance
{
class
ciMethodHandle
:
public
ciInstance
{
private:
private:
ciMethod
*
_callee
;
ciMethod
*
_callee
;
ciMethod
*
_caller
;
ciCallProfile
*
_profile
;
ciCallProfile
*
_profile
;
// Return an adapter for this MethodHandle.
// Return an adapter for this MethodHandle.
ciMethod
*
get_adapter
(
bool
is_invokedynamic
)
const
;
ciMethod
*
get_adapter_impl
(
bool
is_invokedynamic
)
const
;
ciMethod
*
get_adapter
(
bool
is_invokedynamic
)
const
;
protected:
protected:
void
print_impl
(
outputStream
*
st
);
void
print_impl
(
outputStream
*
st
);
public:
public:
ciMethodHandle
(
instanceHandle
h_i
)
:
ciInstance
(
h_i
)
{};
ciMethodHandle
(
instanceHandle
h_i
)
:
ciInstance
(
h_i
),
_callee
(
NULL
),
_caller
(
NULL
),
_profile
(
NULL
)
{}
// What kind of ciObject is this?
// What kind of ciObject is this?
bool
is_method_handle
()
const
{
return
true
;
}
bool
is_method_handle
()
const
{
return
true
;
}
ciMethod
*
callee
()
const
{
return
_callee
;
}
void
set_callee
(
ciMethod
*
m
)
{
_callee
=
m
;
}
void
set_callee
(
ciMethod
*
m
)
{
_callee
=
m
;
}
void
set_caller
(
ciMethod
*
m
)
{
_caller
=
m
;
}
void
set_call_profile
(
ciCallProfile
*
profile
)
{
_profile
=
profile
;
}
ciCallProfile
*
call_profile
()
const
{
return
_profile
;
}
void
set_call_profile
(
ciCallProfile
*
profile
)
{
_profile
=
profile
;
}
// Return an adapter for a MethodHandle call.
// Return an adapter for a MethodHandle call.
ciMethod
*
get_method_handle_adapter
()
const
{
ciMethod
*
get_method_handle_adapter
()
const
{
return
get_adapter
(
false
);
}
return
get_adapter
(
false
);
}
// Return an adapter for an invokedynamic call.
// Return an adapter for an invokedynamic call.
ciMethod
*
get_invokedynamic_adapter
()
const
{
ciMethod
*
get_invokedynamic_adapter
()
const
{
return
get_adapter
(
true
);
}
return
get_adapter
(
true
);
}
};
};
#endif // SHARE_VM_CI_CIMETHODHANDLE_HPP
#endif // SHARE_VM_CI_CIMETHODHANDLE_HPP
src/share/vm/opto/doCall.cpp
浏览文件 @
79bbc02e
...
@@ -62,7 +62,10 @@ void trace_type_profile(ciMethod *method, int depth, int bci, ciMethod *prof_met
...
@@ -62,7 +62,10 @@ void trace_type_profile(ciMethod *method, int depth, int bci, ciMethod *prof_met
CallGenerator
*
Compile
::
call_generator
(
ciMethod
*
call_method
,
int
vtable_index
,
bool
call_is_virtual
,
CallGenerator
*
Compile
::
call_generator
(
ciMethod
*
call_method
,
int
vtable_index
,
bool
call_is_virtual
,
JVMState
*
jvms
,
bool
allow_inline
,
JVMState
*
jvms
,
bool
allow_inline
,
float
prof_factor
)
{
float
prof_factor
)
{
CallGenerator
*
cg
;
CallGenerator
*
cg
;
ciMethod
*
caller
=
jvms
->
method
();
int
bci
=
jvms
->
bci
();
Bytecodes
::
Code
bytecode
=
caller
->
java_code_at_bci
(
bci
);
guarantee
(
call_method
!=
NULL
,
"failed method resolution"
);
guarantee
(
call_method
!=
NULL
,
"failed method resolution"
);
// Dtrace currently doesn't work unless all calls are vanilla
// Dtrace currently doesn't work unless all calls are vanilla
...
@@ -73,8 +76,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
...
@@ -73,8 +76,7 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
// Note: When we get profiling during stage-1 compiles, we want to pull
// Note: When we get profiling during stage-1 compiles, we want to pull
// from more specific profile data which pertains to this inlining.
// from more specific profile data which pertains to this inlining.
// Right now, ignore the information in jvms->caller(), and do method[bci].
// Right now, ignore the information in jvms->caller(), and do method[bci].
ciCallProfile
profile
=
jvms
->
method
()
->
call_profile_at_bci
(
jvms
->
bci
());
ciCallProfile
profile
=
caller
->
call_profile_at_bci
(
bci
);
Bytecodes
::
Code
bytecode
=
jvms
->
method
()
->
java_code_at_bci
(
jvms
->
bci
());
// See how many times this site has been invoked.
// See how many times this site has been invoked.
int
site_count
=
profile
.
count
();
int
site_count
=
profile
.
count
();
...
@@ -126,9 +128,10 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
...
@@ -126,9 +128,10 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
ciObject
*
const_oop
=
oop_ptr
->
const_oop
();
ciObject
*
const_oop
=
oop_ptr
->
const_oop
();
ciMethodHandle
*
method_handle
=
const_oop
->
as_method_handle
();
ciMethodHandle
*
method_handle
=
const_oop
->
as_method_handle
();
// Set the
actually called method to have access to the class
// Set the
callee to have access to the class and signature in
//
and signature in
the MethodHandleCompiler.
// the MethodHandleCompiler.
method_handle
->
set_callee
(
call_method
);
method_handle
->
set_callee
(
call_method
);
method_handle
->
set_caller
(
caller
);
method_handle
->
set_call_profile
(
&
profile
);
method_handle
->
set_call_profile
(
&
profile
);
// Get an adapter for the MethodHandle.
// Get an adapter for the MethodHandle.
...
@@ -150,9 +153,10 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
...
@@ -150,9 +153,10 @@ CallGenerator* Compile::call_generator(ciMethod* call_method, int vtable_index,
ciCallSite
*
call_site
=
str
.
get_call_site
();
ciCallSite
*
call_site
=
str
.
get_call_site
();
ciMethodHandle
*
method_handle
=
call_site
->
get_target
();
ciMethodHandle
*
method_handle
=
call_site
->
get_target
();
// Set the
actually called method to have access to the class
// Set the
callee to have access to the class and signature in
//
and signature in
the MethodHandleCompiler.
// the MethodHandleCompiler.
method_handle
->
set_callee
(
call_method
);
method_handle
->
set_callee
(
call_method
);
method_handle
->
set_caller
(
caller
);
method_handle
->
set_call_profile
(
&
profile
);
method_handle
->
set_call_profile
(
&
profile
);
// Get an adapter for the MethodHandle.
// Get an adapter for the MethodHandle.
...
...
src/share/vm/prims/methodHandleWalk.cpp
浏览文件 @
79bbc02e
...
@@ -31,6 +31,11 @@
...
@@ -31,6 +31,11 @@
* JSR 292 reference implementation: method handle structure analysis
* JSR 292 reference implementation: method handle structure analysis
*/
*/
#ifdef PRODUCT
#define print_method_handle(mh) {}
#else //PRODUCT
extern
"C"
void
print_method_handle
(
oop
mh
);
#endif //PRODUCT
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// MethodHandleChain
// MethodHandleChain
...
@@ -206,8 +211,10 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -206,8 +211,10 @@ MethodHandleWalker::walk(TRAPS) {
lose
(
"bad argument index"
,
CHECK_
(
empty
));
lose
(
"bad argument index"
,
CHECK_
(
empty
));
}
}
bool
retain_original_args
=
false
;
// used by fold/collect logic
// perform the adapter action
// perform the adapter action
switch
(
c
hain
().
adapter_conversion_op
()
)
{
switch
(
c
onv_op
)
{
case
java_lang_invoke_AdapterMethodHandle
::
OP_RETYPE_ONLY
:
case
java_lang_invoke_AdapterMethodHandle
::
OP_RETYPE_ONLY
:
// No changes to arguments; pass the bits through.
// No changes to arguments; pass the bits through.
break
;
break
;
...
@@ -216,51 +223,36 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -216,51 +223,36 @@ MethodHandleWalker::walk(TRAPS) {
// To keep the verifier happy, emit bitwise ("raw") conversions as needed.
// To keep the verifier happy, emit bitwise ("raw") conversions as needed.
// See MethodHandles::same_basic_type_for_arguments for allowed conversions.
// See MethodHandles::same_basic_type_for_arguments for allowed conversions.
Handle
incoming_mtype
(
THREAD
,
chain
().
method_type_oop
());
Handle
incoming_mtype
(
THREAD
,
chain
().
method_type_oop
());
oop
outgoing_mh_oop
=
chain
().
vmtarget_oop
();
Handle
outgoing_mtype
;
if
(
!
java_lang_invoke_MethodHandle
::
is_instance
(
outgoing_mh_oop
))
{
lose
(
"outgoing target not a MethodHandle"
,
CHECK_
(
empty
));
oop
outgoing_mh_oop
=
chain
().
vmtarget_oop
();
Handle
outgoing_mtype
(
THREAD
,
java_lang_invoke_MethodHandle
::
type
(
outgoing_mh_oop
));
if
(
!
java_lang_invoke_MethodHandle
::
is_instance
(
outgoing_mh_oop
))
outgoing_mh_oop
=
NULL
;
// GC safety
lose
(
"outgoing target not a MethodHandle"
,
CHECK_
(
empty
));
outgoing_mtype
=
Handle
(
THREAD
,
java_lang_invoke_MethodHandle
::
type
(
outgoing_mh_oop
));
}
int
nptypes
=
java_lang_invoke_MethodType
::
ptype_count
(
outgoing_mtype
());
int
nptypes
=
java_lang_invoke_MethodType
::
ptype_count
(
outgoing_mtype
());
if
(
nptypes
!=
java_lang_invoke_MethodType
::
ptype_count
(
incoming_mtype
()))
if
(
nptypes
!=
java_lang_invoke_MethodType
::
ptype_count
(
incoming_mtype
()))
lose
(
"incoming and outgoing parameter count do not agree"
,
CHECK_
(
empty
));
lose
(
"incoming and outgoing parameter count do not agree"
,
CHECK_
(
empty
));
// 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
);
SlotState
*
arg_state
=
slot_state
(
slot
);
if
(
arg_state
->
_type
==
T_VOID
)
continue
;
if
(
arg_state
->
_type
==
T_VOID
)
continue
;
ArgToken
arg
=
_outgoing
.
at
(
slot
).
_arg
;
klassOop
in_klass
=
NULL
;
klassOop
out_klass
=
NULL
;
BasicType
inpbt
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
ptype
(
incoming_mtype
(),
i
),
&
in_klass
);
BasicType
outpbt
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
ptype
(
outgoing_mtype
(),
i
),
&
out_klass
);
assert
(
inpbt
==
arg
.
basic_type
(),
"sanity"
);
if
(
inpbt
!=
outpbt
)
{
vmIntrinsics
::
ID
iid
=
vmIntrinsics
::
for_raw_conversion
(
inpbt
,
outpbt
);
if
(
iid
==
vmIntrinsics
::
_none
)
{
lose
(
"no raw conversion method"
,
CHECK_
(
empty
));
}
ArgToken
arglist
[
2
];
arglist
[
0
]
=
arg
;
// outgoing 'this'
arglist
[
1
]
=
ArgToken
();
// sentinel
arg
=
make_invoke
(
NULL
,
iid
,
Bytecodes
::
_invokestatic
,
false
,
1
,
&
arglist
[
0
],
CHECK_
(
empty
));
change_argument
(
inpbt
,
slot
,
outpbt
,
arg
);
}
klassOop
src_klass
=
NULL
;
klassOop
dst_klass
=
NULL
;
BasicType
src
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
ptype
(
incoming_mtype
(),
i
),
&
src_klass
);
BasicType
dst
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
ptype
(
outgoing_mtype
(),
i
),
&
dst_klass
);
retype_raw_argument_type
(
src
,
dst
,
slot
,
CHECK_
(
empty
));
i
++
;
// We need to skip void slots at the top of the loop.
i
++
;
// We need to skip void slots at the top of the loop.
}
}
BasicType
inrbt
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
rtype
(
incoming_mtype
()));
// Return type.
BasicType
outrbt
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
rtype
(
outgoing_mtype
()));
{
if
(
inrbt
!=
outrbt
)
{
BasicType
src
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
rtype
(
incoming_mtype
()));
if
(
inrbt
==
T_INT
&&
outrbt
==
T_VOID
)
{
BasicType
dst
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
rtype
(
outgoing_mtype
()));
// See comments in MethodHandles::same_basic_type_for_arguments.
retype_raw_return_type
(
src
,
dst
,
CHECK_
(
empty
));
}
else
{
assert
(
false
,
"IMPLEMENT ME"
);
lose
(
"no raw conversion method"
,
CHECK_
(
empty
));
}
}
}
break
;
break
;
}
}
...
@@ -273,7 +265,7 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -273,7 +265,7 @@ MethodHandleWalker::walk(TRAPS) {
assert
(
dest
==
arg_state
->
_type
,
""
);
assert
(
dest
==
arg_state
->
_type
,
""
);
ArgToken
arg
=
arg_state
->
_arg
;
ArgToken
arg
=
arg_state
->
_arg
;
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
.
index
()
==
new_arg
.
index
(),
"should be the same index"
);
assert
(
arg
.
token_type
()
>=
tt_symbolic
||
arg
.
index
()
==
new_arg
.
index
(),
"should be the same index"
);
debug_only
(
dest_klass
=
(
klassOop
)
badOop
);
debug_only
(
dest_klass
=
(
klassOop
)
badOop
);
break
;
break
;
}
}
...
@@ -332,7 +324,7 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -332,7 +324,7 @@ MethodHandleWalker::walk(TRAPS) {
ArgToken
arglist
[
2
];
ArgToken
arglist
[
2
];
arglist
[
0
]
=
arg
;
// outgoing value
arglist
[
0
]
=
arg
;
// outgoing value
arglist
[
1
]
=
ArgToken
();
// sentinel
arglist
[
1
]
=
ArgToken
();
// sentinel
arg
=
make_invoke
(
NULL
,
boxer
,
Bytecodes
::
_invoke
virtual
,
false
,
1
,
&
arglist
[
0
],
CHECK_
(
empty
));
arg
=
make_invoke
(
NULL
,
boxer
,
Bytecodes
::
_invoke
static
,
false
,
1
,
&
arglist
[
0
],
CHECK_
(
empty
));
change_argument
(
src
,
arg_slot
,
T_OBJECT
,
arg
);
change_argument
(
src
,
arg_slot
,
T_OBJECT
,
arg
);
break
;
break
;
}
}
...
@@ -404,13 +396,54 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -404,13 +396,54 @@ MethodHandleWalker::walk(TRAPS) {
break
;
break
;
}
}
case
java_lang_invoke_AdapterMethodHandle
::
OP_COLLECT_ARGS
:
{
//NYI, may GC
case
java_lang_invoke_AdapterMethodHandle
::
OP_FOLD_ARGS
:
lose
(
"unimplemented"
,
CHECK_
(
empty
));
retain_original_args
=
true
;
// and fall through:
break
;
case
java_lang_invoke_AdapterMethodHandle
::
OP_COLLECT_ARGS
:
{
}
// call argument MH recursively
//{static int x; if (!x++) print_method_handle(chain().method_handle_oop()); --x;}
case
java_lang_invoke_AdapterMethodHandle
::
OP_FOLD_ARGS
:
{
//NYI, may GC
Handle
recursive_mh
(
THREAD
,
chain
().
adapter_arg_oop
());
lose
(
"unimplemented"
,
CHECK_
(
empty
));
if
(
!
java_lang_invoke_MethodHandle
::
is_instance
(
recursive_mh
()))
{
lose
(
"recursive target not a MethodHandle"
,
CHECK_
(
empty
));
}
Handle
recursive_mtype
(
THREAD
,
java_lang_invoke_MethodHandle
::
type
(
recursive_mh
()));
int
argc
=
java_lang_invoke_MethodType
::
ptype_count
(
recursive_mtype
());
int
coll_slots
=
java_lang_invoke_MethodHandle
::
vmslots
(
recursive_mh
());
BasicType
rtype
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
rtype
(
recursive_mtype
()));
ArgToken
*
arglist
=
NEW_RESOURCE_ARRAY
(
ArgToken
,
1
+
argc
+
1
);
// 1+: mh, +1: sentinel
arglist
[
0
]
=
make_oop_constant
(
recursive_mh
(),
CHECK_
(
empty
));
if
(
arg_slot
<
0
||
coll_slots
<
0
||
arg_slot
+
coll_slots
>
_outgoing
.
length
())
{
lose
(
"bad fold/collect arg slot"
,
CHECK_
(
empty
));
}
for
(
int
i
=
0
,
slot
=
arg_slot
+
coll_slots
-
1
;
slot
>=
arg_slot
;
slot
--
)
{
SlotState
*
arg_state
=
slot_state
(
slot
);
BasicType
arg_type
=
arg_state
->
_type
;
if
(
arg_type
==
T_VOID
)
continue
;
ArgToken
arg
=
_outgoing
.
at
(
slot
).
_arg
;
if
(
i
>=
argc
)
{
lose
(
"bad fold/collect arg"
,
CHECK_
(
empty
));
}
arglist
[
1
+
i
]
=
arg
;
if
(
!
retain_original_args
)
change_argument
(
arg_type
,
slot
,
T_VOID
,
ArgToken
(
tt_void
));
}
arglist
[
1
+
argc
]
=
ArgToken
();
// sentinel
oop
invoker
=
java_lang_invoke_MethodTypeForm
::
vmlayout
(
java_lang_invoke_MethodType
::
form
(
recursive_mtype
())
);
if
(
invoker
==
NULL
||
!
invoker
->
is_method
())
{
lose
(
"bad vmlayout slot"
,
CHECK_
(
empty
));
}
// FIXME: consider inlining the invokee at the bytecode level
ArgToken
ret
=
make_invoke
(
methodOop
(
invoker
),
vmIntrinsics
::
_none
,
Bytecodes
::
_invokevirtual
,
false
,
1
+
argc
,
&
arglist
[
0
],
CHECK_
(
empty
));
DEBUG_ONLY
(
invoker
=
NULL
);
if
(
rtype
==
T_OBJECT
)
{
klassOop
rklass
=
java_lang_Class
::
as_klassOop
(
java_lang_invoke_MethodType
::
rtype
(
recursive_mtype
())
);
if
(
rklass
!=
SystemDictionary
::
Object_klass
()
&&
!
Klass
::
cast
(
rklass
)
->
is_interface
())
{
// preserve type safety
ret
=
make_conversion
(
T_OBJECT
,
rklass
,
Bytecodes
::
_checkcast
,
ret
,
CHECK_
(
empty
));
}
}
int
ret_slot
=
arg_slot
+
(
retain_original_args
?
coll_slots
:
0
);
change_argument
(
T_VOID
,
ret_slot
,
rtype
,
ret
);
break
;
break
;
}
}
...
@@ -504,7 +537,7 @@ MethodHandleWalker::walk(TRAPS) {
...
@@ -504,7 +537,7 @@ MethodHandleWalker::walk(TRAPS) {
lose
(
"bad bound value"
,
CHECK_
(
empty
));
lose
(
"bad bound value"
,
CHECK_
(
empty
));
}
}
}
}
debug_only
(
arg_oop
=
badOop
);
DEBUG_ONLY
(
arg_oop
=
badOop
);
change_argument
(
T_VOID
,
arg_slot
,
arg_type
,
arg
);
change_argument
(
T_VOID
,
arg_slot
,
arg_type
,
arg
);
}
}
...
@@ -547,11 +580,10 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
...
@@ -547,11 +580,10 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
}
}
for
(
int
i
=
0
;
i
<
nptypes
;
i
++
)
{
for
(
int
i
=
0
;
i
<
nptypes
;
i
++
)
{
klassOop
arg_type_klass
=
NULL
;
klassOop
arg_type_klass
=
NULL
;
BasicType
arg_type
=
java_lang_Class
::
as_BasicType
(
BasicType
arg_type
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
ptype
(
mtype
(),
i
),
&
arg_type_klass
);
java_lang_invoke_MethodType
::
ptype
(
mtype
(),
i
),
&
arg_type_klass
);
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
,
make_state
(
arg_type
,
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
...
@@ -561,8 +593,7 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
...
@@ -561,8 +593,7 @@ void MethodHandleWalker::walk_incoming_state(TRAPS) {
}
}
// call make_parameter at the end of the list for the return type
// call make_parameter at the end of the list for the return type
klassOop
ret_type_klass
=
NULL
;
klassOop
ret_type_klass
=
NULL
;
BasicType
ret_type
=
java_lang_Class
::
as_BasicType
(
BasicType
ret_type
=
java_lang_Class
::
as_BasicType
(
java_lang_invoke_MethodType
::
rtype
(
mtype
()),
&
ret_type_klass
);
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
}
}
...
@@ -613,6 +644,48 @@ int MethodHandleWalker::argument_count_slow() {
...
@@ -613,6 +644,48 @@ int MethodHandleWalker::argument_count_slow() {
#endif
#endif
// -----------------------------------------------------------------------------
// MethodHandleWalker::retype_raw_conversion
//
// Do the raw retype conversions for OP_RETYPE_RAW.
void
MethodHandleWalker
::
retype_raw_conversion
(
BasicType
src
,
BasicType
dst
,
bool
for_return
,
int
slot
,
TRAPS
)
{
if
(
src
!=
dst
)
{
if
(
MethodHandles
::
same_basic_type_for_returns
(
src
,
dst
,
/*raw*/
true
))
{
if
(
MethodHandles
::
is_float_fixed_reinterpretation_cast
(
src
,
dst
))
{
if
(
for_return
)
Untested
(
"MHW return raw conversion"
);
// still untested
vmIntrinsics
::
ID
iid
=
vmIntrinsics
::
for_raw_conversion
(
src
,
dst
);
if
(
iid
==
vmIntrinsics
::
_none
)
{
lose
(
"no raw conversion method"
,
CHECK
);
}
ArgToken
arglist
[
2
];
if
(
!
for_return
)
{
// argument type conversion
ArgToken
arg
=
_outgoing
.
at
(
slot
).
_arg
;
assert
(
arg
.
token_type
()
>=
tt_symbolic
||
src
==
arg
.
basic_type
(),
"sanity"
);
arglist
[
0
]
=
arg
;
// outgoing 'this'
arglist
[
1
]
=
ArgToken
();
// sentinel
arg
=
make_invoke
(
NULL
,
iid
,
Bytecodes
::
_invokestatic
,
false
,
1
,
&
arglist
[
0
],
CHECK
);
change_argument
(
src
,
slot
,
dst
,
arg
);
}
else
{
// return type conversion
klassOop
arg_klass
=
NULL
;
arglist
[
0
]
=
make_parameter
(
src
,
arg_klass
,
-
1
,
CHECK
);
// return value
arglist
[
1
]
=
ArgToken
();
// sentinel
(
void
)
make_invoke
(
NULL
,
iid
,
Bytecodes
::
_invokestatic
,
false
,
1
,
&
arglist
[
0
],
CHECK
);
}
}
else
{
// Nothing to do.
}
}
else
if
(
src
==
T_OBJECT
&&
is_java_primitive
(
dst
))
{
// ref-to-prim: discard ref, push zero
lose
(
"requested ref-to-prim conversion not expected"
,
CHECK
);
}
else
{
lose
(
"requested raw conversion not allowed"
,
CHECK
);
}
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// MethodHandleCompiler
// MethodHandleCompiler
...
@@ -719,6 +792,7 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
...
@@ -719,6 +792,7 @@ void MethodHandleCompiler::emit_bc(Bytecodes::Code op, int index) {
case
Bytecodes
::
_astore_1
:
case
Bytecodes
::
_astore_1
:
case
Bytecodes
::
_astore_2
:
case
Bytecodes
::
_astore_2
:
case
Bytecodes
::
_astore_3
:
case
Bytecodes
::
_astore_3
:
case
Bytecodes
::
_iand
:
case
Bytecodes
::
_i2l
:
case
Bytecodes
::
_i2l
:
case
Bytecodes
::
_i2f
:
case
Bytecodes
::
_i2f
:
case
Bytecodes
::
_i2d
:
case
Bytecodes
::
_i2d
:
...
@@ -945,7 +1019,11 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co
...
@@ -945,7 +1019,11 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co
break
;
break
;
default:
default:
ShouldNotReachHere
();
if
(
op
==
Bytecodes
::
_illegal
)
lose
(
"no such primitive conversion"
,
THREAD
);
else
lose
(
"bad primitive conversion op"
,
THREAD
);
return
make_prim_constant
(
type
,
&
zero_jvalue
,
THREAD
);
}
}
return
make_parameter
(
type
,
tk
,
index
,
THREAD
);
return
make_parameter
(
type
,
tk
,
index
,
THREAD
);
...
@@ -956,7 +1034,9 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co
...
@@ -956,7 +1034,9 @@ MethodHandleCompiler::make_conversion(BasicType type, klassOop tk, Bytecodes::Co
// MethodHandleCompiler
// MethodHandleCompiler
//
//
static
jvalue
zero_jvalue
;
// Values used by the compiler.
jvalue
MethodHandleCompiler
::
zero_jvalue
=
{
0
};
jvalue
MethodHandleCompiler
::
one_jvalue
=
{
1
};
// Emit bytecodes for the given invoke instruction.
// Emit bytecodes for the given invoke instruction.
MethodHandleWalker
::
ArgToken
MethodHandleWalker
::
ArgToken
...
@@ -964,18 +1044,18 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
...
@@ -964,18 +1044,18 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
Bytecodes
::
Code
op
,
bool
tailcall
,
Bytecodes
::
Code
op
,
bool
tailcall
,
int
argc
,
MethodHandleWalker
::
ArgToken
*
argv
,
int
argc
,
MethodHandleWalker
::
ArgToken
*
argv
,
TRAPS
)
{
TRAPS
)
{
ArgToken
zero
;
if
(
m
==
NULL
)
{
if
(
m
==
NULL
)
{
// Get the intrinsic methodOop.
// Get the intrinsic methodOop.
m
=
vmIntrinsics
::
method_for
(
iid
);
m
=
vmIntrinsics
::
method_for
(
iid
);
if
(
m
==
NULL
)
{
if
(
m
==
NULL
)
{
ArgToken
zero
;
lose
(
vmIntrinsics
::
name_at
(
iid
),
CHECK_
(
zero
));
lose
(
vmIntrinsics
::
name_at
(
iid
),
CHECK_
(
zero
));
}
}
}
}
klassOop
klass
=
m
->
method_holder
();
klassOop
klass
=
m
->
method_holder
();
Symbol
*
name
=
m
->
name
();
Symbol
*
name
=
m
->
name
();
Symbol
*
signature
=
m
->
signature
();
Symbol
*
signature
=
m
->
signature
();
if
(
tailcall
)
{
if
(
tailcall
)
{
// Actually, in order to make these methods more recognizable,
// Actually, in order to make these methods more recognizable,
...
@@ -1041,7 +1121,6 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
...
@@ -1041,7 +1121,6 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
if
(
rbt
!=
_rtype
)
{
if
(
rbt
!=
_rtype
)
{
if
(
rbt
==
T_VOID
)
{
if
(
rbt
==
T_VOID
)
{
// push a zero of the right sort
// push a zero of the right sort
ArgToken
zero
;
if
(
_rtype
==
T_OBJECT
)
{
if
(
_rtype
==
T_OBJECT
)
{
zero
=
make_oop_constant
(
NULL
,
CHECK_
(
zero
));
zero
=
make_oop_constant
(
NULL
,
CHECK_
(
zero
));
}
else
{
}
else
{
...
@@ -1051,9 +1130,27 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
...
@@ -1051,9 +1130,27 @@ MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid,
}
else
if
(
_rtype
==
T_VOID
)
{
}
else
if
(
_rtype
==
T_VOID
)
{
// We'll emit a _return with something on the stack.
// We'll emit a _return with something on the stack.
// It's OK to ignore what's on the stack.
// It's OK to ignore what's on the stack.
}
else
if
(
rbt
==
T_INT
&&
is_subword_type
(
_rtype
))
{
// Convert value to match return type.
switch
(
_rtype
)
{
case
T_BOOLEAN
:
{
// boolean is treated as a one-bit unsigned integer.
// Cf. API documentation: java/lang/invoke/MethodHandles.html#explicitCastArguments
ArgToken
one
=
make_prim_constant
(
T_INT
,
&
one_jvalue
,
CHECK_
(
zero
));
emit_load_constant
(
one
);
emit_bc
(
Bytecodes
::
_iand
);
break
;
}
case
T_BYTE
:
emit_bc
(
Bytecodes
::
_i2b
);
break
;
case
T_CHAR
:
emit_bc
(
Bytecodes
::
_i2c
);
break
;
case
T_SHORT
:
emit_bc
(
Bytecodes
::
_i2s
);
break
;
default:
ShouldNotReachHere
();
}
}
else
if
(
is_subword_type
(
rbt
)
&&
(
is_subword_type
(
_rtype
)
||
(
_rtype
==
T_INT
)))
{
// The subword type was returned as an int and will be passed
// on as an int.
}
else
{
}
else
{
tty
->
print_cr
(
"*** rbt=%d != rtype=%d"
,
rbt
,
_rtype
);
lose
(
"unknown conversion"
,
CHECK_
(
zero
));
assert
(
false
,
"IMPLEMENT ME"
);
}
}
}
}
switch
(
_rtype
)
{
switch
(
_rtype
)
{
...
@@ -1216,17 +1313,17 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const {
...
@@ -1216,17 +1313,17 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const {
typeArrayHandle
exception_handlers
(
THREAD
,
Universe
::
the_empty_int_array
());
typeArrayHandle
exception_handlers
(
THREAD
,
Universe
::
the_empty_int_array
());
m
->
set_exception_table
(
exception_handlers
());
m
->
set_exception_table
(
exception_handlers
());
// Set the invocation counter's count to the invoke count of the
// original call site.
InvocationCounter
*
ic
=
m
->
invocation_counter
();
ic
->
set
(
InvocationCounter
::
wait_for_compile
,
_invoke_count
);
// Rewrite the method and set up the constant pool cache.
// Rewrite the method and set up the constant pool cache.
objArrayOop
m_array
=
oopFactory
::
new_system_objArray
(
1
,
CHECK_
(
empty
));
objArrayOop
m_array
=
oopFactory
::
new_system_objArray
(
1
,
CHECK_
(
empty
));
objArrayHandle
methods
(
THREAD
,
m_array
);
objArrayHandle
methods
(
THREAD
,
m_array
);
methods
->
obj_at_put
(
0
,
m
());
methods
->
obj_at_put
(
0
,
m
());
Rewriter
::
rewrite
(
_target_klass
(),
cpool
,
methods
,
CHECK_
(
empty
));
// Use fake class.
Rewriter
::
rewrite
(
_target_klass
(),
cpool
,
methods
,
CHECK_
(
empty
));
// Use fake class.
// Set the invocation counter's count to the invoke count of the
// original call site.
InvocationCounter
*
ic
=
m
->
invocation_counter
();
ic
->
set
(
InvocationCounter
::
wait_for_compile
,
_invoke_count
);
// Create a new MDO
// Create a new MDO
{
{
methodDataOop
mdo
=
oopFactory
::
new_methodData
(
m
,
CHECK_
(
empty
));
methodDataOop
mdo
=
oopFactory
::
new_methodData
(
m
,
CHECK_
(
empty
));
...
@@ -1235,10 +1332,12 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const {
...
@@ -1235,10 +1332,12 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const {
// Iterate over all profile data and set the count of the counter
// Iterate over all profile data and set the count of the counter
// data entries to the original call site counter.
// data entries to the original call site counter.
for
(
ProfileData
*
pd
=
mdo
->
first_data
();
mdo
->
is_valid
(
pd
);
pd
=
mdo
->
next_data
(
pd
))
{
for
(
ProfileData
*
profile_data
=
mdo
->
first_data
();
if
(
pd
->
is_CounterData
())
{
mdo
->
is_valid
(
profile_data
);
CounterData
*
cd
=
pd
->
as_CounterData
();
profile_data
=
mdo
->
next_data
(
profile_data
))
{
cd
->
set_count
(
_invoke_count
);
if
(
profile_data
->
is_CounterData
())
{
CounterData
*
counter_data
=
profile_data
->
as_CounterData
();
counter_data
->
set_count
(
_invoke_count
);
}
}
}
}
}
}
...
@@ -1257,7 +1356,6 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const {
...
@@ -1257,7 +1356,6 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const {
#ifndef PRODUCT
#ifndef PRODUCT
#if 0
// MH printer for debugging.
// MH printer for debugging.
class
MethodHandlePrinter
:
public
MethodHandleWalker
{
class
MethodHandlePrinter
:
public
MethodHandleWalker
{
...
@@ -1265,6 +1363,7 @@ private:
...
@@ -1265,6 +1363,7 @@ private:
outputStream
*
_out
;
outputStream
*
_out
;
bool
_verbose
;
bool
_verbose
;
int
_temp_num
;
int
_temp_num
;
int
_param_state
;
stringStream
_strbuf
;
stringStream
_strbuf
;
const
char
*
strbuf
()
{
const
char
*
strbuf
()
{
const
char
*
s
=
_strbuf
.
as_string
();
const
char
*
s
=
_strbuf
.
as_string
();
...
@@ -1272,14 +1371,21 @@ private:
...
@@ -1272,14 +1371,21 @@ private:
return
s
;
return
s
;
}
}
ArgToken
token
(
const
char
*
str
)
{
ArgToken
token
(
const
char
*
str
)
{
return (ArgToken) str;
jvalue
string_con
;
string_con
.
j
=
(
intptr_t
)
str
;
return
ArgToken
(
tt_symbolic
,
T_LONG
,
string_con
);
}
const
char
*
string
(
ArgToken
token
)
{
return
(
const
char
*
)
(
intptr_t
)
token
.
get_jlong
();
}
}
void
start_params
()
{
void
start_params
()
{
_param_state
<<=
1
;
_out
->
print
(
"("
);
_out
->
print
(
"("
);
}
}
void
end_params
()
{
void
end_params
()
{
if
(
_verbose
)
_out
->
print
(
"
\n
"
);
if
(
_verbose
)
_out
->
print
(
"
\n
"
);
_out
->
print
(
") => {"
);
_out
->
print
(
") => {"
);
_param_state
>>=
1
;
}
}
void
put_type_name
(
BasicType
type
,
klassOop
tk
,
outputStream
*
s
)
{
void
put_type_name
(
BasicType
type
,
klassOop
tk
,
outputStream
*
s
)
{
const
char
*
kname
=
NULL
;
const
char
*
kname
=
NULL
;
...
@@ -1299,9 +1405,10 @@ private:
...
@@ -1299,9 +1405,10 @@ private:
public:
public:
MethodHandlePrinter
(
Handle
root
,
bool
verbose
,
outputStream
*
out
,
TRAPS
)
MethodHandlePrinter
(
Handle
root
,
bool
verbose
,
outputStream
*
out
,
TRAPS
)
: MethodHandleWalker(root, THREAD),
:
MethodHandleWalker
(
root
,
false
,
THREAD
),
_out
(
out
),
_out
(
out
),
_verbose
(
verbose
),
_verbose
(
verbose
),
_param_state
(
0
),
_temp_num
(
0
)
_temp_num
(
0
)
{
{
start_params
();
start_params
();
...
@@ -1309,9 +1416,10 @@ public:
...
@@ -1309,9 +1416,10 @@ 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
NULL
;
return
token
(
"return"
)
;
}
}
if (argnum == 0) {
if
((
_param_state
&
1
)
==
0
)
{
_param_state
|=
1
;
_out
->
print
(
_verbose
?
"
\n
"
:
""
);
_out
->
print
(
_verbose
?
"
\n
"
:
""
);
}
else
{
}
else
{
_out
->
print
(
_verbose
?
",
\n
"
:
", "
);
_out
->
print
(
_verbose
?
",
\n
"
:
", "
);
...
@@ -1341,8 +1449,15 @@ public:
...
@@ -1341,8 +1449,15 @@ public:
java_lang_boxing_object
::
print
(
type
,
con
,
&
_strbuf
);
java_lang_boxing_object
::
print
(
type
,
con
,
&
_strbuf
);
return
maybe_make_temp
(
"constant"
,
type
,
"k"
);
return
maybe_make_temp
(
"constant"
,
type
,
"k"
);
}
}
virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, ArgToken src, TRAPS) {
void
print_bytecode_name
(
Bytecodes
::
Code
op
)
{
_strbuf.print("%s(%s", Bytecodes::name(op), (const char*)src);
if
(
Bytecodes
::
is_defined
(
op
))
_strbuf
.
print
(
"%s"
,
Bytecodes
::
name
(
op
));
else
_strbuf
.
print
(
"bytecode_%d"
,
(
int
)
op
);
}
virtual
ArgToken
make_conversion
(
BasicType
type
,
klassOop
tk
,
Bytecodes
::
Code
op
,
const
ArgToken
&
src
,
TRAPS
)
{
print_bytecode_name
(
op
);
_strbuf
.
print
(
"(%s"
,
string
(
src
));
if
(
tk
!=
NULL
)
{
if
(
tk
!=
NULL
)
{
_strbuf
.
print
(
", "
);
_strbuf
.
print
(
", "
);
put_type_name
(
type
,
tk
,
&
_strbuf
);
put_type_name
(
type
,
tk
,
&
_strbuf
);
...
@@ -1350,8 +1465,8 @@ public:
...
@@ -1350,8 +1465,8 @@ public:
_strbuf
.
print
(
")"
);
_strbuf
.
print
(
")"
);
return
maybe_make_temp
(
"convert"
,
type
,
"v"
);
return
maybe_make_temp
(
"convert"
,
type
,
"v"
);
}
}
virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op,
ArgToken base, ArgToken
offset, TRAPS) {
virtual
ArgToken
make_fetch
(
BasicType
type
,
klassOop
tk
,
Bytecodes
::
Code
op
,
const
ArgToken
&
base
,
const
ArgToken
&
offset
,
TRAPS
)
{
_strbuf.print("%s(%s, %s", Bytecodes::name(op),
(const char*)base, (const char*)offset
);
_strbuf
.
print
(
"%s(%s, %s"
,
Bytecodes
::
name
(
op
),
string
(
base
),
string
(
offset
)
);
if
(
tk
!=
NULL
)
{
if
(
tk
!=
NULL
)
{
_strbuf
.
print
(
", "
);
_strbuf
.
print
(
", "
);
put_type_name
(
type
,
tk
,
&
_strbuf
);
put_type_name
(
type
,
tk
,
&
_strbuf
);
...
@@ -1362,7 +1477,8 @@ public:
...
@@ -1362,7 +1477,8 @@ public:
virtual
ArgToken
make_invoke
(
methodOop
m
,
vmIntrinsics
::
ID
iid
,
virtual
ArgToken
make_invoke
(
methodOop
m
,
vmIntrinsics
::
ID
iid
,
Bytecodes
::
Code
op
,
bool
tailcall
,
Bytecodes
::
Code
op
,
bool
tailcall
,
int
argc
,
ArgToken
*
argv
,
TRAPS
)
{
int
argc
,
ArgToken
*
argv
,
TRAPS
)
{
Symbol* name, sig;
Symbol
*
name
;
Symbol
*
sig
;
if
(
m
!=
NULL
)
{
if
(
m
!=
NULL
)
{
name
=
m
->
name
();
name
=
m
->
name
();
sig
=
m
->
signature
();
sig
=
m
->
signature
();
...
@@ -1372,7 +1488,7 @@ public:
...
@@ -1372,7 +1488,7 @@ public:
}
}
_strbuf
.
print
(
"%s %s%s("
,
Bytecodes
::
name
(
op
),
name
->
as_C_string
(),
sig
->
as_C_string
());
_strbuf
.
print
(
"%s %s%s("
,
Bytecodes
::
name
(
op
),
name
->
as_C_string
(),
sig
->
as_C_string
());
for
(
int
i
=
0
;
i
<
argc
;
i
++
)
{
for
(
int
i
=
0
;
i
<
argc
;
i
++
)
{
_strbuf.print("%s%s", (i > 0 ? ", " : ""),
(const char*)argv[i]
);
_strbuf
.
print
(
"%s%s"
,
(
i
>
0
?
", "
:
""
),
string
(
argv
[
i
])
);
}
}
_strbuf
.
print
(
")"
);
_strbuf
.
print
(
")"
);
if
(
!
tailcall
)
{
if
(
!
tailcall
)
{
...
@@ -1410,24 +1526,20 @@ public:
...
@@ -1410,24 +1526,20 @@ public:
if
(
HAS_PENDING_EXCEPTION
)
{
if
(
HAS_PENDING_EXCEPTION
)
{
oop
ex
=
PENDING_EXCEPTION
;
oop
ex
=
PENDING_EXCEPTION
;
CLEAR_PENDING_EXCEPTION
;
CLEAR_PENDING_EXCEPTION
;
out->print("\n*** ");
out
->
print
(
" *** "
);
if (ex != Universe::virtual_machine_error_instance())
if
(
printer
.
lose_message
()
!=
NULL
)
out
->
print
(
"%s "
,
printer
.
lose_message
());
ex->print_on(out);
out
->
print
(
"}"
);
else
out->print("lose: %s", printer.lose_message());
out->print("\n}\n");
}
}
out
->
print
(
"
\n
"
);
out
->
print
(
"
\n
"
);
}
}
};
};
#endif // 0
extern
"C"
extern
"C"
void
print_method_handle
(
oop
mh
)
{
void
print_method_handle
(
oop
mh
)
{
if
(
!
mh
->
is_oop
())
{
if
(
!
mh
->
is_oop
())
{
tty
->
print_cr
(
"*** not a method handle: "
INT
PTR_FORMAT
,
(
intptr_t
)
mh
);
tty
->
print_cr
(
"*** not a method handle: "
PTR_FORMAT
,
(
intptr_t
)
mh
);
}
else
if
(
java_lang_invoke_MethodHandle
::
is_instance
(
mh
))
{
}
else
if
(
java_lang_invoke_MethodHandle
::
is_instance
(
mh
))
{
//
MethodHandlePrinter::print(mh);
MethodHandlePrinter
::
print
(
mh
);
}
else
{
}
else
{
tty
->
print
(
"*** not a method handle: "
);
tty
->
print
(
"*** not a method handle: "
);
mh
->
print
();
mh
->
print
();
...
...
src/share/vm/prims/methodHandleWalk.hpp
浏览文件 @
79bbc02e
...
@@ -113,6 +113,7 @@ public:
...
@@ -113,6 +113,7 @@ public:
tt_parameter
,
tt_parameter
,
tt_temporary
,
tt_temporary
,
tt_constant
,
tt_constant
,
tt_symbolic
,
tt_illegal
tt_illegal
};
};
...
@@ -164,6 +165,10 @@ private:
...
@@ -164,6 +165,10 @@ private:
bool
_for_invokedynamic
;
bool
_for_invokedynamic
;
int
_local_index
;
int
_local_index
;
// This array is kept in an unusual order, indexed by low-level "slot number".
// 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 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
<
SlotState
>
_outgoing
;
// current outgoing parameter slots
int
_outgoing_argc
;
// # non-empty outgoing slots
int
_outgoing_argc
;
// # non-empty outgoing slots
...
@@ -173,6 +178,11 @@ private:
...
@@ -173,6 +178,11 @@ private:
// 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
,
BasicType
new_type
,
const
ArgToken
&
new_arg
);
// Raw retype conversions for OP_RAW_RETYPE.
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_return_type
(
BasicType
src
,
BasicType
dst
,
TRAPS
)
{
retype_raw_conversion
(
src
,
dst
,
true
,
-
1
,
CHECK
);
}
SlotState
*
slot_state
(
int
slot
)
{
SlotState
*
slot_state
(
int
slot
)
{
if
(
slot
<
0
||
slot
>=
_outgoing
.
length
())
if
(
slot
<
0
||
slot
>=
_outgoing
.
length
())
return
NULL
;
return
NULL
;
...
@@ -221,12 +231,12 @@ public:
...
@@ -221,12 +231,12 @@ public:
int
max_locals
()
const
{
return
_local_index
;
}
int
max_locals
()
const
{
return
_local_index
;
}
// plug-in abstract interpretation steps:
// plug-in abstract interpretation steps:
virtual
ArgToken
make_parameter
(
BasicType
type
,
klassOop
tk
,
int
argnum
,
TRAPS
)
=
0
;
virtual
ArgToken
make_parameter
(
BasicType
type
,
klassOop
tk
,
int
argnum
,
TRAPS
)
=
0
;
virtual
ArgToken
make_prim_constant
(
BasicType
type
,
jvalue
*
con
,
TRAPS
)
=
0
;
virtual
ArgToken
make_prim_constant
(
BasicType
type
,
jvalue
*
con
,
TRAPS
)
=
0
;
virtual
ArgToken
make_oop_constant
(
oop
con
,
TRAPS
)
=
0
;
virtual
ArgToken
make_oop_constant
(
oop
con
,
TRAPS
)
=
0
;
virtual
ArgToken
make_conversion
(
BasicType
type
,
klassOop
tk
,
Bytecodes
::
Code
op
,
const
ArgToken
&
src
,
TRAPS
)
=
0
;
virtual
ArgToken
make_conversion
(
BasicType
type
,
klassOop
tk
,
Bytecodes
::
Code
op
,
const
ArgToken
&
src
,
TRAPS
)
=
0
;
virtual
ArgToken
make_fetch
(
BasicType
type
,
klassOop
tk
,
Bytecodes
::
Code
op
,
const
ArgToken
&
base
,
const
ArgToken
&
offset
,
TRAPS
)
=
0
;
virtual
ArgToken
make_fetch
(
BasicType
type
,
klassOop
tk
,
Bytecodes
::
Code
op
,
const
ArgToken
&
base
,
const
ArgToken
&
offset
,
TRAPS
)
=
0
;
virtual
ArgToken
make_invoke
(
methodOop
m
,
vmIntrinsics
::
ID
iid
,
Bytecodes
::
Code
op
,
bool
tailcall
,
int
argc
,
ArgToken
*
argv
,
TRAPS
)
=
0
;
virtual
ArgToken
make_invoke
(
methodOop
m
,
vmIntrinsics
::
ID
iid
,
Bytecodes
::
Code
op
,
bool
tailcall
,
int
argc
,
ArgToken
*
argv
,
TRAPS
)
=
0
;
// For make_invoke, the methodOop can be NULL if the intrinsic ID
// For make_invoke, the methodOop can be NULL if the intrinsic ID
// is something other than vmIntrinsics::_none.
// is something other than vmIntrinsics::_none.
...
@@ -253,6 +263,10 @@ private:
...
@@ -253,6 +263,10 @@ private:
KlassHandle
_target_klass
;
KlassHandle
_target_klass
;
Thread
*
_thread
;
Thread
*
_thread
;
// Values used by the compiler.
static
jvalue
zero_jvalue
;
static
jvalue
one_jvalue
;
// Fake constant pool entry.
// Fake constant pool entry.
class
ConstantValue
{
class
ConstantValue
{
private:
private:
...
@@ -417,7 +431,7 @@ private:
...
@@ -417,7 +431,7 @@ private:
methodHandle
get_method_oop
(
TRAPS
)
const
;
methodHandle
get_method_oop
(
TRAPS
)
const
;
public:
public:
MethodHandleCompiler
(
Handle
root
,
methodHandle
call
_method
,
int
invoke_count
,
bool
for_invokedynamic
,
TRAPS
);
MethodHandleCompiler
(
Handle
root
,
methodHandle
call
ee
,
int
invoke_count
,
bool
for_invokedynamic
,
TRAPS
);
// Compile the given MH chain into bytecode.
// Compile the given MH chain into bytecode.
methodHandle
compile
(
TRAPS
);
methodHandle
compile
(
TRAPS
);
...
...
src/share/vm/prims/methodHandles.cpp
浏览文件 @
79bbc02e
...
@@ -1099,6 +1099,14 @@ static oop object_java_mirror() {
...
@@ -1099,6 +1099,14 @@ static oop object_java_mirror() {
return
Klass
::
cast
(
SystemDictionary
::
Object_klass
())
->
java_mirror
();
return
Klass
::
cast
(
SystemDictionary
::
Object_klass
())
->
java_mirror
();
}
}
bool
MethodHandles
::
is_float_fixed_reinterpretation_cast
(
BasicType
src
,
BasicType
dst
)
{
if
(
src
==
T_FLOAT
)
return
dst
==
T_INT
;
if
(
src
==
T_INT
)
return
dst
==
T_FLOAT
;
if
(
src
==
T_DOUBLE
)
return
dst
==
T_LONG
;
if
(
src
==
T_LONG
)
return
dst
==
T_DOUBLE
;
return
false
;
}
bool
MethodHandles
::
same_basic_type_for_arguments
(
BasicType
src
,
bool
MethodHandles
::
same_basic_type_for_arguments
(
BasicType
src
,
BasicType
dst
,
BasicType
dst
,
bool
raw
,
bool
raw
,
...
@@ -1125,10 +1133,8 @@ bool MethodHandles::same_basic_type_for_arguments(BasicType src,
...
@@ -1125,10 +1133,8 @@ bool MethodHandles::same_basic_type_for_arguments(BasicType src,
return
true
;
// remaining case: byte fits in short
return
true
;
// remaining case: byte fits in short
}
}
// allow float/fixed reinterpretation casts
// allow float/fixed reinterpretation casts
if
(
src
==
T_FLOAT
)
return
dst
==
T_INT
;
if
(
is_float_fixed_reinterpretation_cast
(
src
,
dst
))
if
(
src
==
T_INT
)
return
dst
==
T_FLOAT
;
return
true
;
if
(
src
==
T_DOUBLE
)
return
dst
==
T_LONG
;
if
(
src
==
T_LONG
)
return
dst
==
T_DOUBLE
;
return
false
;
return
false
;
}
}
...
@@ -1399,7 +1405,7 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
...
@@ -1399,7 +1405,7 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
int
argnum
,
int
argnum
,
bool
raw
)
{
bool
raw
)
{
const
char
*
err
=
NULL
;
const
char
*
err
=
NULL
;
bool
for_return
=
(
argnum
<
0
);
const
bool
for_return
=
(
argnum
<
0
);
// just in case:
// just in case:
if
(
src_type
==
T_ARRAY
)
src_type
=
T_OBJECT
;
if
(
src_type
==
T_ARRAY
)
src_type
=
T_OBJECT
;
...
@@ -1408,17 +1414,17 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
...
@@ -1408,17 +1414,17 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
// Produce some nice messages if VerifyMethodHandles is turned on:
// Produce some nice messages if VerifyMethodHandles is turned on:
if
(
!
same_basic_type_for_arguments
(
src_type
,
dst_type
,
raw
,
for_return
))
{
if
(
!
same_basic_type_for_arguments
(
src_type
,
dst_type
,
raw
,
for_return
))
{
if
(
src_type
==
T_OBJECT
)
{
if
(
src_type
==
T_OBJECT
)
{
if
(
raw
&&
dst_type
==
T_INT
&&
is_always_null_type
(
src_klass
))
if
(
raw
&&
is_java_primitive
(
dst_type
))
return
NULL
;
//
OK to convert a null pointer to a garbage int
return
NULL
;
//
ref-to-prim discards ref and returns zero
err
=
(
(
argnum
>=
0
)
err
=
(
!
for_return
?
"type mismatch: passing a %s for method argument #%d, which expects primitive %s"
?
"type mismatch: passing a %s for method argument #%d, which expects primitive %s"
:
"type mismatch: returning a %s, but caller expects primitive %s"
);
:
"type mismatch: returning a %s, but caller expects primitive %s"
);
}
else
if
(
dst_type
==
T_OBJECT
)
{
}
else
if
(
dst_type
==
T_OBJECT
)
{
err
=
(
(
argnum
>=
0
)
err
=
(
!
for_return
?
"type mismatch: passing a primitive %s for method argument #%d, which expects %s"
?
"type mismatch: passing a primitive %s for method argument #%d, which expects %s"
:
"type mismatch: returning a primitive %s, but caller expects %s"
);
:
"type mismatch: returning a primitive %s, but caller expects %s"
);
}
else
{
}
else
{
err
=
(
(
argnum
>=
0
)
err
=
(
!
for_return
?
"type mismatch: passing a %s for method argument #%d, which expects %s"
?
"type mismatch: passing a %s for method argument #%d, which expects %s"
:
"type mismatch: returning a %s, but caller expects %s"
);
:
"type mismatch: returning a %s, but caller expects %s"
);
}
}
...
@@ -1427,11 +1433,11 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
...
@@ -1427,11 +1433,11 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
if
(
!
class_cast_needed
(
dst_klass
,
src_klass
))
{
if
(
!
class_cast_needed
(
dst_klass
,
src_klass
))
{
if
(
raw
)
if
(
raw
)
return
NULL
;
// reverse cast is OK; the MH target is trusted to enforce it
return
NULL
;
// reverse cast is OK; the MH target is trusted to enforce it
err
=
(
(
argnum
>=
0
)
err
=
(
!
for_return
?
"cast required: passing a %s for method argument #%d, which expects %s"
?
"cast required: passing a %s for method argument #%d, which expects %s"
:
"cast required: returning a %s, but caller expects %s"
);
:
"cast required: returning a %s, but caller expects %s"
);
}
else
{
}
else
{
err
=
(
(
argnum
>=
0
)
err
=
(
!
for_return
?
"reference mismatch: passing a %s for method argument #%d, which expects %s"
?
"reference mismatch: passing a %s for method argument #%d, which expects %s"
:
"reference mismatch: returning a %s, but caller expects %s"
);
:
"reference mismatch: returning a %s, but caller expects %s"
);
}
}
...
@@ -1452,7 +1458,7 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
...
@@ -1452,7 +1458,7 @@ const char* MethodHandles::check_argument_type_change(BasicType src_type,
size_t
msglen
=
strlen
(
err
)
+
strlen
(
src_name
)
+
strlen
(
dst_name
)
+
(
argnum
<
10
?
1
:
11
);
size_t
msglen
=
strlen
(
err
)
+
strlen
(
src_name
)
+
strlen
(
dst_name
)
+
(
argnum
<
10
?
1
:
11
);
char
*
msg
=
NEW_RESOURCE_ARRAY
(
char
,
msglen
+
1
);
char
*
msg
=
NEW_RESOURCE_ARRAY
(
char
,
msglen
+
1
);
if
(
argnum
>=
0
)
{
if
(
!
for_return
)
{
assert
(
strstr
(
err
,
"%d"
)
!=
NULL
,
""
);
assert
(
strstr
(
err
,
"%d"
)
!=
NULL
,
""
);
jio_snprintf
(
msg
,
msglen
,
err
,
src_name
,
argnum
,
dst_name
);
jio_snprintf
(
msg
,
msglen
,
err
,
src_name
,
argnum
,
dst_name
);
}
else
{
}
else
{
...
@@ -2180,9 +2186,10 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
...
@@ -2180,9 +2186,10 @@ void MethodHandles::verify_AdapterMethodHandle(Handle mh, int argnum, TRAPS) {
}
}
void
MethodHandles
::
init_AdapterMethodHandle
(
Handle
mh
,
Handle
target
,
int
argnum
,
TRAPS
)
{
void
MethodHandles
::
init_AdapterMethodHandle
(
Handle
mh
,
Handle
target
,
int
argnum
,
TRAPS
)
{
int
argslot
=
java_lang_invoke_AdapterMethodHandle
::
vmargslot
(
mh
());
Handle
argument
=
java_lang_invoke_AdapterMethodHandle
::
argument
(
mh
());
jint
conversion
=
java_lang_invoke_AdapterMethodHandle
::
conversion
(
mh
());
int
argslot
=
java_lang_invoke_AdapterMethodHandle
::
vmargslot
(
mh
());
jint
conv_op
=
adapter_conversion_op
(
conversion
);
jint
conversion
=
java_lang_invoke_AdapterMethodHandle
::
conversion
(
mh
());
jint
conv_op
=
adapter_conversion_op
(
conversion
);
// adjust the adapter code to the internal EntryKind enumeration:
// adjust the adapter code to the internal EntryKind enumeration:
EntryKind
ek_orig
=
adapter_entry_kind
(
conv_op
);
EntryKind
ek_orig
=
adapter_entry_kind
(
conv_op
);
...
@@ -2241,7 +2248,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
...
@@ -2241,7 +2248,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
}
else
if
(
src
==
T_DOUBLE
&&
dest
==
T_FLOAT
)
{
}
else
if
(
src
==
T_DOUBLE
&&
dest
==
T_FLOAT
)
{
ek_opt
=
_adapter_opt_d2f
;
ek_opt
=
_adapter_opt_d2f
;
}
else
{
}
else
{
assert
(
false
,
""
);
goto
throw_not_impl
;
// runs user code, hence could block
}
}
break
;
break
;
case
1
*
4
+
2
:
case
1
*
4
+
2
:
...
@@ -2250,11 +2257,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
...
@@ -2250,11 +2257,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
}
else
if
(
src
==
T_FLOAT
&&
dest
==
T_DOUBLE
)
{
}
else
if
(
src
==
T_FLOAT
&&
dest
==
T_DOUBLE
)
{
ek_opt
=
_adapter_opt_f2d
;
ek_opt
=
_adapter_opt_f2d
;
}
else
{
}
else
{
assert
(
false
,
""
);
goto
throw_not_impl
;
// runs user code, hence could block
}
}
break
;
break
;
default:
default:
assert
(
false
,
""
);
goto
throw_not_impl
;
// runs user code, hence could block
break
;
break
;
}
}
}
}
...
@@ -2271,7 +2278,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
...
@@ -2271,7 +2278,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
ek_opt
=
_adapter_opt_unboxl
;
ek_opt
=
_adapter_opt_unboxl
;
break
;
break
;
default:
default:
assert
(
false
,
""
)
;
goto
throw_not_impl
;
break
;
break
;
}
}
}
}
...
@@ -2284,6 +2291,9 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
...
@@ -2284,6 +2291,9 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
vminfo
=
argslot
;
vminfo
=
argslot
;
ek_opt
=
_adapter_opt_collect_ref
;
ek_opt
=
_adapter_opt_collect_ref
;
ensure_vmlayout_field
(
target
,
CHECK
);
ensure_vmlayout_field
(
target
,
CHECK
);
// for MethodHandleWalk:
if
(
java_lang_invoke_AdapterMethodHandle
::
is_instance
(
argument
()))
ensure_vmlayout_field
(
argument
,
CHECK
);
if
(
!
OptimizeMethodHandles
)
break
;
if
(
!
OptimizeMethodHandles
)
break
;
switch
(
type2size
[
src
])
{
switch
(
type2size
[
src
])
{
case
1
:
case
1
:
...
@@ -2311,7 +2321,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
...
@@ -2311,7 +2321,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
ek_opt
=
_adapter_opt_collect_2_ref
;
ek_opt
=
_adapter_opt_collect_2_ref
;
break
;
break
;
default:
default:
assert
(
false
,
""
)
;
goto
throw_not_impl
;
break
;
break
;
}
}
}
}
...
@@ -2335,7 +2345,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
...
@@ -2335,7 +2345,7 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
rotate
>
0
?
_adapter_opt_rot_2_up
:
_adapter_opt_rot_2_down
);
rotate
>
0
?
_adapter_opt_rot_2_up
:
_adapter_opt_rot_2_down
);
break
;
break
;
default:
default:
assert
(
false
,
""
)
;
goto
throw_not_impl
;
break
;
break
;
}
}
}
}
...
@@ -2402,12 +2412,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
...
@@ -2402,12 +2412,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
case
_adapter_collect_args
:
case
_adapter_collect_args
:
{
{
assert
(
UseRicochetFrames
,
"else don't come here"
);
assert
(
UseRicochetFrames
,
"else don't come here"
);
int
elem_slots
=
argument_slot_count
(
int
elem_slots
=
argument_slot_count
(
java_lang_invoke_MethodHandle
::
type
(
argument
()));
java_lang_invoke_MethodHandle
::
type
(
java_lang_invoke_AdapterMethodHandle
::
argument
(
mh
())
)
);
// vminfo will be the location to insert the return value
// vminfo will be the location to insert the return value
vminfo
=
argslot
;
vminfo
=
argslot
;
ensure_vmlayout_field
(
target
,
CHECK
);
ensure_vmlayout_field
(
target
,
CHECK
);
ensure_vmlayout_field
(
argument
,
CHECK
);
// general case:
// general case:
switch
(
dest
)
{
switch
(
dest
)
{
...
@@ -2472,12 +2481,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
...
@@ -2472,12 +2481,11 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
case
_adapter_fold_args
:
case
_adapter_fold_args
:
{
{
assert
(
UseRicochetFrames
,
"else don't come here"
);
assert
(
UseRicochetFrames
,
"else don't come here"
);
int
elem_slots
=
argument_slot_count
(
int
elem_slots
=
argument_slot_count
(
java_lang_invoke_MethodHandle
::
type
(
argument
()));
java_lang_invoke_MethodHandle
::
type
(
java_lang_invoke_AdapterMethodHandle
::
argument
(
mh
())
)
);
// vminfo will be the location to insert the return value
// vminfo will be the location to insert the return value
vminfo
=
argslot
+
elem_slots
;
vminfo
=
argslot
+
elem_slots
;
ensure_vmlayout_field
(
target
,
CHECK
);
ensure_vmlayout_field
(
target
,
CHECK
);
ensure_vmlayout_field
(
argument
,
CHECK
);
switch
(
dest
)
{
switch
(
dest
)
{
default
:
if
(
!
is_subword_type
(
dest
))
goto
throw_not_impl
;
default
:
if
(
!
is_subword_type
(
dest
))
goto
throw_not_impl
;
...
@@ -2527,15 +2535,31 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
...
@@ -2527,15 +2535,31 @@ void MethodHandles::init_AdapterMethodHandle(Handle mh, Handle target, int argnu
break
;
break
;
}
}
if
(
err
!
=
NULL
&&
(
vminfo
&
CONV_VMINFO_MASK
)
!=
vminfo
)
{
if
(
err
=
=
NULL
&&
(
vminfo
&
CONV_VMINFO_MASK
)
!=
vminfo
)
{
// should not happen, since vminfo is used to encode arg/slot indexes < 255
// should not happen, since vminfo is used to encode arg/slot indexes < 255
err
=
"vminfo overflow"
;
err
=
"vminfo overflow"
;
}
}
if
(
err
!
=
NULL
&&
!
have_entry
(
ek_opt
))
{
if
(
err
=
=
NULL
&&
!
have_entry
(
ek_opt
))
{
err
=
"adapter stub for this kind of method handle is missing"
;
err
=
"adapter stub for this kind of method handle is missing"
;
}
}
if
(
err
==
NULL
&&
ek_opt
==
ek_orig
)
{
switch
(
ek_opt
)
{
case
_adapter_prim_to_prim
:
case
_adapter_ref_to_prim
:
case
_adapter_prim_to_ref
:
case
_adapter_swap_args
:
case
_adapter_rot_args
:
case
_adapter_collect_args
:
case
_adapter_fold_args
:
case
_adapter_spread_args
:
// should be handled completely by optimized cases; see above
err
=
"init_AdapterMethodHandle should not issue this"
;
break
;
}
}
if
(
err
!=
NULL
)
{
if
(
err
!=
NULL
)
{
throw_InternalError_for_bad_conversion
(
conversion
,
err
,
THREAD
);
throw_InternalError_for_bad_conversion
(
conversion
,
err
,
THREAD
);
return
;
return
;
...
...
src/share/vm/prims/methodHandles.hpp
浏览文件 @
79bbc02e
...
@@ -698,6 +698,8 @@ class MethodHandles: AllStatic {
...
@@ -698,6 +698,8 @@ class MethodHandles: AllStatic {
KlassHandle
receiver_klass
,
KlassHandle
receiver_klass
,
TRAPS
);
TRAPS
);
public:
static
bool
is_float_fixed_reinterpretation_cast
(
BasicType
src
,
BasicType
dst
);
static
bool
same_basic_type_for_arguments
(
BasicType
src
,
BasicType
dst
,
static
bool
same_basic_type_for_arguments
(
BasicType
src
,
BasicType
dst
,
bool
raw
=
false
,
bool
raw
=
false
,
bool
for_return
=
false
);
bool
for_return
=
false
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录