Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
b85595b7
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看板
提交
b85595b7
编写于
12月 05, 2007
作者:
N
never
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6395208: Elide autoboxing for calls to HashMap.get(int) and HashMap.get(long)
Reviewed-by: kvn, rasbold
上级
6cfe96aa
变更
16
显示空白变更内容
内联
并排
Showing
16 changed file
with
540 addition
and
67 deletion
+540
-67
src/share/vm/ci/ciObjArray.cpp
src/share/vm/ci/ciObjArray.cpp
+43
-0
src/share/vm/ci/ciObjArray.hpp
src/share/vm/ci/ciObjArray.hpp
+2
-0
src/share/vm/classfile/vmSymbols.hpp
src/share/vm/classfile/vmSymbols.hpp
+6
-0
src/share/vm/includeDB_core
src/share/vm/includeDB_core
+10
-5
src/share/vm/opto/addnode.cpp
src/share/vm/opto/addnode.cpp
+22
-0
src/share/vm/opto/addnode.hpp
src/share/vm/opto/addnode.hpp
+5
-0
src/share/vm/opto/c2_globals.hpp
src/share/vm/opto/c2_globals.hpp
+6
-0
src/share/vm/opto/cfgnode.hpp
src/share/vm/opto/cfgnode.hpp
+6
-0
src/share/vm/opto/ifnode.cpp
src/share/vm/opto/ifnode.cpp
+158
-0
src/share/vm/opto/loopnode.cpp
src/share/vm/opto/loopnode.cpp
+1
-54
src/share/vm/opto/loopnode.hpp
src/share/vm/opto/loopnode.hpp
+0
-1
src/share/vm/opto/memnode.cpp
src/share/vm/opto/memnode.cpp
+224
-0
src/share/vm/opto/memnode.hpp
src/share/vm/opto/memnode.hpp
+3
-0
src/share/vm/opto/parse2.cpp
src/share/vm/opto/parse2.cpp
+36
-7
src/share/vm/opto/type.hpp
src/share/vm/opto/type.hpp
+2
-0
src/share/vm/runtime/arguments.cpp
src/share/vm/runtime/arguments.cpp
+16
-0
未找到文件。
src/share/vm/ci/ciObjArray.cpp
0 → 100644
浏览文件 @
b85595b7
/*
* Copyright 1999-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*
*/
#include "incls/_precompiled.incl"
#include "incls/_ciObjArray.cpp.incl"
// ciObjArray
//
// This class represents an objArrayOop in the HotSpot virtual
// machine.
ciObject
*
ciObjArray
::
obj_at
(
int
index
)
{
VM_ENTRY_MARK
;
objArrayOop
array
=
get_objArrayOop
();
if
(
index
<
0
||
index
>=
array
->
length
())
return
NULL
;
oop
o
=
array
->
obj_at
(
index
);
if
(
o
==
NULL
)
{
return
ciNullObject
::
make
();
}
else
{
return
CURRENT_ENV
->
get_object
(
o
);
}
}
src/share/vm/ci/ciObjArray.hpp
浏览文件 @
b85595b7
...
...
@@ -43,4 +43,6 @@ protected:
public:
// What kind of ciObject is this?
bool
is_obj_array
()
{
return
true
;
}
ciObject
*
obj_at
(
int
index
);
};
src/share/vm/classfile/vmSymbols.hpp
浏览文件 @
b85595b7
...
...
@@ -58,12 +58,17 @@
template(java_lang_ThreadDeath, "java/lang/ThreadDeath") \
template(java_lang_Boolean, "java/lang/Boolean") \
template(java_lang_Character, "java/lang/Character") \
template(java_lang_Character_CharacterCache, "java/lang/Character$CharacterCache") \
template(java_lang_Float, "java/lang/Float") \
template(java_lang_Double, "java/lang/Double") \
template(java_lang_Byte, "java/lang/Byte") \
template(java_lang_Byte_Cache, "java/lang/Byte$ByteCache") \
template(java_lang_Short, "java/lang/Short") \
template(java_lang_Short_ShortCache, "java/lang/Short$ShortCache") \
template(java_lang_Integer, "java/lang/Integer") \
template(java_lang_Integer_IntegerCache, "java/lang/Integer$IntegerCache") \
template(java_lang_Long, "java/lang/Long") \
template(java_lang_Long_LongCache, "java/lang/Long$LongCache") \
template(java_lang_Shutdown, "java/lang/Shutdown") \
template(java_lang_ref_Reference, "java/lang/ref/Reference") \
template(java_lang_ref_SoftReference, "java/lang/ref/SoftReference") \
...
...
@@ -274,6 +279,7 @@
template(exclusive_owner_thread_name, "exclusiveOwnerThread") \
template(park_blocker_name, "parkBlocker") \
template(park_event_name, "nativeParkEventPointer") \
template(cache_field_name, "cache") \
template(value_name, "value") \
\
/* non-intrinsic name/signature pairs: */
\
...
...
src/share/vm/includeDB_core
浏览文件 @
b85595b7
...
...
@@ -720,6 +720,11 @@ ciObjArray.hpp ciArray.hpp
ciObjArray.hpp ciClassList.hpp
ciObjArray.hpp objArrayOop.hpp
ciObjArray.cpp ciObjArray.hpp
ciObjArray.cpp ciNullObject.hpp
ciObjArray.cpp ciUtilities.hpp
ciObjArray.cpp objArrayOop.hpp
ciObjArrayKlass.cpp ciInstanceKlass.hpp
ciObjArrayKlass.cpp ciObjArrayKlass.hpp
ciObjArrayKlass.cpp ciObjArrayKlassKlass.hpp
...
...
src/share/vm/opto/addnode.cpp
浏览文件 @
b85595b7
...
...
@@ -608,6 +608,28 @@ Node* AddPNode::Ideal_base_and_offset(Node* ptr, PhaseTransform* phase,
return
NULL
;
}
//------------------------------unpack_offsets----------------------------------
// Collect the AddP offset values into the elements array, giving up
// if there are more than length.
int
AddPNode
::
unpack_offsets
(
Node
*
elements
[],
int
length
)
{
int
count
=
0
;
Node
*
addr
=
this
;
Node
*
base
=
addr
->
in
(
AddPNode
::
Base
);
while
(
addr
->
is_AddP
())
{
if
(
addr
->
in
(
AddPNode
::
Base
)
!=
base
)
{
// give up
return
-
1
;
}
elements
[
count
++
]
=
addr
->
in
(
AddPNode
::
Offset
);
if
(
count
==
length
)
{
// give up
return
-
1
;
}
addr
=
addr
->
in
(
AddPNode
::
Address
);
}
return
count
;
}
//------------------------------match_edge-------------------------------------
// Do we Match on this edge index or not? Do not match base pointer edge
uint
AddPNode
::
match_edge
(
uint
idx
)
const
{
...
...
src/share/vm/opto/addnode.hpp
浏览文件 @
b85595b7
...
...
@@ -144,6 +144,11 @@ public:
static
Node
*
Ideal_base_and_offset
(
Node
*
ptr
,
PhaseTransform
*
phase
,
// second return value:
intptr_t
&
offset
);
// Collect the AddP offset values into the elements array, giving up
// if there are more than length.
int
unpack_offsets
(
Node
*
elements
[],
int
length
);
// Do not match base-ptr edge
virtual
uint
match_edge
(
uint
idx
)
const
;
static
const
Type
*
mach_bottom_type
(
const
MachNode
*
n
);
// used by ad_<arch>.hpp
...
...
src/share/vm/opto/c2_globals.hpp
浏览文件 @
b85595b7
...
...
@@ -367,6 +367,12 @@
notproduct(bool, PrintEliminateLocks, false, \
"Print out when locks are eliminated") \
\
diagnostic(bool, EliminateAutoBox, false, \
"Private flag to control optimizations for autobox elimination") \
\
product(intx, AutoBoxCacheMax, 128, \
"Sets max value cached by the java.lang.Integer autobox cache") \
\
product(bool, DoEscapeAnalysis, false, \
"Perform escape analysis") \
\
...
...
src/share/vm/opto/cfgnode.hpp
浏览文件 @
b85595b7
...
...
@@ -310,8 +310,14 @@ public:
virtual
const
RegMask
&
out_RegMask
()
const
;
void
dominated_by
(
Node
*
prev_dom
,
PhaseIterGVN
*
igvn
);
int
is_range_check
(
Node
*
&
range
,
Node
*
&
index
,
jint
&
offset
);
Node
*
fold_compares
(
PhaseGVN
*
phase
);
static
Node
*
up_one_dom
(
Node
*
curr
,
bool
linear_only
=
false
);
// Takes the type of val and filters it through the test represented
// by if_proj and returns a more refined type if one is produced.
// Returns NULL is it couldn't improve the type.
static
const
TypeInt
*
filtered_int_type
(
PhaseGVN
*
phase
,
Node
*
val
,
Node
*
if_proj
);
#ifndef PRODUCT
virtual
void
dump_spec
(
outputStream
*
st
)
const
;
#endif
...
...
src/share/vm/opto/ifnode.cpp
浏览文件 @
b85595b7
...
...
@@ -543,6 +543,159 @@ Node* IfNode::up_one_dom(Node *curr, bool linear_only) {
return
NULL
;
// Dead loop? Or hit root?
}
//------------------------------filtered_int_type--------------------------------
// Return a possibly more restrictive type for val based on condition control flow for an if
const
TypeInt
*
IfNode
::
filtered_int_type
(
PhaseGVN
*
gvn
,
Node
*
val
,
Node
*
if_proj
)
{
assert
(
if_proj
&&
(
if_proj
->
Opcode
()
==
Op_IfTrue
||
if_proj
->
Opcode
()
==
Op_IfFalse
),
"expecting an if projection"
);
if
(
if_proj
->
in
(
0
)
&&
if_proj
->
in
(
0
)
->
is_If
())
{
IfNode
*
iff
=
if_proj
->
in
(
0
)
->
as_If
();
if
(
iff
->
in
(
1
)
&&
iff
->
in
(
1
)
->
is_Bool
())
{
BoolNode
*
bol
=
iff
->
in
(
1
)
->
as_Bool
();
if
(
bol
->
in
(
1
)
&&
bol
->
in
(
1
)
->
is_Cmp
())
{
const
CmpNode
*
cmp
=
bol
->
in
(
1
)
->
as_Cmp
();
if
(
cmp
->
in
(
1
)
==
val
)
{
const
TypeInt
*
cmp2_t
=
gvn
->
type
(
cmp
->
in
(
2
))
->
isa_int
();
if
(
cmp2_t
!=
NULL
)
{
jint
lo
=
cmp2_t
->
_lo
;
jint
hi
=
cmp2_t
->
_hi
;
BoolTest
::
mask
msk
=
if_proj
->
Opcode
()
==
Op_IfTrue
?
bol
->
_test
.
_test
:
bol
->
_test
.
negate
();
switch
(
msk
)
{
case
BoolTest
::
ne
:
// Can't refine type
return
NULL
;
case
BoolTest
::
eq
:
return
cmp2_t
;
case
BoolTest
::
lt
:
lo
=
TypeInt
::
INT
->
_lo
;
if
(
hi
-
1
<
hi
)
{
hi
=
hi
-
1
;
}
break
;
case
BoolTest
::
le
:
lo
=
TypeInt
::
INT
->
_lo
;
break
;
case
BoolTest
::
gt
:
if
(
lo
+
1
>
lo
)
{
lo
=
lo
+
1
;
}
hi
=
TypeInt
::
INT
->
_hi
;
break
;
case
BoolTest
::
ge
:
// lo unchanged
hi
=
TypeInt
::
INT
->
_hi
;
break
;
}
const
TypeInt
*
rtn_t
=
TypeInt
::
make
(
lo
,
hi
,
cmp2_t
->
_widen
);
return
rtn_t
;
}
}
}
}
}
return
NULL
;
}
//------------------------------fold_compares----------------------------
// See if a pair of CmpIs can be converted into a CmpU. In some cases
// the direction of this if is determined by the preciding if so it
// can be eliminate entirely. Given an if testing (CmpI n c) check
// for an immediately control dependent if that is testing (CmpI n c2)
// and has one projection leading to this if and the other projection
// leading to a region that merges one of this ifs control
// projections.
//
// If
// / |
// / |
// / |
// If |
// /\ |
// / \ |
// / \ |
// / Region
//
Node
*
IfNode
::
fold_compares
(
PhaseGVN
*
phase
)
{
if
(
!
EliminateAutoBox
||
Opcode
()
!=
Op_If
)
return
NULL
;
Node
*
this_cmp
=
in
(
1
)
->
in
(
1
);
if
(
this_cmp
!=
NULL
&&
this_cmp
->
Opcode
()
==
Op_CmpI
&&
this_cmp
->
in
(
2
)
->
is_Con
()
&&
this_cmp
->
in
(
2
)
!=
phase
->
C
->
top
())
{
Node
*
ctrl
=
in
(
0
);
BoolNode
*
this_bool
=
in
(
1
)
->
as_Bool
();
Node
*
n
=
this_cmp
->
in
(
1
);
int
hi
=
this_cmp
->
in
(
2
)
->
get_int
();
if
(
ctrl
!=
NULL
&&
ctrl
->
is_Proj
()
&&
ctrl
->
outcnt
()
==
1
&&
ctrl
->
in
(
0
)
->
is_If
()
&&
ctrl
->
in
(
0
)
->
outcnt
()
==
2
&&
ctrl
->
in
(
0
)
->
in
(
1
)
->
is_Bool
()
&&
ctrl
->
in
(
0
)
->
in
(
1
)
->
in
(
1
)
->
Opcode
()
==
Op_CmpI
&&
ctrl
->
in
(
0
)
->
in
(
1
)
->
in
(
1
)
->
in
(
2
)
->
is_Con
()
&&
ctrl
->
in
(
0
)
->
in
(
1
)
->
in
(
1
)
->
in
(
1
)
==
n
)
{
IfNode
*
dom_iff
=
ctrl
->
in
(
0
)
->
as_If
();
Node
*
otherproj
=
dom_iff
->
proj_out
(
!
ctrl
->
as_Proj
()
->
_con
);
if
(
otherproj
->
outcnt
()
==
1
&&
otherproj
->
unique_out
()
->
is_Region
()
&&
this_bool
->
_test
.
_test
!=
BoolTest
::
ne
&&
this_bool
->
_test
.
_test
!=
BoolTest
::
eq
)
{
// Identify which proj goes to the region and which continues on
RegionNode
*
region
=
otherproj
->
unique_out
()
->
as_Region
();
Node
*
success
=
NULL
;
Node
*
fail
=
NULL
;
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
Node
*
proj
=
proj_out
(
i
);
if
(
success
==
NULL
&&
proj
->
outcnt
()
==
1
&&
proj
->
unique_out
()
==
region
)
{
success
=
proj
;
}
else
if
(
fail
==
NULL
)
{
fail
=
proj
;
}
else
{
success
=
fail
=
NULL
;
}
}
if
(
success
!=
NULL
&&
fail
!=
NULL
&&
!
region
->
has_phi
())
{
int
lo
=
dom_iff
->
in
(
1
)
->
in
(
1
)
->
in
(
2
)
->
get_int
();
BoolNode
*
dom_bool
=
dom_iff
->
in
(
1
)
->
as_Bool
();
Node
*
dom_cmp
=
dom_bool
->
in
(
1
);
const
TypeInt
*
failtype
=
filtered_int_type
(
phase
,
n
,
ctrl
);
if
(
failtype
!=
NULL
)
{
const
TypeInt
*
type2
=
filtered_int_type
(
phase
,
n
,
fail
);
if
(
type2
!=
NULL
)
{
failtype
=
failtype
->
join
(
type2
)
->
is_int
();
}
else
{
failtype
=
NULL
;
}
}
if
(
failtype
!=
NULL
&&
dom_bool
->
_test
.
_test
!=
BoolTest
::
ne
&&
dom_bool
->
_test
.
_test
!=
BoolTest
::
eq
)
{
int
bound
=
failtype
->
_hi
-
failtype
->
_lo
+
1
;
if
(
failtype
->
_hi
!=
max_jint
&&
failtype
->
_lo
!=
min_jint
&&
bound
>
1
)
{
// Merge the two compares into a single unsigned compare by building (CmpU (n - lo) hi)
BoolTest
::
mask
cond
=
fail
->
as_Proj
()
->
_con
?
BoolTest
::
lt
:
BoolTest
::
ge
;
Node
*
adjusted
=
phase
->
transform
(
new
(
phase
->
C
,
3
)
SubINode
(
n
,
phase
->
intcon
(
failtype
->
_lo
)));
Node
*
newcmp
=
phase
->
transform
(
new
(
phase
->
C
,
3
)
CmpUNode
(
adjusted
,
phase
->
intcon
(
bound
)));
Node
*
newbool
=
phase
->
transform
(
new
(
phase
->
C
,
2
)
BoolNode
(
newcmp
,
cond
));
phase
->
hash_delete
(
dom_iff
);
dom_iff
->
set_req
(
1
,
phase
->
intcon
(
ctrl
->
as_Proj
()
->
_con
));
phase
->
is_IterGVN
()
->
_worklist
.
push
(
dom_iff
);
phase
->
hash_delete
(
this
);
set_req
(
1
,
newbool
);
return
this
;
}
if
(
failtype
->
_lo
>
failtype
->
_hi
)
{
// previous if determines the result of this if so
// replace Bool with constant
phase
->
hash_delete
(
this
);
set_req
(
1
,
phase
->
intcon
(
success
->
as_Proj
()
->
_con
));
return
this
;
}
}
}
}
}
}
return
NULL
;
}
//------------------------------remove_useless_bool----------------------------
// Check for people making a useless boolean: things like
// if( (x < y ? true : false) ) { ... }
...
...
@@ -744,6 +897,11 @@ Node *IfNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// Normal equivalent-test check.
if
(
!
dom
)
return
NULL
;
// Dead loop?
Node
*
result
=
fold_compares
(
phase
);
if
(
result
!=
NULL
)
{
return
result
;
}
// Search up the dominator tree for an If with an identical test
while
(
dom
->
Opcode
()
!=
op
||
// Not same opcode?
dom
->
in
(
1
)
!=
in
(
1
)
||
// Not same input 1?
...
...
src/share/vm/opto/loopnode.cpp
浏览文件 @
b85595b7
...
...
@@ -651,7 +651,7 @@ const TypeInt* PhaseIdealLoop::filtered_type_from_dominators( Node* val, Node *u
while
(
if_cnt
<
if_limit
)
{
if
((
pred
->
Opcode
()
==
Op_IfTrue
||
pred
->
Opcode
()
==
Op_IfFalse
))
{
if_cnt
++
;
const
TypeInt
*
if_t
=
filtered_type_at_if
(
val
,
pred
);
const
TypeInt
*
if_t
=
IfNode
::
filtered_int_type
(
&
_igvn
,
val
,
pred
);
if
(
if_t
!=
NULL
)
{
if
(
rtn_t
==
NULL
)
{
rtn_t
=
if_t
;
...
...
@@ -674,59 +674,6 @@ const TypeInt* PhaseIdealLoop::filtered_type_from_dominators( Node* val, Node *u
}
//------------------------------filtered_type_at_if--------------------------------
// Return a possibly more restrictive type for val based on condition control flow for an if
const
TypeInt
*
PhaseIdealLoop
::
filtered_type_at_if
(
Node
*
val
,
Node
*
if_proj
)
{
assert
(
if_proj
&&
(
if_proj
->
Opcode
()
==
Op_IfTrue
||
if_proj
->
Opcode
()
==
Op_IfFalse
),
"expecting an if projection"
);
if
(
if_proj
->
in
(
0
)
&&
if_proj
->
in
(
0
)
->
is_If
())
{
IfNode
*
iff
=
if_proj
->
in
(
0
)
->
as_If
();
if
(
iff
->
in
(
1
)
&&
iff
->
in
(
1
)
->
is_Bool
())
{
BoolNode
*
bol
=
iff
->
in
(
1
)
->
as_Bool
();
if
(
bol
->
in
(
1
)
&&
bol
->
in
(
1
)
->
is_Cmp
())
{
const
CmpNode
*
cmp
=
bol
->
in
(
1
)
->
as_Cmp
();
if
(
cmp
->
in
(
1
)
==
val
)
{
const
TypeInt
*
cmp2_t
=
_igvn
.
type
(
cmp
->
in
(
2
))
->
isa_int
();
if
(
cmp2_t
!=
NULL
)
{
jint
lo
=
cmp2_t
->
_lo
;
jint
hi
=
cmp2_t
->
_hi
;
BoolTest
::
mask
msk
=
if_proj
->
Opcode
()
==
Op_IfTrue
?
bol
->
_test
.
_test
:
bol
->
_test
.
negate
();
switch
(
msk
)
{
case
BoolTest
::
ne
:
// Can't refine type
return
NULL
;
case
BoolTest
::
eq
:
return
cmp2_t
;
case
BoolTest
::
lt
:
lo
=
TypeInt
::
INT
->
_lo
;
if
(
hi
-
1
<
hi
)
{
hi
=
hi
-
1
;
}
break
;
case
BoolTest
::
le
:
lo
=
TypeInt
::
INT
->
_lo
;
break
;
case
BoolTest
::
gt
:
if
(
lo
+
1
>
lo
)
{
lo
=
lo
+
1
;
}
hi
=
TypeInt
::
INT
->
_hi
;
break
;
case
BoolTest
::
ge
:
// lo unchanged
hi
=
TypeInt
::
INT
->
_hi
;
break
;
}
const
TypeInt
*
rtn_t
=
TypeInt
::
make
(
lo
,
hi
,
cmp2_t
->
_widen
);
return
rtn_t
;
}
}
}
}
}
return
NULL
;
}
//------------------------------dump_spec--------------------------------------
// Dump special per-node info
#ifndef PRODUCT
...
...
src/share/vm/opto/loopnode.hpp
浏览文件 @
b85595b7
...
...
@@ -850,7 +850,6 @@ private:
const
TypeInt
*
filtered_type
(
Node
*
n
)
{
return
filtered_type
(
n
,
NULL
);
}
// Helpers for filtered type
const
TypeInt
*
filtered_type_from_dominators
(
Node
*
val
,
Node
*
val_ctrl
);
const
TypeInt
*
filtered_type_at_if
(
Node
*
val
,
Node
*
if_proj
);
// Helper functions
void
register_new_node
(
Node
*
n
,
Node
*
blk
);
...
...
src/share/vm/opto/memnode.cpp
浏览文件 @
b85595b7
...
...
@@ -634,6 +634,46 @@ uint LoadNode::hash() const {
Node
*
MemNode
::
can_see_stored_value
(
Node
*
st
,
PhaseTransform
*
phase
)
const
{
Node
*
ld_adr
=
in
(
MemNode
::
Address
);
const
TypeInstPtr
*
tp
=
phase
->
type
(
ld_adr
)
->
isa_instptr
();
Compile
::
AliasType
*
atp
=
tp
!=
NULL
?
phase
->
C
->
alias_type
(
tp
)
:
NULL
;
if
(
EliminateAutoBox
&&
atp
!=
NULL
&&
atp
->
index
()
>=
Compile
::
AliasIdxRaw
&&
atp
->
field
()
!=
NULL
&&
!
atp
->
field
()
->
is_volatile
())
{
uint
alias_idx
=
atp
->
index
();
bool
final
=
atp
->
field
()
->
is_final
();
Node
*
result
=
NULL
;
Node
*
current
=
st
;
// Skip through chains of MemBarNodes checking the MergeMems for
// new states for the slice of this load. Stop once any other
// kind of node is encountered. Loads from final memory can skip
// through any kind of MemBar but normal loads shouldn't skip
// through MemBarAcquire since the could allow them to move out of
// a synchronized region.
while
(
current
->
is_Proj
())
{
int
opc
=
current
->
in
(
0
)
->
Opcode
();
if
((
final
&&
opc
==
Op_MemBarAcquire
)
||
opc
==
Op_MemBarRelease
||
opc
==
Op_MemBarCPUOrder
)
{
Node
*
mem
=
current
->
in
(
0
)
->
in
(
TypeFunc
::
Memory
);
if
(
mem
->
is_MergeMem
())
{
MergeMemNode
*
merge
=
mem
->
as_MergeMem
();
Node
*
new_st
=
merge
->
memory_at
(
alias_idx
);
if
(
new_st
==
merge
->
base_memory
())
{
// Keep searching
current
=
merge
->
base_memory
();
continue
;
}
// Save the new memory state for the slice and fall through
// to exit.
result
=
new_st
;
}
}
break
;
}
if
(
result
!=
NULL
)
{
st
=
result
;
}
}
// Loop around twice in the case Load -> Initialize -> Store.
// (See PhaseIterGVN::add_users_to_worklist, which knows about this case.)
for
(
int
trip
=
0
;
trip
<=
1
;
trip
++
)
{
...
...
@@ -723,6 +763,168 @@ Node *LoadNode::Identity( PhaseTransform *phase ) {
return
this
;
}
// Returns true if the AliasType refers to the field that holds the
// cached box array. Currently only handles the IntegerCache case.
static
bool
is_autobox_cache
(
Compile
::
AliasType
*
atp
)
{
if
(
atp
!=
NULL
&&
atp
->
field
()
!=
NULL
)
{
ciField
*
field
=
atp
->
field
();
ciSymbol
*
klass
=
field
->
holder
()
->
name
();
if
(
field
->
name
()
==
ciSymbol
::
cache_field_name
()
&&
field
->
holder
()
->
uses_default_loader
()
&&
klass
==
ciSymbol
::
java_lang_Integer_IntegerCache
())
{
return
true
;
}
}
return
false
;
}
// Fetch the base value in the autobox array
static
bool
fetch_autobox_base
(
Compile
::
AliasType
*
atp
,
int
&
cache_offset
)
{
if
(
atp
!=
NULL
&&
atp
->
field
()
!=
NULL
)
{
ciField
*
field
=
atp
->
field
();
ciSymbol
*
klass
=
field
->
holder
()
->
name
();
if
(
field
->
name
()
==
ciSymbol
::
cache_field_name
()
&&
field
->
holder
()
->
uses_default_loader
()
&&
klass
==
ciSymbol
::
java_lang_Integer_IntegerCache
())
{
assert
(
field
->
is_constant
(),
"what?"
);
ciObjArray
*
array
=
field
->
constant_value
().
as_object
()
->
as_obj_array
();
// Fetch the box object at the base of the array and get its value
ciInstance
*
box
=
array
->
obj_at
(
0
)
->
as_instance
();
ciInstanceKlass
*
ik
=
box
->
klass
()
->
as_instance_klass
();
if
(
ik
->
nof_nonstatic_fields
()
==
1
)
{
// This should be true nonstatic_field_at requires calling
// nof_nonstatic_fields so check it anyway
ciConstant
c
=
box
->
field_value
(
ik
->
nonstatic_field_at
(
0
));
cache_offset
=
c
.
as_int
();
}
return
true
;
}
}
return
false
;
}
// Returns true if the AliasType refers to the value field of an
// autobox object. Currently only handles Integer.
static
bool
is_autobox_object
(
Compile
::
AliasType
*
atp
)
{
if
(
atp
!=
NULL
&&
atp
->
field
()
!=
NULL
)
{
ciField
*
field
=
atp
->
field
();
ciSymbol
*
klass
=
field
->
holder
()
->
name
();
if
(
field
->
name
()
==
ciSymbol
::
value_name
()
&&
field
->
holder
()
->
uses_default_loader
()
&&
klass
==
ciSymbol
::
java_lang_Integer
())
{
return
true
;
}
}
return
false
;
}
// We're loading from an object which has autobox behaviour.
// If this object is result of a valueOf call we'll have a phi
// merging a newly allocated object and a load from the cache.
// We want to replace this load with the original incoming
// argument to the valueOf call.
Node
*
LoadNode
::
eliminate_autobox
(
PhaseGVN
*
phase
)
{
Node
*
base
=
in
(
Address
)
->
in
(
AddPNode
::
Base
);
if
(
base
->
is_Phi
()
&&
base
->
req
()
==
3
)
{
AllocateNode
*
allocation
=
NULL
;
int
allocation_index
=
-
1
;
int
load_index
=
-
1
;
for
(
uint
i
=
1
;
i
<
base
->
req
();
i
++
)
{
allocation
=
AllocateNode
::
Ideal_allocation
(
base
->
in
(
i
),
phase
);
if
(
allocation
!=
NULL
)
{
allocation_index
=
i
;
load_index
=
3
-
allocation_index
;
break
;
}
}
LoadNode
*
load
=
NULL
;
if
(
allocation
!=
NULL
&&
base
->
in
(
load_index
)
->
is_Load
())
{
load
=
base
->
in
(
load_index
)
->
as_Load
();
}
if
(
load
!=
NULL
&&
in
(
Memory
)
->
is_Phi
()
&&
in
(
Memory
)
->
in
(
0
)
==
base
->
in
(
0
))
{
// Push the loads from the phi that comes from valueOf up
// through it to allow elimination of the loads and the recovery
// of the original value.
Node
*
mem_phi
=
in
(
Memory
);
Node
*
offset
=
in
(
Address
)
->
in
(
AddPNode
::
Offset
);
Node
*
in1
=
clone
();
Node
*
in1_addr
=
in1
->
in
(
Address
)
->
clone
();
in1_addr
->
set_req
(
AddPNode
::
Base
,
base
->
in
(
allocation_index
));
in1_addr
->
set_req
(
AddPNode
::
Address
,
base
->
in
(
allocation_index
));
in1_addr
->
set_req
(
AddPNode
::
Offset
,
offset
);
in1
->
set_req
(
0
,
base
->
in
(
allocation_index
));
in1
->
set_req
(
Address
,
in1_addr
);
in1
->
set_req
(
Memory
,
mem_phi
->
in
(
allocation_index
));
Node
*
in2
=
clone
();
Node
*
in2_addr
=
in2
->
in
(
Address
)
->
clone
();
in2_addr
->
set_req
(
AddPNode
::
Base
,
base
->
in
(
load_index
));
in2_addr
->
set_req
(
AddPNode
::
Address
,
base
->
in
(
load_index
));
in2_addr
->
set_req
(
AddPNode
::
Offset
,
offset
);
in2
->
set_req
(
0
,
base
->
in
(
load_index
));
in2
->
set_req
(
Address
,
in2_addr
);
in2
->
set_req
(
Memory
,
mem_phi
->
in
(
load_index
));
in1_addr
=
phase
->
transform
(
in1_addr
);
in1
=
phase
->
transform
(
in1
);
in2_addr
=
phase
->
transform
(
in2_addr
);
in2
=
phase
->
transform
(
in2
);
PhiNode
*
result
=
PhiNode
::
make_blank
(
base
->
in
(
0
),
this
);
result
->
set_req
(
allocation_index
,
in1
);
result
->
set_req
(
load_index
,
in2
);
return
result
;
}
}
else
if
(
base
->
is_Load
())
{
// Eliminate the load of Integer.value for integers from the cache
// array by deriving the value from the index into the array.
// Capture the offset of the load and then reverse the computation.
Node
*
load_base
=
base
->
in
(
Address
)
->
in
(
AddPNode
::
Base
);
if
(
load_base
!=
NULL
)
{
Compile
::
AliasType
*
atp
=
phase
->
C
->
alias_type
(
load_base
->
adr_type
());
intptr_t
cache_offset
;
int
shift
=
-
1
;
Node
*
cache
=
NULL
;
if
(
is_autobox_cache
(
atp
))
{
shift
=
exact_log2
(
type2aelembytes
[
T_OBJECT
]);
cache
=
AddPNode
::
Ideal_base_and_offset
(
load_base
->
in
(
Address
),
phase
,
cache_offset
);
}
if
(
cache
!=
NULL
&&
base
->
in
(
Address
)
->
is_AddP
())
{
Node
*
elements
[
4
];
int
count
=
base
->
in
(
Address
)
->
as_AddP
()
->
unpack_offsets
(
elements
,
ARRAY_SIZE
(
elements
));
int
cache_low
;
if
(
count
>
0
&&
fetch_autobox_base
(
atp
,
cache_low
))
{
int
offset
=
arrayOopDesc
::
base_offset_in_bytes
(
memory_type
())
-
(
cache_low
<<
shift
);
// Add up all the offsets making of the address of the load
Node
*
result
=
elements
[
0
];
for
(
int
i
=
1
;
i
<
count
;
i
++
)
{
result
=
phase
->
transform
(
new
(
phase
->
C
,
3
)
AddXNode
(
result
,
elements
[
i
]));
}
// Remove the constant offset from the address and then
// remove the scaling of the offset to recover the original index.
result
=
phase
->
transform
(
new
(
phase
->
C
,
3
)
AddXNode
(
result
,
phase
->
MakeConX
(
-
offset
)));
if
(
result
->
Opcode
()
==
Op_LShiftX
&&
result
->
in
(
2
)
==
phase
->
intcon
(
shift
))
{
// Peel the shift off directly but wrap it in a dummy node
// since Ideal can't return existing nodes
result
=
new
(
phase
->
C
,
3
)
RShiftXNode
(
result
->
in
(
1
),
phase
->
intcon
(
0
));
}
else
{
result
=
new
(
phase
->
C
,
3
)
RShiftXNode
(
result
,
phase
->
intcon
(
shift
));
}
#ifdef _LP64
result
=
new
(
phase
->
C
,
2
)
ConvL2INode
(
phase
->
transform
(
result
));
#endif
return
result
;
}
}
}
}
return
NULL
;
}
//------------------------------Ideal------------------------------------------
// If the load is from Field memory and the pointer is non-null, we can
// zero out the control input.
...
...
@@ -755,6 +957,17 @@ Node *LoadNode::Ideal(PhaseGVN *phase, bool can_reshape) {
}
}
if
(
EliminateAutoBox
&&
can_reshape
&&
in
(
Address
)
->
is_AddP
())
{
Node
*
base
=
in
(
Address
)
->
in
(
AddPNode
::
Base
);
if
(
base
!=
NULL
)
{
Compile
::
AliasType
*
atp
=
phase
->
C
->
alias_type
(
adr_type
());
if
(
is_autobox_object
(
atp
))
{
Node
*
result
=
eliminate_autobox
(
phase
);
if
(
result
!=
NULL
)
return
result
;
}
}
}
// Check for prior store with a different base or offset; make Load
// independent. Skip through any number of them. Bail out if the stores
// are in an endless dead cycle and report no progress. This is a key
...
...
@@ -858,6 +1071,17 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const {
// This can happen if a interface-typed array narrows to a class type.
jt
=
_type
;
}
if
(
EliminateAutoBox
)
{
// The pointers in the autobox arrays are always non-null
Node
*
base
=
in
(
Address
)
->
in
(
AddPNode
::
Base
);
if
(
base
!=
NULL
)
{
Compile
::
AliasType
*
atp
=
phase
->
C
->
alias_type
(
base
->
adr_type
());
if
(
is_autobox_cache
(
atp
))
{
return
jt
->
join
(
TypePtr
::
NOTNULL
)
->
is_ptr
();
}
}
}
return
jt
;
}
}
...
...
src/share/vm/opto/memnode.hpp
浏览文件 @
b85595b7
...
...
@@ -141,6 +141,9 @@ public:
// zero out the control input.
virtual
Node
*
Ideal
(
PhaseGVN
*
phase
,
bool
can_reshape
);
// Recover original value from boxed values
Node
*
eliminate_autobox
(
PhaseGVN
*
phase
);
// Compute a new Type for this node. Basically we just do the pre-check,
// then call the virtual add() to set the type.
virtual
const
Type
*
Value
(
PhaseTransform
*
phase
)
const
;
...
...
src/share/vm/opto/parse2.cpp
浏览文件 @
b85595b7
...
...
@@ -885,6 +885,9 @@ inline void Parse::repush_if_args() {
void
Parse
::
do_ifnull
(
BoolTest
::
mask
btest
)
{
int
target_bci
=
iter
().
get_dest
();
Block
*
branch_block
=
successor_for_bci
(
target_bci
);
Block
*
next_block
=
successor_for_bci
(
iter
().
next_bci
());
float
cnt
;
float
prob
=
branch_prediction
(
cnt
,
btest
,
target_bci
);
if
(
prob
==
PROB_UNKNOWN
)
{
...
...
@@ -902,13 +905,16 @@ void Parse::do_ifnull(BoolTest::mask btest) {
uncommon_trap
(
Deoptimization
::
Reason_unreached
,
Deoptimization
::
Action_reinterpret
,
NULL
,
"cold"
);
if
(
EliminateAutoBox
)
{
// Mark the successor blocks as parsed
branch_block
->
next_path_num
();
next_block
->
next_path_num
();
}
return
;
}
// If this is a backwards branch in the bytecodes, add Safepoint
maybe_add_safepoint
(
target_bci
);
Block
*
branch_block
=
successor_for_bci
(
target_bci
);
Block
*
next_block
=
successor_for_bci
(
iter
().
next_bci
());
explicit_null_checks_inserted
++
;
Node
*
a
=
null
();
...
...
@@ -935,6 +941,10 @@ void Parse::do_ifnull(BoolTest::mask btest) {
if
(
stopped
())
{
// Path is dead?
explicit_null_checks_elided
++
;
if
(
EliminateAutoBox
)
{
// Mark the successor block as parsed
branch_block
->
next_path_num
();
}
}
else
{
// Path is live.
// Update method data
profile_taken_branch
(
target_bci
);
...
...
@@ -950,6 +960,10 @@ void Parse::do_ifnull(BoolTest::mask btest) {
if
(
stopped
())
{
// Path is dead?
explicit_null_checks_elided
++
;
if
(
EliminateAutoBox
)
{
// Mark the successor block as parsed
next_block
->
next_path_num
();
}
}
else
{
// Path is live.
// Update method data
profile_not_taken_branch
();
...
...
@@ -962,6 +976,9 @@ void Parse::do_ifnull(BoolTest::mask btest) {
void
Parse
::
do_if
(
BoolTest
::
mask
btest
,
Node
*
c
)
{
int
target_bci
=
iter
().
get_dest
();
Block
*
branch_block
=
successor_for_bci
(
target_bci
);
Block
*
next_block
=
successor_for_bci
(
iter
().
next_bci
());
float
cnt
;
float
prob
=
branch_prediction
(
cnt
,
btest
,
target_bci
);
float
untaken_prob
=
1.0
-
prob
;
...
...
@@ -980,6 +997,11 @@ void Parse::do_if(BoolTest::mask btest, Node* c) {
uncommon_trap
(
Deoptimization
::
Reason_unreached
,
Deoptimization
::
Action_reinterpret
,
NULL
,
"cold"
);
if
(
EliminateAutoBox
)
{
// Mark the successor blocks as parsed
branch_block
->
next_path_num
();
next_block
->
next_path_num
();
}
return
;
}
...
...
@@ -1018,15 +1040,17 @@ void Parse::do_if(BoolTest::mask btest, Node* c) {
untaken_branch
=
tmp
;
}
Block
*
branch_block
=
successor_for_bci
(
target_bci
);
Block
*
next_block
=
successor_for_bci
(
iter
().
next_bci
());
// Branch is taken:
{
PreserveJVMState
pjvms
(
this
);
taken_branch
=
_gvn
.
transform
(
taken_branch
);
set_control
(
taken_branch
);
if
(
!
stopped
())
{
if
(
stopped
())
{
if
(
EliminateAutoBox
)
{
// Mark the successor block as parsed
branch_block
->
next_path_num
();
}
}
else
{
// Update method data
profile_taken_branch
(
target_bci
);
adjust_map_after_if
(
taken_btest
,
c
,
prob
,
branch_block
,
next_block
);
...
...
@@ -1039,7 +1063,12 @@ void Parse::do_if(BoolTest::mask btest, Node* c) {
set_control
(
untaken_branch
);
// Branch not taken.
if
(
!
stopped
())
{
if
(
stopped
())
{
if
(
EliminateAutoBox
)
{
// Mark the successor block as parsed
next_block
->
next_path_num
();
}
}
else
{
// Update method data
profile_not_taken_branch
();
adjust_map_after_if
(
untaken_btest
,
c
,
untaken_prob
,
...
...
src/share/vm/opto/type.hpp
浏览文件 @
b85595b7
...
...
@@ -1070,6 +1070,7 @@ inline bool Type::is_floatingpoint() const {
#define LShiftXNode LShiftLNode
// For object size computation:
#define AddXNode AddLNode
#define RShiftXNode RShiftLNode
// For card marks and hashcodes
#define URShiftXNode URShiftLNode
// Opcodes
...
...
@@ -1108,6 +1109,7 @@ inline bool Type::is_floatingpoint() const {
#define LShiftXNode LShiftINode
// For object size computation:
#define AddXNode AddINode
#define RShiftXNode RShiftINode
// For card marks and hashcodes
#define URShiftXNode URShiftINode
// Opcodes
...
...
src/share/vm/runtime/arguments.cpp
浏览文件 @
b85595b7
...
...
@@ -1254,6 +1254,22 @@ void Arguments::set_bytecode_flags() {
// Aggressive optimization flags -XX:+AggressiveOpts
void
Arguments
::
set_aggressive_opts_flags
()
{
#ifdef COMPILER2
if
(
AggressiveOpts
||
!
FLAG_IS_DEFAULT
(
AutoBoxCacheMax
))
{
if
(
FLAG_IS_DEFAULT
(
EliminateAutoBox
))
{
FLAG_SET_DEFAULT
(
EliminateAutoBox
,
true
);
}
if
(
FLAG_IS_DEFAULT
(
AutoBoxCacheMax
))
{
FLAG_SET_DEFAULT
(
AutoBoxCacheMax
,
20000
);
}
// Feed the cache size setting into the JDK
char
buffer
[
1024
];
sprintf
(
buffer
,
"java.lang.Integer.IntegerCache.high=%d"
,
AutoBoxCacheMax
);
add_property
(
buffer
);
}
#endif
if
(
AggressiveOpts
)
{
NOT_WINDOWS
(
// No measured benefit on Windows
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录