Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
ce297e28
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,发现更多精彩内容 >>
提交
ce297e28
编写于
6月 17, 2011
作者:
T
trims
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
9d1bfe47
58ce2f18
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
427 addition
and
59 deletion
+427
-59
src/share/classes/java/lang/invoke/AdapterMethodHandle.java
src/share/classes/java/lang/invoke/AdapterMethodHandle.java
+19
-14
src/share/classes/java/lang/invoke/MethodHandleImpl.java
src/share/classes/java/lang/invoke/MethodHandleImpl.java
+21
-19
src/share/classes/java/lang/invoke/MethodHandleNatives.java
src/share/classes/java/lang/invoke/MethodHandleNatives.java
+14
-25
src/share/classes/java/lang/invoke/SwitchPoint.java
src/share/classes/java/lang/invoke/SwitchPoint.java
+1
-1
test/java/lang/invoke/PermuteArgsTest.java
test/java/lang/invoke/PermuteArgsTest.java
+372
-0
未找到文件。
src/share/classes/java/lang/invoke/AdapterMethodHandle.java
浏览文件 @
ce297e28
...
...
@@ -405,13 +405,13 @@ class AdapterMethodHandle extends BoundMethodHandle {
insertStackMove
(
stackMove
)
);
}
private
static
long
makeSwapConv
(
int
convOp
,
int
srcArg
,
byte
type
,
int
destSlot
)
{
private
static
long
makeSwapConv
(
int
convOp
,
int
srcArg
,
byte
srcType
,
int
destSlot
,
byte
destType
)
{
// more complex argument motion, requiring two slots to specify
assert
(
convOp
==
OP_SWAP_ARGS
||
convOp
==
OP_ROT_ARGS
);
return
((
long
)
srcArg
<<
32
|
(
long
)
convOp
<<
CONV_OP_SHIFT
|
(
int
)
type
<<
CONV_SRC_TYPE_SHIFT
|
(
int
)
type
<<
CONV_DEST_TYPE_SHIFT
|
(
int
)
srcType
<<
CONV_SRC_TYPE_SHIFT
|
(
int
)
destType
<<
CONV_DEST_TYPE_SHIFT
|
(
int
)
destSlot
<<
CONV_VMINFO_SHIFT
);
}
...
...
@@ -943,24 +943,27 @@ class AdapterMethodHandle extends BoundMethodHandle {
if
(
type2size
(
newType
.
parameterType
(
swapArg1
))
!=
type2size
(
newType
.
parameterType
(
swapArg2
)))
{
// turn a swap into a pair of rotates:
// [x a b c y]
=> [a b c y x] =>
[y a b c x]
// [x a b c y]
rot2(-1,argc=5) => [a b c y x] rot1(+1,argc=4) => target
[y a b c x]
int
argc
=
swapArg2
-
swapArg1
+
1
;
final
int
ROT
=
1
;
ArrayList
<
Class
<?>>
rot1Params
=
new
ArrayList
<
Class
<?>>(
target
.
type
().
parameterList
());
Collections
.
rotate
(
rot1Params
.
subList
(
swapArg1
,
swapArg1
+
argc
),
-
ROT
);
MethodType
rot1Type
=
MethodType
.
methodType
(
target
.
type
().
returnType
(),
rot1Params
);
MethodHandle
rot1
=
makeRotateArguments
(
rot1Type
,
target
,
swapArg1
,
argc
,
+
ROT
);
assert
(
rot1
!=
null
);
if
(
argc
==
2
)
return
rot1
;
MethodHandle
rot2
=
makeRotateArguments
(
newType
,
rot1
,
swapArg1
,
argc
-
1
,
-
ROT
);
assert
(
rot2
!=
null
);
return
rot2
;
}
if
(!
canSwapArguments
(
newType
,
target
.
type
(),
swapArg1
,
swapArg2
))
return
null
;
Class
<?>
swapType
=
newType
.
parameterType
(
swapArg1
);
Class
<?>
type1
=
newType
.
parameterType
(
swapArg1
);
Class
<?>
type2
=
newType
.
parameterType
(
swapArg2
);
// in arglist: [0: ...keep1 | pos1: a1 | pos1+1: keep2... | pos2: a2 | pos2+1: keep3... ]
// out arglist: [0: ...keep1 | pos1: a2 | pos1+1: keep2... | pos2: a1 | pos2+1: keep3... ]
int
swapSlot2
=
newType
.
parameterSlotDepth
(
swapArg2
+
1
);
long
conv
=
makeSwapConv
(
OP_SWAP_ARGS
,
swapArg1
,
basicType
(
swapType
),
swapSlot2
);
long
conv
=
makeSwapConv
(
OP_SWAP_ARGS
,
swapArg1
,
basicType
(
type1
),
swapSlot2
,
basicType
(
type2
)
);
return
new
AdapterMethodHandle
(
target
,
newType
,
conv
);
}
...
...
@@ -1029,16 +1032,16 @@ class AdapterMethodHandle extends BoundMethodHandle {
assert
(
MAX_ARG_ROTATION
==
1
);
int
srcArg
,
dstArg
;
int
dstSlot
;
byte
basicType
;
if
(
chunk2Slots
<=
chunk1Slots
)
{
int
moveChunk
;
if
(
rotateBy
==
1
)
{
// Rotate right/down N (rotateBy = +N, N small, c2 small):
// in arglist: [0: ...keep1 | arg1: c1... | limit-N: c2 | limit: keep2... ]
// out arglist: [0: ...keep1 | arg1: c2 | arg1+N: c1... | limit: keep2... ]
srcArg
=
limit
-
1
;
dstArg
=
firstArg
;
dstSlot
=
depth0
-
chunk2Slots
;
basicType
=
basicType
(
newType
.
parameterType
(
srcArg
))
;
assert
(
chunk2Slots
==
type2size
(
basicType
))
;
//dstSlot = depth0 - chunk2Slots; //chunk2Slots is not relevant
dstSlot
=
depth0
+
MethodHandleNatives
.
OP_ROT_ARGS_DOWN_LIMIT_BIAS
;
moveChunk
=
chunk2Slots
;
}
else
{
// Rotate left/up N (rotateBy = -N, N small, c1 small):
// in arglist: [0: ...keep1 | arg1: c1 | arg1+N: c2... | limit: keep2... ]
...
...
@@ -1046,10 +1049,12 @@ class AdapterMethodHandle extends BoundMethodHandle {
srcArg
=
firstArg
;
dstArg
=
limit
-
1
;
dstSlot
=
depth2
;
basicType
=
basicType
(
newType
.
parameterType
(
srcArg
));
assert
(
chunk1Slots
==
type2size
(
basicType
));
moveChunk
=
chunk1Slots
;
}
long
conv
=
makeSwapConv
(
OP_ROT_ARGS
,
srcArg
,
basicType
,
dstSlot
);
byte
srcType
=
basicType
(
newType
.
parameterType
(
srcArg
));
byte
dstType
=
basicType
(
newType
.
parameterType
(
dstArg
));
assert
(
moveChunk
==
type2size
(
srcType
));
long
conv
=
makeSwapConv
(
OP_ROT_ARGS
,
srcArg
,
srcType
,
dstSlot
,
dstType
);
return
new
AdapterMethodHandle
(
target
,
newType
,
conv
);
}
...
...
src/share/classes/java/lang/invoke/MethodHandleImpl.java
浏览文件 @
ce297e28
...
...
@@ -788,6 +788,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
.
insertParameterTypes
(
keepPosArgs
,
arrayType
);
return
spreadArguments
(
target
,
newType
,
keepPosArgs
,
arrayType
,
arrayLength
);
}
// called internally only
static
MethodHandle
spreadArgumentsFromPos
(
MethodHandle
target
,
MethodType
newType
,
int
spreadArgPos
)
{
int
arrayLength
=
target
.
type
().
parameterCount
()
-
spreadArgPos
;
return
spreadArguments
(
target
,
newType
,
spreadArgPos
,
Object
[].
class
,
arrayLength
);
...
...
@@ -849,6 +850,12 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
MethodType
ttype
=
target
.
type
();
MethodType
ftype
=
filter
.
type
();
assert
(
ftype
.
parameterCount
()
==
1
);
MethodHandle
result
=
null
;
if
(
AdapterMethodHandle
.
canCollectArguments
(
ttype
,
ftype
,
pos
,
false
))
{
result
=
AdapterMethodHandle
.
makeCollectArguments
(
target
,
filter
,
pos
,
false
);
if
(
result
!=
null
)
return
result
;
}
assert
(
MethodHandleNatives
.
workaroundWithoutRicochetFrames
());
// this code is deprecated
MethodType
rtype
=
ttype
.
changeParameterType
(
pos
,
ftype
.
parameterType
(
0
));
MethodType
gttype
=
ttype
.
generic
();
if
(
ttype
!=
gttype
)
{
...
...
@@ -860,18 +867,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
filter
=
convertArguments
(
filter
,
gftype
,
ftype
,
0
);
ftype
=
gftype
;
}
MethodHandle
result
=
null
;
if
(
AdapterMethodHandle
.
canCollectArguments
(
ttype
,
ftype
,
pos
,
false
))
{
result
=
AdapterMethodHandle
.
makeCollectArguments
(
target
,
filter
,
pos
,
false
);
}
if
(
result
==
null
)
{
assert
(
MethodHandleNatives
.
workaroundWithoutRicochetFrames
());
// this code is deprecated
if
(
ftype
==
ttype
)
{
if
(
ftype
==
ttype
)
{
// simple unary case
result
=
FilterOneArgument
.
make
(
filter
,
target
);
}
else
{
result
=
FilterGeneric
.
makeArgumentFilter
(
pos
,
filter
,
target
);
}
result
=
FilterOneArgument
.
make
(
filter
,
target
);
}
else
{
result
=
FilterGeneric
.
makeArgumentFilter
(
pos
,
filter
,
target
);
}
if
(
result
.
type
()
!=
rtype
)
result
=
result
.
asType
(
rtype
);
...
...
@@ -920,7 +920,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
this
.
fallback
=
fallback
;
}
static
boolean
preferRicochetFrame
(
MethodType
type
)
{
return
(
type
.
parameterCount
()
>=
INVOKES
.
length
||
type
.
hasPrimitives
());
return
true
;
// always use RF if available
}
static
MethodHandle
make
(
MethodHandle
test
,
MethodHandle
target
,
MethodHandle
fallback
)
{
MethodType
type
=
target
.
type
();
...
...
@@ -931,12 +931,13 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
MethodHandle
invoke
=
INVOKES
[
nargs
];
MethodType
gtype
=
type
.
generic
();
assert
(
invoke
.
type
().
dropParameterTypes
(
0
,
1
)
==
gtype
);
MethodHandle
gtest
=
convertArguments
(
test
,
gtype
.
changeReturnType
(
boolean
.
class
),
test
.
type
(),
0
);
MethodHandle
gtarget
=
convertArguments
(
target
,
gtype
,
type
,
0
);
MethodHandle
gfallback
=
convertArguments
(
fallback
,
gtype
,
type
,
0
);
// Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
MethodHandle
gtest
=
convertArguments
(
test
,
gtype
.
changeReturnType
(
boolean
.
class
),
test
.
type
(),
2
);
MethodHandle
gtarget
=
convertArguments
(
target
,
gtype
,
type
,
2
);
MethodHandle
gfallback
=
convertArguments
(
fallback
,
gtype
,
type
,
2
);
if
(
gtest
==
null
||
gtarget
==
null
||
gfallback
==
null
)
return
null
;
MethodHandle
gguard
=
new
GuardWithTest
(
invoke
,
gtest
,
gtarget
,
gfallback
);
return
convertArguments
(
gguard
,
type
,
gtype
,
0
);
return
convertArguments
(
gguard
,
type
,
gtype
,
2
);
}
else
{
assert
(
MethodHandleNatives
.
workaroundWithoutRicochetFrames
());
// this code is deprecated
MethodHandle
invoke
=
VARARGS_INVOKE
;
...
...
@@ -1221,11 +1222,12 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
if
(
nargs
<
GuardWithCatch
.
INVOKES
.
length
)
{
MethodType
gtype
=
type
.
generic
();
MethodType
gcatchType
=
gtype
.
insertParameterTypes
(
0
,
Throwable
.
class
);
MethodHandle
gtarget
=
convertArguments
(
target
,
gtype
,
type
,
0
);
MethodHandle
gcatcher
=
convertArguments
(
catcher
,
gcatchType
,
ctype
,
0
);
// Note: convertArguments(...2) avoids interface casts present in convertArguments(...0)
MethodHandle
gtarget
=
convertArguments
(
target
,
gtype
,
type
,
2
);
MethodHandle
gcatcher
=
convertArguments
(
catcher
,
gcatchType
,
ctype
,
2
);
MethodHandle
gguard
=
new
GuardWithCatch
(
gtarget
,
exType
,
gcatcher
);
if
(
gtarget
==
null
||
gcatcher
==
null
||
gguard
==
null
)
return
null
;
return
convertArguments
(
gguard
,
type
,
gtype
,
0
);
return
convertArguments
(
gguard
,
type
,
gtype
,
2
);
}
else
{
MethodType
gtype
=
MethodType
.
genericMethodType
(
0
,
true
);
MethodType
gcatchType
=
gtype
.
insertParameterTypes
(
0
,
Throwable
.
class
);
...
...
src/share/classes/java/lang/invoke/MethodHandleNatives.java
浏览文件 @
ce297e28
...
...
@@ -118,32 +118,20 @@ class MethodHandleNatives {
/** Derived mode flag. Only false on some old JVM implementations. */
static
final
boolean
HAVE_RICOCHET_FRAMES
;
static
final
int
OP_ROT_ARGS_DOWN_LIMIT_BIAS
;
private
static
native
void
registerNatives
();
static
{
int
JVM_PUSH_LIMIT_
;
int
JVM_STACK_MOVE_UNIT_
;
int
CONV_OP_IMPLEMENTED_MASK_
;
try
{
registerNatives
();
JVM_PUSH_LIMIT_
=
getConstant
(
Constants
.
GC_JVM_PUSH_LIMIT
);
JVM_STACK_MOVE_UNIT_
=
getConstant
(
Constants
.
GC_JVM_STACK_MOVE_UNIT
);
CONV_OP_IMPLEMENTED_MASK_
=
getConstant
(
Constants
.
GC_CONV_OP_IMPLEMENTED_MASK
);
//sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
}
catch
(
UnsatisfiedLinkError
ee
)
{
// ignore; if we use init() methods later we'll see linkage errors
JVM_PUSH_LIMIT_
=
3
;
// arbitrary
JVM_STACK_MOVE_UNIT_
=
-
1
;
// arbitrary
CONV_OP_IMPLEMENTED_MASK_
=
0
;
JVM_PUSH_LIMIT
=
JVM_PUSH_LIMIT_
;
JVM_STACK_MOVE_UNIT
=
JVM_STACK_MOVE_UNIT_
;
throw
ee
;
// just die; hopeless to try to run with an older JVM
}
JVM_PUSH_LIMIT
=
JVM_PUSH_LIMIT_
;
JVM_STACK_MOVE_UNIT
=
JVM_STACK_MOVE_UNIT_
;
if
(
CONV_OP_IMPLEMENTED_MASK_
==
0
)
CONV_OP_IMPLEMENTED_MASK_
=
DEFAULT_CONV_OP_IMPLEMENTED_MASK
;
CONV_OP_IMPLEMENTED_MASK
=
CONV_OP_IMPLEMENTED_MASK_
;
HAVE_RICOCHET_FRAMES
=
(
CONV_OP_IMPLEMENTED_MASK
&
(
1
<<
OP_COLLECT_ARGS
))
!=
0
;
registerNatives
();
int
k
;
JVM_PUSH_LIMIT
=
getConstant
(
Constants
.
GC_JVM_PUSH_LIMIT
);
JVM_STACK_MOVE_UNIT
=
getConstant
(
Constants
.
GC_JVM_STACK_MOVE_UNIT
);
k
=
getConstant
(
Constants
.
GC_CONV_OP_IMPLEMENTED_MASK
);
CONV_OP_IMPLEMENTED_MASK
=
(
k
!=
0
)
?
k
:
DEFAULT_CONV_OP_IMPLEMENTED_MASK
;
k
=
getConstant
(
Constants
.
GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS
);
OP_ROT_ARGS_DOWN_LIMIT_BIAS
=
(
k
!=
0
)
?
(
byte
)
k
:
-
1
;
HAVE_RICOCHET_FRAMES
=
(
CONV_OP_IMPLEMENTED_MASK
&
(
1
<<
OP_COLLECT_ARGS
))
!=
0
;
//sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
}
// All compile-time constants go here.
...
...
@@ -154,7 +142,8 @@ class MethodHandleNatives {
static
final
int
// for getConstant
GC_JVM_PUSH_LIMIT
=
0
,
GC_JVM_STACK_MOVE_UNIT
=
1
,
GC_CONV_OP_IMPLEMENTED_MASK
=
2
;
GC_CONV_OP_IMPLEMENTED_MASK
=
2
,
GC_OP_ROT_ARGS_DOWN_LIMIT_BIAS
=
3
;
static
final
int
ETF_HANDLE_OR_METHOD_NAME
=
0
,
// all available data (immediate MH or method)
ETF_DIRECT_HANDLE
=
1
,
// ultimate method handle (will be a DMH, may be self)
...
...
src/share/classes/java/lang/invoke/SwitchPoint.java
浏览文件 @
ce297e28
...
...
@@ -134,7 +134,7 @@ public class SwitchPoint {
* to return true for {@code hasBeenInvalidated},
* it will always do so in the future.
* On the other hand, a valid switch point visible to other threads may
* invalidated at any moment, due to a request by another thread.
*
be
invalidated at any moment, due to a request by another thread.
* <p style="font-size:smaller;">
* Since invalidation is a global and immediate operation,
* the execution of this query, on a valid switchpoint,
...
...
test/java/lang/invoke/PermuteArgsTest.java
0 → 100644
浏览文件 @
ce297e28
/*
* Copyright (c) 2011, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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
* @summary unit tests for method handles which permute their arguments
* @run junit/othervm -ea -esa -DPermuteArgsTest.MAX_ARITY=8 test.java.lang.invoke.PermuteArgsTest
*/
/* Examples of manual runs:
* java -DPermuteArgsTest.{DRY_RUN=true,MAX_ARITY=253} test.java.lang.invoke.PermuteArgsTest
* java -DPermuteArgsTest.{VERBOSE=true,MAX_ARITY=5} test.java.lang.invoke.PermuteArgsTest
* java test.java.lang.invoke.PermuteArgsTest list3I[2,0,1] listJLJ[2,0,1]
*/
package
test.java.lang.invoke
;
import
org.junit.*
;
import
java.util.*
;
import
java.lang.reflect.*
;
import
java.lang.invoke.*
;
import
static
java
.
lang
.
invoke
.
MethodHandles
.*;
import
static
java
.
lang
.
invoke
.
MethodType
.*;
public
class
PermuteArgsTest
{
private
static
final
Class
CLASS
=
PermuteArgsTest
.
class
;
private
static
final
int
MAX_ARITY
=
Integer
.
getInteger
(
CLASS
.
getSimpleName
()+
".MAX_ARITY"
,
8
);
private
static
final
boolean
DRY_RUN
=
Boolean
.
getBoolean
(
CLASS
.
getSimpleName
()+
".DRY_RUN"
);
private
static
final
boolean
VERBOSE
=
Boolean
.
getBoolean
(
CLASS
.
getSimpleName
()+
".VERBOSE"
)
||
DRY_RUN
;
static
Object
list2I
(
int
x
,
int
y
)
{
return
Arrays
.
asList
(
x
,
y
);
}
static
Object
list3I
(
int
x
,
int
y
,
int
z
)
{
return
Arrays
.
asList
(
x
,
y
,
z
);
}
static
Object
list4I
(
int
w
,
int
x
,
int
y
,
int
z
)
{
return
Arrays
.
asList
(
w
,
x
,
y
,
z
);
}
static
Object
list2J
(
long
x
,
long
y
)
{
return
Arrays
.
asList
(
x
,
y
);
}
static
Object
list3J
(
long
x
,
long
y
,
long
z
)
{
return
Arrays
.
asList
(
x
,
y
,
z
);
}
static
Object
list4J
(
long
w
,
long
x
,
long
y
,
long
z
)
{
return
Arrays
.
asList
(
w
,
x
,
y
,
z
);
}
static
Object
list2I2J
(
int
w
,
int
x
,
long
y
,
long
z
)
{
return
Arrays
.
asList
(
w
,
x
,
y
,
z
);
}
static
Object
list2J2I
(
long
w
,
long
x
,
int
y
,
int
z
)
{
return
Arrays
.
asList
(
w
,
x
,
y
,
z
);
}
static
Object
listLJJ
(
Object
x
,
long
y
,
long
z
)
{
return
Arrays
.
asList
(
x
,
y
,
z
);
}
static
Object
listJLJ
(
long
x
,
Object
y
,
long
z
)
{
return
Arrays
.
asList
(
x
,
y
,
z
);
}
static
Object
listJJL
(
long
x
,
long
y
,
Object
z
)
{
return
Arrays
.
asList
(
x
,
y
,
z
);
}
static
Object
listJLL
(
long
x
,
Object
y
,
Object
z
)
{
return
Arrays
.
asList
(
x
,
y
,
z
);
}
static
Object
listLJL
(
Object
x
,
long
y
,
Object
z
)
{
return
Arrays
.
asList
(
x
,
y
,
z
);
}
static
Object
listLLJ
(
Object
x
,
Object
y
,
long
z
)
{
return
Arrays
.
asList
(
x
,
y
,
z
);
}
static
Object
listJLLJ
(
long
w
,
Object
x
,
Object
y
,
long
z
)
{
return
Arrays
.
asList
(
w
,
x
,
y
,
z
);
}
static
Object
listLJJL
(
Object
w
,
long
x
,
long
y
,
Object
z
)
{
return
Arrays
.
asList
(
w
,
x
,
y
,
z
);
}
static
Object
listI_etc
(
int
...
va
)
{
ArrayList
<
Object
>
res
=
new
ArrayList
<
Object
>();
for
(
int
x
:
va
)
res
.
add
(
x
);
return
res
;
}
static
Object
listIJL_etc
(
int
x
,
long
y
,
Object
z
,
Object
...
va
)
{
ArrayList
<
Object
>
res
=
new
ArrayList
<
Object
>();
res
.
addAll
(
Arrays
.
asList
(
x
,
y
,
z
));
res
.
addAll
(
Arrays
.
asList
(
va
));
return
res
;
}
public
static
void
main
(
String
argv
[])
throws
Throwable
{
if
(
argv
.
length
>
0
)
{
for
(
String
arg
:
argv
)
{
// arg ::= name[n,...]
int
k
=
arg
.
indexOf
(
'['
);
String
mhName
=
arg
.
substring
(
0
,
k
).
trim
();
String
permString
=
arg
.
substring
(
k
);
testOnePermutation
(
mhName
,
permString
);
}
return
;
}
new
PermuteArgsTest
().
test
();
}
static
int
testCases
;
@Test
public
void
test
()
throws
Throwable
{
testCases
=
0
;
Lookup
lookup
=
lookup
();
for
(
Method
m
:
lookup
.
lookupClass
().
getDeclaredMethods
())
{
if
(
m
.
getName
().
startsWith
(
"list"
)
&&
Modifier
.
isStatic
(
m
.
getModifiers
()))
{
test
(
m
.
getName
(),
lookup
.
unreflect
(
m
));
}
}
System
.
out
.
println
(
"ran a total of "
+
testCases
+
" test cases"
);
}
static
int
jump
(
int
i
,
int
min
,
int
max
)
{
if
(
i
>=
min
&&
i
<=
max
-
1
)
{
// jump faster
int
len
=
max
-
min
;
if
(
i
<
min
+
len
/
2
)
i
=
min
+
len
/
2
;
else
i
=
max
-
1
;
}
return
i
;
}
static
void
test
(
String
name
,
MethodHandle
mh
)
throws
Throwable
{
if
(
VERBOSE
)
System
.
out
.
println
(
"mh = "
+
name
+
" : "
+
mh
+
" { "
+
Arrays
.
toString
(
junkArgs
(
mh
.
type
().
parameterArray
())));
int
testCases0
=
testCases
;
if
(!
mh
.
isVarargsCollector
())
{
// normal case
testPermutations
(
mh
);
}
else
{
// varargs case; add params up to MAX_ARITY
MethodType
mt
=
mh
.
type
();
int
posArgs
=
mt
.
parameterCount
()
-
1
;
int
arity0
=
Math
.
max
(
3
,
posArgs
);
for
(
int
arity
=
arity0
;
arity
<=
MAX_ARITY
;
arity
++)
{
MethodHandle
mh1
;
try
{
mh1
=
adjustArity
(
mh
,
arity
);
}
catch
(
IllegalArgumentException
ex
)
{
System
.
out
.
println
(
"*** mh = "
+
name
+
" : "
+
mh
+
"; arity = "
+
arity
+
" => "
+
ex
);
ex
.
printStackTrace
();
break
;
// cannot get this arity for this type
}
test
(
"("
+
arity
+
")"
+
name
,
mh1
);
arity
=
jump
(
arity
,
arity0
*
2
,
MAX_ARITY
);
}
}
if
(
VERBOSE
)
System
.
out
.
println
(
"ran "
+(
testCases
-
testCases0
)+
" test cases for "
+
name
+
" }"
);
}
static
MethodHandle
adjustArity
(
MethodHandle
mh
,
int
arity
)
{
MethodType
mt
=
mh
.
type
();
int
posArgs
=
mt
.
parameterCount
()
-
1
;
Class
<?>
reptype
=
mt
.
parameterType
(
posArgs
).
getComponentType
();
MethodType
mt1
=
mt
.
dropParameterTypes
(
posArgs
,
posArgs
+
1
);
while
(
mt1
.
parameterCount
()
<
arity
)
{
Class
<?>
pt
=
reptype
;
if
(
pt
==
Object
.
class
&&
posArgs
>
0
)
// repeat types cyclically if possible:
pt
=
mt1
.
parameterType
(
mt1
.
parameterCount
()
-
posArgs
);
mt1
=
mt1
.
appendParameterTypes
(
pt
);
}
return
mh
.
asType
(
mt1
);
}
static
MethodHandle
findTestMH
(
String
name
,
int
[]
perm
)
throws
ReflectiveOperationException
{
int
arity
=
perm
.
length
;
Lookup
lookup
=
lookup
();
for
(
Method
m
:
lookup
.
lookupClass
().
getDeclaredMethods
())
{
if
(
m
.
getName
().
equals
(
name
)
&&
Modifier
.
isStatic
(
m
.
getModifiers
()))
{
MethodHandle
mh
=
lookup
.
unreflect
(
m
);
int
mhArity
=
mh
.
type
().
parameterCount
();
if
(
mh
.
isVarargsCollector
())
{
if
(
mhArity
-
1
<=
arity
)
return
adjustArity
(
mh
,
arity
);
}
else
if
(
mhArity
==
arity
)
{
return
mh
;
}
}
}
throw
new
RuntimeException
(
"no such method for arity "
+
arity
+
": "
+
name
);
}
static
void
testPermutations
(
MethodHandle
mh
)
throws
Throwable
{
HashSet
<
String
>
done
=
new
HashSet
<
String
>();
MethodType
mt
=
mh
.
type
();
int
[]
perm
=
nullPerm
(
mt
.
parameterCount
());
final
int
MARGIN
=
(
perm
.
length
<=
10
?
2
:
0
);
int
testCases0
=
testCases
;
for
(
int
j
=
0
;
j
<=
1
;
j
++)
{
int
maxStart
=
perm
.
length
-
1
;
if
(
j
!=
0
)
maxStart
/=
2
;
for
(
int
start
=
0
;
start
<=
maxStart
;
start
++)
{
int
maxOmit
=
(
maxStart
-
start
)
/
2
;
if
(
start
!=
0
)
maxOmit
=
2
;
if
(
j
!=
0
)
maxOmit
=
1
;
for
(
int
omit
=
0
;
omit
<=
maxOmit
;
omit
++)
{
int
end
=
perm
.
length
-
omit
;
if
(
end
-
start
>=
2
)
{
//System.out.println("testPermutations"+Arrays.asList(start, end)+(j == 0 ? "" : " (reverse)"));
testPermutations
(
mh
,
perm
,
start
,
end
,
done
);
}
omit
=
jump
(
omit
,
(
start
==
0
&&
j
==
0
?
MARGIN
:
0
),
maxOmit
);
}
start
=
jump
(
start
,
(
j
==
0
?
MARGIN
:
0
),
maxStart
);
}
// do everything in reverse:
reverse
(
perm
,
0
,
perm
.
length
);
}
switch
(
perm
.
length
)
{
case
2
:
assert
(
testCases
-
testCases0
==
2
);
break
;
case
3
:
assert
(
testCases
-
testCases0
==
6
);
break
;
case
4
:
assert
(
testCases
-
testCases0
==
24
);
break
;
case
5
:
assert
(
testCases
-
testCases0
==
120
);
break
;
case
6
:
assert
(
testCases
-
testCases0
>
720
/
3
);
break
;
}
}
static
void
testPermutations
(
MethodHandle
mh
,
int
[]
perm
,
int
start
,
int
end
,
Set
<
String
>
done
)
throws
Throwable
{
if
(
end
-
start
<=
1
)
return
;
for
(
int
j
=
0
;
j
<=
1
;
j
++)
{
testRotations
(
mh
,
perm
,
start
,
end
,
done
);
if
(
end
-
start
<=
2
)
return
;
reverse
(
perm
,
start
,
end
);
}
if
(
end
-
start
<=
3
)
return
;
int
excess4
=
(
end
-
start
)
-
4
;
// composed rotations:
int
start2
=
start
+
1
+
excess4
/
3
;
int
end2
=
end
-
excess4
/
3
;
end2
=
start2
+
Math
.
min
(
start
==
0
?
4
:
3
,
end2
-
start2
);
int
skips
=
(
perm
.
length
+
3
)/
5
;
for
(
int
i
=
start
;
i
<
end
;
i
++)
{
rotate
(
perm
,
start
,
end
);
if
(
skips
>
1
&&
((
i
-
start
)
+
(
i
-
start
)/
7
)
%
skips
!=
0
)
continue
;
for
(
int
j
=
0
;
j
<=
1
;
j
++)
{
testPermutations
(
mh
,
perm
,
start2
,
end2
,
done
);
reverse
(
perm
,
start
,
end
);
}
}
}
static
void
testRotations
(
MethodHandle
mh
,
int
[]
perm
,
int
start
,
int
end
,
Set
<
String
>
done
)
throws
Throwable
{
Object
[]
args
=
junkArgs
(
mh
.
type
().
parameterArray
());
for
(
int
i
=
start
;
i
<
end
;
i
++)
{
if
(
done
.
add
(
Arrays
.
toString
(
perm
)))
testOnePermutation
(
mh
,
perm
,
args
);
rotate
(
perm
,
start
,
end
);
}
}
static
void
testOnePermutation
(
MethodHandle
mh
,
int
[]
perm
,
Object
[]
args
)
throws
Throwable
{
MethodType
mt
=
mh
.
type
();
MethodType
pmt
=
methodType
(
mt
.
returnType
(),
unpermuteArgs
(
perm
,
mt
.
parameterArray
(),
Class
[].
class
));
if
(
VERBOSE
)
System
.
out
.
println
(
Arrays
.
toString
(
perm
));
testCases
+=
1
;
if
(
DRY_RUN
)
return
;
Object
res
=
permuteArguments
(
mh
,
pmt
,
perm
).
invokeWithArguments
(
unpermuteArgs
(
perm
,
args
));
String
str
=
String
.
valueOf
(
res
);
if
(!
Arrays
.
toString
(
args
).
equals
(
str
))
{
System
.
out
.
println
(
Arrays
.
toString
(
perm
)+
" "
+
str
+
" *** WRONG ***"
);
}
}
// For reproducing failures:
static
void
testOnePermutation
(
String
mhName
,
String
permString
)
throws
Throwable
{
String
s
=
permString
;
s
=
s
.
replace
(
'['
,
' '
).
replace
(
']'
,
' '
).
replace
(
','
,
' '
);
// easier to trim spaces
s
=
s
.
trim
();
int
[]
perm
=
new
int
[
s
.
length
()];
int
arity
=
0
;
while
(!
s
.
isEmpty
())
{
int
k
=
s
.
indexOf
(
' '
);
if
(
k
<
0
)
k
=
s
.
length
();
perm
[
arity
++]
=
Integer
.
parseInt
(
s
.
substring
(
0
,
k
));
s
=
s
.
substring
(
k
).
trim
();
}
perm
=
Arrays
.
copyOf
(
perm
,
arity
);
testOnePermutation
(
mhName
,
perm
);
}
static
void
testOnePermutation
(
String
mhName
,
int
[]
perm
)
throws
Throwable
{
MethodHandle
mh
=
findTestMH
(
mhName
,
perm
);
System
.
out
.
println
(
"mh = "
+
mhName
+
" : "
+
mh
+
" { "
+
Arrays
.
toString
(
junkArgs
(
mh
.
type
().
parameterArray
())));
Object
[]
args
=
junkArgs
(
mh
.
type
().
parameterArray
());
testOnePermutation
(
mh
,
perm
,
args
);
System
.
out
.
println
(
"}"
);
}
static
Object
[]
junkArgs
(
Class
<?>[]
ptypes
)
{
Object
[]
args
=
new
Object
[
ptypes
.
length
];
for
(
int
i
=
0
;
i
<
ptypes
.
length
;
i
++)
{
Class
<?>
pt
=
ptypes
[
i
];
Object
arg
;
if
(
pt
==
Void
.
class
)
arg
=
null
;
else
if
(
pt
==
int
.
class
)
arg
=
(
int
)
i
+
101
;
else
if
(
pt
==
long
.
class
)
arg
=
(
long
)
i
+
10_000_000_001L
;
else
arg
=
"#"
+
(
i
+
1
);
args
[
i
]
=
arg
;
}
return
args
;
}
static
int
[]
nullPerm
(
int
len
)
{
int
[]
perm
=
new
int
[
len
];
for
(
int
i
=
0
;
i
<
len
;
i
++)
perm
[
i
]
=
i
;
return
perm
;
}
static
void
rotate
(
int
[]
perm
)
{
rotate
(
perm
,
0
,
perm
.
length
);
}
static
void
rotate
(
int
[]
perm
,
int
start
,
int
end
)
{
int
x
=
perm
[
end
-
1
];
for
(
int
j
=
start
;
j
<
end
;
j
++)
{
int
y
=
perm
[
j
];
perm
[
j
]
=
x
;
x
=
y
;
}
}
static
void
reverse
(
int
[]
perm
)
{
reverse
(
perm
,
0
,
perm
.
length
);
}
static
void
reverse
(
int
[]
perm
,
int
start
,
int
end
)
{
int
mid
=
start
+
(
end
-
start
)/
2
;
for
(
int
j
=
start
;
j
<
mid
;
j
++)
{
int
k
=
(
end
-
1
)
-
j
;
int
x
=
perm
[
j
];
perm
[
j
]
=
perm
[
k
];
perm
[
k
]
=
x
;
}
}
// Permute the args according to the inverse of perm.
static
Object
[]
unpermuteArgs
(
int
[]
perm
,
Object
[]
args
)
{
return
unpermuteArgs
(
perm
,
args
,
Object
[].
class
);
}
static
<
T
>
T
[]
unpermuteArgs
(
int
[]
perm
,
T
[]
args
,
Class
<
T
[]>
Tclass
)
{
T
[]
res
=
Arrays
.
copyOf
(
new
Object
[
0
],
perm
.
length
,
Tclass
);
for
(
int
i
=
0
;
i
<
perm
.
length
;
i
++)
res
[
perm
[
i
]]
=
args
[
i
];
return
res
;
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录