Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_hotspot
提交
f6759736
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看板
提交
f6759736
编写于
4月 21, 2016
作者:
S
shshahma
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8141551: C2 can not handle returns with inccompatible interface arrays
Reviewed-by: kvn
上级
7815e8f0
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
436 addition
and
19 deletion
+436
-19
src/share/vm/opto/cfgnode.cpp
src/share/vm/opto/cfgnode.cpp
+16
-9
src/share/vm/opto/parse1.cpp
src/share/vm/opto/parse1.cpp
+21
-7
src/share/vm/opto/type.cpp
src/share/vm/opto/type.cpp
+43
-3
src/share/vm/opto/type.hpp
src/share/vm/opto/type.hpp
+5
-0
test/compiler/types/TestMeetIncompatibleInterfaceArrays.java
test/compiler/types/TestMeetIncompatibleInterfaceArrays.java
+351
-0
未找到文件。
src/share/vm/opto/cfgnode.cpp
浏览文件 @
f6759736
...
...
@@ -973,7 +973,7 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const {
#ifdef ASSERT
// The following logic has been moved into TypeOopPtr::filter.
const
Type
*
jt
=
t
->
join_speculative
(
_type
);
if
(
jt
->
empty
()
)
{
// Emptied out???
if
(
jt
->
empty
()
)
{
// Emptied out???
// Check for evil case of 't' being a class and '_type' expecting an
// interface. This can happen because the bytecodes do not contain
...
...
@@ -984,14 +984,21 @@ const Type *PhiNode::Value( PhaseTransform *phase ) const {
// be 'I' or 'j/l/O'. Thus we'll pick 'j/l/O'. If this then flows
// into a Phi which "knows" it's an Interface type we'll have to
// uplift the type.
if
(
!
t
->
empty
()
&&
ttip
&&
ttip
->
is_loaded
()
&&
ttip
->
klass
()
->
is_interface
()
)
{
assert
(
ft
==
_type
,
""
);
}
// Uplift to interface
else
if
(
!
t
->
empty
()
&&
ttkp
&&
ttkp
->
is_loaded
()
&&
ttkp
->
klass
()
->
is_interface
()
)
{
assert
(
ft
==
_type
,
""
);
}
// Uplift to interface
// Otherwise it's something stupid like non-overlapping int ranges
// found on dying counted loops.
else
{
assert
(
ft
==
Type
::
TOP
,
""
);
}
// Canonical empty value
if
(
!
t
->
empty
()
&&
ttip
&&
ttip
->
is_loaded
()
&&
ttip
->
klass
()
->
is_interface
())
{
assert
(
ft
==
_type
,
""
);
// Uplift to interface
}
else
if
(
!
t
->
empty
()
&&
ttkp
&&
ttkp
->
is_loaded
()
&&
ttkp
->
klass
()
->
is_interface
())
{
assert
(
ft
==
_type
,
""
);
// Uplift to interface
}
else
{
// We also have to handle 'evil cases' of interface- vs. class-arrays
Type
::
get_arrays_base_elements
(
jt
,
_type
,
NULL
,
&
ttip
);
if
(
!
t
->
empty
()
&&
ttip
!=
NULL
&&
ttip
->
is_loaded
()
&&
ttip
->
klass
()
->
is_interface
())
{
assert
(
ft
==
_type
,
""
);
// Uplift to array of interface
}
else
{
// Otherwise it's something stupid like non-overlapping int ranges
// found on dying counted loops.
assert
(
ft
==
Type
::
TOP
,
""
);
// Canonical empty value
}
}
}
else
{
...
...
src/share/vm/opto/parse1.cpp
浏览文件 @
f6759736
...
...
@@ -962,13 +962,18 @@ void Parse::do_exits() {
// In case of concurrent class loading, the type we set for the
// ret_phi in build_exits() may have been too optimistic and the
// ret_phi may be top now.
#ifdef ASSERT
// Otherwise, we've encountered an error and have to mark the method as
// not compilable. Just using an assertion instead would be dangerous
// as this could lead to an infinite compile loop in non-debug builds.
{
MutexLockerEx
ml
(
Compile_lock
,
Mutex
::
_no_safepoint_check_flag
);
assert
(
ret_type
->
isa_ptr
()
&&
C
->
env
()
->
system_dictionary_modification_counter_changed
(),
"return value must be well defined"
);
if
(
C
->
env
()
->
system_dictionary_modification_counter_changed
())
{
C
->
record_failure
(
C2Compiler
::
retry_class_loading_during_parsing
());
}
else
{
C
->
record_method_not_compilable
(
"Can't determine return type."
);
}
}
#endif
C
->
record_failure
(
C2Compiler
::
retry_class_loading_during_parsing
());
return
;
}
_exits
.
push_node
(
ret_type
->
basic_type
(),
ret_phi
);
}
...
...
@@ -2093,15 +2098,24 @@ void Parse::return_current(Node* value) {
// here.
Node
*
phi
=
_exits
.
argument
(
0
);
const
TypeInstPtr
*
tr
=
phi
->
bottom_type
()
->
isa_instptr
();
if
(
tr
&&
tr
->
klass
()
->
is_loaded
()
&&
tr
->
klass
()
->
is_interface
()
)
{
if
(
tr
&&
tr
->
klass
()
->
is_loaded
()
&&
tr
->
klass
()
->
is_interface
())
{
const
TypeInstPtr
*
tp
=
value
->
bottom_type
()
->
isa_instptr
();
if
(
tp
&&
tp
->
klass
()
->
is_loaded
()
&&
!
tp
->
klass
()
->
is_interface
())
{
// sharpen the type eagerly; this eases certain assert checking
if
(
tp
->
higher_equal
(
TypeInstPtr
::
NOTNULL
))
tr
=
tr
->
join_speculative
(
TypeInstPtr
::
NOTNULL
)
->
is_instptr
();
value
=
_gvn
.
transform
(
new
(
C
)
CheckCastPPNode
(
0
,
value
,
tr
));
value
=
_gvn
.
transform
(
new
(
C
)
CheckCastPPNode
(
0
,
value
,
tr
));
}
}
else
{
// Also handle returns of oop-arrays to an arrays-of-interface return
const
TypeInstPtr
*
phi_tip
;
const
TypeInstPtr
*
val_tip
;
Type
::
get_arrays_base_elements
(
phi
->
bottom_type
(),
value
->
bottom_type
(),
&
phi_tip
,
&
val_tip
);
if
(
phi_tip
!=
NULL
&&
phi_tip
->
is_loaded
()
&&
phi_tip
->
klass
()
->
is_interface
()
&&
val_tip
!=
NULL
&&
val_tip
->
is_loaded
()
&&
!
val_tip
->
klass
()
->
is_interface
())
{
value
=
_gvn
.
transform
(
new
(
C
)
CheckCastPPNode
(
0
,
value
,
phi
->
bottom_type
()));
}
}
phi
->
add_req
(
value
);
...
...
src/share/vm/opto/type.cpp
浏览文件 @
f6759736
...
...
@@ -149,6 +149,33 @@ BasicType Type::array_element_basic_type() const {
return
bt
;
}
// For two instance arrays of same dimension, return the base element types.
// Otherwise or if the arrays have different dimensions, return NULL.
void
Type
::
get_arrays_base_elements
(
const
Type
*
a1
,
const
Type
*
a2
,
const
TypeInstPtr
**
e1
,
const
TypeInstPtr
**
e2
)
{
if
(
e1
)
*
e1
=
NULL
;
if
(
e2
)
*
e2
=
NULL
;
const
TypeAryPtr
*
a1tap
=
(
a1
==
NULL
)
?
NULL
:
a1
->
isa_aryptr
();
const
TypeAryPtr
*
a2tap
=
(
a2
==
NULL
)
?
NULL
:
a2
->
isa_aryptr
();
if
(
a1tap
!=
NULL
&&
a2tap
!=
NULL
)
{
// Handle multidimensional arrays
const
TypePtr
*
a1tp
=
a1tap
->
elem
()
->
make_ptr
();
const
TypePtr
*
a2tp
=
a2tap
->
elem
()
->
make_ptr
();
while
(
a1tp
&&
a1tp
->
isa_aryptr
()
&&
a2tp
&&
a2tp
->
isa_aryptr
())
{
a1tap
=
a1tp
->
is_aryptr
();
a2tap
=
a2tp
->
is_aryptr
();
a1tp
=
a1tap
->
elem
()
->
make_ptr
();
a2tp
=
a2tap
->
elem
()
->
make_ptr
();
}
if
(
a1tp
&&
a1tp
->
isa_instptr
()
&&
a2tp
&&
a2tp
->
isa_instptr
())
{
if
(
e1
)
*
e1
=
a1tp
->
is_instptr
();
if
(
e2
)
*
e2
=
a2tp
->
is_instptr
();
}
}
}
//---------------------------get_typeflow_type---------------------------------
// Import a type produced by ciTypeFlow.
const
Type
*
Type
::
get_typeflow_type
(
ciType
*
type
)
{
...
...
@@ -1982,7 +2009,11 @@ const Type* TypeAry::remove_speculative() const {
bool
TypeAry
::
interface_vs_oop
(
const
Type
*
t
)
const
{
const
TypeAry
*
t_ary
=
t
->
is_ary
();
if
(
t_ary
)
{
return
_elem
->
interface_vs_oop
(
t_ary
->
_elem
);
const
TypePtr
*
this_ptr
=
_elem
->
make_ptr
();
// In case we have narrow_oops
const
TypePtr
*
t_ptr
=
t_ary
->
_elem
->
make_ptr
();
if
(
this_ptr
!=
NULL
&&
t_ptr
!=
NULL
)
{
return
this_ptr
->
interface_vs_oop
(
t_ptr
);
}
}
return
false
;
}
...
...
@@ -2834,8 +2865,17 @@ const Type *TypeOopPtr::filter_helper(const Type *kills, bool include_speculativ
// be 'I' or 'j/l/O'. Thus we'll pick 'j/l/O'. If this then flows
// into a Phi which "knows" it's an Interface type we'll have to
// uplift the type.
if
(
!
empty
()
&&
ktip
!=
NULL
&&
ktip
->
is_loaded
()
&&
ktip
->
klass
()
->
is_interface
())
return
kills
;
// Uplift to interface
if
(
!
empty
())
{
if
(
ktip
!=
NULL
&&
ktip
->
is_loaded
()
&&
ktip
->
klass
()
->
is_interface
())
{
return
kills
;
// Uplift to interface
}
// Also check for evil cases of 'this' being a class array
// and 'kills' expecting an array of interfaces.
Type
::
get_arrays_base_elements
(
ft
,
kills
,
NULL
,
&
ktip
);
if
(
ktip
!=
NULL
&&
ktip
->
is_loaded
()
&&
ktip
->
klass
()
->
is_interface
())
{
return
kills
;
// Uplift to array of interface
}
}
return
Type
::
TOP
;
// Canonical empty value
}
...
...
src/share/vm/opto/type.hpp
浏览文件 @
f6759736
...
...
@@ -367,6 +367,11 @@ public:
return
_const_basic_type
[
type
];
}
// For two instance arrays of same dimension, return the base element types.
// Otherwise or if the arrays have different dimensions, return NULL.
static
void
get_arrays_base_elements
(
const
Type
*
a1
,
const
Type
*
a2
,
const
TypeInstPtr
**
e1
,
const
TypeInstPtr
**
e2
);
// Mapping to the array element's basic type.
BasicType
array_element_basic_type
()
const
;
...
...
test/compiler/types/TestMeetIncompatibleInterfaceArrays.java
0 → 100644
浏览文件 @
f6759736
/*
* Copyright 2015 SAP AG. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8141551
* @summary C2 can not handle returns with inccompatible interface arrays
* @library /testlibrary /testlibrary/whitebox/
* @build sun.hotspot.WhiteBox
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
* @run main/othervm
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -Xbatch
* -XX:CompileThreshold=1
* -XX:-TieredCompilation
* -XX:CICompilerCount=1
* -XX:+PrintCompilation
* -XX:+PrintInlining
* -XX:CompileCommand=compileonly,MeetIncompatibleInterfaceArrays*.run
* -XX:CompileCommand=dontinline,TestMeetIncompatibleInterfaceArrays$Helper.createI2*
* -XX:CompileCommand=quiet
* TestMeetIncompatibleInterfaceArrays 0
* @run main/othervm
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -Xbatch
* -XX:CompileThreshold=1
* -XX:-TieredCompilation
* -XX:CICompilerCount=1
* -XX:+PrintCompilation
* -XX:+PrintInlining
* -XX:CompileCommand=compileonly,MeetIncompatibleInterfaceArrays*.run
* -XX:CompileCommand=inline,TestMeetIncompatibleInterfaceArrays$Helper.createI2*
* -XX:CompileCommand=quiet
* TestMeetIncompatibleInterfaceArrays 1
* @run main/othervm
* -Xbootclasspath/a:.
* -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI
* -Xbatch
* -XX:CompileThreshold=1
* -XX:Tier0InvokeNotifyFreqLog=0 -XX:Tier2InvokeNotifyFreqLog=0 -XX:Tier3InvokeNotifyFreqLog=0 -XX:Tier23InlineeNotifyFreqLog=0
* -XX:Tier3InvocationThreshold=2 -XX:Tier3MinInvocationThreshold=2 -XX:Tier3CompileThreshold=2
* -XX:Tier4InvocationThreshold=1 -XX:Tier4MinInvocationThreshold=1 -XX:Tier4CompileThreshold=1
* -XX:+TieredCompilation
* -XX:CICompilerCount=2
* -XX:+PrintCompilation
* -XX:+PrintInlining
* -XX:CompileCommand=compileonly,MeetIncompatibleInterfaceArrays*.run
* -XX:CompileCommand=compileonly,TestMeetIncompatibleInterfaceArrays$Helper.createI2*
* -XX:CompileCommand=inline,TestMeetIncompatibleInterfaceArrays$Helper.createI2*
* -XX:CompileCommand=quiet
* TestMeetIncompatibleInterfaceArrays 2
*
* @author volker.simonis@gmail.com
*/
import
java.io.FileOutputStream
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
jdk.internal.org.objectweb.asm.ClassWriter
;
import
jdk.internal.org.objectweb.asm.MethodVisitor
;
import
static
jdk
.
internal
.
org
.
objectweb
.
asm
.
Opcodes
.*;
import
sun.hotspot.WhiteBox
;
public
class
TestMeetIncompatibleInterfaceArrays
extends
ClassLoader
{
private
static
final
WhiteBox
WB
=
WhiteBox
.
getWhiteBox
();
public
static
interface
I1
{
public
String
getName
();
}
public
static
interface
I2
{
public
String
getName
();
}
public
static
class
I2C
implements
I2
{
public
String
getName
()
{
return
"I2"
;}
}
public
static
class
I21C
implements
I2
,
I1
{
public
String
getName
()
{
return
"I2 and I1"
;}
}
public
static
class
Helper
{
public
static
I2
createI2Array0
()
{
return
new
I2C
();
}
public
static
I2
[]
createI2Array1
()
{
return
new
I2C
[]
{
new
I2C
()
};
}
public
static
I2
[][]
createI2Array2
()
{
return
new
I2C
[][]
{
new
I2C
[]
{
new
I2C
()
}
};
}
public
static
I2
[][][]
createI2Array3
()
{
return
new
I2C
[][][]
{
new
I2C
[][]
{
new
I2C
[]
{
new
I2C
()
}
}
};
}
public
static
I2
[][][][]
createI2Array4
()
{
return
new
I2C
[][][][]
{
new
I2C
[][][]
{
new
I2C
[][]
{
new
I2C
[]
{
new
I2C
()
}
}
}
};
}
public
static
I2
[][][][][]
createI2Array5
()
{
return
new
I2C
[][][][][]
{
new
I2C
[][][][]
{
new
I2C
[][][]
{
new
I2C
[][]
{
new
I2C
[]
{
new
I2C
()
}
}
}
}
};
}
public
static
I2
createI21Array0
()
{
return
new
I21C
();
}
public
static
I2
[]
createI21Array1
()
{
return
new
I21C
[]
{
new
I21C
()
};
}
public
static
I2
[][]
createI21Array2
()
{
return
new
I21C
[][]
{
new
I21C
[]
{
new
I21C
()
}
};
}
public
static
I2
[][][]
createI21Array3
()
{
return
new
I21C
[][][]
{
new
I21C
[][]
{
new
I21C
[]
{
new
I21C
()
}
}
};
}
public
static
I2
[][][][]
createI21Array4
()
{
return
new
I21C
[][][][]
{
new
I21C
[][][]
{
new
I21C
[][]
{
new
I21C
[]
{
new
I21C
()
}
}
}
};
}
public
static
I2
[][][][][]
createI21Array5
()
{
return
new
I21C
[][][][][]
{
new
I21C
[][][][]
{
new
I21C
[][][]
{
new
I21C
[][]
{
new
I21C
[]
{
new
I21C
()
}
}
}
}
};
}
}
// Location for the generated class files
public
static
final
String
PATH
=
System
.
getProperty
(
"test.classes"
,
"."
)
+
java
.
io
.
File
.
separator
;
/*
* With 'good == false' this helper method creates the following classes
* (using the nested 'Helper' class and the nested interfaces 'I1' and 'I2').
* For brevity I omit the enclosing class 'TestMeetIncompatibleInterfaceArrays' in the
* following examples:
*
* public class MeetIncompatibleInterfaceArrays0ASM {
* public static I1 run() {
* return Helper.createI2Array0(); // returns I2
* }
* public static void test() {
* I1 i1 = run();
* System.out.println(i1.getName());
* }
* }
* public class MeetIncompatibleInterfaceArrays1ASM {
* public static I1[] run() {
* return Helper.createI2Array1(); // returns I2[]
* }
* public static void test() {
* I1[] i1 = run();
* System.out.println(i1[0].getName());
* }
* }
* ...
* // MeetIncompatibleInterfaceArrays4ASM is special because it creates
* // an illegal class which will be rejected by the verifier.
* public class MeetIncompatibleInterfaceArrays4ASM {
* public static I1[][][][] run() {
* return Helper.createI2Array3(); // returns I1[][][] which gives a verifier error because return expects I1[][][][]
* }
* public static void test() {
* I1[][][][][] i1 = run();
* System.out.println(i1[0][0][0][0][0].getName());
* }
* ...
* public class MeetIncompatibleInterfaceArrays5ASM {
* public static I1[][][][][] run() {
* return Helper.createI2Array5(); // returns I2[][][][][]
* }
* public static void test() {
* I1[][][][][] i1 = run();
* System.out.println(i1[0][0][0][0][0].getName());
* }
* }
*
* Notice that this is not legal Java code. We would have to use a cast in "run()" to make it legal:
*
* public static I1[] run() {
* return (I1[])Helper.createI2Array1(); // returns I2[]
* }
*
* But in pure bytecode, the "run()" methods are perfectly legal:
*
* public static I1[] run();
* Code:
* 0: invokestatic #16 // Method Helper.createI2Array1:()[LI2;
* 3: areturn
*
* The "test()" method calls the "getName()" function from I1 on the objects returned by "run()".
* This will epectedly fail with an "IncompatibleClassChangeError" because the objects returned
* by "run()" (and by createI2Array()) are actually of type "I2C" and only implement "I2" but not "I1".
*
*
* With 'good == true' this helper method will create the following classes:
*
* public class MeetIncompatibleInterfaceArraysGood0ASM {
* public static I1 run() {
* return Helper.createI21Array0(); // returns I2
* }
* public static void test() {
* I1 i1 = run();
* System.out.println(i1.getName());
* }
* }
*
* Calling "test()" on these objects will succeed and output "I2 and I1" because now the "run()"
* method calls "createI21Array()" which actually return an object (or an array of objects) of
* type "I21C" which implements both "I2" and "I1".
*
* Notice that at the bytecode level, the code for the "run()" and "test()" methods in
* "MeetIncompatibleInterfaceArraysASM" and "MeetIncompatibleInterfaceArraysGoodASM" look exactly
* the same. I.e. the verifier has no chance to verify if the I2 object returned by "createI1Array()"
* or "createI21Array()" implements "I1" or not. That's actually the reason why both versions of
* generated classes are legal from a verifier point of view.
*
*/
static
void
generateTestClass
(
int
dim
,
boolean
good
)
throws
Exception
{
String
baseClassName
=
"MeetIncompatibleInterfaceArrays"
;
if
(
good
)
baseClassName
+=
"Good"
;
String
createName
=
"createI2"
+
(
good
?
"1"
:
""
)
+
"Array"
;
String
a
=
""
;
for
(
int
i
=
0
;
i
<
dim
;
i
++)
a
+=
"["
;
ClassWriter
cw
=
new
ClassWriter
(
ClassWriter
.
COMPUTE_FRAMES
);
cw
.
visit
(
V1_8
,
ACC_PUBLIC
,
baseClassName
+
dim
+
"ASM"
,
null
,
"java/lang/Object"
,
null
);
MethodVisitor
constr
=
cw
.
visitMethod
(
ACC_PUBLIC
,
"<init>"
,
"()V"
,
null
,
null
);
constr
.
visitCode
();
constr
.
visitVarInsn
(
ALOAD
,
0
);
constr
.
visitMethodInsn
(
INVOKESPECIAL
,
"java/lang/Object"
,
"<init>"
,
"()V"
,
false
);
constr
.
visitInsn
(
RETURN
);
constr
.
visitMaxs
(
0
,
0
);
constr
.
visitEnd
();
MethodVisitor
run
=
cw
.
visitMethod
(
ACC_PUBLIC
|
ACC_STATIC
,
"run"
,
"()"
+
a
+
"LTestMeetIncompatibleInterfaceArrays$I1;"
,
null
,
null
);
run
.
visitCode
();
if
(
dim
==
4
)
{
run
.
visitMethodInsn
(
INVOKESTATIC
,
"TestMeetIncompatibleInterfaceArrays$Helper"
,
createName
+
3
,
"()"
+
"[[["
+
"LTestMeetIncompatibleInterfaceArrays$I2;"
,
false
);
}
else
{
run
.
visitMethodInsn
(
INVOKESTATIC
,
"TestMeetIncompatibleInterfaceArrays$Helper"
,
createName
+
dim
,
"()"
+
a
+
"LTestMeetIncompatibleInterfaceArrays$I2;"
,
false
);
}
run
.
visitInsn
(
ARETURN
);
run
.
visitMaxs
(
0
,
0
);
run
.
visitEnd
();
MethodVisitor
test
=
cw
.
visitMethod
(
ACC_PUBLIC
|
ACC_STATIC
,
"test"
,
"()V"
,
null
,
null
);
test
.
visitCode
();
test
.
visitMethodInsn
(
INVOKESTATIC
,
baseClassName
+
dim
+
"ASM"
,
"run"
,
"()"
+
a
+
"LTestMeetIncompatibleInterfaceArrays$I1;"
,
false
);
test
.
visitVarInsn
(
ASTORE
,
0
);
if
(
dim
>
0
)
{
test
.
visitVarInsn
(
ALOAD
,
0
);
for
(
int
i
=
1
;
i
<=
dim
;
i
++)
{
test
.
visitInsn
(
ICONST_0
);
test
.
visitInsn
(
AALOAD
);
}
test
.
visitVarInsn
(
ASTORE
,
1
);
}
test
.
visitFieldInsn
(
GETSTATIC
,
"java/lang/System"
,
"out"
,
"Ljava/io/PrintStream;"
);
test
.
visitVarInsn
(
ALOAD
,
dim
>
0
?
1
:
0
);
test
.
visitMethodInsn
(
INVOKEINTERFACE
,
"TestMeetIncompatibleInterfaceArrays$I1"
,
"getName"
,
"()Ljava/lang/String;"
,
true
);
test
.
visitMethodInsn
(
INVOKEVIRTUAL
,
"java/io/PrintStream"
,
"println"
,
"(Ljava/lang/Object;)V"
,
false
);
test
.
visitInsn
(
RETURN
);
test
.
visitMaxs
(
0
,
0
);
test
.
visitEnd
();
// Get the bytes of the class..
byte
[]
b
=
cw
.
toByteArray
();
// ..and write them into a class file (for debugging)
FileOutputStream
fos
=
new
FileOutputStream
(
PATH
+
baseClassName
+
dim
+
"ASM.class"
);
fos
.
write
(
b
);
fos
.
close
();
}
public
static
String
[][]
tier
=
{
{
"interpreted"
,
"C2 (tier 4) without inlining"
,
"C2 (tier4) without inlining"
},
{
"interpreted"
,
"C2 (tier 4) with inlining"
,
"C2 (tier4) with inlining"
},
{
"interpreted"
,
"C1 (tier 3) with inlining"
,
"C2 (tier4) with inlining"
}
};
public
static
void
main
(
String
[]
args
)
throws
Exception
{
final
int
pass
=
Integer
.
parseInt
(
args
.
length
>
0
?
args
[
0
]
:
"0"
);
// Load and initialize some classes required for compilation
Class
.
forName
(
"TestMeetIncompatibleInterfaceArrays$I1"
);
Class
.
forName
(
"TestMeetIncompatibleInterfaceArrays$I2"
);
Class
.
forName
(
"TestMeetIncompatibleInterfaceArrays$Helper"
);
for
(
int
g
=
0
;
g
<
2
;
g
++)
{
String
baseClassName
=
"MeetIncompatibleInterfaceArrays"
;
boolean
good
=
(
g
==
0
)
?
false
:
true
;
if
(
good
)
baseClassName
+=
"Good"
;
for
(
int
i
=
0
;
i
<
6
;
i
++)
{
System
.
out
.
println
();
System
.
out
.
println
(
"Creating "
+
baseClassName
+
i
+
"ASM.class"
);
System
.
out
.
println
(
"========================================"
+
"="
+
"========="
);
// Create the "MeetIncompatibleInterfaceArrays<i>ASM" class
generateTestClass
(
i
,
good
);
Class
<?>
c
=
null
;
try
{
c
=
Class
.
forName
(
baseClassName
+
i
+
"ASM"
);
}
catch
(
VerifyError
ve
)
{
if
(
i
==
4
)
{
System
.
out
.
println
(
"OK - must be ("
+
ve
.
getMessage
()
+
")."
);
}
else
{
throw
ve
;
}
continue
;
}
// Call MeetIncompatibleInterfaceArrays<i>ASM.test()
Method
m
=
c
.
getMethod
(
"test"
);
Method
r
=
c
.
getMethod
(
"run"
);
for
(
int
j
=
0
;
j
<
3
;
j
++)
{
System
.
out
.
println
((
j
+
1
)
+
". invokation of "
+
baseClassName
+
i
+
"ASM.test() [should be "
+
tier
[
pass
][
j
]
+
"]"
);
try
{
m
.
invoke
(
null
);
}
catch
(
InvocationTargetException
ite
)
{
if
(
good
)
{
throw
ite
;
}
else
{
if
(
ite
.
getCause
()
instanceof
IncompatibleClassChangeError
)
{
System
.
out
.
println
(
" OK - catched InvocationTargetException("
+
ite
.
getCause
().
getMessage
()
+
")."
);
}
else
{
throw
ite
;
}
}
}
}
System
.
out
.
println
(
"Method "
+
r
+
(
WB
.
isMethodCompiled
(
r
)
?
" has"
:
" has not"
)
+
" been compiled."
);
if
(!
WB
.
isMethodCompiled
(
r
))
{
throw
new
Exception
(
"Method "
+
r
+
" must be compiled!"
);
}
}
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录