Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
114dcaf7
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看板
提交
114dcaf7
编写于
3月 24, 2011
作者:
J
jcoomes
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
bdff6c3c
08952416
变更
18
展开全部
隐藏空白更改
内联
并排
Showing
18 changed file
with
711 addition
and
1126 deletion
+711
-1126
src/cpu/sparc/vm/methodHandles_sparc.cpp
src/cpu/sparc/vm/methodHandles_sparc.cpp
+7
-3
src/share/vm/opto/c2_globals.hpp
src/share/vm/opto/c2_globals.hpp
+3
-0
src/share/vm/opto/graphKit.cpp
src/share/vm/opto/graphKit.cpp
+43
-0
src/share/vm/opto/graphKit.hpp
src/share/vm/opto/graphKit.hpp
+4
-0
src/share/vm/opto/idealKit.cpp
src/share/vm/opto/idealKit.cpp
+11
-1
src/share/vm/opto/idealKit.hpp
src/share/vm/opto/idealKit.hpp
+2
-1
src/share/vm/opto/library_call.cpp
src/share/vm/opto/library_call.cpp
+4
-2
src/share/vm/opto/loopTransform.cpp
src/share/vm/opto/loopTransform.cpp
+202
-143
src/share/vm/opto/loopUnswitch.cpp
src/share/vm/opto/loopUnswitch.cpp
+7
-0
src/share/vm/opto/loopnode.cpp
src/share/vm/opto/loopnode.cpp
+267
-200
src/share/vm/opto/loopnode.hpp
src/share/vm/opto/loopnode.hpp
+20
-11
src/share/vm/opto/loopopts.cpp
src/share/vm/opto/loopopts.cpp
+83
-53
src/share/vm/opto/parse.hpp
src/share/vm/opto/parse.hpp
+13
-5
src/share/vm/opto/parse1.cpp
src/share/vm/opto/parse1.cpp
+38
-38
src/share/vm/opto/parse2.cpp
src/share/vm/opto/parse2.cpp
+0
-27
src/share/vm/opto/stringopts.cpp
src/share/vm/opto/stringopts.cpp
+7
-0
test/compiler/6987555/Test6987555.java
test/compiler/6987555/Test6987555.java
+0
-177
test/compiler/6991596/Test6991596.java
test/compiler/6991596/Test6991596.java
+0
-465
未找到文件。
src/cpu/sparc/vm/methodHandles_sparc.cpp
浏览文件 @
114dcaf7
...
...
@@ -775,9 +775,13 @@ void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHan
switch
(
ek
)
{
case
_adapter_opt_i2l
:
{
__
ldsw
(
arg_lsw
,
O2_scratch
);
// Load LSW
NOT_LP64
(
__
srlx
(
O2_scratch
,
BitsPerInt
,
O3_scratch
));
// Move high bits to lower bits for std
__
st_long
(
O2_scratch
,
arg_msw
);
// Uses O2/O3 on !_LP64
#ifdef _LP64
__
ldsw
(
arg_lsw
,
O2_scratch
);
// Load LSW sign-extended
#else
__
ldsw
(
arg_lsw
,
O3_scratch
);
// Load LSW sign-extended
__
srlx
(
O3_scratch
,
BitsPerInt
,
O2_scratch
);
// Move MSW value to lower 32-bits for std
#endif
__
st_long
(
O2_scratch
,
arg_msw
);
// Uses O2/O3 on !_LP64
}
break
;
case
_adapter_opt_unboxl
:
...
...
src/share/vm/opto/c2_globals.hpp
浏览文件 @
114dcaf7
...
...
@@ -180,6 +180,9 @@
develop(bool, TraceLoopPredicate, false, \
"Trace generation of loop predicates") \
\
develop(bool, TraceLoopOpts, false, \
"Trace executed loop optimizations") \
\
product(bool, OptimizeFill, false, \
"convert fill/copy loops into intrinsic") \
\
...
...
src/share/vm/opto/graphKit.cpp
浏览文件 @
114dcaf7
...
...
@@ -3338,6 +3338,49 @@ InitializeNode* AllocateNode::initialization() {
return
NULL
;
}
//----------------------------- loop predicates ---------------------------
//------------------------------add_predicate_impl----------------------------
void
GraphKit
::
add_predicate_impl
(
Deoptimization
::
DeoptReason
reason
,
int
nargs
)
{
// Too many traps seen?
if
(
too_many_traps
(
reason
))
{
#ifdef ASSERT
if
(
TraceLoopPredicate
)
{
int
tc
=
C
->
trap_count
(
reason
);
tty
->
print
(
"too many traps=%s tcount=%d in "
,
Deoptimization
::
trap_reason_name
(
reason
),
tc
);
method
()
->
print
();
// which method has too many predicate traps
tty
->
cr
();
}
#endif
// We cannot afford to take more traps here,
// do not generate predicate.
return
;
}
Node
*
cont
=
_gvn
.
intcon
(
1
);
Node
*
opq
=
_gvn
.
transform
(
new
(
C
,
2
)
Opaque1Node
(
C
,
cont
));
Node
*
bol
=
_gvn
.
transform
(
new
(
C
,
2
)
Conv2BNode
(
opq
));
IfNode
*
iff
=
create_and_map_if
(
control
(),
bol
,
PROB_MAX
,
COUNT_UNKNOWN
);
Node
*
iffalse
=
_gvn
.
transform
(
new
(
C
,
1
)
IfFalseNode
(
iff
));
C
->
add_predicate_opaq
(
opq
);
{
PreserveJVMState
pjvms
(
this
);
set_control
(
iffalse
);
_sp
+=
nargs
;
uncommon_trap
(
reason
,
Deoptimization
::
Action_maybe_recompile
);
}
Node
*
iftrue
=
_gvn
.
transform
(
new
(
C
,
1
)
IfTrueNode
(
iff
));
set_control
(
iftrue
);
}
//------------------------------add_predicate---------------------------------
void
GraphKit
::
add_predicate
(
int
nargs
)
{
if
(
UseLoopPredicate
)
{
add_predicate_impl
(
Deoptimization
::
Reason_predicate
,
nargs
);
}
}
//----------------------------- store barriers ----------------------------
#define __ ideal.
...
...
src/share/vm/opto/graphKit.hpp
浏览文件 @
114dcaf7
...
...
@@ -793,6 +793,10 @@ class GraphKit : public Phase {
if
(
!
tst
->
is_Con
())
record_for_igvn
(
iff
);
// Range-check and Null-check removal is later
return
iff
;
}
// Insert a loop predicate into the graph
void
add_predicate
(
int
nargs
=
0
);
void
add_predicate_impl
(
Deoptimization
::
DeoptReason
reason
,
int
nargs
);
};
// Helper class to support building of control flow branches. Upon
...
...
src/share/vm/opto/idealKit.cpp
浏览文件 @
114dcaf7
...
...
@@ -154,8 +154,18 @@ void IdealKit::end_if() {
//
// Pushes the loop top cvstate first, then the else (loop exit) cvstate
// onto the stack.
void
IdealKit
::
loop
(
IdealVariable
&
iv
,
Node
*
init
,
BoolTest
::
mask
relop
,
Node
*
limit
,
float
prob
,
float
cnt
)
{
void
IdealKit
::
loop
(
GraphKit
*
gkit
,
int
nargs
,
IdealVariable
&
iv
,
Node
*
init
,
BoolTest
::
mask
relop
,
Node
*
limit
,
float
prob
,
float
cnt
)
{
assert
((
state
()
&
(
BlockS
|
LoopS
|
IfThenS
|
ElseS
)),
"bad state for new loop"
);
// Sync IdealKit and graphKit.
gkit
->
set_all_memory
(
this
->
merged_memory
());
gkit
->
set_control
(
this
->
ctrl
());
// Add loop predicate.
gkit
->
add_predicate
(
nargs
);
// Update IdealKit memory.
this
->
set_all_memory
(
gkit
->
merged_memory
());
this
->
set_ctrl
(
gkit
->
control
());
set
(
iv
,
init
);
Node
*
head
=
make_label
(
1
);
bind
(
head
);
...
...
src/share/vm/opto/idealKit.hpp
浏览文件 @
114dcaf7
...
...
@@ -29,6 +29,7 @@
#include "opto/cfgnode.hpp"
#include "opto/connode.hpp"
#include "opto/divnode.hpp"
#include "opto/graphKit.hpp"
#include "opto/mulnode.hpp"
#include "opto/phaseX.hpp"
#include "opto/subnode.hpp"
...
...
@@ -160,7 +161,7 @@ class IdealKit: public StackObj {
bool
push_new_state
=
true
);
void
else_
();
void
end_if
();
void
loop
(
IdealVariable
&
iv
,
Node
*
init
,
BoolTest
::
mask
cmp
,
Node
*
limit
,
void
loop
(
GraphKit
*
gkit
,
int
nargs
,
IdealVariable
&
iv
,
Node
*
init
,
BoolTest
::
mask
cmp
,
Node
*
limit
,
float
prob
=
PROB_LIKELY
(
0.9
),
float
cnt
=
COUNT_UNKNOWN
);
void
end_loop
();
Node
*
make_label
(
int
goto_ct
);
...
...
src/share/vm/opto/library_call.cpp
浏览文件 @
114dcaf7
...
...
@@ -1101,6 +1101,8 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar
float
likely
=
PROB_LIKELY
(
0.9
);
float
unlikely
=
PROB_UNLIKELY
(
0.9
);
const
int
nargs
=
2
;
// number of arguments to push back for uncommon trap in predicate
const
int
value_offset
=
java_lang_String
::
value_offset_in_bytes
();
const
int
count_offset
=
java_lang_String
::
count_offset_in_bytes
();
const
int
offset_offset
=
java_lang_String
::
offset_offset_in_bytes
();
...
...
@@ -1138,12 +1140,12 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar
Node
*
return_
=
__
make_label
(
1
);
__
set
(
rtn
,
__
ConI
(
-
1
));
__
loop
(
i
,
sourceOffset
,
BoolTest
::
lt
,
sourceEnd
);
{
__
loop
(
this
,
nargs
,
i
,
sourceOffset
,
BoolTest
::
lt
,
sourceEnd
);
{
Node
*
i2
=
__
AddI
(
__
value
(
i
),
targetCountLess1
);
// pin to prohibit loading of "next iteration" value which may SEGV (rare)
Node
*
src
=
load_array_element
(
__
ctrl
(),
source
,
i2
,
TypeAryPtr
::
CHARS
);
__
if_then
(
src
,
BoolTest
::
eq
,
lastChar
,
unlikely
);
{
__
loop
(
j
,
zero
,
BoolTest
::
lt
,
targetCountLess1
);
{
__
loop
(
this
,
nargs
,
j
,
zero
,
BoolTest
::
lt
,
targetCountLess1
);
{
Node
*
tpj
=
__
AddI
(
targetOffset
,
__
value
(
j
));
Node
*
targ
=
load_array_element
(
no_ctrl
,
target
,
tpj
,
target_type
);
Node
*
ipj
=
__
AddI
(
__
value
(
i
),
__
value
(
j
));
...
...
src/share/vm/opto/loopTransform.cpp
浏览文件 @
114dcaf7
此差异已折叠。
点击以展开。
src/share/vm/opto/loopUnswitch.cpp
浏览文件 @
114dcaf7
...
...
@@ -110,6 +110,13 @@ void PhaseIdealLoop::do_unswitching (IdealLoopTree *loop, Node_List &old_new) {
IfNode
*
unswitch_iff
=
find_unswitching_candidate
((
const
IdealLoopTree
*
)
loop
);
assert
(
unswitch_iff
!=
NULL
,
"should be at least one"
);
#ifndef PRODUCT
if
(
TraceLoopOpts
)
{
tty
->
print
(
"Unswitch %d "
,
head
->
unswitch_count
()
+
1
);
loop
->
dump_head
();
}
#endif
// Need to revert back to normal loop
if
(
head
->
is_CountedLoop
()
&&
!
head
->
as_CountedLoop
()
->
is_normal_loop
())
{
head
->
as_CountedLoop
()
->
set_normal_loop
();
...
...
src/share/vm/opto/loopnode.cpp
浏览文件 @
114dcaf7
此差异已折叠。
点击以展开。
src/share/vm/opto/loopnode.hpp
浏览文件 @
114dcaf7
...
...
@@ -93,6 +93,7 @@ public:
in
(
1
)
!=
NULL
&&
phase
->
type
(
in
(
1
))
!=
Type
::
TOP
&&
in
(
2
)
!=
NULL
&&
phase
->
type
(
in
(
2
))
!=
Type
::
TOP
;
}
bool
is_valid_counted_loop
()
const
;
#ifndef PRODUCT
virtual
void
dump_spec
(
outputStream
*
st
)
const
;
#endif
...
...
@@ -101,9 +102,8 @@ public:
//------------------------------Counted Loops----------------------------------
// Counted loops are all trip-counted loops, with exactly 1 trip-counter exit
// path (and maybe some other exit paths). The trip-counter exit is always
// last in the loop. The trip-counter does not have to stride by a constant,
// but it does have to stride by a loop-invariant amount; the exit value is
// also loop invariant.
// last in the loop. The trip-counter have to stride by a constant;
// the exit value is also loop invariant.
// CountedLoopNodes and CountedLoopEndNodes come in matched pairs. The
// CountedLoopNode has the incoming loop control and the loop-back-control
...
...
@@ -112,7 +112,7 @@ public:
// CountedLoopNode if there is control flow in the loop), the post-increment
// trip-counter value, and the limit. The trip-counter value is always of
// the form (Op old-trip-counter stride). The old-trip-counter is produced
// by a Phi connected to the CountedLoopNode. The stride is
loop invari
ant.
// by a Phi connected to the CountedLoopNode. The stride is
const
ant.
// The Op is any commutable opcode, including Add, Mul, Xor. The
// CountedLoopEndNode also takes in the loop-invariant limit value.
...
...
@@ -696,6 +696,9 @@ private:
// Is safept not required by an outer loop?
bool
is_deleteable_safept
(
Node
*
sfpt
);
// Replace parallel induction variable (parallel to trip counter)
void
replace_parallel_iv
(
IdealLoopTree
*
loop
);
// Perform verification that the graph is valid.
PhaseIdealLoop
(
PhaseIterGVN
&
igvn
)
:
PhaseTransform
(
Ideal_Loop
),
...
...
@@ -751,7 +754,7 @@ public:
// Per-Node transform
virtual
Node
*
transform
(
Node
*
a_node
)
{
return
0
;
}
Node
*
is_counted_loop
(
Node
*
x
,
IdealLoopTree
*
loop
);
bool
is_counted_loop
(
Node
*
x
,
IdealLoopTree
*
loop
);
// Return a post-walked LoopNode
IdealLoopTree
*
get_loop
(
Node
*
n
)
const
{
...
...
@@ -815,16 +818,22 @@ public:
bool
is_scaled_iv_plus_offset
(
Node
*
exp
,
Node
*
iv
,
int
*
p_scale
,
Node
**
p_offset
,
int
depth
=
0
);
// Return true if proj is for "proj->[region->..]call_uct"
bool
is_uncommon_trap_proj
(
ProjNode
*
proj
,
bool
must_reason_predicate
=
false
);
// Return true if proj is for "proj->[region->..]call_uct"
static
bool
is_uncommon_trap_proj
(
ProjNode
*
proj
,
Deoptimization
::
DeoptReason
reason
);
// Return true for "if(test)-> proj -> ...
// |
// V
// other_proj->[region->..]call_uct"
bool
is_uncommon_trap_if_pattern
(
ProjNode
*
proj
,
bool
must_reason_predicate
=
false
);
static
bool
is_uncommon_trap_if_pattern
(
ProjNode
*
proj
,
Deoptimization
::
DeoptReason
reason
);
// Create a new if above the uncommon_trap_if_pattern for the predicate to be promoted
ProjNode
*
create_new_if_for_predicate
(
ProjNode
*
cont_proj
);
// Find a good location to insert a predicate
ProjNode
*
find_predicate_insertion_point
(
Node
*
start_c
);
ProjNode
*
create_new_if_for_predicate
(
ProjNode
*
cont_proj
,
Node
*
new_entry
,
Deoptimization
::
DeoptReason
reason
);
void
register_control
(
Node
*
n
,
IdealLoopTree
*
loop
,
Node
*
pred
);
// Find a good location to insert a predicate
static
ProjNode
*
find_predicate_insertion_point
(
Node
*
start_c
,
Deoptimization
::
DeoptReason
reason
);
// Find a predicate
static
Node
*
find_predicate
(
Node
*
entry
);
// Construct a range check for a predicate if
BoolNode
*
rc_predicate
(
Node
*
ctrl
,
int
scale
,
Node
*
offset
,
...
...
@@ -936,7 +945,7 @@ public:
Node
*
has_local_phi_input
(
Node
*
n
);
// Mark an IfNode as being dominated by a prior test,
// without actually altering the CFG (and hence IDOM info).
void
dominated_by
(
Node
*
prevdom
,
Node
*
iff
);
void
dominated_by
(
Node
*
prevdom
,
Node
*
iff
,
bool
flip
=
false
);
// Split Node 'n' through merge point
Node
*
split_thru_region
(
Node
*
n
,
Node
*
region
);
...
...
src/share/vm/opto/loopopts.cpp
浏览文件 @
114dcaf7
...
...
@@ -42,13 +42,13 @@ Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) {
return
NULL
;
}
int
wins
=
0
;
assert
(
!
n
->
is_CFG
(),
""
);
assert
(
region
->
is_Region
(),
""
);
assert
(
!
n
->
is_CFG
(),
""
);
assert
(
region
->
is_Region
(),
""
);
const
Type
*
type
=
n
->
bottom_type
();
const
TypeOopPtr
*
t_oop
=
_igvn
.
type
(
n
)
->
isa_oopptr
();
Node
*
phi
;
if
(
t_oop
!=
NULL
&&
t_oop
->
is_known_instance_field
()
)
{
if
(
t_oop
!=
NULL
&&
t_oop
->
is_known_instance_field
()
)
{
int
iid
=
t_oop
->
instance_id
();
int
index
=
C
->
get_alias_index
(
t_oop
);
int
offset
=
t_oop
->
offset
();
...
...
@@ -57,20 +57,20 @@ Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) {
phi
=
PhiNode
::
make_blank
(
region
,
n
);
}
uint
old_unique
=
C
->
unique
();
for
(
uint
i
=
1
;
i
<
region
->
req
();
i
++
)
{
for
(
uint
i
=
1
;
i
<
region
->
req
();
i
++
)
{
Node
*
x
;
Node
*
the_clone
=
NULL
;
if
(
region
->
in
(
i
)
==
C
->
top
()
)
{
if
(
region
->
in
(
i
)
==
C
->
top
()
)
{
x
=
C
->
top
();
// Dead path? Use a dead data op
}
else
{
x
=
n
->
clone
();
// Else clone up the data op
the_clone
=
x
;
// Remember for possible deletion.
// Alter data node to use pre-phi inputs
if
(
n
->
in
(
0
)
==
region
)
if
(
n
->
in
(
0
)
==
region
)
x
->
set_req
(
0
,
region
->
in
(
i
)
);
for
(
uint
j
=
1
;
j
<
n
->
req
();
j
++
)
{
for
(
uint
j
=
1
;
j
<
n
->
req
();
j
++
)
{
Node
*
in
=
n
->
in
(
j
);
if
(
in
->
is_Phi
()
&&
in
->
in
(
0
)
==
region
)
if
(
in
->
is_Phi
()
&&
in
->
in
(
0
)
==
region
)
x
->
set_req
(
j
,
in
->
in
(
i
)
);
// Use pre-Phi input for the clone
}
}
...
...
@@ -85,7 +85,7 @@ Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) {
// happen if the singleton occurs on loop entry, as the elimination of
// the PhiNode may cause the resulting node to migrate back to a previous
// loop iteration.
if
(
singleton
&&
t
==
Type
::
TOP
)
{
if
(
singleton
&&
t
==
Type
::
TOP
)
{
// Is_Loop() == false does not confirm the absence of a loop (e.g., an
// irreducible loop may not be indicated by an affirmative is_Loop());
// therefore, the only top we can split thru a phi is on a backedge of
...
...
@@ -93,7 +93,7 @@ Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) {
singleton
&=
region
->
is_Loop
()
&&
(
i
!=
LoopNode
::
EntryControl
);
}
if
(
singleton
)
{
if
(
singleton
)
{
wins
++
;
x
=
((
PhaseGVN
&
)
_igvn
).
makecon
(
t
);
}
else
{
...
...
@@ -108,12 +108,12 @@ Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) {
// igvn->type(x) is set to x->Value() already.
x
->
raise_bottom_type
(
t
);
Node
*
y
=
x
->
Identity
(
&
_igvn
);
if
(
y
!=
x
)
{
if
(
y
!=
x
)
{
wins
++
;
x
=
y
;
}
else
{
y
=
_igvn
.
hash_find
(
x
);
if
(
y
)
{
if
(
y
)
{
wins
++
;
x
=
y
;
}
else
{
...
...
@@ -129,7 +129,7 @@ Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) {
phi
->
set_req
(
i
,
x
);
}
// Too few wins?
if
(
wins
<=
policy
)
{
if
(
wins
<=
policy
)
{
_igvn
.
remove_dead_node
(
phi
);
return
NULL
;
}
...
...
@@ -137,7 +137,7 @@ Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) {
// Record Phi
register_new_node
(
phi
,
region
);
for
(
uint
i2
=
1
;
i2
<
phi
->
req
();
i2
++
)
{
for
(
uint
i2
=
1
;
i2
<
phi
->
req
();
i2
++
)
{
Node
*
x
=
phi
->
in
(
i2
);
// If we commoned up the cloned 'x' with another existing Node,
// the existing Node picks up a new use. We need to make the
...
...
@@ -145,24 +145,44 @@ Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) {
Node
*
old_ctrl
;
IdealLoopTree
*
old_loop
;
if
(
x
->
is_Con
())
{
// Constant's control is always root.
set_ctrl
(
x
,
C
->
root
());
continue
;
}
// The occasional new node
if
(
x
->
_idx
>=
old_unique
)
{
// Found a new, unplaced node?
old_ctrl
=
x
->
is_Con
()
?
C
->
root
()
:
NULL
;
old_loop
=
NULL
;
// Not in any prior loop
if
(
x
->
_idx
>=
old_unique
)
{
// Found a new, unplaced node?
old_ctrl
=
NULL
;
old_loop
=
NULL
;
// Not in any prior loop
}
else
{
old_ctrl
=
x
->
is_Con
()
?
C
->
root
()
:
get_ctrl
(
x
);
old_ctrl
=
get_ctrl
(
x
);
old_loop
=
get_loop
(
old_ctrl
);
// Get prior loop
}
// New late point must dominate new use
Node
*
new_ctrl
=
dom_lca
(
old_ctrl
,
region
->
in
(
i2
)
);
Node
*
new_ctrl
=
dom_lca
(
old_ctrl
,
region
->
in
(
i2
));
if
(
new_ctrl
==
old_ctrl
)
// Nothing is changed
continue
;
IdealLoopTree
*
new_loop
=
get_loop
(
new_ctrl
);
// Don't move x into a loop if its uses are
// outside of loop. Otherwise x will be cloned
// for each use outside of this loop.
IdealLoopTree
*
use_loop
=
get_loop
(
region
);
if
(
!
new_loop
->
is_member
(
use_loop
)
&&
(
old_loop
==
NULL
||
!
new_loop
->
is_member
(
old_loop
)))
{
// Take early control, later control will be recalculated
// during next iteration of loop optimizations.
new_ctrl
=
get_early_ctrl
(
x
);
new_loop
=
get_loop
(
new_ctrl
);
}
// Set new location
set_ctrl
(
x
,
new_ctrl
);
IdealLoopTree
*
new_loop
=
get_loop
(
new_ctrl
);
// If changing loop bodies, see if we need to collect into new body
if
(
old_loop
!=
new_loop
)
{
if
(
old_loop
&&
!
old_loop
->
_child
)
if
(
old_loop
!=
new_loop
)
{
if
(
old_loop
&&
!
old_loop
->
_child
)
old_loop
->
_body
.
yank
(
x
);
if
(
!
new_loop
->
_child
)
if
(
!
new_loop
->
_child
)
new_loop
->
_body
.
push
(
x
);
// Collect body info
}
}
...
...
@@ -174,9 +194,9 @@ Node *PhaseIdealLoop::split_thru_phi( Node *n, Node *region, int policy ) {
// Replace the dominated test with an obvious true or false. Place it on the
// IGVN worklist for later cleanup. Move control-dependent data Nodes on the
// live path up to the dominating control.
void
PhaseIdealLoop
::
dominated_by
(
Node
*
prevdom
,
Node
*
iff
)
{
void
PhaseIdealLoop
::
dominated_by
(
Node
*
prevdom
,
Node
*
iff
,
bool
flip
)
{
#ifndef PRODUCT
if
(
VerifyLoopOptimizations
&&
PrintOpto
)
tty
->
print_cr
(
"dominating test"
);
if
(
VerifyLoopOptimizations
&&
PrintOpto
)
tty
->
print_cr
(
"dominating test"
);
#endif
...
...
@@ -185,6 +205,12 @@ void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff ) {
assert
(
iff
->
Opcode
()
==
Op_If
||
iff
->
Opcode
()
==
Op_CountedLoopEnd
,
"Check this code when new subtype is added"
);
int
pop
=
prevdom
->
Opcode
();
assert
(
pop
==
Op_IfFalse
||
pop
==
Op_IfTrue
,
""
);
if
(
flip
)
{
if
(
pop
==
Op_IfTrue
)
pop
=
Op_IfFalse
;
else
pop
=
Op_IfTrue
;
}
// 'con' is set to true or false to kill the dominated test.
Node
*
con
=
_igvn
.
makecon
(
pop
==
Op_IfTrue
?
TypeInt
::
ONE
:
TypeInt
::
ZERO
);
set_ctrl
(
con
,
C
->
root
());
// Constant gets a new use
...
...
@@ -197,7 +223,7 @@ void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff ) {
// I can assume this path reaches an infinite loop. In this case it's not
// important to optimize the data Nodes - either the whole compilation will
// be tossed or this path (and all data Nodes) will go dead.
if
(
iff
->
outcnt
()
!=
2
)
return
;
if
(
iff
->
outcnt
()
!=
2
)
return
;
// Make control-dependent data Nodes on the live path (path that will remain
// once the dominated IF is removed) become control-dependent on the
...
...
@@ -207,16 +233,16 @@ void PhaseIdealLoop::dominated_by( Node *prevdom, Node *iff ) {
for
(
DUIterator_Fast
imax
,
i
=
dp
->
fast_outs
(
imax
);
i
<
imax
;
i
++
)
{
Node
*
cd
=
dp
->
fast_out
(
i
);
// Control-dependent node
if
(
cd
->
depends_only_on_test
()
)
{
assert
(
cd
->
in
(
0
)
==
dp
,
""
);
_igvn
.
hash_delete
(
cd
);
if
(
cd
->
depends_only_on_test
()
)
{
assert
(
cd
->
in
(
0
)
==
dp
,
""
);
_igvn
.
hash_delete
(
cd
);
cd
->
set_req
(
0
,
prevdom
);
set_early_ctrl
(
cd
);
set_early_ctrl
(
cd
);
_igvn
.
_worklist
.
push
(
cd
);
IdealLoopTree
*
new_loop
=
get_loop
(
get_ctrl
(
cd
));
if
(
old_loop
!=
new_loop
)
{
if
(
!
old_loop
->
_child
)
old_loop
->
_body
.
yank
(
cd
);
if
(
!
new_loop
->
_child
)
new_loop
->
_body
.
push
(
cd
);
if
(
old_loop
!=
new_loop
)
{
if
(
!
old_loop
->
_child
)
old_loop
->
_body
.
yank
(
cd
);
if
(
!
new_loop
->
_child
)
new_loop
->
_body
.
push
(
cd
);
}
--
i
;
--
imax
;
...
...
@@ -2338,6 +2364,11 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
}
#if !defined(PRODUCT)
if
(
TraceLoopOpts
)
{
tty
->
print
(
"PartialPeel "
);
loop
->
dump_head
();
}
if
(
TracePartialPeeling
)
{
tty
->
print_cr
(
"before partial peel one iteration"
);
Node_List
wl
;
...
...
@@ -2481,6 +2512,7 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
// Create new loop head for new phis and to hang
// the nodes being moved (sinked) from the peel region.
LoopNode
*
new_head
=
new
(
C
,
3
)
LoopNode
(
last_peel
,
last_peel
);
new_head
->
set_unswitch_count
(
head
->
unswitch_count
());
// Preserve
_igvn
.
register_new_node_with_optimizer
(
new_head
);
assert
(
first_not_peeled
->
in
(
0
)
==
last_peel
,
"last_peel <- first_not_peeled"
);
first_not_peeled
->
set_req
(
0
,
new_head
);
...
...
@@ -2651,24 +2683,23 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
// prevent loop-fallout uses of the pre-incremented trip counter (which are
// then alive with the post-incremented trip counter forcing an extra
// register move)
void
PhaseIdealLoop
::
reorg_offsets
(
IdealLoopTree
*
loop
)
{
void
PhaseIdealLoop
::
reorg_offsets
(
IdealLoopTree
*
loop
)
{
// Perform it only for canonical counted loops.
// Loop's shape could be messed up by iteration_split_impl.
if
(
!
loop
->
_head
->
is_CountedLoop
())
return
;
if
(
!
loop
->
_head
->
as_Loop
()
->
is_valid_counted_loop
())
return
;
CountedLoopNode
*
cl
=
loop
->
_head
->
as_CountedLoop
();
CountedLoopEndNode
*
cle
=
cl
->
loopexit
();
if
(
!
cle
)
return
;
// The occasional dead loop
// Find loop exit control
Node
*
exit
=
cle
->
proj_out
(
false
);
assert
(
exit
->
Opcode
()
==
Op_IfFalse
,
""
);
Node
*
phi
=
cl
->
phi
(
);
// Check for the special case of folks using the pre-incremented
// trip-counter on the fall-out path (forces the pre-incremented
// and post-incremented trip counter to be live at the same time).
// Fix this by adjusting to use the post-increment trip counter.
Node
*
phi
=
cl
->
phi
();
if
(
!
phi
)
return
;
// Dead infinite loop
// Shape messed up, probably by iteration_split_impl
if
(
phi
->
in
(
LoopNode
::
LoopBackControl
)
!=
cl
->
incr
())
return
;
bool
progress
=
true
;
while
(
progress
)
{
...
...
@@ -2677,21 +2708,19 @@ void PhaseIdealLoop::reorg_offsets( IdealLoopTree *loop ) {
Node
*
use
=
phi
->
fast_out
(
i
);
// User of trip-counter
if
(
!
has_ctrl
(
use
))
continue
;
Node
*
u_ctrl
=
get_ctrl
(
use
);
if
(
use
->
is_Phi
()
)
{
if
(
use
->
is_Phi
()
)
{
u_ctrl
=
NULL
;
for
(
uint
j
=
1
;
j
<
use
->
req
();
j
++
)
if
(
use
->
in
(
j
)
==
phi
)
u_ctrl
=
dom_lca
(
u_ctrl
,
use
->
in
(
0
)
->
in
(
j
)
);
for
(
uint
j
=
1
;
j
<
use
->
req
();
j
++
)
if
(
use
->
in
(
j
)
==
phi
)
u_ctrl
=
dom_lca
(
u_ctrl
,
use
->
in
(
0
)
->
in
(
j
)
);
}
IdealLoopTree
*
u_loop
=
get_loop
(
u_ctrl
);
// Look for loop-invariant use
if
(
u_loop
==
loop
)
continue
;
if
(
loop
->
is_member
(
u_loop
)
)
continue
;
if
(
u_loop
==
loop
)
continue
;
if
(
loop
->
is_member
(
u_loop
)
)
continue
;
// Check that use is live out the bottom. Assuming the trip-counter
// update is right at the bottom, uses of of the loop middle are ok.
if
(
dom_lca
(
exit
,
u_ctrl
)
!=
exit
)
continue
;
// protect against stride not being a constant
if
(
!
cle
->
stride_is_con
()
)
continue
;
if
(
dom_lca
(
exit
,
u_ctrl
)
!=
exit
)
continue
;
// Hit! Refactor use to use the post-incremented tripcounter.
// Compute a post-increment tripcounter.
Node
*
opaq
=
new
(
C
,
2
)
Opaque2Node
(
C
,
cle
->
incr
()
);
...
...
@@ -2702,9 +2731,10 @@ void PhaseIdealLoop::reorg_offsets( IdealLoopTree *loop ) {
register_new_node
(
post
,
u_ctrl
);
_igvn
.
hash_delete
(
use
);
_igvn
.
_worklist
.
push
(
use
);
for
(
uint
j
=
1
;
j
<
use
->
req
();
j
++
)
if
(
use
->
in
(
j
)
==
phi
)
for
(
uint
j
=
1
;
j
<
use
->
req
();
j
++
)
{
if
(
use
->
in
(
j
)
==
phi
)
use
->
set_req
(
j
,
post
);
}
// Since DU info changed, rerun loop
progress
=
true
;
break
;
...
...
src/share/vm/opto/parse.hpp
浏览文件 @
114dcaf7
...
...
@@ -136,6 +136,7 @@ class Parse : public GraphKit {
uint
_count
;
// how many times executed? Currently only set by _goto's
bool
_is_parsed
;
// has this block been parsed yet?
bool
_is_handler
;
// is this block an exception handler?
bool
_has_merged_backedge
;
// does this block have merged backedge?
SafePointNode
*
_start_map
;
// all values flowing into this block
MethodLivenessResult
_live_locals
;
// lazily initialized liveness bitmap
...
...
@@ -168,6 +169,18 @@ class Parse : public GraphKit {
// True after any predecessor flows control into this block
bool
is_merged
()
const
{
return
_start_map
!=
NULL
;
}
#ifdef ASSERT
// True after backedge predecessor flows control into this block
bool
has_merged_backedge
()
const
{
return
_has_merged_backedge
;
}
void
mark_merged_backedge
(
Block
*
pred
)
{
assert
(
is_SEL_head
(),
"should be loop head"
);
if
(
pred
!=
NULL
&&
is_SEL_backedge
(
pred
))
{
assert
(
is_parsed
(),
"block should be parsed before merging backedges"
);
_has_merged_backedge
=
true
;
}
}
#endif
// True when all non-exception predecessors have been parsed.
bool
is_ready
()
const
{
return
preds_parsed
()
==
pred_count
();
}
...
...
@@ -441,11 +454,6 @@ class Parse : public GraphKit {
}
}
// Return true if the parser should add a loop predicate
bool
should_add_predicate
(
int
target_bci
);
// Insert a loop predicate into the graph
void
add_predicate
();
// Note: Intrinsic generation routines may be found in library_call.cpp.
// Helper function to setup Ideal Call nodes
...
...
src/share/vm/opto/parse1.cpp
浏览文件 @
114dcaf7
...
...
@@ -637,6 +637,25 @@ void Parse::do_all_blocks() {
// (Note that dead locals do not get phis built, ever.)
ensure_phis_everywhere
();
if
(
block
->
is_SEL_head
()
&&
UseLoopPredicate
)
{
// Add predicate to single entry (not irreducible) loop head.
assert
(
!
block
->
has_merged_backedge
(),
"only entry paths should be merged for now"
);
// Need correct bci for predicate.
// It is fine to set it here since do_one_block() will set it anyway.
set_parse_bci
(
block
->
start
());
add_predicate
();
// Add new region for back branches.
int
edges
=
block
->
pred_count
()
-
block
->
preds_parsed
()
+
1
;
// +1 for original region
RegionNode
*
r
=
new
(
C
,
edges
+
1
)
RegionNode
(
edges
+
1
);
_gvn
.
set_type
(
r
,
Type
::
CONTROL
);
record_for_igvn
(
r
);
r
->
init_req
(
edges
,
control
());
set_control
(
r
);
// Add new phis.
ensure_phis_everywhere
();
}
// Leave behind an undisturbed copy of the map, for future merges.
set_map
(
clone_map
());
}
...
...
@@ -1113,7 +1132,7 @@ void Parse::Block::init_node(Parse* outer, int rpo) {
_preds_parsed
=
0
;
_count
=
0
;
assert
(
pred_count
()
==
0
&&
preds_parsed
()
==
0
,
"sanity"
);
assert
(
!
(
is_merged
()
||
is_parsed
()
||
is_handler
()),
"sanity"
);
assert
(
!
(
is_merged
()
||
is_parsed
()
||
is_handler
()
||
has_merged_backedge
()
),
"sanity"
);
assert
(
_live_locals
.
size
()
==
0
,
"sanity"
);
// entry point has additional predecessor
...
...
@@ -1350,10 +1369,6 @@ void Parse::do_one_block() {
set_parse_bci
(
iter
().
cur_bci
());
if
(
bci
()
==
block
()
->
limit
())
{
// insert a predicate if it falls through to a loop head block
if
(
should_add_predicate
(
bci
())){
add_predicate
();
}
// Do not walk into the next block until directed by do_all_blocks.
merge
(
bci
());
break
;
...
...
@@ -1498,17 +1513,29 @@ void Parse::merge_common(Parse::Block* target, int pnum) {
||
target
->
is_handler
()
// These have unpredictable inputs.
||
target
->
is_loop_head
()
// Known multiple inputs
||
control
()
->
is_Region
())
{
// We must hide this guy.
int
current_bci
=
bci
();
set_parse_bci
(
target
->
start
());
// Set target bci
if
(
target
->
is_SEL_head
())
{
DEBUG_ONLY
(
target
->
mark_merged_backedge
(
block
());
)
if
(
target
->
start
()
==
0
)
{
// Add loop predicate for the special case when
// there are backbranches to the method entry.
add_predicate
();
}
}
// Add a Region to start the new basic block. Phis will be added
// later lazily.
int
edges
=
target
->
pred_count
();
if
(
edges
<
pnum
)
edges
=
pnum
;
// might be a new path!
Node
*
r
=
new
(
C
,
edges
+
1
)
RegionNode
(
edges
+
1
);
Region
Node
*
r
=
new
(
C
,
edges
+
1
)
RegionNode
(
edges
+
1
);
gvn
().
set_type
(
r
,
Type
::
CONTROL
);
record_for_igvn
(
r
);
// zap all inputs to NULL for debugging (done in Node(uint) constructor)
// for (int j = 1; j < edges+1; j++) { r->init_req(j, NULL); }
r
->
init_req
(
pnum
,
control
());
set_control
(
r
);
set_parse_bci
(
current_bci
);
// Restore bci
}
// Convert the existing Parser mapping into a mapping at this bci.
...
...
@@ -1517,7 +1544,11 @@ void Parse::merge_common(Parse::Block* target, int pnum) {
}
else
{
// Prior mapping at this bci
if
(
TraceOptoParse
)
{
tty
->
print
(
" with previous state"
);
}
#ifdef ASSERT
if
(
target
->
is_SEL_head
())
{
target
->
mark_merged_backedge
(
block
());
}
#endif
// We must not manufacture more phis if the target is already parsed.
bool
nophi
=
target
->
is_parsed
();
...
...
@@ -2054,37 +2085,6 @@ void Parse::add_safepoint() {
}
}
//------------------------------should_add_predicate--------------------------
bool
Parse
::
should_add_predicate
(
int
target_bci
)
{
if
(
!
UseLoopPredicate
)
return
false
;
Block
*
target
=
successor_for_bci
(
target_bci
);
if
(
target
!=
NULL
&&
target
->
is_loop_head
()
&&
block
()
->
rpo
()
<
target
->
rpo
())
{
return
true
;
}
return
false
;
}
//------------------------------add_predicate---------------------------------
void
Parse
::
add_predicate
()
{
assert
(
UseLoopPredicate
,
"use only for loop predicate"
);
Node
*
cont
=
_gvn
.
intcon
(
1
);
Node
*
opq
=
_gvn
.
transform
(
new
(
C
,
2
)
Opaque1Node
(
C
,
cont
));
Node
*
bol
=
_gvn
.
transform
(
new
(
C
,
2
)
Conv2BNode
(
opq
));
IfNode
*
iff
=
create_and_map_if
(
control
(),
bol
,
PROB_MAX
,
COUNT_UNKNOWN
);
Node
*
iffalse
=
_gvn
.
transform
(
new
(
C
,
1
)
IfFalseNode
(
iff
));
C
->
add_predicate_opaq
(
opq
);
{
PreserveJVMState
pjvms
(
this
);
set_control
(
iffalse
);
uncommon_trap
(
Deoptimization
::
Reason_predicate
,
Deoptimization
::
Action_maybe_recompile
);
}
Node
*
iftrue
=
_gvn
.
transform
(
new
(
C
,
1
)
IfTrueNode
(
iff
));
set_control
(
iftrue
);
}
#ifndef PRODUCT
//------------------------show_parse_info--------------------------------------
void
Parse
::
show_parse_info
()
{
...
...
src/share/vm/opto/parse2.cpp
浏览文件 @
114dcaf7
...
...
@@ -293,11 +293,6 @@ void Parse::do_tableswitch() {
if
(
len
<
1
)
{
// If this is a backward branch, add safepoint
maybe_add_safepoint
(
default_dest
);
if
(
should_add_predicate
(
default_dest
)){
_sp
+=
1
;
// set original stack for use by uncommon_trap
add_predicate
();
_sp
-=
1
;
}
merge
(
default_dest
);
return
;
}
...
...
@@ -344,11 +339,6 @@ void Parse::do_lookupswitch() {
if
(
len
<
1
)
{
// If this is a backward branch, add safepoint
maybe_add_safepoint
(
default_dest
);
if
(
should_add_predicate
(
default_dest
)){
_sp
+=
1
;
// set original stack for use by uncommon_trap
add_predicate
();
_sp
-=
1
;
}
merge
(
default_dest
);
return
;
}
...
...
@@ -756,9 +746,6 @@ void Parse::do_jsr() {
push
(
_gvn
.
makecon
(
ret_addr
));
// Flow to the jsr.
if
(
should_add_predicate
(
jsr_bci
)){
add_predicate
();
}
merge
(
jsr_bci
);
}
...
...
@@ -1040,11 +1027,6 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) {
profile_taken_branch
(
target_bci
);
adjust_map_after_if
(
btest
,
c
,
prob
,
branch_block
,
next_block
);
if
(
!
stopped
())
{
if
(
should_add_predicate
(
target_bci
)){
// add a predicate if it branches to a loop
int
nargs
=
repush_if_args
();
// set original stack for uncommon_trap
add_predicate
();
_sp
-=
nargs
;
}
merge
(
target_bci
);
}
}
...
...
@@ -1168,11 +1150,6 @@ void Parse::do_if(BoolTest::mask btest, Node* c) {
profile_taken_branch
(
target_bci
);
adjust_map_after_if
(
taken_btest
,
c
,
prob
,
branch_block
,
next_block
);
if
(
!
stopped
())
{
if
(
should_add_predicate
(
target_bci
)){
// add a predicate if it branches to a loop
int
nargs
=
repush_if_args
();
// set original stack for the uncommon_trap
add_predicate
();
_sp
-=
nargs
;
}
merge
(
target_bci
);
}
}
...
...
@@ -2166,10 +2143,6 @@ void Parse::do_one_bytecode() {
// Update method data
profile_taken_branch
(
target_bci
);
// Add loop predicate if it goes to a loop
if
(
should_add_predicate
(
target_bci
)){
add_predicate
();
}
// Merge the current control into the target basic block
merge
(
target_bci
);
...
...
src/share/vm/opto/stringopts.cpp
浏览文件 @
114dcaf7
...
...
@@ -969,6 +969,10 @@ Node* PhaseStringOpts::int_stringSize(GraphKit& kit, Node* arg) {
// for (int i=0; ; i++)
// if (x <= sizeTable[i])
// return i+1;
// Add loop predicate first.
kit
.
add_predicate
();
RegionNode
*
loop
=
new
(
C
,
3
)
RegionNode
(
3
);
loop
->
init_req
(
1
,
kit
.
control
());
kit
.
gvn
().
set_type
(
loop
,
Type
::
CONTROL
);
...
...
@@ -1086,6 +1090,9 @@ void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, N
// }
{
// Add loop predicate first.
kit
.
add_predicate
();
RegionNode
*
head
=
new
(
C
,
3
)
RegionNode
(
3
);
head
->
init_req
(
1
,
kit
.
control
());
kit
.
gvn
().
set_type
(
head
,
Type
::
CONTROL
);
...
...
test/compiler/6987555/Test6987555.java
已删除
100644 → 0
浏览文件 @
bdff6c3c
/*
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/**
* @test
* @bug 6987555
* @summary JSR 292 unboxing to a boolean value fails on big-endian SPARC
*
* @run main/othervm -Xint -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6987555
*/
import
java.dyn.*
;
public
class
Test6987555
{
private
static
final
Class
CLASS
=
Test6987555
.
class
;
private
static
final
String
NAME
=
"foo"
;
private
static
final
boolean
DEBUG
=
false
;
public
static
void
main
(
String
[]
args
)
throws
Throwable
{
testboolean
();
testbyte
();
testchar
();
testshort
();
testint
();
}
// boolean
static
void
testboolean
()
throws
Throwable
{
doboolean
(
false
);
doboolean
(
true
);
}
static
void
doboolean
(
boolean
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"boolean="
+
x
);
MethodHandle
mh1
=
MethodHandles
.
lookup
().
findStatic
(
CLASS
,
NAME
,
MethodType
.
methodType
(
boolean
.
class
,
boolean
.
class
));
MethodHandle
mh2
=
mh1
.
asType
(
MethodType
.
methodType
(
boolean
.
class
,
Boolean
.
class
));
boolean
a
=
(
boolean
)
mh1
.
invokeExact
(
x
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
Boolean
.
valueOf
(
x
));
assert
a
==
b
:
a
+
" != "
+
b
;
}
// byte
static
void
testbyte
()
throws
Throwable
{
byte
[]
a
=
new
byte
[]
{
Byte
.
MIN_VALUE
,
Byte
.
MIN_VALUE
+
1
,
-
0x0F
,
-
1
,
0
,
1
,
0x0F
,
Byte
.
MAX_VALUE
-
1
,
Byte
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
dobyte
(
a
[
i
]);
}
}
static
void
dobyte
(
byte
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"byte="
+
x
);
MethodHandle
mh1
=
MethodHandles
.
lookup
().
findStatic
(
CLASS
,
NAME
,
MethodType
.
methodType
(
byte
.
class
,
byte
.
class
));
MethodHandle
mh2
=
mh1
.
asType
(
MethodType
.
methodType
(
byte
.
class
,
Byte
.
class
));
byte
a
=
(
byte
)
mh1
.
invokeExact
(
x
);
byte
b
=
(
byte
)
mh2
.
invokeExact
(
Byte
.
valueOf
(
x
));
assert
a
==
b
:
a
+
" != "
+
b
;
}
// char
static
void
testchar
()
throws
Throwable
{
char
[]
a
=
new
char
[]
{
Character
.
MIN_VALUE
,
Character
.
MIN_VALUE
+
1
,
0x000F
,
0x00FF
,
0x0FFF
,
Character
.
MAX_VALUE
-
1
,
Character
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
dochar
(
a
[
i
]);
}
}
static
void
dochar
(
char
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"char="
+
x
);
MethodHandle
mh1
=
MethodHandles
.
lookup
().
findStatic
(
CLASS
,
NAME
,
MethodType
.
methodType
(
char
.
class
,
char
.
class
));
MethodHandle
mh2
=
mh1
.
asType
(
MethodType
.
methodType
(
char
.
class
,
Character
.
class
));
char
a
=
(
char
)
mh1
.
invokeExact
(
x
);
char
b
=
(
char
)
mh2
.
invokeExact
(
Character
.
valueOf
(
x
));
assert
a
==
b
:
a
+
" != "
+
b
;
}
// short
static
void
testshort
()
throws
Throwable
{
short
[]
a
=
new
short
[]
{
Short
.
MIN_VALUE
,
Short
.
MIN_VALUE
+
1
,
-
0x0FFF
,
-
0x00FF
,
-
0x000F
,
-
1
,
0
,
1
,
0x000F
,
0x00FF
,
0x0FFF
,
Short
.
MAX_VALUE
-
1
,
Short
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
doshort
(
a
[
i
]);
}
}
static
void
doshort
(
short
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"short="
+
x
);
MethodHandle
mh1
=
MethodHandles
.
lookup
().
findStatic
(
CLASS
,
NAME
,
MethodType
.
methodType
(
short
.
class
,
short
.
class
));
MethodHandle
mh2
=
mh1
.
asType
(
MethodType
.
methodType
(
short
.
class
,
Short
.
class
));
short
a
=
(
short
)
mh1
.
invokeExact
(
x
);
short
b
=
(
short
)
mh2
.
invokeExact
(
Short
.
valueOf
(
x
));
assert
a
==
b
:
a
+
" != "
+
b
;
}
// int
static
void
testint
()
throws
Throwable
{
int
[]
a
=
new
int
[]
{
Integer
.
MIN_VALUE
,
Integer
.
MIN_VALUE
+
1
,
-
0x00000FFF
,
-
0x000000FF
,
-
0x0000000F
,
-
1
,
0
,
1
,
0x0000000F
,
0x000000FF
,
0x00000FFF
,
Integer
.
MAX_VALUE
-
1
,
Integer
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
doint
(
a
[
i
]);
}
}
static
void
doint
(
int
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"int="
+
x
);
MethodHandle
mh1
=
MethodHandles
.
lookup
().
findStatic
(
CLASS
,
NAME
,
MethodType
.
methodType
(
int
.
class
,
int
.
class
));
MethodHandle
mh2
=
mh1
.
asType
(
MethodType
.
methodType
(
int
.
class
,
Integer
.
class
));
int
a
=
(
int
)
mh1
.
invokeExact
(
x
);
int
b
=
(
int
)
mh2
.
invokeExact
(
Integer
.
valueOf
(
x
));
assert
a
==
b
:
a
+
" != "
+
b
;
}
public
static
boolean
foo
(
boolean
i
)
{
return
i
;
}
public
static
byte
foo
(
byte
i
)
{
return
i
;
}
public
static
char
foo
(
char
i
)
{
return
i
;
}
public
static
short
foo
(
short
i
)
{
return
i
;
}
public
static
int
foo
(
int
i
)
{
return
i
;
}
}
test/compiler/6991596/Test6991596.java
已删除
100644 → 0
浏览文件 @
bdff6c3c
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/**
* @test
* @bug 6991596
* @summary JSR 292 unimplemented adapter_opt_i2i and adapter_opt_l2i on SPARC
*
* @run main/othervm -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6991596
*/
import
java.dyn.*
;
public
class
Test6991596
{
private
static
final
Class
CLASS
=
Test6991596
.
class
;
private
static
final
String
NAME
=
"foo"
;
private
static
final
boolean
DEBUG
=
System
.
getProperty
(
"DEBUG"
,
"false"
).
equals
(
"true"
);
public
static
void
main
(
String
[]
args
)
throws
Throwable
{
testboolean
();
testbyte
();
testchar
();
testshort
();
testint
();
testlong
();
}
// Helpers to get various methods.
static
MethodHandle
getmh1
(
Class
ret
,
Class
arg
)
throws
NoAccessException
{
return
MethodHandles
.
lookup
().
findStatic
(
CLASS
,
NAME
,
MethodType
.
methodType
(
ret
,
arg
));
}
static
MethodHandle
getmh2
(
MethodHandle
mh1
,
Class
ret
,
Class
arg
)
{
return
MethodHandles
.
convertArguments
(
mh1
,
MethodType
.
methodType
(
ret
,
arg
));
}
static
MethodHandle
getmh3
(
MethodHandle
mh1
,
Class
ret
,
Class
arg
)
{
return
MethodHandles
.
convertArguments
(
mh1
,
MethodType
.
methodType
(
ret
,
arg
));
}
// test adapter_opt_i2i
static
void
testboolean
()
throws
Throwable
{
boolean
[]
a
=
new
boolean
[]
{
true
,
false
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
doboolean
(
a
[
i
]);
}
}
static
void
doboolean
(
boolean
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"boolean="
+
x
);
// boolean
{
MethodHandle
mh1
=
getmh1
(
boolean
.
class
,
boolean
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
boolean
.
class
,
boolean
.
class
);
// TODO add this for all cases when the bugs are fixed.
//MethodHandle mh3 = getmh3(mh1, boolean.class, boolean.class);
boolean
a
=
(
boolean
)
mh1
.
invokeExact
((
boolean
)
x
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
x
);
//boolean c = mh3.<boolean>invokeExact((boolean) x);
check
(
x
,
a
,
b
);
//check(x, c, x);
}
// byte
{
MethodHandle
mh1
=
getmh1
(
byte
.
class
,
byte
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
byte
.
class
,
boolean
.
class
);
byte
a
=
(
byte
)
mh1
.
invokeExact
((
byte
)
(
x
?
1
:
0
));
byte
b
=
(
byte
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// char
{
MethodHandle
mh1
=
getmh1
(
char
.
class
,
char
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
char
.
class
,
boolean
.
class
);
char
a
=
(
char
)
mh1
.
invokeExact
((
char
)
(
x
?
1
:
0
));
char
b
=
(
char
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// short
{
MethodHandle
mh1
=
getmh1
(
short
.
class
,
short
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
short
.
class
,
boolean
.
class
);
short
a
=
(
short
)
mh1
.
invokeExact
((
short
)
(
x
?
1
:
0
));
short
b
=
(
short
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
}
static
void
testbyte
()
throws
Throwable
{
byte
[]
a
=
new
byte
[]
{
Byte
.
MIN_VALUE
,
Byte
.
MIN_VALUE
+
1
,
-
0x0F
,
-
1
,
0
,
1
,
0x0F
,
Byte
.
MAX_VALUE
-
1
,
Byte
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
dobyte
(
a
[
i
]);
}
}
static
void
dobyte
(
byte
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"byte="
+
x
);
// boolean
{
MethodHandle
mh1
=
getmh1
(
boolean
.
class
,
boolean
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
boolean
.
class
,
byte
.
class
);
boolean
a
=
(
boolean
)
mh1
.
invokeExact
((
x
&
1
)
==
1
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// byte
{
MethodHandle
mh1
=
getmh1
(
byte
.
class
,
byte
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
byte
.
class
,
byte
.
class
);
byte
a
=
(
byte
)
mh1
.
invokeExact
((
byte
)
x
);
byte
b
=
(
byte
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// char
{
MethodHandle
mh1
=
getmh1
(
char
.
class
,
char
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
char
.
class
,
byte
.
class
);
char
a
=
(
char
)
mh1
.
invokeExact
((
char
)
x
);
char
b
=
(
char
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// short
{
MethodHandle
mh1
=
getmh1
(
short
.
class
,
short
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
short
.
class
,
byte
.
class
);
short
a
=
(
short
)
mh1
.
invokeExact
((
short
)
x
);
short
b
=
(
short
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
}
static
void
testchar
()
throws
Throwable
{
char
[]
a
=
new
char
[]
{
Character
.
MIN_VALUE
,
Character
.
MIN_VALUE
+
1
,
0x000F
,
0x00FF
,
0x0FFF
,
Character
.
MAX_VALUE
-
1
,
Character
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
dochar
(
a
[
i
]);
}
}
static
void
dochar
(
char
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"char="
+
x
);
// boolean
{
MethodHandle
mh1
=
getmh1
(
boolean
.
class
,
boolean
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
boolean
.
class
,
char
.
class
);
boolean
a
=
(
boolean
)
mh1
.
invokeExact
((
x
&
1
)
==
1
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// byte
{
MethodHandle
mh1
=
getmh1
(
byte
.
class
,
byte
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
byte
.
class
,
char
.
class
);
byte
a
=
(
byte
)
mh1
.
invokeExact
((
byte
)
x
);
byte
b
=
(
byte
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// char
{
MethodHandle
mh1
=
getmh1
(
char
.
class
,
char
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
char
.
class
,
char
.
class
);
char
a
=
(
char
)
mh1
.
invokeExact
((
char
)
x
);
char
b
=
(
char
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// short
{
MethodHandle
mh1
=
getmh1
(
short
.
class
,
short
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
short
.
class
,
char
.
class
);
short
a
=
(
short
)
mh1
.
invokeExact
((
short
)
x
);
short
b
=
(
short
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
}
static
void
testshort
()
throws
Throwable
{
short
[]
a
=
new
short
[]
{
Short
.
MIN_VALUE
,
Short
.
MIN_VALUE
+
1
,
-
0x0FFF
,
-
0x00FF
,
-
0x000F
,
-
1
,
0
,
1
,
0x000F
,
0x00FF
,
0x0FFF
,
Short
.
MAX_VALUE
-
1
,
Short
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
doshort
(
a
[
i
]);
}
}
static
void
doshort
(
short
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"short="
+
x
);
// boolean
{
MethodHandle
mh1
=
getmh1
(
boolean
.
class
,
boolean
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
boolean
.
class
,
short
.
class
);
boolean
a
=
(
boolean
)
mh1
.
invokeExact
((
x
&
1
)
==
1
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// byte
{
MethodHandle
mh1
=
getmh1
(
byte
.
class
,
byte
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
byte
.
class
,
short
.
class
);
byte
a
=
(
byte
)
mh1
.
invokeExact
((
byte
)
x
);
byte
b
=
(
byte
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// char
{
MethodHandle
mh1
=
getmh1
(
char
.
class
,
char
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
char
.
class
,
short
.
class
);
char
a
=
(
char
)
mh1
.
invokeExact
((
char
)
x
);
char
b
=
(
char
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// short
{
MethodHandle
mh1
=
getmh1
(
short
.
class
,
short
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
short
.
class
,
short
.
class
);
short
a
=
(
short
)
mh1
.
invokeExact
((
short
)
x
);
short
b
=
(
short
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
}
static
void
testint
()
throws
Throwable
{
int
[]
a
=
new
int
[]
{
Integer
.
MIN_VALUE
,
Integer
.
MIN_VALUE
+
1
,
-
0x0FFFFFFF
,
-
0x00FFFFFF
,
-
0x000FFFFF
,
-
0x0000FFFF
,
-
0x00000FFF
,
-
0x000000FF
,
-
0x0000000F
,
-
1
,
0
,
1
,
0x0000000F
,
0x000000FF
,
0x00000FFF
,
0x0000FFFF
,
0x000FFFFF
,
0x00FFFFFF
,
0x0FFFFFFF
,
Integer
.
MAX_VALUE
-
1
,
Integer
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
doint
(
a
[
i
]);
}
}
static
void
doint
(
int
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"int="
+
x
);
// boolean
{
MethodHandle
mh1
=
getmh1
(
boolean
.
class
,
boolean
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
boolean
.
class
,
int
.
class
);
boolean
a
=
(
boolean
)
mh1
.
invokeExact
((
x
&
1
)
==
1
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// byte
{
MethodHandle
mh1
=
getmh1
(
byte
.
class
,
byte
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
byte
.
class
,
int
.
class
);
byte
a
=
(
byte
)
mh1
.
invokeExact
((
byte
)
x
);
byte
b
=
(
byte
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// char
{
MethodHandle
mh1
=
getmh1
(
char
.
class
,
char
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
char
.
class
,
int
.
class
);
char
a
=
(
char
)
mh1
.
invokeExact
((
char
)
x
);
char
b
=
(
char
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// short
{
MethodHandle
mh1
=
getmh1
(
short
.
class
,
short
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
short
.
class
,
int
.
class
);
short
a
=
(
short
)
mh1
.
invokeExact
((
short
)
x
);
short
b
=
(
short
)
mh2
.
invokeExact
(
x
);
assert
a
==
b
:
a
+
" != "
+
b
;
check
(
x
,
a
,
b
);
}
// int
{
MethodHandle
mh1
=
getmh1
(
int
.
class
,
int
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
int
.
class
,
int
.
class
);
int
a
=
(
int
)
mh1
.
invokeExact
((
int
)
x
);
int
b
=
(
int
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
}
// test adapter_opt_l2i
static
void
testlong
()
throws
Throwable
{
long
[]
a
=
new
long
[]
{
Long
.
MIN_VALUE
,
Long
.
MIN_VALUE
+
1
,
-
0x000000000FFFFFFF
L
,
-
0x0000000000FFFFFF
L
,
-
0x00000000000FFFFF
L
,
-
0x000000000000FFFF
L
,
-
0x0000000000000FFF
L
,
-
0x00000000000000FF
L
,
-
0x000000000000000F
L
,
-
1L
,
0L
,
1L
,
0x000000000000000F
L
,
0x00000000000000FF
L
,
0x0000000000000FFF
L
,
0x0000000000000FFF
L
,
0x000000000000FFFF
L
,
0x00000000000FFFFF
L
,
0x0000000000FFFFFF
L
,
0x000000000FFFFFFF
L
,
Long
.
MAX_VALUE
-
1
,
Long
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
dolong
(
a
[
i
]);
}
}
static
void
dolong
(
long
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"long="
+
x
);
// boolean
{
MethodHandle
mh1
=
getmh1
(
boolean
.
class
,
boolean
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
boolean
.
class
,
long
.
class
);
boolean
a
=
(
boolean
)
mh1
.
invokeExact
((
x
&
1L
)
==
1L
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// byte
{
MethodHandle
mh1
=
getmh1
(
byte
.
class
,
byte
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
byte
.
class
,
long
.
class
);
byte
a
=
(
byte
)
mh1
.
invokeExact
((
byte
)
x
);
byte
b
=
(
byte
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// char
{
MethodHandle
mh1
=
getmh1
(
char
.
class
,
char
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
char
.
class
,
long
.
class
);
char
a
=
(
char
)
mh1
.
invokeExact
((
char
)
x
);
char
b
=
(
char
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// short
{
MethodHandle
mh1
=
getmh1
(
short
.
class
,
short
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
short
.
class
,
long
.
class
);
short
a
=
(
short
)
mh1
.
invokeExact
((
short
)
x
);
short
b
=
(
short
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// int
{
MethodHandle
mh1
=
getmh1
(
int
.
class
,
int
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
int
.
class
,
long
.
class
);
int
a
=
(
int
)
mh1
.
invokeExact
((
int
)
x
);
int
b
=
(
int
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
}
static
void
check
(
boolean
x
,
boolean
e
,
boolean
a
)
{
p
(
z2h
(
x
),
z2h
(
e
),
z2h
(
a
));
assert
e
==
a
:
z2h
(
x
)
+
": "
+
z2h
(
e
)
+
" != "
+
z2h
(
a
);
}
static
void
check
(
boolean
x
,
byte
e
,
byte
a
)
{
p
(
z2h
(
x
),
i2h
(
e
),
i2h
(
a
));
assert
e
==
a
:
z2h
(
x
)
+
": "
+
i2h
(
e
)
+
" != "
+
i2h
(
a
);
}
static
void
check
(
boolean
x
,
int
e
,
int
a
)
{
p
(
z2h
(
x
),
i2h
(
e
),
i2h
(
a
));
assert
e
==
a
:
z2h
(
x
)
+
": "
+
i2h
(
e
)
+
" != "
+
i2h
(
a
);
}
static
void
check
(
int
x
,
boolean
e
,
boolean
a
)
{
p
(
i2h
(
x
),
z2h
(
e
),
z2h
(
a
));
assert
e
==
a
:
i2h
(
x
)
+
": "
+
z2h
(
e
)
+
" != "
+
z2h
(
a
);
}
static
void
check
(
int
x
,
byte
e
,
byte
a
)
{
p
(
i2h
(
x
),
i2h
(
e
),
i2h
(
a
));
assert
e
==
a
:
i2h
(
x
)
+
": "
+
i2h
(
e
)
+
" != "
+
i2h
(
a
);
}
static
void
check
(
int
x
,
int
e
,
int
a
)
{
p
(
i2h
(
x
),
i2h
(
e
),
i2h
(
a
));
assert
e
==
a
:
i2h
(
x
)
+
": "
+
i2h
(
e
)
+
" != "
+
i2h
(
a
);
}
static
void
check
(
long
x
,
boolean
e
,
boolean
a
)
{
p
(
l2h
(
x
),
z2h
(
e
),
z2h
(
a
));
assert
e
==
a
:
l2h
(
x
)
+
": "
+
z2h
(
e
)
+
" != "
+
z2h
(
a
);
}
static
void
check
(
long
x
,
byte
e
,
byte
a
)
{
p
(
l2h
(
x
),
i2h
(
e
),
i2h
(
a
));
assert
e
==
a
:
l2h
(
x
)
+
": "
+
i2h
(
e
)
+
" != "
+
i2h
(
a
);
}
static
void
check
(
long
x
,
int
e
,
int
a
)
{
p
(
l2h
(
x
),
i2h
(
e
),
i2h
(
a
));
assert
e
==
a
:
l2h
(
x
)
+
": "
+
i2h
(
e
)
+
" != "
+
i2h
(
a
);
}
static
void
p
(
String
x
,
String
e
,
String
a
)
{
if
(
DEBUG
)
System
.
out
.
println
(
x
+
": expected: "
+
e
+
", actual: "
+
a
);
}
static
String
z2h
(
boolean
x
)
{
return
x
?
"1"
:
"0"
;
}
static
String
i2h
(
int
x
)
{
return
Integer
.
toHexString
(
x
);
}
static
String
l2h
(
long
x
)
{
return
Long
.
toHexString
(
x
);
}
// to int
public
static
boolean
foo
(
boolean
i
)
{
return
i
;
}
public
static
byte
foo
(
byte
i
)
{
return
i
;
}
public
static
char
foo
(
char
i
)
{
return
i
;
}
public
static
short
foo
(
short
i
)
{
return
i
;
}
public
static
int
foo
(
int
i
)
{
return
i
;
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录