Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
7689f3c9
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看板
提交
7689f3c9
编写于
9月 01, 2011
作者:
T
twisti
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
7079673: JSR 292: C1 should inline bytecoded method handle adapters
Reviewed-by: never
上级
2ceba375
变更
9
隐藏空白更改
内联
并排
Showing
9 changed file
with
241 addition
and
78 deletion
+241
-78
src/share/vm/c1/c1_GraphBuilder.cpp
src/share/vm/c1/c1_GraphBuilder.cpp
+162
-37
src/share/vm/c1/c1_GraphBuilder.hpp
src/share/vm/c1/c1_GraphBuilder.hpp
+15
-3
src/share/vm/c1/c1_Instruction.cpp
src/share/vm/c1/c1_Instruction.cpp
+20
-15
src/share/vm/c1/c1_Instruction.hpp
src/share/vm/c1/c1_Instruction.hpp
+1
-0
src/share/vm/classfile/javaClasses.cpp
src/share/vm/classfile/javaClasses.cpp
+12
-0
src/share/vm/classfile/vmSymbols.hpp
src/share/vm/classfile/vmSymbols.hpp
+3
-0
src/share/vm/opto/bytecodeInfo.cpp
src/share/vm/opto/bytecodeInfo.cpp
+23
-5
src/share/vm/opto/callGenerator.cpp
src/share/vm/opto/callGenerator.cpp
+3
-18
src/share/vm/opto/parse.hpp
src/share/vm/opto/parse.hpp
+2
-0
未找到文件。
src/share/vm/c1/c1_GraphBuilder.cpp
浏览文件 @
7689f3c9
...
@@ -28,8 +28,10 @@
...
@@ -28,8 +28,10 @@
#include "c1/c1_Compilation.hpp"
#include "c1/c1_Compilation.hpp"
#include "c1/c1_GraphBuilder.hpp"
#include "c1/c1_GraphBuilder.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "ci/ciCallSite.hpp"
#include "ci/ciField.hpp"
#include "ci/ciField.hpp"
#include "ci/ciKlass.hpp"
#include "ci/ciKlass.hpp"
#include "ci/ciMethodHandle.hpp"
#include "compiler/compileBroker.hpp"
#include "compiler/compileBroker.hpp"
#include "interpreter/bytecode.hpp"
#include "interpreter/bytecode.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/sharedRuntime.hpp"
...
@@ -1424,7 +1426,7 @@ void GraphBuilder::method_return(Value x) {
...
@@ -1424,7 +1426,7 @@ void GraphBuilder::method_return(Value x) {
// See whether this is the first return; if so, store off some
// See whether this is the first return; if so, store off some
// of the state for later examination
// of the state for later examination
if
(
num_returns
()
==
0
)
{
if
(
num_returns
()
==
0
)
{
set_inline_cleanup_info
(
_block
,
_last
,
state
()
);
set_inline_cleanup_info
();
}
}
// The current bci() is in the wrong scope, so use the bci() of
// The current bci() is in the wrong scope, so use the bci() of
...
@@ -1582,6 +1584,8 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
...
@@ -1582,6 +1584,8 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
code
=
Bytecodes
::
_invokespecial
;
code
=
Bytecodes
::
_invokespecial
;
}
}
bool
is_invokedynamic
=
code
==
Bytecodes
::
_invokedynamic
;
// NEEDS_CLEANUP
// NEEDS_CLEANUP
// I've added the target-is_loaded() test below but I don't really understand
// I've added the target-is_loaded() test below but I don't really understand
// how klass->is_loaded() can be true and yet target->is_loaded() is false.
// how klass->is_loaded() can be true and yet target->is_loaded() is false.
...
@@ -1693,26 +1697,31 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
...
@@ -1693,26 +1697,31 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
&&
target
->
will_link
(
klass
,
callee_holder
,
code
))
{
&&
target
->
will_link
(
klass
,
callee_holder
,
code
))
{
// callee is known => check if we have static binding
// callee is known => check if we have static binding
assert
(
target
->
is_loaded
(),
"callee must be known"
);
assert
(
target
->
is_loaded
(),
"callee must be known"
);
if
(
code
==
Bytecodes
::
_invokestatic
if
(
code
==
Bytecodes
::
_invokestatic
||
||
code
==
Bytecodes
::
_invokespecial
code
==
Bytecodes
::
_invokespecial
||
||
code
==
Bytecodes
::
_invokevirtual
&&
target
->
is_final_method
()
code
==
Bytecodes
::
_invokevirtual
&&
target
->
is_final_method
()
||
)
{
code
==
Bytecodes
::
_invokedynamic
)
{
// static binding => check if callee is ok
ciMethod
*
inline_target
=
(
cha_monomorphic_target
!=
NULL
)
?
cha_monomorphic_target
:
target
;
ciMethod
*
inline_target
=
(
cha_monomorphic_target
!=
NULL
)
bool
success
=
false
;
?
cha_monomorphic_target
if
(
target
->
is_method_handle_invoke
())
{
:
target
;
// method handle invokes
bool
res
=
try_inline
(
inline_target
,
(
cha_monomorphic_target
!=
NULL
)
||
(
exact_target
!=
NULL
));
success
=
!
is_invokedynamic
?
for_method_handle_inline
(
target
)
:
for_invokedynamic_inline
(
target
);
}
if
(
!
success
)
{
// static binding => check if callee is ok
success
=
try_inline
(
inline_target
,
(
cha_monomorphic_target
!=
NULL
)
||
(
exact_target
!=
NULL
));
}
CHECK_BAILOUT
();
CHECK_BAILOUT
();
#ifndef PRODUCT
#ifndef PRODUCT
// printing
// printing
if
(
PrintInlining
&&
!
re
s
)
{
if
(
PrintInlining
&&
!
succes
s
)
{
// if it was successfully inlined, then it was already printed.
// if it was successfully inlined, then it was already printed.
print_inline_result
(
inline_target
,
re
s
);
print_inline_result
(
inline_target
,
succes
s
);
}
}
#endif
#endif
clear_inline_bailout
();
clear_inline_bailout
();
if
(
re
s
)
{
if
(
succes
s
)
{
// Register dependence if JVMTI has either breakpoint
// Register dependence if JVMTI has either breakpoint
// setting or hotswapping of methods capabilities since they may
// setting or hotswapping of methods capabilities since they may
// cause deoptimization.
// cause deoptimization.
...
@@ -1740,7 +1749,6 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
...
@@ -1740,7 +1749,6 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
code
==
Bytecodes
::
_invokespecial
||
code
==
Bytecodes
::
_invokespecial
||
code
==
Bytecodes
::
_invokevirtual
||
code
==
Bytecodes
::
_invokevirtual
||
code
==
Bytecodes
::
_invokeinterface
;
code
==
Bytecodes
::
_invokeinterface
;
bool
is_invokedynamic
=
code
==
Bytecodes
::
_invokedynamic
;
ValueType
*
result_type
=
as_ValueType
(
target
->
return_type
());
ValueType
*
result_type
=
as_ValueType
(
target
->
return_type
());
// We require the debug info to be the "state before" because
// We require the debug info to be the "state before" because
...
@@ -3038,7 +3046,7 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known) {
...
@@ -3038,7 +3046,7 @@ bool GraphBuilder::try_inline(ciMethod* callee, bool holder_known) {
INLINE_BAILOUT
(
"disallowed by CompilerOracle"
)
INLINE_BAILOUT
(
"disallowed by CompilerOracle"
)
}
else
if
(
!
callee
->
can_be_compiled
())
{
}
else
if
(
!
callee
->
can_be_compiled
())
{
// callee is not compilable (prob. has breakpoints)
// callee is not compilable (prob. has breakpoints)
INLINE_BAILOUT
(
"not compilable"
)
INLINE_BAILOUT
(
"not compilable
(disabled)
"
)
}
else
if
(
callee
->
intrinsic_id
()
!=
vmIntrinsics
::
_none
&&
try_inline_intrinsics
(
callee
))
{
}
else
if
(
callee
->
intrinsic_id
()
!=
vmIntrinsics
::
_none
&&
try_inline_intrinsics
(
callee
))
{
// intrinsics can be native or not
// intrinsics can be native or not
return
true
;
return
true
;
...
@@ -3397,7 +3405,7 @@ void GraphBuilder::fill_sync_handler(Value lock, BlockBegin* sync_handler, bool
...
@@ -3397,7 +3405,7 @@ void GraphBuilder::fill_sync_handler(Value lock, BlockBegin* sync_handler, bool
}
}
bool
GraphBuilder
::
try_inline_full
(
ciMethod
*
callee
,
bool
holder_known
)
{
bool
GraphBuilder
::
try_inline_full
(
ciMethod
*
callee
,
bool
holder_known
,
BlockBegin
*
cont_block
)
{
assert
(
!
callee
->
is_native
(),
"callee must not be native"
);
assert
(
!
callee
->
is_native
(),
"callee must not be native"
);
if
(
CompilationPolicy
::
policy
()
->
should_not_inline
(
compilation
()
->
env
(),
callee
))
{
if
(
CompilationPolicy
::
policy
()
->
should_not_inline
(
compilation
()
->
env
(),
callee
))
{
INLINE_BAILOUT
(
"inlining prohibited by policy"
);
INLINE_BAILOUT
(
"inlining prohibited by policy"
);
...
@@ -3468,7 +3476,8 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) {
...
@@ -3468,7 +3476,8 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) {
// Insert null check if necessary
// Insert null check if necessary
Value
recv
=
NULL
;
Value
recv
=
NULL
;
if
(
code
()
!=
Bytecodes
::
_invokestatic
)
{
if
(
code
()
!=
Bytecodes
::
_invokestatic
&&
code
()
!=
Bytecodes
::
_invokedynamic
)
{
// note: null check must happen even if first instruction of callee does
// note: null check must happen even if first instruction of callee does
// an implicit null check since the callee is in a different scope
// an implicit null check since the callee is in a different scope
// and we must make sure exception handling does the right thing
// and we must make sure exception handling does the right thing
...
@@ -3496,7 +3505,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) {
...
@@ -3496,7 +3505,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) {
// fall-through of control flow, all return instructions of the
// fall-through of control flow, all return instructions of the
// callee will need to be replaced by Goto's pointing to this
// callee will need to be replaced by Goto's pointing to this
// continuation point.
// continuation point.
BlockBegin
*
cont
=
block_at
(
next_bci
());
BlockBegin
*
cont
=
cont_block
!=
NULL
?
cont_block
:
block_at
(
next_bci
());
bool
continuation_existed
=
true
;
bool
continuation_existed
=
true
;
if
(
cont
==
NULL
)
{
if
(
cont
==
NULL
)
{
cont
=
new
BlockBegin
(
next_bci
());
cont
=
new
BlockBegin
(
next_bci
());
...
@@ -3608,27 +3617,29 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) {
...
@@ -3608,27 +3617,29 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) {
// block merging. This allows load elimination and CSE to take place
// block merging. This allows load elimination and CSE to take place
// across multiple callee scopes if they are relatively simple, and
// across multiple callee scopes if they are relatively simple, and
// is currently essential to making inlining profitable.
// is currently essential to making inlining profitable.
if
(
num_returns
()
==
1
if
(
cont_block
==
NULL
)
{
&&
block
()
==
orig_block
if
(
num_returns
()
==
1
&&
block
()
==
inline_cleanup_block
())
{
&&
block
()
==
orig_block
_last
=
inline_cleanup_return_prev
();
&&
block
()
==
inline_cleanup_block
())
{
_state
=
inline_cleanup_state
();
_last
=
inline_cleanup_return_prev
();
}
else
if
(
continuation_preds
==
cont
->
number_of_preds
())
{
_state
=
inline_cleanup_state
();
// Inlining caused that the instructions after the invoke in the
}
else
if
(
continuation_preds
==
cont
->
number_of_preds
())
{
// caller are not reachable any more. So skip filling this block
// Inlining caused that the instructions after the invoke in the
// with instructions!
// caller are not reachable any more. So skip filling this block
assert
(
cont
==
continuation
(),
""
);
// with instructions!
assert
(
_last
&&
_last
->
as_BlockEnd
(),
""
);
assert
(
cont
==
continuation
(),
""
);
_skip_block
=
true
;
}
else
{
// Resume parsing in continuation block unless it was already parsed.
// Note that if we don't change _last here, iteration in
// iterate_bytecodes_for_block will stop when we return.
if
(
!
continuation
()
->
is_set
(
BlockBegin
::
was_visited_flag
))
{
// add continuation to work list instead of parsing it immediately
assert
(
_last
&&
_last
->
as_BlockEnd
(),
""
);
assert
(
_last
&&
_last
->
as_BlockEnd
(),
""
);
scope_data
()
->
parent
()
->
add_to_work_list
(
continuation
());
_skip_block
=
true
;
_skip_block
=
true
;
}
else
{
// Resume parsing in continuation block unless it was already parsed.
// Note that if we don't change _last here, iteration in
// iterate_bytecodes_for_block will stop when we return.
if
(
!
continuation
()
->
is_set
(
BlockBegin
::
was_visited_flag
))
{
// add continuation to work list instead of parsing it immediately
assert
(
_last
&&
_last
->
as_BlockEnd
(),
""
);
scope_data
()
->
parent
()
->
add_to_work_list
(
continuation
());
_skip_block
=
true
;
}
}
}
}
}
...
@@ -3645,6 +3656,120 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) {
...
@@ -3645,6 +3656,120 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) {
}
}
bool
GraphBuilder
::
for_method_handle_inline
(
ciMethod
*
callee
)
{
assert
(
!
callee
->
is_static
(),
"change next line"
);
int
index
=
state
()
->
stack_size
()
-
(
callee
->
arg_size_no_receiver
()
+
1
);
Value
receiver
=
state
()
->
stack_at
(
index
);
if
(
receiver
->
type
()
->
is_constant
())
{
ciMethodHandle
*
method_handle
=
receiver
->
type
()
->
as_ObjectType
()
->
constant_value
()
->
as_method_handle
();
// Set the callee to have access to the class and signature in
// the MethodHandleCompiler.
method_handle
->
set_callee
(
callee
);
method_handle
->
set_caller
(
method
());
// Get an adapter for the MethodHandle.
ciMethod
*
method_handle_adapter
=
method_handle
->
get_method_handle_adapter
();
if
(
method_handle_adapter
!=
NULL
)
{
return
try_inline
(
method_handle_adapter
,
/*holder_known=*/
true
);
}
}
else
if
(
receiver
->
as_CheckCast
())
{
// Match MethodHandle.selectAlternative idiom
Phi
*
phi
=
receiver
->
as_CheckCast
()
->
obj
()
->
as_Phi
();
if
(
phi
!=
NULL
&&
phi
->
operand_count
()
==
2
)
{
// Get the two MethodHandle inputs from the Phi.
Value
op1
=
phi
->
operand_at
(
0
);
Value
op2
=
phi
->
operand_at
(
1
);
ciMethodHandle
*
mh1
=
op1
->
type
()
->
as_ObjectType
()
->
constant_value
()
->
as_method_handle
();
ciMethodHandle
*
mh2
=
op2
->
type
()
->
as_ObjectType
()
->
constant_value
()
->
as_method_handle
();
// Set the callee to have access to the class and signature in
// the MethodHandleCompiler.
mh1
->
set_callee
(
callee
);
mh1
->
set_caller
(
method
());
mh2
->
set_callee
(
callee
);
mh2
->
set_caller
(
method
());
// Get adapters for the MethodHandles.
ciMethod
*
mh1_adapter
=
mh1
->
get_method_handle_adapter
();
ciMethod
*
mh2_adapter
=
mh2
->
get_method_handle_adapter
();
if
(
mh1_adapter
!=
NULL
&&
mh2_adapter
!=
NULL
)
{
set_inline_cleanup_info
();
// Build the If guard
BlockBegin
*
one
=
new
BlockBegin
(
next_bci
());
BlockBegin
*
two
=
new
BlockBegin
(
next_bci
());
BlockBegin
*
end
=
new
BlockBegin
(
next_bci
());
Instruction
*
iff
=
append
(
new
If
(
phi
,
If
::
eql
,
false
,
op1
,
one
,
two
,
NULL
,
false
));
block
()
->
set_end
(
iff
->
as_BlockEnd
());
// Connect up the states
one
->
merge
(
block
()
->
end
()
->
state
());
two
->
merge
(
block
()
->
end
()
->
state
());
// Save the state for the second inlinee
ValueStack
*
state_before
=
copy_state_before
();
// Parse first adapter
_last
=
_block
=
one
;
if
(
!
try_inline_full
(
mh1_adapter
,
/*holder_known=*/
true
,
end
))
{
restore_inline_cleanup_info
();
block
()
->
clear_end
();
// remove appended iff
return
false
;
}
// Parse second adapter
_last
=
_block
=
two
;
_state
=
state_before
;
if
(
!
try_inline_full
(
mh2_adapter
,
/*holder_known=*/
true
,
end
))
{
restore_inline_cleanup_info
();
block
()
->
clear_end
();
// remove appended iff
return
false
;
}
connect_to_end
(
end
);
return
true
;
}
}
}
return
false
;
}
bool
GraphBuilder
::
for_invokedynamic_inline
(
ciMethod
*
callee
)
{
// Get the MethodHandle from the CallSite.
ciCallSite
*
call_site
=
stream
()
->
get_call_site
();
ciMethodHandle
*
method_handle
=
call_site
->
get_target
();
// Inline constant and mutable call sites. We don't inline
// volatile call sites optimistically since they are specified
// to change their value often and that would result in a lot of
// deoptimizations and recompiles.
if
(
call_site
->
is_constant_call_site
()
||
call_site
->
is_mutable_call_site
())
{
// Set the callee to have access to the class and signature in the
// MethodHandleCompiler.
method_handle
->
set_callee
(
callee
);
method_handle
->
set_caller
(
method
());
// Get an adapter for the MethodHandle.
ciMethod
*
method_handle_adapter
=
method_handle
->
get_invokedynamic_adapter
();
if
(
method_handle_adapter
!=
NULL
)
{
if
(
try_inline
(
method_handle_adapter
,
/*holder_known=*/
true
))
{
// Add a dependence for invalidation of the optimization.
if
(
!
call_site
->
is_constant_call_site
())
{
dependency_recorder
()
->
assert_call_site_target_value
(
call_site
,
method_handle
);
}
return
true
;
}
}
}
return
false
;
}
void
GraphBuilder
::
inline_bailout
(
const
char
*
msg
)
{
void
GraphBuilder
::
inline_bailout
(
const
char
*
msg
)
{
assert
(
msg
!=
NULL
,
"inline bailout msg must exist"
);
assert
(
msg
!=
NULL
,
"inline bailout msg must exist"
);
_inline_bailout_msg
=
msg
;
_inline_bailout_msg
=
msg
;
...
...
src/share/vm/c1/c1_GraphBuilder.hpp
浏览文件 @
7689f3c9
/*
/*
* Copyright (c) 1999, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 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
...
@@ -315,9 +315,17 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
...
@@ -315,9 +315,17 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
ValueStack
*
return_state
)
{
scope_data
()
->
set_inline_cleanup_info
(
block
,
ValueStack
*
return_state
)
{
scope_data
()
->
set_inline_cleanup_info
(
block
,
return_prev
,
return_prev
,
return_state
);
}
return_state
);
}
void
set_inline_cleanup_info
()
{
set_inline_cleanup_info
(
_block
,
_last
,
_state
);
}
BlockBegin
*
inline_cleanup_block
()
const
{
return
scope_data
()
->
inline_cleanup_block
();
}
BlockBegin
*
inline_cleanup_block
()
const
{
return
scope_data
()
->
inline_cleanup_block
();
}
Instruction
*
inline_cleanup_return_prev
()
const
{
return
scope_data
()
->
inline_cleanup_return_prev
();
}
Instruction
*
inline_cleanup_return_prev
()
const
{
return
scope_data
()
->
inline_cleanup_return_prev
();
}
ValueStack
*
inline_cleanup_state
()
const
{
return
scope_data
()
->
inline_cleanup_state
();
}
ValueStack
*
inline_cleanup_state
()
const
{
return
scope_data
()
->
inline_cleanup_state
();
}
void
restore_inline_cleanup_info
()
{
_block
=
inline_cleanup_block
();
_last
=
inline_cleanup_return_prev
();
_state
=
inline_cleanup_state
();
}
void
incr_num_returns
()
{
scope_data
()
->
incr_num_returns
();
}
void
incr_num_returns
()
{
scope_data
()
->
incr_num_returns
();
}
int
num_returns
()
const
{
return
scope_data
()
->
num_returns
();
}
int
num_returns
()
const
{
return
scope_data
()
->
num_returns
();
}
intx
max_inline_size
()
const
{
return
scope_data
()
->
max_inline_size
();
}
intx
max_inline_size
()
const
{
return
scope_data
()
->
max_inline_size
();
}
...
@@ -329,11 +337,15 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
...
@@ -329,11 +337,15 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC {
void
fill_sync_handler
(
Value
lock
,
BlockBegin
*
sync_handler
,
bool
default_handler
=
false
);
void
fill_sync_handler
(
Value
lock
,
BlockBegin
*
sync_handler
,
bool
default_handler
=
false
);
// inliners
// inliners
bool
try_inline
(
ciMethod
*
callee
,
bool
holder_known
);
bool
try_inline
(
ciMethod
*
callee
,
bool
holder_known
);
bool
try_inline_intrinsics
(
ciMethod
*
callee
);
bool
try_inline_intrinsics
(
ciMethod
*
callee
);
bool
try_inline_full
(
ciMethod
*
callee
,
bool
holder_known
);
bool
try_inline_full
(
ciMethod
*
callee
,
bool
holder_known
,
BlockBegin
*
cont_block
=
NULL
);
bool
try_inline_jsr
(
int
jsr_dest_bci
);
bool
try_inline_jsr
(
int
jsr_dest_bci
);
// JSR 292 support
bool
for_method_handle_inline
(
ciMethod
*
callee
);
bool
for_invokedynamic_inline
(
ciMethod
*
callee
);
// helpers
// helpers
void
inline_bailout
(
const
char
*
msg
);
void
inline_bailout
(
const
char
*
msg
);
BlockBegin
*
header_block
(
BlockBegin
*
entry
,
BlockBegin
::
Flag
f
,
ValueStack
*
state
);
BlockBegin
*
header_block
(
BlockBegin
*
entry
,
BlockBegin
::
Flag
f
,
ValueStack
*
state
);
...
...
src/share/vm/c1/c1_Instruction.cpp
浏览文件 @
7689f3c9
...
@@ -514,28 +514,17 @@ Constant::CompareResult Constant::compare(Instruction::Condition cond, Value rig
...
@@ -514,28 +514,17 @@ Constant::CompareResult Constant::compare(Instruction::Condition cond, Value rig
void
BlockBegin
::
set_end
(
BlockEnd
*
end
)
{
void
BlockBegin
::
set_end
(
BlockEnd
*
end
)
{
assert
(
end
!=
NULL
,
"should not reset block end to NULL"
);
assert
(
end
!=
NULL
,
"should not reset block end to NULL"
);
BlockEnd
*
old_end
=
_end
;
if
(
end
==
_end
)
{
if
(
end
==
old_end
)
{
return
;
return
;
}
}
// Must make the predecessors/successors match up with the
clear_end
();
// BlockEnd's notion.
int
i
,
n
;
if
(
old_end
!=
NULL
)
{
// disconnect from the old end
old_end
->
set_begin
(
NULL
);
// disconnect this block from it's current successors
// Set the new end
for
(
i
=
0
;
i
<
_successors
.
length
();
i
++
)
{
_successors
.
at
(
i
)
->
remove_predecessor
(
this
);
}
}
_end
=
end
;
_end
=
end
;
_successors
.
clear
();
_successors
.
clear
();
// Now reset successors list based on BlockEnd
// Now reset successors list based on BlockEnd
n
=
end
->
number_of_sux
();
for
(
int
i
=
0
;
i
<
end
->
number_of_sux
();
i
++
)
{
for
(
i
=
0
;
i
<
n
;
i
++
)
{
BlockBegin
*
sux
=
end
->
sux_at
(
i
);
BlockBegin
*
sux
=
end
->
sux_at
(
i
);
_successors
.
append
(
sux
);
_successors
.
append
(
sux
);
sux
->
_predecessors
.
append
(
this
);
sux
->
_predecessors
.
append
(
this
);
...
@@ -544,6 +533,22 @@ void BlockBegin::set_end(BlockEnd* end) {
...
@@ -544,6 +533,22 @@ void BlockBegin::set_end(BlockEnd* end) {
}
}
void
BlockBegin
::
clear_end
()
{
// Must make the predecessors/successors match up with the
// BlockEnd's notion.
if
(
_end
!=
NULL
)
{
// disconnect from the old end
_end
->
set_begin
(
NULL
);
// disconnect this block from it's current successors
for
(
int
i
=
0
;
i
<
_successors
.
length
();
i
++
)
{
_successors
.
at
(
i
)
->
remove_predecessor
(
this
);
}
_end
=
NULL
;
}
}
void
BlockBegin
::
disconnect_edge
(
BlockBegin
*
from
,
BlockBegin
*
to
)
{
void
BlockBegin
::
disconnect_edge
(
BlockBegin
*
from
,
BlockBegin
*
to
)
{
// disconnect any edges between from and to
// disconnect any edges between from and to
#ifndef PRODUCT
#ifndef PRODUCT
...
...
src/share/vm/c1/c1_Instruction.hpp
浏览文件 @
7689f3c9
...
@@ -1601,6 +1601,7 @@ LEAF(BlockBegin, StateSplit)
...
@@ -1601,6 +1601,7 @@ LEAF(BlockBegin, StateSplit)
void
set_depth_first_number
(
int
dfn
)
{
_depth_first_number
=
dfn
;
}
void
set_depth_first_number
(
int
dfn
)
{
_depth_first_number
=
dfn
;
}
void
set_linear_scan_number
(
int
lsn
)
{
_linear_scan_number
=
lsn
;
}
void
set_linear_scan_number
(
int
lsn
)
{
_linear_scan_number
=
lsn
;
}
void
set_end
(
BlockEnd
*
end
);
void
set_end
(
BlockEnd
*
end
);
void
clear_end
();
void
disconnect_from_graph
();
void
disconnect_from_graph
();
static
void
disconnect_edge
(
BlockBegin
*
from
,
BlockBegin
*
to
);
static
void
disconnect_edge
(
BlockBegin
*
from
,
BlockBegin
*
to
);
BlockBegin
*
insert_block_between
(
BlockBegin
*
sux
);
BlockBegin
*
insert_block_between
(
BlockBegin
*
sux
);
...
...
src/share/vm/classfile/javaClasses.cpp
浏览文件 @
7689f3c9
...
@@ -28,6 +28,7 @@
...
@@ -28,6 +28,7 @@
#include "classfile/vmSymbols.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/debugInfo.hpp"
#include "code/debugInfo.hpp"
#include "code/pcDesc.hpp"
#include "code/pcDesc.hpp"
#include "compiler/compilerOracle.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreter.hpp"
#include "memory/oopFactory.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/resourceArea.hpp"
...
@@ -2674,6 +2675,17 @@ void java_lang_invoke_CallSite::compute_offsets() {
...
@@ -2674,6 +2675,17 @@ void java_lang_invoke_CallSite::compute_offsets() {
if
(
k
!=
NULL
)
{
if
(
k
!=
NULL
)
{
compute_offset
(
_target_offset
,
k
,
vmSymbols
::
target_name
(),
vmSymbols
::
java_lang_invoke_MethodHandle_signature
());
compute_offset
(
_target_offset
,
k
,
vmSymbols
::
target_name
(),
vmSymbols
::
java_lang_invoke_MethodHandle_signature
());
}
}
// Disallow compilation of CallSite.setTargetNormal and CallSite.setTargetVolatile
// (For C2: keep this until we have throttling logic for uncommon traps.)
if
(
k
!=
NULL
)
{
instanceKlass
*
ik
=
instanceKlass
::
cast
(
k
);
methodOop
m_normal
=
ik
->
lookup_method
(
vmSymbols
::
setTargetNormal_name
(),
vmSymbols
::
setTarget_signature
());
methodOop
m_volatile
=
ik
->
lookup_method
(
vmSymbols
::
setTargetVolatile_name
(),
vmSymbols
::
setTarget_signature
());
guarantee
(
m_normal
&&
m_volatile
,
"must exist"
);
m_normal
->
set_not_compilable_quietly
();
m_volatile
->
set_not_compilable_quietly
();
}
}
}
oop
java_lang_invoke_CallSite
::
target
(
oop
site
)
{
oop
java_lang_invoke_CallSite
::
target
(
oop
site
)
{
...
...
src/share/vm/classfile/vmSymbols.hpp
浏览文件 @
7689f3c9
...
@@ -258,6 +258,9 @@
...
@@ -258,6 +258,9 @@
template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \
template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \
template(makeDynamicCallSite_name, "makeDynamicCallSite") \
template(makeDynamicCallSite_name, "makeDynamicCallSite") \
template(makeDynamicCallSite_signature, "(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/invoke/MemberName;I)Ljava/lang/invoke/CallSite;") \
template(makeDynamicCallSite_signature, "(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/Object;Ljava/lang/invoke/MemberName;I)Ljava/lang/invoke/CallSite;") \
template(setTargetNormal_name, "setTargetNormal") \
template(setTargetVolatile_name, "setTargetVolatile") \
template(setTarget_signature, "(Ljava/lang/invoke/MethodHandle;)V") \
NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \
LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \
\
\
...
...
src/share/vm/opto/bytecodeInfo.cpp
浏览文件 @
7689f3c9
...
@@ -394,6 +394,16 @@ bool pass_initial_checks(ciMethod* caller_method, int caller_bci, ciMethod* call
...
@@ -394,6 +394,16 @@ bool pass_initial_checks(ciMethod* caller_method, int caller_bci, ciMethod* call
return
true
;
return
true
;
}
}
//------------------------------check_can_parse--------------------------------
const
char
*
InlineTree
::
check_can_parse
(
ciMethod
*
callee
)
{
// Certain methods cannot be parsed at all:
if
(
callee
->
is_native
())
return
"native method"
;
if
(
!
callee
->
can_be_compiled
())
return
"not compilable (disabled)"
;
if
(
!
callee
->
has_balanced_monitors
())
return
"not compilable (unbalanced monitors)"
;
if
(
callee
->
get_flow_analysis
()
->
failing
())
return
"not compilable (flow analysis failed)"
;
return
NULL
;
}
//------------------------------print_inlining---------------------------------
//------------------------------print_inlining---------------------------------
// Really, the failure_msg can be a success message also.
// Really, the failure_msg can be a success message also.
void
InlineTree
::
print_inlining
(
ciMethod
*
callee_method
,
int
caller_bci
,
const
char
*
failure_msg
)
const
{
void
InlineTree
::
print_inlining
(
ciMethod
*
callee_method
,
int
caller_bci
,
const
char
*
failure_msg
)
const
{
...
@@ -423,14 +433,22 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
...
@@ -423,14 +433,22 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
int
caller_bci
=
jvms
->
bci
();
int
caller_bci
=
jvms
->
bci
();
ciMethod
*
caller_method
=
jvms
->
method
();
ciMethod
*
caller_method
=
jvms
->
method
();
if
(
!
pass_initial_checks
(
caller_method
,
caller_bci
,
callee_method
))
{
// Do some initial checks.
if
(
PrintInlining
)
{
if
(
!
pass_initial_checks
(
caller_method
,
caller_bci
,
callee_method
))
{
if
(
PrintInlining
)
{
failure_msg
=
"failed_initial_checks"
;
failure_msg
=
"failed_initial_checks"
;
print_inlining
(
callee_method
,
caller_bci
,
failure_msg
);
print_inlining
(
callee_method
,
caller_bci
,
failure_msg
);
}
}
return
NULL
;
return
NULL
;
}
}
// Do some parse checks.
failure_msg
=
check_can_parse
(
callee_method
);
if
(
failure_msg
!=
NULL
)
{
if
(
PrintInlining
)
print_inlining
(
callee_method
,
caller_bci
,
failure_msg
);
return
NULL
;
}
// Check if inlining policy says no.
// Check if inlining policy says no.
WarmCallInfo
wci
=
*
(
initial_wci
);
WarmCallInfo
wci
=
*
(
initial_wci
);
failure_msg
=
try_to_inline
(
callee_method
,
caller_method
,
caller_bci
,
profile
,
&
wci
);
failure_msg
=
try_to_inline
(
callee_method
,
caller_method
,
caller_bci
,
profile
,
&
wci
);
...
@@ -471,7 +489,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
...
@@ -471,7 +489,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
if
(
failure_msg
==
NULL
)
failure_msg
=
"inline (hot)"
;
if
(
failure_msg
==
NULL
)
failure_msg
=
"inline (hot)"
;
// Inline!
// Inline!
if
(
PrintInlining
)
print_inlining
(
callee_method
,
caller_bci
,
failure_msg
);
if
(
PrintInlining
)
print_inlining
(
callee_method
,
caller_bci
,
failure_msg
);
if
(
UseOldInlining
)
if
(
UseOldInlining
)
build_inline_tree_for_callee
(
callee_method
,
jvms
,
caller_bci
);
build_inline_tree_for_callee
(
callee_method
,
jvms
,
caller_bci
);
if
(
InlineWarmCalls
&&
!
wci
.
is_hot
())
if
(
InlineWarmCalls
&&
!
wci
.
is_hot
())
...
@@ -481,7 +499,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
...
@@ -481,7 +499,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
// Do not inline
// Do not inline
if
(
failure_msg
==
NULL
)
failure_msg
=
"too cold to inline"
;
if
(
failure_msg
==
NULL
)
failure_msg
=
"too cold to inline"
;
if
(
PrintInlining
)
print_inlining
(
callee_method
,
caller_bci
,
failure_msg
);
if
(
PrintInlining
)
print_inlining
(
callee_method
,
caller_bci
,
failure_msg
);
return
NULL
;
return
NULL
;
}
}
...
...
src/share/vm/opto/callGenerator.cpp
浏览文件 @
7689f3c9
...
@@ -61,12 +61,9 @@ public:
...
@@ -61,12 +61,9 @@ public:
{
{
_is_osr
=
is_osr
;
_is_osr
=
is_osr
;
_expected_uses
=
expected_uses
;
_expected_uses
=
expected_uses
;
assert
(
can_parse
(
method
,
is_osr
)
,
"parse must be possible"
);
assert
(
InlineTree
::
check_can_parse
(
method
)
==
NULL
,
"parse must be possible"
);
}
}
// Can we build either an OSR or a regular parser for this method?
static
bool
can_parse
(
ciMethod
*
method
,
int
is_osr
=
false
);
virtual
bool
is_parse
()
const
{
return
true
;
}
virtual
bool
is_parse
()
const
{
return
true
;
}
virtual
JVMState
*
generate
(
JVMState
*
jvms
);
virtual
JVMState
*
generate
(
JVMState
*
jvms
);
int
is_osr
()
{
return
_is_osr
;
}
int
is_osr
()
{
return
_is_osr
;
}
...
@@ -303,20 +300,8 @@ JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
...
@@ -303,20 +300,8 @@ JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
return
kit
.
transfer_exceptions_into_jvms
();
return
kit
.
transfer_exceptions_into_jvms
();
}
}
bool
ParseGenerator
::
can_parse
(
ciMethod
*
m
,
int
entry_bci
)
{
// Certain methods cannot be parsed at all:
if
(
!
m
->
can_be_compiled
())
return
false
;
if
(
!
m
->
has_balanced_monitors
())
return
false
;
if
(
m
->
get_flow_analysis
()
->
failing
())
return
false
;
// (Methods may bail out for other reasons, after the parser is run.
// We try to avoid this, but if forced, we must return (Node*)NULL.
// The user of the CallGenerator must check for this condition.)
return
true
;
}
CallGenerator
*
CallGenerator
::
for_inline
(
ciMethod
*
m
,
float
expected_uses
)
{
CallGenerator
*
CallGenerator
::
for_inline
(
ciMethod
*
m
,
float
expected_uses
)
{
if
(
!
ParseGenerator
::
can_parse
(
m
)
)
return
NULL
;
if
(
InlineTree
::
check_can_parse
(
m
)
!=
NULL
)
return
NULL
;
return
new
ParseGenerator
(
m
,
expected_uses
);
return
new
ParseGenerator
(
m
,
expected_uses
);
}
}
...
@@ -324,7 +309,7 @@ CallGenerator* CallGenerator::for_inline(ciMethod* m, float expected_uses) {
...
@@ -324,7 +309,7 @@ CallGenerator* CallGenerator::for_inline(ciMethod* m, float expected_uses) {
// for the method execution already in progress, not just the JVMS
// for the method execution already in progress, not just the JVMS
// of the caller. Thus, this CallGenerator cannot be mixed with others!
// of the caller. Thus, this CallGenerator cannot be mixed with others!
CallGenerator
*
CallGenerator
::
for_osr
(
ciMethod
*
m
,
int
osr_bci
)
{
CallGenerator
*
CallGenerator
::
for_osr
(
ciMethod
*
m
,
int
osr_bci
)
{
if
(
!
ParseGenerator
::
can_parse
(
m
,
true
)
)
return
NULL
;
if
(
InlineTree
::
check_can_parse
(
m
)
!=
NULL
)
return
NULL
;
float
past_uses
=
m
->
interpreter_invocation_count
();
float
past_uses
=
m
->
interpreter_invocation_count
();
float
expected_uses
=
past_uses
;
float
expected_uses
=
past_uses
;
return
new
ParseGenerator
(
m
,
expected_uses
,
true
);
return
new
ParseGenerator
(
m
,
expected_uses
,
true
);
...
...
src/share/vm/opto/parse.hpp
浏览文件 @
7689f3c9
...
@@ -78,6 +78,8 @@ protected:
...
@@ -78,6 +78,8 @@ protected:
int
stack_depth
()
const
{
return
_caller_jvms
?
_caller_jvms
->
depth
()
:
0
;
}
int
stack_depth
()
const
{
return
_caller_jvms
?
_caller_jvms
->
depth
()
:
0
;
}
public:
public:
static
const
char
*
check_can_parse
(
ciMethod
*
callee
);
static
InlineTree
*
build_inline_tree_root
();
static
InlineTree
*
build_inline_tree_root
();
static
InlineTree
*
find_subtree_from_root
(
InlineTree
*
root
,
JVMState
*
jvms
,
ciMethod
*
callee
,
bool
create_if_not_found
=
false
);
static
InlineTree
*
find_subtree_from_root
(
InlineTree
*
root
,
JVMState
*
jvms
,
ciMethod
*
callee
,
bool
create_if_not_found
=
false
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录