Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
b17e9bbd
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看板
提交
b17e9bbd
编写于
9月 16, 2013
作者:
T
tschatzl
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
2756411f
4bbfb70f
变更
51
隐藏空白更改
内联
并排
Showing
51 changed file
with
2176 addition
and
114 deletion
+2176
-114
.hgtags
.hgtags
+2
-0
make/hotspot_version
make/hotspot_version
+1
-1
src/cpu/sparc/vm/c2_globals_sparc.hpp
src/cpu/sparc/vm/c2_globals_sparc.hpp
+1
-0
src/cpu/x86/vm/c2_globals_x86.hpp
src/cpu/x86/vm/c2_globals_x86.hpp
+1
-1
src/share/vm/ci/ciArray.cpp
src/share/vm/ci/ciArray.cpp
+79
-0
src/share/vm/ci/ciArray.hpp
src/share/vm/ci/ciArray.hpp
+18
-1
src/share/vm/ci/ciConstant.hpp
src/share/vm/ci/ciConstant.hpp
+14
-1
src/share/vm/ci/ciField.cpp
src/share/vm/ci/ciField.cpp
+15
-5
src/share/vm/ci/ciField.hpp
src/share/vm/ci/ciField.hpp
+5
-1
src/share/vm/ci/ciFlags.hpp
src/share/vm/ci/ciFlags.hpp
+1
-0
src/share/vm/ci/ciInstance.cpp
src/share/vm/ci/ciInstance.cpp
+2
-0
src/share/vm/ci/ciTypeArray.cpp
src/share/vm/ci/ciTypeArray.cpp
+6
-1
src/share/vm/classfile/classFileParser.cpp
src/share/vm/classfile/classFileParser.cpp
+6
-0
src/share/vm/classfile/classFileParser.hpp
src/share/vm/classfile/classFileParser.hpp
+14
-4
src/share/vm/classfile/vmSymbols.hpp
src/share/vm/classfile/vmSymbols.hpp
+1
-0
src/share/vm/oops/fieldInfo.hpp
src/share/vm/oops/fieldInfo.hpp
+8
-0
src/share/vm/opto/c2_globals.hpp
src/share/vm/opto/c2_globals.hpp
+4
-1
src/share/vm/opto/compile.cpp
src/share/vm/opto/compile.cpp
+16
-1
src/share/vm/opto/compile.hpp
src/share/vm/opto/compile.hpp
+11
-1
src/share/vm/opto/graphKit.cpp
src/share/vm/opto/graphKit.cpp
+13
-5
src/share/vm/opto/graphKit.hpp
src/share/vm/opto/graphKit.hpp
+3
-0
src/share/vm/opto/library_call.cpp
src/share/vm/opto/library_call.cpp
+5
-0
src/share/vm/opto/memnode.cpp
src/share/vm/opto/memnode.cpp
+75
-15
src/share/vm/opto/parse.hpp
src/share/vm/opto/parse.hpp
+1
-1
src/share/vm/opto/parse3.cpp
src/share/vm/opto/parse3.cpp
+33
-36
src/share/vm/opto/type.cpp
src/share/vm/opto/type.cpp
+71
-8
src/share/vm/opto/type.hpp
src/share/vm/opto/type.hpp
+12
-3
src/share/vm/runtime/globals.hpp
src/share/vm/runtime/globals.hpp
+3
-0
src/share/vm/runtime/interfaceSupport.hpp
src/share/vm/runtime/interfaceSupport.hpp
+0
-10
src/share/vm/utilities/accessFlags.hpp
src/share/vm/utilities/accessFlags.hpp
+3
-0
test/gc/TestVerifyDuringStartup.java
test/gc/TestVerifyDuringStartup.java
+1
-1
test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java
...estlibrary/com/oracle/java/testlibrary/JDKToolFinder.java
+36
-17
test/testlibrary/ctw/Makefile
test/testlibrary/ctw/Makefile
+73
-0
test/testlibrary/ctw/README
test/testlibrary/ctw/README
+93
-0
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java
...rary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java
+117
-0
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java
...rary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java
+81
-0
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java
...ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java
+62
-0
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java
...rary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java
+61
-0
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java
...ibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java
+175
-0
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java
+235
-0
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java
...estlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java
+149
-0
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java
+215
-0
test/testlibrary/ctw/test/Bar.java
test/testlibrary/ctw/test/Bar.java
+5
-0
test/testlibrary/ctw/test/ClassesDirTest.java
test/testlibrary/ctw/test/ClassesDirTest.java
+61
-0
test/testlibrary/ctw/test/ClassesListTest.java
test/testlibrary/ctw/test/ClassesListTest.java
+58
-0
test/testlibrary/ctw/test/CtwTest.java
test/testlibrary/ctw/test/CtwTest.java
+118
-0
test/testlibrary/ctw/test/Foo.java
test/testlibrary/ctw/test/Foo.java
+5
-0
test/testlibrary/ctw/test/JarDirTest.java
test/testlibrary/ctw/test/JarDirTest.java
+75
-0
test/testlibrary/ctw/test/JarsTest.java
test/testlibrary/ctw/test/JarsTest.java
+65
-0
test/testlibrary/ctw/test/classes.lst
test/testlibrary/ctw/test/classes.lst
+4
-0
test/testlibrary/whitebox/Makefile
test/testlibrary/whitebox/Makefile
+63
-0
未找到文件。
.hgtags
浏览文件 @
b17e9bbd
...
@@ -375,3 +375,5 @@ acac3bde66b2c22791c257a8d99611d6d08c6713 jdk8-b105
...
@@ -375,3 +375,5 @@ acac3bde66b2c22791c257a8d99611d6d08c6713 jdk8-b105
18b4798adbc42c6fa16f5ecb7d5cd3ca130754bf hs25-b48
18b4798adbc42c6fa16f5ecb7d5cd3ca130754bf hs25-b48
aed585cafc0d9655726af6d1e1081d1c94cb3b5c jdk8-b106
aed585cafc0d9655726af6d1e1081d1c94cb3b5c jdk8-b106
50794d8ac11c9579b41dec4de23b808fef9f34a1 hs25-b49
50794d8ac11c9579b41dec4de23b808fef9f34a1 hs25-b49
5b7f90aab3ad25a25b75b7b2bb18d5ae23d8231c jdk8-b107
a09fe9d1e016c285307507a5793bc4fa6215e9c9 hs25-b50
make/hotspot_version
浏览文件 @
b17e9bbd
...
@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2013
...
@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2013
HS_MAJOR_VER=25
HS_MAJOR_VER=25
HS_MINOR_VER=0
HS_MINOR_VER=0
HS_BUILD_NUMBER=5
0
HS_BUILD_NUMBER=5
1
JDK_MAJOR_VER=1
JDK_MAJOR_VER=1
JDK_MINOR_VER=8
JDK_MINOR_VER=8
...
...
src/cpu/sparc/vm/c2_globals_sparc.hpp
浏览文件 @
b17e9bbd
...
@@ -57,6 +57,7 @@ define_pd_global(intx, RegisterCostAreaRatio, 12000);
...
@@ -57,6 +57,7 @@ define_pd_global(intx, RegisterCostAreaRatio, 12000);
define_pd_global
(
bool
,
UseTLAB
,
true
);
define_pd_global
(
bool
,
UseTLAB
,
true
);
define_pd_global
(
bool
,
ResizeTLAB
,
true
);
define_pd_global
(
bool
,
ResizeTLAB
,
true
);
define_pd_global
(
intx
,
LoopUnrollLimit
,
60
);
// Design center runs on 1.3.1
define_pd_global
(
intx
,
LoopUnrollLimit
,
60
);
// Design center runs on 1.3.1
define_pd_global
(
intx
,
MinJumpTableSize
,
5
);
// Peephole and CISC spilling both break the graph, and so makes the
// Peephole and CISC spilling both break the graph, and so makes the
// scheduler sick.
// scheduler sick.
...
...
src/cpu/x86/vm/c2_globals_x86.hpp
浏览文件 @
b17e9bbd
...
@@ -30,7 +30,6 @@
...
@@ -30,7 +30,6 @@
// Sets the default values for platform dependent flags used by the server compiler.
// Sets the default values for platform dependent flags used by the server compiler.
// (see c2_globals.hpp). Alpha-sorted.
// (see c2_globals.hpp). Alpha-sorted.
define_pd_global
(
bool
,
BackgroundCompilation
,
true
);
define_pd_global
(
bool
,
BackgroundCompilation
,
true
);
define_pd_global
(
bool
,
UseTLAB
,
true
);
define_pd_global
(
bool
,
UseTLAB
,
true
);
define_pd_global
(
bool
,
ResizeTLAB
,
true
);
define_pd_global
(
bool
,
ResizeTLAB
,
true
);
...
@@ -52,6 +51,7 @@ define_pd_global(intx, OnStackReplacePercentage, 140);
...
@@ -52,6 +51,7 @@ define_pd_global(intx, OnStackReplacePercentage, 140);
define_pd_global
(
intx
,
ConditionalMoveLimit
,
3
);
define_pd_global
(
intx
,
ConditionalMoveLimit
,
3
);
define_pd_global
(
intx
,
FLOATPRESSURE
,
6
);
define_pd_global
(
intx
,
FLOATPRESSURE
,
6
);
define_pd_global
(
intx
,
FreqInlineSize
,
325
);
define_pd_global
(
intx
,
FreqInlineSize
,
325
);
define_pd_global
(
intx
,
MinJumpTableSize
,
10
);
#ifdef AMD64
#ifdef AMD64
define_pd_global
(
intx
,
INTPRESSURE
,
13
);
define_pd_global
(
intx
,
INTPRESSURE
,
13
);
define_pd_global
(
intx
,
InteriorEntryAlignment
,
16
);
define_pd_global
(
intx
,
InteriorEntryAlignment
,
16
);
...
...
src/share/vm/ci/ciArray.cpp
浏览文件 @
b17e9bbd
...
@@ -24,13 +24,92 @@
...
@@ -24,13 +24,92 @@
#include "precompiled.hpp"
#include "precompiled.hpp"
#include "ci/ciArray.hpp"
#include "ci/ciArray.hpp"
#include "ci/ciArrayKlass.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciKlass.hpp"
#include "ci/ciKlass.hpp"
#include "ci/ciUtilities.hpp"
#include "ci/ciUtilities.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/typeArrayOop.hpp"
// ciArray
// ciArray
//
//
// This class represents an arrayOop in the HotSpot virtual
// This class represents an arrayOop in the HotSpot virtual
// machine.
// machine.
static
BasicType
fixup_element_type
(
BasicType
bt
)
{
if
(
bt
==
T_ARRAY
)
return
T_OBJECT
;
if
(
bt
==
T_BOOLEAN
)
return
T_BYTE
;
return
bt
;
}
ciConstant
ciArray
::
element_value_impl
(
BasicType
elembt
,
arrayOop
ary
,
int
index
)
{
if
(
ary
==
NULL
)
return
ciConstant
();
assert
(
ary
->
is_array
(),
""
);
if
(
index
<
0
||
index
>=
ary
->
length
())
return
ciConstant
();
ArrayKlass
*
ak
=
(
ArrayKlass
*
)
ary
->
klass
();
BasicType
abt
=
ak
->
element_type
();
if
(
fixup_element_type
(
elembt
)
!=
fixup_element_type
(
abt
))
return
ciConstant
();
switch
(
elembt
)
{
case
T_ARRAY
:
case
T_OBJECT
:
{
assert
(
ary
->
is_objArray
(),
""
);
objArrayOop
objary
=
(
objArrayOop
)
ary
;
oop
elem
=
objary
->
obj_at
(
index
);
ciEnv
*
env
=
CURRENT_ENV
;
ciObject
*
box
=
env
->
get_object
(
elem
);
return
ciConstant
(
T_OBJECT
,
box
);
}
}
assert
(
ary
->
is_typeArray
(),
""
);
typeArrayOop
tary
=
(
typeArrayOop
)
ary
;
jint
value
=
0
;
switch
(
elembt
)
{
case
T_LONG
:
return
ciConstant
(
tary
->
long_at
(
index
));
case
T_FLOAT
:
return
ciConstant
(
tary
->
float_at
(
index
));
case
T_DOUBLE
:
return
ciConstant
(
tary
->
double_at
(
index
));
default:
return
ciConstant
();
case
T_BYTE
:
value
=
tary
->
byte_at
(
index
);
break
;
case
T_BOOLEAN
:
value
=
tary
->
byte_at
(
index
)
&
1
;
break
;
case
T_SHORT
:
value
=
tary
->
short_at
(
index
);
break
;
case
T_CHAR
:
value
=
tary
->
char_at
(
index
);
break
;
case
T_INT
:
value
=
tary
->
int_at
(
index
);
break
;
}
return
ciConstant
(
elembt
,
value
);
}
// ------------------------------------------------------------------
// ciArray::element_value
//
// Current value of an element.
// Returns T_ILLEGAL if there is no element at the given index.
ciConstant
ciArray
::
element_value
(
int
index
)
{
BasicType
elembt
=
element_basic_type
();
GUARDED_VM_ENTRY
(
return
element_value_impl
(
elembt
,
get_arrayOop
(),
index
);
)
}
// ------------------------------------------------------------------
// ciArray::element_value_by_offset
//
// Current value of an element at the specified offset.
// Returns T_ILLEGAL if there is no element at the given offset.
ciConstant
ciArray
::
element_value_by_offset
(
intptr_t
element_offset
)
{
BasicType
elembt
=
element_basic_type
();
intptr_t
shift
=
exact_log2
(
type2aelembytes
(
elembt
));
intptr_t
header
=
arrayOopDesc
::
base_offset_in_bytes
(
elembt
);
intptr_t
index
=
(
element_offset
-
header
)
>>
shift
;
intptr_t
offset
=
header
+
((
intptr_t
)
index
<<
shift
);
if
(
offset
!=
element_offset
||
index
!=
(
jint
)
index
)
return
ciConstant
();
return
element_value
((
jint
)
index
);
}
// ------------------------------------------------------------------
// ------------------------------------------------------------------
// ciArray::print_impl
// ciArray::print_impl
...
...
src/share/vm/ci/ciArray.hpp
浏览文件 @
b17e9bbd
...
@@ -25,6 +25,8 @@
...
@@ -25,6 +25,8 @@
#ifndef SHARE_VM_CI_CIARRAY_HPP
#ifndef SHARE_VM_CI_CIARRAY_HPP
#define SHARE_VM_CI_CIARRAY_HPP
#define SHARE_VM_CI_CIARRAY_HPP
#include "ci/ciArrayKlass.hpp"
#include "ci/ciConstant.hpp"
#include "ci/ciObject.hpp"
#include "ci/ciObject.hpp"
#include "oops/arrayOop.hpp"
#include "oops/arrayOop.hpp"
#include "oops/objArrayOop.hpp"
#include "oops/objArrayOop.hpp"
...
@@ -45,15 +47,30 @@ protected:
...
@@ -45,15 +47,30 @@ protected:
ciArray
(
ciKlass
*
klass
,
int
len
)
:
ciObject
(
klass
),
_length
(
len
)
{}
ciArray
(
ciKlass
*
klass
,
int
len
)
:
ciObject
(
klass
),
_length
(
len
)
{}
arrayOop
get_arrayOop
()
{
return
(
arrayOop
)
get_oop
();
}
arrayOop
get_arrayOop
()
const
{
return
(
arrayOop
)
get_oop
();
}
const
char
*
type_string
()
{
return
"ciArray"
;
}
const
char
*
type_string
()
{
return
"ciArray"
;
}
void
print_impl
(
outputStream
*
st
);
void
print_impl
(
outputStream
*
st
);
ciConstant
element_value_impl
(
BasicType
elembt
,
arrayOop
ary
,
int
index
);
public:
public:
int
length
()
{
return
_length
;
}
int
length
()
{
return
_length
;
}
// Convenience routines.
ciArrayKlass
*
array_type
()
{
return
klass
()
->
as_array_klass
();
}
ciType
*
element_type
()
{
return
array_type
()
->
element_type
();
}
BasicType
element_basic_type
()
{
return
element_type
()
->
basic_type
();
}
// Current value of an element.
// Returns T_ILLEGAL if there is no element at the given index.
ciConstant
element_value
(
int
index
);
// Current value of an element at the specified offset.
// Returns T_ILLEGAL if there is no element at the given offset.
ciConstant
element_value_by_offset
(
intptr_t
element_offset
);
// What kind of ciObject is this?
// What kind of ciObject is this?
bool
is_array
()
{
return
true
;
}
bool
is_array
()
{
return
true
;
}
bool
is_java_object
()
{
return
true
;
}
bool
is_java_object
()
{
return
true
;
}
...
...
src/share/vm/ci/ciConstant.hpp
浏览文件 @
b17e9bbd
...
@@ -41,7 +41,6 @@ private:
...
@@ -41,7 +41,6 @@ private:
union
{
union
{
jint
_int
;
jint
_int
;
jlong
_long
;
jlong
_long
;
jint
_long_half
[
2
];
jfloat
_float
;
jfloat
_float
;
jdouble
_double
;
jdouble
_double
;
ciObject
*
_object
;
ciObject
*
_object
;
...
@@ -111,6 +110,20 @@ public:
...
@@ -111,6 +110,20 @@ public:
return
_value
.
_object
;
return
_value
.
_object
;
}
}
bool
is_null_or_zero
()
const
{
if
(
!
is_java_primitive
(
basic_type
()))
{
return
as_object
()
->
is_null_object
();
}
else
if
(
type2size
[
basic_type
()]
==
1
)
{
// treat float bits as int, to avoid comparison with -0 and NaN
return
(
_value
.
_int
==
0
);
}
else
if
(
type2size
[
basic_type
()]
==
2
)
{
// treat double bits as long, to avoid comparison with -0 and NaN
return
(
_value
.
_long
==
0
);
}
else
{
return
false
;
}
}
// Debugging output
// Debugging output
void
print
();
void
print
();
};
};
...
...
src/share/vm/ci/ciField.cpp
浏览文件 @
b17e9bbd
...
@@ -189,12 +189,14 @@ void ciField::initialize_from(fieldDescriptor* fd) {
...
@@ -189,12 +189,14 @@ void ciField::initialize_from(fieldDescriptor* fd) {
_holder
=
CURRENT_ENV
->
get_instance_klass
(
fd
->
field_holder
());
_holder
=
CURRENT_ENV
->
get_instance_klass
(
fd
->
field_holder
());
// Check to see if the field is constant.
// Check to see if the field is constant.
if
(
_holder
->
is_initialized
()
&&
this
->
is_final
())
{
bool
is_final
=
this
->
is_final
();
bool
is_stable
=
FoldStableValues
&&
this
->
is_stable
();
if
(
_holder
->
is_initialized
()
&&
(
is_final
||
is_stable
))
{
if
(
!
this
->
is_static
())
{
if
(
!
this
->
is_static
())
{
// A field can be constant if it's a final static field or if
// A field can be constant if it's a final static field or if
// it's a final non-static field of a trusted class (classes in
// it's a final non-static field of a trusted class (classes in
// java.lang.invoke and sun.invoke packages and subpackages).
// java.lang.invoke and sun.invoke packages and subpackages).
if
(
trust_final_non_static_fields
(
_holder
))
{
if
(
is_stable
||
trust_final_non_static_fields
(
_holder
))
{
_is_constant
=
true
;
_is_constant
=
true
;
return
;
return
;
}
}
...
@@ -227,7 +229,6 @@ void ciField::initialize_from(fieldDescriptor* fd) {
...
@@ -227,7 +229,6 @@ void ciField::initialize_from(fieldDescriptor* fd) {
Handle
mirror
=
k
->
java_mirror
();
Handle
mirror
=
k
->
java_mirror
();
_is_constant
=
true
;
switch
(
type
()
->
basic_type
())
{
switch
(
type
()
->
basic_type
())
{
case
T_BYTE
:
case
T_BYTE
:
_constant_value
=
ciConstant
(
type
()
->
basic_type
(),
mirror
->
byte_field
(
_offset
));
_constant_value
=
ciConstant
(
type
()
->
basic_type
(),
mirror
->
byte_field
(
_offset
));
...
@@ -273,6 +274,12 @@ void ciField::initialize_from(fieldDescriptor* fd) {
...
@@ -273,6 +274,12 @@ void ciField::initialize_from(fieldDescriptor* fd) {
}
}
}
}
}
}
if
(
is_stable
&&
_constant_value
.
is_null_or_zero
())
{
// It is not a constant after all; treat it as uninitialized.
_is_constant
=
false
;
}
else
{
_is_constant
=
true
;
}
}
else
{
}
else
{
_is_constant
=
false
;
_is_constant
=
false
;
}
}
...
@@ -373,8 +380,11 @@ void ciField::print() {
...
@@ -373,8 +380,11 @@ void ciField::print() {
tty
->
print
(
" signature="
);
tty
->
print
(
" signature="
);
_signature
->
print_symbol
();
_signature
->
print_symbol
();
tty
->
print
(
" offset=%d type="
,
_offset
);
tty
->
print
(
" offset=%d type="
,
_offset
);
if
(
_type
!=
NULL
)
_type
->
print_name
();
if
(
_type
!=
NULL
)
else
tty
->
print
(
"(reference)"
);
_type
->
print_name
();
else
tty
->
print
(
"(reference)"
);
tty
->
print
(
" flags=%04x"
,
flags
().
as_int
());
tty
->
print
(
" is_constant=%s"
,
bool_to_str
(
_is_constant
));
tty
->
print
(
" is_constant=%s"
,
bool_to_str
(
_is_constant
));
if
(
_is_constant
&&
is_static
())
{
if
(
_is_constant
&&
is_static
())
{
tty
->
print
(
" constant_value="
);
tty
->
print
(
" constant_value="
);
...
...
src/share/vm/ci/ciField.hpp
浏览文件 @
b17e9bbd
...
@@ -139,7 +139,10 @@ public:
...
@@ -139,7 +139,10 @@ public:
// non-constant fields. These are java.lang.System.in
// non-constant fields. These are java.lang.System.in
// and java.lang.System.out. Abomination.
// and java.lang.System.out. Abomination.
//
//
// Note: the check for case 4 is not yet implemented.
// A field is also considered constant if it is marked @Stable
// and is non-null (or non-zero, if a primitive).
// For non-static fields, the null/zero check must be
// arranged by the user, as constant_value().is_null_or_zero().
bool
is_constant
()
{
return
_is_constant
;
}
bool
is_constant
()
{
return
_is_constant
;
}
// Get the constant value of this field.
// Get the constant value of this field.
...
@@ -173,6 +176,7 @@ public:
...
@@ -173,6 +176,7 @@ public:
bool
is_protected
()
{
return
flags
().
is_protected
();
}
bool
is_protected
()
{
return
flags
().
is_protected
();
}
bool
is_static
()
{
return
flags
().
is_static
();
}
bool
is_static
()
{
return
flags
().
is_static
();
}
bool
is_final
()
{
return
flags
().
is_final
();
}
bool
is_final
()
{
return
flags
().
is_final
();
}
bool
is_stable
()
{
return
flags
().
is_stable
();
}
bool
is_volatile
()
{
return
flags
().
is_volatile
();
}
bool
is_volatile
()
{
return
flags
().
is_volatile
();
}
bool
is_transient
()
{
return
flags
().
is_transient
();
}
bool
is_transient
()
{
return
flags
().
is_transient
();
}
...
...
src/share/vm/ci/ciFlags.hpp
浏览文件 @
b17e9bbd
...
@@ -59,6 +59,7 @@ public:
...
@@ -59,6 +59,7 @@ public:
bool
is_interface
()
const
{
return
(
_flags
&
JVM_ACC_INTERFACE
)
!=
0
;
}
bool
is_interface
()
const
{
return
(
_flags
&
JVM_ACC_INTERFACE
)
!=
0
;
}
bool
is_abstract
()
const
{
return
(
_flags
&
JVM_ACC_ABSTRACT
)
!=
0
;
}
bool
is_abstract
()
const
{
return
(
_flags
&
JVM_ACC_ABSTRACT
)
!=
0
;
}
bool
is_strict
()
const
{
return
(
_flags
&
JVM_ACC_STRICT
)
!=
0
;
}
bool
is_strict
()
const
{
return
(
_flags
&
JVM_ACC_STRICT
)
!=
0
;
}
bool
is_stable
()
const
{
return
(
_flags
&
JVM_ACC_FIELD_STABLE
)
!=
0
;
}
// Conversion
// Conversion
jint
as_int
()
{
return
_flags
;
}
jint
as_int
()
{
return
_flags
;
}
...
...
src/share/vm/ci/ciInstance.cpp
浏览文件 @
b17e9bbd
...
@@ -127,6 +127,8 @@ ciConstant ciInstance::field_value(ciField* field) {
...
@@ -127,6 +127,8 @@ ciConstant ciInstance::field_value(ciField* field) {
ciConstant
ciInstance
::
field_value_by_offset
(
int
field_offset
)
{
ciConstant
ciInstance
::
field_value_by_offset
(
int
field_offset
)
{
ciInstanceKlass
*
ik
=
klass
()
->
as_instance_klass
();
ciInstanceKlass
*
ik
=
klass
()
->
as_instance_klass
();
ciField
*
field
=
ik
->
get_field_by_offset
(
field_offset
,
false
);
ciField
*
field
=
ik
->
get_field_by_offset
(
field_offset
,
false
);
if
(
field
==
NULL
)
return
ciConstant
();
// T_ILLEGAL
return
field_value
(
field
);
return
field_value
(
field
);
}
}
...
...
src/share/vm/ci/ciTypeArray.cpp
浏览文件 @
b17e9bbd
...
@@ -39,5 +39,10 @@
...
@@ -39,5 +39,10 @@
jchar
ciTypeArray
::
char_at
(
int
index
)
{
jchar
ciTypeArray
::
char_at
(
int
index
)
{
VM_ENTRY_MARK
;
VM_ENTRY_MARK
;
assert
(
index
>=
0
&&
index
<
length
(),
"out of range"
);
assert
(
index
>=
0
&&
index
<
length
(),
"out of range"
);
return
get_typeArrayOop
()
->
char_at
(
index
);
jchar
c
=
get_typeArrayOop
()
->
char_at
(
index
);
#ifdef ASSERT
jchar
d
=
element_value
(
index
).
as_char
();
assert
(
c
==
d
,
""
);
#endif //ASSERT
return
c
;
}
}
src/share/vm/classfile/classFileParser.cpp
浏览文件 @
b17e9bbd
...
@@ -1774,6 +1774,10 @@ ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_d
...
@@ -1774,6 +1774,10 @@ ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_d
if
(
_location
!=
_in_method
)
break
;
// only allow for methods
if
(
_location
!=
_in_method
)
break
;
// only allow for methods
if
(
!
privileged
)
break
;
// only allow in privileged code
if
(
!
privileged
)
break
;
// only allow in privileged code
return
_method_LambdaForm_Hidden
;
return
_method_LambdaForm_Hidden
;
case
vmSymbols
::
VM_SYMBOL_ENUM_NAME
(
sun_invoke_Stable_signature
):
if
(
_location
!=
_in_field
)
break
;
// only allow for fields
if
(
!
privileged
)
break
;
// only allow in privileged code
return
_field_Stable
;
case
vmSymbols
::
VM_SYMBOL_ENUM_NAME
(
sun_misc_Contended_signature
):
case
vmSymbols
::
VM_SYMBOL_ENUM_NAME
(
sun_misc_Contended_signature
):
if
(
_location
!=
_in_field
&&
_location
!=
_in_class
)
break
;
// only allow for fields and classes
if
(
_location
!=
_in_field
&&
_location
!=
_in_class
)
break
;
// only allow for fields and classes
if
(
!
EnableContended
||
(
RestrictContended
&&
!
privileged
))
break
;
// honor privileges
if
(
!
EnableContended
||
(
RestrictContended
&&
!
privileged
))
break
;
// honor privileges
...
@@ -1786,6 +1790,8 @@ ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_d
...
@@ -1786,6 +1790,8 @@ ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_d
void
ClassFileParser
::
FieldAnnotationCollector
::
apply_to
(
FieldInfo
*
f
)
{
void
ClassFileParser
::
FieldAnnotationCollector
::
apply_to
(
FieldInfo
*
f
)
{
if
(
is_contended
())
if
(
is_contended
())
f
->
set_contended_group
(
contended_group
());
f
->
set_contended_group
(
contended_group
());
if
(
is_stable
())
f
->
set_stable
(
true
);
}
}
ClassFileParser
::
FieldAnnotationCollector
::~
FieldAnnotationCollector
()
{
ClassFileParser
::
FieldAnnotationCollector
::~
FieldAnnotationCollector
()
{
...
...
src/share/vm/classfile/classFileParser.hpp
浏览文件 @
b17e9bbd
...
@@ -125,6 +125,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
...
@@ -125,6 +125,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
_method_LambdaForm_Compiled
,
_method_LambdaForm_Compiled
,
_method_LambdaForm_Hidden
,
_method_LambdaForm_Hidden
,
_sun_misc_Contended
,
_sun_misc_Contended
,
_field_Stable
,
_annotation_LIMIT
_annotation_LIMIT
};
};
const
Location
_location
;
const
Location
_location
;
...
@@ -143,14 +144,23 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
...
@@ -143,14 +144,23 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
assert
((
int
)
id
>=
0
&&
(
int
)
id
<
(
int
)
_annotation_LIMIT
,
"oob"
);
assert
((
int
)
id
>=
0
&&
(
int
)
id
<
(
int
)
_annotation_LIMIT
,
"oob"
);
_annotations_present
|=
nth_bit
((
int
)
id
);
_annotations_present
|=
nth_bit
((
int
)
id
);
}
}
void
remove_annotation
(
ID
id
)
{
assert
((
int
)
id
>=
0
&&
(
int
)
id
<
(
int
)
_annotation_LIMIT
,
"oob"
);
_annotations_present
&=
~
nth_bit
((
int
)
id
);
}
// Report if the annotation is present.
// Report if the annotation is present.
bool
has_any_annotations
()
{
return
_annotations_present
!=
0
;
}
bool
has_any_annotations
()
const
{
return
_annotations_present
!=
0
;
}
bool
has_annotation
(
ID
id
)
{
return
(
nth_bit
((
int
)
id
)
&
_annotations_present
)
!=
0
;
}
bool
has_annotation
(
ID
id
)
const
{
return
(
nth_bit
((
int
)
id
)
&
_annotations_present
)
!=
0
;
}
void
set_contended_group
(
u2
group
)
{
_contended_group
=
group
;
}
void
set_contended_group
(
u2
group
)
{
_contended_group
=
group
;
}
u2
contended_group
()
{
return
_contended_group
;
}
u2
contended_group
()
const
{
return
_contended_group
;
}
bool
is_contended
()
const
{
return
has_annotation
(
_sun_misc_Contended
);
}
bool
is_contended
()
{
return
has_annotation
(
_sun_misc_Contended
);
}
void
set_stable
(
bool
stable
)
{
set_annotation
(
_field_Stable
);
}
bool
is_stable
()
const
{
return
has_annotation
(
_field_Stable
);
}
};
};
// This class also doubles as a holder for metadata cleanup.
// This class also doubles as a holder for metadata cleanup.
...
...
src/share/vm/classfile/vmSymbols.hpp
浏览文件 @
b17e9bbd
...
@@ -270,6 +270,7 @@
...
@@ -270,6 +270,7 @@
template(java_lang_invoke_LambdaForm, "java/lang/invoke/LambdaForm") \
template(java_lang_invoke_LambdaForm, "java/lang/invoke/LambdaForm") \
template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \
template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \
template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \
template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \
template(sun_invoke_Stable_signature, "Lsun/invoke/Stable;") \
template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \
template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \
template(java_lang_invoke_MagicLambdaImpl, "java/lang/invoke/MagicLambdaImpl") \
template(java_lang_invoke_MagicLambdaImpl, "java/lang/invoke/MagicLambdaImpl") \
...
...
src/share/vm/oops/fieldInfo.hpp
浏览文件 @
b17e9bbd
...
@@ -240,6 +240,14 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC {
...
@@ -240,6 +240,14 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC {
return
(
access_flags
()
&
JVM_ACC_FIELD_INTERNAL
)
!=
0
;
return
(
access_flags
()
&
JVM_ACC_FIELD_INTERNAL
)
!=
0
;
}
}
bool
is_stable
()
const
{
return
(
access_flags
()
&
JVM_ACC_FIELD_STABLE
)
!=
0
;
}
void
set_stable
(
bool
z
)
{
if
(
z
)
_shorts
[
access_flags_offset
]
|=
JVM_ACC_FIELD_STABLE
;
else
_shorts
[
access_flags_offset
]
&=
~
JVM_ACC_FIELD_STABLE
;
}
Symbol
*
lookup_symbol
(
int
symbol_index
)
const
{
Symbol
*
lookup_symbol
(
int
symbol_index
)
const
{
assert
(
is_internal
(),
"only internal fields"
);
assert
(
is_internal
(),
"only internal fields"
);
return
vmSymbols
::
symbol_at
((
vmSymbols
::
SID
)
symbol_index
);
return
vmSymbols
::
symbol_at
((
vmSymbols
::
SID
)
symbol_index
);
...
...
src/share/vm/opto/c2_globals.hpp
浏览文件 @
b17e9bbd
...
@@ -421,7 +421,7 @@
...
@@ -421,7 +421,7 @@
product(bool, UseDivMod, true, \
product(bool, UseDivMod, true, \
"Use combined DivMod instruction if available") \
"Use combined DivMod instruction if available") \
\
\
product
(intx, MinJumpTableSize, 18,
\
product
_pd(intx, MinJumpTableSize,
\
"Minimum number of targets in a generated jump table") \
"Minimum number of targets in a generated jump table") \
\
\
product(intx, MaxJumpTableSize, 65000, \
product(intx, MaxJumpTableSize, 65000, \
...
@@ -448,6 +448,9 @@
...
@@ -448,6 +448,9 @@
product(bool, EliminateAutoBox, true, \
product(bool, EliminateAutoBox, true, \
"Control optimizations for autobox elimination") \
"Control optimizations for autobox elimination") \
\
\
experimental(bool, UseImplicitStableValues, false, \
"Mark well-known stable fields as such (e.g. String.value)") \
\
product(intx, AutoBoxCacheMax, 128, \
product(intx, AutoBoxCacheMax, 128, \
"Sets max value cached by the java.lang.Integer autobox cache") \
"Sets max value cached by the java.lang.Integer autobox cache") \
\
\
...
...
src/share/vm/opto/compile.cpp
浏览文件 @
b17e9bbd
...
@@ -1297,6 +1297,10 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
...
@@ -1297,6 +1297,10 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const {
// Array pointers need some flattening
// Array pointers need some flattening
const
TypeAryPtr
*
ta
=
tj
->
isa_aryptr
();
const
TypeAryPtr
*
ta
=
tj
->
isa_aryptr
();
if
(
ta
&&
ta
->
is_stable
())
{
// Erase stability property for alias analysis.
tj
=
ta
=
ta
->
cast_to_stable
(
false
);
}
if
(
ta
&&
is_known_inst
)
{
if
(
ta
&&
is_known_inst
)
{
if
(
offset
!=
Type
::
OffsetBot
&&
if
(
offset
!=
Type
::
OffsetBot
&&
offset
>
arrayOopDesc
::
length_offset_in_bytes
()
)
{
offset
>
arrayOopDesc
::
length_offset_in_bytes
()
)
{
...
@@ -1497,6 +1501,7 @@ void Compile::AliasType::Init(int i, const TypePtr* at) {
...
@@ -1497,6 +1501,7 @@ void Compile::AliasType::Init(int i, const TypePtr* at) {
_index
=
i
;
_index
=
i
;
_adr_type
=
at
;
_adr_type
=
at
;
_field
=
NULL
;
_field
=
NULL
;
_element
=
NULL
;
_is_rewritable
=
true
;
// default
_is_rewritable
=
true
;
// default
const
TypeOopPtr
*
atoop
=
(
at
!=
NULL
)
?
at
->
isa_oopptr
()
:
NULL
;
const
TypeOopPtr
*
atoop
=
(
at
!=
NULL
)
?
at
->
isa_oopptr
()
:
NULL
;
if
(
atoop
!=
NULL
&&
atoop
->
is_known_instance
())
{
if
(
atoop
!=
NULL
&&
atoop
->
is_known_instance
())
{
...
@@ -1615,6 +1620,16 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr
...
@@ -1615,6 +1620,16 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr
&&
flat
->
is_instptr
()
->
klass
()
==
env
()
->
Class_klass
())
&&
flat
->
is_instptr
()
->
klass
()
==
env
()
->
Class_klass
())
alias_type
(
idx
)
->
set_rewritable
(
false
);
alias_type
(
idx
)
->
set_rewritable
(
false
);
}
}
if
(
flat
->
isa_aryptr
())
{
#ifdef ASSERT
const
int
header_size_min
=
arrayOopDesc
::
base_offset_in_bytes
(
T_BYTE
);
// (T_BYTE has the weakest alignment and size restrictions...)
assert
(
flat
->
offset
()
<
header_size_min
,
"array body reference must be OffsetBot"
);
#endif
if
(
flat
->
offset
()
==
TypePtr
::
OffsetBot
)
{
alias_type
(
idx
)
->
set_element
(
flat
->
is_aryptr
()
->
elem
());
}
}
if
(
flat
->
isa_klassptr
())
{
if
(
flat
->
isa_klassptr
())
{
if
(
flat
->
offset
()
==
in_bytes
(
Klass
::
super_check_offset_offset
()))
if
(
flat
->
offset
()
==
in_bytes
(
Klass
::
super_check_offset_offset
()))
alias_type
(
idx
)
->
set_rewritable
(
false
);
alias_type
(
idx
)
->
set_rewritable
(
false
);
...
@@ -1677,7 +1692,7 @@ Compile::AliasType* Compile::alias_type(ciField* field) {
...
@@ -1677,7 +1692,7 @@ Compile::AliasType* Compile::alias_type(ciField* field) {
else
else
t
=
TypeOopPtr
::
make_from_klass_raw
(
field
->
holder
());
t
=
TypeOopPtr
::
make_from_klass_raw
(
field
->
holder
());
AliasType
*
atp
=
alias_type
(
t
->
add_offset
(
field
->
offset_in_bytes
()),
field
);
AliasType
*
atp
=
alias_type
(
t
->
add_offset
(
field
->
offset_in_bytes
()),
field
);
assert
(
field
->
is_final
(
)
==
!
atp
->
is_rewritable
(),
"must get the rewritable bits correct"
);
assert
(
(
field
->
is_final
()
||
field
->
is_stable
()
)
==
!
atp
->
is_rewritable
(),
"must get the rewritable bits correct"
);
return
atp
;
return
atp
;
}
}
...
...
src/share/vm/opto/compile.hpp
浏览文件 @
b17e9bbd
...
@@ -72,6 +72,7 @@ class Scope;
...
@@ -72,6 +72,7 @@ class Scope;
class
StartNode
;
class
StartNode
;
class
SafePointNode
;
class
SafePointNode
;
class
JVMState
;
class
JVMState
;
class
Type
;
class
TypeData
;
class
TypeData
;
class
TypePtr
;
class
TypePtr
;
class
TypeOopPtr
;
class
TypeOopPtr
;
...
@@ -119,6 +120,7 @@ class Compile : public Phase {
...
@@ -119,6 +120,7 @@ class Compile : public Phase {
int
_index
;
// unique index, used with MergeMemNode
int
_index
;
// unique index, used with MergeMemNode
const
TypePtr
*
_adr_type
;
// normalized address type
const
TypePtr
*
_adr_type
;
// normalized address type
ciField
*
_field
;
// relevant instance field, or null if none
ciField
*
_field
;
// relevant instance field, or null if none
const
Type
*
_element
;
// relevant array element type, or null if none
bool
_is_rewritable
;
// false if the memory is write-once only
bool
_is_rewritable
;
// false if the memory is write-once only
int
_general_index
;
// if this is type is an instance, the general
int
_general_index
;
// if this is type is an instance, the general
// type that this is an instance of
// type that this is an instance of
...
@@ -129,6 +131,7 @@ class Compile : public Phase {
...
@@ -129,6 +131,7 @@ class Compile : public Phase {
int
index
()
const
{
return
_index
;
}
int
index
()
const
{
return
_index
;
}
const
TypePtr
*
adr_type
()
const
{
return
_adr_type
;
}
const
TypePtr
*
adr_type
()
const
{
return
_adr_type
;
}
ciField
*
field
()
const
{
return
_field
;
}
ciField
*
field
()
const
{
return
_field
;
}
const
Type
*
element
()
const
{
return
_element
;
}
bool
is_rewritable
()
const
{
return
_is_rewritable
;
}
bool
is_rewritable
()
const
{
return
_is_rewritable
;
}
bool
is_volatile
()
const
{
return
(
_field
?
_field
->
is_volatile
()
:
false
);
}
bool
is_volatile
()
const
{
return
(
_field
?
_field
->
is_volatile
()
:
false
);
}
int
general_index
()
const
{
return
(
_general_index
!=
0
)
?
_general_index
:
_index
;
}
int
general_index
()
const
{
return
(
_general_index
!=
0
)
?
_general_index
:
_index
;
}
...
@@ -137,7 +140,14 @@ class Compile : public Phase {
...
@@ -137,7 +140,14 @@ class Compile : public Phase {
void
set_field
(
ciField
*
f
)
{
void
set_field
(
ciField
*
f
)
{
assert
(
!
_field
,
""
);
assert
(
!
_field
,
""
);
_field
=
f
;
_field
=
f
;
if
(
f
->
is_final
())
_is_rewritable
=
false
;
if
(
f
->
is_final
()
||
f
->
is_stable
())
{
// In the case of @Stable, multiple writes are possible but may be assumed to be no-ops.
_is_rewritable
=
false
;
}
}
void
set_element
(
const
Type
*
e
)
{
assert
(
_element
==
NULL
,
""
);
_element
=
e
;
}
}
void
print_on
(
outputStream
*
st
)
PRODUCT_RETURN
;
void
print_on
(
outputStream
*
st
)
PRODUCT_RETURN
;
...
...
src/share/vm/opto/graphKit.cpp
浏览文件 @
b17e9bbd
...
@@ -3825,8 +3825,13 @@ Node* GraphKit::load_String_value(Node* ctrl, Node* str) {
...
@@ -3825,8 +3825,13 @@ Node* GraphKit::load_String_value(Node* ctrl, Node* str) {
TypeAry
::
make
(
TypeInt
::
CHAR
,
TypeInt
::
POS
),
TypeAry
::
make
(
TypeInt
::
CHAR
,
TypeInt
::
POS
),
ciTypeArrayKlass
::
make
(
T_CHAR
),
true
,
0
);
ciTypeArrayKlass
::
make
(
T_CHAR
),
true
,
0
);
int
value_field_idx
=
C
->
get_alias_index
(
value_field_type
);
int
value_field_idx
=
C
->
get_alias_index
(
value_field_type
);
return
make_load
(
ctrl
,
basic_plus_adr
(
str
,
str
,
value_offset
),
Node
*
load
=
make_load
(
ctrl
,
basic_plus_adr
(
str
,
str
,
value_offset
),
value_type
,
T_OBJECT
,
value_field_idx
);
value_type
,
T_OBJECT
,
value_field_idx
);
// String.value field is known to be @Stable.
if
(
UseImplicitStableValues
)
{
load
=
cast_array_to_stable
(
load
,
value_type
);
}
return
load
;
}
}
void
GraphKit
::
store_String_offset
(
Node
*
ctrl
,
Node
*
str
,
Node
*
value
)
{
void
GraphKit
::
store_String_offset
(
Node
*
ctrl
,
Node
*
str
,
Node
*
value
)
{
...
@@ -3844,9 +3849,6 @@ void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
...
@@ -3844,9 +3849,6 @@ void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
const
TypeInstPtr
*
string_type
=
TypeInstPtr
::
make
(
TypePtr
::
NotNull
,
C
->
env
()
->
String_klass
(),
const
TypeInstPtr
*
string_type
=
TypeInstPtr
::
make
(
TypePtr
::
NotNull
,
C
->
env
()
->
String_klass
(),
false
,
NULL
,
0
);
false
,
NULL
,
0
);
const
TypePtr
*
value_field_type
=
string_type
->
add_offset
(
value_offset
);
const
TypePtr
*
value_field_type
=
string_type
->
add_offset
(
value_offset
);
const
TypeAryPtr
*
value_type
=
TypeAryPtr
::
make
(
TypePtr
::
NotNull
,
TypeAry
::
make
(
TypeInt
::
CHAR
,
TypeInt
::
POS
),
ciTypeArrayKlass
::
make
(
T_CHAR
),
true
,
0
);
int
value_field_idx
=
C
->
get_alias_index
(
value_field_type
);
int
value_field_idx
=
C
->
get_alias_index
(
value_field_type
);
store_to_memory
(
ctrl
,
basic_plus_adr
(
str
,
value_offset
),
store_to_memory
(
ctrl
,
basic_plus_adr
(
str
,
value_offset
),
value
,
T_OBJECT
,
value_field_idx
);
value
,
T_OBJECT
,
value_field_idx
);
...
@@ -3861,3 +3863,9 @@ void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) {
...
@@ -3861,3 +3863,9 @@ void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) {
store_to_memory
(
ctrl
,
basic_plus_adr
(
str
,
count_offset
),
store_to_memory
(
ctrl
,
basic_plus_adr
(
str
,
count_offset
),
value
,
T_INT
,
count_field_idx
);
value
,
T_INT
,
count_field_idx
);
}
}
Node
*
GraphKit
::
cast_array_to_stable
(
Node
*
ary
,
const
TypeAryPtr
*
ary_type
)
{
// Reify the property as a CastPP node in Ideal graph to comply with monotonicity
// assumption of CCP analysis.
return
_gvn
.
transform
(
new
(
C
)
CastPPNode
(
ary
,
ary_type
->
cast_to_stable
(
true
)));
}
src/share/vm/opto/graphKit.hpp
浏览文件 @
b17e9bbd
...
@@ -836,6 +836,9 @@ class GraphKit : public Phase {
...
@@ -836,6 +836,9 @@ class GraphKit : public Phase {
// Insert a loop predicate into the graph
// Insert a loop predicate into the graph
void
add_predicate
(
int
nargs
=
0
);
void
add_predicate
(
int
nargs
=
0
);
void
add_predicate_impl
(
Deoptimization
::
DeoptReason
reason
,
int
nargs
);
void
add_predicate_impl
(
Deoptimization
::
DeoptReason
reason
,
int
nargs
);
// Produce new array node of stable type
Node
*
cast_array_to_stable
(
Node
*
ary
,
const
TypeAryPtr
*
ary_type
);
};
};
// Helper class to support building of control flow branches. Upon
// Helper class to support building of control flow branches. Upon
...
...
src/share/vm/opto/library_call.cpp
浏览文件 @
b17e9bbd
...
@@ -1280,6 +1280,11 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar
...
@@ -1280,6 +1280,11 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar
const
TypeAry
*
target_array_type
=
TypeAry
::
make
(
TypeInt
::
CHAR
,
TypeInt
::
make
(
0
,
target_length
,
Type
::
WidenMin
));
const
TypeAry
*
target_array_type
=
TypeAry
::
make
(
TypeInt
::
CHAR
,
TypeInt
::
make
(
0
,
target_length
,
Type
::
WidenMin
));
const
TypeAryPtr
*
target_type
=
TypeAryPtr
::
make
(
TypePtr
::
BotPTR
,
target_array_type
,
target_array
->
klass
(),
true
,
Type
::
OffsetBot
);
const
TypeAryPtr
*
target_type
=
TypeAryPtr
::
make
(
TypePtr
::
BotPTR
,
target_array_type
,
target_array
->
klass
(),
true
,
Type
::
OffsetBot
);
// String.value field is known to be @Stable.
if
(
UseImplicitStableValues
)
{
target
=
cast_array_to_stable
(
target
,
target_type
);
}
IdealKit
kit
(
this
,
false
,
true
);
IdealKit
kit
(
this
,
false
,
true
);
#define __ kit.
#define __ kit.
Node
*
zero
=
__
ConI
(
0
);
Node
*
zero
=
__
ConI
(
0
);
...
...
src/share/vm/opto/memnode.cpp
浏览文件 @
b17e9bbd
...
@@ -962,6 +962,19 @@ uint LoadNode::hash() const {
...
@@ -962,6 +962,19 @@ uint LoadNode::hash() const {
return
(
uintptr_t
)
in
(
Control
)
+
(
uintptr_t
)
in
(
Memory
)
+
(
uintptr_t
)
in
(
Address
);
return
(
uintptr_t
)
in
(
Control
)
+
(
uintptr_t
)
in
(
Memory
)
+
(
uintptr_t
)
in
(
Address
);
}
}
static
bool
skip_through_membars
(
Compile
::
AliasType
*
atp
,
const
TypeInstPtr
*
tp
,
bool
eliminate_boxing
)
{
if
((
atp
!=
NULL
)
&&
(
atp
->
index
()
>=
Compile
::
AliasIdxRaw
))
{
bool
non_volatile
=
(
atp
->
field
()
!=
NULL
)
&&
!
atp
->
field
()
->
is_volatile
();
bool
is_stable_ary
=
FoldStableValues
&&
(
tp
!=
NULL
)
&&
(
tp
->
isa_aryptr
()
!=
NULL
)
&&
tp
->
isa_aryptr
()
->
is_stable
();
return
(
eliminate_boxing
&&
non_volatile
)
||
is_stable_ary
;
}
return
false
;
}
//---------------------------can_see_stored_value------------------------------
//---------------------------can_see_stored_value------------------------------
// This routine exists to make sure this set of tests is done the same
// This routine exists to make sure this set of tests is done the same
// everywhere. We need to make a coordinated change: first LoadNode::Ideal
// everywhere. We need to make a coordinated change: first LoadNode::Ideal
...
@@ -976,11 +989,9 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const {
...
@@ -976,11 +989,9 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const {
const
TypeInstPtr
*
tp
=
phase
->
type
(
ld_adr
)
->
isa_instptr
();
const
TypeInstPtr
*
tp
=
phase
->
type
(
ld_adr
)
->
isa_instptr
();
Compile
::
AliasType
*
atp
=
(
tp
!=
NULL
)
?
phase
->
C
->
alias_type
(
tp
)
:
NULL
;
Compile
::
AliasType
*
atp
=
(
tp
!=
NULL
)
?
phase
->
C
->
alias_type
(
tp
)
:
NULL
;
// This is more general than load from boxing objects.
// This is more general than load from boxing objects.
if
(
phase
->
C
->
eliminate_boxing
()
&&
(
atp
!=
NULL
)
&&
if
(
skip_through_membars
(
atp
,
tp
,
phase
->
C
->
eliminate_boxing
()))
{
(
atp
->
index
()
>=
Compile
::
AliasIdxRaw
)
&&
(
atp
->
field
()
!=
NULL
)
&&
!
atp
->
field
()
->
is_volatile
())
{
uint
alias_idx
=
atp
->
index
();
uint
alias_idx
=
atp
->
index
();
bool
final
=
atp
->
field
()
->
is_final
();
bool
final
=
!
atp
->
is_rewritable
();
Node
*
result
=
NULL
;
Node
*
result
=
NULL
;
Node
*
current
=
st
;
Node
*
current
=
st
;
// Skip through chains of MemBarNodes checking the MergeMems for
// Skip through chains of MemBarNodes checking the MergeMems for
...
@@ -1015,7 +1026,6 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const {
...
@@ -1015,7 +1026,6 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const {
}
}
}
}
// Loop around twice in the case Load -> Initialize -> Store.
// Loop around twice in the case Load -> Initialize -> Store.
// (See PhaseIterGVN::add_users_to_worklist, which knows about this case.)
// (See PhaseIterGVN::add_users_to_worklist, which knows about this case.)
for
(
int
trip
=
0
;
trip
<=
1
;
trip
++
)
{
for
(
int
trip
=
0
;
trip
<=
1
;
trip
++
)
{
...
@@ -1577,6 +1587,40 @@ LoadNode::load_array_final_field(const TypeKlassPtr *tkls,
...
@@ -1577,6 +1587,40 @@ LoadNode::load_array_final_field(const TypeKlassPtr *tkls,
return
NULL
;
return
NULL
;
}
}
// Try to constant-fold a stable array element.
static
const
Type
*
fold_stable_ary_elem
(
const
TypeAryPtr
*
ary
,
int
off
,
BasicType
loadbt
)
{
assert
(
ary
->
is_stable
(),
"array should be stable"
);
if
(
ary
->
const_oop
()
!=
NULL
)
{
// Decode the results of GraphKit::array_element_address.
ciArray
*
aobj
=
ary
->
const_oop
()
->
as_array
();
ciConstant
con
=
aobj
->
element_value_by_offset
(
off
);
if
(
con
.
basic_type
()
!=
T_ILLEGAL
&&
!
con
.
is_null_or_zero
())
{
const
Type
*
con_type
=
Type
::
make_from_constant
(
con
);
if
(
con_type
!=
NULL
)
{
if
(
con_type
->
isa_aryptr
())
{
// Join with the array element type, in case it is also stable.
int
dim
=
ary
->
stable_dimension
();
con_type
=
con_type
->
is_aryptr
()
->
cast_to_stable
(
true
,
dim
-
1
);
}
if
(
loadbt
==
T_NARROWOOP
&&
con_type
->
isa_oopptr
())
{
con_type
=
con_type
->
make_narrowoop
();
}
#ifndef PRODUCT
if
(
TraceIterativeGVN
)
{
tty
->
print
(
"FoldStableValues: array element [off=%d]: con_type="
,
off
);
con_type
->
dump
();
tty
->
cr
();
}
#endif //PRODUCT
return
con_type
;
}
}
}
return
NULL
;
}
//------------------------------Value-----------------------------------------
//------------------------------Value-----------------------------------------
const
Type
*
LoadNode
::
Value
(
PhaseTransform
*
phase
)
const
{
const
Type
*
LoadNode
::
Value
(
PhaseTransform
*
phase
)
const
{
// Either input is TOP ==> the result is TOP
// Either input is TOP ==> the result is TOP
...
@@ -1591,8 +1635,31 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const {
...
@@ -1591,8 +1635,31 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const {
Compile
*
C
=
phase
->
C
;
Compile
*
C
=
phase
->
C
;
// Try to guess loaded type from pointer type
// Try to guess loaded type from pointer type
if
(
tp
->
base
()
==
Type
::
AryPtr
)
{
if
(
tp
->
isa_aryptr
())
{
const
Type
*
t
=
tp
->
is_aryptr
()
->
elem
();
const
TypeAryPtr
*
ary
=
tp
->
is_aryptr
();
const
Type
*
t
=
ary
->
elem
();
// Determine whether the reference is beyond the header or not, by comparing
// the offset against the offset of the start of the array's data.
// Different array types begin at slightly different offsets (12 vs. 16).
// We choose T_BYTE as an example base type that is least restrictive
// as to alignment, which will therefore produce the smallest
// possible base offset.
const
int
min_base_off
=
arrayOopDesc
::
base_offset_in_bytes
(
T_BYTE
);
const
bool
off_beyond_header
=
((
uint
)
off
>=
(
uint
)
min_base_off
);
// Try to constant-fold a stable array element.
if
(
FoldStableValues
&&
ary
->
is_stable
())
{
// Make sure the reference is not into the header
if
(
off_beyond_header
&&
off
!=
Type
::
OffsetBot
)
{
assert
(
adr
->
is_AddP
()
&&
adr
->
in
(
AddPNode
::
Offset
)
->
is_Con
(),
"offset is a constant"
);
const
Type
*
con_type
=
fold_stable_ary_elem
(
ary
,
off
,
memory_type
());
if
(
con_type
!=
NULL
)
{
return
con_type
;
}
}
}
// Don't do this for integer types. There is only potential profit if
// Don't do this for integer types. There is only potential profit if
// the element type t is lower than _type; that is, for int types, if _type is
// the element type t is lower than _type; that is, for int types, if _type is
// more restrictive than t. This only happens here if one is short and the other
// more restrictive than t. This only happens here if one is short and the other
...
@@ -1613,14 +1680,7 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const {
...
@@ -1613,14 +1680,7 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const {
&&
Opcode
()
!=
Op_LoadKlass
&&
Opcode
()
!=
Op_LoadNKlass
)
{
&&
Opcode
()
!=
Op_LoadKlass
&&
Opcode
()
!=
Op_LoadNKlass
)
{
// t might actually be lower than _type, if _type is a unique
// t might actually be lower than _type, if _type is a unique
// concrete subclass of abstract class t.
// concrete subclass of abstract class t.
// Make sure the reference is not into the header, by comparing
if
(
off_beyond_header
)
{
// is the offset beyond the header?
// the offset against the offset of the start of the array's data.
// Different array types begin at slightly different offsets (12 vs. 16).
// We choose T_BYTE as an example base type that is least restrictive
// as to alignment, which will therefore produce the smallest
// possible base offset.
const
int
min_base_off
=
arrayOopDesc
::
base_offset_in_bytes
(
T_BYTE
);
if
((
uint
)
off
>=
(
uint
)
min_base_off
)
{
// is the offset beyond the header?
const
Type
*
jt
=
t
->
join
(
_type
);
const
Type
*
jt
=
t
->
join
(
_type
);
// In any case, do not allow the join, per se, to empty out the type.
// In any case, do not allow the join, per se, to empty out the type.
if
(
jt
->
empty
()
&&
!
t
->
empty
())
{
if
(
jt
->
empty
()
&&
!
t
->
empty
())
{
...
...
src/share/vm/opto/parse.hpp
浏览文件 @
b17e9bbd
...
@@ -518,7 +518,7 @@ class Parse : public GraphKit {
...
@@ -518,7 +518,7 @@ class Parse : public GraphKit {
// loading from a constant field or the constant pool
// loading from a constant field or the constant pool
// returns false if push failed (non-perm field constants only, not ldcs)
// returns false if push failed (non-perm field constants only, not ldcs)
bool
push_constant
(
ciConstant
con
,
bool
require_constant
=
false
,
bool
is_autobox_cache
=
false
);
bool
push_constant
(
ciConstant
con
,
bool
require_constant
=
false
,
bool
is_autobox_cache
=
false
,
const
Type
*
basic_type
=
NULL
);
// implementation of object creation bytecodes
// implementation of object creation bytecodes
void
emit_guard_for_new
(
ciInstanceKlass
*
klass
);
void
emit_guard_for_new
(
ciInstanceKlass
*
klass
);
...
...
src/share/vm/opto/parse3.cpp
浏览文件 @
b17e9bbd
...
@@ -147,7 +147,15 @@ void Parse::do_field_access(bool is_get, bool is_field) {
...
@@ -147,7 +147,15 @@ void Parse::do_field_access(bool is_get, bool is_field) {
void
Parse
::
do_get_xxx
(
Node
*
obj
,
ciField
*
field
,
bool
is_field
)
{
void
Parse
::
do_get_xxx
(
Node
*
obj
,
ciField
*
field
,
bool
is_field
)
{
// Does this field have a constant value? If so, just push the value.
// Does this field have a constant value? If so, just push the value.
if
(
field
->
is_constant
())
{
if
(
field
->
is_constant
())
{
// final field
// final or stable field
const
Type
*
stable_type
=
NULL
;
if
(
FoldStableValues
&&
field
->
is_stable
())
{
stable_type
=
Type
::
get_const_type
(
field
->
type
());
if
(
field
->
type
()
->
is_array_klass
())
{
int
stable_dimension
=
field
->
type
()
->
as_array_klass
()
->
dimension
();
stable_type
=
stable_type
->
is_aryptr
()
->
cast_to_stable
(
true
,
stable_dimension
);
}
}
if
(
field
->
is_static
())
{
if
(
field
->
is_static
())
{
// final static field
// final static field
if
(
C
->
eliminate_boxing
())
{
if
(
C
->
eliminate_boxing
())
{
...
@@ -167,11 +175,10 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
...
@@ -167,11 +175,10 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
}
}
}
}
}
}
if
(
push_constant
(
field
->
constant_value
()))
if
(
push_constant
(
field
->
constant_value
()
,
false
,
false
,
stable_type
))
return
;
return
;
}
}
else
{
else
{
// final or stable non-static field
// final non-static field
// Treat final non-static fields of trusted classes (classes in
// Treat final non-static fields of trusted classes (classes in
// java.lang.invoke and sun.invoke packages and subpackages) as
// java.lang.invoke and sun.invoke packages and subpackages) as
// compile time constants.
// compile time constants.
...
@@ -179,8 +186,12 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
...
@@ -179,8 +186,12 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) {
const
TypeOopPtr
*
oop_ptr
=
obj
->
bottom_type
()
->
isa_oopptr
();
const
TypeOopPtr
*
oop_ptr
=
obj
->
bottom_type
()
->
isa_oopptr
();
ciObject
*
constant_oop
=
oop_ptr
->
const_oop
();
ciObject
*
constant_oop
=
oop_ptr
->
const_oop
();
ciConstant
constant
=
field
->
constant_value_of
(
constant_oop
);
ciConstant
constant
=
field
->
constant_value_of
(
constant_oop
);
if
(
push_constant
(
constant
,
true
))
if
(
FoldStableValues
&&
field
->
is_stable
()
&&
constant
.
is_null_or_zero
())
{
return
;
// fall through to field load; the field is not yet initialized
}
else
{
if
(
push_constant
(
constant
,
true
,
false
,
stable_type
))
return
;
}
}
}
}
}
}
}
...
@@ -301,7 +312,8 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) {
...
@@ -301,7 +312,8 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) {
// Note the presence of writes to final non-static fields, so that we
// Note the presence of writes to final non-static fields, so that we
// can insert a memory barrier later on to keep the writes from floating
// can insert a memory barrier later on to keep the writes from floating
// out of the constructor.
// out of the constructor.
if
(
is_field
&&
field
->
is_final
())
{
// Any method can write a @Stable field; insert memory barriers after those also.
if
(
is_field
&&
(
field
->
is_final
()
||
field
->
is_stable
()))
{
set_wrote_final
(
true
);
set_wrote_final
(
true
);
// Preserve allocation ptr to create precedent edge to it in membar
// Preserve allocation ptr to create precedent edge to it in membar
// generated on exit from constructor.
// generated on exit from constructor.
...
@@ -314,35 +326,21 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) {
...
@@ -314,35 +326,21 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) {
}
}
bool
Parse
::
push_constant
(
ciConstant
constant
,
bool
require_constant
,
bool
is_autobox_cache
)
{
bool
Parse
::
push_constant
(
ciConstant
constant
,
bool
require_constant
,
bool
is_autobox_cache
,
const
Type
*
stable_type
)
{
const
Type
*
con_type
=
Type
::
make_from_constant
(
constant
,
require_constant
,
is_autobox_cache
);
switch
(
constant
.
basic_type
())
{
switch
(
constant
.
basic_type
())
{
case
T_BOOLEAN
:
push
(
intcon
(
constant
.
as_boolean
())
);
break
;
case
T_INT
:
push
(
intcon
(
constant
.
as_int
())
);
break
;
case
T_CHAR
:
push
(
intcon
(
constant
.
as_char
())
);
break
;
case
T_BYTE
:
push
(
intcon
(
constant
.
as_byte
())
);
break
;
case
T_SHORT
:
push
(
intcon
(
constant
.
as_short
())
);
break
;
case
T_FLOAT
:
push
(
makecon
(
TypeF
::
make
(
constant
.
as_float
()))
);
break
;
case
T_DOUBLE
:
push_pair
(
makecon
(
TypeD
::
make
(
constant
.
as_double
()))
);
break
;
case
T_LONG
:
push_pair
(
longcon
(
constant
.
as_long
())
);
break
;
case
T_ARRAY
:
case
T_ARRAY
:
case
T_OBJECT
:
{
case
T_OBJECT
:
// cases:
// cases:
// can_be_constant = (oop not scavengable || ScavengeRootsInCode != 0)
// can_be_constant = (oop not scavengable || ScavengeRootsInCode != 0)
// should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2)
// should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2)
// An oop is not scavengable if it is in the perm gen.
// An oop is not scavengable if it is in the perm gen.
ciObject
*
oop_constant
=
constant
.
as_object
();
if
(
stable_type
!=
NULL
&&
con_type
!=
NULL
&&
con_type
->
isa_oopptr
())
if
(
oop_constant
->
is_null_object
())
{
con_type
=
con_type
->
join
(
stable_type
);
push
(
zerocon
(
T_OBJECT
)
);
break
;
break
;
}
else
if
(
require_constant
||
oop_constant
->
should_be_constant
())
{
case
T_ILLEGAL
:
push
(
makecon
(
TypeOopPtr
::
make_from_constant
(
oop_constant
,
require_constant
,
is_autobox_cache
))
);
break
;
}
else
{
// we cannot inline the oop, but we can use it later to narrow a type
return
false
;
}
}
case
T_ILLEGAL
:
{
// Invalid ciConstant returned due to OutOfMemoryError in the CI
// Invalid ciConstant returned due to OutOfMemoryError in the CI
assert
(
C
->
env
()
->
failing
(),
"otherwise should not see this"
);
assert
(
C
->
env
()
->
failing
(),
"otherwise should not see this"
);
// These always occur because of object types; we are going to
// These always occur because of object types; we are going to
...
@@ -350,17 +348,16 @@ bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_au
...
@@ -350,17 +348,16 @@ bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_au
push
(
zerocon
(
T_OBJECT
)
);
push
(
zerocon
(
T_OBJECT
)
);
return
false
;
return
false
;
}
}
default:
ShouldNotReachHere
();
if
(
con_type
==
NULL
)
// we cannot inline the oop, but we can use it later to narrow a type
return
false
;
return
false
;
}
// success
push_node
(
constant
.
basic_type
(),
makecon
(
con_type
));
return
true
;
return
true
;
}
}
//=============================================================================
//=============================================================================
void
Parse
::
do_anewarray
()
{
void
Parse
::
do_anewarray
()
{
bool
will_link
;
bool
will_link
;
...
...
src/share/vm/opto/type.cpp
浏览文件 @
b17e9bbd
...
@@ -189,6 +189,38 @@ const Type* Type::get_typeflow_type(ciType* type) {
...
@@ -189,6 +189,38 @@ const Type* Type::get_typeflow_type(ciType* type) {
}
}
//-----------------------make_from_constant------------------------------------
const
Type
*
Type
::
make_from_constant
(
ciConstant
constant
,
bool
require_constant
,
bool
is_autobox_cache
)
{
switch
(
constant
.
basic_type
())
{
case
T_BOOLEAN
:
return
TypeInt
::
make
(
constant
.
as_boolean
());
case
T_CHAR
:
return
TypeInt
::
make
(
constant
.
as_char
());
case
T_BYTE
:
return
TypeInt
::
make
(
constant
.
as_byte
());
case
T_SHORT
:
return
TypeInt
::
make
(
constant
.
as_short
());
case
T_INT
:
return
TypeInt
::
make
(
constant
.
as_int
());
case
T_LONG
:
return
TypeLong
::
make
(
constant
.
as_long
());
case
T_FLOAT
:
return
TypeF
::
make
(
constant
.
as_float
());
case
T_DOUBLE
:
return
TypeD
::
make
(
constant
.
as_double
());
case
T_ARRAY
:
case
T_OBJECT
:
{
// cases:
// can_be_constant = (oop not scavengable || ScavengeRootsInCode != 0)
// should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2)
// An oop is not scavengable if it is in the perm gen.
ciObject
*
oop_constant
=
constant
.
as_object
();
if
(
oop_constant
->
is_null_object
())
{
return
Type
::
get_zero_type
(
T_OBJECT
);
}
else
if
(
require_constant
||
oop_constant
->
should_be_constant
())
{
return
TypeOopPtr
::
make_from_constant
(
oop_constant
,
require_constant
,
is_autobox_cache
);
}
}
}
// Fall through to failure
return
NULL
;
}
//------------------------------make-------------------------------------------
//------------------------------make-------------------------------------------
// Create a simple Type, with default empty symbol sets. Then hashcons it
// Create a simple Type, with default empty symbol sets. Then hashcons it
// and look for an existing copy in the type dictionary.
// and look for an existing copy in the type dictionary.
...
@@ -1824,12 +1856,12 @@ inline const TypeInt* normalize_array_size(const TypeInt* size) {
...
@@ -1824,12 +1856,12 @@ inline const TypeInt* normalize_array_size(const TypeInt* size) {
}
}
//------------------------------make-------------------------------------------
//------------------------------make-------------------------------------------
const
TypeAry
*
TypeAry
::
make
(
const
Type
*
elem
,
const
TypeInt
*
siz
e
)
{
const
TypeAry
*
TypeAry
::
make
(
const
Type
*
elem
,
const
TypeInt
*
size
,
bool
stabl
e
)
{
if
(
UseCompressedOops
&&
elem
->
isa_oopptr
())
{
if
(
UseCompressedOops
&&
elem
->
isa_oopptr
())
{
elem
=
elem
->
make_narrowoop
();
elem
=
elem
->
make_narrowoop
();
}
}
size
=
normalize_array_size
(
size
);
size
=
normalize_array_size
(
size
);
return
(
TypeAry
*
)(
new
TypeAry
(
elem
,
size
))
->
hashcons
();
return
(
TypeAry
*
)(
new
TypeAry
(
elem
,
size
,
stable
))
->
hashcons
();
}
}
//------------------------------meet-------------------------------------------
//------------------------------meet-------------------------------------------
...
@@ -1850,7 +1882,8 @@ const Type *TypeAry::xmeet( const Type *t ) const {
...
@@ -1850,7 +1882,8 @@ const Type *TypeAry::xmeet( const Type *t ) const {
case
Array
:
{
// Meeting 2 arrays?
case
Array
:
{
// Meeting 2 arrays?
const
TypeAry
*
a
=
t
->
is_ary
();
const
TypeAry
*
a
=
t
->
is_ary
();
return
TypeAry
::
make
(
_elem
->
meet
(
a
->
_elem
),
return
TypeAry
::
make
(
_elem
->
meet
(
a
->
_elem
),
_size
->
xmeet
(
a
->
_size
)
->
is_int
());
_size
->
xmeet
(
a
->
_size
)
->
is_int
(),
_stable
&
a
->
_stable
);
}
}
case
Top
:
case
Top
:
break
;
break
;
...
@@ -1863,7 +1896,7 @@ const Type *TypeAry::xmeet( const Type *t ) const {
...
@@ -1863,7 +1896,7 @@ const Type *TypeAry::xmeet( const Type *t ) const {
const
Type
*
TypeAry
::
xdual
()
const
{
const
Type
*
TypeAry
::
xdual
()
const
{
const
TypeInt
*
size_dual
=
_size
->
dual
()
->
is_int
();
const
TypeInt
*
size_dual
=
_size
->
dual
()
->
is_int
();
size_dual
=
normalize_array_size
(
size_dual
);
size_dual
=
normalize_array_size
(
size_dual
);
return
new
TypeAry
(
_elem
->
dual
(),
size_dual
);
return
new
TypeAry
(
_elem
->
dual
(),
size_dual
,
!
_stable
);
}
}
//------------------------------eq---------------------------------------------
//------------------------------eq---------------------------------------------
...
@@ -1871,13 +1904,14 @@ const Type *TypeAry::xdual() const {
...
@@ -1871,13 +1904,14 @@ const Type *TypeAry::xdual() const {
bool
TypeAry
::
eq
(
const
Type
*
t
)
const
{
bool
TypeAry
::
eq
(
const
Type
*
t
)
const
{
const
TypeAry
*
a
=
(
const
TypeAry
*
)
t
;
const
TypeAry
*
a
=
(
const
TypeAry
*
)
t
;
return
_elem
==
a
->
_elem
&&
return
_elem
==
a
->
_elem
&&
_stable
==
a
->
_stable
&&
_size
==
a
->
_size
;
_size
==
a
->
_size
;
}
}
//------------------------------hash-------------------------------------------
//------------------------------hash-------------------------------------------
// Type-specific hashing function.
// Type-specific hashing function.
int
TypeAry
::
hash
(
void
)
const
{
int
TypeAry
::
hash
(
void
)
const
{
return
(
intptr_t
)
_elem
+
(
intptr_t
)
_size
;
return
(
intptr_t
)
_elem
+
(
intptr_t
)
_size
+
(
_stable
?
43
:
0
)
;
}
}
//----------------------interface_vs_oop---------------------------------------
//----------------------interface_vs_oop---------------------------------------
...
@@ -1894,6 +1928,7 @@ bool TypeAry::interface_vs_oop(const Type *t) const {
...
@@ -1894,6 +1928,7 @@ bool TypeAry::interface_vs_oop(const Type *t) const {
//------------------------------dump2------------------------------------------
//------------------------------dump2------------------------------------------
#ifndef PRODUCT
#ifndef PRODUCT
void
TypeAry
::
dump2
(
Dict
&
d
,
uint
depth
,
outputStream
*
st
)
const
{
void
TypeAry
::
dump2
(
Dict
&
d
,
uint
depth
,
outputStream
*
st
)
const
{
if
(
_stable
)
st
->
print
(
"stable:"
);
_elem
->
dump2
(
d
,
depth
,
st
);
_elem
->
dump2
(
d
,
depth
,
st
);
st
->
print
(
"["
);
st
->
print
(
"["
);
_size
->
dump2
(
d
,
depth
,
st
);
_size
->
dump2
(
d
,
depth
,
st
);
...
@@ -3457,11 +3492,39 @@ const TypeAryPtr* TypeAryPtr::cast_to_size(const TypeInt* new_size) const {
...
@@ -3457,11 +3492,39 @@ const TypeAryPtr* TypeAryPtr::cast_to_size(const TypeInt* new_size) const {
assert
(
new_size
!=
NULL
,
""
);
assert
(
new_size
!=
NULL
,
""
);
new_size
=
narrow_size_type
(
new_size
);
new_size
=
narrow_size_type
(
new_size
);
if
(
new_size
==
size
())
return
this
;
if
(
new_size
==
size
())
return
this
;
const
TypeAry
*
new_ary
=
TypeAry
::
make
(
elem
(),
new_size
);
const
TypeAry
*
new_ary
=
TypeAry
::
make
(
elem
(),
new_size
,
is_stable
()
);
return
make
(
ptr
(),
const_oop
(),
new_ary
,
klass
(),
klass_is_exact
(),
_offset
,
_instance_id
);
return
make
(
ptr
(),
const_oop
(),
new_ary
,
klass
(),
klass_is_exact
(),
_offset
,
_instance_id
);
}
}
//------------------------------cast_to_stable---------------------------------
const
TypeAryPtr
*
TypeAryPtr
::
cast_to_stable
(
bool
stable
,
int
stable_dimension
)
const
{
if
(
stable_dimension
<=
0
||
(
stable_dimension
==
1
&&
stable
==
this
->
is_stable
()))
return
this
;
const
Type
*
elem
=
this
->
elem
();
const
TypePtr
*
elem_ptr
=
elem
->
make_ptr
();
if
(
stable_dimension
>
1
&&
elem_ptr
!=
NULL
&&
elem_ptr
->
isa_aryptr
())
{
// If this is widened from a narrow oop, TypeAry::make will re-narrow it.
elem
=
elem_ptr
=
elem_ptr
->
is_aryptr
()
->
cast_to_stable
(
stable
,
stable_dimension
-
1
);
}
const
TypeAry
*
new_ary
=
TypeAry
::
make
(
elem
,
size
(),
stable
);
return
make
(
ptr
(),
const_oop
(),
new_ary
,
klass
(),
klass_is_exact
(),
_offset
,
_instance_id
);
}
//-----------------------------stable_dimension--------------------------------
int
TypeAryPtr
::
stable_dimension
()
const
{
if
(
!
is_stable
())
return
0
;
int
dim
=
1
;
const
TypePtr
*
elem_ptr
=
elem
()
->
make_ptr
();
if
(
elem_ptr
!=
NULL
&&
elem_ptr
->
isa_aryptr
())
dim
+=
elem_ptr
->
is_aryptr
()
->
stable_dimension
();
return
dim
;
}
//------------------------------eq---------------------------------------------
//------------------------------eq---------------------------------------------
// Structural equality check for Type representations
// Structural equality check for Type representations
bool
TypeAryPtr
::
eq
(
const
Type
*
t
)
const
{
bool
TypeAryPtr
::
eq
(
const
Type
*
t
)
const
{
...
@@ -3570,7 +3633,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const {
...
@@ -3570,7 +3633,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const {
// Something like byte[int+] meets char[int+].
// Something like byte[int+] meets char[int+].
// This must fall to bottom, not (int[-128..65535])[int+].
// This must fall to bottom, not (int[-128..65535])[int+].
instance_id
=
InstanceBot
;
instance_id
=
InstanceBot
;
tary
=
TypeAry
::
make
(
Type
::
BOTTOM
,
tary
->
_size
);
tary
=
TypeAry
::
make
(
Type
::
BOTTOM
,
tary
->
_size
,
tary
->
_stable
);
}
}
}
else
// Non integral arrays.
}
else
// Non integral arrays.
// Must fall to bottom if exact klasses in upper lattice
// Must fall to bottom if exact klasses in upper lattice
...
@@ -3584,7 +3647,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const {
...
@@ -3584,7 +3647,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const {
(
tap
->
_klass_is_exact
&&
!
tap
->
klass
()
->
is_subtype_of
(
klass
()))
||
(
tap
->
_klass_is_exact
&&
!
tap
->
klass
()
->
is_subtype_of
(
klass
()))
||
// 'this' is exact and super or unrelated:
// 'this' is exact and super or unrelated:
(
this
->
_klass_is_exact
&&
!
klass
()
->
is_subtype_of
(
tap
->
klass
()))))
{
(
this
->
_klass_is_exact
&&
!
klass
()
->
is_subtype_of
(
tap
->
klass
()))))
{
tary
=
TypeAry
::
make
(
Type
::
BOTTOM
,
tary
->
_size
);
tary
=
TypeAry
::
make
(
Type
::
BOTTOM
,
tary
->
_size
,
tary
->
_stable
);
return
make
(
NotNull
,
NULL
,
tary
,
lazy_klass
,
false
,
off
,
InstanceBot
);
return
make
(
NotNull
,
NULL
,
tary
,
lazy_klass
,
false
,
off
,
InstanceBot
);
}
}
...
...
src/share/vm/opto/type.hpp
浏览文件 @
b17e9bbd
...
@@ -372,6 +372,10 @@ public:
...
@@ -372,6 +372,10 @@ public:
// Mapping from CI type system to compiler type:
// Mapping from CI type system to compiler type:
static
const
Type
*
get_typeflow_type
(
ciType
*
type
);
static
const
Type
*
get_typeflow_type
(
ciType
*
type
);
static
const
Type
*
make_from_constant
(
ciConstant
constant
,
bool
require_constant
=
false
,
bool
is_autobox_cache
=
false
);
private:
private:
// support arrays
// support arrays
static
const
BasicType
_basic_type
[];
static
const
BasicType
_basic_type
[];
...
@@ -588,8 +592,8 @@ public:
...
@@ -588,8 +592,8 @@ public:
//------------------------------TypeAry----------------------------------------
//------------------------------TypeAry----------------------------------------
// Class of Array Types
// Class of Array Types
class
TypeAry
:
public
Type
{
class
TypeAry
:
public
Type
{
TypeAry
(
const
Type
*
elem
,
const
TypeInt
*
siz
e
)
:
Type
(
Array
),
TypeAry
(
const
Type
*
elem
,
const
TypeInt
*
size
,
bool
stabl
e
)
:
Type
(
Array
),
_elem
(
elem
),
_size
(
siz
e
)
{}
_elem
(
elem
),
_size
(
size
),
_stable
(
stabl
e
)
{}
public:
public:
virtual
bool
eq
(
const
Type
*
t
)
const
;
virtual
bool
eq
(
const
Type
*
t
)
const
;
virtual
int
hash
()
const
;
// Type specific hashing
virtual
int
hash
()
const
;
// Type specific hashing
...
@@ -599,10 +603,11 @@ public:
...
@@ -599,10 +603,11 @@ public:
private:
private:
const
Type
*
_elem
;
// Element type of array
const
Type
*
_elem
;
// Element type of array
const
TypeInt
*
_size
;
// Elements in array
const
TypeInt
*
_size
;
// Elements in array
const
bool
_stable
;
// Are elements @Stable?
friend
class
TypeAryPtr
;
friend
class
TypeAryPtr
;
public:
public:
static
const
TypeAry
*
make
(
const
Type
*
elem
,
const
TypeInt
*
siz
e
);
static
const
TypeAry
*
make
(
const
Type
*
elem
,
const
TypeInt
*
size
,
bool
stable
=
fals
e
);
virtual
const
Type
*
xmeet
(
const
Type
*
t
)
const
;
virtual
const
Type
*
xmeet
(
const
Type
*
t
)
const
;
virtual
const
Type
*
xdual
()
const
;
// Compute dual right now.
virtual
const
Type
*
xdual
()
const
;
// Compute dual right now.
...
@@ -988,6 +993,7 @@ public:
...
@@ -988,6 +993,7 @@ public:
const
TypeAry
*
ary
()
const
{
return
_ary
;
}
const
TypeAry
*
ary
()
const
{
return
_ary
;
}
const
Type
*
elem
()
const
{
return
_ary
->
_elem
;
}
const
Type
*
elem
()
const
{
return
_ary
->
_elem
;
}
const
TypeInt
*
size
()
const
{
return
_ary
->
_size
;
}
const
TypeInt
*
size
()
const
{
return
_ary
->
_size
;
}
bool
is_stable
()
const
{
return
_ary
->
_stable
;
}
bool
is_autobox_cache
()
const
{
return
_is_autobox_cache
;
}
bool
is_autobox_cache
()
const
{
return
_is_autobox_cache
;
}
...
@@ -1011,6 +1017,9 @@ public:
...
@@ -1011,6 +1017,9 @@ public:
virtual
const
Type
*
xmeet
(
const
Type
*
t
)
const
;
virtual
const
Type
*
xmeet
(
const
Type
*
t
)
const
;
virtual
const
Type
*
xdual
()
const
;
// Compute dual right now.
virtual
const
Type
*
xdual
()
const
;
// Compute dual right now.
const
TypeAryPtr
*
cast_to_stable
(
bool
stable
,
int
stable_dimension
=
1
)
const
;
int
stable_dimension
()
const
;
// Convenience common pre-built types.
// Convenience common pre-built types.
static
const
TypeAryPtr
*
RANGE
;
static
const
TypeAryPtr
*
RANGE
;
static
const
TypeAryPtr
*
OOPS
;
static
const
TypeAryPtr
*
OOPS
;
...
...
src/share/vm/runtime/globals.hpp
浏览文件 @
b17e9bbd
...
@@ -3649,6 +3649,9 @@ class CommandLineFlags {
...
@@ -3649,6 +3649,9 @@ class CommandLineFlags {
experimental(bool, TrustFinalNonStaticFields, false, \
experimental(bool, TrustFinalNonStaticFields, false, \
"trust final non-static declarations for constant folding") \
"trust final non-static declarations for constant folding") \
\
\
experimental(bool, FoldStableValues, false, \
"Private flag to control optimizations for stable variables") \
\
develop(bool, TraceInvokeDynamic, false, \
develop(bool, TraceInvokeDynamic, false, \
"trace internal invoke dynamic operations") \
"trace internal invoke dynamic operations") \
\
\
...
...
src/share/vm/runtime/interfaceSupport.hpp
浏览文件 @
b17e9bbd
...
@@ -471,16 +471,6 @@ class RuntimeHistogramElement : public HistogramElement {
...
@@ -471,16 +471,6 @@ class RuntimeHistogramElement : public HistogramElement {
VM_ENTRY_BASE(result_type, header, thread) \
VM_ENTRY_BASE(result_type, header, thread) \
debug_only(VMEntryWrapper __vew;)
debug_only(VMEntryWrapper __vew;)
// Another special case for nmethod_entry_point so the nmethod that the
// interpreter is about to branch to doesn't get flushed before as we
// branch to it's interpreter_entry_point. Skip stress testing here too.
// Also we don't allow async exceptions because it is just too painful.
#define IRT_ENTRY_FOR_NMETHOD(result_type, header) \
result_type header { \
nmethodLocker _nmlock(nm); \
ThreadInVMfromJavaNoAsyncException __tiv(thread); \
VM_ENTRY_BASE(result_type, header, thread)
#define IRT_END }
#define IRT_END }
...
...
src/share/vm/utilities/accessFlags.hpp
浏览文件 @
b17e9bbd
...
@@ -78,11 +78,13 @@ enum {
...
@@ -78,11 +78,13 @@ enum {
JVM_ACC_FIELD_ACCESS_WATCHED
=
0x00002000
,
// field access is watched by JVMTI
JVM_ACC_FIELD_ACCESS_WATCHED
=
0x00002000
,
// field access is watched by JVMTI
JVM_ACC_FIELD_MODIFICATION_WATCHED
=
0x00008000
,
// field modification is watched by JVMTI
JVM_ACC_FIELD_MODIFICATION_WATCHED
=
0x00008000
,
// field modification is watched by JVMTI
JVM_ACC_FIELD_INTERNAL
=
0x00000400
,
// internal field, same as JVM_ACC_ABSTRACT
JVM_ACC_FIELD_INTERNAL
=
0x00000400
,
// internal field, same as JVM_ACC_ABSTRACT
JVM_ACC_FIELD_STABLE
=
0x00000020
,
// @Stable field, same as JVM_ACC_SYNCHRONIZED
JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE
=
0x00000800
,
// field has generic signature
JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE
=
0x00000800
,
// field has generic signature
JVM_ACC_FIELD_INTERNAL_FLAGS
=
JVM_ACC_FIELD_ACCESS_WATCHED
|
JVM_ACC_FIELD_INTERNAL_FLAGS
=
JVM_ACC_FIELD_ACCESS_WATCHED
|
JVM_ACC_FIELD_MODIFICATION_WATCHED
|
JVM_ACC_FIELD_MODIFICATION_WATCHED
|
JVM_ACC_FIELD_INTERNAL
|
JVM_ACC_FIELD_INTERNAL
|
JVM_ACC_FIELD_STABLE
|
JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE
,
JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE
,
// flags accepted by set_field_flags()
// flags accepted by set_field_flags()
...
@@ -148,6 +150,7 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
...
@@ -148,6 +150,7 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC {
{
return
(
_flags
&
JVM_ACC_FIELD_MODIFICATION_WATCHED
)
!=
0
;
}
{
return
(
_flags
&
JVM_ACC_FIELD_MODIFICATION_WATCHED
)
!=
0
;
}
bool
on_stack
()
const
{
return
(
_flags
&
JVM_ACC_ON_STACK
)
!=
0
;
}
bool
on_stack
()
const
{
return
(
_flags
&
JVM_ACC_ON_STACK
)
!=
0
;
}
bool
is_internal
()
const
{
return
(
_flags
&
JVM_ACC_FIELD_INTERNAL
)
!=
0
;
}
bool
is_internal
()
const
{
return
(
_flags
&
JVM_ACC_FIELD_INTERNAL
)
!=
0
;
}
bool
is_stable
()
const
{
return
(
_flags
&
JVM_ACC_FIELD_STABLE
)
!=
0
;
}
bool
field_has_generic_signature
()
const
bool
field_has_generic_signature
()
const
{
return
(
_flags
&
JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE
)
!=
0
;
}
{
return
(
_flags
&
JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE
)
!=
0
;
}
...
...
test/gc/TestVerifyDuringStartup.java
浏览文件 @
b17e9bbd
...
@@ -48,7 +48,7 @@ public class TestVerifyDuringStartup {
...
@@ -48,7 +48,7 @@ public class TestVerifyDuringStartup {
"-XX:+VerifyDuringStartup"
,
"-XX:+VerifyDuringStartup"
,
"-version"
});
"-version"
});
System
.
out
.
print
(
"Testing:\n"
+
JDKToolFinder
.
getJDKTool
(
"java"
));
System
.
out
.
print
(
"Testing:\n"
+
JDKToolFinder
.
get
Current
JDKTool
(
"java"
));
for
(
int
i
=
0
;
i
<
vmOpts
.
size
();
i
+=
1
)
{
for
(
int
i
=
0
;
i
<
vmOpts
.
size
();
i
+=
1
)
{
System
.
out
.
print
(
" "
+
vmOpts
.
get
(
i
));
System
.
out
.
print
(
" "
+
vmOpts
.
get
(
i
));
}
}
...
...
test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java
浏览文件 @
b17e9bbd
...
@@ -27,24 +27,43 @@ import java.io.File;
...
@@ -27,24 +27,43 @@ import java.io.File;
public
final
class
JDKToolFinder
{
public
final
class
JDKToolFinder
{
private
JDKToolFinder
()
{
private
JDKToolFinder
()
{
}
/**
* Returns the full path to an executable in jdk/bin based on System property
* test.jdk (set by jtreg test suite)
*
* @return Full path to an executable in jdk/bin
*/
public
static
String
getJDKTool
(
String
tool
)
{
String
binPath
=
System
.
getProperty
(
"test.jdk"
);
if
(
binPath
==
null
)
{
throw
new
RuntimeException
(
"System property 'test.jdk' not set. This property is normally set by jtreg. "
+
"When running test separately, set this property using '-Dtest.jdk=/path/to/jdk'."
);
}
}
binPath
+=
File
.
separatorChar
+
"bin"
+
File
.
separatorChar
+
tool
;
/**
* Returns the full path to an executable in jdk/bin based on System
* property {@code compile.jdk} (set by jtreg test suite)
*
* @return Full path to an executable in jdk/bin
*/
public
static
String
getJDKTool
(
String
tool
)
{
String
binPath
=
System
.
getProperty
(
"compile.jdk"
);
if
(
binPath
==
null
)
{
throw
new
RuntimeException
(
"System property 'compile.jdk' not set. "
+
"This property is normally set by jtreg. "
+
"When running test separately, set this property using "
+
"'-Dcompile.jdk=/path/to/jdk'."
);
}
binPath
+=
File
.
separatorChar
+
"bin"
+
File
.
separatorChar
+
tool
;
return
binPath
;
}
/**
* Returns the full path to an executable in <current jdk>/bin based
* on System property {@code test.jdk} (set by jtreg test suite)
*
* @return Full path to an executable in jdk/bin
*/
public
static
String
getCurrentJDKTool
(
String
tool
)
{
String
binPath
=
System
.
getProperty
(
"test.jdk"
);
if
(
binPath
==
null
)
{
throw
new
RuntimeException
(
"System property 'test.jdk' not set. "
+
"This property is normally set by jtreg. "
+
"When running test separately, set this property using "
+
"'-Dtest.jdk=/path/to/jdk'."
);
}
binPath
+=
File
.
separatorChar
+
"bin"
+
File
.
separatorChar
+
tool
;
return
binPath
;
return
binPath
;
}
}
}
}
test/testlibrary/ctw/Makefile
0 → 100644
浏览文件 @
b17e9bbd
#
# Copyright (c) 2013, 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.
#
#
ifneq
"x$(ALT_BOOTDIR)" "x"
BOOTDIR
:=
$(ALT_BOOTDIR)
endif
ifeq
"x$(BOOTDIR)" "x"
JDK_HOME
:=
$(
shell
dirname
$(
shell
which java
))
/..
else
JDK_HOME
:=
$(BOOTDIR)
endif
SRC_DIR
=
src
BUILD_DIR
=
build
OUTPUT_DIR
=
$(BUILD_DIR)
/classes
WHITEBOX_DIR
=
../whitebox
JAVAC
=
$(JDK_HOME)
/bin/javac
JAR
=
$(JDK_HOME)
/bin/jar
SRC_FILES
=
$(
shell
find
$(SRC_DIR)
-name
'*.java'
)
MAIN_CLASS
=
sun.hotspot.tools.ctw.CompileTheWorld
.PHONY
:
clean cleantmp
all
:
ctw.jar cleantmp
clean
:
cleantmp
@
rm
-rf
ctw.jar wb.jar
cleantmp
:
@
rm
-rf
filelist manifest.mf
@
rm
-rf
$(BUILD_DIR)
ctw.jar
:
filelist wb.jar manifest.mf
@
mkdir
-p
$(OUTPUT_DIR)
$(JAVAC)
-sourcepath
$(SRC_DIR)
-d
$(OUTPUT_DIR)
-cp
wb.jar @filelist
$(JAR)
cfm ctw.jar manifest.mf
-C
$(OUTPUT_DIR)
.
wb.jar
:
make
-C
${WHITEBOX_DIR}
wb.jar
cp
${WHITEBOX_DIR}
/wb.jar ./
make
-C
${WHITEBOX_DIR}
clean
filelist
:
$(SRC_FILES)
@
rm
-f
$@
@
echo
$(SRC_FILES)
>
$@
manifest.mf
:
@
echo
"Main-Class:
${MAIN_CLASS}
"
>
manifest.mf
test/testlibrary/ctw/README
0 → 100644
浏览文件 @
b17e9bbd
#
# Copyright (c) 2013, 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.
#
#
DESCRIPTION
This is replacement for CompileTheWorld (CTW) written on java. Its purpose is
to make possible the use of CTW in product builds.
DEPENDENCES
The tool depends on Whitebox API. Assumed, that the sources of whitebox are
located in '../whitebox' directory.
BUILDING
Simple way to build, just type 'make'.
Makefile uses environment variables 'ALT_BOOTDIR', 'BOOTDIR' as root-dir of jdk
that will be used for compilation and creating jar.
On successful building 'ctw.jar' will be created.
RUNNING
Since the tool uses WhiteBox API, options 'UnlockDiagnosticVMOptions' and
'WhiteBoxAPI' should be specified, and 'wb.jar' should be added to
boot-classpath:
$ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar
Arguments can be paths to '.jar, '.zip', '.lst' files or directories with
classes, that define which classes will be compiled:
- '.jar', '.zip' files and directories are interpreted like in classpath
(including '<dir>/*' syntax)
- '.lst' files -- files with class names (in java notation) to compile.
CTW will try to find these classes with default class loader, so they should
be located in classpath.
Without arguments it would work as old version of CTW: all classes in
boot-classpath will be compiled, excluding classes in 'rt.jar' if 'rt.jar' isn't
first in boot-classpath.
Due CTW's flags also are not available in product builds, the tool uses
properties with the same names:
- 'CompileTheWorldPreloadClasses' -- type:boolean, default:true, description:
Preload all classes used by a class before start loading
- 'CompileTheWorldStartAt' -- type:long, default:1, description: First class
to consider
- 'CompileTheWorldStopAt' -- type:long, default:Long.MAX_VALUE, description:
Last class to consider
Also it uses additional properties:
- 'sun.hotspot.tools.ctw.verbose' -- type:boolean, default:false,
description: Verbose output, adds additional information about compilation
- 'sun.hotspot.tools.ctw.logfile' -- type:string, default:null,
description: Path to logfile, if it's null, cout will be used.
EXAMPLES
compile classes from 'rt.jar':
$ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar ${JAVA_HOME}/jre/lib/rt.jar
compile classes from all '.jar' in './testjars' directory:
$ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar ./testjars/*
compile classes from './build/classes' directory:
$ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar ./build/classes
compile only java.lang.String, java.lang.Object classes:
$ echo java.lang.String > classes.lst
$ echo java.lang.Object >> classes.lst
$ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar classes.lst
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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.
*/
package
sun.hotspot.tools.ctw
;
import
java.net.MalformedURLException
;
import
java.net.URL
;
import
java.net.URLClassLoader
;
import
java.util.Set
;
import
java.util.EnumSet
;
import
java.util.HashSet
;
import
java.util.concurrent.Executor
;
import
java.io.*
;
import
java.nio.file.*
;
import
java.nio.file.attribute.*
;
/**
* * Handler for dirs containing classes to compile.
* @author igor.ignatyev@oracle.com
*/
public
class
ClassPathDirEntry
extends
PathHandler
{
private
final
int
rootLength
=
root
.
toString
().
length
();
public
ClassPathDirEntry
(
Path
root
,
Executor
executor
)
{
super
(
root
,
executor
);
try
{
URL
url
=
root
.
toUri
().
toURL
();
setLoader
(
new
URLClassLoader
(
new
URL
[]{
url
}));
}
catch
(
MalformedURLException
e
)
{
e
.
printStackTrace
();
}
}
@Override
public
void
process
()
{
System
.
out
.
println
(
"# dir: "
+
root
);
if
(!
Files
.
exists
(
root
))
{
return
;
}
try
{
Files
.
walkFileTree
(
root
,
EnumSet
.
of
(
FileVisitOption
.
FOLLOW_LINKS
),
Integer
.
MAX_VALUE
,
new
CompileFileVisitor
());
}
catch
(
IOException
ioe
)
{
ioe
.
printStackTrace
();
}
}
private
void
processFile
(
Path
file
)
{
if
(
Utils
.
isClassFile
(
file
.
toString
()))
{
processClass
(
pathToClassName
(
file
));
}
}
private
String
pathToClassName
(
Path
file
)
{
String
fileString
;
if
(
root
==
file
)
{
fileString
=
file
.
normalize
().
toString
();
}
else
{
fileString
=
file
.
normalize
().
toString
().
substring
(
rootLength
+
1
);
}
return
Utils
.
fileNameToClassName
(
fileString
);
}
private
class
CompileFileVisitor
extends
SimpleFileVisitor
<
Path
>
{
private
final
Set
<
Path
>
ready
=
new
HashSet
<>();
@Override
public
FileVisitResult
preVisitDirectory
(
Path
dir
,
BasicFileAttributes
attrs
)
throws
IOException
{
if
(
ready
.
contains
(
dir
))
{
return
FileVisitResult
.
SKIP_SUBTREE
;
}
ready
.
add
(
dir
);
return
super
.
preVisitDirectory
(
dir
,
attrs
);
}
@Override
public
FileVisitResult
visitFile
(
Path
file
,
BasicFileAttributes
attrs
)
throws
IOException
{
if
(!
ready
.
contains
(
file
))
{
processFile
(
file
);
}
return
isFinished
()
?
FileVisitResult
.
TERMINATE
:
FileVisitResult
.
CONTINUE
;
}
@Override
public
FileVisitResult
visitFileFailed
(
Path
file
,
IOException
exc
)
throws
IOException
{
return
FileVisitResult
.
CONTINUE
;
}
}
}
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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.
*/
package
sun.hotspot.tools.ctw
;
import
java.net.MalformedURLException
;
import
java.net.URL
;
import
java.net.URLClassLoader
;
import
java.util.*
;
import
java.util.jar.*
;
import
java.util.concurrent.Executor
;
import
java.io.*
;
import
java.nio.file.*
;
/**
* Handler for jar-files containing classes to compile.
* @author igor.ignatyev@oracle.com
*/
public
class
ClassPathJarEntry
extends
PathHandler
{
public
ClassPathJarEntry
(
Path
root
,
Executor
executor
)
{
super
(
root
,
executor
);
try
{
URL
url
=
root
.
toUri
().
toURL
();
setLoader
(
new
URLClassLoader
(
new
URL
[]{
url
}));
}
catch
(
MalformedURLException
e
)
{
e
.
printStackTrace
();
}
}
@Override
public
void
process
()
{
System
.
out
.
println
(
"# jar: "
+
root
);
if
(!
Files
.
exists
(
root
))
{
return
;
}
try
{
JarFile
jarFile
=
new
JarFile
(
root
.
toFile
());
JarEntry
entry
;
for
(
Enumeration
<
JarEntry
>
e
=
jarFile
.
entries
();
e
.
hasMoreElements
();
)
{
entry
=
e
.
nextElement
();
processJarEntry
(
entry
);
if
(
isFinished
())
{
return
;
}
}
}
catch
(
IOException
ioe
)
{
ioe
.
printStackTrace
();
}
}
private
void
processJarEntry
(
JarEntry
entry
)
{
String
filename
=
entry
.
getName
();
if
(
Utils
.
isClassFile
(
filename
))
{
processClass
(
Utils
.
fileNameToClassName
(
filename
));
}
}
}
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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.
*/
package
sun.hotspot.tools.ctw
;
import
java.io.IOException
;
import
java.nio.file.DirectoryStream
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.util.concurrent.Executor
;
/**
* Handler for dirs containing jar-files with classes to compile.
*
* @author igor.ignatyev@oracle.com
*/
public
class
ClassPathJarInDirEntry
extends
PathHandler
{
public
ClassPathJarInDirEntry
(
Path
root
,
Executor
executor
)
{
super
(
root
,
executor
);
}
@Override
public
void
process
()
{
System
.
out
.
println
(
"# jar_in_dir: "
+
root
);
if
(!
Files
.
exists
(
root
))
{
return
;
}
try
(
DirectoryStream
<
Path
>
ds
=
Files
.
newDirectoryStream
(
root
,
"*.jar"
))
{
for
(
Path
p
:
ds
)
{
new
ClassPathJarEntry
(
p
,
executor
).
process
();
if
(
isFinished
())
{
return
;
}
}
}
catch
(
IOException
ioe
)
{
ioe
.
printStackTrace
();
}
}
}
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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.
*/
package
sun.hotspot.tools.ctw
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.util.concurrent.Executor
;
/**
* Handler for files containing a list of classes to compile.
*
* @author igor.ignatyev@oracle.com
*/
public
class
ClassesListInFile
extends
PathHandler
{
public
ClassesListInFile
(
Path
root
,
Executor
executor
)
{
super
(
root
,
executor
);
}
@Override
public
void
process
()
{
System
.
out
.
println
(
"# list: "
+
root
);
if
(!
Files
.
exists
(
root
))
{
return
;
}
try
{
try
(
BufferedReader
reader
=
Files
.
newBufferedReader
(
root
,
StandardCharsets
.
UTF_8
))
{
String
line
;
while
(!
isFinished
()
&&
((
line
=
reader
.
readLine
())
!=
null
))
{
processClass
(
line
);
}
}
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
}
}
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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.
*/
package
sun.hotspot.tools.ctw
;
import
sun.management.ManagementFactoryHelper
;
import
java.io.*
;
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
java.util.List
;
import
java.util.concurrent.*
;
/**
* @author igor.ignatyev@oracle.com
*/
public
class
CompileTheWorld
{
/**
* Entry point. Compiles classes in {@code args}, or all classes in
* boot-classpath if args is empty
*
* @param args paths to jar/zip, dir contains classes, or to .lst file
* contains list of classes to compile
*/
public
static
void
main
(
String
[]
args
)
{
String
logfile
=
Utils
.
LOG_FILE
;
PrintStream
os
=
null
;
if
(
logfile
!=
null
)
{
try
{
os
=
new
PrintStream
(
Files
.
newOutputStream
(
Paths
.
get
(
logfile
)));
}
catch
(
IOException
io
)
{
}
}
if
(
os
!=
null
)
{
System
.
setOut
(
os
);
}
try
{
try
{
if
(
ManagementFactoryHelper
.
getCompilationMXBean
()
==
null
)
{
throw
new
RuntimeException
(
"CTW can not work in interpreted mode"
);
}
}
catch
(
java
.
lang
.
NoClassDefFoundError
e
)
{
// compact1, compact2 support
}
String
[]
paths
=
args
;
boolean
skipRtJar
=
false
;
if
(
args
.
length
==
0
)
{
paths
=
getDefaultPaths
();
skipRtJar
=
true
;
}
ExecutorService
executor
=
createExecutor
();
long
start
=
System
.
currentTimeMillis
();
try
{
String
path
;
for
(
int
i
=
0
,
n
=
paths
.
length
;
i
<
n
&&
!
PathHandler
.
isFinished
();
++
i
)
{
path
=
paths
[
i
];
if
(
skipRtJar
&&
i
>
0
&&
isRtJar
(
path
))
{
// rt.jar is not first, so skip it
continue
;
}
PathHandler
.
create
(
path
,
executor
).
process
();
}
}
finally
{
await
(
executor
);
}
System
.
out
.
printf
(
"Done (%d classes, %d methods, %d ms)%n"
,
Compiler
.
getClassCount
(),
Compiler
.
getMethodCount
(),
System
.
currentTimeMillis
()
-
start
);
}
finally
{
if
(
os
!=
null
)
{
os
.
close
();
}
}
}
private
static
ExecutorService
createExecutor
()
{
final
int
threadsCount
=
Math
.
min
(
Runtime
.
getRuntime
().
availableProcessors
(),
Utils
.
CI_COMPILER_COUNT
);
ExecutorService
result
;
if
(
threadsCount
>
1
)
{
result
=
new
ThreadPoolExecutor
(
threadsCount
,
threadsCount
,
/* keepAliveTime */
0L
,
TimeUnit
.
MILLISECONDS
,
new
ArrayBlockingQueue
<>(
threadsCount
),
new
ThreadPoolExecutor
.
CallerRunsPolicy
());
}
else
{
result
=
new
CurrentThreadExecutor
();
}
return
result
;
}
private
static
String
[]
getDefaultPaths
()
{
String
property
=
System
.
getProperty
(
"sun.boot.class.path"
);
System
.
out
.
println
(
"# use 'sun.boot.class.path' as args: "
+
property
);
return
Utils
.
PATH_SEPARATOR
.
split
(
property
);
}
private
static
void
await
(
ExecutorService
executor
)
{
executor
.
shutdown
();
while
(!
executor
.
isTerminated
())
{
try
{
executor
.
awaitTermination
(
Long
.
MAX_VALUE
,
TimeUnit
.
NANOSECONDS
);
}
catch
(
InterruptedException
ie
)
{
Thread
.
currentThread
().
interrupt
();
break
;
}
}
}
private
static
boolean
isRtJar
(
String
path
)
{
return
Utils
.
endsWithIgnoreCase
(
path
,
File
.
separator
+
"rt.jar"
);
}
private
static
class
CurrentThreadExecutor
extends
AbstractExecutorService
{
private
boolean
isShutdown
;
@Override
public
void
shutdown
()
{
this
.
isShutdown
=
true
;
}
@Override
public
List
<
Runnable
>
shutdownNow
()
{
return
null
;
}
@Override
public
boolean
isShutdown
()
{
return
isShutdown
;
}
@Override
public
boolean
isTerminated
()
{
return
isShutdown
;
}
@Override
public
boolean
awaitTermination
(
long
timeout
,
TimeUnit
unit
)
throws
InterruptedException
{
return
isShutdown
;
}
@Override
public
void
execute
(
Runnable
command
)
{
command
.
run
();
}
}
}
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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.
*/
package
sun.hotspot.tools.ctw
;
import
sun.hotspot.WhiteBox
;
import
sun.misc.SharedSecrets
;
import
sun.reflect.ConstantPool
;
import
java.lang.reflect.Executable
;
import
java.util.Objects
;
import
java.util.concurrent.Executor
;
import
java.util.concurrent.atomic.AtomicLong
;
/**
* Provide method to compile whole class.
* Also contains compiled methods and classes counters.
*
* @author igor.ignatyev@oracle.com
*/
public
class
Compiler
{
private
Compiler
()
{
}
private
static
final
WhiteBox
WHITE_BOX
=
WhiteBox
.
getWhiteBox
();
private
static
final
AtomicLong
CLASS_COUNT
=
new
AtomicLong
(
0L
);
private
static
final
AtomicLong
METHOD_COUNT
=
new
AtomicLong
(
0L
);
private
static
volatile
boolean
CLASSES_LIMIT_REACHED
=
false
;
/**
* @return count of processed classes
*/
public
static
long
getClassCount
()
{
return
CLASS_COUNT
.
get
();
}
/**
* @return count of processed methods
*/
public
static
long
getMethodCount
()
{
return
METHOD_COUNT
.
get
();
}
/**
* @return {@code true} if classes limit is reached
*/
public
static
boolean
isLimitReached
()
{
return
CLASSES_LIMIT_REACHED
;
}
/**
* Compiles all methods and constructors.
*
* @param aClass class to compile
* @param executor executor used for compile task invocation
* @throws NullPointerException if {@code class} or {@code executor}
* is {@code null}
*/
public
static
void
compileClass
(
Class
aClass
,
Executor
executor
)
{
Objects
.
requireNonNull
(
aClass
);
Objects
.
requireNonNull
(
executor
);
long
id
=
CLASS_COUNT
.
incrementAndGet
();
if
(
id
>
Utils
.
COMPILE_THE_WORLD_STOP_AT
)
{
CLASS_COUNT
.
decrementAndGet
();
CLASSES_LIMIT_REACHED
=
true
;
return
;
}
if
(
id
>=
Utils
.
COMPILE_THE_WORLD_START_AT
)
{
String
name
=
aClass
.
getName
();
try
{
System
.
out
.
printf
(
"[%d]\t%s%n"
,
id
,
name
);
ConstantPool
constantPool
=
SharedSecrets
.
getJavaLangAccess
().
getConstantPool
(
aClass
);
if
(
Utils
.
COMPILE_THE_WORLD_PRELOAD_CLASSES
)
{
preloadClasses
(
name
,
id
,
constantPool
);
}
long
methodCount
=
0
;
for
(
Executable
e
:
aClass
.
getDeclaredConstructors
())
{
++
methodCount
;
executor
.
execute
(
new
CompileMethodCommand
(
id
,
name
,
e
));
}
for
(
Executable
e
:
aClass
.
getDeclaredMethods
())
{
++
methodCount
;
executor
.
execute
(
new
CompileMethodCommand
(
id
,
name
,
e
));
}
METHOD_COUNT
.
addAndGet
(
methodCount
);
if
(
Utils
.
DEOPTIMIZE_ALL_CLASSES_RATE
>
0
&&
(
id
%
Utils
.
DEOPTIMIZE_ALL_CLASSES_RATE
==
0
))
{
WHITE_BOX
.
deoptimizeAll
();
}
}
catch
(
Throwable
t
)
{
System
.
out
.
printf
(
"[%d]\t%s\tskipping %s%n"
,
id
,
name
,
t
);
t
.
printStackTrace
();
}
}
}
private
static
void
preloadClasses
(
String
className
,
long
id
,
ConstantPool
constantPool
)
{
try
{
for
(
int
i
=
0
,
n
=
constantPool
.
getSize
();
i
<
n
;
++
i
)
{
try
{
constantPool
.
getClassAt
(
i
);
}
catch
(
IllegalArgumentException
ignore
)
{
}
}
}
catch
(
Throwable
t
)
{
System
.
out
.
printf
(
"[%d]\t%s\tpreloading failed : %s%n"
,
id
,
className
,
t
);
}
}
/**
* Compilation of method.
* Will compile method on all available comp levels.
*/
private
static
class
CompileMethodCommand
implements
Runnable
{
private
final
long
classId
;
private
final
String
className
;
private
final
Executable
method
;
/**
* @param classId id of class
* @param className name of class
* @param method compiled for compilation
*/
public
CompileMethodCommand
(
long
classId
,
String
className
,
Executable
method
)
{
this
.
classId
=
classId
;
this
.
className
=
className
;
this
.
method
=
method
;
}
@Override
public
final
void
run
()
{
int
compLevel
=
Utils
.
INITIAL_COMP_LEVEL
;
if
(
Utils
.
TIERED_COMPILATION
)
{
for
(
int
i
=
compLevel
;
i
<=
Utils
.
TIERED_STOP_AT_LEVEL
;
++
i
)
{
WHITE_BOX
.
deoptimizeMethod
(
method
);
compileMethod
(
method
,
i
);
}
}
else
{
compileMethod
(
method
,
compLevel
);
}
}
private
void
waitCompilation
()
{
if
(!
Utils
.
BACKGROUND_COMPILATION
)
{
return
;
}
final
Object
obj
=
new
Object
();
synchronized
(
obj
)
{
for
(
int
i
=
0
;
i
<
10
&&
WHITE_BOX
.
isMethodQueuedForCompilation
(
method
);
++
i
)
{
try
{
obj
.
wait
(
1000
);
}
catch
(
InterruptedException
e
)
{
Thread
.
currentThread
().
interrupt
();
}
}
}
}
private
void
compileMethod
(
Executable
method
,
int
compLevel
)
{
if
(
WHITE_BOX
.
isMethodCompilable
(
method
,
compLevel
))
{
try
{
WHITE_BOX
.
enqueueMethodForCompilation
(
method
,
compLevel
);
waitCompilation
();
int
tmp
=
WHITE_BOX
.
getMethodCompilationLevel
(
method
);
if
(
tmp
!=
compLevel
)
{
logMethod
(
method
,
"compilation level = "
+
tmp
+
", but not "
+
compLevel
);
}
else
if
(
Utils
.
IS_VERBOSE
)
{
logMethod
(
method
,
"compilation level = "
+
tmp
+
". OK"
);
}
}
catch
(
Throwable
t
)
{
logMethod
(
method
,
"error on compile at "
+
compLevel
+
" level"
);
t
.
printStackTrace
();
}
}
else
if
(
Utils
.
IS_VERBOSE
)
{
logMethod
(
method
,
"not compilable at "
+
compLevel
);
}
}
private
void
logMethod
(
Executable
method
,
String
message
)
{
StringBuilder
builder
=
new
StringBuilder
(
"["
);
builder
.
append
(
classId
);
builder
.
append
(
"]\t"
);
builder
.
append
(
className
);
builder
.
append
(
"::"
);
builder
.
append
(
method
.
getName
());
builder
.
append
(
'('
);
Class
[]
params
=
method
.
getParameterTypes
();
for
(
int
i
=
0
,
n
=
params
.
length
-
1
;
i
<
n
;
++
i
)
{
builder
.
append
(
params
[
i
].
getName
());
builder
.
append
(
", "
);
}
if
(
params
.
length
!=
0
)
{
builder
.
append
(
params
[
params
.
length
-
1
].
getName
());
}
builder
.
append
(
')'
);
if
(
message
!=
null
)
{
builder
.
append
(
'\t'
);
builder
.
append
(
message
);
}
System
.
err
.
println
(
builder
);
}
}
}
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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.
*/
package
sun.hotspot.tools.ctw
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.io.File
;
import
java.util.Objects
;
import
java.util.regex.Pattern
;
import
java.util.regex.Matcher
;
import
java.util.concurrent.Executor
;
/**
* Abstract handler for path.
* <p/>
* Concrete subclasses should implement method {@link #process()}.
*
* @author igor.ignatyev@oracle.com
*/
public
abstract
class
PathHandler
{
private
static
final
Pattern
JAR_IN_DIR_PATTERN
=
Pattern
.
compile
(
"^(.*[/\\\\])?\\*$"
);
protected
final
Path
root
;
protected
final
Executor
executor
;
private
ClassLoader
loader
;
/**
* @param root root path to process
* @param executor executor used for process task invocation
* @throws NullPointerException if {@code root} or {@code executor} is
* {@code null}
*/
protected
PathHandler
(
Path
root
,
Executor
executor
)
{
Objects
.
requireNonNull
(
root
);
Objects
.
requireNonNull
(
executor
);
this
.
root
=
root
.
normalize
();
this
.
executor
=
executor
;
this
.
loader
=
ClassLoader
.
getSystemClassLoader
();
}
/**
* Factory method. Construct concrete handler in depends from {@code path}.
*
* @param path the path to process
* @param executor executor used for compile task invocation
* @throws NullPointerException if {@code path} or {@code executor} is
* {@code null}
*/
public
static
PathHandler
create
(
String
path
,
Executor
executor
)
{
Objects
.
requireNonNull
(
path
);
Objects
.
requireNonNull
(
executor
);
Matcher
matcher
=
JAR_IN_DIR_PATTERN
.
matcher
(
path
);
if
(
matcher
.
matches
())
{
path
=
matcher
.
group
(
1
);
path
=
path
.
isEmpty
()
?
"."
:
path
;
return
new
ClassPathJarInDirEntry
(
Paths
.
get
(
path
),
executor
);
}
else
{
path
=
path
.
isEmpty
()
?
"."
:
path
;
Path
p
=
Paths
.
get
(
path
);
if
(
isJarFile
(
p
))
{
return
new
ClassPathJarEntry
(
p
,
executor
);
}
else
if
(
isListFile
(
p
))
{
return
new
ClassesListInFile
(
p
,
executor
);
}
else
{
return
new
ClassPathDirEntry
(
p
,
executor
);
}
}
}
private
static
boolean
isJarFile
(
Path
path
)
{
if
(
Files
.
isRegularFile
(
path
))
{
String
name
=
path
.
toString
();
return
Utils
.
endsWithIgnoreCase
(
name
,
".zip"
)
||
Utils
.
endsWithIgnoreCase
(
name
,
".jar"
);
}
return
false
;
}
private
static
boolean
isListFile
(
Path
path
)
{
if
(
Files
.
isRegularFile
(
path
))
{
String
name
=
path
.
toString
();
return
Utils
.
endsWithIgnoreCase
(
name
,
".lst"
);
}
return
false
;
}
/**
* Processes all classes in specified path.
*/
public
abstract
void
process
();
/**
* Sets class loader, that will be used to define class at
* {@link #processClass(String)}.
*
* @param loader class loader
* @throws NullPointerException if {@code loader} is {@code null}
*/
protected
final
void
setLoader
(
ClassLoader
loader
)
{
Objects
.
requireNonNull
(
loader
);
this
.
loader
=
loader
;
}
/**
* Processes specificed class.
* @param name fully qualified name of class to process
*/
protected
final
void
processClass
(
String
name
)
{
try
{
Class
aClass
=
Class
.
forName
(
name
,
true
,
loader
);
Compiler
.
compileClass
(
aClass
,
executor
);
}
catch
(
ClassNotFoundException
|
LinkageError
e
)
{
System
.
out
.
printf
(
"Class %s loading failed : %s%n"
,
name
,
e
.
getMessage
());
}
}
/**
* @return {@code true} if processing should be stopped
*/
public
static
boolean
isFinished
()
{
return
Compiler
.
isLimitReached
();
}
}
test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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.
*/
package
sun.hotspot.tools.ctw
;
import
com.sun.management.HotSpotDiagnosticMXBean
;
import
sun.management.ManagementFactoryHelper
;
import
java.io.File
;
import
java.util.regex.Pattern
;
/**
* Auxiliary methods.
*
* @author igor.ignatyev@oracle.com
*/
public
class
Utils
{
/**
* Value of {@code -XX:CompileThreshold}
*/
public
static
final
boolean
TIERED_COMPILATION
=
Boolean
.
parseBoolean
(
getVMOption
(
"TieredCompilation"
,
"false"
));
/**
* Value of {@code -XX:BackgroundCompilation}
*/
public
static
final
boolean
BACKGROUND_COMPILATION
=
Boolean
.
parseBoolean
(
getVMOption
(
"BackgroundCompilation"
,
"false"
));
/**
* Value of {@code -XX:TieredStopAtLevel}
*/
public
static
final
int
TIERED_STOP_AT_LEVEL
;
/**
* Value of {@code -XX:CICompilerCount}
*/
public
static
final
Integer
CI_COMPILER_COUNT
=
Integer
.
valueOf
(
getVMOption
(
"CICompilerCount"
,
"1"
));
/**
* Initial compilation level.
*/
public
static
final
int
INITIAL_COMP_LEVEL
;
/**
* Compiled path-separator regexp.
*/
public
static
final
Pattern
PATH_SEPARATOR
=
Pattern
.
compile
(
File
.
pathSeparator
,
Pattern
.
LITERAL
);
/**
* Value of {@code -DDeoptimizeAllClassesRate}. Frequency of
* {@code WB.deoptimizeAll()} invocation If it less that {@code 0},
* {@code WB.deoptimizeAll()} will not be invoked.
*/
public
static
final
int
DEOPTIMIZE_ALL_CLASSES_RATE
=
Integer
.
getInteger
(
"DeoptimizeAllClassesRate"
,
-
1
);
/**
* Value of {@code -DCompileTheWorldStopAt}. Last class to consider.
*/
public
static
final
long
COMPILE_THE_WORLD_STOP_AT
=
Long
.
getLong
(
"CompileTheWorldStopAt"
,
Long
.
MAX_VALUE
);
/**
* Value of {@code -DCompileTheWorldStartAt}. First class to consider.
*/
public
static
final
long
COMPILE_THE_WORLD_START_AT
=
Long
.
getLong
(
"CompileTheWorldStartAt"
,
1
);
/**
* Value of {@code -DCompileTheWorldPreloadClasses}. Preload all classes
* used by a class before start loading.
*/
public
static
final
boolean
COMPILE_THE_WORLD_PRELOAD_CLASSES
;
/**
* Value of {@code -Dsun.hotspot.tools.ctw.verbose}. Verbose output,
* adds additional information about compilation.
*/
public
static
final
boolean
IS_VERBOSE
=
Boolean
.
getBoolean
(
"sun.hotspot.tools.ctw.verbose"
);
/**
* Value of {@code -Dsun.hotspot.tools.ctw.logfile}.Path to logfile, if
* it's null, cout will be used.
*/
public
static
final
String
LOG_FILE
=
System
.
getProperty
(
"sun.hotspot.tools.ctw.logfile"
);
static
{
if
(
Utils
.
TIERED_COMPILATION
)
{
INITIAL_COMP_LEVEL
=
1
;
}
else
{
String
vmName
=
System
.
getProperty
(
"java.vm.name"
);
if
(
Utils
.
endsWithIgnoreCase
(
vmName
,
" Server VM"
))
{
INITIAL_COMP_LEVEL
=
4
;
}
else
if
(
Utils
.
endsWithIgnoreCase
(
vmName
,
" Client VM"
)
||
Utils
.
endsWithIgnoreCase
(
vmName
,
" Minimal VM"
))
{
INITIAL_COMP_LEVEL
=
1
;
}
else
{
throw
new
RuntimeException
(
"Unknown VM: "
+
vmName
);
}
}
TIERED_STOP_AT_LEVEL
=
Integer
.
parseInt
(
getVMOption
(
"TieredStopAtLevel"
,
String
.
valueOf
(
INITIAL_COMP_LEVEL
)));
}
static
{
String
tmp
=
System
.
getProperty
(
"CompileTheWorldPreloadClasses"
);
if
(
tmp
==
null
)
{
COMPILE_THE_WORLD_PRELOAD_CLASSES
=
true
;
}
else
{
COMPILE_THE_WORLD_PRELOAD_CLASSES
=
Boolean
.
parseBoolean
(
tmp
);
}
}
public
static
final
String
CLASSFILE_EXT
=
".class"
;
private
Utils
()
{
}
/**
* Tests if the string ends with the suffix, ignoring case
* considerations
*
* @param string the tested string
* @param suffix the suffix
* @return {@code true} if {@code string} ends with the {@code suffix}
* @see String#endsWith(String)
*/
public
static
boolean
endsWithIgnoreCase
(
String
string
,
String
suffix
)
{
if
(
string
==
null
||
suffix
==
null
)
{
return
false
;
}
int
length
=
suffix
.
length
();
int
toffset
=
string
.
length
()
-
length
;
if
(
toffset
<
0
)
{
return
false
;
}
return
string
.
regionMatches
(
true
,
toffset
,
suffix
,
0
,
length
);
}
/**
* Returns value of VM option.
*
* @param name option's name
* @return value of option or {@code null}, if option doesn't exist
* @throws NullPointerException if name is null
*/
public
static
String
getVMOption
(
String
name
)
{
String
result
;
HotSpotDiagnosticMXBean
diagnostic
=
ManagementFactoryHelper
.
getDiagnosticMXBean
();
result
=
diagnostic
.
getVMOption
(
name
).
getValue
();
return
result
;
}
/**
* Returns value of VM option or default value.
*
* @param name option's name
* @param defaultValue default value
* @return value of option or {@code defaultValue}, if option doesn't exist
* @throws NullPointerException if name is null
* @see #getVMOption(String)
*/
public
static
String
getVMOption
(
String
name
,
String
defaultValue
)
{
String
result
;
try
{
result
=
getVMOption
(
name
);
}
catch
(
NoClassDefFoundError
e
)
{
// compact1, compact2 support
result
=
defaultValue
;
}
return
result
==
null
?
defaultValue
:
result
;
}
/**
* Tests if the filename is valid filename for class file.
*
* @param filename tested filename
*/
public
static
boolean
isClassFile
(
String
filename
)
{
// If the filename has a period after removing '.class', it's not valid class file
return
endsWithIgnoreCase
(
filename
,
CLASSFILE_EXT
)
&&
(
filename
.
indexOf
(
'.'
)
==
(
filename
.
length
()
-
CLASSFILE_EXT
.
length
()));
}
/**
* Converts the filename to classname.
*
* @param filename filename to convert
* @return corresponding classname.
* @throws AssertionError if filename isn't valid filename for class file -
* {@link #isClassFile(String)}
*/
public
static
String
fileNameToClassName
(
String
filename
)
{
assert
isClassFile
(
filename
);
return
filename
.
substring
(
0
,
filename
.
length
()
-
CLASSFILE_EXT
.
length
())
.
replace
(
File
.
separatorChar
,
'.'
);
}
}
test/testlibrary/ctw/test/Bar.java
0 → 100644
浏览文件 @
b17e9bbd
public
class
Bar
{
private
static
void
staticMethod
()
{
}
public
void
method
()
{
}
protected
Bar
()
{
}
}
test/testlibrary/ctw/test/ClassesDirTest.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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 ClassesDirTest
* @bug 8012447
* @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src
* @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox ClassesDirTest Foo Bar
* @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
* @run main ClassesDirTest prepare
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes
* @run main ClassesDirTest check ctw.log
* @summary testing of CompileTheWorld :: classes in directory
* @author igor.ignatyev@oracle.com
*/
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
java.nio.file.StandardCopyOption
;
public
class
ClassesDirTest
extends
CtwTest
{
private
static
final
String
[]
SHOULD_CONTAIN
=
{
"# dir: classes"
,
"Done (2 classes, 6 methods, "
};
private
ClassesDirTest
()
{
super
(
SHOULD_CONTAIN
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
new
ClassesDirTest
().
run
(
args
);
}
protected
void
prepare
()
throws
Exception
{
String
path
=
"classes"
;
Files
.
createDirectory
(
Paths
.
get
(
path
));
Files
.
move
(
Paths
.
get
(
"Foo.class"
),
Paths
.
get
(
path
,
"Foo.class"
),
StandardCopyOption
.
REPLACE_EXISTING
);
Files
.
move
(
Paths
.
get
(
"Bar.class"
),
Paths
.
get
(
path
,
"Bar.class"
),
StandardCopyOption
.
REPLACE_EXISTING
);
}
}
test/testlibrary/ctw/test/ClassesListTest.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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 ClassesListTest
* @bug 8012447
* @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src
* @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox ClassesListTest Foo Bar
* @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
* @run main ClassesListTest prepare
* @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes.lst
* @run main ClassesListTest check ctw.log
* @summary testing of CompileTheWorld :: list of classes in file
* @author igor.ignatyev@oracle.com
*/
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
java.nio.file.StandardCopyOption
;
public
class
ClassesListTest
extends
CtwTest
{
private
static
final
String
[]
SHOULD_CONTAIN
=
{
"# list: classes.lst"
,
"Done (4 classes, "
};
private
ClassesListTest
()
{
super
(
SHOULD_CONTAIN
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
new
ClassesListTest
().
run
(
args
);
}
protected
void
prepare
()
throws
Exception
{
String
path
=
"classes.lst"
;
Files
.
copy
(
Paths
.
get
(
System
.
getProperty
(
"test.src"
),
path
),
Paths
.
get
(
path
),
StandardCopyOption
.
REPLACE_EXISTING
);
}
}
test/testlibrary/ctw/test/CtwTest.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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.
*/
import
java.util.List
;
import
java.util.Collections
;
import
java.util.ArrayList
;
import
java.io.File
;
import
java.io.Writer
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.io.BufferedReader
;
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
java.nio.file.StandardCopyOption
;
import
java.nio.charset.Charset
;
import
com.oracle.java.testlibrary.JDKToolFinder
;
import
com.oracle.java.testlibrary.OutputAnalyzer
;
public
abstract
class
CtwTest
{
protected
final
String
[]
shouldContain
;
protected
CtwTest
(
String
[]
shouldContain
)
{
this
.
shouldContain
=
shouldContain
;
}
public
void
run
(
String
[]
args
)
throws
Exception
{
if
(
args
.
length
==
0
)
{
throw
new
Error
(
"args is empty"
);
}
switch
(
args
[
0
])
{
case
"prepare"
:
prepare
();
break
;
case
"check"
:
check
(
args
);
break
;
default
:
throw
new
Error
(
"unregonized action -- "
+
args
[
0
]);
}
}
protected
void
prepare
()
throws
Exception
{
}
protected
void
check
(
String
[]
args
)
throws
Exception
{
if
(
args
.
length
<
2
)
{
throw
new
Error
(
"logfile isn't specified"
);
}
String
logfile
=
args
[
1
];
try
(
BufferedReader
r
=
Files
.
newBufferedReader
(
Paths
.
get
(
logfile
),
Charset
.
defaultCharset
()))
{
OutputAnalyzer
output
=
readOutput
(
r
);
for
(
String
test
:
shouldContain
)
{
output
.
shouldContain
(
test
);
}
}
}
private
static
OutputAnalyzer
readOutput
(
BufferedReader
reader
)
throws
IOException
{
StringBuilder
builder
=
new
StringBuilder
();
String
eol
=
String
.
format
(
"%n"
);
String
line
;
while
((
line
=
reader
.
readLine
())
!=
null
)
{
builder
.
append
(
line
);
builder
.
append
(
eol
);
}
return
new
OutputAnalyzer
(
builder
.
toString
(),
""
);
}
protected
void
dump
(
OutputAnalyzer
output
,
String
name
)
{
try
(
Writer
w
=
new
FileWriter
(
name
+
".out"
))
{
String
s
=
output
.
getStdout
();
w
.
write
(
s
,
s
.
length
(),
0
);
}
catch
(
IOException
io
)
{
io
.
printStackTrace
();
}
try
(
Writer
w
=
new
FileWriter
(
name
+
".err"
))
{
String
s
=
output
.
getStderr
();
w
.
write
(
s
,
s
.
length
(),
0
);
}
catch
(
IOException
io
)
{
io
.
printStackTrace
();
}
}
protected
ProcessBuilder
createJarProcessBuilder
(
String
...
command
)
throws
Exception
{
String
javapath
=
JDKToolFinder
.
getJDKTool
(
"jar"
);
ArrayList
<
String
>
args
=
new
ArrayList
<>();
args
.
add
(
javapath
);
Collections
.
addAll
(
args
,
command
);
return
new
ProcessBuilder
(
args
.
toArray
(
new
String
[
args
.
size
()]));
}
}
test/testlibrary/ctw/test/Foo.java
0 → 100644
浏览文件 @
b17e9bbd
public
class
Foo
{
private
static
void
staticMethod
()
{
}
public
void
method
()
{
}
protected
Foo
()
{
}
}
test/testlibrary/ctw/test/JarDirTest.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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 JarDirTest
* @bug 8012447
* @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src
* @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox JarDirTest Foo Bar
* @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
* @run main JarDirTest prepare
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld jars/*
* @run main JarDirTest check ctw.log
* @summary testing of CompileTheWorld :: jars in directory
* @author igor.ignatyev@oracle.com
*/
import
java.io.File
;
import
java.nio.file.Files
;
import
java.nio.file.Paths
;
import
com.oracle.java.testlibrary.OutputAnalyzer
;
public
class
JarDirTest
extends
CtwTest
{
private
static
final
String
[]
SHOULD_CONTAIN
=
{
"# jar_in_dir: jars"
,
"# jar: jars"
+
File
.
separator
+
"foo.jar"
,
"# jar: jars"
+
File
.
separator
+
"bar.jar"
,
"Done (4 classes, 12 methods, "
};
private
JarDirTest
()
{
super
(
SHOULD_CONTAIN
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
new
JarDirTest
().
run
(
args
);
}
protected
void
prepare
()
throws
Exception
{
String
path
=
"jars"
;
Files
.
createDirectory
(
Paths
.
get
(
path
));
ProcessBuilder
pb
=
createJarProcessBuilder
(
"cf"
,
"jars/foo.jar"
,
"Foo.class"
,
"Bar.class"
);
OutputAnalyzer
output
=
new
OutputAnalyzer
(
pb
.
start
());
dump
(
output
,
"ctw-foo.jar"
);
output
.
shouldHaveExitValue
(
0
);
pb
=
createJarProcessBuilder
(
"cf"
,
"jars/bar.jar"
,
"Foo.class"
,
"Bar.class"
);
output
=
new
OutputAnalyzer
(
pb
.
start
());
dump
(
output
,
"ctw-bar.jar"
);
output
.
shouldHaveExitValue
(
0
);
}
}
test/testlibrary/ctw/test/JarsTest.java
0 → 100644
浏览文件 @
b17e9bbd
/*
* Copyright (c) 2013, 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 JarsTest
* @bug 8012447
* @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src
* @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox JarsTest Foo Bar
* @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar
* @run main JarsTest prepare
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld foo.jar bar.jar
* @run main JarsTest check ctw.log
* @summary testing of CompileTheWorld :: jars
* @author igor.ignatyev@oracle.com
*/
import
com.oracle.java.testlibrary.OutputAnalyzer
;
public
class
JarsTest
extends
CtwTest
{
private
static
final
String
[]
SHOULD_CONTAIN
=
{
"# jar: foo.jar"
,
"# jar: bar.jar"
,
"Done (4 classes, 12 methods, "
};
private
JarsTest
()
{
super
(
SHOULD_CONTAIN
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
new
JarsTest
().
run
(
args
);
}
protected
void
prepare
()
throws
Exception
{
ProcessBuilder
pb
=
createJarProcessBuilder
(
"cf"
,
"foo.jar"
,
"Foo.class"
,
"Bar.class"
);
OutputAnalyzer
output
=
new
OutputAnalyzer
(
pb
.
start
());
dump
(
output
,
"ctw-foo.jar"
);
output
.
shouldHaveExitValue
(
0
);
pb
=
createJarProcessBuilder
(
"cf"
,
"bar.jar"
,
"Foo.class"
,
"Bar.class"
);
output
=
new
OutputAnalyzer
(
pb
.
start
());
dump
(
output
,
"ctw-bar.jar"
);
output
.
shouldHaveExitValue
(
0
);
}
}
test/testlibrary/ctw/test/classes.lst
0 → 100644
浏览文件 @
b17e9bbd
java.lang.String
java.lang.Object
Foo
Bar
test/testlibrary/whitebox/Makefile
0 → 100644
浏览文件 @
b17e9bbd
#
# Copyright (c) 2013, 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.
#
#
ifneq
"x$(ALT_BOOTDIR)" "x"
BOOTDIR
:=
$(ALT_BOOTDIR)
endif
ifeq
"x$(BOOTDIR)" "x"
JDK_HOME
:=
$(
shell
dirname
$(
shell
which java
))
/..
else
JDK_HOME
:=
$(BOOTDIR)
endif
SRC_DIR
=
./
BUILD_DIR
=
build
OUTPUT_DIR
=
$(BUILD_DIR)
/classes
JAVAC
=
$(JDK_HOME)
/bin/javac
JAR
=
$(JDK_HOME)
/bin/jar
SRC_FILES
=
$(
shell
find
$(SRC_DIR)
-name
'*.java'
)
.PHONY
:
filelist clean cleantmp
all
:
wb.jar cleantmp
wb.jar
:
filelist
@
mkdir
-p
$(OUTPUT_DIR)
$(JAVAC)
-sourcepath
$(SRC_DIR)
-d
$(OUTPUT_DIR)
-cp
$(OUTPUT_DIR)
@filelist
$(JAR)
cf wb.jar
-C
$(OUTPUT_DIR)
.
@
rm
-rf
$(OUTPUT_DIR)
filelist
:
$(SRC_FILES)
@
rm
-f
$@
@
echo
$(SRC_FILES)
>
$@
clean
:
cleantmp
@
rm
-rf
wb.jar
cleantmp
:
@
rm
-rf
filelist
@
rm
-rf
$(BUILD_DIR)
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录