Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell11
提交
b9eb40b4
D
dragonwell11
项目概览
openanolis
/
dragonwell11
通知
7
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell11
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b9eb40b4
编写于
1月 14, 2015
作者:
F
fzhinkin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8059342: Add test to cover JDK-8030976
Reviewed-by: kvn, iignatyev
上级
57020328
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
402 addition
and
0 deletion
+402
-0
hotspot/test/compiler/testlibrary/uncommontrap/Verifier.java
hotspot/test/compiler/testlibrary/uncommontrap/Verifier.java
+145
-0
hotspot/test/compiler/uncommontrap/TestUnstableIfTrap.java
hotspot/test/compiler/uncommontrap/TestUnstableIfTrap.java
+257
-0
未找到文件。
hotspot/test/compiler/testlibrary/uncommontrap/Verifier.java
0 → 100644
浏览文件 @
b9eb40b4
/*
* Copyright (c) 2014, 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
uncommontrap
;
import
java.io.FileReader
;
import
java.io.IOException
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Properties
;
import
java.util.regex.Pattern
;
import
com.oracle.java.testlibrary.Asserts
;
/**
* Utility tool aimed to verify presence or absence of specified uncommon trap
* in compilation log.
*/
public
class
Verifier
{
public
static
final
String
PROPERTIES_FILE_SUFFIX
=
".verify.properties"
;
public
static
final
String
VERIFICATION_SHOULD_BE_SKIPPED
=
"uncommon.trap.verification.skipped"
;
public
static
final
String
UNCOMMON_TRAP_NAME
=
"uncommon.trap.name"
;
public
static
final
String
UNCOMMON_TRAP_BCI
=
"uncommon.trap.bci"
;
public
static
final
String
UNCOMMON_TRAP_COMMENT
=
"uncommon.trap.comment"
;
public
static
final
String
UNCOMMON_TRAP_ACTION
=
"uncommon.trap.action"
;
public
static
final
String
UNCOMMON_TRAP_SHOULD_EMITTED
=
"uncommon.trap.emitted"
;
public
static
final
String
UNCOMMON_TRAP_SHOULD_FIRED
=
"uncommon.trap.fired"
;
private
static
final
String
EMITTED_TRAP_PATTERN
=
"<uncommon_trap bci='%s' reason='%s' action='%s' "
+
"comment='%s'"
;
private
static
final
String
FIRED_TRAP_PATTERN
=
"<uncommon_trap thread='[0-9]*' reason='%s' action='%s'"
;
private
static
final
String
JVMS_PATTERN
=
"<jvms bci='%s'"
;
public
static
void
main
(
String
args
[])
{
if
(
args
.
length
==
0
)
{
throw
new
Error
(
"At least one argument containing name of "
+
"compilation log file is expected"
);
}
for
(
String
compLogFile
:
args
)
{
try
{
verify
(
Paths
.
get
(
compLogFile
));
}
catch
(
IOException
e
)
{
throw
new
Error
(
"Unable to process compilation log."
,
e
);
}
}
}
private
static
void
verify
(
Path
compLogFile
)
throws
IOException
{
Path
propertiesFile
=
Paths
.
get
(
compLogFile
.
toString
()
+
PROPERTIES_FILE_SUFFIX
);
Properties
properties
=
new
Properties
();
properties
.
load
(
new
FileReader
(
propertiesFile
.
toFile
()));
if
(
Boolean
.
valueOf
(
properties
.
getProperty
(
VERIFICATION_SHOULD_BE_SKIPPED
,
"false"
)))
{
System
.
out
.
println
(
"Skipping verification for log file: "
+
compLogFile
.
toString
());
return
;
}
System
.
out
.
println
(
"Verifying log file: "
+
compLogFile
.
toString
());
List
<
String
>
compLogContent
=
Files
.
readAllLines
(
compLogFile
);
verifyUncommonTrapEmitted
(
properties
,
compLogContent
);
verifyUncommonTrapFired
(
properties
,
compLogContent
);
}
private
static
void
verifyUncommonTrapEmitted
(
Properties
properties
,
List
<
String
>
compLogContent
)
{
String
emittedTrapRE
=
String
.
format
(
EMITTED_TRAP_PATTERN
,
properties
.
getProperty
(
UNCOMMON_TRAP_BCI
,
".*"
),
properties
.
getProperty
(
UNCOMMON_TRAP_NAME
,
".*"
),
properties
.
getProperty
(
UNCOMMON_TRAP_ACTION
,
".*"
),
properties
.
getProperty
(
UNCOMMON_TRAP_COMMENT
,
".*"
));
Pattern
pattern
=
Pattern
.
compile
(
emittedTrapRE
);
long
trapsCount
=
compLogContent
.
stream
()
.
filter
(
line
->
pattern
.
matcher
(
line
).
find
())
.
count
();
boolean
shouldBeEmitted
=
Boolean
.
valueOf
(
properties
.
getProperty
(
UNCOMMON_TRAP_SHOULD_EMITTED
));
Asserts
.
assertEQ
(
shouldBeEmitted
,
trapsCount
>
0
,
String
.
format
(
"Uncommon trap that matches following string in compilation log"
+
" should %sbe emitted: %s."
,
(
shouldBeEmitted
?
" "
:
"not "
),
emittedTrapRE
));
}
private
static
void
verifyUncommonTrapFired
(
Properties
properties
,
List
<
String
>
compLogContent
)
{
String
firedTrapRE
=
String
.
format
(
FIRED_TRAP_PATTERN
,
properties
.
getProperty
(
UNCOMMON_TRAP_NAME
,
".*"
),
properties
.
getProperty
(
UNCOMMON_TRAP_ACTION
,
".*"
));
String
jvmsRE
=
String
.
format
(
JVMS_PATTERN
,
properties
.
getProperty
(
UNCOMMON_TRAP_BCI
,
".*"
));
boolean
trapFired
=
false
;
Pattern
firedTrapPattern
=
Pattern
.
compile
(
firedTrapRE
);
Pattern
jvmsPattern
=
Pattern
.
compile
(
jvmsRE
);
Iterator
<
String
>
iterator
=
compLogContent
.
iterator
();
while
(
iterator
.
hasNext
()
&&
!
trapFired
)
{
trapFired
=
firedTrapPattern
.
matcher
(
iterator
.
next
()).
find
()
&&
jvmsPattern
.
matcher
(
iterator
.
next
()).
find
();
}
boolean
shouldBeFired
=
Boolean
.
valueOf
(
properties
.
getProperty
(
UNCOMMON_TRAP_SHOULD_FIRED
));
Asserts
.
assertEQ
(
shouldBeFired
,
trapFired
,
String
.
format
(
"Uncommon trap that matches following string in compilation log"
+
" should %sbe fired: %s."
,
(
shouldBeFired
?
""
:
"not "
),
firedTrapRE
));
}
}
hotspot/test/compiler/uncommontrap/TestUnstableIfTrap.java
0 → 100644
浏览文件 @
b9eb40b4
/*
* Copyright (c) 2014, 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.io.File
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.lang.reflect.Method
;
import
java.util.Properties
;
import
com.oracle.java.testlibrary.ByteCodeLoader
;
import
com.oracle.java.testlibrary.Platform
;
import
jdk.internal.org.objectweb.asm.ClassVisitor
;
import
jdk.internal.org.objectweb.asm.ClassWriter
;
import
jdk.internal.org.objectweb.asm.Label
;
import
jdk.internal.org.objectweb.asm.MethodVisitor
;
import
static
jdk
.
internal
.
org
.
objectweb
.
asm
.
Opcodes
.*;
import
sun.hotspot.WhiteBox
;
import
uncommontrap.Verifier
;
/*
* @test
* @bug 8030976 8059226
* @library /testlibrary /compiler/testlibrary /../../test/lib
* @build TestUnstableIfTrap com.oracle.java.testlibrary.* uncommontrap.Verifier
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm -Xbatch -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,UnstableIfExecutable.test
* -XX:LogFile=always_taken_not_fired.xml
* TestUnstableIfTrap ALWAYS_TAKEN false
* @run main/othervm -Xbatch -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,UnstableIfExecutable.test
* -XX:LogFile=always_taken_fired.xml
* TestUnstableIfTrap ALWAYS_TAKEN true
* @run main/othervm -Xbatch -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,UnstableIfExecutable.test
* -XX:LogFile=never_taken_not_fired.xml
* TestUnstableIfTrap NEVER_TAKEN false
* @run main/othervm -Xbatch -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI -XX:+LogCompilation
* -XX:CompileCommand=compileonly,UnstableIfExecutable.test
* -XX:LogFile=never_taken_fired.xml
* TestUnstableIfTrap NEVER_TAKEN true
* @run main uncommontrap.Verifier always_taken_not_fired.xml
* always_taken_fired.xml
* never_taken_not_fired.xml
* never_taken_fired.xml
*/
public
class
TestUnstableIfTrap
{
private
static
final
WhiteBox
WB
=
WhiteBox
.
getWhiteBox
();
private
static
final
String
CLASS_NAME
=
"UnstableIfExecutable"
;
private
static
final
String
METHOD_NAME
=
"test"
;
private
static
final
String
FIELD_NAME
=
"field"
;
private
static
final
int
ITERATIONS
=
1_000_000
;
// There is no dependency on particular class file version, so it could be
// set to any version (if you're updating this test for Java 42).
private
static
final
int
CLASS_FILE_VERSION
=
49
;
private
static
final
int
MAX_TIER
=
4
;
// This test aimed to verify that uncommon trap with reason "unstable_if"
// is emitted when method that contain control-flow divergence such that
// one of two branches is never taken (and other one is taken always).
// C2 will made a decision whether or not the branch was ever taken
// depending on method's profile.
// If profile was collected for a few method's invocations, then C2 will not
// trust in branches' probabilities and the tested trap won't be emitted.
// In fact, a method has to be invoked at least 40 time at the day when this
// comment was written (see Parse::dynamic_branch_prediction for an actual
// value). It would be to implementation dependent to use "40" as
// a threshold value in the test, so in order to improve test's robustness
// the threshold value is 1000: if the tested method was compiled by C2
// before it was invoked 1000 times, then we won't verify that trap was
// emitted and fired.
private
static
final
int
MIN_INVOCATIONS_BEFORE_C2_COMPILATION
=
1000
;
/**
* Description of test case parameters and uncommon trap that will
* be emitted during tested method compilation.
*/
private
static
enum
TestCaseName
{
ALWAYS_TAKEN
(
false
,
"taken always"
),
NEVER_TAKEN
(
true
,
"taken never"
);
TestCaseName
(
boolean
predicate
,
String
comment
)
{
this
.
predicate
=
predicate
;
this
.
comment
=
comment
;
}
public
final
boolean
predicate
;
public
final
String
name
=
"unstable_if"
;
public
final
String
comment
;
}
public
static
void
main
(
String
args
[])
{
if
(
args
.
length
!=
2
)
{
throw
new
Error
(
"Expected two arguments: test case name and a "
+
"boolean determining if uncommon trap should be fired."
);
}
test
(
TestCaseName
.
valueOf
(
args
[
0
]),
Boolean
.
valueOf
(
args
[
1
]));
}
private
static
void
test
(
TestCaseName
testCase
,
boolean
shouldBeFired
)
{
Method
testMethod
;
Label
unstableIfLocation
=
new
Label
();
boolean
shouldBeEmitted
;
boolean
compiledToEarly
=
false
;
try
{
Class
testClass
=
ByteCodeLoader
.
load
(
CLASS_NAME
,
generateTest
(
unstableIfLocation
));
testMethod
=
testClass
.
getDeclaredMethod
(
METHOD_NAME
,
boolean
.
class
);
for
(
int
i
=
0
;
i
<
ITERATIONS
;
i
++)
{
testMethod
.
invoke
(
null
,
testCase
.
predicate
);
if
(
i
<
MIN_INVOCATIONS_BEFORE_C2_COMPILATION
&&
isMethodCompiledByC2
(
testMethod
))
{
compiledToEarly
=
true
;
// There is no sense in further invocations: we already
// decided to avoid verification.
break
;
}
}
// We're checking that trap should be emitted (i.e. it was compiled
// by C2) before the trap is fired, because otherwise the nmethod
// will be deoptimized and isMethodCompiledByC2 will return false.
shouldBeEmitted
=
isMethodCompiledByC2
(
testMethod
)
&&
!
compiledToEarly
;
if
(
shouldBeFired
)
{
testMethod
.
invoke
(
null
,
!
testCase
.
predicate
);
}
}
catch
(
ReflectiveOperationException
e
)
{
throw
new
Error
(
"Test case should be generated, loaded and executed"
+
" without any issues."
,
e
);
}
shouldBeFired
&=
shouldBeEmitted
;
Properties
properties
=
new
Properties
();
properties
.
setProperty
(
Verifier
.
VERIFICATION_SHOULD_BE_SKIPPED
,
Boolean
.
toString
(
compiledToEarly
));
properties
.
setProperty
(
Verifier
.
UNCOMMON_TRAP_SHOULD_EMITTED
,
Boolean
.
toString
(
shouldBeEmitted
));
properties
.
setProperty
(
Verifier
.
UNCOMMON_TRAP_SHOULD_FIRED
,
Boolean
.
toString
(
shouldBeFired
));
properties
.
setProperty
(
Verifier
.
UNCOMMON_TRAP_NAME
,
testCase
.
name
);
properties
.
setProperty
(
Verifier
.
UNCOMMON_TRAP_COMMENT
,
testCase
.
comment
);
properties
.
setProperty
(
Verifier
.
UNCOMMON_TRAP_BCI
,
Integer
.
toString
(
unstableIfLocation
.
getOffset
()));
properties
.
list
(
System
.
out
);
File
f
=
new
File
(
WB
.
getStringVMFlag
(
"LogFile"
)
+
Verifier
.
PROPERTIES_FILE_SUFFIX
);
try
(
FileWriter
wr
=
new
FileWriter
(
f
))
{
properties
.
store
(
wr
,
""
);
}
catch
(
IOException
e
)
{
throw
new
Error
(
"Unable to store test properties."
,
e
);
}
}
private
static
boolean
isMethodCompiledByC2
(
Method
m
)
{
boolean
isTiered
=
WB
.
getBooleanVMFlag
(
"TieredCompilation"
);
boolean
isMethodCompiled
=
WB
.
isMethodCompiled
(
m
);
boolean
isMethodCompiledAtMaxTier
=
WB
.
getMethodCompilationLevel
(
m
)
==
MAX_TIER
;
return
Platform
.
isServer
()
&&
isMethodCompiled
&&
(!
isTiered
||
isMethodCompiledAtMaxTier
);
}
/**
* Generates class with name {@code CLASS_NAME}, which will contain a
* static method {@code METHOD_NAME}:
*
* <pre>{@code
* public abstract class UnstableIfExecutable {
* private static int field = 0;
*
* public static void test(boolean alwaysTrue) {
* if (alwaysTrue) {
* field++;
* } else {
* field--;
* }
* }
* }
* }</pre>
*
* @return generated bytecode.
*/
private
static
byte
[]
generateTest
(
Label
unstableIfLocation
)
{
ClassWriter
cw
=
new
ClassWriter
(
ClassWriter
.
COMPUTE_FRAMES
);
cw
.
visit
(
CLASS_FILE_VERSION
,
ACC_PUBLIC
|
ACC_ABSTRACT
,
CLASS_NAME
,
null
,
"java/lang/Object"
,
null
);
cw
.
visitField
(
ACC_PUBLIC
|
ACC_STATIC
|
ACC_VOLATILE
,
FIELD_NAME
,
"I"
,
null
,
Integer
.
valueOf
(
0
));
generateTestMethod
(
cw
,
unstableIfLocation
);
return
cw
.
toByteArray
();
}
private
static
void
generateTestMethod
(
ClassVisitor
cv
,
Label
unstableIfLocation
)
{
MethodVisitor
mv
=
cv
.
visitMethod
(
ACC_PUBLIC
|
ACC_STATIC
,
METHOD_NAME
,
"(Z)V"
,
null
,
null
);
mv
.
visitCode
();
Label
end
=
new
Label
();
Label
falseBranch
=
new
Label
();
// push "field" field's value and 1 to stack
mv
.
visitFieldInsn
(
GETSTATIC
,
CLASS_NAME
,
FIELD_NAME
,
"I"
);
mv
.
visitInsn
(
ICONST_1
);
// load argument's value
mv
.
visitVarInsn
(
ILOAD
,
0
);
// alwaysTrue
// here is our unstable if
mv
.
visitLabel
(
unstableIfLocation
);
mv
.
visitJumpInsn
(
IFEQ
,
falseBranch
);
// increment on "true"
mv
.
visitInsn
(
IADD
);
mv
.
visitJumpInsn
(
GOTO
,
end
);
// decrement on "false"
mv
.
visitLabel
(
falseBranch
);
mv
.
visitInsn
(
ISUB
);
mv
.
visitLabel
(
end
);
// bye bye
mv
.
visitInsn
(
RETURN
);
mv
.
visitMaxs
(
0
,
0
);
mv
.
visitEnd
();
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录