Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
301e0094
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
301e0094
编写于
9月 10, 2014
作者:
V
vlivanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8049555: Move varargsArray from sun.invoke.util package to java.lang.invoke
Reviewed-by: psandoz, iignatyev
上级
7e35994f
变更
6
展开全部
隐藏空白更改
内联
并排
Showing
6 changed file
with
537 addition
and
604 deletion
+537
-604
src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
...re/classes/java/lang/invoke/InvokerBytecodeGenerator.java
+1
-2
src/share/classes/java/lang/invoke/MethodHandle.java
src/share/classes/java/lang/invoke/MethodHandle.java
+1
-2
src/share/classes/java/lang/invoke/MethodHandleImpl.java
src/share/classes/java/lang/invoke/MethodHandleImpl.java
+308
-5
src/share/classes/sun/invoke/util/ValueConversions.java
src/share/classes/sun/invoke/util/ValueConversions.java
+1
-405
test/java/lang/invoke/VarargsArrayTest.java
test/java/lang/invoke/VarargsArrayTest.java
+224
-0
test/sun/invoke/util/ValueConversionsTest.java
test/sun/invoke/util/ValueConversionsTest.java
+2
-190
未找到文件。
src/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java
浏览文件 @
301e0094
...
...
@@ -36,7 +36,6 @@ import static java.lang.invoke.LambdaForm.BasicType.*;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
import
static
java
.
lang
.
invoke
.
MethodHandleNatives
.
Constants
.*;
import
java.lang.invoke.MethodHandleImpl.ArrayAccessor
;
import
sun.invoke.util.ValueConversions
;
import
sun.invoke.util.VerifyAccess
;
import
sun.invoke.util.VerifyType
;
import
sun.invoke.util.Wrapper
;
...
...
@@ -904,7 +903,7 @@ class InvokerBytecodeGenerator {
if
(!
ptypes
.
equals
(
Collections
.
nCopies
(
size
,
arrayElementType
)))
return
false
;
// Assume varargsArray caches pointers.
if
(
fn
!=
ValueConversions
.
varargsArray
(
rtype
,
size
))
if
(
fn
!=
MethodHandleImpl
.
varargsArray
(
rtype
,
size
))
return
false
;
return
true
;
}
...
...
src/share/classes/java/lang/invoke/MethodHandle.java
浏览文件 @
301e0094
...
...
@@ -28,7 +28,6 @@ package java.lang.invoke;
import
java.util.*
;
import
java.lang.invoke.LambdaForm.BasicType
;
import
sun.invoke.util.*
;
import
sun.misc.Unsafe
;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
...
...
@@ -988,7 +987,7 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123));
MethodHandle
target
=
this
;
if
(
arrayType
!=
type
().
parameterType
(
collectArgPos
))
target
=
convertArguments
(
type
().
changeParameterType
(
collectArgPos
,
arrayType
));
MethodHandle
collector
=
ValueConversions
.
varargsArray
(
arrayType
,
arrayLength
);
MethodHandle
collector
=
MethodHandleImpl
.
varargsArray
(
arrayType
,
arrayLength
);
return
MethodHandles
.
collectArguments
(
target
,
collectArgPos
,
collector
);
}
...
...
src/share/classes/java/lang/invoke/MethodHandleImpl.java
浏览文件 @
301e0094
...
...
@@ -27,8 +27,11 @@ package java.lang.invoke;
import
java.security.AccessController
;
import
java.security.PrivilegedAction
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.Collections
;
import
java.util.List
;
import
sun.invoke.empty.Empty
;
import
sun.invoke.util.ValueConversions
;
import
sun.invoke.util.VerifyType
;
...
...
@@ -44,6 +47,20 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
* @author jrose
*/
/*non-public*/
abstract
class
MethodHandleImpl
{
// Do not adjust this except for special platforms:
private
static
final
int
MAX_ARITY
;
static
{
final
Object
[]
values
=
{
255
};
AccessController
.
doPrivileged
(
new
PrivilegedAction
<
Void
>()
{
@Override
public
Void
run
()
{
values
[
0
]
=
Integer
.
getInteger
(
MethodHandleImpl
.
class
.
getName
()+
".MAX_ARITY"
,
255
);
return
null
;
}
});
MAX_ARITY
=
(
Integer
)
values
[
0
];
}
/// Factory methods to create method handles:
static
void
initStatics
()
{
...
...
@@ -516,6 +533,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
static
final
NamedFunction
NF_throwException
;
static
final
MethodHandle
MH_castReference
;
static
final
MethodHandle
MH_copyAsPrimitiveArray
;
static
final
MethodHandle
MH_copyAsReferenceArray
;
static
final
MethodHandle
MH_fillNewTypedArray
;
static
final
MethodHandle
MH_fillNewArray
;
static
final
MethodHandle
MH_arrayIdentity
;
static
{
try
{
...
...
@@ -531,8 +553,18 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
NF_selectAlternative
.
resolve
();
NF_throwException
.
resolve
();
MethodType
mt
=
MethodType
.
methodType
(
Object
.
class
,
Class
.
class
,
Object
.
class
);
MH_castReference
=
IMPL_LOOKUP
.
findStatic
(
MHI
,
"castReference"
,
mt
);
MH_castReference
=
IMPL_LOOKUP
.
findStatic
(
MHI
,
"castReference"
,
MethodType
.
methodType
(
Object
.
class
,
Class
.
class
,
Object
.
class
));
MH_copyAsPrimitiveArray
=
IMPL_LOOKUP
.
findStatic
(
MHI
,
"copyAsPrimitiveArray"
,
MethodType
.
methodType
(
Object
.
class
,
Wrapper
.
class
,
Object
[].
class
));
MH_copyAsReferenceArray
=
IMPL_LOOKUP
.
findStatic
(
MHI
,
"copyAsReferenceArray"
,
MethodType
.
methodType
(
Object
[].
class
,
Class
.
class
,
Object
[].
class
));
MH_arrayIdentity
=
IMPL_LOOKUP
.
findStatic
(
MHI
,
"identity"
,
MethodType
.
methodType
(
Object
[].
class
,
Object
[].
class
));
MH_fillNewArray
=
IMPL_LOOKUP
.
findStatic
(
MHI
,
"fillNewArray"
,
MethodType
.
methodType
(
Object
[].
class
,
Integer
.
class
,
Object
[].
class
));
MH_fillNewTypedArray
=
IMPL_LOOKUP
.
findStatic
(
MHI
,
"fillNewTypedArray"
,
MethodType
.
methodType
(
Object
[].
class
,
Object
[].
class
,
Integer
.
class
,
Object
[].
class
));
}
catch
(
ReflectiveOperationException
ex
)
{
throw
newInternalError
(
ex
);
}
...
...
@@ -713,8 +745,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
// Prepare auxiliary method handles used during LambdaForm interpreation.
// Box arguments and wrap them into Object[]: ValueConversions.array().
MethodType
varargsType
=
type
.
changeReturnType
(
Object
[].
class
);
MethodHandle
collectArgs
=
ValueConversions
.
varargsArray
(
type
.
parameterCount
())
.
asType
(
varargsType
);
MethodHandle
collectArgs
=
varargsArray
(
type
.
parameterCount
()).
asType
(
varargsType
);
// Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
MethodHandle
unboxResult
;
if
(
type
.
returnType
().
isPrimitive
())
{
...
...
@@ -999,4 +1030,276 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
return
new
WrappedMember
(
target
,
target
.
type
(),
member
,
null
);
}
/// Collection of multiple arguments.
private
static
MethodHandle
findCollector
(
String
name
,
int
nargs
,
Class
<?>
rtype
,
Class
<?>...
ptypes
)
{
MethodType
type
=
MethodType
.
genericMethodType
(
nargs
)
.
changeReturnType
(
rtype
)
.
insertParameterTypes
(
0
,
ptypes
);
try
{
return
IMPL_LOOKUP
.
findStatic
(
MethodHandleImpl
.
class
,
name
,
type
);
}
catch
(
ReflectiveOperationException
ex
)
{
return
null
;
}
}
private
static
final
Object
[]
NO_ARGS_ARRAY
=
{};
private
static
Object
[]
makeArray
(
Object
...
args
)
{
return
args
;
}
private
static
Object
[]
array
()
{
return
NO_ARGS_ARRAY
;
}
private
static
Object
[]
array
(
Object
a0
)
{
return
makeArray
(
a0
);
}
private
static
Object
[]
array
(
Object
a0
,
Object
a1
)
{
return
makeArray
(
a0
,
a1
);
}
private
static
Object
[]
array
(
Object
a0
,
Object
a1
,
Object
a2
)
{
return
makeArray
(
a0
,
a1
,
a2
);
}
private
static
Object
[]
array
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
)
{
return
makeArray
(
a0
,
a1
,
a2
,
a3
);
}
private
static
Object
[]
array
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
,
Object
a4
)
{
return
makeArray
(
a0
,
a1
,
a2
,
a3
,
a4
);
}
private
static
Object
[]
array
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
,
Object
a4
,
Object
a5
)
{
return
makeArray
(
a0
,
a1
,
a2
,
a3
,
a4
,
a5
);
}
private
static
Object
[]
array
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
,
Object
a4
,
Object
a5
,
Object
a6
)
{
return
makeArray
(
a0
,
a1
,
a2
,
a3
,
a4
,
a5
,
a6
);
}
private
static
Object
[]
array
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
,
Object
a4
,
Object
a5
,
Object
a6
,
Object
a7
)
{
return
makeArray
(
a0
,
a1
,
a2
,
a3
,
a4
,
a5
,
a6
,
a7
);
}
private
static
Object
[]
array
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
,
Object
a4
,
Object
a5
,
Object
a6
,
Object
a7
,
Object
a8
)
{
return
makeArray
(
a0
,
a1
,
a2
,
a3
,
a4
,
a5
,
a6
,
a7
,
a8
);
}
private
static
Object
[]
array
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
,
Object
a4
,
Object
a5
,
Object
a6
,
Object
a7
,
Object
a8
,
Object
a9
)
{
return
makeArray
(
a0
,
a1
,
a2
,
a3
,
a4
,
a5
,
a6
,
a7
,
a8
,
a9
);
}
private
static
MethodHandle
[]
makeArrays
()
{
ArrayList
<
MethodHandle
>
mhs
=
new
ArrayList
<>();
for
(;;)
{
MethodHandle
mh
=
findCollector
(
"array"
,
mhs
.
size
(),
Object
[].
class
);
if
(
mh
==
null
)
break
;
mhs
.
add
(
mh
);
}
assert
(
mhs
.
size
()
==
11
);
// current number of methods
return
mhs
.
toArray
(
new
MethodHandle
[
MAX_ARITY
+
1
]);
}
private
static
final
MethodHandle
[]
ARRAYS
=
makeArrays
();
// filling versions of the above:
// using Integer len instead of int len and no varargs to avoid bootstrapping problems
private
static
Object
[]
fillNewArray
(
Integer
len
,
Object
[]
/*not ...*/
args
)
{
Object
[]
a
=
new
Object
[
len
];
fillWithArguments
(
a
,
0
,
args
);
return
a
;
}
private
static
Object
[]
fillNewTypedArray
(
Object
[]
example
,
Integer
len
,
Object
[]
/*not ...*/
args
)
{
Object
[]
a
=
Arrays
.
copyOf
(
example
,
len
);
fillWithArguments
(
a
,
0
,
args
);
return
a
;
}
private
static
void
fillWithArguments
(
Object
[]
a
,
int
pos
,
Object
...
args
)
{
System
.
arraycopy
(
args
,
0
,
a
,
pos
,
args
.
length
);
}
// using Integer pos instead of int pos to avoid bootstrapping problems
private
static
Object
[]
fillArray
(
Integer
pos
,
Object
[]
a
,
Object
a0
)
{
fillWithArguments
(
a
,
pos
,
a0
);
return
a
;
}
private
static
Object
[]
fillArray
(
Integer
pos
,
Object
[]
a
,
Object
a0
,
Object
a1
)
{
fillWithArguments
(
a
,
pos
,
a0
,
a1
);
return
a
;
}
private
static
Object
[]
fillArray
(
Integer
pos
,
Object
[]
a
,
Object
a0
,
Object
a1
,
Object
a2
)
{
fillWithArguments
(
a
,
pos
,
a0
,
a1
,
a2
);
return
a
;
}
private
static
Object
[]
fillArray
(
Integer
pos
,
Object
[]
a
,
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
)
{
fillWithArguments
(
a
,
pos
,
a0
,
a1
,
a2
,
a3
);
return
a
;
}
private
static
Object
[]
fillArray
(
Integer
pos
,
Object
[]
a
,
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
,
Object
a4
)
{
fillWithArguments
(
a
,
pos
,
a0
,
a1
,
a2
,
a3
,
a4
);
return
a
;
}
private
static
Object
[]
fillArray
(
Integer
pos
,
Object
[]
a
,
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
,
Object
a4
,
Object
a5
)
{
fillWithArguments
(
a
,
pos
,
a0
,
a1
,
a2
,
a3
,
a4
,
a5
);
return
a
;
}
private
static
Object
[]
fillArray
(
Integer
pos
,
Object
[]
a
,
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
,
Object
a4
,
Object
a5
,
Object
a6
)
{
fillWithArguments
(
a
,
pos
,
a0
,
a1
,
a2
,
a3
,
a4
,
a5
,
a6
);
return
a
;
}
private
static
Object
[]
fillArray
(
Integer
pos
,
Object
[]
a
,
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
,
Object
a4
,
Object
a5
,
Object
a6
,
Object
a7
)
{
fillWithArguments
(
a
,
pos
,
a0
,
a1
,
a2
,
a3
,
a4
,
a5
,
a6
,
a7
);
return
a
;
}
private
static
Object
[]
fillArray
(
Integer
pos
,
Object
[]
a
,
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
,
Object
a4
,
Object
a5
,
Object
a6
,
Object
a7
,
Object
a8
)
{
fillWithArguments
(
a
,
pos
,
a0
,
a1
,
a2
,
a3
,
a4
,
a5
,
a6
,
a7
,
a8
);
return
a
;
}
private
static
Object
[]
fillArray
(
Integer
pos
,
Object
[]
a
,
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
,
Object
a4
,
Object
a5
,
Object
a6
,
Object
a7
,
Object
a8
,
Object
a9
)
{
fillWithArguments
(
a
,
pos
,
a0
,
a1
,
a2
,
a3
,
a4
,
a5
,
a6
,
a7
,
a8
,
a9
);
return
a
;
}
private
static
MethodHandle
[]
makeFillArrays
()
{
ArrayList
<
MethodHandle
>
mhs
=
new
ArrayList
<>();
mhs
.
add
(
null
);
// there is no empty fill; at least a0 is required
for
(;;)
{
MethodHandle
mh
=
findCollector
(
"fillArray"
,
mhs
.
size
(),
Object
[].
class
,
Integer
.
class
,
Object
[].
class
);
if
(
mh
==
null
)
break
;
mhs
.
add
(
mh
);
}
assert
(
mhs
.
size
()
==
11
);
// current number of methods
return
mhs
.
toArray
(
new
MethodHandle
[
0
]);
}
private
static
final
MethodHandle
[]
FILL_ARRAYS
=
makeFillArrays
();
private
static
Object
[]
copyAsReferenceArray
(
Class
<?
extends
Object
[]>
arrayType
,
Object
...
a
)
{
return
Arrays
.
copyOf
(
a
,
a
.
length
,
arrayType
);
}
private
static
Object
copyAsPrimitiveArray
(
Wrapper
w
,
Object
...
boxes
)
{
Object
a
=
w
.
makeArray
(
boxes
.
length
);
w
.
copyArrayUnboxing
(
boxes
,
0
,
a
,
0
,
boxes
.
length
);
return
a
;
}
/** Return a method handle that takes the indicated number of Object
* arguments and returns an Object array of them, as if for varargs.
*/
static
MethodHandle
varargsArray
(
int
nargs
)
{
MethodHandle
mh
=
ARRAYS
[
nargs
];
if
(
mh
!=
null
)
return
mh
;
mh
=
findCollector
(
"array"
,
nargs
,
Object
[].
class
);
if
(
mh
!=
null
)
return
ARRAYS
[
nargs
]
=
mh
;
mh
=
buildVarargsArray
(
Lazy
.
MH_fillNewArray
,
Lazy
.
MH_arrayIdentity
,
nargs
);
assert
(
assertCorrectArity
(
mh
,
nargs
));
return
ARRAYS
[
nargs
]
=
mh
;
}
private
static
boolean
assertCorrectArity
(
MethodHandle
mh
,
int
arity
)
{
assert
(
mh
.
type
().
parameterCount
()
==
arity
)
:
"arity != "
+
arity
+
": "
+
mh
;
return
true
;
}
// Array identity function (used as Lazy.MH_arrayIdentity).
static
<
T
>
T
[]
identity
(
T
[]
x
)
{
return
x
;
}
private
static
MethodHandle
buildVarargsArray
(
MethodHandle
newArray
,
MethodHandle
finisher
,
int
nargs
)
{
// Build up the result mh as a sequence of fills like this:
// finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
// The various fill(_,10*I,___*[J]) are reusable.
int
leftLen
=
Math
.
min
(
nargs
,
LEFT_ARGS
);
// absorb some arguments immediately
int
rightLen
=
nargs
-
leftLen
;
MethodHandle
leftCollector
=
newArray
.
bindTo
(
nargs
);
leftCollector
=
leftCollector
.
asCollector
(
Object
[].
class
,
leftLen
);
MethodHandle
mh
=
finisher
;
if
(
rightLen
>
0
)
{
MethodHandle
rightFiller
=
fillToRight
(
LEFT_ARGS
+
rightLen
);
if
(
mh
==
Lazy
.
MH_arrayIdentity
)
mh
=
rightFiller
;
else
mh
=
MethodHandles
.
collectArguments
(
mh
,
0
,
rightFiller
);
}
if
(
mh
==
Lazy
.
MH_arrayIdentity
)
mh
=
leftCollector
;
else
mh
=
MethodHandles
.
collectArguments
(
mh
,
0
,
leftCollector
);
return
mh
;
}
private
static
final
int
LEFT_ARGS
=
(
FILL_ARRAYS
.
length
-
1
);
private
static
final
MethodHandle
[]
FILL_ARRAY_TO_RIGHT
=
new
MethodHandle
[
MAX_ARITY
+
1
];
/** fill_array_to_right(N).invoke(a, argL..arg[N-1])
* fills a[L]..a[N-1] with corresponding arguments,
* and then returns a. The value L is a global constant (LEFT_ARGS).
*/
private
static
MethodHandle
fillToRight
(
int
nargs
)
{
MethodHandle
filler
=
FILL_ARRAY_TO_RIGHT
[
nargs
];
if
(
filler
!=
null
)
return
filler
;
filler
=
buildFiller
(
nargs
);
assert
(
assertCorrectArity
(
filler
,
nargs
-
LEFT_ARGS
+
1
));
return
FILL_ARRAY_TO_RIGHT
[
nargs
]
=
filler
;
}
private
static
MethodHandle
buildFiller
(
int
nargs
)
{
if
(
nargs
<=
LEFT_ARGS
)
return
Lazy
.
MH_arrayIdentity
;
// no args to fill; return the array unchanged
// we need room for both mh and a in mh.invoke(a, arg*[nargs])
final
int
CHUNK
=
LEFT_ARGS
;
int
rightLen
=
nargs
%
CHUNK
;
int
midLen
=
nargs
-
rightLen
;
if
(
rightLen
==
0
)
{
midLen
=
nargs
-
(
rightLen
=
CHUNK
);
if
(
FILL_ARRAY_TO_RIGHT
[
midLen
]
==
null
)
{
// build some precursors from left to right
for
(
int
j
=
LEFT_ARGS
%
CHUNK
;
j
<
midLen
;
j
+=
CHUNK
)
if
(
j
>
LEFT_ARGS
)
fillToRight
(
j
);
}
}
if
(
midLen
<
LEFT_ARGS
)
rightLen
=
nargs
-
(
midLen
=
LEFT_ARGS
);
assert
(
rightLen
>
0
);
MethodHandle
midFill
=
fillToRight
(
midLen
);
// recursive fill
MethodHandle
rightFill
=
FILL_ARRAYS
[
rightLen
].
bindTo
(
midLen
);
// [midLen..nargs-1]
assert
(
midFill
.
type
().
parameterCount
()
==
1
+
midLen
-
LEFT_ARGS
);
assert
(
rightFill
.
type
().
parameterCount
()
==
1
+
rightLen
);
// Combine the two fills:
// right(mid(a, x10..x19), x20..x23)
// The final product will look like this:
// right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
if
(
midLen
==
LEFT_ARGS
)
return
rightFill
;
else
return
MethodHandles
.
collectArguments
(
rightFill
,
0
,
midFill
);
}
// Type-polymorphic version of varargs maker.
private
static
final
ClassValue
<
MethodHandle
[]>
TYPED_COLLECTORS
=
new
ClassValue
<
MethodHandle
[]>()
{
@Override
protected
MethodHandle
[]
computeValue
(
Class
<?>
type
)
{
return
new
MethodHandle
[
256
];
}
};
static
final
int
MAX_JVM_ARITY
=
255
;
// limit imposed by the JVM
/** Return a method handle that takes the indicated number of
* typed arguments and returns an array of them.
* The type argument is the array type.
*/
static
MethodHandle
varargsArray
(
Class
<?>
arrayType
,
int
nargs
)
{
Class
<?>
elemType
=
arrayType
.
getComponentType
();
if
(
elemType
==
null
)
throw
new
IllegalArgumentException
(
"not an array: "
+
arrayType
);
// FIXME: Need more special casing and caching here.
if
(
nargs
>=
MAX_JVM_ARITY
/
2
-
1
)
{
int
slots
=
nargs
;
final
int
MAX_ARRAY_SLOTS
=
MAX_JVM_ARITY
-
1
;
// 1 for receiver MH
if
(
arrayType
==
double
[].
class
||
arrayType
==
long
[].
class
)
slots
*=
2
;
if
(
slots
>
MAX_ARRAY_SLOTS
)
throw
new
IllegalArgumentException
(
"too many arguments: "
+
arrayType
.
getSimpleName
()+
", length "
+
nargs
);
}
if
(
elemType
==
Object
.
class
)
return
varargsArray
(
nargs
);
// other cases: primitive arrays, subtypes of Object[]
MethodHandle
cache
[]
=
TYPED_COLLECTORS
.
get
(
elemType
);
MethodHandle
mh
=
nargs
<
cache
.
length
?
cache
[
nargs
]
:
null
;
if
(
mh
!=
null
)
return
mh
;
if
(
elemType
.
isPrimitive
())
{
MethodHandle
builder
=
Lazy
.
MH_fillNewArray
;
MethodHandle
producer
=
buildArrayProducer
(
arrayType
);
mh
=
buildVarargsArray
(
builder
,
producer
,
nargs
);
}
else
{
@SuppressWarnings
(
"unchecked"
)
Class
<?
extends
Object
[]>
objArrayType
=
(
Class
<?
extends
Object
[]>)
arrayType
;
Object
[]
example
=
Arrays
.
copyOf
(
NO_ARGS_ARRAY
,
0
,
objArrayType
);
MethodHandle
builder
=
Lazy
.
MH_fillNewTypedArray
.
bindTo
(
example
);
MethodHandle
producer
=
Lazy
.
MH_arrayIdentity
;
mh
=
buildVarargsArray
(
builder
,
producer
,
nargs
);
}
mh
=
mh
.
asType
(
MethodType
.
methodType
(
arrayType
,
Collections
.<
Class
<?>>
nCopies
(
nargs
,
elemType
)));
assert
(
assertCorrectArity
(
mh
,
nargs
));
if
(
nargs
<
cache
.
length
)
cache
[
nargs
]
=
mh
;
return
mh
;
}
private
static
MethodHandle
buildArrayProducer
(
Class
<?>
arrayType
)
{
Class
<?>
elemType
=
arrayType
.
getComponentType
();
if
(
elemType
.
isPrimitive
())
return
Lazy
.
MH_copyAsPrimitiveArray
.
bindTo
(
Wrapper
.
forPrimitiveType
(
elemType
));
else
return
Lazy
.
MH_copyAsReferenceArray
.
bindTo
(
arrayType
);
}
}
src/share/classes/sun/invoke/util/ValueConversions.java
浏览文件 @
301e0094
此差异已折叠。
点击以展开。
test/java/lang/invoke/VarargsArrayTest.java
0 → 100644
浏览文件 @
301e0094
/*
* 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
java.lang.invoke
;
import
sun.invoke.util.Wrapper
;
import
java.util.Arrays
;
import
java.util.Collections
;
/* @test
* @summary unit tests for varargs array methods: MethodHandleInfo.varargsArray(int),
* MethodHandleInfo.varargsArray(Class,int) & MethodHandleInfo.varargsList(int)
*
* @run main/bootclasspath java.lang.invoke.VarargsArrayTest
* @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.START_ARITY=250
* java.lang.invoke.VarargsArrayTest
*/
/* This might take a while and burn lots of metadata:
* @run main/bootclasspath -DVarargsArrayTest.MAX_ARITY=255 -DVarargsArrayTest.EXHAUSTIVE=true java.lang.invoke.VarargsArrayTest
*/
public
class
VarargsArrayTest
{
private
static
final
Class
<?>
CLASS
=
VarargsArrayTest
.
class
;
private
static
final
int
MAX_ARITY
=
Integer
.
getInteger
(
CLASS
.
getSimpleName
()+
".MAX_ARITY"
,
40
);
private
static
final
int
START_ARITY
=
Integer
.
getInteger
(
CLASS
.
getSimpleName
()+
".START_ARITY"
,
0
);
private
static
final
boolean
EXHAUSTIVE
=
Boolean
.
getBoolean
(
CLASS
.
getSimpleName
()+
".EXHAUSTIVE"
);
public
static
void
main
(
String
[]
args
)
throws
Throwable
{
testVarargsArray
();
testVarargsReferenceArray
();
testVarargsPrimitiveArray
();
}
public
static
void
testVarargsArray
()
throws
Throwable
{
final
int
MIN
=
START_ARITY
;
final
int
MAX
=
MAX_ARITY
-
2
;
// 253+1 would cause parameter overflow with 'this' added
for
(
int
nargs
=
MIN
;
nargs
<=
MAX
;
nargs
=
nextArgCount
(
nargs
,
17
,
MAX
))
{
MethodHandle
target
=
MethodHandleImpl
.
varargsArray
(
nargs
);
Object
[]
args
=
new
Object
[
nargs
];
for
(
int
i
=
0
;
i
<
nargs
;
i
++)
args
[
i
]
=
"#"
+
i
;
Object
res
=
target
.
invokeWithArguments
(
args
);
assertArrayEquals
(
args
,
(
Object
[])
res
);
}
}
public
static
void
testVarargsReferenceArray
()
throws
Throwable
{
testTypedVarargsArray
(
Object
[].
class
);
testTypedVarargsArray
(
String
[].
class
);
testTypedVarargsArray
(
Number
[].
class
);
}
public
static
void
testVarargsPrimitiveArray
()
throws
Throwable
{
testTypedVarargsArray
(
int
[].
class
);
testTypedVarargsArray
(
long
[].
class
);
testTypedVarargsArray
(
byte
[].
class
);
testTypedVarargsArray
(
boolean
[].
class
);
testTypedVarargsArray
(
short
[].
class
);
testTypedVarargsArray
(
char
[].
class
);
testTypedVarargsArray
(
float
[].
class
);
testTypedVarargsArray
(
double
[].
class
);
}
private
static
int
nextArgCount
(
int
nargs
,
int
density
,
int
MAX
)
{
if
(
EXHAUSTIVE
)
return
nargs
+
1
;
if
(
nargs
>=
MAX
)
return
Integer
.
MAX_VALUE
;
int
BOT
=
20
,
TOP
=
MAX
-
5
;
if
(
density
<
10
)
{
BOT
=
10
;
MAX
=
TOP
-
2
;
}
if
(
nargs
<=
BOT
||
nargs
>=
TOP
)
{
++
nargs
;
}
else
{
int
bump
=
Math
.
max
(
1
,
100
/
density
);
nargs
+=
bump
;
if
(
nargs
>
TOP
)
nargs
=
TOP
;
}
return
nargs
;
}
private
static
void
testTypedVarargsArray
(
Class
<?>
arrayType
)
throws
Throwable
{
Class
<?>
elemType
=
arrayType
.
getComponentType
();
int
MIN
=
START_ARITY
;
int
MAX
=
MAX_ARITY
-
2
;
// 253+1 would cause parameter overflow with 'this' added
int
density
=
3
;
if
(
elemType
==
int
.
class
||
elemType
==
long
.
class
)
density
=
7
;
if
(
elemType
==
long
.
class
||
elemType
==
double
.
class
)
{
MAX
/=
2
;
MIN
/=
2
;
}
for
(
int
nargs
=
MIN
;
nargs
<=
MAX
;
nargs
=
nextArgCount
(
nargs
,
density
,
MAX
))
{
Object
[]
args
=
makeTestArray
(
elemType
,
nargs
);
MethodHandle
varargsArray
=
MethodHandleImpl
.
varargsArray
(
arrayType
,
nargs
);
MethodType
vaType
=
varargsArray
.
type
();
assertEquals
(
arrayType
,
vaType
.
returnType
());
if
(
nargs
!=
0
)
{
assertEquals
(
elemType
,
vaType
.
parameterType
(
0
));
assertEquals
(
elemType
,
vaType
.
parameterType
(
vaType
.
parameterCount
()-
1
));
}
assertEquals
(
MethodType
.
methodType
(
arrayType
,
Collections
.<
Class
<?>>
nCopies
(
nargs
,
elemType
)),
vaType
);
Object
res
=
varargsArray
.
invokeWithArguments
(
args
);
assertEquals
(
res
.
getClass
(),
arrayType
);
String
resString
=
toArrayString
(
res
);
assertEquals
(
Arrays
.
toString
(
args
),
resString
);
MethodHandle
spreader
=
varargsArray
.
asSpreader
(
arrayType
,
nargs
);
MethodType
stype
=
spreader
.
type
();
assert
(
stype
==
MethodType
.
methodType
(
arrayType
,
arrayType
));
if
(
nargs
<=
5
)
{
// invoke target as a spreader also:
@SuppressWarnings
(
"cast"
)
Object
res2
=
spreader
.
invokeWithArguments
((
Object
)
res
);
String
res2String
=
toArrayString
(
res2
);
assertEquals
(
Arrays
.
toString
(
args
),
res2String
);
// invoke the spreader on a generic Object[] array; check for error
try
{
Object
res3
=
spreader
.
invokeWithArguments
((
Object
)
args
);
String
res3String
=
toArrayString
(
res3
);
assertTrue
(
arrayType
.
getName
(),
arrayType
.
isAssignableFrom
(
Object
[].
class
));
assertEquals
(
Arrays
.
toString
(
args
),
res3String
);
}
catch
(
ClassCastException
ex
)
{
assertFalse
(
arrayType
.
getName
(),
arrayType
.
isAssignableFrom
(
Object
[].
class
));
}
}
if
(
nargs
==
0
)
{
// invoke spreader on null arglist
Object
res3
=
spreader
.
invokeWithArguments
((
Object
)
null
);
String
res3String
=
toArrayString
(
res3
);
assertEquals
(
Arrays
.
toString
(
args
),
res3String
);
}
}
}
private
static
Object
[]
makeTestArray
(
Class
<?>
elemType
,
int
len
)
{
Wrapper
elem
=
null
;
if
(
elemType
.
isPrimitive
())
elem
=
Wrapper
.
forPrimitiveType
(
elemType
);
else
if
(
Wrapper
.
isWrapperType
(
elemType
))
elem
=
Wrapper
.
forWrapperType
(
elemType
);
Object
[]
args
=
new
Object
[
len
];
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
Object
arg
=
i
*
100
;
if
(
elem
==
null
)
{
if
(
elemType
==
String
.
class
)
arg
=
"#"
+
arg
;
arg
=
elemType
.
cast
(
arg
);
// just to make sure
}
else
{
switch
(
elem
)
{
case
BOOLEAN:
arg
=
(
i
%
3
==
0
);
break
;
case
CHAR:
arg
=
'a'
+
i
;
break
;
case
LONG:
arg
=
(
long
)
i
*
1000_000_000
;
break
;
case
FLOAT:
arg
=
(
float
)
i
/
100
;
break
;
case
DOUBLE:
arg
=
(
double
)
i
/
1000_000
;
break
;
}
arg
=
elem
.
cast
(
arg
,
elemType
);
}
args
[
i
]
=
arg
;
}
return
args
;
}
private
static
String
toArrayString
(
Object
a
)
{
if
(
a
==
null
)
return
"null"
;
Class
<?>
elemType
=
a
.
getClass
().
getComponentType
();
if
(
elemType
==
null
)
return
a
.
toString
();
if
(
elemType
.
isPrimitive
())
{
switch
(
Wrapper
.
forPrimitiveType
(
elemType
))
{
case
INT:
return
Arrays
.
toString
((
int
[])
a
);
case
BYTE:
return
Arrays
.
toString
((
byte
[])
a
);
case
BOOLEAN:
return
Arrays
.
toString
((
boolean
[])
a
);
case
SHORT:
return
Arrays
.
toString
((
short
[])
a
);
case
CHAR:
return
Arrays
.
toString
((
char
[])
a
);
case
FLOAT:
return
Arrays
.
toString
((
float
[])
a
);
case
LONG:
return
Arrays
.
toString
((
long
[])
a
);
case
DOUBLE:
return
Arrays
.
toString
((
double
[])
a
);
}
}
return
Arrays
.
toString
((
Object
[])
a
);
}
public
static
void
assertArrayEquals
(
Object
[]
arr1
,
Object
[]
arr2
)
{
if
(
arr1
==
null
&&
arr2
==
null
)
return
;
if
(
arr1
!=
null
&&
arr2
!=
null
&&
arr1
.
length
==
arr2
.
length
)
{
for
(
int
i
=
0
;
i
<
arr1
.
length
;
i
++)
{
assertEquals
(
arr1
[
i
],
arr2
[
i
]);
}
return
;
}
throw
new
AssertionError
(
Arrays
.
deepToString
(
arr1
)
+
" != "
+
Arrays
.
deepToString
(
arr2
));
}
public
static
void
assertEquals
(
Object
o1
,
Object
o2
)
{
if
(
o1
==
null
&&
o2
==
null
)
return
;
if
(
o1
!=
null
&&
o1
.
equals
(
o2
))
return
;
throw
new
AssertionError
(
o1
+
" != "
+
o2
);
}
public
static
void
assertTrue
(
String
msg
,
boolean
b
)
{
if
(!
b
)
{
throw
new
AssertionError
(
msg
);
}
}
public
static
void
assertFalse
(
String
msg
,
boolean
b
)
{
assertTrue
(
msg
,
!
b
);
}
}
test/sun/invoke/util/ValueConversionsTest.java
浏览文件 @
301e0094
...
...
@@ -25,11 +25,11 @@ package test.sun.invoke.util;
import
sun.invoke.util.ValueConversions
;
import
sun.invoke.util.Wrapper
;
import
java.lang.invoke.MethodType
;
import
java.lang.invoke.MethodHandle
;
import
java.io.Serializable
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
org.junit.Test
;
import
static
org
.
junit
.
Assert
.*;
...
...
@@ -37,24 +37,13 @@ import static org.junit.Assert.*;
* @summary unit tests for value-type conversion utilities
* @compile -XDignore.symbol.file ValueConversionsTest.java
* @run junit/othervm test.sun.invoke.util.ValueConversionsTest
* @run junit/othervm
* -DValueConversionsTest.MAX_ARITY=255 -DValueConversionsTest.START_ARITY=250
* test.sun.invoke.util.ValueConversionsTest
*/
// This might take a while and burn lots of metadata:
// @run junit/othervm -DValueConversionsTest.MAX_ARITY=255 -DValueConversionsTest.EXHAUSTIVE=true test.sun.invoke.util.ValueConversionsTest
/**
*
* @author jrose
*/
public
class
ValueConversionsTest
{
private
static
final
Class
<?>
CLASS
=
ValueConversionsTest
.
class
;
private
static
final
int
MAX_ARITY
=
Integer
.
getInteger
(
CLASS
.
getSimpleName
()+
".MAX_ARITY"
,
40
);
private
static
final
int
START_ARITY
=
Integer
.
getInteger
(
CLASS
.
getSimpleName
()+
".START_ARITY"
,
0
);
private
static
final
boolean
EXHAUSTIVE
=
Boolean
.
getBoolean
(
CLASS
.
getSimpleName
()+
".EXHAUSTIVE"
);
@Test
public
void
testUnbox
()
throws
Throwable
{
testUnbox
(
false
);
...
...
@@ -66,9 +55,7 @@ public class ValueConversionsTest {
}
private
void
testUnbox
(
boolean
doCast
)
throws
Throwable
{
//System.out.println("unbox");
for
(
Wrapper
dst
:
Wrapper
.
values
())
{
//System.out.println(dst);
for
(
Wrapper
src
:
Wrapper
.
values
())
{
testUnbox
(
doCast
,
dst
,
src
);
}
...
...
@@ -123,10 +110,8 @@ public class ValueConversionsTest {
@Test
public
void
testBox
()
throws
Throwable
{
//System.out.println("box");
for
(
Wrapper
w
:
Wrapper
.
values
())
{
if
(
w
==
Wrapper
.
VOID
)
continue
;
// skip this; no unboxed form
//System.out.println(w);
for
(
int
n
=
-
5
;
n
<
10
;
n
++)
{
Object
box
=
w
.
wrap
(
n
);
MethodHandle
boxer
=
ValueConversions
.
box
(
w
.
primitiveType
());
...
...
@@ -151,7 +136,6 @@ public class ValueConversionsTest {
@Test
public
void
testCast
()
throws
Throwable
{
//System.out.println("cast");
Class
<?>[]
types
=
{
Object
.
class
,
Serializable
.
class
,
String
.
class
,
Number
.
class
,
Integer
.
class
};
Object
[]
objects
=
{
new
Object
(),
Boolean
.
FALSE
,
"hello"
,
(
Long
)
12L
,
(
Integer
)
6
};
for
(
Class
<?>
dst
:
types
)
{
...
...
@@ -160,7 +144,6 @@ public class ValueConversionsTest {
for
(
Object
obj
:
objects
)
{
Class
<?>
src
=
obj
.
getClass
();
boolean
canCast
=
dst
.
isAssignableFrom
(
src
);
//System.out.println("obj="+obj+" <: dst="+dst+(canCast ? " (OK)" : " (will fail)"));
try
{
Object
result
=
caster
.
invokeExact
(
obj
);
if
(
canCast
)
...
...
@@ -177,24 +160,19 @@ public class ValueConversionsTest {
@Test
public
void
testIdentity
()
throws
Throwable
{
//System.out.println("identity");
MethodHandle
id
=
ValueConversions
.
identity
();
Object
expResult
=
"foo"
;
Object
result
=
id
.
invokeExact
(
expResult
);
// compiler bug: ValueConversions.identity().invokeExact("bar");
assertEquals
(
expResult
,
result
);
}
@Test
public
void
testConvert
()
throws
Throwable
{
//System.out.println("convert");
for
(
long
tval
=
0
,
ctr
=
0
;;)
{
if
(++
ctr
>
99999
)
throw
new
AssertionError
(
"too many test values"
);
// next test value:
//System.out.println(Long.toHexString(tval)); // prints 3776 test patterns
// prints 3776 test patterns (3776 = 8*59*8)
tval
=
nextTestValue
(
tval
);
if
(
tval
==
0
)
{
//System.out.println("test value count = "+ctr); // 3776 = 8*59*8
break
;
// repeat
}
}
...
...
@@ -205,7 +183,6 @@ public class ValueConversionsTest {
}
}
static
void
testConvert
(
Wrapper
src
,
Wrapper
dst
,
long
tval
)
throws
Throwable
{
//System.out.println(src+" => "+dst);
boolean
testSingleCase
=
(
tval
!=
0
);
final
long
tvalInit
=
tval
;
MethodHandle
conv
=
ValueConversions
.
convertPrimitive
(
src
,
dst
);
...
...
@@ -269,169 +246,4 @@ public class ValueConversionsTest {
}
return
tweakSign
(
ux
);
}
@Test
public
void
testVarargsArray
()
throws
Throwable
{
//System.out.println("varargsArray");
final
int
MIN
=
START_ARITY
;
final
int
MAX
=
MAX_ARITY
-
2
;
// 253+1 would cause parameter overflow with 'this' added
for
(
int
nargs
=
MIN
;
nargs
<=
MAX
;
nargs
=
nextArgCount
(
nargs
,
17
,
MAX
))
{
MethodHandle
target
=
ValueConversions
.
varargsArray
(
nargs
);
Object
[]
args
=
new
Object
[
nargs
];
for
(
int
i
=
0
;
i
<
nargs
;
i
++)
args
[
i
]
=
"#"
+
i
;
Object
res
=
target
.
invokeWithArguments
(
args
);
assertArrayEquals
(
args
,
(
Object
[])
res
);
}
}
@Test
public
void
testVarargsReferenceArray
()
throws
Throwable
{
//System.out.println("varargsReferenceArray");
testTypedVarargsArray
(
Object
[].
class
);
testTypedVarargsArray
(
String
[].
class
);
testTypedVarargsArray
(
Number
[].
class
);
}
@Test
public
void
testVarargsPrimitiveArray
()
throws
Throwable
{
//System.out.println("varargsPrimitiveArray");
testTypedVarargsArray
(
int
[].
class
);
testTypedVarargsArray
(
long
[].
class
);
testTypedVarargsArray
(
byte
[].
class
);
testTypedVarargsArray
(
boolean
[].
class
);
testTypedVarargsArray
(
short
[].
class
);
testTypedVarargsArray
(
char
[].
class
);
testTypedVarargsArray
(
float
[].
class
);
testTypedVarargsArray
(
double
[].
class
);
}
private
static
int
nextArgCount
(
int
nargs
,
int
density
,
int
MAX
)
{
if
(
EXHAUSTIVE
)
return
nargs
+
1
;
if
(
nargs
>=
MAX
)
return
Integer
.
MAX_VALUE
;
int
BOT
=
20
,
TOP
=
MAX
-
5
;
if
(
density
<
10
)
{
BOT
=
10
;
MAX
=
TOP
-
2
;
}
if
(
nargs
<=
BOT
||
nargs
>=
TOP
)
{
++
nargs
;
}
else
{
int
bump
=
Math
.
max
(
1
,
100
/
density
);
nargs
+=
bump
;
if
(
nargs
>
TOP
)
nargs
=
TOP
;
}
return
nargs
;
}
private
void
testTypedVarargsArray
(
Class
<?>
arrayType
)
throws
Throwable
{
//System.out.println(arrayType.getSimpleName());
Class
<?>
elemType
=
arrayType
.
getComponentType
();
int
MIN
=
START_ARITY
;
int
MAX
=
MAX_ARITY
-
2
;
// 253+1 would cause parameter overflow with 'this' added
int
density
=
3
;
if
(
elemType
==
int
.
class
||
elemType
==
long
.
class
)
density
=
7
;
if
(
elemType
==
long
.
class
||
elemType
==
double
.
class
)
{
MAX
/=
2
;
MIN
/=
2
;
}
for
(
int
nargs
=
MIN
;
nargs
<=
MAX
;
nargs
=
nextArgCount
(
nargs
,
density
,
MAX
))
{
Object
[]
args
=
makeTestArray
(
elemType
,
nargs
);
MethodHandle
varargsArray
=
ValueConversions
.
varargsArray
(
arrayType
,
nargs
);
MethodType
vaType
=
varargsArray
.
type
();
assertEquals
(
arrayType
,
vaType
.
returnType
());
if
(
nargs
!=
0
)
{
assertEquals
(
elemType
,
vaType
.
parameterType
(
0
));
assertEquals
(
elemType
,
vaType
.
parameterType
(
vaType
.
parameterCount
()-
1
));
}
assertEquals
(
MethodType
.
methodType
(
arrayType
,
Collections
.<
Class
<?>>
nCopies
(
nargs
,
elemType
)),
vaType
);
Object
res
=
varargsArray
.
invokeWithArguments
(
args
);
String
resString
=
toArrayString
(
res
);
assertEquals
(
Arrays
.
toString
(
args
),
resString
);
MethodHandle
spreader
=
varargsArray
.
asSpreader
(
arrayType
,
nargs
);
MethodType
stype
=
spreader
.
type
();
assert
(
stype
==
MethodType
.
methodType
(
arrayType
,
arrayType
));
if
(
nargs
<=
5
)
{
// invoke target as a spreader also:
@SuppressWarnings
(
"cast"
)
Object
res2
=
spreader
.
invokeWithArguments
((
Object
)
res
);
String
res2String
=
toArrayString
(
res2
);
assertEquals
(
Arrays
.
toString
(
args
),
res2String
);
// invoke the spreader on a generic Object[] array; check for error
try
{
Object
res3
=
spreader
.
invokeWithArguments
((
Object
)
args
);
String
res3String
=
toArrayString
(
res3
);
assertTrue
(
arrayType
.
getName
(),
arrayType
.
isAssignableFrom
(
Object
[].
class
));
assertEquals
(
Arrays
.
toString
(
args
),
res3String
);
}
catch
(
ClassCastException
ex
)
{
assertFalse
(
arrayType
.
getName
(),
arrayType
.
isAssignableFrom
(
Object
[].
class
));
}
}
if
(
nargs
==
0
)
{
// invoke spreader on null arglist
Object
res3
=
spreader
.
invokeWithArguments
((
Object
)
null
);
String
res3String
=
toArrayString
(
res3
);
assertEquals
(
Arrays
.
toString
(
args
),
res3String
);
}
}
}
private
static
Object
[]
makeTestArray
(
Class
<?>
elemType
,
int
len
)
{
Wrapper
elem
=
null
;
if
(
elemType
.
isPrimitive
())
elem
=
Wrapper
.
forPrimitiveType
(
elemType
);
else
if
(
Wrapper
.
isWrapperType
(
elemType
))
elem
=
Wrapper
.
forWrapperType
(
elemType
);
Object
[]
args
=
new
Object
[
len
];
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
Object
arg
=
i
*
100
;
if
(
elem
==
null
)
{
if
(
elemType
==
String
.
class
)
arg
=
"#"
+
arg
;
arg
=
elemType
.
cast
(
arg
);
// just to make sure
}
else
{
switch
(
elem
)
{
case
BOOLEAN:
arg
=
(
i
%
3
==
0
);
break
;
case
CHAR:
arg
=
'a'
+
i
;
break
;
case
LONG:
arg
=
(
long
)
i
*
1000_000_000
;
break
;
case
FLOAT:
arg
=
(
float
)
i
/
100
;
break
;
case
DOUBLE:
arg
=
(
double
)
i
/
1000_000
;
break
;
}
arg
=
elem
.
cast
(
arg
,
elemType
);
}
args
[
i
]
=
arg
;
}
//System.out.println(elemType.getName()+Arrays.toString(args));
return
args
;
}
private
static
String
toArrayString
(
Object
a
)
{
if
(
a
==
null
)
return
"null"
;
Class
<?>
elemType
=
a
.
getClass
().
getComponentType
();
if
(
elemType
==
null
)
return
a
.
toString
();
if
(
elemType
.
isPrimitive
())
{
switch
(
Wrapper
.
forPrimitiveType
(
elemType
))
{
case
INT:
return
Arrays
.
toString
((
int
[])
a
);
case
BYTE:
return
Arrays
.
toString
((
byte
[])
a
);
case
BOOLEAN:
return
Arrays
.
toString
((
boolean
[])
a
);
case
SHORT:
return
Arrays
.
toString
((
short
[])
a
);
case
CHAR:
return
Arrays
.
toString
((
char
[])
a
);
case
FLOAT:
return
Arrays
.
toString
((
float
[])
a
);
case
LONG:
return
Arrays
.
toString
((
long
[])
a
);
case
DOUBLE:
return
Arrays
.
toString
((
double
[])
a
);
}
}
return
Arrays
.
toString
((
Object
[])
a
);
}
@Test
public
void
testVarargsList
()
throws
Throwable
{
//System.out.println("varargsList");
final
int
MIN
=
START_ARITY
;
final
int
MAX
=
MAX_ARITY
-
2
;
// 253+1 would cause parameter overflow with 'this' added
for
(
int
nargs
=
MIN
;
nargs
<=
MAX
;
nargs
=
nextArgCount
(
nargs
,
7
,
MAX
))
{
MethodHandle
target
=
ValueConversions
.
varargsList
(
nargs
);
Object
[]
args
=
new
Object
[
nargs
];
for
(
int
i
=
0
;
i
<
nargs
;
i
++)
args
[
i
]
=
"#"
+
i
;
Object
res
=
target
.
invokeWithArguments
(
args
);
assertEquals
(
Arrays
.
asList
(
args
),
res
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录