Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
5150d263
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,发现更多精彩内容 >>
提交
5150d263
编写于
10月 30, 2010
作者:
J
jrose
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6981777: implement JSR 292 EG adjustments from summer 2010
Reviewed-by: twisti
上级
70e0218c
变更
29
展开全部
隐藏空白更改
内联
并排
Showing
29 changed file
with
1571 addition
and
1471 deletion
+1571
-1471
src/share/classes/java/dyn/BootstrapMethod.java
src/share/classes/java/dyn/BootstrapMethod.java
+0
-82
src/share/classes/java/dyn/CallSite.java
src/share/classes/java/dyn/CallSite.java
+116
-122
src/share/classes/java/dyn/ConstantCallSite.java
src/share/classes/java/dyn/ConstantCallSite.java
+5
-3
src/share/classes/java/dyn/InvokeDynamic.java
src/share/classes/java/dyn/InvokeDynamic.java
+0
-80
src/share/classes/java/dyn/Linkage.java
src/share/classes/java/dyn/Linkage.java
+22
-120
src/share/classes/java/dyn/LinkagePermission.java
src/share/classes/java/dyn/LinkagePermission.java
+0
-102
src/share/classes/java/dyn/MethodHandle.java
src/share/classes/java/dyn/MethodHandle.java
+248
-160
src/share/classes/java/dyn/MethodHandleProvider.java
src/share/classes/java/dyn/MethodHandleProvider.java
+0
-80
src/share/classes/java/dyn/MethodHandles.java
src/share/classes/java/dyn/MethodHandles.java
+442
-244
src/share/classes/java/dyn/MethodType.java
src/share/classes/java/dyn/MethodType.java
+9
-63
src/share/classes/java/dyn/VolatileCallSite.java
src/share/classes/java/dyn/VolatileCallSite.java
+144
-0
src/share/classes/java/dyn/package-info.java
src/share/classes/java/dyn/package-info.java
+192
-97
src/share/classes/sun/dyn/AdapterMethodHandle.java
src/share/classes/sun/dyn/AdapterMethodHandle.java
+1
-1
src/share/classes/sun/dyn/BoundMethodHandle.java
src/share/classes/sun/dyn/BoundMethodHandle.java
+16
-8
src/share/classes/sun/dyn/CallSiteImpl.java
src/share/classes/sun/dyn/CallSiteImpl.java
+40
-8
src/share/classes/sun/dyn/FilterGeneric.java
src/share/classes/sun/dyn/FilterGeneric.java
+4
-4
src/share/classes/sun/dyn/FilterOneArgument.java
src/share/classes/sun/dyn/FilterOneArgument.java
+2
-2
src/share/classes/sun/dyn/FromGeneric.java
src/share/classes/sun/dyn/FromGeneric.java
+3
-3
src/share/classes/sun/dyn/Invokers.java
src/share/classes/sun/dyn/Invokers.java
+33
-0
src/share/classes/sun/dyn/JavaMethodHandle.java
src/share/classes/sun/dyn/JavaMethodHandle.java
+0
-172
src/share/classes/sun/dyn/MethodHandleImpl.java
src/share/classes/sun/dyn/MethodHandleImpl.java
+22
-19
src/share/classes/sun/dyn/SpreadGeneric.java
src/share/classes/sun/dyn/SpreadGeneric.java
+4
-4
src/share/classes/sun/dyn/ToGeneric.java
src/share/classes/sun/dyn/ToGeneric.java
+4
-4
src/share/classes/sun/dyn/util/ValueConversions.java
src/share/classes/sun/dyn/util/ValueConversions.java
+4
-2
src/share/classes/sun/dyn/util/VerifyAccess.java
src/share/classes/sun/dyn/util/VerifyAccess.java
+5
-22
src/share/classes/sun/dyn/util/Wrapper.java
src/share/classes/sun/dyn/util/Wrapper.java
+80
-11
test/java/dyn/InvokeGenericTest.java
test/java/dyn/InvokeGenericTest.java
+1
-1
test/java/dyn/JavaDocExamplesTest.java
test/java/dyn/JavaDocExamplesTest.java
+78
-8
test/java/dyn/MethodHandlesTest.java
test/java/dyn/MethodHandlesTest.java
+96
-49
未找到文件。
src/share/classes/java/dyn/BootstrapMethod.java
已删除
100644 → 0
浏览文件 @
70e0218c
/*
* Copyright (c) 2010, 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.
*/
package
java.dyn
;
import
java.lang.annotation.*
;
/**
* Annotation on InvokeDynamic method calls which requests the JVM to use a specific
* <a href="package-summary.html#bsm">bootstrap method</a>
* to link the call. This annotation is not retained as such in the class file,
* but is transformed into a constant-pool entry for the invokedynamic instruction which
* specifies the desired bootstrap method.
* <p>
* If only the <code>value</code> is given, it must name a subclass of {@link CallSite}
* with a constructor which accepts a class, string, and method type.
* If the <code>value</code> and <code>name</code> are both given, there must be
* a static method in the given class of the given name which accepts a class, string,
* and method type, and returns a reference coercible to {@link CallSite}.
* <p>
* This annotation can be placed either on the return type of a single {@link InvokeDynamic}
* call (see examples) or else it can be placed on an enclosing class or method, where it
* determines a default bootstrap method for any {@link InvokeDynamic} calls which are not
* specifically annotated with a bootstrap method.
* Every {@link InvokeDynamic} call must be given a bootstrap method.
* <p>
* Examples:
<blockquote><pre>
@BootstrapMethod(value=MyLanguageRuntime.class, name="bootstrapDynamic")
String x = (String) InvokeDynamic.greet();
//BSM => MyLanguageRuntime.bootstrapDynamic(Here.class, "greet", methodType(String.class))
@BootstrapMethod(MyCallSite.class)
void example() throws Throwable {
InvokeDynamic.greet();
//BSM => new MyCallSite(Here.class, "greet", methodType(void.class))
}
</pre></blockquote>
* <p>
*/
@Target
({
ElementType
.
TYPE_USE
,
// For defaulting every indy site within a class or method; cf. @SuppressWarnings:
ElementType
.
TYPE
,
ElementType
.
METHOD
,
ElementType
.
CONSTRUCTOR
})
@Retention
(
RetentionPolicy
.
SOURCE
)
public
@interface
BootstrapMethod
{
/** The class containing the bootstrap method. */
Class
<?>
value
();
/** The name of the bootstrap method.
* If this is the empty string, an instance of the bootstrap class is created,
* and a constructor is invoked.
* Otherwise, there must be a static method of the required name.
*/
String
name
()
default
""
;
// empty string denotes a constructor with 'new'
/** The argument types of the bootstrap method, as passed out by the JVM.
* There is usually no reason to override the default.
*/
Class
<?>[]
arguments
()
default
{
Class
.
class
,
String
.
class
,
MethodType
.
class
};
}
src/share/classes/java/dyn/CallSite.java
浏览文件 @
5150d263
...
...
@@ -26,40 +26,34 @@
package
java.dyn
;
import
sun.dyn.*
;
import
sun.dyn.empty.Empty
;
import
sun.misc.Unsafe
;
import
java.util.Collection
;
/**
* A {@code CallSite} is a holder for a variable {@link MethodHandle},
* which is called its {@code target}.
* Every call to a {@code CallSite} is delegated to the site's current target.
* An {@code invokedynamic} instruction linked to a {@code CallSite} delegates
* all calls to the site's current target.
* <p>
*
A call site is initially created in an <em>unlinked</em> state,
*
which is distinguished by a null target variable
.
*
Before the call site may be invoked (and before certain other
*
operations are attempted), the call site must be linked to
*
a non-null target
.
*
If a mutable target is not required, the {@code invokedynamic} instruction
*
should be linked to a {@linkplain ConstantCallSite constant call site}
.
*
If a volatile target is required, because updates to the target must be
*
reliably witnessed by other threads, the {@code invokedynamic} instruction
*
should be linked to a {@linkplain VolatileCallSite volatile call site}
.
* <p>
* A call site may be <em>relinked</em> by changing its target.
* The new target must be non-null and must have the same
* {@linkplain MethodHandle#type() type}
* The new target must have the same {@linkplain MethodHandle#type() type}
* as the previous target.
* Thus, though a call site can be relinked to a series of
* successive targets, it cannot change its type.
* <p>
* Linkage happens once in the lifetime of any given {@code CallSite} object.
* Because of call site invalidation, this linkage can be repeated for
* a single {@code invokedynamic} instruction, with multiple {@code CallSite} objects.
* When a {@code CallSite} is unlinked from an {@code invokedynamic} instruction,
* the instruction is reset so that it is no longer associated with
* the {@code CallSite} object, but the {@code CallSite} does not change
* state.
* <p>
* Here is a sample use of call sites and bootstrap methods which links every
* dynamic call site to print its arguments:
<blockquote><pre><!-- see indy-demo/src/PrintArgsDemo.java -->
@BootstrapMethod(value=PrintArgsDemo.class, name="bootstrapDynamic")
static void test() throws Throwable {
InvokeDynamic.baz("baz arg", 2, 3.14);
// THE FOLLOWING LINE IS PSEUDOCODE FOR A JVM INSTRUCTION
InvokeDynamic[#bootstrapDynamic].baz("baz arg", 2, 3.14);
}
private static void printArgs(Object... args) {
System.out.println(java.util.Arrays.deepToString(args));
...
...
@@ -71,16 +65,14 @@ static {
printArgs = lookup.findStatic(thisClass,
"printArgs", MethodType.methodType(void.class, Object[].class));
}
private static CallSite bootstrapDynamic(
Class
caller, String name, MethodType type) {
private static CallSite bootstrapDynamic(
MethodHandles.Lookup
caller, String name, MethodType type) {
// ignore caller and name, but match the type:
return new CallSite(MethodHandles.collectArguments(printArgs, type));
return new C
onstantC
allSite(MethodHandles.collectArguments(printArgs, type));
}
</pre></blockquote>
* @author John Rose, JSR 292 EG
*/
public
class
CallSite
implements
MethodHandleProvider
{
public
class
CallSite
{
private
static
final
Access
IMPL_TOKEN
=
Access
.
getToken
();
// Fields used only by the JVM. Do not use or change.
...
...
@@ -88,61 +80,44 @@ public class CallSite
private
int
vmindex
;
// supplied by the JVM (BCI within calling method)
// The actual payload of this call site:
private
MethodHandle
target
;
/*package-private*/
MethodHandle
target
;
// Remove this field for PFD and delete deprecated methods:
private
MemberName
calleeNameRemoveForPFD
;
/**
* Make a blank call site object.
* Before it is returned from a bootstrap method, this {@code CallSite} object
* must be provided with
* a target method via a call to {@link CallSite#setTarget(MethodHandle) setTarget},
* or by a subclass override of {@link CallSite#initialTarget(Class,String,MethodType) initialTarget}.
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Make a blank call site object with the given method type.
* An initial target method is supplied which will throw
* an {@link IllegalStateException} if called.
* <p>
* Before this {@code CallSite} object is returned from a bootstrap method,
* it is usually provided with a more useful target method,
* via a call to {@link CallSite#setTarget(MethodHandle) setTarget}.
*/
public
CallSite
()
{
public
CallSite
(
MethodType
type
)
{
target
=
MethodHandles
.
invokers
(
type
).
uninitializedCallSite
();
}
/**
* Make a blank call site object, possibly equipped with an initial target method handle.
* The initial target reference may be null, in which case the {@code CallSite} object
* must be provided with a target method via a call to {@link CallSite#setTarget},
* or by a subclass override of {@link CallSite#initialTarget}.
* @param target the method handle which will be the initial target of the call site, or null if there is none yet
* @param target the method handle which will be the initial target of the call site
*/
public
CallSite
(
MethodHandle
target
)
{
target
.
type
();
// null check
this
.
target
=
target
;
}
/** @deprecated transitional form defined in EDR but removed in PFD */
public
CallSite
(
Class
<?>
caller
,
String
name
,
MethodType
type
)
{
this
.
calleeNameRemoveForPFD
=
new
MemberName
(
caller
,
name
,
type
);
}
/** @deprecated transitional form defined in EDR but removed in PFD */
public
Class
<?>
callerClass
()
{
MemberName
callee
=
this
.
calleeNameRemoveForPFD
;
return
callee
==
null
?
null
:
callee
.
getDeclaringClass
();
}
/** @deprecated transitional form defined in EDR but removed in PFD */
public
String
name
()
{
MemberName
callee
=
this
.
calleeNameRemoveForPFD
;
return
callee
==
null
?
null
:
callee
.
getName
();
}
/** @deprecated transitional form defined in EDR but removed in PFD */
public
MethodType
type
()
{
MemberName
callee
=
this
.
calleeNameRemoveForPFD
;
return
callee
==
null
?
(
target
==
null
?
null
:
target
.
type
())
:
callee
.
getMethodType
();
}
/** @deprecated transitional form defined in EDR but removed in PFD */
protected
MethodHandle
initialTarget
()
{
return
initialTarget
(
callerClass
(),
name
(),
type
());
}
/** Report if the JVM has linked this {@code CallSite} object to a dynamic call site instruction.
* Once it is linked, it is never unlinked.
/**
* Report the type of this call site's target.
* Although targets may change, the call site's type can never change.
* The {@code setTarget} method enforces this invariant by refusing any new target that does
* not have the previous target's type.
* @return the type of the current target, which is also the type of any future target
*/
p
rivate
boolean
isLinked
()
{
return
vmmethod
!=
null
;
p
ublic
MethodType
type
()
{
return
target
.
type
()
;
}
/** Called from JVM (or low-level Java code) after the BSM returns the newly created CallSite.
...
...
@@ -152,68 +127,66 @@ public class CallSite
MethodType
type
,
MemberName
callerMethod
,
int
callerBCI
)
{
if
(
this
.
isLinked
())
{
if
(
this
.
vmmethod
!=
null
)
{
// FIXME
throw
new
InvokeDynamicBootstrapError
(
"call site has already been linked to an invokedynamic instruction"
);
}
MethodHandle
target
=
this
.
target
;
if
(
target
==
null
)
{
this
.
target
=
target
=
this
.
initialTarget
(
callerMethod
.
getDeclaringClass
(),
name
,
type
);
}
if
(!
target
.
type
().
equals
(
type
))
{
if
(!
this
.
type
().
equals
(
type
))
{
throw
wrongTargetType
(
target
,
type
);
}
this
.
vmindex
=
callerBCI
;
this
.
vmmethod
=
callerMethod
;
assert
(
this
.
isLinked
());
}
/**
* Just after a call site is created by a bootstrap method handle,
* if the target has not been initialized by the factory method itself,
* the method {@code initialTarget} is called to produce an initial
* non-null target. (Live call sites must never have null targets.)
* <p>
* The arguments are the same as those passed to the bootstrap method.
* Thus, a bootstrap method is free to ignore the arguments and simply
* create a "blank" {@code CallSite} object of an appropriate subclass.
* Report the current linkage state of the call site, a value which may change over time.
* <p>
* If the bootstrap method itself does not initialize the call site,
* this method must be overridden, because it just raises an
* {@code InvokeDynamicBootstrapError}, which in turn causes the
* linkage of the {@code invokedynamic} instruction to terminate
* abnormally.
* @deprecated transitional form defined in EDR but removed in PFD
*/
protected
MethodHandle
initialTarget
(
Class
<?>
callerClass
,
String
name
,
MethodType
type
)
{
throw
new
InvokeDynamicBootstrapError
(
"target must be initialized before call site is linked: "
+
name
+
type
);
}
/**
* Report the current linkage state of the call site. (This is mutable.)
* The value may not be null after the {@code CallSite} object is returned
* from the bootstrap method of the {@code invokedynamic} instruction.
* When an {@code invokedynamic} instruction is executed, the target method
* of its associated {@code call site} object is invoked directly,
* as if via {@link MethodHandle}{@code .invoke}.
* If a {@code CallSite} object is returned
* from the bootstrap method of the {@code invokedynamic} instruction,
* the {@code CallSite} is permanently bound to that instruction.
* When the {@code invokedynamic} instruction is executed, the target method
* of its associated call site object is invoked directly.
* It is as if the instruction calls {@code getTarget} and then
* calls {@link MethodHandle#invokeExact invokeExact} on the result.
* <p>
* The interactions of {@code getTarget} with memory are the same
* Unless specified differently by a subclass,
* the interactions of {@code getTarget} with memory are the same
* as of a read from an ordinary variable, such as an array element or a
* non-volatile, non-final field.
* <p>
* In particular, the current thread may choose to reuse the result
* of a previous read of the target from memory, and may fail to see
* a recent update to the target by another thread.
* @return the current linkage state of the call site
* <p>
* In a {@linkplain ConstantCallSite constant call site}, the {@code getTarget} method behaves
* like a read from a {@code final} field of the {@code CallSite}.
* <p>
* In a {@linkplain VolatileCallSite volatile call site}, the {@code getTarget} method behaves
* like a read from a {@code volatile} field of the {@code CallSite}.
* <p>
* This method may not be overridden by application code.
* @return the current linkage state of the call site, its target method handle
* @see ConstantCallSite
* @see VolatileCallSite
* @see #setTarget
*/
public
MethodHandle
getTarget
()
{
public
final
MethodHandle
getTarget
()
{
return
getTarget0
();
}
/**
* Privileged implementations can override this to force final or volatile semantics on getTarget.
*/
/*package-private*/
MethodHandle
getTarget0
()
{
return
target
;
}
/**
* Set the target method of this call site.
* <p>
* The interactions of {@code setTarget} with memory are the same
* Unless a subclass of CallSite documents otherwise,
* the interactions of {@code setTarget} with memory are the same
* as of a write to an ordinary variable, such as an array element or a
* non-volatile, non-final field.
* <p>
...
...
@@ -224,27 +197,23 @@ public class CallSite
* at any given call site.
* @param newTarget the new target
* @throws NullPointerException if the proposed new target is null
* @throws WrongMethodTypeException if the
call site is linked and the
proposed new target
* @throws WrongMethodTypeException if the proposed new target
* has a method type that differs from the previous target
*/
public
void
setTarget
(
MethodHandle
newTarget
)
{
MethodType
newType
=
newTarget
.
type
();
// null check!
MethodHandle
oldTarget
=
this
.
target
;
if
(
oldTarget
==
null
)
{
// CallSite is not yet linked.
assert
(!
isLinked
());
this
.
target
=
newTarget
;
// might be null!
return
;
}
checkTargetChange
(
this
.
target
,
newTarget
);
setTargetNormal
(
newTarget
);
}
void
checkTargetChange
(
MethodHandle
oldTarget
,
MethodHandle
newTarget
)
{
MethodType
oldType
=
oldTarget
.
type
();
if
(!
newTarget
.
type
().
equals
(
oldType
))
MethodType
newType
=
newTarget
.
type
();
// null check!
if
(!
newType
.
equals
(
oldType
))
throw
wrongTargetType
(
newTarget
,
oldType
);
if
(
oldTarget
!=
newTarget
)
CallSiteImpl
.
setCallSiteTarget
(
IMPL_TOKEN
,
this
,
newTarget
);
}
private
static
WrongMethodTypeException
wrongTargetType
(
MethodHandle
target
,
MethodType
type
)
{
return
new
WrongMethodTypeException
(
String
.
valueOf
(
target
)+
target
.
type
()+
" should be of type "
+
type
);
return
new
WrongMethodTypeException
(
String
.
valueOf
(
target
)+
" should be of type "
+
type
);
}
/** Produce a printed representation that displays information about this call site
...
...
@@ -252,15 +221,14 @@ public class CallSite
*/
@Override
public
String
toString
()
{
return
"CallSite"
+(
target
==
null
?
""
:
target
.
type
()
);
return
super
.
toString
()
+
type
(
);
}
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Produce a method handle equivalent to an invokedynamic instruction
* which has been linked to this call site.
* <p>If this call site is a {@link
ConstantCallSite}, this method
*
simply returns the call site's target, since that will not
change.
* <p>If this call site is a {@link
plain ConstantCallSite constant call site},
*
this method simply returns the call site's target, since that will never
change.
* <p>Otherwise, this method is equivalent to the following code:
* <p><blockquote><pre>
* MethodHandle getTarget, invoker, result;
...
...
@@ -271,8 +239,9 @@ public class CallSite
* @return a method handle which always invokes this call site's current target
*/
public
final
MethodHandle
dynamicInvoker
()
{
if
(
this
instanceof
ConstantCallSite
)
return
getTarget
();
// will not change dynamically
if
(
this
instanceof
ConstantCallSite
)
{
return
target
;
// will not change dynamically
}
MethodHandle
getTarget
=
MethodHandleImpl
.
bindReceiver
(
IMPL_TOKEN
,
GET_TARGET
,
this
);
MethodHandle
invoker
=
MethodHandles
.
exactInvoker
(
this
.
type
());
return
MethodHandles
.
foldArguments
(
invoker
,
getTarget
);
...
...
@@ -287,9 +256,34 @@ public class CallSite
}
}
/** Implementation of {@link MethodHandleProvider} which returns {@code this.dynamicInvoker()}. */
public
final
MethodHandle
asMethodHandle
()
{
return
dynamicInvoker
();
}
/** This guy is rolled into the default target if a MethodType is supplied to the constructor. */
/*package-private*/
static
Empty
uninitializedCallSite
()
{
throw
new
IllegalStateException
(
"uninitialized call site"
);
}
// unsafe stuff:
private
static
final
Unsafe
unsafe
=
Unsafe
.
getUnsafe
();
private
static
final
long
TARGET_OFFSET
;
static
{
try
{
TARGET_OFFSET
=
unsafe
.
objectFieldOffset
(
CallSite
.
class
.
getDeclaredField
(
"target"
));
}
catch
(
Exception
ex
)
{
throw
new
Error
(
ex
);
}
}
/** Implementation of {@link MethodHandleProvider}, which returns {@code this.dynamicInvoker().asType(type)}. */
public
final
MethodHandle
asMethodHandle
(
MethodType
type
)
{
return
dynamicInvoker
().
asType
(
type
);
}
/*package-private*/
void
setTargetNormal
(
MethodHandle
newTarget
)
{
target
=
newTarget
;
//CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
}
/*package-private*/
MethodHandle
getTargetVolatile
()
{
return
(
MethodHandle
)
unsafe
.
getObjectVolatile
(
this
,
TARGET_OFFSET
);
}
/*package-private*/
void
setTargetVolatile
(
MethodHandle
newTarget
)
{
unsafe
.
putObjectVolatile
(
this
,
TARGET_OFFSET
,
newTarget
);
//CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
}
}
src/share/classes/java/dyn/ConstantCallSite.java
浏览文件 @
5150d263
...
...
@@ -27,8 +27,8 @@ package java.dyn;
/**
* A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
*
The only way to relink an {@code invokedynamic} instruction bound to a {@code ConstantCallSite} is
*
to invalidate the instruction as a whole
.
*
An {@code invokedynamic} instruction linked to a {@code ConstantCallSite} is permanently
*
bound to the call site's target
.
* @author John Rose, JSR 292 EG
*/
public
class
ConstantCallSite
extends
CallSite
{
...
...
@@ -36,7 +36,9 @@ public class ConstantCallSite extends CallSite {
public
ConstantCallSite
(
MethodHandle
target
)
{
super
(
target
);
}
/** Throw an {@link IllegalArgumentException}, because this kind of call site cannot change its target. */
/**
* Throw an {@link IllegalArgumentException}, because this kind of call site cannot change its target.
*/
@Override
public
final
void
setTarget
(
MethodHandle
ignore
)
{
throw
new
IllegalArgumentException
(
"ConstantCallSite"
);
}
...
...
src/share/classes/java/dyn/InvokeDynamic.java
已删除
100644 → 0
浏览文件 @
70e0218c
/*
* Copyright (c) 2008, 2009, 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.
*/
package
java.dyn
;
/**
* {@code InvokeDynamic} is a class with neither methods nor instances,
* which serves only as a syntactic marker in Java source code for
* an {@code invokedynamic} instruction.
* (See <a href="package-summary.html#jvm_mods">the package information</a> for specifics on this instruction.)
* <p>
* The {@code invokedynamic} instruction is incomplete without a target method.
* The target method is a property of the reified {@linkplain CallSite call site object}
* which is linked to each active {@code invokedynamic} instruction.
* The call site object is initially produced by a
* {@linkplain BootstrapMethod bootstrap method}
* associated with the class whose bytecodes include the dynamic call site.
* <p>
* The type {@code InvokeDynamic} has no particular meaning as a
* class or interface supertype, or an object type; it can never be instantiated.
* Logically, it denotes a source of all dynamically typed methods.
* It may be viewed as a pure syntactic marker of static calls.
* It may be imported for ease of use.
* <p>
* Here are some examples:
<blockquote><pre><!-- see indy-demo/src/JavaDocExamples.java -->
@BootstrapMethod(value=Here.class, name="bootstrapDynamic")
static void example() throws Throwable {
Object x; String s; int i;
x = InvokeDynamic.greet("world"); // greet(Ljava/lang/String;)Ljava/lang/Object;
s = (String) InvokeDynamic.hail(x); // hail(Ljava/lang/Object;)Ljava/lang/String;
InvokeDynamic.cogito(); // cogito()V
i = (int) InvokeDynamic.#"op:+"(2, 3); // "op:+"(II)I
}
static MethodHandle bootstrapDynamic(Class caller, String name, MethodType type) { ... }
</pre></blockquote>
* Each of the above calls generates a single invokedynamic instruction
* with the name-and-type descriptors indicated in the comments.
* <p>
* The argument types are taken directly from the actual arguments,
* while the return type corresponds to the target of the assignment.
* (Currently, the return type must be given as a false type parameter.
* This type parameter is an irregular use of the generic type syntax,
* and is likely to change in favor of a convention based on target typing.)
* <p>
* The final example uses a special syntax for uttering non-Java names.
* Any name legal to the JVM may be given between the double quotes.
* <p>
* None of these calls is complete without a bootstrap method,
* which must be declared for the enclosing class or method.
* @author John Rose, JSR 292 EG
*/
@MethodHandle
.
PolymorphicSignature
public
final
class
InvokeDynamic
{
private
InvokeDynamic
()
{
throw
new
InternalError
();
}
// do not instantiate
// no statically defined static methods
}
src/share/classes/java/dyn/Linkage.java
浏览文件 @
5150d263
...
...
@@ -29,15 +29,16 @@ import java.dyn.MethodHandles.Lookup;
import
java.util.WeakHashMap
;
import
sun.dyn.Access
;
import
sun.dyn.MethodHandleImpl
;
import
sun.dyn.util.VerifyAccess
;
import
sun.reflect.Reflection
;
import
static
sun
.
dyn
.
util
.
VerifyAccess
.
checkBootstrapPrivilege
;
import
static
sun
.
dyn
.
MemberName
.
newIllegalArgumentException
;
/**
*
This class consists exclusively of static methods that control
*
the linkage of {@code invokedynamic} instructions, and specifically
*
their reification as {@link CallSite} object
s.
*
<em>CLASS WILL BE REMOVED FOR PFD:</em>
*
Static routines for controlling invokedynamic behavior.
*
Replaced by non-static API
s.
* @author John Rose, JSR 292 EG
* @deprecated This class will be removed in the Public Final Draft.
*/
public
class
Linkage
{
private
static
final
Access
IMPL_TOKEN
=
Access
.
getToken
();
...
...
@@ -45,68 +46,24 @@ public class Linkage {
private
Linkage
()
{}
// do not instantiate
/**
* <em>
PROVISIONAL API, WORK IN PROGRESS
:</em>
* <em>
METHOD WILL BE REMOVED FOR PFD
:</em>
* Register a <em>bootstrap method</em> to use when linking dynamic call sites within
* a given caller class.
* <p>
* A bootstrap method must be a method handle with a return type of {@link CallSite}
* and the following arguments:
* <ul>
* <li>the class containing the {@code invokedynamic} instruction, for which the bootstrap method was registered
* <li>the name of the method being invoked (a {@link String})
* <li>the type of the method being invoked (a {@link MethodType})
* </ul>
* The bootstrap method acts as a factory method which accepts the given arguments
* and returns a {@code CallSite} object (possibly of a subclass of {@code CallSite}).
* <p>
* The registration must take place exactly once, either before the class has begun
* being initialized, or from within the class's static initializer.
* Registration will fail with an exception if any of the following conditions hold:
* <ul>
* <li>The immediate caller of this method is in a different package than the given caller class,
* and there is a security manager, and its {@code checkPermission} call throws
* when passed {@link LinkagePermission}("registerBootstrapMethod",callerClass).
* <li>The given caller class already has a bootstrap method registered.
* <li>The given caller class is already fully initialized.
* <li>The given caller class is in the process of initialization, in another thread.
* </ul>
* Because of these rules, a class may install its own bootstrap method in
* a static initializer.
* @param callerClass a class that may have {@code invokedynamic} sites
* @param bootstrapMethod the method to use to bootstrap all such sites
* @exception IllegalArgumentException if the class argument is null or
* a primitive class, or if the bootstrap method is the wrong type
* @exception IllegalStateException if the class already has a bootstrap
* method, or if the its static initializer has already run
* or is already running in another thread
* @exception SecurityException if there is a security manager installed,
* and a {@link LinkagePermission} check fails for "registerBootstrapMethod"
* @deprecated Use @{@link BootstrapMethod} annotations instead
* @deprecated Use @{@link BootstrapMethod} annotations instead.
*/
public
static
void
registerBootstrapMethod
(
Class
callerClass
,
MethodHandle
bootstrapMethod
)
{
Class
callc
=
Reflection
.
getCallerClass
(
2
);
checkBootstrapPrivilege
(
callc
,
callerClass
,
"registerBootstrapMethod"
);
checkBSM
(
bootstrapMethod
);
if
(
callc
!=
null
&&
!
VerifyAccess
.
isSamePackage
(
callerClass
,
callc
))
throw
new
IllegalArgumentException
(
"cannot set bootstrap method on "
+
callerClass
);
MethodHandleImpl
.
registerBootstrap
(
IMPL_TOKEN
,
callerClass
,
bootstrapMethod
);
}
static
private
void
checkBSM
(
MethodHandle
mh
)
{
if
(
mh
==
null
)
throw
newIllegalArgumentException
(
"null bootstrap method"
);
if
(
mh
.
type
()
==
BOOTSTRAP_METHOD_TYPE
)
return
;
throw
new
WrongMethodTypeException
(
mh
.
toString
());
}
/**
* <em>
PROVISIONAL API, WORK IN PROGRESS
:</em>
* <em>
METHOD WILL BE REMOVED FOR PFD
:</em>
* Simplified version of {@code registerBootstrapMethod} for self-registration,
* to be called from a static initializer.
* Finds a static method of the required type in the
* given runtime class, and installs it on the caller class.
* @throws NoSuchMethodException if there is no such method
* @throws IllegalStateException if the caller class's static initializer
* has already run, or is already running in another thread
* @deprecated Use @{@link BootstrapMethod} annotations instead
* @deprecated Use @{@link BootstrapMethod} annotations instead.
*/
public
static
void
registerBootstrapMethod
(
Class
<?>
runtime
,
String
name
)
{
...
...
@@ -115,15 +72,9 @@ public class Linkage {
}
/**
* <em>
PROVISIONAL API, WORK IN PROGRESS
:</em>
* <em>
METHOD WILL BE REMOVED FOR PFD
:</em>
* Simplified version of {@code registerBootstrapMethod} for self-registration,
* to be called from a static initializer.
* Finds a static method of the required type in the
* caller class itself, and installs it on the caller class.
* @throws IllegalArgumentException if there is no such method
* @throws IllegalStateException if the caller class's static initializer
* has already run, or is already running in another thread
* @deprecated Use @{@link BootstrapMethod} annotations instead
* @deprecated Use @{@link BootstrapMethod} annotations instead.
*/
public
static
void
registerBootstrapMethod
(
String
name
)
{
...
...
@@ -140,82 +91,33 @@ public class Linkage {
}
catch
(
NoAccessException
ex
)
{
throw
new
IllegalArgumentException
(
"no such bootstrap method in "
+
runtime
+
": "
+
name
,
ex
);
}
checkBSM
(
bootstrapMethod
);
MethodHandleImpl
.
registerBootstrap
(
IMPL_TOKEN
,
callerClass
,
bootstrapMethod
);
}
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* Report the bootstrap method registered for a given caller class.
* Returns null if the class has never yet registered a bootstrap method.
* Only callers privileged to set the bootstrap method may inquire
* about it, because a bootstrap method is potentially a back-door entry
* point into its class.
* @exception IllegalArgumentException if the argument is null or
* a primitive class
* @exception SecurityException if there is a security manager installed,
* and the immediate caller of this method is not in the same
* package as the caller class
* and a {@link LinkagePermission} check fails for "getBootstrapMethod"
* @deprecated
*/
public
static
MethodHandle
getBootstrapMethod
(
Class
callerClass
)
{
Class
callc
=
Reflection
.
getCallerClass
(
2
);
checkBootstrapPrivilege
(
callc
,
callerClass
,
"getBootstrapMethod"
);
return
MethodHandleImpl
.
getBootstrap
(
IMPL_TOKEN
,
callerClass
);
}
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* The type of any bootstrap method is a three-argument method
* {@code (Class, String, MethodType)} returning a {@code CallSite}.
*/
public
static
final
MethodType
BOOTSTRAP_METHOD_TYPE
private
static
final
MethodType
BOOTSTRAP_METHOD_TYPE
=
MethodType
.
methodType
(
CallSite
.
class
,
Class
.
class
,
String
.
class
,
MethodType
.
class
);
/**
* <em>
PROVISIONAL API, WORK IN PROGRESS
:</em>
* <em>
METHOD WILL BE REMOVED FOR PFD
:</em>
* Invalidate all <code>invokedynamic</code> call sites everywhere.
* <p>
* When this method returns, every <code>invokedynamic</code> instruction
* will invoke its bootstrap method on next call.
* <p>
* It is unspecified whether call sites already known to the Java
* code will continue to be associated with <code>invokedynamic</code>
* instructions. If any call site is still so associated, its
* {@link CallSite#getTarget()} method is guaranteed to return null
* the invalidation operation completes.
* <p>
* Invalidation operations are likely to be slow. Use them sparingly.
* @deprecated Use {@linkplain CallSite#setTarget call site target setting}
* and {@link VolatileCallSite#invalidateAll call site invalidation} instead.
*/
public
static
Object
invalidateAll
()
{
SecurityManager
security
=
System
.
getSecurityManager
();
if
(
security
!=
null
)
{
security
.
checkPermission
(
new
LinkagePermission
(
"invalidateAll"
));
}
throw
new
UnsupportedOperationException
(
"NYI"
);
throw
new
UnsupportedOperationException
();
}
/**
* <em>
PROVISIONAL API, WORK IN PROGRESS
:</em>
* <em>
METHOD WILL BE REMOVED FOR PFD
:</em>
* Invalidate all {@code invokedynamic} call sites in the bytecodes
* of any methods of the given class.
* <p>
* When this method returns, every matching <code>invokedynamic</code>
* instruction will invoke its bootstrap method on next call.
* <p>
* For additional semantics of call site invalidation,
* see {@link #invalidateAll()}.
* @deprecated Use {@linkplain CallSite#setTarget call site target setting}
* and {@link VolatileCallSite#invalidateAll call site invalidation} instead.
*/
public
static
Object
invalidateCallerClass
(
Class
<?>
callerClass
)
{
SecurityManager
security
=
System
.
getSecurityManager
();
if
(
security
!=
null
)
{
security
.
checkPermission
(
new
LinkagePermission
(
"invalidateAll"
,
callerClass
));
}
throw
new
UnsupportedOperationException
(
"NYI"
);
throw
new
UnsupportedOperationException
();
}
}
src/share/classes/java/dyn/LinkagePermission.java
已删除
100644 → 0
浏览文件 @
70e0218c
/*
* Copyright (c) 2008, 2010, 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.
*/
package
java.dyn
;
import
java.security.*
;
import
java.util.Enumeration
;
import
java.util.Hashtable
;
import
java.util.StringTokenizer
;
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* This class is for managing runtime permission checking for
* operations performed by methods in the {@link Linkage} class.
* Like a {@link RuntimePermission}, on which it is modeled,
* a {@code LinkagePermission} contains a target name but
* no actions list; you either have the named permission
* or you don't.
* <p>
* The following table lists all the possible {@code LinkagePermission} target names,
* and for each provides a description of what the permission allows
* and a discussion of the risks of granting code the permission.
* <p>
*
* <table border=1 cellpadding=5 summary="permission target name,
* what the target allows,and associated risks">
* <tr>
* <th>Permission Target Name</th>
* <th>What the Permission Allows</th>
* <th>Risks of Allowing this Permission</th>
* </tr>
*
* <tr>
* <td>invalidateAll</td>
* <td>Force the relinking of invokedynamic call sites everywhere.</td>
* <td>This could allow an attacker to slow down the system,
* or perhaps expose timing bugs in a dynamic language implementations,
* by forcing redundant relinking operations.</td>
* </tr>
*
*
* <tr>
* <td>invalidateCallerClass.{class name}</td>
* <td>Force the relinking of invokedynamic call sites in the given class.</td>
* <td>See {@code invalidateAll}.</td>
* </tr>
* </table>
* <p>ISSUE: Is this still needed?
*
* @see java.lang.RuntimePermission
* @see java.lang.SecurityManager
*
* @author John Rose, JSR 292 EG
*/
public
final
class
LinkagePermission
extends
BasicPermission
{
/**
* Create a new LinkagePermission with the given name.
* The name is the symbolic name of the LinkagePermission, such as
* "invalidateCallerClass.*", etc. An asterisk
* may appear at the end of the name, following a ".", or by itself, to
* signify a wildcard match.
*
* @param name the name of the LinkagePermission
*/
public
LinkagePermission
(
String
name
)
{
super
(
name
);
}
/**
* Create a new LinkagePermission with the given name on the given class.
* Equivalent to {@code LinkagePermission(name+"."+clazz.getName())}.
*
* @param name the name of the LinkagePermission
* @param clazz the class affected by the permission
*/
public
LinkagePermission
(
String
name
,
Class
<?>
clazz
)
{
super
(
name
+
"."
+
clazz
.
getName
());
}
}
src/share/classes/java/dyn/MethodHandle.java
浏览文件 @
5150d263
此差异已折叠。
点击以展开。
src/share/classes/java/dyn/MethodHandleProvider.java
已删除
100644 → 0
浏览文件 @
70e0218c
/*
* Copyright (c) 2009, 2010, 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.
*/
package
java.dyn
;
/**
* An interface for an object to provide a target {@linkplain MethodHandle method handle} to a {@code invokedynamic} instruction.
* There are many function-like objects in various Java APIs.
* This interface provides a standard way for such function-like objects to be bound
* to a dynamic call site, by providing a view of their behavior in the form of a low-level method handle.
* <p>
* The type {@link MethodHandle} is a concrete class whose implementation
* hierarchy (if any) may be tightly coupled to the underlying JVM implementation.
* It cannot also serve as a base type for user-defined functional APIs.
* For this reason, {@code MethodHandle} cannot be subclassed to add new
* behavior to method handles. But this interface can be used to provide
* a link between a user-defined function and the {@code invokedynamic}
* instruction and the method handle API.
*/
public
interface
MethodHandleProvider
{
/** Produce a method handle which will serve as a behavioral proxy for the current object.
* The type and invocation behavior of the proxy method handle are user-defined,
* and should have some relation to the intended meaning of the original object itself.
* <p>
* The current object may have a changeable behavior.
* For example, {@link CallSite} has a {@code setTarget} method which changes its invocation.
* In such a case, it is <em>incorrect</em> for {@code asMethodHandle} to return
* a method handle whose behavior may diverge from that of the current object.
* Rather, the returned method handle must stably and permanently access
* the behavior of the current object, even if that behavior is changeable.
* <p>
* The reference identity of the proxy method handle is not guaranteed to
* have any particular relation to the reference identity of the object.
* In particular, several objects with the same intended meaning could
* share a common method handle, or the same object could return different
* method handles at different times. In the latter case, the different
* method handles should have the same type and invocation behavior,
* and be usable from any thread at any time.
* In particular, if a MethodHandleProvider is bound to an <code>invokedynamic</code>
* call site, the proxy method handle extracted at the time of binding
* will be used for an unlimited time, until the call site is rebound.
* <p>
* The type {@link MethodHandle} itself implements {@code MethodHandleProvider}, and
* for this method simply returns {@code this}.
*/
public
MethodHandle
asMethodHandle
();
/** Produce a method handle of a given type which will serve as a behavioral proxy for the current object.
* As for the no-argument version {@link #asMethodHandle()}, the invocation behavior of the
* proxy method handle is user-defined. But the type must be the given type,
* or else a {@link WrongMethodTypeException} must be thrown.
* <p>
* If the current object somehow represents a variadic or overloaded behavior,
* the method handle returned for a given type might represent only a subset of
* the current object's repertoire of behaviors, which correspond to that type.
*/
public
MethodHandle
asMethodHandle
(
MethodType
type
)
throws
WrongMethodTypeException
;
}
src/share/classes/java/dyn/MethodHandles.java
浏览文件 @
5150d263
此差异已折叠。
点击以展开。
src/share/classes/java/dyn/MethodType.java
浏览文件 @
5150d263
...
...
@@ -119,7 +119,7 @@ class MethodType implements java.lang.reflect.Type {
for
(
Class
<?>
ptype
:
ptypes
)
{
ptype
.
equals
(
ptype
);
// null check
if
(
ptype
==
void
.
class
)
throw
newIllegalArgumentException
(
"
void parameter: "
+
this
);
throw
newIllegalArgumentException
(
"
parameter type cannot be void"
);
}
}
...
...
@@ -139,10 +139,6 @@ class MethodType implements java.lang.reflect.Type {
MethodType
methodType
(
Class
<?>
rtype
,
Class
<?>[]
ptypes
)
{
return
makeImpl
(
rtype
,
ptypes
,
false
);
}
@Deprecated
public
static
MethodType
make
(
Class
<?>
rtype
,
Class
<?>[]
ptypes
)
{
return
methodType
(
rtype
,
ptypes
);
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}. */
public
static
...
...
@@ -150,10 +146,6 @@ class MethodType implements java.lang.reflect.Type {
boolean
notrust
=
false
;
// random List impl. could return evil ptypes array
return
makeImpl
(
rtype
,
ptypes
.
toArray
(
NO_PTYPES
),
notrust
);
}
@Deprecated
public
static
MethodType
make
(
Class
<?>
rtype
,
List
<?
extends
Class
<?>>
ptypes
)
{
return
methodType
(
rtype
,
ptypes
);
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* The leading parameter type is prepended to the remaining array.
...
...
@@ -165,10 +157,6 @@ class MethodType implements java.lang.reflect.Type {
System
.
arraycopy
(
ptypes
,
0
,
ptypes1
,
1
,
ptypes
.
length
);
return
makeImpl
(
rtype
,
ptypes1
,
true
);
}
@Deprecated
public
static
MethodType
make
(
Class
<?>
rtype
,
Class
<?>
ptype0
,
Class
<?>...
ptypes
)
{
return
methodType
(
rtype
,
ptype0
,
ptypes
);
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* The resulting method has no parameter types.
...
...
@@ -177,10 +165,6 @@ class MethodType implements java.lang.reflect.Type {
MethodType
methodType
(
Class
<?>
rtype
)
{
return
makeImpl
(
rtype
,
NO_PTYPES
,
true
);
}
@Deprecated
public
static
MethodType
make
(
Class
<?>
rtype
)
{
return
methodType
(
rtype
);
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* The resulting method has the single given parameter type.
...
...
@@ -189,10 +173,6 @@ class MethodType implements java.lang.reflect.Type {
MethodType
methodType
(
Class
<?>
rtype
,
Class
<?>
ptype0
)
{
return
makeImpl
(
rtype
,
new
Class
<?>[]{
ptype0
},
true
);
}
@Deprecated
public
static
MethodType
make
(
Class
<?>
rtype
,
Class
<?>
ptype0
)
{
return
methodType
(
rtype
,
ptype0
);
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* The resulting method has the same parameter types as {@code ptypes},
...
...
@@ -202,10 +182,6 @@ class MethodType implements java.lang.reflect.Type {
MethodType
methodType
(
Class
<?>
rtype
,
MethodType
ptypes
)
{
return
makeImpl
(
rtype
,
ptypes
.
ptypes
,
true
);
}
@Deprecated
public
static
MethodType
make
(
Class
<?>
rtype
,
MethodType
ptypes
)
{
return
methodType
(
rtype
,
ptypes
);
}
/**
* Sole factory method to find or create an interned method type.
...
...
@@ -275,10 +251,6 @@ class MethodType implements java.lang.reflect.Type {
}
return
mt
;
}
@Deprecated
public
static
MethodType
makeGeneric
(
int
objectArgCount
,
boolean
varargs
)
{
return
genericMethodType
(
objectArgCount
,
varargs
);
}
/**
* All parameters and the return type will be Object.
...
...
@@ -290,10 +262,6 @@ class MethodType implements java.lang.reflect.Type {
MethodType
genericMethodType
(
int
objectArgCount
)
{
return
genericMethodType
(
objectArgCount
,
false
);
}
@Deprecated
public
static
MethodType
makeGeneric
(
int
objectArgCount
)
{
return
genericMethodType
(
objectArgCount
);
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param num the index (zero-based) of the parameter type to change
...
...
@@ -307,18 +275,6 @@ class MethodType implements java.lang.reflect.Type {
return
makeImpl
(
rtype
,
nptypes
,
true
);
}
/** Convenience method for {@link #insertParameterTypes}.
* @deprecated Use {@link #insertParameterTypes} instead.
*/
@Deprecated
public
MethodType
insertParameterType
(
int
num
,
Class
<?>
nptype
)
{
int
len
=
ptypes
.
length
;
Class
<?>[]
nptypes
=
Arrays
.
copyOfRange
(
ptypes
,
0
,
len
+
1
);
System
.
arraycopy
(
nptypes
,
num
,
nptypes
,
num
+
1
,
len
-
num
);
nptypes
[
num
]
=
nptype
;
return
makeImpl
(
rtype
,
nptypes
,
true
);
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param num the position (zero-based) of the inserted parameter type(s)
* @param ptypesToInsert zero or more a new parameter types to insert into the parameter list
...
...
@@ -336,6 +292,14 @@ class MethodType implements java.lang.reflect.Type {
return
makeImpl
(
rtype
,
nptypes
,
true
);
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param ptypesToInsert zero or more a new parameter types to insert after the end of the parameter list
* @return the same type, except with the selected parameter(s) appended
*/
public
MethodType
appendParameterTypes
(
Class
<?>...
ptypesToInsert
)
{
return
insertParameterTypes
(
parameterCount
(),
ptypesToInsert
);
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param num the position (zero-based) of the inserted parameter type(s)
* @param ptypesToInsert zero or more a new parameter types to insert into the parameter list
...
...
@@ -377,14 +341,6 @@ class MethodType implements java.lang.reflect.Type {
return
makeImpl
(
rtype
,
nptypes
,
true
);
}
/** Convenience method for {@link #dropParameterTypes}.
* @deprecated Use {@link #dropParameterTypes} instead.
*/
@Deprecated
public
MethodType
dropParameterType
(
int
num
)
{
return
dropParameterTypes
(
num
,
num
+
1
);
}
/** Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[])}.
* @param nrtype a return parameter type to replace the old one with
* @return the same type, except with the return type change
...
...
@@ -690,14 +646,4 @@ class MethodType implements java.lang.reflect.Type {
public
String
toMethodDescriptorString
()
{
return
BytecodeDescriptor
.
unparse
(
this
);
}
/** Temporary alias for toMethodDescriptorString; delete after M3. */
public
String
toBytecodeString
()
{
return
toMethodDescriptorString
();
}
/** Temporary alias for fromMethodDescriptorString; delete after M3. */
public
static
MethodType
fromBytecodeString
(
String
descriptor
,
ClassLoader
loader
)
throws
IllegalArgumentException
,
TypeNotPresentException
{
return
fromMethodDescriptorString
(
descriptor
,
loader
);
}
}
src/share/classes/java/dyn/VolatileCallSite.java
0 → 100644
浏览文件 @
5150d263
/*
* Copyright (c) 2010, 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.
*/
package
java.dyn
;
import
java.util.List
;
/**
* <em>PROVISIONAL API, WORK IN PROGRESS:</em>
* A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable.
* An {@code invokedynamic} instruction linked to a {@code VolatileCallSite} sees updates
* to its call site target immediately, even if the update occurs in another thread.
* <p>
* Also, a volatile call site has the ability to be <em>invalidated</em>,
* or reset to a well-defined fallback state.
* <p>
* A volatile call site can be used as a switch to control the behavior
* of another method handle. For example:
* <blockquote><pre>
MethodHandle strcat = MethodHandles.lookup()
.findVirtual(String.class, "concat", MethodType.methodType(String.class, String.class));
MethodHandle trueCon = MethodHandles.constant(boolean.class, true);
MethodHandle falseCon = MethodHandles.constant(boolean.class, false);
VolatileCallSite switcher = new VolatileCallSite(trueCon, falseCon);
// following steps may be repeated to re-use the same switcher:
MethodHandle worker1 = strcat;
MethodHandle worker2 = MethodHandles.permuteArguments(strcat, strcat.type(), 1, 0);
MethodHandle worker = MethodHandles.guardWithTest(switcher.dynamicInvoker(), worker1, worker2);
System.out.println((String) worker.invokeExact("met", "hod")); // method
switcher.invalidate();
System.out.println((String) worker.invokeExact("met", "hod")); // hodmet
* </pre></blockquote>
* In this case, the fallback path (worker2) does not cause a state change.
* In a real application, the fallback path could cause call sites to relink
* themselves in response to a global data structure change.
* Thus, volatile call sites can be used to build dependency mechanisms.
* @author John Rose, JSR 292 EG
*/
public
class
VolatileCallSite
extends
CallSite
{
volatile
MethodHandle
fallback
;
/** Create a call site with a volatile target.
* The initial target and fallback are both set to a method handle
* of the given type which will throw {@code IllegalStateException}.
*/
public
VolatileCallSite
(
MethodType
type
)
{
super
(
type
);
fallback
=
target
;
}
/** Create a call site with a volatile target.
* The fallback and target are both set to the same initial value.
*/
public
VolatileCallSite
(
MethodHandle
target
)
{
super
(
target
);
fallback
=
target
;
}
/** Create a call site with a volatile target.
* The fallback and target are set to the given initial values.
*/
public
VolatileCallSite
(
MethodHandle
target
,
MethodHandle
fallback
)
{
this
(
target
);
checkTargetChange
(
target
,
fallback
);
// make sure they have the same type
this
.
fallback
=
fallback
;
}
/** Internal override to nominally final getTarget. */
@Override
MethodHandle
getTarget0
()
{
return
getTargetVolatile
();
}
/**
* Set the target method of this call site, as a volatile variable.
* Has the same effect as {@link CallSite#setTarget}, with the additional
* effects associated with volatiles, in the Java Memory Model.
*/
@Override
public
void
setTarget
(
MethodHandle
newTarget
)
{
checkTargetChange
(
getTargetVolatile
(),
newTarget
);
setTargetVolatile
(
newTarget
);
}
/**
* Return the fallback target for this call site.
* It is initialized to the target the call site had when it was constructed,
* but it may be changed by {@link setFallbackTarget}.
* <p>
* Like the regular target of a volatile call site,
* the fallback target also has the behavior of a volatile variable.
*/
public
MethodHandle
getFallbackTarget
()
{
return
fallback
;
}
/**
* Update the fallback target for this call site.
* @see #getFallbackTarget
*/
public
void
setFallbackTarget
(
MethodHandle
newFallbackTarget
)
{
checkTargetChange
(
fallback
,
newFallbackTarget
);
fallback
=
newFallbackTarget
;
}
/**
* Reset this call site to a known state by changing the target to the fallback target value.
* Equivalent to {@code setTarget(getFallbackTarget())}.
*/
public
void
invalidate
()
{
setTargetVolatile
(
getFallbackTarget
());
}
/**
* Reset all call sites in a list by changing the target of each to its fallback value.
*/
public
static
void
invalidateAll
(
List
<
VolatileCallSite
>
sites
)
{
for
(
VolatileCallSite
site
:
sites
)
{
site
.
invalidate
();
}
}
}
src/share/classes/java/dyn/package-info.java
浏览文件 @
5150d263
此差异已折叠。
点击以展开。
src/share/classes/sun/dyn/AdapterMethodHandle.java
浏览文件 @
5150d263
...
...
@@ -487,7 +487,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
static
class
WithTypeHandler
extends
AdapterMethodHandle
{
final
MethodHandle
target
,
typeHandler
;
WithTypeHandler
(
MethodHandle
target
,
MethodHandle
typeHandler
)
{
super
(
target
,
target
.
type
(),
OP_RETYPE_ONLY
);
super
(
target
,
target
.
type
(),
makeConv
(
OP_RETYPE_ONLY
)
);
this
.
target
=
target
;
this
.
typeHandler
=
typeHandler
.
asType
(
TYPE_HANDLER_TYPE
);
}
...
...
src/share/classes/sun/dyn/BoundMethodHandle.java
浏览文件 @
5150d263
...
...
@@ -106,18 +106,17 @@ public class BoundMethodHandle extends MethodHandle {
assert
(
this
instanceof
AdapterMethodHandle
);
}
/** Initialize the current object as a
Java
method handle, binding it
/** Initialize the current object as a
self-bound
method handle, binding it
* as the first argument of the method handle {@code entryPoint}.
* The invocation type of the resulting method handle will be the
* same as {@code entryPoint}, except that the first argument
* type will be dropped.
*/
protected
BoundMethodHandle
(
MethodHandle
entryPoint
)
{
super
(
Access
.
TOKEN
,
entryPoint
.
type
().
dropParameterTypes
(
0
,
1
));
protected
BoundMethodHandle
(
Access
token
,
MethodHandle
entryPoint
)
{
super
(
token
,
entryPoint
.
type
().
dropParameterTypes
(
0
,
1
));
this
.
argument
=
this
;
// kludge; get rid of
this
.
vmargslot
=
this
.
type
().
parameterSlotDepth
(
0
);
initTarget
(
entryPoint
,
0
);
assert
(
this
instanceof
JavaMethodHandle
);
}
/** Make sure the given {@code argument} can be used as {@code argnum}-th
...
...
@@ -173,6 +172,11 @@ public class BoundMethodHandle extends MethodHandle {
@Override
public
String
toString
()
{
return
MethodHandleImpl
.
addTypeString
(
baseName
(),
this
);
}
/** Component of toString() before the type string. */
protected
String
baseName
()
{
MethodHandle
mh
=
this
;
while
(
mh
instanceof
BoundMethodHandle
)
{
Object
info
=
MethodHandleNatives
.
getTargetInfo
(
mh
);
...
...
@@ -185,12 +189,16 @@ public class BoundMethodHandle extends MethodHandle {
if
(
name
!=
null
)
return
name
;
else
return
super
.
toString
();
// <unknown>
, probably
return
noParens
(
super
.
toString
());
// "invoke"
, probably
}
assert
(
mh
!=
this
);
if
(
mh
instanceof
JavaMethodHandle
)
break
;
// access JMH.toString(), not BMH.toString()
}
return
mh
.
toString
();
return
noParens
(
mh
.
toString
());
}
private
static
String
noParens
(
String
str
)
{
int
paren
=
str
.
indexOf
(
'('
);
if
(
paren
>=
0
)
str
=
str
.
substring
(
0
,
paren
);
return
str
;
}
}
src/share/classes/sun/dyn/CallSiteImpl.java
浏览文件 @
5150d263
...
...
@@ -41,25 +41,39 @@ public class CallSiteImpl {
Object
info
,
// Caller information:
MemberName
callerMethod
,
int
callerBCI
)
{
Class
<?>
caller
=
callerMethod
.
getDeclaringClass
();
Class
<?>
callerClass
=
callerMethod
.
getDeclaringClass
();
Object
caller
;
if
(
bootstrapMethod
.
type
().
parameterType
(
0
)
==
Class
.
class
)
caller
=
callerClass
;
// remove for PFD
else
caller
=
MethodHandleImpl
.
IMPL_LOOKUP
.
in
(
callerClass
);
if
(
bootstrapMethod
==
null
)
{
// If there is no bootstrap method, throw IncompatibleClassChangeError.
// This is a valid generic error type for resolution (JLS 12.3.3).
throw
new
IncompatibleClassChangeError
(
"Class "
+
caller
.
getName
()+
" has not declared a bootstrap method for invokedynamic"
);
(
"Class "
+
caller
Class
.
getName
()+
" has not declared a bootstrap method for invokedynamic"
);
}
CallSite
site
;
try
{
Object
binding
;
if
(
false
)
// switch when invokeGeneric works
binding
=
bootstrapMethod
.
invokeGeneric
(
caller
,
name
,
type
);
else
binding
=
bootstrapMethod
.
invokeVarargs
(
new
Object
[]{
caller
,
name
,
type
});
if
(
info
==
null
)
{
if
(
false
)
// switch when invokeGeneric works
binding
=
bootstrapMethod
.
invokeGeneric
(
caller
,
name
,
type
);
else
binding
=
bootstrapMethod
.
invokeVarargs
(
new
Object
[]{
caller
,
name
,
type
});
}
else
{
info
=
maybeReBox
(
info
);
if
(
false
)
// switch when invokeGeneric works
binding
=
bootstrapMethod
.
invokeGeneric
(
caller
,
name
,
type
,
info
);
else
binding
=
bootstrapMethod
.
invokeVarargs
(
new
Object
[]{
caller
,
name
,
type
,
info
});
}
//System.out.println("BSM for "+name+type+" => "+binding);
if
(
binding
instanceof
CallSite
)
{
site
=
(
CallSite
)
binding
;
}
else
if
(
binding
instanceof
MethodHandleProvider
)
{
MethodHandle
target
=
((
MethodHandleProvider
)
binding
).
asMethodHandle
();
}
else
if
(
binding
instanceof
MethodHandle
)
{
// Transitional!
MethodHandle
target
=
(
MethodHandle
)
binding
;
site
=
new
ConstantCallSite
(
target
);
}
else
{
throw
new
ClassCastException
(
"bootstrap method failed to produce a MethodHandle or CallSite"
);
...
...
@@ -79,6 +93,24 @@ public class CallSiteImpl {
return
site
;
}
private
static
Object
maybeReBox
(
Object
x
)
{
if
(
x
instanceof
Integer
)
{
int
xi
=
(
int
)
x
;
if
(
xi
==
(
byte
)
xi
)
x
=
xi
;
// must rebox; see JLS 5.1.7
return
x
;
}
else
if
(
x
instanceof
Object
[])
{
Object
[]
xa
=
(
Object
[])
x
;
for
(
int
i
=
0
;
i
<
xa
.
length
;
i
++)
{
if
(
xa
[
i
]
instanceof
Integer
)
xa
[
i
]
=
maybeReBox
(
xa
[
i
]);
}
return
xa
;
}
else
{
return
x
;
}
}
// This method is private in CallSite because it touches private fields in CallSite.
// These private fields (vmmethod, vmindex) are specific to the JVM.
private
static
final
MethodHandle
PRIVATE_INITIALIZE_CALL_SITE
;
...
...
src/share/classes/sun/dyn/FilterGeneric.java
浏览文件 @
5150d263
...
...
@@ -115,7 +115,7 @@ class FilterGeneric {
static
MethodHandle
make
(
Kind
kind
,
int
pos
,
MethodHandle
filter
,
MethodHandle
target
)
{
FilterGeneric
fgen
=
of
(
kind
,
pos
,
filter
.
type
(),
target
.
type
());
return
fgen
.
makeInstance
(
kind
,
pos
,
filter
,
target
)
.
asMethodHandle
()
;
return
fgen
.
makeInstance
(
kind
,
pos
,
filter
,
target
);
}
/** Return the adapter information for this target and filter type. */
...
...
@@ -225,13 +225,13 @@ class FilterGeneric {
* The invoker is kept separate from the target because it can be
* generated once per type erasure family, and reused across adapters.
*/
static
abstract
class
Adapter
extends
Java
MethodHandle
{
static
abstract
class
Adapter
extends
Bound
MethodHandle
{
protected
final
MethodHandle
filter
;
// transforms one or more arguments
protected
final
MethodHandle
target
;
// ultimate target
@Override
public
String
toString
()
{
return
target
.
toString
(
);
return
MethodHandleImpl
.
addTypeString
(
target
,
this
);
}
protected
boolean
isPrototype
()
{
return
target
==
null
;
}
...
...
@@ -246,7 +246,7 @@ class FilterGeneric {
protected
Adapter
(
MethodHandle
entryPoint
,
MethodHandle
filter
,
MethodHandle
target
)
{
super
(
entryPoint
);
super
(
Access
.
TOKEN
,
entryPoint
);
this
.
filter
=
filter
;
this
.
target
=
target
;
}
...
...
src/share/classes/sun/dyn/FilterOneArgument.java
浏览文件 @
5150d263
...
...
@@ -36,7 +36,7 @@ import static sun.dyn.MemberName.uncaughtException;
* final method type is the responsibility of a JVM-level adapter.
* @author jrose
*/
public
class
FilterOneArgument
extends
Java
MethodHandle
{
public
class
FilterOneArgument
extends
Bound
MethodHandle
{
protected
final
MethodHandle
filter
;
// Object -> Object
protected
final
MethodHandle
target
;
// Object -> Object
...
...
@@ -62,7 +62,7 @@ public class FilterOneArgument extends JavaMethodHandle {
}
protected
FilterOneArgument
(
MethodHandle
filter
,
MethodHandle
target
)
{
super
(
INVOKE
);
super
(
Access
.
TOKEN
,
INVOKE
);
this
.
filter
=
filter
;
this
.
target
=
target
;
}
...
...
src/share/classes/sun/dyn/FromGeneric.java
浏览文件 @
5150d263
...
...
@@ -241,7 +241,7 @@ class FromGeneric {
* The invoker is kept separate from the target because it can be
* generated once per type erasure family, and reused across adapters.
*/
static
abstract
class
Adapter
extends
Java
MethodHandle
{
static
abstract
class
Adapter
extends
Bound
MethodHandle
{
/*
* class X<<R,int N>> extends Adapter {
* (MH, Object**N)=>raw(R) invoker;
...
...
@@ -256,7 +256,7 @@ class FromGeneric {
@Override
public
String
toString
()
{
return
target
.
toString
(
);
return
MethodHandleImpl
.
addTypeString
(
target
,
this
);
}
protected
boolean
isPrototype
()
{
return
target
==
null
;
}
...
...
@@ -271,7 +271,7 @@ class FromGeneric {
protected
Adapter
(
MethodHandle
entryPoint
,
MethodHandle
invoker
,
MethodHandle
convert
,
MethodHandle
target
)
{
super
(
entryPoint
);
super
(
Access
.
TOKEN
,
entryPoint
);
this
.
invoker
=
invoker
;
this
.
convert
=
convert
;
this
.
target
=
target
;
...
...
src/share/classes/sun/dyn/Invokers.java
浏览文件 @
5150d263
...
...
@@ -26,6 +26,7 @@
package
sun.dyn
;
import
java.dyn.*
;
import
sun.dyn.empty.Empty
;
/**
* Construction and caching of often-used invokers.
...
...
@@ -48,6 +49,9 @@ public class Invokers {
// generic (untyped) invoker for the outgoing call; accepts a single Object[]
private
final
/*lazy*/
MethodHandle
[]
varargsInvokers
;
// invoker for an unbound callsite
private
/*lazy*/
MethodHandle
uninitializedCallSite
;
/** Compute and cache information common to all collecting adapters
* that implement members of the erasure-family of the given erased type.
*/
...
...
@@ -107,6 +111,35 @@ public class Invokers {
return
vaInvoker
;
}
private
static
MethodHandle
THROW_UCS
=
null
;
public
MethodHandle
uninitializedCallSite
()
{
MethodHandle
invoker
=
uninitializedCallSite
;
if
(
invoker
!=
null
)
return
invoker
;
if
(
targetType
.
parameterCount
()
>
0
)
{
MethodType
type0
=
targetType
.
dropParameterTypes
(
0
,
targetType
.
parameterCount
());
Invokers
invokers0
=
MethodTypeImpl
.
invokers
(
Access
.
TOKEN
,
type0
);
invoker
=
MethodHandles
.
dropArguments
(
invokers0
.
uninitializedCallSite
(),
0
,
targetType
.
parameterList
());
assert
(
invoker
.
type
().
equals
(
targetType
));
uninitializedCallSite
=
invoker
;
return
invoker
;
}
if
(
THROW_UCS
==
null
)
{
try
{
THROW_UCS
=
MethodHandleImpl
.
IMPL_LOOKUP
.
findStatic
(
CallSite
.
class
,
"uninitializedCallSite"
,
MethodType
.
methodType
(
Empty
.
class
));
}
catch
(
NoAccessException
ex
)
{
throw
new
RuntimeException
(
ex
);
}
}
invoker
=
AdapterMethodHandle
.
makeRetypeRaw
(
Access
.
TOKEN
,
targetType
,
THROW_UCS
);
assert
(
invoker
.
type
().
equals
(
targetType
));
uninitializedCallSite
=
invoker
;
return
invoker
;
}
public
String
toString
()
{
return
"Invokers"
+
targetType
;
}
...
...
src/share/classes/sun/dyn/JavaMethodHandle.java
已删除
100644 → 0
浏览文件 @
70e0218c
/*
* Copyright (c) 2008, 2009, 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.
*/
package
sun.dyn
;
import
java.dyn.*
;
import
sun.dyn.Access
;
/**
* A Java method handle is a deprecated proposal for extending
* the basic method handle type with additional
* programmer defined methods and fields.
* Its behavior as a method handle is determined at instance creation time,
* by providing the new instance with an "entry point" method handle
* to handle calls. This entry point must accept a leading argument
* whose type is the Java method handle itself or a supertype, and the
* entry point is always called with the Java method handle itself as
* the first argument. This is similar to ordinary virtual methods, which also
* accept the receiver object {@code this} as an implicit leading argument.
* The {@code MethodType} of the Java method handle is the same as that
* of the entry point method handle, with the leading parameter type
* omitted.
* <p>
* Here is an example of usage, creating a hybrid object/functional datum:
* <p><blockquote><pre>
* class Greeter extends JavaMethodHandle {
* private String greeting = "hello";
* public void setGreeting(String s) { greeting = s; }
* public void run() { System.out.println(greeting+", "+greetee); }
* private final String greetee;
* Greeter(String greetee) {
* super(RUN); // alternatively, super("run")
* this.greetee = greetee;
* }
* // the entry point function is computed once:
* private static final MethodHandle RUN
* = MethodHandles.lookup().findVirtual(Greeter.class, "run",
* MethodType.make(void.class));
* }
* // class Main { public static void main(String... av) { ...
* Greeter greeter = new Greeter("world");
* greeter.run(); // prints "hello, world"
* // Statically typed method handle invocation (most direct):
* MethodHandle mh = greeter;
* mh.<void>invokeExact(); // also prints "hello, world"
* // Dynamically typed method handle invocation:
* MethodHandles.invokeExact(greeter); // also prints "hello, world"
* greeter.setGreeting("howdy");
* mh.invokeExact(); // prints "howdy, world" (object-like mutable behavior)
* </pre></blockquote>
* <p>
* In the example of {@code Greeter}, the method {@code run} provides the entry point.
* The entry point need not be a constant value; it may be independently
* computed in each call to the constructor. The entry point does not
* even need to be a method on the {@code Greeter} class, though
* that is the typical case.
* <p>
* The entry point may also be provided symbolically, in which case the the
* {@code JavaMethodHandle} constructor performs the lookup of the entry point.
* This makes it possible to use {@code JavaMethodHandle} to create an anonymous
* inner class:
* <p><blockquote><pre>
* // We can also do this with symbolic names and/or inner classes:
* MethodHandles.invokeExact(new JavaMethodHandle("yow") {
* void yow() { System.out.println("yow, world"); }
* });
* </pre></blockquote>
* <p>
* Here is similar lower-level code which works in terms of a bound method handle.
* <p><blockquote><pre>
* class Greeter {
* public void run() { System.out.println("hello, "+greetee); }
* private final String greetee;
* Greeter(String greetee) { this.greetee = greetee; }
* // the entry point function is computed once:
* private static final MethodHandle RUN
* = MethodHandles.findVirtual(Greeter.class, "run",
* MethodType.make(void.class));
* }
* // class Main { public static void main(String... av) { ...
* Greeter greeter = new Greeter("world");
* greeter.run(); // prints "hello, world"
* MethodHandle mh = MethodHanndles.insertArgument(Greeter.RUN, 0, greeter);
* mh.invokeExact(); // also prints "hello, world"
* </pre></blockquote>
* Note that the method handle must be separately created as a view on the base object.
* This increases footprint, complexity, and dynamic indirections.
* <p>
* Here is a pure functional value expressed most concisely as an anonymous inner class:
* <p><blockquote><pre>
* // class Main { public static void main(String... av) { ...
* final String greetee = "world";
* MethodHandle greeter = new JavaMethodHandle("run") {
* private void run() { System.out.println("hello, "+greetee); }
* }
* greeter.invokeExact(); // prints "hello, world"
* </pre></blockquote>
* <p>
* Here is an abstract parameterized lvalue, efficiently expressed as a subtype of MethodHandle,
* and instantiated as an anonymous class. The data structure is a handle to 1-D array,
* with a specialized index type (long). It is created by inner class, and uses
* signature-polymorphic APIs throughout.
* <p><blockquote><pre>
* abstract class AssignableMethodHandle extends JavaMethodHandle {
* private final MethodHandle setter;
* public MethodHandle setter() { return setter; }
* public AssignableMethodHandle(String get, String set) {
* super(get);
* MethodType getType = this.type();
* MethodType setType = getType.insertParameterType(getType.parameterCount(), getType.returnType()).changeReturnType(void.class);
* this.setter = MethodHandles.publicLookup().bind(this, set, setType);
* }
* }
* // class Main { public static void main(String... av) { ...
* final Number[] stuff = { 123, 456 };
* AssignableMethodHandle stuffPtr = new AssignableMethodHandle("get", "set") {
* public Number get(long i) { return stuff[(int)i]; }
* public void set(long i, Object x) { stuff[(int)i] = x; }
* }
* int x = (Integer) stuffPtr.<Number>invokeExact(1L); // 456
* stuffPtr.setter().<void>invokeExact(0L, (Number) 789); // replaces 123 with 789
* </pre></blockquote>
* @see MethodHandle
* @deprecated The JSR 292 EG intends to replace {@code JavaMethodHandle} with
* an interface-based API for mixing method handle behavior with other classes.
* @author John Rose, JSR 292 EG
*/
public
abstract
class
JavaMethodHandle
// Note: This is an implementation inheritance hack, and will be removed
// with a JVM change which moves the required hidden behavior onto this class.
extends
sun
.
dyn
.
BoundMethodHandle
{
private
static
final
Access
IMPL_TOKEN
=
Access
.
getToken
();
/**
* When creating a {@code JavaMethodHandle}, the actual method handle
* invocation behavior will be delegated to the specified {@code entryPoint}.
* This may be any method handle which can take the newly constructed object
* as a leading parameter.
* <p>
* The method handle type of {@code this} (i.e, the fully constructed object)
* will be {@code entryPoint}, minus the leading argument.
* The leading argument will be bound to {@code this} on every method
* handle invocation.
* @param entryPoint the method handle to handle calls
*/
protected
JavaMethodHandle
(
MethodHandle
entryPoint
)
{
super
(
entryPoint
);
}
}
src/share/classes/sun/dyn/MethodHandleImpl.java
浏览文件 @
5150d263
...
...
@@ -199,7 +199,7 @@ public abstract class MethodHandleImpl {
return
allocator
;
}
static
final
class
AllocateObject
<
C
>
extends
Java
MethodHandle
{
static
final
class
AllocateObject
<
C
>
extends
Bound
MethodHandle
{
private
static
final
Unsafe
unsafe
=
Unsafe
.
getUnsafe
();
private
final
Class
<
C
>
allocateClass
;
...
...
@@ -207,7 +207,7 @@ public abstract class MethodHandleImpl {
private
AllocateObject
(
MethodHandle
invoker
,
Class
<
C
>
allocateClass
,
MethodHandle
rawConstructor
)
{
super
(
invoker
);
super
(
Access
.
TOKEN
,
invoker
);
this
.
allocateClass
=
allocateClass
;
this
.
rawConstructor
=
rawConstructor
;
}
...
...
@@ -237,7 +237,7 @@ public abstract class MethodHandleImpl {
}
@Override
public
String
toString
()
{
return
a
llocateClass
.
getSimpleName
(
);
return
a
ddTypeString
(
allocateClass
.
getSimpleName
(),
this
);
}
@SuppressWarnings
(
"unchecked"
)
private
C
allocate
()
throws
InstantiationException
{
...
...
@@ -369,19 +369,19 @@ public abstract class MethodHandleImpl {
return
mhs
[
isSetter
?
1
:
0
];
}
static
final
class
FieldAccessor
<
C
,
V
>
extends
Java
MethodHandle
{
static
final
class
FieldAccessor
<
C
,
V
>
extends
Bound
MethodHandle
{
private
static
final
Unsafe
unsafe
=
Unsafe
.
getUnsafe
();
final
Object
base
;
// for static refs only
final
long
offset
;
final
String
name
;
public
FieldAccessor
(
Access
token
,
MemberName
field
,
boolean
isSetter
)
{
super
(
fhandle
(
field
.
getDeclaringClass
(),
field
.
getFieldType
(),
isSetter
,
field
.
isStatic
()));
super
(
Access
.
TOKEN
,
fhandle
(
field
.
getDeclaringClass
(),
field
.
getFieldType
(),
isSetter
,
field
.
isStatic
()));
this
.
offset
=
(
long
)
field
.
getVMIndex
(
token
);
this
.
name
=
field
.
getName
();
this
.
base
=
staticBase
(
field
);
}
public
String
toString
()
{
return
name
;
}
public
String
toString
()
{
return
addTypeString
(
name
,
this
)
;
}
int
getFieldI
(
C
obj
)
{
return
unsafe
.
getInt
(
obj
,
offset
);
}
void
setFieldI
(
C
obj
,
int
x
)
{
unsafe
.
putInt
(
obj
,
offset
,
x
);
}
...
...
@@ -910,11 +910,11 @@ public abstract class MethodHandleImpl {
throw
new
UnsupportedOperationException
(
"NYI"
);
}
private
static
class
GuardWithTest
extends
Java
MethodHandle
{
private
static
class
GuardWithTest
extends
Bound
MethodHandle
{
private
final
MethodHandle
test
,
target
,
fallback
;
private
GuardWithTest
(
MethodHandle
invoker
,
MethodHandle
test
,
MethodHandle
target
,
MethodHandle
fallback
)
{
super
(
invoker
);
super
(
Access
.
TOKEN
,
invoker
);
this
.
test
=
test
;
this
.
target
=
target
;
this
.
fallback
=
fallback
;
...
...
@@ -948,7 +948,7 @@ public abstract class MethodHandleImpl {
}
@Override
public
String
toString
()
{
return
target
.
toString
(
);
return
addTypeString
(
target
,
this
);
}
private
Object
invoke_V
(
Object
...
av
)
throws
Throwable
{
if
(
test
.<
boolean
>
invokeExact
(
av
))
...
...
@@ -1038,7 +1038,7 @@ public abstract class MethodHandleImpl {
return
GuardWithTest
.
make
(
token
,
test
,
target
,
fallback
);
}
private
static
class
GuardWithCatch
extends
Java
MethodHandle
{
private
static
class
GuardWithCatch
extends
Bound
MethodHandle
{
private
final
MethodHandle
target
;
private
final
Class
<?
extends
Throwable
>
exType
;
private
final
MethodHandle
catcher
;
...
...
@@ -1047,14 +1047,14 @@ public abstract class MethodHandleImpl {
}
public
GuardWithCatch
(
MethodHandle
invoker
,
MethodHandle
target
,
Class
<?
extends
Throwable
>
exType
,
MethodHandle
catcher
)
{
super
(
invoker
);
super
(
Access
.
TOKEN
,
invoker
);
this
.
target
=
target
;
this
.
exType
=
exType
;
this
.
catcher
=
catcher
;
}
@Override
public
String
toString
()
{
return
target
.
toString
(
);
return
addTypeString
(
target
,
this
);
}
private
Object
invoke_V
(
Object
...
av
)
throws
Throwable
{
try
{
...
...
@@ -1219,21 +1219,24 @@ public abstract class MethodHandleImpl {
if
(
target
!=
null
)
name
=
MethodHandleNatives
.
getMethodName
(
target
);
if
(
name
==
null
)
return
"
<unknown>"
;
return
name
.
getName
();
return
"
invoke"
+
target
.
type
()
;
return
name
.
getName
()
+
target
.
type
()
;
}
public
static
String
addTypeString
(
MethodHandle
target
)
{
if
(
target
==
null
)
return
"null"
;
return
target
.
toString
()
+
target
.
type
();
static
String
addTypeString
(
Object
obj
,
MethodHandle
target
)
{
String
str
=
String
.
valueOf
(
obj
);
if
(
target
==
null
)
return
str
;
int
paren
=
str
.
indexOf
(
'('
);
if
(
paren
>=
0
)
str
=
str
.
substring
(
0
,
paren
);
return
str
+
target
.
type
();
}
public
static
void
checkSpreadArgument
(
Object
av
,
int
n
)
{
static
void
checkSpreadArgument
(
Object
av
,
int
n
)
{
if
(
av
==
null
?
n
!=
0
:
((
Object
[])
av
).
length
!=
n
)
throw
newIllegalArgumentException
(
"Array is not of length "
+
n
);
}
public
static
void
raiseException
(
int
code
,
Object
actual
,
Object
required
)
{
static
void
raiseException
(
int
code
,
Object
actual
,
Object
required
)
{
String
message
;
// disregard the identity of the actual object, if it is not a class:
if
(!(
actual
instanceof
Class
)
&&
!(
actual
instanceof
MethodType
))
...
...
src/share/classes/sun/dyn/SpreadGeneric.java
浏览文件 @
5150d263
...
...
@@ -208,7 +208,7 @@ class SpreadGeneric {
* The invoker is kept separate from the target because it can be
* generated once per type erasure family, and reused across adapters.
*/
static
abstract
class
Adapter
extends
Java
MethodHandle
{
static
abstract
class
Adapter
extends
Bound
MethodHandle
{
/*
* class X<<R,int M,int N>> extends Adapter {
* (Object**N)=>R target;
...
...
@@ -221,21 +221,21 @@ class SpreadGeneric {
@Override
public
String
toString
()
{
return
target
.
toString
(
);
return
MethodHandleImpl
.
addTypeString
(
target
,
this
);
}
static
final
MethodHandle
NO_ENTRY
=
ValueConversions
.
identity
();
protected
boolean
isPrototype
()
{
return
target
==
null
;
}
protected
Adapter
(
SpreadGeneric
outer
)
{
super
(
NO_ENTRY
);
super
(
Access
.
TOKEN
,
NO_ENTRY
);
this
.
outer
=
outer
;
this
.
target
=
null
;
assert
(
isPrototype
());
}
protected
Adapter
(
SpreadGeneric
outer
,
MethodHandle
target
)
{
super
(
outer
.
entryPoint
);
super
(
Access
.
TOKEN
,
outer
.
entryPoint
);
this
.
outer
=
outer
;
this
.
target
=
target
;
}
...
...
src/share/classes/sun/dyn/ToGeneric.java
浏览文件 @
5150d263
...
...
@@ -323,7 +323,7 @@ class ToGeneric {
* via another method handle {@code convert}, which is responsible for
* converting the object result into the raw return value.
*/
static
abstract
class
Adapter
extends
Java
MethodHandle
{
static
abstract
class
Adapter
extends
Bound
MethodHandle
{
/*
* class X<<R,A...>> extends Adapter {
* Object...=>Object target;
...
...
@@ -337,13 +337,13 @@ class ToGeneric {
@Override
public
String
toString
()
{
return
target
==
null
?
"prototype:"
+
convert
:
target
.
toString
(
);
return
target
==
null
?
"prototype:"
+
convert
:
MethodHandleImpl
.
addTypeString
(
target
,
this
);
}
protected
boolean
isPrototype
()
{
return
target
==
null
;
}
/* Prototype constructor. */
protected
Adapter
(
MethodHandle
entryPoint
)
{
super
(
entryPoint
);
super
(
Access
.
TOKEN
,
entryPoint
);
this
.
invoker
=
null
;
this
.
convert
=
entryPoint
;
this
.
target
=
null
;
...
...
@@ -355,7 +355,7 @@ class ToGeneric {
}
protected
Adapter
(
MethodHandle
entryPoint
,
MethodHandle
invoker
,
MethodHandle
convert
,
MethodHandle
target
)
{
super
(
entryPoint
);
super
(
Access
.
TOKEN
,
entryPoint
);
this
.
invoker
=
invoker
;
this
.
convert
=
convert
;
this
.
target
=
target
;
...
...
src/share/classes/sun/dyn/util/ValueConversions.java
浏览文件 @
5150d263
...
...
@@ -649,7 +649,9 @@ public class ValueConversions {
return
mh
;
}
// slow path
MethodType
type
=
MethodType
.
methodType
(
wrap
.
primitiveType
(),
wrap
.
primitiveType
());
MethodType
type
=
MethodType
.
methodType
(
wrap
.
primitiveType
());
if
(
wrap
!=
Wrapper
.
VOID
)
type
=
type
.
appendParameterTypes
(
wrap
.
primitiveType
());
try
{
mh
=
IMPL_LOOKUP
.
findStatic
(
ValueConversions
.
class
,
"identity"
,
type
);
}
catch
(
NoAccessException
ex
)
{
...
...
@@ -677,7 +679,7 @@ public class ValueConversions {
}
private
static
MethodHandle
retype
(
MethodType
type
,
MethodHandle
mh
)
{
return
AdapterMethodHandle
.
makeRetype
Only
(
IMPL_TOKEN
,
type
,
mh
);
return
AdapterMethodHandle
.
makeRetype
Raw
(
IMPL_TOKEN
,
type
,
mh
);
}
private
static
final
Object
[]
NO_ARGS_ARRAY
=
{};
...
...
src/share/classes/sun/dyn/util/VerifyAccess.java
浏览文件 @
5150d263
...
...
@@ -25,7 +25,6 @@
package
sun.dyn.util
;
import
java.dyn.LinkagePermission
;
import
java.dyn.NoAccessException
;
import
java.lang.reflect.Modifier
;
import
sun.dyn.MemberName
;
...
...
@@ -43,6 +42,7 @@ public class VerifyAccess {
private
static
final
int
PACKAGE_ONLY
=
0
;
private
static
final
int
ALL_ACCESS_MODES
=
(
PUBLIC
|
PRIVATE
|
PROTECTED
|
PACKAGE_ONLY
);
private
static
final
boolean
ALLOW_NESTMATE_ACCESS
=
false
;
/**
* Evaluate the JVM linkage rules for access to the given method
...
...
@@ -102,6 +102,8 @@ public class VerifyAccess {
// a superclass of the lookup class.
}
}
if
(
defc
==
lookupClass
)
return
true
;
// easy check; all self-access is OK
switch
(
mods
&
ALL_ACCESS_MODES
)
{
case
PUBLIC:
if
(
refc
!=
defc
)
return
true
;
// already checked above
...
...
@@ -112,7 +114,8 @@ public class VerifyAccess {
return
isSamePackage
(
defc
,
lookupClass
);
case
PRIVATE:
// Loosened rules for privates follows access rules for inner classes.
return
isSamePackageMember
(
defc
,
lookupClass
);
return
(
ALLOW_NESTMATE_ACCESS
&&
isSamePackageMember
(
defc
,
lookupClass
));
default
:
throw
new
IllegalArgumentException
(
"bad modifiers: "
+
Modifier
.
toString
(
mods
));
}
...
...
@@ -206,24 +209,4 @@ public class VerifyAccess {
}
return
false
;
}
/**
* Ensure the requesting class have privileges to perform invokedynamic
* linkage operations on subjectClass. True if requestingClass is
* Access.class (meaning the request originates from the JVM) or if the
* classes are in the same package and have consistent class loaders.
* (The subject class loader must be identical with or be a child of
* the requesting class loader.)
* @param requestingClass
* @param subjectClass
*/
public
static
void
checkBootstrapPrivilege
(
Class
requestingClass
,
Class
subjectClass
,
String
permissionName
)
{
if
(
requestingClass
==
null
)
return
;
if
(
requestingClass
==
subjectClass
)
return
;
SecurityManager
security
=
System
.
getSecurityManager
();
if
(
security
==
null
)
return
;
// open season
if
(
isSamePackage
(
requestingClass
,
subjectClass
))
return
;
security
.
checkPermission
(
new
LinkagePermission
(
permissionName
,
requestingClass
));
}
}
src/share/classes/sun/dyn/util/Wrapper.java
浏览文件 @
5150d263
...
...
@@ -26,17 +26,19 @@
package
sun.dyn.util
;
public
enum
Wrapper
{
INT
(
Integer
.
class
,
int
.
class
,
'I'
,
(
Integer
)(
int
)
0
,
Format
.
signed
(
32
)),
LONG
(
Long
.
class
,
long
.
class
,
'J'
,
(
Long
)(
long
)
0
,
Format
.
signed
(
64
)),
BOOLEAN
(
Boolean
.
class
,
boolean
.
class
,
'Z'
,
(
Boolean
)
false
,
Format
.
unsigned
(
1
)),
// These must be in the order defined for widening primitive conversions in JLS 5.1.2
BYTE
(
Byte
.
class
,
byte
.
class
,
'B'
,
(
Byte
)(
byte
)
0
,
Format
.
signed
(
8
)),
SHORT
(
Short
.
class
,
short
.
class
,
'S'
,
(
Short
)(
short
)
0
,
Format
.
signed
(
16
)),
CHAR
(
Character
.
class
,
char
.
class
,
'C'
,
(
Character
)(
char
)
0
,
Format
.
unsigned
(
16
)),
BOOLEAN
(
Boolean
.
class
,
boolean
.
class
,
'Z'
,
(
Boolean
)
false
,
Format
.
unsigned
(
1
)),
INT
(
Integer
.
class
,
int
.
class
,
'I'
,
(
Integer
)(
int
)
0
,
Format
.
signed
(
32
)),
LONG
(
Long
.
class
,
long
.
class
,
'J'
,
(
Long
)(
long
)
0
,
Format
.
signed
(
64
)),
FLOAT
(
Float
.
class
,
float
.
class
,
'F'
,
(
Float
)(
float
)
0
,
Format
.
floating
(
32
)),
DOUBLE
(
Double
.
class
,
double
.
class
,
'D'
,
(
Double
)(
double
)
0
,
Format
.
floating
(
64
)),
VOID
(
Void
.
class
,
void
.
class
,
'V'
,
null
,
Format
.
other
(
0
)),
//NULL(Null.class, null.class, 'N', null, Format.other(1)),
OBJECT
(
Object
.
class
,
Object
.
class
,
'L'
,
null
,
Format
.
other
(
1
)),
// VOID must be the last type, since it is "assignable" from any other type:
VOID
(
Void
.
class
,
void
.
class
,
'V'
,
null
,
Format
.
other
(
0
)),
;
private
final
Class
<?>
wrapperType
;
...
...
@@ -76,9 +78,11 @@ public enum Wrapper {
false
);
return
kind
|
(
size
<<
SIZE_SHIFT
)
|
(
slots
<<
SLOT_SHIFT
);
}
static
int
static
final
int
INT
=
SIGNED
|
(
32
<<
SIZE_SHIFT
)
|
(
1
<<
SLOT_SHIFT
),
SHORT
=
SIGNED
|
(
16
<<
SIZE_SHIFT
)
|
(
1
<<
SLOT_SHIFT
),
BOOLEAN
=
UNSIGNED
|
(
1
<<
SIZE_SHIFT
)
|
(
1
<<
SLOT_SHIFT
),
CHAR
=
UNSIGNED
|
(
16
<<
SIZE_SHIFT
)
|
(
1
<<
SLOT_SHIFT
),
FLOAT
=
FLOATING
|
(
32
<<
SIZE_SHIFT
)
|
(
1
<<
SLOT_SHIFT
),
VOID
=
UNSIGNED
|
(
0
<<
SIZE_SHIFT
)
|
(
0
<<
SLOT_SHIFT
),
NUM_MASK
=
(-
1
)
<<
SIZE_SHIFT
;
...
...
@@ -111,6 +115,29 @@ public enum Wrapper {
/** Is the wrapped type either float or double? */
public
boolean
isFloating
()
{
return
format
>=
Format
.
FLOAT
;
}
/** Does the JVM verifier allow a variable of this wrapper's
* primitive type to be assigned from a value of the given wrapper's primitive type?
* Cases:
* <ul>
* <li>unboxing followed by widening primitive conversion
* <li>any type converted to {@code void}
* <li>boxing conversion followed by widening reference conversion to {@code Object}
* <li>conversion of {@code boolean} to any type
* </ul>
*/
public
boolean
isConvertibleFrom
(
Wrapper
source
)
{
if
(
this
==
source
)
return
true
;
if
(
this
.
compareTo
(
source
)
<
0
)
{
// At best, this is a narrowing conversion.
return
false
;
}
if
((
this
.
format
^
source
.
format
)
==
(
Format
.
SHORT
^
Format
.
CHAR
))
{
assert
(
this
==
SHORT
&&
source
==
CHAR
)
||
(
this
==
CHAR
&&
source
==
SHORT
);
return
false
;
}
return
true
;
}
/** Produce a zero value for the given wrapper type.
* This will be a numeric zero for a number or character,
* false for a boolean, and null for a reference or void.
...
...
@@ -122,10 +149,10 @@ public enum Wrapper {
public
Object
zero
()
{
return
zero
;
}
/** Produce a zero value for the given wrapper type T.
* The opti
no
al argument must a type compatible with this wrapper.
* The opti
on
al argument must a type compatible with this wrapper.
* Equivalent to {@code this.cast(this.zero(), type)}.
*/
public
<
T
>
T
zero
(
Class
<
T
>
type
)
{
return
c
as
t
(
zero
,
type
);
}
public
<
T
>
T
zero
(
Class
<
T
>
type
)
{
return
c
onver
t
(
zero
,
type
);
}
// /** Produce a wrapper for the given wrapper or primitive type. */
// public static Wrapper valueOf(Class<?> type) {
...
...
@@ -264,7 +291,11 @@ public enum Wrapper {
exampleType
.
isInterface
())
{
return
forceType
(
wrapperType
,
exampleType
);
}
throw
new
ClassCastException
(
exampleType
+
" not <:"
+
wrapperType
);
throw
newClassCastException
(
exampleType
,
primitiveType
);
}
private
static
ClassCastException
newClassCastException
(
Class
<?>
actual
,
Class
<?>
expected
)
{
return
new
ClassCastException
(
actual
+
" is not compatible with "
+
expected
);
}
/** If {@code type} is a primitive type, return the corresponding
...
...
@@ -325,17 +356,55 @@ public enum Wrapper {
// }
/** Cast a wrapped value to the given type, which may be either a primitive or wrapper type.
* The given target type must be this wrapper's primitive or wrapper type.
* If this wrapper is OBJECT, the target type may also be an interface, perform no runtime check.
* Performs standard primitive conversions, including truncation and float conversions.
* The given type must be compatible with this wrapper. That is, it must either
* be the wrapper type (or a subtype, in the case of {@code OBJECT}) or else
* it must be the wrapper's primitive type.
* Primitive conversions are only performed if the given type is itself a primitive.
* @throws ClassCastException if the given type is not compatible with this wrapper
*/
public
<
T
>
T
cast
(
Object
x
,
Class
<
T
>
type
)
{
return
convert
(
x
,
type
,
true
);
}
/** Convert a wrapped value to the given type.
* The given target type must be this wrapper's primitive or wrapper type.
* This is equivalent to {@link #cast}, except that it refuses to perform
* narrowing primitive conversions.
*/
public
<
T
>
T
convert
(
Object
x
,
Class
<
T
>
type
)
{
return
convert
(
x
,
type
,
false
);
}
private
<
T
>
T
convert
(
Object
x
,
Class
<
T
>
type
,
boolean
isCast
)
{
if
(
this
==
OBJECT
)
{
// If the target wrapper is OBJECT, just do a reference cast.
// If the target type is an interface, perform no runtime check.
// (This loophole is safe, and is allowed by the JVM verifier.)
// If the target type is a primitive, change it to a wrapper.
@SuppressWarnings
(
"unchecked"
)
T
result
=
(
T
)
x
;
// unchecked warning is expected here
return
result
;
}
Class
<
T
>
wtype
=
wrapperType
(
type
);
if
(
wtype
.
isInstance
(
x
))
return
wtype
.
cast
(
x
);
return
wtype
.
cast
(
wrap
(
x
));
if
(
wtype
.
isInstance
(
x
))
{
@SuppressWarnings
(
"unchecked"
)
T
result
=
(
T
)
x
;
// unchecked warning is expected here
return
result
;
}
Class
<?>
sourceType
=
x
.
getClass
();
// throw NPE if x is null
if
(!
isCast
)
{
Wrapper
source
=
findWrapperType
(
sourceType
);
if
(
source
==
null
||
!
this
.
isConvertibleFrom
(
source
))
{
throw
newClassCastException
(
wtype
,
sourceType
);
}
}
@SuppressWarnings
(
"unchecked"
)
T
result
=
(
T
)
wrap
(
x
);
// unchecked warning is expected here
assert
result
.
getClass
()
==
wtype
;
return
result
;
}
/** Cast a reference type to another reference type.
...
...
test/java/dyn/InvokeGenericTest.java
浏览文件 @
5150d263
...
...
@@ -398,7 +398,7 @@ public class InvokeGenericTest {
case
4
:
junk
=
target
.
invokeGeneric
(
args
[
0
],
args
[
1
],
args
[
2
],
args
[
3
]);
break
;
default
:
junk
=
MethodHandles
.
invokeVarargs
(
target
,
args
);
break
;
junk
=
target
.
invokeWithArguments
(
args
);
break
;
}
}
catch
(
WrongMethodTypeException
ex
)
{
return
;
...
...
test/java/dyn/JavaDocExamples.java
→
test/java/dyn/JavaDocExamples
Test
.java
浏览文件 @
5150d263
...
...
@@ -25,18 +25,18 @@
/* @test
* @summary example code used in javadoc for java.dyn API
* @compile -XDallowTransitionalJSR292=no JavaDocExamples.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.JavaDocExamples
* @compile -XDallowTransitionalJSR292=no JavaDocExamples
Test
.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.dyn.JavaDocExamples
Test
*/
/*
---- To run outside jtreg:
$ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \
$DAVINCI/sources/jdk/test/java/dyn/JavaDocExamples.java
$DAVINCI/sources/jdk/test/java/dyn/JavaDocExamples
Test
.java
$ $JAVA7X_HOME/bin/java -cp $JUNIT4_JAR:/tmp/Classes \
-XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \
-Dtest.java.dyn.JavaDocExamples.verbosity=1 \
test.java.dyn.JavaDocExamples
-Dtest.java.dyn.JavaDocExamples
Test
.verbosity=1 \
test.java.dyn.JavaDocExamples
Test
----
*/
...
...
@@ -57,15 +57,15 @@ import static org.junit.Assume.*;
/**
* @author jrose
*/
public
class
JavaDocExamples
{
public
class
JavaDocExamples
Test
{
/** Wrapper for running the JUnit tests in this module.
* Put JUnit on the classpath!
*/
public
static
void
main
(
String
...
ignore
)
{
org
.
junit
.
runner
.
JUnitCore
.
runClasses
(
JavaDocExamples
.
class
);
org
.
junit
.
runner
.
JUnitCore
.
runClasses
(
JavaDocExamples
Test
.
class
);
}
// How much output?
static
int
verbosity
=
Integer
.
getInteger
(
"test.java.dyn.JavaDocExamples.verbosity"
,
0
);
static
int
verbosity
=
Integer
.
getInteger
(
"test.java.dyn.JavaDocExamples
Test
.verbosity"
,
0
);
{}
static
final
private
Lookup
LOOKUP
=
lookup
();
...
...
@@ -120,9 +120,79 @@ assertEquals("xz", /*(String)*/ d12.invokeExact("x", 12, true, "z"));
}}
}
@Test
public
void
testFilterArguments
()
throws
Throwable
{
{{
{}
/// JAVADOC
MethodHandle
cat
=
lookup
().
findVirtual
(
String
.
class
,
"concat"
,
methodType
(
String
.
class
,
String
.
class
));
cat
=
cat
.
asType
(
methodType
(
Object
.
class
,
String
.
class
,
String
.
class
));
/*(String)*/
MethodHandle
upcase
=
lookup
().
findVirtual
(
String
.
class
,
"toUpperCase"
,
methodType
(
String
.
class
));
assertEquals
(
"xy"
,
/*(String)*/
cat
.
invokeExact
(
"x"
,
"y"
));
// xy
MethodHandle
f0
=
filterArguments
(
cat
,
0
,
upcase
);
assertEquals
(
"Xy"
,
/*(String)*/
f0
.
invokeExact
(
"x"
,
"y"
));
// Xy
MethodHandle
f1
=
filterArguments
(
cat
,
1
,
upcase
);
assertEquals
(
"xY"
,
/*(String)*/
f1
.
invokeExact
(
"x"
,
"y"
));
// xY
MethodHandle
f2
=
filterArguments
(
cat
,
0
,
upcase
,
upcase
);
assertEquals
(
"XY"
,
/*(String)*/
f2
.
invokeExact
(
"x"
,
"y"
));
// XY
}}
}
static
void
assertEquals
(
Object
exp
,
Object
act
)
{
if
(
verbosity
>
0
)
System
.
out
.
println
(
"result: "
+
act
);
Assert
.
assertEquals
(
exp
,
act
);
}
@Test
public
void
testVolatileCallSite
()
throws
Throwable
{
{{
{}
/// JAVADOC
MethodHandle
strcat
=
MethodHandles
.
lookup
()
.
findVirtual
(
String
.
class
,
"concat"
,
MethodType
.
methodType
(
String
.
class
,
String
.
class
));
MethodHandle
trueCon
=
MethodHandles
.
constant
(
boolean
.
class
,
true
);
MethodHandle
falseCon
=
MethodHandles
.
constant
(
boolean
.
class
,
false
);
VolatileCallSite
switcher
=
new
VolatileCallSite
(
trueCon
,
falseCon
);
// following steps may be repeated to re-use the same switcher:
MethodHandle
worker1
=
strcat
;
MethodHandle
worker2
=
MethodHandles
.
permuteArguments
(
strcat
,
strcat
.
type
(),
1
,
0
);
MethodHandle
worker
=
MethodHandles
.
guardWithTest
(
switcher
.
dynamicInvoker
(),
worker1
,
worker2
);
System
.
out
.
println
((
String
)
worker
.
invokeExact
(
"met"
,
"hod"
));
// method
switcher
.
invalidate
();
System
.
out
.
println
((
String
)
worker
.
invokeExact
(
"met"
,
"hod"
));
// hodmet
}}
}
static
MethodHandle
asList
;
@Test
public
void
testWithTypeHandler
()
throws
Throwable
{
{{
{}
/// JAVADOC
MethodHandle
makeEmptyList
=
MethodHandles
.
constant
(
List
.
class
,
Arrays
.
asList
());
MethodHandle
asList
=
lookup
()
.
findStatic
(
Arrays
.
class
,
"asList"
,
methodType
(
List
.
class
,
Object
[].
class
));
JavaDocExamplesTest
.
asList
=
asList
;
/*
static MethodHandle collectingTypeHandler(MethodHandle base, MethodType newType) {
return asList.asCollector(Object[].class, newType.parameterCount()).asType(newType);
}
*/
MethodHandle
collectingTypeHandler
=
lookup
()
.
findStatic
(
lookup
().
lookupClass
(),
"collectingTypeHandler"
,
methodType
(
MethodHandle
.
class
,
MethodHandle
.
class
,
MethodType
.
class
));
MethodHandle
makeAnyList
=
makeEmptyList
.
withTypeHandler
(
collectingTypeHandler
);
System
.
out
.
println
(
makeAnyList
.
invokeGeneric
());
System
.
out
.
println
(
makeAnyList
.
invokeGeneric
(
1
));
System
.
out
.
println
(
makeAnyList
.
invokeGeneric
(
"two"
,
"too"
));
}}
}
static
MethodHandle
collectingTypeHandler
(
MethodHandle
base
,
MethodType
newType
)
{
//System.out.println("Converting "+asList+" to "+newType);
MethodHandle
conv
=
asList
.
asCollector
(
Object
[].
class
,
newType
.
parameterCount
()).
asType
(
newType
);
//System.out.println(" =>"+conv);
return
conv
;
}
}
test/java/dyn/MethodHandlesTest.java
浏览文件 @
5150d263
...
...
@@ -62,7 +62,6 @@ public class MethodHandlesTest {
// lookups, without exercising the actual method handle.
static
boolean
DO_MORE_CALLS
=
true
;
@Test
public
void
testFirst
()
throws
Throwable
{
verbosity
+=
9
;
try
{
...
...
@@ -458,7 +457,7 @@ public class MethodHandlesTest {
Exception
noAccess
=
null
;
try
{
if
(
verbosity
>=
4
)
System
.
out
.
println
(
"lookup via "
+
lookup
+
" of "
+
defc
+
" "
+
name
+
type
);
target
=
lookup
.
findStatic
(
defc
,
name
,
type
);
target
=
lookup
.
in
(
defc
).
findStatic
(
defc
,
name
,
type
);
}
catch
(
NoAccessException
ex
)
{
noAccess
=
ex
;
}
...
...
@@ -469,16 +468,22 @@ public class MethodHandlesTest {
assertEquals
(
positive
?
"positive test"
:
"negative test erroneously passed"
,
positive
,
target
!=
null
);
if
(!
positive
)
return
;
// negative test failed as expected
assertEquals
(
type
,
target
.
type
());
assert
True
(
target
.
toString
().
contains
(
name
));
// rough check
assert
NameStringContains
(
target
,
name
);
if
(!
DO_MORE_CALLS
&&
lookup
!=
PRIVATE
)
return
;
Object
[]
args
=
randomArgs
(
params
);
printCalled
(
target
,
name
,
args
);
target
.
invoke
Vararg
s
(
args
);
target
.
invoke
WithArgument
s
(
args
);
assertCalled
(
name
,
args
);
if
(
verbosity
>=
1
)
System
.
out
.
print
(
':'
);
}
// rough check of name string
static
void
assertNameStringContains
(
Object
x
,
String
s
)
{
if
(
x
.
toString
().
contains
(
s
))
return
;
assertEquals
(
s
,
x
);
}
@Test
public
void
testFindVirtual
()
throws
Throwable
{
if
(
CAN_SKIP_WORKING
)
return
;
...
...
@@ -522,7 +527,7 @@ public class MethodHandlesTest {
Exception
noAccess
=
null
;
try
{
if
(
verbosity
>=
4
)
System
.
out
.
println
(
"lookup via "
+
lookup
+
" of "
+
defc
+
" "
+
name
+
type
);
target
=
lookup
.
findVirtual
(
defc
,
methodName
,
type
);
target
=
lookup
.
in
(
defc
).
findVirtual
(
defc
,
methodName
,
type
);
}
catch
(
NoAccessException
ex
)
{
noAccess
=
ex
;
}
...
...
@@ -535,12 +540,12 @@ public class MethodHandlesTest {
Class
<?>[]
paramsWithSelf
=
cat
(
array
(
Class
[].
class
,
(
Class
)
defc
),
params
);
MethodType
typeWithSelf
=
MethodType
.
methodType
(
ret
,
paramsWithSelf
);
assertEquals
(
typeWithSelf
,
target
.
type
());
assert
True
(
target
.
toString
().
contains
(
methodName
));
// rough check
assert
NameStringContains
(
target
,
methodName
);
if
(!
DO_MORE_CALLS
&&
lookup
!=
PRIVATE
)
return
;
Object
[]
argsWithSelf
=
randomArgs
(
paramsWithSelf
);
if
(
rcvc
!=
defc
)
argsWithSelf
[
0
]
=
randomArg
(
rcvc
);
printCalled
(
target
,
name
,
argsWithSelf
);
target
.
invoke
Vararg
s
(
argsWithSelf
);
target
.
invoke
WithArgument
s
(
argsWithSelf
);
assertCalled
(
name
,
argsWithSelf
);
if
(
verbosity
>=
1
)
System
.
out
.
print
(
':'
);
...
...
@@ -576,7 +581,8 @@ public class MethodHandlesTest {
Exception
noAccess
=
null
;
try
{
if
(
verbosity
>=
4
)
System
.
out
.
println
(
"lookup via "
+
lookup
+
" of "
+
defc
+
" "
+
name
+
type
);
target
=
lookup
.
findSpecial
(
defc
,
name
,
type
,
specialCaller
);
if
(
verbosity
>=
5
)
System
.
out
.
println
(
" lookup => "
+
lookup
.
in
(
specialCaller
));
target
=
lookup
.
in
(
specialCaller
).
findSpecial
(
defc
,
name
,
type
,
specialCaller
);
}
catch
(
NoAccessException
ex
)
{
noAccess
=
ex
;
}
...
...
@@ -591,11 +597,11 @@ public class MethodHandlesTest {
assertEquals
(
type
,
target
.
type
().
dropParameterTypes
(
0
,
1
));
Class
<?>[]
paramsWithSelf
=
cat
(
array
(
Class
[].
class
,
(
Class
)
specialCaller
),
params
);
MethodType
typeWithSelf
=
MethodType
.
methodType
(
ret
,
paramsWithSelf
);
assert
True
(
target
.
toString
().
contains
(
name
));
// rough check
assert
NameStringContains
(
target
,
name
);
if
(!
DO_MORE_CALLS
&&
lookup
!=
PRIVATE
&&
lookup
!=
EXAMPLE
)
return
;
Object
[]
args
=
randomArgs
(
paramsWithSelf
);
printCalled
(
target
,
name
,
args
);
target
.
invoke
Vararg
s
(
args
);
target
.
invoke
WithArgument
s
(
args
);
assertCalled
(
name
,
args
);
}
...
...
@@ -632,7 +638,7 @@ public class MethodHandlesTest {
Exception
noAccess
=
null
;
try
{
if
(
verbosity
>=
4
)
System
.
out
.
println
(
"lookup via "
+
lookup
+
" of "
+
defc
+
" "
+
name
+
type
);
target
=
lookup
.
bind
(
receiver
,
methodName
,
type
);
target
=
lookup
.
in
(
defc
).
bind
(
receiver
,
methodName
,
type
);
}
catch
(
NoAccessException
ex
)
{
noAccess
=
ex
;
}
...
...
@@ -645,7 +651,7 @@ public class MethodHandlesTest {
assertEquals
(
type
,
target
.
type
());
Object
[]
args
=
randomArgs
(
params
);
printCalled
(
target
,
name
,
args
);
target
.
invoke
Vararg
s
(
args
);
target
.
invoke
WithArgument
s
(
args
);
Object
[]
argsWithReceiver
=
cat
(
array
(
Object
[].
class
,
receiver
),
args
);
assertCalled
(
name
,
argsWithReceiver
);
if
(
verbosity
>=
1
)
...
...
@@ -705,9 +711,9 @@ public class MethodHandlesTest {
try
{
if
(
verbosity
>=
4
)
System
.
out
.
println
(
"lookup via "
+
lookup
+
" of "
+
defc
+
" "
+
name
+
type
);
if
(
isSpecial
)
target
=
lookup
.
unreflectSpecial
(
rmethod
,
specialCaller
);
target
=
lookup
.
in
(
specialCaller
).
unreflectSpecial
(
rmethod
,
specialCaller
);
else
target
=
lookup
.
unreflect
(
rmethod
);
target
=
lookup
.
in
(
defc
).
unreflect
(
rmethod
);
}
catch
(
NoAccessException
ex
)
{
noAccess
=
ex
;
}
...
...
@@ -737,7 +743,7 @@ public class MethodHandlesTest {
}
Object
[]
argsMaybeWithSelf
=
randomArgs
(
paramsMaybeWithSelf
);
printCalled
(
target
,
name
,
argsMaybeWithSelf
);
target
.
invoke
Vararg
s
(
argsMaybeWithSelf
);
target
.
invoke
WithArgument
s
(
argsMaybeWithSelf
);
assertCalled
(
name
,
argsMaybeWithSelf
);
if
(
verbosity
>=
1
)
System
.
out
.
print
(
':'
);
...
...
@@ -875,7 +881,7 @@ public class MethodHandlesTest {
if
(
isStatic
)
expType
=
expType
.
dropParameterTypes
(
0
,
1
);
MethodHandle
mh
=
lookup
.
unreflectGetter
(
f
);
assertSame
(
mh
.
type
(),
expType
);
assert
Equals
(
mh
.
toString
()
,
fname
);
assert
NameStringContains
(
mh
,
fname
);
HasFields
fields
=
new
HasFields
();
Object
sawValue
;
Class
<?>
rtype
=
type
;
...
...
@@ -947,7 +953,7 @@ public class MethodHandlesTest {
mh
=
lookup
.
findStaticSetter
(
fclass
,
fname
,
ftype
);
else
throw
new
InternalError
();
assertSame
(
mh
.
type
(),
expType
);
assert
Equals
(
mh
.
toString
()
,
fname
);
assert
NameStringContains
(
mh
,
fname
);
HasFields
fields
=
new
HasFields
();
Object
sawValue
;
Class
<?>
vtype
=
type
;
...
...
@@ -1102,6 +1108,18 @@ public class MethodHandlesTest {
}
}
static
MethodHandle
typeHandler2
(
MethodHandle
target
,
MethodType
newType
)
{
MethodType
oldType
=
target
.
type
();
int
oldArity
=
oldType
.
parameterCount
();
int
newArity
=
newType
.
parameterCount
();
if
(
newArity
<
oldArity
)
return
MethodHandles
.
insertArguments
(
target
,
oldArity
,
"OPTIONAL"
);
else
if
(
newArity
>
oldArity
)
return
MethodHandles
.
dropArguments
(
target
,
oldArity
-
1
,
newType
.
parameterType
(
oldArity
-
1
));
else
return
target
;
// attempt no further conversions
}
@Test
public
void
testConvertArguments
()
throws
Throwable
{
if
(
CAN_SKIP_WORKING
)
return
;
...
...
@@ -1115,10 +1133,29 @@ public class MethodHandlesTest {
}
void
testConvert
(
MethodHandle
id
,
Class
<?>
rtype
,
String
name
,
Class
<?>...
params
)
throws
Throwable
{
testConvert
(
true
,
id
,
rtype
,
name
,
params
);
testConvert
(
true
,
false
,
id
,
rtype
,
name
,
params
);
testConvert
(
true
,
true
,
id
,
rtype
,
name
,
params
);
}
void
testConvert
(
boolean
positive
,
MethodHandle
id
,
Class
<?>
rtype
,
String
name
,
Class
<?>...
params
)
throws
Throwable
{
@Test
public
void
testTypeHandler
()
throws
Throwable
{
MethodHandle
id
=
Callee
.
ofType
(
1
);
MethodHandle
th2
=
PRIVATE
.
findStatic
(
MethodHandlesTest
.
class
,
"typeHandler2"
,
MethodType
.
methodType
(
MethodHandle
.
class
,
MethodHandle
.
class
,
MethodType
.
class
));
MethodHandle
id2
=
id
.
withTypeHandler
(
th2
);
testConvert
(
true
,
false
,
id2
,
null
,
"id"
,
Object
.
class
);
testConvert
(
true
,
true
,
id2
,
null
,
"id"
,
Object
.
class
);
if
(
true
)
return
;
//FIXME
testConvert
(
true
,
false
,
id2
,
null
,
"id"
,
String
.
class
);
// FIXME: throws WMT
testConvert
(
false
,
true
,
id2
,
null
,
"id"
,
String
.
class
);
// FIXME: should not succeed
testConvert
(
false
,
false
,
id2
,
null
,
"id"
,
Object
.
class
,
String
.
class
);
//FIXME: array[1] line 1164
testConvert
(
true
,
true
,
id2
,
null
,
"id"
,
Object
.
class
,
String
.
class
);
testConvert
(
false
,
false
,
id2
,
null
,
"id"
);
testConvert
(
true
,
true
,
id2
,
null
,
"id"
);
}
void
testConvert
(
boolean
positive
,
boolean
useAsType
,
MethodHandle
id
,
Class
<?>
rtype
,
String
name
,
Class
<?>...
params
)
throws
Throwable
{
countTest
(
positive
);
MethodType
idType
=
id
.
type
();
if
(
rtype
==
null
)
rtype
=
idType
.
returnType
();
...
...
@@ -1135,7 +1172,7 @@ public class MethodHandlesTest {
if
(
src
!=
dst
)
convArgs
[
i
]
=
castToWrapper
(
convArgs
[
i
],
dst
);
}
Object
convResult
=
id
.
invoke
Vararg
s
(
convArgs
);
Object
convResult
=
id
.
invoke
WithArgument
s
(
convArgs
);
{
Class
<?>
dst
=
newType
.
returnType
();
Class
<?>
src
=
idType
.
returnType
();
...
...
@@ -1145,7 +1182,10 @@ public class MethodHandlesTest {
MethodHandle
target
=
null
;
RuntimeException
error
=
null
;
try
{
target
=
MethodHandles
.
convertArguments
(
id
,
newType
);
if
(
useAsType
)
target
=
MethodHandles
.
convertArguments
(
id
,
newType
);
else
target
=
id
.
asType
(
newType
);
}
catch
(
RuntimeException
ex
)
{
error
=
ex
;
}
...
...
@@ -1157,7 +1197,7 @@ public class MethodHandlesTest {
if
(!
positive
)
return
;
// negative test failed as expected
assertEquals
(
newType
,
target
.
type
());
printCalled
(
target
,
id
.
toString
(),
args
);
Object
result
=
target
.
invoke
Vararg
s
(
args
);
Object
result
=
target
.
invoke
WithArgument
s
(
args
);
assertCalled
(
name
,
convArgs
);
assertEquals
(
convResult
,
result
);
if
(
verbosity
>=
1
)
...
...
@@ -1279,7 +1319,7 @@ public class MethodHandlesTest {
MethodType
outType
=
MethodType
.
methodType
(
Object
.
class
,
permTypes
);
MethodHandle
target
=
MethodHandles
.
convertArguments
(
ValueConversions
.
varargsList
(
outargs
),
outType
);
MethodHandle
newTarget
=
MethodHandles
.
permuteArguments
(
target
,
inType
,
reorder
);
Object
result
=
newTarget
.
invoke
Vararg
s
(
args
);
Object
result
=
newTarget
.
invoke
WithArgument
s
(
args
);
Object
expected
=
Arrays
.
asList
(
permArgs
);
assertEquals
(
expected
,
result
);
}
...
...
@@ -1311,7 +1351,7 @@ public class MethodHandlesTest {
Object
[]
args
=
randomArgs
(
target2
.
type
().
parameterArray
());
// make sure the target does what we think it does:
if
(
pos
==
0
&&
nargs
<
5
)
{
Object
[]
check
=
(
Object
[])
target
.
invoke
Vararg
s
(
args
);
Object
[]
check
=
(
Object
[])
target
.
invoke
WithArgument
s
(
args
);
assertArrayEquals
(
args
,
check
);
switch
(
nargs
)
{
case
0
:
...
...
@@ -1342,7 +1382,7 @@ public class MethodHandlesTest {
}
else
{
Object
[]
args1
=
Arrays
.
copyOfRange
(
args
,
0
,
pos
+
1
);
args1
[
pos
]
=
Arrays
.
copyOfRange
(
args
,
pos
,
args
.
length
);
returnValue
=
(
Object
[])
result
.
invoke
Vararg
s
(
args1
);
returnValue
=
(
Object
[])
result
.
invoke
WithArgument
s
(
args1
);
}
assertArrayEquals
(
args
,
returnValue
);
}
...
...
@@ -1379,7 +1419,7 @@ public class MethodHandlesTest {
if
(
verbosity
>=
3
)
System
.
out
.
println
(
"collect from "
+
Arrays
.
asList
(
args
)+
" ["
+
pos
+
".."
+
nargs
+
"]"
);
MethodHandle
result
=
MethodHandles
.
collectArguments
(
target
,
newType
);
Object
[]
returnValue
=
(
Object
[])
result
.
invoke
Vararg
s
(
args
);
Object
[]
returnValue
=
(
Object
[])
result
.
invoke
WithArgument
s
(
args
);
// assertTrue(returnValue.length == pos+1 && returnValue[pos] instanceof Object[]);
// returnValue[pos] = Arrays.asList((Object[]) returnValue[pos]);
// collectedArgs[pos] = Arrays.asList((Object[]) collectedArgs[pos]);
...
...
@@ -1412,7 +1452,7 @@ public class MethodHandlesTest {
MethodHandle
target2
=
MethodHandles
.
insertArguments
(
target
,
pos
,
(
Object
[])
argsToInsert
.
toArray
());
argsToInsert
.
clear
();
// remove from argsToInsert
Object
res2
=
target2
.
invoke
Vararg
s
(
argsToPass
);
Object
res2
=
target2
.
invoke
WithArgument
s
(
argsToPass
);
Object
res2List
=
Arrays
.
asList
((
Object
[])
res2
);
if
(
verbosity
>=
3
)
System
.
out
.
println
(
"result: "
+
res2List
);
...
...
@@ -1440,14 +1480,12 @@ public class MethodHandlesTest {
Object
[]
argsToPass
=
randomArgs
(
nargs
,
Object
.
class
);
if
(
verbosity
>=
3
)
System
.
out
.
println
(
"filter "
+
target
+
" at "
+
pos
+
" with "
+
filter
);
MethodHandle
[]
filters
=
new
MethodHandle
[
pos
*
2
+
1
];
filters
[
pos
]
=
filter
;
MethodHandle
target2
=
MethodHandles
.
filterArguments
(
target
,
filters
);
MethodHandle
target2
=
MethodHandles
.
filterArguments
(
target
,
pos
,
filter
);
// Simulate expected effect of filter on arglist:
Object
[]
filteredArgs
=
argsToPass
.
clone
();
filteredArgs
[
pos
]
=
filter
.
invokeExact
(
filteredArgs
[
pos
]);
List
<
Object
>
expected
=
Arrays
.
asList
(
filteredArgs
);
Object
result
=
target2
.
invoke
Vararg
s
(
argsToPass
);
Object
result
=
target2
.
invoke
WithArgument
s
(
argsToPass
);
if
(
verbosity
>=
3
)
System
.
out
.
println
(
"result: "
+
result
);
if
(!
expected
.
equals
(
result
))
...
...
@@ -1482,9 +1520,9 @@ public class MethodHandlesTest {
List
<
Object
>
argsToFold
=
expected
.
subList
(
pos
,
pos
+
fold
);
if
(
verbosity
>=
3
)
System
.
out
.
println
(
"fold: "
+
argsToFold
+
" into "
+
target2
);
Object
foldedArgs
=
combine
.
invoke
Vararg
s
(
argsToFold
);
Object
foldedArgs
=
combine
.
invoke
WithArgument
s
(
argsToFold
);
argsToFold
.
add
(
0
,
foldedArgs
);
Object
result
=
target2
.
invoke
Vararg
s
(
argsToPass
);
Object
result
=
target2
.
invoke
WithArgument
s
(
argsToPass
);
if
(
verbosity
>=
3
)
System
.
out
.
println
(
"result: "
+
result
);
if
(!
expected
.
equals
(
result
))
...
...
@@ -1516,7 +1554,7 @@ public class MethodHandlesTest {
for
(
int
i
=
drop
;
i
>
0
;
i
--)
{
argsToDrop
.
add
(
pos
,
"blort#"
+
i
);
}
Object
res2
=
target2
.
invoke
Vararg
s
(
argsToDrop
);
Object
res2
=
target2
.
invoke
WithArgument
s
(
argsToDrop
);
Object
res2List
=
Arrays
.
asList
((
Object
[])
res2
);
//if (!resList.equals(res2List))
// System.out.println("*** fail at n/p/d = "+nargs+"/"+pos+"/"+drop+": "+argsToDrop+" => "+res2List);
...
...
@@ -1572,7 +1610,7 @@ public class MethodHandlesTest {
countTest
();
calledLog
.
clear
();
inv
=
MethodHandles
.
exactInvoker
(
type
);
result
=
inv
.
invoke
Vararg
s
(
targetPlusArgs
);
result
=
inv
.
invoke
WithArgument
s
(
targetPlusArgs
);
if
(
testRetCode
)
assertEquals
(
code
,
result
);
assertCalled
(
"invokee"
,
args
);
// generic invoker
...
...
@@ -1598,7 +1636,7 @@ public class MethodHandlesTest {
assertCalled
(
"invokee"
,
args
);
}
calledLog
.
clear
();
result
=
inv
.
invoke
Vararg
s
(
targetPlusArgs
);
result
=
inv
.
invoke
WithArgument
s
(
targetPlusArgs
);
if
(
testRetCode
)
assertEquals
(
code
,
result
);
assertCalled
(
"invokee"
,
args
);
// varargs invoker #0
...
...
@@ -1640,17 +1678,29 @@ public class MethodHandlesTest {
List
<
Object
>
tailList
=
targetPlusVarArgs
.
subList
(
1
+
k
,
1
+
nargs
);
Object
[]
tail
=
tailList
.
toArray
();
tailList
.
clear
();
tailList
.
add
(
tail
);
result
=
inv
.
invoke
Vararg
s
(
targetPlusVarArgs
);
result
=
inv
.
invoke
WithArgument
s
(
targetPlusVarArgs
);
if
(
testRetCode
)
assertEquals
(
code
,
result
);
assertCalled
(
"invokee"
,
args
);
}
// dynamic invoker
countTest
();
CallSite
site
=
new
CallSite
(
MethodHandlesTest
.
class
,
"foo"
,
type
);
CallSite
site
=
new
CallSite
(
type
);
inv
=
MethodHandles
.
dynamicInvoker
(
site
);
// see if we get the result of the original target:
try
{
result
=
inv
.
invokeWithArguments
(
args
);
assertTrue
(
"should not reach here"
,
false
);
}
catch
(
IllegalStateException
ex
)
{
String
msg
=
ex
.
getMessage
();
assertTrue
(
msg
,
msg
.
contains
(
"site"
));
}
// set new target after invoker is created, to make sure we track target
site
.
setTarget
(
target
);
calledLog
.
clear
();
result
=
inv
.
invoke
Vararg
s
(
args
);
result
=
inv
.
invoke
WithArgument
s
(
args
);
if
(
testRetCode
)
assertEquals
(
code
,
result
);
assertCalled
(
"invokee"
,
args
);
}
...
...
@@ -1734,7 +1784,7 @@ public class MethodHandlesTest {
String
willCall
=
(
equals
?
"targetIfEquals"
:
"fallbackIfNotEquals"
);
if
(
verbosity
>=
3
)
System
.
out
.
println
(
logEntry
(
willCall
,
argList
));
Object
result
=
mh
.
invoke
Vararg
s
(
argList
);
Object
result
=
mh
.
invoke
WithArgument
s
(
argList
);
assertCalled
(
willCall
,
argList
);
}
}
...
...
@@ -1776,7 +1826,7 @@ public class MethodHandlesTest {
//System.out.println("catching with "+target+" : "+throwOrReturn);
Object
[]
args
=
randomArgs
(
nargs
,
Object
.
class
);
args
[
1
]
=
(
throwIt
?
thrown
:
null
);
Object
returned
=
target
.
invoke
Vararg
s
(
args
);
Object
returned
=
target
.
invoke
WithArgument
s
(
args
);
//System.out.println("return from "+target+" : "+returned);
if
(!
throwIt
)
{
assertSame
(
args
[
0
],
returned
);
...
...
@@ -1828,13 +1878,10 @@ public class MethodHandlesTest {
testCastFailure
(
"unbox/return"
,
11000
);
}
static
class
Surprise
implements
MethodHandleProvider
{
static
class
Surprise
{
public
MethodHandle
asMethodHandle
()
{
return
VALUE
.
bindTo
(
this
);
}
public
MethodHandle
asMethodHandle
(
MethodType
type
)
{
return
asMethodHandle
().
asType
(
type
);
}
Object
value
(
Object
x
)
{
trace
(
"value"
,
x
);
if
(
boo
!=
null
)
return
boo
;
...
...
@@ -1896,8 +1943,8 @@ public class MethodHandlesTest {
}
if
(
callee
!=
null
)
{
callee
=
MethodHandles
.
convertArguments
(
callee
,
MethodType
.
genericMethodType
(
1
));
surprise
=
MethodHandles
.
filterArguments
(
callee
,
surprise
);
identity
=
MethodHandles
.
filterArguments
(
callee
,
identity
);
surprise
=
MethodHandles
.
filterArguments
(
callee
,
0
,
surprise
);
identity
=
MethodHandles
.
filterArguments
(
callee
,
0
,
identity
);
}
}
assertNotSame
(
mode
,
surprise
,
surprise0
);
...
...
@@ -1949,7 +1996,7 @@ public class MethodHandlesTest {
assertEquals
(
mt
,
mh
.
type
());
assertEquals
(
Example
.
class
,
mh
.
type
().
returnType
());
args
=
randomArgs
(
mh
.
type
().
parameterArray
());
mh
.
invoke
Vararg
s
(
args
);
mh
.
invoke
WithArgument
s
(
args
);
assertCalled
(
name
,
args
);
// Try a virtual method.
...
...
@@ -1959,7 +2006,7 @@ public class MethodHandlesTest {
assertEquals
(
mt
,
mh
.
type
().
dropParameterTypes
(
0
,
1
));
assertTrue
(
mh
.
type
().
parameterList
().
contains
(
Example
.
class
));
args
=
randomArgs
(
mh
.
type
().
parameterArray
());
mh
.
invoke
Vararg
s
(
args
);
mh
.
invoke
WithArgument
s
(
args
);
assertCalled
(
name
,
args
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录