Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
33ee9ccf
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看板
提交
33ee9ccf
编写于
3月 24, 2011
作者:
J
jrose
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
a43c1c0e
af1c19af
变更
61
隐藏空白更改
内联
并排
Showing
61 changed file
with
1810 addition
and
1653 deletion
+1810
-1653
make/common/Release.gmk
make/common/Release.gmk
+0
-3
make/docs/CORE_PKGS.gmk
make/docs/CORE_PKGS.gmk
+3
-3
make/java/Makefile
make/java/Makefile
+2
-2
make/java/invoke/Makefile
make/java/invoke/Makefile
+6
-6
src/share/classes/java/dyn/Linkage.java
src/share/classes/java/dyn/Linkage.java
+0
-125
src/share/classes/java/dyn/MethodTypeForm.java
src/share/classes/java/dyn/MethodTypeForm.java
+0
-39
src/share/classes/java/lang/BootstrapMethodError.java
src/share/classes/java/lang/BootstrapMethodError.java
+15
-17
src/share/classes/java/lang/ClassValue.java
src/share/classes/java/lang/ClassValue.java
+4
-11
src/share/classes/java/lang/invoke/AdapterMethodHandle.java
src/share/classes/java/lang/invoke/AdapterMethodHandle.java
+51
-82
src/share/classes/java/lang/invoke/BoundMethodHandle.java
src/share/classes/java/lang/invoke/BoundMethodHandle.java
+19
-35
src/share/classes/java/lang/invoke/CallSite.java
src/share/classes/java/lang/invoke/CallSite.java
+72
-15
src/share/classes/java/lang/invoke/ConstantCallSite.java
src/share/classes/java/lang/invoke/ConstantCallSite.java
+1
-1
src/share/classes/java/lang/invoke/DirectMethodHandle.java
src/share/classes/java/lang/invoke/DirectMethodHandle.java
+4
-5
src/share/classes/java/lang/invoke/FilterGeneric.java
src/share/classes/java/lang/invoke/FilterGeneric.java
+9
-9
src/share/classes/java/lang/invoke/FilterOneArgument.java
src/share/classes/java/lang/invoke/FilterOneArgument.java
+8
-8
src/share/classes/java/lang/invoke/FromGeneric.java
src/share/classes/java/lang/invoke/FromGeneric.java
+16
-15
src/share/classes/java/lang/invoke/InvokeDynamic.java
src/share/classes/java/lang/invoke/InvokeDynamic.java
+2
-2
src/share/classes/java/lang/invoke/InvokeGeneric.java
src/share/classes/java/lang/invoke/InvokeGeneric.java
+12
-22
src/share/classes/java/lang/invoke/Invokers.java
src/share/classes/java/lang/invoke/Invokers.java
+14
-14
src/share/classes/java/lang/invoke/MemberName.java
src/share/classes/java/lang/invoke/MemberName.java
+23
-44
src/share/classes/java/lang/invoke/MethodHandle.java
src/share/classes/java/lang/invoke/MethodHandle.java
+105
-86
src/share/classes/java/lang/invoke/MethodHandleImpl.java
src/share/classes/java/lang/invoke/MethodHandleImpl.java
+101
-279
src/share/classes/java/lang/invoke/MethodHandleNatives.java
src/share/classes/java/lang/invoke/MethodHandleNatives.java
+42
-33
src/share/classes/java/lang/invoke/MethodHandleStatics.java
src/share/classes/java/lang/invoke/MethodHandleStatics.java
+92
-0
src/share/classes/java/lang/invoke/MethodHandles.java
src/share/classes/java/lang/invoke/MethodHandles.java
+187
-169
src/share/classes/java/lang/invoke/MethodType.java
src/share/classes/java/lang/invoke/MethodType.java
+31
-55
src/share/classes/java/lang/invoke/MethodTypeForm.java
src/share/classes/java/lang/invoke/MethodTypeForm.java
+30
-70
src/share/classes/java/lang/invoke/MutableCallSite.java
src/share/classes/java/lang/invoke/MutableCallSite.java
+1
-3
src/share/classes/java/lang/invoke/SpreadGeneric.java
src/share/classes/java/lang/invoke/SpreadGeneric.java
+12
-12
src/share/classes/java/lang/invoke/SwitchPoint.java
src/share/classes/java/lang/invoke/SwitchPoint.java
+5
-1
src/share/classes/java/lang/invoke/ToGeneric.java
src/share/classes/java/lang/invoke/ToGeneric.java
+49
-29
src/share/classes/java/lang/invoke/VolatileCallSite.java
src/share/classes/java/lang/invoke/VolatileCallSite.java
+1
-3
src/share/classes/java/lang/invoke/WrongMethodTypeException.java
...re/classes/java/lang/invoke/WrongMethodTypeException.java
+2
-2
src/share/classes/java/lang/invoke/package-info.java
src/share/classes/java/lang/invoke/package-info.java
+38
-50
src/share/classes/sun/dyn/Access.java
src/share/classes/sun/dyn/Access.java
+0
-109
src/share/classes/sun/dyn/CallSiteImpl.java
src/share/classes/sun/dyn/CallSiteImpl.java
+0
-141
src/share/classes/sun/invoke/WrapperInstance.java
src/share/classes/sun/invoke/WrapperInstance.java
+4
-4
src/share/classes/sun/invoke/anon/AnonymousClassLoader.java
src/share/classes/sun/invoke/anon/AnonymousClassLoader.java
+2
-2
src/share/classes/sun/invoke/anon/ConstantPoolParser.java
src/share/classes/sun/invoke/anon/ConstantPoolParser.java
+3
-3
src/share/classes/sun/invoke/anon/ConstantPoolPatch.java
src/share/classes/sun/invoke/anon/ConstantPoolPatch.java
+3
-3
src/share/classes/sun/invoke/anon/ConstantPoolVisitor.java
src/share/classes/sun/invoke/anon/ConstantPoolVisitor.java
+2
-2
src/share/classes/sun/invoke/anon/InvalidConstantPoolFormatException.java
...s/sun/invoke/anon/InvalidConstantPoolFormatException.java
+2
-2
src/share/classes/sun/invoke/empty/Empty.java
src/share/classes/sun/invoke/empty/Empty.java
+3
-3
src/share/classes/sun/invoke/package-info.java
src/share/classes/sun/invoke/package-info.java
+2
-2
src/share/classes/sun/invoke/util/BytecodeDescriptor.java
src/share/classes/sun/invoke/util/BytecodeDescriptor.java
+3
-3
src/share/classes/sun/invoke/util/BytecodeName.java
src/share/classes/sun/invoke/util/BytecodeName.java
+2
-2
src/share/classes/sun/invoke/util/ValueConversions.java
src/share/classes/sun/invoke/util/ValueConversions.java
+44
-34
src/share/classes/sun/invoke/util/VerifyAccess.java
src/share/classes/sun/invoke/util/VerifyAccess.java
+2
-5
src/share/classes/sun/invoke/util/VerifyType.java
src/share/classes/sun/invoke/util/VerifyType.java
+4
-4
src/share/classes/sun/invoke/util/Wrapper.java
src/share/classes/sun/invoke/util/Wrapper.java
+3
-3
src/share/classes/sun/invoke/util/package-info.java
src/share/classes/sun/invoke/util/package-info.java
+3
-3
src/share/native/common/check_code.c
src/share/native/common/check_code.c
+2
-2
test/java/lang/invoke/6987555/Test6987555.java
test/java/lang/invoke/6987555/Test6987555.java
+177
-0
test/java/lang/invoke/6991596/Test6991596.java
test/java/lang/invoke/6991596/Test6991596.java
+465
-0
test/java/lang/invoke/ClassValueTest.java
test/java/lang/invoke/ClassValueTest.java
+6
-6
test/java/lang/invoke/InvokeDynamicPrintArgs.java
test/java/lang/invoke/InvokeDynamicPrintArgs.java
+12
-12
test/java/lang/invoke/InvokeGenericTest.java
test/java/lang/invoke/InvokeGenericTest.java
+9
-9
test/java/lang/invoke/JavaDocExamplesTest.java
test/java/lang/invoke/JavaDocExamplesTest.java
+20
-10
test/java/lang/invoke/MethodHandlesTest.java
test/java/lang/invoke/MethodHandlesTest.java
+8
-8
test/java/lang/invoke/MethodTypeTest.java
test/java/lang/invoke/MethodTypeTest.java
+48
-23
test/java/lang/invoke/indify/Indify.java
test/java/lang/invoke/indify/Indify.java
+24
-8
未找到文件。
make/common/Release.gmk
浏览文件 @
33ee9ccf
...
@@ -54,9 +54,6 @@ EXCLUDE_PROPWARN_PKGS = com.sun.java.swing.plaf.windows \
...
@@ -54,9 +54,6 @@ EXCLUDE_PROPWARN_PKGS = com.sun.java.swing.plaf.windows \
com.sun.java.swing.plaf.motif \
com.sun.java.swing.plaf.motif \
com.sun.java.swing.plaf.gtk
com.sun.java.swing.plaf.gtk
# This is a stopgap until 6839872 is fixed.
EXCLUDE_PROPWARN_PKGS += sun.dyn
#
#
# Include the exported private packages in ct.sym.
# Include the exported private packages in ct.sym.
# This is an interim solution until the ct.sym is replaced
# This is an interim solution until the ct.sym is replaced
...
...
make/docs/CORE_PKGS.gmk
浏览文件 @
33ee9ccf
#
#
# Copyright (c) 2001, 201
0
, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2001, 201
1
, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
#
# This code is free software; you can redistribute it and/or modify it
# This code is free software; you can redistribute it and/or modify it
...
@@ -55,7 +55,7 @@ EXCLUDE_PKGS = \
...
@@ -55,7 +55,7 @@ EXCLUDE_PKGS = \
# This is a list of regular expressions. So foo.* matches "foo" and "foo.bar".
# This is a list of regular expressions. So foo.* matches "foo" and "foo.bar".
#
#
ACTIVE_JSR_PKGS= \
ACTIVE_JSR_PKGS= \
java.
dyn
\
java.
lang.invoke
\
java.sql \
java.sql \
javax.activation \
javax.activation \
javax.annotation.* \
javax.annotation.* \
...
@@ -97,11 +97,11 @@ CORE_PKGS = \
...
@@ -97,11 +97,11 @@ CORE_PKGS = \
java.awt.print \
java.awt.print \
java.beans \
java.beans \
java.beans.beancontext \
java.beans.beancontext \
java.dyn \
java.io \
java.io \
java.lang \
java.lang \
java.lang.annotation \
java.lang.annotation \
java.lang.instrument \
java.lang.instrument \
java.lang.invoke \
java.lang.management \
java.lang.management \
java.lang.ref \
java.lang.ref \
java.lang.reflect \
java.lang.reflect \
...
...
make/java/Makefile
浏览文件 @
33ee9ccf
#
#
# Copyright (c) 1995, 201
0
, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 1995, 201
1
, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
#
# This code is free software; you can redistribute it and/or modify it
# This code is free software; you can redistribute it and/or modify it
...
@@ -44,7 +44,7 @@ SUBDIRS += security math util text net nio jar
...
@@ -44,7 +44,7 @@ SUBDIRS += security math util text net nio jar
SUBDIRS_desktop
=
awt applet beans
SUBDIRS_desktop
=
awt applet beans
SUBDIRS_management
=
management
SUBDIRS_management
=
management
SUBDIRS_misc
=
npt java_crw_demo java_hprof_demo
\
SUBDIRS_misc
=
npt java_crw_demo java_hprof_demo
\
logging instrument
dyn
sql rmi
logging instrument
invoke
sql rmi
ifeq
($(PLATFORM), solaris)
ifeq
($(PLATFORM), solaris)
...
...
make/java/
dyn
/Makefile
→
make/java/
invoke
/Makefile
浏览文件 @
33ee9ccf
#
#
# Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
#
# This code is free software; you can redistribute it and/or modify it
# This code is free software; you can redistribute it and/or modify it
...
@@ -25,18 +25,18 @@
...
@@ -25,18 +25,18 @@
BUILDDIR
=
../..
BUILDDIR
=
../..
PACKAGE
=
java.
dyn
PACKAGE
=
java.
lang.invoke
PRODUCT
=
java
PRODUCT
=
java
include
$(BUILDDIR)/common/Defs.gmk
include
$(BUILDDIR)/common/Defs.gmk
AUTO_FILES_JAVA_DIRS
=
java/dyn sun/dyn
AUTO_FILES_JAVA_DIRS
=
java/lang/invoke sun/invoke
FILES_java
=
\
java/lang/ClassValue.java
\
java/lang/BootstrapMethodError.java
# The sources built here use new language syntax to generate
# The sources built here use new language syntax to generate
# method handle calls. Let's be sure we are using that format.
# method handle calls. Let's be sure we are using that format.
LANGUAGE_VERSION
=
-source
7
LANGUAGE_VERSION
=
-source
7
CLASS_VERSION
=
-target
7
CLASS_VERSION
=
-target
7
# Tell the compiler not to accept transitional forms.
OTHER_JAVACFLAGS
=
-XDallowTransitionalJSR292
=
no
include
$(BUILDDIR)/common/Classes.gmk
include
$(BUILDDIR)/common/Classes.gmk
src/share/classes/java/dyn/Linkage.java
已删除
100644 → 0
浏览文件 @
a43c1c0e
/*
* 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.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
.
MemberName
.
newIllegalArgumentException
;
/**
* <em>CLASS WILL BE REMOVED FOR PFD:</em>
* Static routines for controlling invokedynamic behavior.
* Replaced by non-static APIs.
* @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
();
private
Linkage
()
{}
// do not instantiate
/**
* <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.
* @deprecated Use @{@link BootstrapMethod} annotations instead.
*/
public
static
void
registerBootstrapMethod
(
Class
callerClass
,
MethodHandle
bootstrapMethod
)
{
Class
callc
=
Reflection
.
getCallerClass
(
2
);
if
(
callc
!=
null
&&
!
VerifyAccess
.
isSamePackage
(
callerClass
,
callc
))
throw
new
IllegalArgumentException
(
"cannot set bootstrap method on "
+
callerClass
);
MethodHandleImpl
.
registerBootstrap
(
IMPL_TOKEN
,
callerClass
,
bootstrapMethod
);
}
/**
* <em>METHOD WILL BE REMOVED FOR PFD:</em>
* Simplified version of {@code registerBootstrapMethod} for self-registration,
* to be called from a static initializer.
* @deprecated Use @{@link BootstrapMethod} annotations instead.
*/
public
static
void
registerBootstrapMethod
(
Class
<?>
runtime
,
String
name
)
{
Class
callerClass
=
Reflection
.
getCallerClass
(
2
);
registerBootstrapMethodLookup
(
callerClass
,
runtime
,
name
);
}
/**
* <em>METHOD WILL BE REMOVED FOR PFD:</em>
* Simplified version of {@code registerBootstrapMethod} for self-registration,
* @deprecated Use @{@link BootstrapMethod} annotations instead.
*/
public
static
void
registerBootstrapMethod
(
String
name
)
{
Class
callerClass
=
Reflection
.
getCallerClass
(
2
);
registerBootstrapMethodLookup
(
callerClass
,
callerClass
,
name
);
}
private
static
void
registerBootstrapMethodLookup
(
Class
<?>
callerClass
,
Class
<?>
runtime
,
String
name
)
{
Lookup
lookup
=
new
Lookup
(
IMPL_TOKEN
,
callerClass
);
MethodHandle
bootstrapMethod
;
try
{
bootstrapMethod
=
lookup
.
findStatic
(
runtime
,
name
,
BOOTSTRAP_METHOD_TYPE
);
}
catch
(
ReflectiveOperationException
ex
)
{
throw
new
IllegalArgumentException
(
"no such bootstrap method in "
+
runtime
+
": "
+
name
,
ex
);
}
MethodHandleImpl
.
registerBootstrap
(
IMPL_TOKEN
,
callerClass
,
bootstrapMethod
);
}
private
static
final
MethodType
BOOTSTRAP_METHOD_TYPE
=
MethodType
.
methodType
(
CallSite
.
class
,
Class
.
class
,
String
.
class
,
MethodType
.
class
);
/**
* <em>METHOD WILL BE REMOVED FOR PFD:</em>
* Invalidate all <code>invokedynamic</code> call sites everywhere.
* @deprecated Use {@linkplain MutableCallSite#setTarget call site target setting},
* {@link MutableCallSite#syncAll call site update pushing},
* and {@link SwitchPoint#guardWithTest target switching} instead.
*/
public
static
Object
invalidateAll
()
{
throw
new
UnsupportedOperationException
();
}
/**
* <em>METHOD WILL BE REMOVED FOR PFD:</em>
* Invalidate all {@code invokedynamic} call sites in the bytecodes
* of any methods of the given class.
* @deprecated Use {@linkplain MutableCallSite#setTarget call site target setting},
* {@link MutableCallSite#syncAll call site update pushing},
* and {@link SwitchPoint#guardWithTest target switching} instead.
*/
public
static
Object
invalidateCallerClass
(
Class
<?>
callerClass
)
{
throw
new
UnsupportedOperationException
();
}
}
src/share/classes/java/dyn/MethodTypeForm.java
已删除
100644 → 0
浏览文件 @
a43c1c0e
/*
* 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
;
/**
* TO DO: Temporary shim; remove after refactoring effects are complete in JVM.
* @author John Rose
*/
import
sun.dyn.MethodTypeImpl
;
class
MethodTypeForm
extends
MethodTypeImpl
{
MethodTypeForm
(
MethodType
erasedType
)
{
super
(
erasedType
);
}
}
src/share/classes/java/
dyn/InvokeDynamicBootstrap
Error.java
→
src/share/classes/java/
lang/BootstrapMethod
Error.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,58 +23,56 @@
...
@@ -23,58 +23,56 @@
* questions.
* questions.
*/
*/
package
java.
dyn
;
package
java.
lang
;
/**
/**
* Thrown to indicate that an {@code invokedynamic} instruction has
* Thrown to indicate that an {@code invokedynamic} instruction has
* failed to find its
* failed to find its bootstrap method,
* {@linkplain BootstrapMethod bootstrap method},
* or the bootstrap method has failed to provide a
* or the bootstrap method has
* {@linkplain java.lang.invoke.CallSite call site} with a {@linkplain java.lang.invoke.CallSite#getTarget target}
* failed to provide a
* of the correct {@linkplain java.lang.invoke.MethodHandle#type method type}.
* {@linkplain CallSite call site} with a {@linkplain CallSite#getTarget target}
* of the correct {@linkplain MethodHandle#type method type}.
*
*
* @author John Rose, JSR 292 EG
* @author John Rose, JSR 292 EG
* @since 1.7
* @since 1.7
*/
*/
public
class
InvokeDynamicBootstrap
Error
extends
LinkageError
{
public
class
BootstrapMethod
Error
extends
LinkageError
{
private
static
final
long
serialVersionUID
=
292L
;
private
static
final
long
serialVersionUID
=
292L
;
/**
/**
* Constructs an {@code
InvokeDynamicBootstrap
Error} with no detail message.
* Constructs an {@code
BootstrapMethod
Error} with no detail message.
*/
*/
public
InvokeDynamicBootstrap
Error
()
{
public
BootstrapMethod
Error
()
{
super
();
super
();
}
}
/**
/**
* Constructs an {@code
InvokeDynamicBootstrap
Error} with the specified
* Constructs an {@code
BootstrapMethod
Error} with the specified
* detail message.
* detail message.
*
*
* @param s the detail message.
* @param s the detail message.
*/
*/
public
InvokeDynamicBootstrap
Error
(
String
s
)
{
public
BootstrapMethod
Error
(
String
s
)
{
super
(
s
);
super
(
s
);
}
}
/**
/**
* Constructs a {@code
InvokeDynamicBootstrap
Error} with the specified
* Constructs a {@code
BootstrapMethod
Error} with the specified
* detail message and cause.
* detail message and cause.
*
*
* @param s the detail message.
* @param s the detail message.
* @param cause the cause, may be {@code null}.
* @param cause the cause, may be {@code null}.
*/
*/
public
InvokeDynamicBootstrap
Error
(
String
s
,
Throwable
cause
)
{
public
BootstrapMethod
Error
(
String
s
,
Throwable
cause
)
{
super
(
s
,
cause
);
super
(
s
,
cause
);
}
}
/**
/**
* Constructs a {@code
InvokeDynamicBootstrap
Error} with the specified
* Constructs a {@code
BootstrapMethod
Error} with the specified
* cause.
* cause.
*
*
* @param cause the cause, may be {@code null}.
* @param cause the cause, may be {@code null}.
*/
*/
public
InvokeDynamicBootstrap
Error
(
Throwable
cause
)
{
public
BootstrapMethod
Error
(
Throwable
cause
)
{
// cf. Throwable(Throwable cause) constructor.
// cf. Throwable(Throwable cause) constructor.
super
(
cause
==
null
?
null
:
cause
.
toString
());
super
(
cause
==
null
?
null
:
cause
.
toString
());
initCause
(
cause
);
initCause
(
cause
);
...
...
src/share/classes/java/
dyn
/ClassValue.java
→
src/share/classes/java/
lang
/ClassValue.java
浏览文件 @
33ee9ccf
...
@@ -23,12 +23,10 @@
...
@@ -23,12 +23,10 @@
* questions.
* questions.
*/
*/
package
java.
dyn
;
package
java.
lang
;
import
java.util.WeakHashMap
;
import
java.util.WeakHashMap
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.concurrent.atomic.AtomicReference
;
import
java.lang.reflect.UndeclaredThrowableException
;
/**
/**
* Lazily associate a computed value with (potentially) every type.
* Lazily associate a computed value with (potentially) every type.
...
@@ -37,10 +35,11 @@ import java.lang.reflect.UndeclaredThrowableException;
...
@@ -37,10 +35,11 @@ import java.lang.reflect.UndeclaredThrowableException;
* it can use a {@code ClassValue} to cache information needed to
* it can use a {@code ClassValue} to cache information needed to
* perform the message send quickly, for each class encountered.
* perform the message send quickly, for each class encountered.
* @author John Rose, JSR 292 EG
* @author John Rose, JSR 292 EG
* @since 1.7
*/
*/
public
abstract
class
ClassValue
<
T
>
{
public
abstract
class
ClassValue
<
T
>
{
/**
/**
* Compute the given class's derived value for this {@code ClassValue}.
* Compute
s
the given class's derived value for this {@code ClassValue}.
* <p>
* <p>
* This method will be invoked within the first thread that accesses
* This method will be invoked within the first thread that accesses
* the value with the {@link #get get} method.
* the value with the {@link #get get} method.
...
@@ -159,13 +158,7 @@ public abstract class ClassValue<T> {
...
@@ -159,13 +158,7 @@ public abstract class ClassValue<T> {
}
}
/// Implementation...
/// Implementation...
// FIXME: Use a data structure here similar that of ThreadLocal (7030453).
// The hash code for this type is based on the identity of the object,
// and is well-dispersed for power-of-two tables.
/** @deprecated This override, which is implementation-specific, will be removed for PFD. */
public
final
int
hashCode
()
{
return
hashCode
;
}
private
final
int
hashCode
=
HASH_CODES
.
getAndAdd
(
0x61c88647
);
private
static
final
AtomicInteger
HASH_CODES
=
new
AtomicInteger
();
private
static
final
AtomicInteger
STORE_BARRIER
=
new
AtomicInteger
();
private
static
final
AtomicInteger
STORE_BARRIER
=
new
AtomicInteger
();
...
...
src/share/classes/
sun/dyn
/AdapterMethodHandle.java
→
src/share/classes/
java/lang/invoke
/AdapterMethodHandle.java
浏览文件 @
33ee9ccf
...
@@ -23,20 +23,19 @@
...
@@ -23,20 +23,19 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
sun.dyn.util.VerifyType
;
import
sun.invoke.util.VerifyType
;
import
sun.dyn.util.Wrapper
;
import
sun.invoke.util.Wrapper
;
import
java.dyn.*
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
static
sun
.
dyn
.
MethodHandleNatives
.
Constants
.*;
import
static
java
.
lang
.
invoke
.
MethodHandleNatives
.
Constants
.*;
import
static
sun
.
dyn
.
MemberName
.
newIllegalArgumentException
;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*
;
/**
/**
* This method handle performs simple conversion or checking of a single argument.
* This method handle performs simple conversion or checking of a single argument.
* @author jrose
* @author jrose
*/
*/
public
class
AdapterMethodHandle
extends
BoundMethodHandle
{
class
AdapterMethodHandle
extends
BoundMethodHandle
{
//MethodHandle vmtarget; // next AMH or BMH in chain or final DMH
//MethodHandle vmtarget; // next AMH or BMH in chain or final DMH
//Object argument; // parameter to the conversion if needed
//Object argument; // parameter to the conversion if needed
...
@@ -48,25 +47,21 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -48,25 +47,21 @@ public class AdapterMethodHandle extends BoundMethodHandle {
long
conv
,
Object
convArg
)
{
long
conv
,
Object
convArg
)
{
super
(
newType
,
convArg
,
newType
.
parameterSlotDepth
(
1
+
convArgPos
(
conv
)));
super
(
newType
,
convArg
,
newType
.
parameterSlotDepth
(
1
+
convArgPos
(
conv
)));
this
.
conversion
=
convCode
(
conv
);
this
.
conversion
=
convCode
(
conv
);
if
(
MethodHandleNatives
.
JVM_SUPPORT
)
{
// JVM might update VM-specific bits of conversion (ignore)
// JVM might update VM-specific bits of conversion (ignore)
MethodHandleNatives
.
init
(
this
,
target
,
convArgPos
(
conv
));
MethodHandleNatives
.
init
(
this
,
target
,
convArgPos
(
conv
));
}
}
}
private
AdapterMethodHandle
(
MethodHandle
target
,
MethodType
newType
,
private
AdapterMethodHandle
(
MethodHandle
target
,
MethodType
newType
,
long
conv
)
{
long
conv
)
{
this
(
target
,
newType
,
conv
,
null
);
this
(
target
,
newType
,
conv
,
null
);
}
}
private
static
final
Access
IMPL_TOKEN
=
Access
.
getToken
();
// TO DO: When adapting another MH with a null conversion, clone
// TO DO: When adapting another MH with a null conversion, clone
// the target and change its type, instead of adding another layer.
// the target and change its type, instead of adding another layer.
/** Can a JVM-level adapter directly implement the proposed
/** Can a JVM-level adapter directly implement the proposed
* argument conversions, as if by MethodHandles.convertArguments?
* argument conversions, as if by MethodHandles.convertArguments?
*/
*/
public
static
boolean
canPairwiseConvert
(
MethodType
newType
,
MethodType
oldType
)
{
static
boolean
canPairwiseConvert
(
MethodType
newType
,
MethodType
oldType
)
{
// same number of args, of course
// same number of args, of course
int
len
=
newType
.
parameterCount
();
int
len
=
newType
.
parameterCount
();
if
(
len
!=
oldType
.
parameterCount
())
if
(
len
!=
oldType
.
parameterCount
())
...
@@ -92,7 +87,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -92,7 +87,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Can a JVM-level adapter directly implement the proposed
/** Can a JVM-level adapter directly implement the proposed
* argument conversion, as if by MethodHandles.convertArguments?
* argument conversion, as if by MethodHandles.convertArguments?
*/
*/
public
static
boolean
canConvertArgument
(
Class
<?>
src
,
Class
<?>
dst
)
{
static
boolean
canConvertArgument
(
Class
<?>
src
,
Class
<?>
dst
)
{
// ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes,
// ? Retool this logic to use RETYPE_ONLY, CHECK_CAST, etc., as opcodes,
// so we don't need to repeat so much decision making.
// so we don't need to repeat so much decision making.
if
(
VerifyType
.
isNullConversion
(
src
,
dst
))
{
if
(
VerifyType
.
isNullConversion
(
src
,
dst
))
{
...
@@ -118,16 +113,13 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -118,16 +113,13 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* the JVM supports ricochet adapters).
* the JVM supports ricochet adapters).
* The argument conversions allowed are casting, unboxing,
* The argument conversions allowed are casting, unboxing,
* integral widening or narrowing, and floating point widening or narrowing.
* integral widening or narrowing, and floating point widening or narrowing.
* @param token access check
* @param newType required call type
* @param newType required call type
* @param target original method handle
* @param target original method handle
* @return an adapter to the original handle with the desired new type,
* @return an adapter to the original handle with the desired new type,
* or the original target if the types are already identical
* or the original target if the types are already identical
* or null if the adaptation cannot be made
* or null if the adaptation cannot be made
*/
*/
public
static
MethodHandle
makePairwiseConvert
(
Access
token
,
static
MethodHandle
makePairwiseConvert
(
MethodType
newType
,
MethodHandle
target
)
{
MethodType
newType
,
MethodHandle
target
)
{
Access
.
check
(
token
);
MethodType
oldType
=
target
.
type
();
MethodType
oldType
=
target
.
type
();
if
(
newType
==
oldType
)
return
target
;
if
(
newType
==
oldType
)
return
target
;
...
@@ -170,9 +162,9 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -170,9 +162,9 @@ public class AdapterMethodHandle extends BoundMethodHandle {
// It parallels canConvertArgument() above.
// It parallels canConvertArgument() above.
if
(
src
.
isPrimitive
())
{
if
(
src
.
isPrimitive
())
{
if
(
dst
.
isPrimitive
())
{
if
(
dst
.
isPrimitive
())
{
adapter
=
makePrimCast
(
token
,
midType
,
adapter
,
i
,
dst
);
adapter
=
makePrimCast
(
midType
,
adapter
,
i
,
dst
);
}
else
{
}
else
{
adapter
=
makeBoxArgument
(
token
,
midType
,
adapter
,
i
,
dst
);
adapter
=
makeBoxArgument
(
midType
,
adapter
,
i
,
dst
);
}
}
}
else
{
}
else
{
if
(
dst
.
isPrimitive
())
{
if
(
dst
.
isPrimitive
())
{
...
@@ -182,13 +174,13 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -182,13 +174,13 @@ public class AdapterMethodHandle extends BoundMethodHandle {
// conversions supported by reflect.Method.invoke.
// conversions supported by reflect.Method.invoke.
// Those conversions require a big nest of if/then/else logic,
// Those conversions require a big nest of if/then/else logic,
// which we prefer to make a user responsibility.
// which we prefer to make a user responsibility.
adapter
=
makeUnboxArgument
(
token
,
midType
,
adapter
,
i
,
dst
);
adapter
=
makeUnboxArgument
(
midType
,
adapter
,
i
,
dst
);
}
else
{
}
else
{
// Simple reference conversion.
// Simple reference conversion.
// Note: Do not check for a class hierarchy relation
// Note: Do not check for a class hierarchy relation
// between src and dst. In all cases a 'null' argument
// between src and dst. In all cases a 'null' argument
// will pass the cast conversion.
// will pass the cast conversion.
adapter
=
makeCheckCast
(
token
,
midType
,
adapter
,
i
,
dst
);
adapter
=
makeCheckCast
(
midType
,
adapter
,
i
,
dst
);
}
}
}
}
assert
(
adapter
!=
null
);
assert
(
adapter
!=
null
);
...
@@ -196,7 +188,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -196,7 +188,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
}
}
if
(
adapter
.
type
()
!=
newType
)
{
if
(
adapter
.
type
()
!=
newType
)
{
// Only trivial conversions remain.
// Only trivial conversions remain.
adapter
=
makeRetypeOnly
(
IMPL_TOKEN
,
newType
,
adapter
);
adapter
=
makeRetypeOnly
(
newType
,
adapter
);
assert
(
adapter
!=
null
);
assert
(
adapter
!=
null
);
// Actually, that's because there were no non-trivial ones:
// Actually, that's because there were no non-trivial ones:
assert
(
lastConv
==
-
1
);
assert
(
lastConv
==
-
1
);
...
@@ -208,7 +200,6 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -208,7 +200,6 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/**
/**
* Create a JVM-level adapter method handle to permute the arguments
* Create a JVM-level adapter method handle to permute the arguments
* of the given method.
* of the given method.
* @param token access check
* @param newType required call type
* @param newType required call type
* @param target original method handle
* @param target original method handle
* @param argumentMap for each target argument, position of its source in newType
* @param argumentMap for each target argument, position of its source in newType
...
@@ -218,8 +209,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -218,8 +209,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* @throws IllegalArgumentException if the adaptation cannot be made
* @throws IllegalArgumentException if the adaptation cannot be made
* directly by a JVM-level adapter, without help from Java code
* directly by a JVM-level adapter, without help from Java code
*/
*/
public
static
MethodHandle
makePermutation
(
Access
token
,
static
MethodHandle
makePermutation
(
MethodType
newType
,
MethodHandle
target
,
MethodType
newType
,
MethodHandle
target
,
int
[]
argumentMap
)
{
int
[]
argumentMap
)
{
MethodType
oldType
=
target
.
type
();
MethodType
oldType
=
target
.
type
();
boolean
nullPermutation
=
true
;
boolean
nullPermutation
=
true
;
...
@@ -234,7 +224,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -234,7 +224,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
if
(
argumentMap
.
length
!=
oldType
.
parameterCount
())
if
(
argumentMap
.
length
!=
oldType
.
parameterCount
())
throw
newIllegalArgumentException
(
"bad permutation: "
+
Arrays
.
toString
(
argumentMap
));
throw
newIllegalArgumentException
(
"bad permutation: "
+
Arrays
.
toString
(
argumentMap
));
if
(
nullPermutation
)
{
if
(
nullPermutation
)
{
MethodHandle
res
=
makePairwiseConvert
(
token
,
newType
,
target
);
MethodHandle
res
=
makePairwiseConvert
(
newType
,
target
);
// well, that was easy
// well, that was easy
if
(
res
==
null
)
if
(
res
==
null
)
throw
newIllegalArgumentException
(
"cannot convert pairwise: "
+
newType
);
throw
newIllegalArgumentException
(
"cannot convert pairwise: "
+
newType
);
...
@@ -435,7 +425,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -435,7 +425,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
}
}
/** Can a retyping adapter (alone) validly convert the target to newType? */
/** Can a retyping adapter (alone) validly convert the target to newType? */
public
static
boolean
canRetypeOnly
(
MethodType
newType
,
MethodType
targetType
)
{
static
boolean
canRetypeOnly
(
MethodType
newType
,
MethodType
targetType
)
{
return
canRetype
(
newType
,
targetType
,
false
);
return
canRetype
(
newType
,
targetType
,
false
);
}
}
/** Can a retyping adapter (alone) convert the target to newType?
/** Can a retyping adapter (alone) convert the target to newType?
...
@@ -444,7 +434,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -444,7 +434,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* reference conversions on return. This last feature requires that the
* reference conversions on return. This last feature requires that the
* caller be trusted, and perform explicit cast conversions on return values.
* caller be trusted, and perform explicit cast conversions on return values.
*/
*/
public
static
boolean
canRetypeRaw
(
MethodType
newType
,
MethodType
targetType
)
{
static
boolean
canRetypeRaw
(
MethodType
newType
,
MethodType
targetType
)
{
return
canRetype
(
newType
,
targetType
,
true
);
return
canRetype
(
newType
,
targetType
,
true
);
}
}
static
boolean
canRetype
(
MethodType
newType
,
MethodType
targetType
,
boolean
raw
)
{
static
boolean
canRetype
(
MethodType
newType
,
MethodType
targetType
,
boolean
raw
)
{
...
@@ -459,17 +449,13 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -459,17 +449,13 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* Allows unchecked argument conversions pairwise, if they are safe.
* Allows unchecked argument conversions pairwise, if they are safe.
* Returns null if not possible.
* Returns null if not possible.
*/
*/
public
static
MethodHandle
makeRetypeOnly
(
Access
token
,
static
MethodHandle
makeRetypeOnly
(
MethodType
newType
,
MethodHandle
target
)
{
MethodType
newType
,
MethodHandle
target
)
{
return
makeRetype
(
newType
,
target
,
false
);
return
makeRetype
(
token
,
newType
,
target
,
false
);
}
}
public
static
MethodHandle
makeRetypeRaw
(
Access
token
,
static
MethodHandle
makeRetypeRaw
(
MethodType
newType
,
MethodHandle
target
)
{
MethodType
newType
,
MethodHandle
target
)
{
return
makeRetype
(
newType
,
target
,
true
);
return
makeRetype
(
token
,
newType
,
target
,
true
);
}
}
static
MethodHandle
makeRetype
(
Access
token
,
static
MethodHandle
makeRetype
(
MethodType
newType
,
MethodHandle
target
,
boolean
raw
)
{
MethodType
newType
,
MethodHandle
target
,
boolean
raw
)
{
Access
.
check
(
token
);
MethodType
oldType
=
target
.
type
();
MethodType
oldType
=
target
.
type
();
if
(
oldType
==
newType
)
return
target
;
if
(
oldType
==
newType
)
return
target
;
if
(!
canRetype
(
newType
,
oldType
,
raw
))
if
(!
canRetype
(
newType
,
oldType
,
raw
))
...
@@ -478,9 +464,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -478,9 +464,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
return
new
AdapterMethodHandle
(
target
,
newType
,
makeConv
(
raw
?
OP_RETYPE_RAW
:
OP_RETYPE_ONLY
));
return
new
AdapterMethodHandle
(
target
,
newType
,
makeConv
(
raw
?
OP_RETYPE_RAW
:
OP_RETYPE_ONLY
));
}
}
static
MethodHandle
makeVarargsCollector
(
Access
token
,
static
MethodHandle
makeVarargsCollector
(
MethodHandle
target
,
Class
<?>
arrayType
)
{
MethodHandle
target
,
Class
<?>
arrayType
)
{
Access
.
check
(
token
);
return
new
AsVarargsCollector
(
target
,
arrayType
);
return
new
AsVarargsCollector
(
target
,
arrayType
);
}
}
...
@@ -526,6 +510,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -526,6 +510,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
return
collector
.
asType
(
newType
);
return
collector
.
asType
(
newType
);
}
}
@Override
public
MethodHandle
asVarargsCollector
(
Class
<?>
arrayType
)
{
public
MethodHandle
asVarargsCollector
(
Class
<?>
arrayType
)
{
MethodType
type
=
this
.
type
();
MethodType
type
=
this
.
type
();
if
(
type
.
parameterType
(
type
.
parameterCount
()-
1
)
==
arrayType
)
if
(
type
.
parameterType
(
type
.
parameterCount
()-
1
)
==
arrayType
)
...
@@ -537,7 +522,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -537,7 +522,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Can a checkcast adapter validly convert the target to newType?
/** Can a checkcast adapter validly convert the target to newType?
* The JVM supports all kind of reference casts, even silly ones.
* The JVM supports all kind of reference casts, even silly ones.
*/
*/
public
static
boolean
canCheckCast
(
MethodType
newType
,
MethodType
targetType
,
static
boolean
canCheckCast
(
MethodType
newType
,
MethodType
targetType
,
int
arg
,
Class
<?>
castType
)
{
int
arg
,
Class
<?>
castType
)
{
if
(!
convOpSupported
(
OP_CHECK_CAST
))
return
false
;
if
(!
convOpSupported
(
OP_CHECK_CAST
))
return
false
;
Class
<?>
src
=
newType
.
parameterType
(
arg
);
Class
<?>
src
=
newType
.
parameterType
(
arg
);
...
@@ -549,7 +534,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -549,7 +534,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
return
(
diff
==
arg
+
1
);
// arg is sole non-trivial diff
return
(
diff
==
arg
+
1
);
// arg is sole non-trivial diff
}
}
/** Can an primitive conversion adapter validly convert src to dst? */
/** Can an primitive conversion adapter validly convert src to dst? */
public
static
boolean
canCheckCast
(
Class
<?>
src
,
Class
<?>
dst
)
{
static
boolean
canCheckCast
(
Class
<?>
src
,
Class
<?>
dst
)
{
return
(!
src
.
isPrimitive
()
&&
!
dst
.
isPrimitive
());
return
(!
src
.
isPrimitive
()
&&
!
dst
.
isPrimitive
());
}
}
...
@@ -558,10 +543,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -558,10 +543,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* with a null conversion to the corresponding target parameter.
* with a null conversion to the corresponding target parameter.
* Return null if this cannot be done.
* Return null if this cannot be done.
*/
*/
public
static
MethodHandle
makeCheckCast
(
Access
token
,
static
MethodHandle
makeCheckCast
(
MethodType
newType
,
MethodHandle
target
,
MethodType
newType
,
MethodHandle
target
,
int
arg
,
Class
<?>
castType
)
{
int
arg
,
Class
<?>
castType
)
{
Access
.
check
(
token
);
if
(!
canCheckCast
(
newType
,
target
.
type
(),
arg
,
castType
))
if
(!
canCheckCast
(
newType
,
target
.
type
(),
arg
,
castType
))
return
null
;
return
null
;
long
conv
=
makeConv
(
OP_CHECK_CAST
,
arg
,
T_OBJECT
,
T_OBJECT
);
long
conv
=
makeConv
(
OP_CHECK_CAST
,
arg
,
T_OBJECT
,
T_OBJECT
);
...
@@ -572,7 +555,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -572,7 +555,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* The JVM currently supports all conversions except those between
* The JVM currently supports all conversions except those between
* floating and integral types.
* floating and integral types.
*/
*/
public
static
boolean
canPrimCast
(
MethodType
newType
,
MethodType
targetType
,
static
boolean
canPrimCast
(
MethodType
newType
,
MethodType
targetType
,
int
arg
,
Class
<?>
convType
)
{
int
arg
,
Class
<?>
convType
)
{
if
(!
convOpSupported
(
OP_PRIM_TO_PRIM
))
return
false
;
if
(!
convOpSupported
(
OP_PRIM_TO_PRIM
))
return
false
;
Class
<?>
src
=
newType
.
parameterType
(
arg
);
Class
<?>
src
=
newType
.
parameterType
(
arg
);
...
@@ -584,7 +567,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -584,7 +567,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
return
(
diff
==
arg
+
1
);
// arg is sole non-trivial diff
return
(
diff
==
arg
+
1
);
// arg is sole non-trivial diff
}
}
/** Can an primitive conversion adapter validly convert src to dst? */
/** Can an primitive conversion adapter validly convert src to dst? */
public
static
boolean
canPrimCast
(
Class
<?>
src
,
Class
<?>
dst
)
{
static
boolean
canPrimCast
(
Class
<?>
src
,
Class
<?>
dst
)
{
if
(
src
==
dst
||
!
src
.
isPrimitive
()
||
!
dst
.
isPrimitive
())
{
if
(
src
==
dst
||
!
src
.
isPrimitive
()
||
!
dst
.
isPrimitive
())
{
return
false
;
return
false
;
}
else
if
(
Wrapper
.
forPrimitiveType
(
dst
).
isFloating
())
{
}
else
if
(
Wrapper
.
forPrimitiveType
(
dst
).
isFloating
())
{
...
@@ -604,10 +587,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -604,10 +587,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* with a null conversion to the corresponding target parameter.
* with a null conversion to the corresponding target parameter.
* Return null if this cannot be done.
* Return null if this cannot be done.
*/
*/
public
static
MethodHandle
makePrimCast
(
Access
token
,
static
MethodHandle
makePrimCast
(
MethodType
newType
,
MethodHandle
target
,
MethodType
newType
,
MethodHandle
target
,
int
arg
,
Class
<?>
convType
)
{
int
arg
,
Class
<?>
convType
)
{
Access
.
check
(
token
);
MethodType
oldType
=
target
.
type
();
MethodType
oldType
=
target
.
type
();
if
(!
canPrimCast
(
newType
,
oldType
,
arg
,
convType
))
if
(!
canPrimCast
(
newType
,
oldType
,
arg
,
convType
))
return
null
;
return
null
;
...
@@ -620,7 +601,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -620,7 +601,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* The JVM currently supports all kinds of casting and unboxing.
* The JVM currently supports all kinds of casting and unboxing.
* The convType is the unboxed type; it can be either a primitive or wrapper.
* The convType is the unboxed type; it can be either a primitive or wrapper.
*/
*/
public
static
boolean
canUnboxArgument
(
MethodType
newType
,
MethodType
targetType
,
static
boolean
canUnboxArgument
(
MethodType
newType
,
MethodType
targetType
,
int
arg
,
Class
<?>
convType
)
{
int
arg
,
Class
<?>
convType
)
{
if
(!
convOpSupported
(
OP_REF_TO_PRIM
))
return
false
;
if
(!
convOpSupported
(
OP_REF_TO_PRIM
))
return
false
;
Class
<?>
src
=
newType
.
parameterType
(
arg
);
Class
<?>
src
=
newType
.
parameterType
(
arg
);
...
@@ -635,15 +616,14 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -635,15 +616,14 @@ public class AdapterMethodHandle extends BoundMethodHandle {
return
(
diff
==
arg
+
1
);
// arg is sole non-trivial diff
return
(
diff
==
arg
+
1
);
// arg is sole non-trivial diff
}
}
/** Can an primitive unboxing adapter validly convert src to dst? */
/** Can an primitive unboxing adapter validly convert src to dst? */
public
static
boolean
canUnboxArgument
(
Class
<?>
src
,
Class
<?>
dst
)
{
static
boolean
canUnboxArgument
(
Class
<?>
src
,
Class
<?>
dst
)
{
return
(!
src
.
isPrimitive
()
&&
Wrapper
.
asPrimitiveType
(
dst
).
isPrimitive
());
return
(!
src
.
isPrimitive
()
&&
Wrapper
.
asPrimitiveType
(
dst
).
isPrimitive
());
}
}
/** Factory method: Unbox the given argument.
/** Factory method: Unbox the given argument.
* Return null if this cannot be done.
* Return null if this cannot be done.
*/
*/
public
static
MethodHandle
makeUnboxArgument
(
Access
token
,
static
MethodHandle
makeUnboxArgument
(
MethodType
newType
,
MethodHandle
target
,
MethodType
newType
,
MethodHandle
target
,
int
arg
,
Class
<?>
convType
)
{
int
arg
,
Class
<?>
convType
)
{
MethodType
oldType
=
target
.
type
();
MethodType
oldType
=
target
.
type
();
Class
<?>
src
=
newType
.
parameterType
(
arg
);
Class
<?>
src
=
newType
.
parameterType
(
arg
);
...
@@ -659,11 +639,11 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -659,11 +639,11 @@ public class AdapterMethodHandle extends BoundMethodHandle {
MethodHandle
adapter
=
new
AdapterMethodHandle
(
target
,
castDone
,
conv
,
boxType
);
MethodHandle
adapter
=
new
AdapterMethodHandle
(
target
,
castDone
,
conv
,
boxType
);
if
(
castDone
==
newType
)
if
(
castDone
==
newType
)
return
adapter
;
return
adapter
;
return
makeCheckCast
(
token
,
newType
,
adapter
,
arg
,
boxType
);
return
makeCheckCast
(
newType
,
adapter
,
arg
,
boxType
);
}
}
/** Can an primitive boxing adapter validly convert src to dst? */
/** Can an primitive boxing adapter validly convert src to dst? */
public
static
boolean
canBoxArgument
(
Class
<?>
src
,
Class
<?>
dst
)
{
static
boolean
canBoxArgument
(
Class
<?>
src
,
Class
<?>
dst
)
{
if
(!
convOpSupported
(
OP_PRIM_TO_REF
))
return
false
;
if
(!
convOpSupported
(
OP_PRIM_TO_REF
))
return
false
;
throw
new
UnsupportedOperationException
(
"NYI"
);
throw
new
UnsupportedOperationException
(
"NYI"
);
}
}
...
@@ -671,15 +651,14 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -671,15 +651,14 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Factory method: Unbox the given argument.
/** Factory method: Unbox the given argument.
* Return null if this cannot be done.
* Return null if this cannot be done.
*/
*/
public
static
MethodHandle
makeBoxArgument
(
Access
token
,
static
MethodHandle
makeBoxArgument
(
MethodType
newType
,
MethodHandle
target
,
MethodType
newType
,
MethodHandle
target
,
int
arg
,
Class
<?>
convType
)
{
int
arg
,
Class
<?>
convType
)
{
// this is difficult to do in the JVM because it must GC
// this is difficult to do in the JVM because it must GC
return
null
;
return
null
;
}
}
/** Can an adapter simply drop arguments to convert the target to newType? */
/** Can an adapter simply drop arguments to convert the target to newType? */
public
static
boolean
canDropArguments
(
MethodType
newType
,
MethodType
targetType
,
static
boolean
canDropArguments
(
MethodType
newType
,
MethodType
targetType
,
int
dropArgPos
,
int
dropArgCount
)
{
int
dropArgPos
,
int
dropArgCount
)
{
if
(
dropArgCount
==
0
)
if
(
dropArgCount
==
0
)
return
canRetypeOnly
(
newType
,
targetType
);
return
canRetypeOnly
(
newType
,
targetType
);
...
@@ -706,12 +685,10 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -706,12 +685,10 @@ public class AdapterMethodHandle extends BoundMethodHandle {
* Allow unchecked retyping of remaining arguments, pairwise.
* Allow unchecked retyping of remaining arguments, pairwise.
* Return null if this is not possible.
* Return null if this is not possible.
*/
*/
public
static
MethodHandle
makeDropArguments
(
Access
token
,
static
MethodHandle
makeDropArguments
(
MethodType
newType
,
MethodHandle
target
,
MethodType
newType
,
MethodHandle
target
,
int
dropArgPos
,
int
dropArgCount
)
{
int
dropArgPos
,
int
dropArgCount
)
{
Access
.
check
(
token
);
if
(
dropArgCount
==
0
)
if
(
dropArgCount
==
0
)
return
makeRetypeOnly
(
IMPL_TOKEN
,
newType
,
target
);
return
makeRetypeOnly
(
newType
,
target
);
if
(!
canDropArguments
(
newType
,
target
.
type
(),
dropArgPos
,
dropArgCount
))
if
(!
canDropArguments
(
newType
,
target
.
type
(),
dropArgPos
,
dropArgCount
))
return
null
;
return
null
;
// in arglist: [0: ...keep1 | dpos: drop... | dpos+dcount: keep2... ]
// in arglist: [0: ...keep1 | dpos: drop... | dpos+dcount: keep2... ]
...
@@ -727,7 +704,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -727,7 +704,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
}
}
/** Can an adapter duplicate an argument to convert the target to newType? */
/** Can an adapter duplicate an argument to convert the target to newType? */
public
static
boolean
canDupArguments
(
MethodType
newType
,
MethodType
targetType
,
static
boolean
canDupArguments
(
MethodType
newType
,
MethodType
targetType
,
int
dupArgPos
,
int
dupArgCount
)
{
int
dupArgPos
,
int
dupArgCount
)
{
if
(!
convOpSupported
(
OP_DUP_ARGS
))
return
false
;
if
(!
convOpSupported
(
OP_DUP_ARGS
))
return
false
;
if
(
diffReturnTypes
(
newType
,
targetType
,
false
)
!=
0
)
if
(
diffReturnTypes
(
newType
,
targetType
,
false
)
!=
0
)
...
@@ -749,10 +726,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -749,10 +726,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Factory method: Duplicate the selected argument.
/** Factory method: Duplicate the selected argument.
* Return null if this is not possible.
* Return null if this is not possible.
*/
*/
public
static
MethodHandle
makeDupArguments
(
Access
token
,
static
MethodHandle
makeDupArguments
(
MethodType
newType
,
MethodHandle
target
,
MethodType
newType
,
MethodHandle
target
,
int
dupArgPos
,
int
dupArgCount
)
{
int
dupArgPos
,
int
dupArgCount
)
{
Access
.
check
(
token
);
if
(!
canDupArguments
(
newType
,
target
.
type
(),
dupArgPos
,
dupArgCount
))
if
(!
canDupArguments
(
newType
,
target
.
type
(),
dupArgPos
,
dupArgCount
))
return
null
;
return
null
;
if
(
dupArgCount
==
0
)
if
(
dupArgCount
==
0
)
...
@@ -769,7 +744,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -769,7 +744,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
}
}
/** Can an adapter swap two arguments to convert the target to newType? */
/** Can an adapter swap two arguments to convert the target to newType? */
public
static
boolean
canSwapArguments
(
MethodType
newType
,
MethodType
targetType
,
static
boolean
canSwapArguments
(
MethodType
newType
,
MethodType
targetType
,
int
swapArg1
,
int
swapArg2
)
{
int
swapArg1
,
int
swapArg2
)
{
if
(!
convOpSupported
(
OP_SWAP_ARGS
))
return
false
;
if
(!
convOpSupported
(
OP_SWAP_ARGS
))
return
false
;
if
(
diffReturnTypes
(
newType
,
targetType
,
false
)
!=
0
)
if
(
diffReturnTypes
(
newType
,
targetType
,
false
)
!=
0
)
...
@@ -796,10 +771,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -796,10 +771,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Factory method: Swap the selected arguments.
/** Factory method: Swap the selected arguments.
* Return null if this is not possible.
* Return null if this is not possible.
*/
*/
public
static
MethodHandle
makeSwapArguments
(
Access
token
,
static
MethodHandle
makeSwapArguments
(
MethodType
newType
,
MethodHandle
target
,
MethodType
newType
,
MethodHandle
target
,
int
swapArg1
,
int
swapArg2
)
{
int
swapArg1
,
int
swapArg2
)
{
Access
.
check
(
token
);
if
(
swapArg1
==
swapArg2
)
if
(
swapArg1
==
swapArg2
)
return
target
;
return
target
;
if
(
swapArg1
>
swapArg2
)
{
int
t
=
swapArg1
;
swapArg1
=
swapArg2
;
swapArg2
=
t
;
}
if
(
swapArg1
>
swapArg2
)
{
int
t
=
swapArg1
;
swapArg1
=
swapArg2
;
swapArg2
=
t
;
}
...
@@ -829,7 +802,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -829,7 +802,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
final
static
int
MAX_ARG_ROTATION
=
1
;
final
static
int
MAX_ARG_ROTATION
=
1
;
/** Can an adapter rotate arguments to convert the target to newType? */
/** Can an adapter rotate arguments to convert the target to newType? */
public
static
boolean
canRotateArguments
(
MethodType
newType
,
MethodType
targetType
,
static
boolean
canRotateArguments
(
MethodType
newType
,
MethodType
targetType
,
int
firstArg
,
int
argCount
,
int
rotateBy
)
{
int
firstArg
,
int
argCount
,
int
rotateBy
)
{
if
(!
convOpSupported
(
OP_ROT_ARGS
))
return
false
;
if
(!
convOpSupported
(
OP_ROT_ARGS
))
return
false
;
if
(
argCount
<=
2
)
return
false
;
// must be a swap, not a rotate
if
(
argCount
<=
2
)
return
false
;
// must be a swap, not a rotate
...
@@ -861,10 +834,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -861,10 +834,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Factory method: Rotate the selected argument range.
/** Factory method: Rotate the selected argument range.
* Return null if this is not possible.
* Return null if this is not possible.
*/
*/
public
static
MethodHandle
makeRotateArguments
(
Access
token
,
static
MethodHandle
makeRotateArguments
(
MethodType
newType
,
MethodHandle
target
,
MethodType
newType
,
MethodHandle
target
,
int
firstArg
,
int
argCount
,
int
rotateBy
)
{
int
firstArg
,
int
argCount
,
int
rotateBy
)
{
Access
.
check
(
token
);
rotateBy
=
positiveRotation
(
argCount
,
rotateBy
);
rotateBy
=
positiveRotation
(
argCount
,
rotateBy
);
if
(!
canRotateArguments
(
newType
,
target
.
type
(),
firstArg
,
argCount
,
rotateBy
))
if
(!
canRotateArguments
(
newType
,
target
.
type
(),
firstArg
,
argCount
,
rotateBy
))
return
null
;
return
null
;
...
@@ -904,7 +875,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -904,7 +875,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
}
}
/** Can an adapter spread an argument to convert the target to newType? */
/** Can an adapter spread an argument to convert the target to newType? */
public
static
boolean
canSpreadArguments
(
MethodType
newType
,
MethodType
targetType
,
static
boolean
canSpreadArguments
(
MethodType
newType
,
MethodType
targetType
,
Class
<?>
spreadArgType
,
int
spreadArgPos
,
int
spreadArgCount
)
{
Class
<?>
spreadArgType
,
int
spreadArgPos
,
int
spreadArgCount
)
{
if
(!
convOpSupported
(
OP_SPREAD_ARGS
))
return
false
;
if
(!
convOpSupported
(
OP_SPREAD_ARGS
))
return
false
;
if
(
diffReturnTypes
(
newType
,
targetType
,
false
)
!=
0
)
if
(
diffReturnTypes
(
newType
,
targetType
,
false
)
!=
0
)
...
@@ -937,10 +908,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -937,10 +908,8 @@ public class AdapterMethodHandle extends BoundMethodHandle {
/** Factory method: Spread selected argument. */
/** Factory method: Spread selected argument. */
public
static
MethodHandle
makeSpreadArguments
(
Access
token
,
static
MethodHandle
makeSpreadArguments
(
MethodType
newType
,
MethodHandle
target
,
MethodType
newType
,
MethodHandle
target
,
Class
<?>
spreadArgType
,
int
spreadArgPos
,
int
spreadArgCount
)
{
Class
<?>
spreadArgType
,
int
spreadArgPos
,
int
spreadArgCount
)
{
Access
.
check
(
token
);
MethodType
targetType
=
target
.
type
();
MethodType
targetType
=
target
.
type
();
if
(!
canSpreadArguments
(
newType
,
targetType
,
spreadArgType
,
spreadArgPos
,
spreadArgCount
))
if
(!
canSpreadArguments
(
newType
,
targetType
,
spreadArgType
,
spreadArgPos
,
spreadArgCount
))
return
null
;
return
null
;
...
@@ -962,7 +931,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
...
@@ -962,7 +931,7 @@ public class AdapterMethodHandle extends BoundMethodHandle {
@Override
@Override
public
String
toString
()
{
public
String
toString
()
{
return
MethodHandleImpl
.
getNameString
(
IMPL_TOKEN
,
nonAdapter
((
MethodHandle
)
vmtarget
),
this
);
return
getNameString
(
nonAdapter
((
MethodHandle
)
vmtarget
),
this
);
}
}
private
static
MethodHandle
nonAdapter
(
MethodHandle
mh
)
{
private
static
MethodHandle
nonAdapter
(
MethodHandle
mh
)
{
...
...
src/share/classes/
sun/dyn
/BoundMethodHandle.java
→
src/share/classes/
java/lang/invoke
/BoundMethodHandle.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,15 +23,11 @@
...
@@ -23,15 +23,11 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
sun.dyn.util.VerifyType
;
import
sun.invoke.util.VerifyType
;
import
sun.dyn.util.Wrapper
;
import
sun.invoke.util.Wrapper
;
import
java.dyn.*
;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
import
java.util.List
;
import
sun.dyn.MethodHandleNatives.Constants
;
import
static
sun
.
dyn
.
MethodHandleImpl
.
IMPL_LOOKUP
;
import
static
sun
.
dyn
.
MemberName
.
newIllegalArgumentException
;
/**
/**
* The flavor of method handle which emulates an invoke instruction
* The flavor of method handle which emulates an invoke instruction
...
@@ -39,37 +35,29 @@ import static sun.dyn.MemberName.newIllegalArgumentException;
...
@@ -39,37 +35,29 @@ import static sun.dyn.MemberName.newIllegalArgumentException;
* when the handle is created, not when it is invoked.
* when the handle is created, not when it is invoked.
* @author jrose
* @author jrose
*/
*/
public
class
BoundMethodHandle
extends
MethodHandle
{
class
BoundMethodHandle
extends
MethodHandle
{
//MethodHandle vmtarget; // next BMH or final DMH or methodOop
//MethodHandle vmtarget; // next BMH or final DMH or methodOop
private
final
Object
argument
;
// argument to insert
private
final
Object
argument
;
// argument to insert
private
final
int
vmargslot
;
// position at which it is inserted
private
final
int
vmargslot
;
// position at which it is inserted
private
static
final
Access
IMPL_TOKEN
=
Access
.
getToken
();
private
static
final
MemberName
.
Factory
IMPL_NAMES
=
MemberName
.
getFactory
(
IMPL_TOKEN
);
// Constructors in this class *must* be package scoped or private.
// Constructors in this class *must* be package scoped or private.
/** Bind a direct MH to its receiver (or first ref. argument).
/** Bind a direct MH to its receiver (or first ref. argument).
* The JVM will pre-dispatch the MH if it is not already static.
* The JVM will pre-dispatch the MH if it is not already static.
*/
*/
BoundMethodHandle
(
DirectMethodHandle
mh
,
Object
argument
)
{
/*non-public*/
BoundMethodHandle
(
DirectMethodHandle
mh
,
Object
argument
)
{
super
(
Access
.
TOKEN
,
mh
.
type
().
dropParameterTypes
(
0
,
1
));
super
(
mh
.
type
().
dropParameterTypes
(
0
,
1
));
// check the type now, once for all:
// check the type now, once for all:
this
.
argument
=
checkReferenceArgument
(
argument
,
mh
,
0
);
this
.
argument
=
checkReferenceArgument
(
argument
,
mh
,
0
);
this
.
vmargslot
=
this
.
type
().
parameterSlotCount
();
this
.
vmargslot
=
this
.
type
().
parameterSlotCount
();
if
(
MethodHandleNatives
.
JVM_SUPPORT
)
{
initTarget
(
mh
,
0
);
this
.
vmtarget
=
null
;
// maybe updated by JVM
MethodHandleNatives
.
init
(
this
,
mh
,
0
);
}
else
{
this
.
vmtarget
=
mh
;
}
}
}
/** Insert an argument into an arbitrary method handle.
/** Insert an argument into an arbitrary method handle.
* If argnum is zero, inserts the first argument, etc.
* If argnum is zero, inserts the first argument, etc.
* The argument type must be a reference.
* The argument type must be a reference.
*/
*/
BoundMethodHandle
(
MethodHandle
mh
,
Object
argument
,
int
argnum
)
{
/*non-public*/
BoundMethodHandle
(
MethodHandle
mh
,
Object
argument
,
int
argnum
)
{
this
(
mh
.
type
().
dropParameterTypes
(
argnum
,
argnum
+
1
),
this
(
mh
.
type
().
dropParameterTypes
(
argnum
,
argnum
+
1
),
mh
,
argument
,
argnum
);
mh
,
argument
,
argnum
);
}
}
...
@@ -77,8 +65,8 @@ public class BoundMethodHandle extends MethodHandle {
...
@@ -77,8 +65,8 @@ public class BoundMethodHandle extends MethodHandle {
/** Insert an argument into an arbitrary method handle.
/** Insert an argument into an arbitrary method handle.
* If argnum is zero, inserts the first argument, etc.
* If argnum is zero, inserts the first argument, etc.
*/
*/
BoundMethodHandle
(
MethodType
type
,
MethodHandle
mh
,
Object
argument
,
int
argnum
)
{
/*non-public*/
BoundMethodHandle
(
MethodType
type
,
MethodHandle
mh
,
Object
argument
,
int
argnum
)
{
super
(
Access
.
TOKEN
,
type
);
super
(
type
);
if
(
mh
.
type
().
parameterType
(
argnum
).
isPrimitive
())
if
(
mh
.
type
().
parameterType
(
argnum
).
isPrimitive
())
this
.
argument
=
bindPrimitiveArgument
(
argument
,
mh
,
argnum
);
this
.
argument
=
bindPrimitiveArgument
(
argument
,
mh
,
argnum
);
else
{
else
{
...
@@ -89,18 +77,14 @@ public class BoundMethodHandle extends MethodHandle {
...
@@ -89,18 +77,14 @@ public class BoundMethodHandle extends MethodHandle {
}
}
private
void
initTarget
(
MethodHandle
mh
,
int
argnum
)
{
private
void
initTarget
(
MethodHandle
mh
,
int
argnum
)
{
if
(
MethodHandleNatives
.
JVM_SUPPORT
)
{
//this.vmtarget = mh; // maybe updated by JVM
this
.
vmtarget
=
null
;
// maybe updated by JVM
MethodHandleNatives
.
init
(
this
,
mh
,
argnum
);
MethodHandleNatives
.
init
(
this
,
mh
,
argnum
);
}
else
{
this
.
vmtarget
=
mh
;
}
}
}
/** For the AdapterMethodHandle subclass.
/** For the AdapterMethodHandle subclass.
*/
*/
BoundMethodHandle
(
MethodType
type
,
Object
argument
,
int
vmargslot
)
{
/*non-public*/
BoundMethodHandle
(
MethodType
type
,
Object
argument
,
int
vmargslot
)
{
super
(
Access
.
TOKEN
,
type
);
super
(
type
);
this
.
argument
=
argument
;
this
.
argument
=
argument
;
this
.
vmargslot
=
vmargslot
;
this
.
vmargslot
=
vmargslot
;
assert
(
this
instanceof
AdapterMethodHandle
);
assert
(
this
instanceof
AdapterMethodHandle
);
...
@@ -112,8 +96,8 @@ public class BoundMethodHandle extends MethodHandle {
...
@@ -112,8 +96,8 @@ public class BoundMethodHandle extends MethodHandle {
* same as {@code entryPoint}, except that the first argument
* same as {@code entryPoint}, except that the first argument
* type will be dropped.
* type will be dropped.
*/
*/
protected
BoundMethodHandle
(
Access
token
,
MethodHandle
entryPoint
)
{
/*non-public*/
BoundMethodHandle
(
MethodHandle
entryPoint
)
{
super
(
token
,
entryPoint
.
type
().
dropParameterTypes
(
0
,
1
));
super
(
entryPoint
.
type
().
dropParameterTypes
(
0
,
1
));
this
.
argument
=
this
;
// kludge; get rid of
this
.
argument
=
this
;
// kludge; get rid of
this
.
vmargslot
=
this
.
type
().
parameterSlotDepth
(
0
);
this
.
vmargslot
=
this
.
type
().
parameterSlotDepth
(
0
);
initTarget
(
entryPoint
,
0
);
initTarget
(
entryPoint
,
0
);
...
@@ -172,7 +156,7 @@ public class BoundMethodHandle extends MethodHandle {
...
@@ -172,7 +156,7 @@ public class BoundMethodHandle extends MethodHandle {
@Override
@Override
public
String
toString
()
{
public
String
toString
()
{
return
MethodHandleImpl
.
addTypeString
(
baseName
(),
this
);
return
addTypeString
(
baseName
(),
this
);
}
}
/** Component of toString() before the type string. */
/** Component of toString() before the type string. */
...
...
src/share/classes/java/
dyn
/CallSite.java
→
src/share/classes/java/
lang/invoke
/CallSite.java
浏览文件 @
33ee9ccf
...
@@ -23,12 +23,12 @@
...
@@ -23,12 +23,12 @@
* questions.
* questions.
*/
*/
package
java.
dyn
;
package
java.
lang.invoke
;
import
sun.dyn.*
;
import
sun.invoke.empty.Empty
;
import
sun.dyn.empty.Empty
;
import
sun.misc.Unsafe
;
import
sun.misc.Unsafe
;
import
java.util.Collection
;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
import
static
java
.
lang
.
invoke
.
MethodHandles
.
Lookup
.
IMPL_LOOKUP
;
/**
/**
* A {@code CallSite} is a holder for a variable {@link MethodHandle},
* A {@code CallSite} is a holder for a variable {@link MethodHandle},
...
@@ -85,7 +85,6 @@ private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String nam
...
@@ -85,7 +85,6 @@ private static CallSite bootstrapDynamic(MethodHandles.Lookup caller, String nam
*/
*/
abstract
abstract
public
class
CallSite
{
public
class
CallSite
{
private
static
final
Access
IMPL_TOKEN
=
Access
.
getToken
();
static
{
MethodHandleImpl
.
initStatics
();
}
static
{
MethodHandleImpl
.
initStatics
();
}
// Fields used only by the JVM. Do not use or change.
// Fields used only by the JVM. Do not use or change.
...
@@ -96,9 +95,6 @@ public class CallSite {
...
@@ -96,9 +95,6 @@ public class CallSite {
/*package-private*/
/*package-private*/
MethodHandle
target
;
MethodHandle
target
;
// Remove this field for PFD and delete deprecated methods:
private
MemberName
calleeNameRemoveForPFD
;
/**
/**
* Make a blank call site object with the given method type.
* Make a blank call site object with the given method type.
* An initial target method is supplied which will throw
* An initial target method is supplied which will throw
...
@@ -111,7 +107,7 @@ public class CallSite {
...
@@ -111,7 +107,7 @@ public class CallSite {
*/
*/
/*package-private*/
/*package-private*/
CallSite
(
MethodType
type
)
{
CallSite
(
MethodType
type
)
{
target
=
MethodHandles
.
invokers
(
type
).
uninitializedCallSite
();
target
=
type
.
invokers
(
).
uninitializedCallSite
();
}
}
/**
/**
...
@@ -145,7 +141,7 @@ public class CallSite {
...
@@ -145,7 +141,7 @@ public class CallSite {
int
callerBCI
)
{
int
callerBCI
)
{
if
(
this
.
vmmethod
!=
null
)
{
if
(
this
.
vmmethod
!=
null
)
{
// FIXME
// FIXME
throw
new
InvokeDynamicBootstrap
Error
(
"call site has already been linked to an invokedynamic instruction"
);
throw
new
BootstrapMethod
Error
(
"call site has already been linked to an invokedynamic instruction"
);
}
}
if
(!
this
.
type
().
equals
(
type
))
{
if
(!
this
.
type
().
equals
(
type
))
{
throw
wrongTargetType
(
target
,
type
);
throw
wrongTargetType
(
target
,
type
);
...
@@ -202,7 +198,7 @@ public class CallSite {
...
@@ -202,7 +198,7 @@ public class CallSite {
}
}
/**
/**
* Produce a method handle equivalent to an invokedynamic instruction
* Produce
s
a method handle equivalent to an invokedynamic instruction
* which has been linked to this call site.
* which has been linked to this call site.
* <p>
* <p>
* This method is equivalent to the following code:
* This method is equivalent to the following code:
...
@@ -218,7 +214,7 @@ public class CallSite {
...
@@ -218,7 +214,7 @@ public class CallSite {
public
abstract
MethodHandle
dynamicInvoker
();
public
abstract
MethodHandle
dynamicInvoker
();
/*non-public*/
MethodHandle
makeDynamicInvoker
()
{
/*non-public*/
MethodHandle
makeDynamicInvoker
()
{
MethodHandle
getTarget
=
MethodHandleImpl
.
bindReceiver
(
IMPL_TOKEN
,
GET_TARGET
,
this
);
MethodHandle
getTarget
=
MethodHandleImpl
.
bindReceiver
(
GET_TARGET
,
this
);
MethodHandle
invoker
=
MethodHandles
.
exactInvoker
(
this
.
type
());
MethodHandle
invoker
=
MethodHandles
.
exactInvoker
(
this
.
type
());
return
MethodHandles
.
foldArguments
(
invoker
,
getTarget
);
return
MethodHandles
.
foldArguments
(
invoker
,
getTarget
);
}
}
...
@@ -226,7 +222,7 @@ public class CallSite {
...
@@ -226,7 +222,7 @@ public class CallSite {
private
static
final
MethodHandle
GET_TARGET
;
private
static
final
MethodHandle
GET_TARGET
;
static
{
static
{
try
{
try
{
GET_TARGET
=
MethodHandles
.
Lookup
.
IMPL_LOOKUP
.
GET_TARGET
=
IMPL_LOOKUP
.
findVirtual
(
CallSite
.
class
,
"getTarget"
,
MethodType
.
methodType
(
MethodHandle
.
class
));
findVirtual
(
CallSite
.
class
,
"getTarget"
,
MethodType
.
methodType
(
MethodHandle
.
class
));
}
catch
(
ReflectiveOperationException
ignore
)
{
}
catch
(
ReflectiveOperationException
ignore
)
{
throw
new
InternalError
();
throw
new
InternalError
();
...
@@ -252,7 +248,6 @@ public class CallSite {
...
@@ -252,7 +248,6 @@ public class CallSite {
/*package-private*/
/*package-private*/
void
setTargetNormal
(
MethodHandle
newTarget
)
{
void
setTargetNormal
(
MethodHandle
newTarget
)
{
target
=
newTarget
;
target
=
newTarget
;
//CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
}
}
/*package-private*/
/*package-private*/
MethodHandle
getTargetVolatile
()
{
MethodHandle
getTargetVolatile
()
{
...
@@ -261,6 +256,68 @@ public class CallSite {
...
@@ -261,6 +256,68 @@ public class CallSite {
/*package-private*/
/*package-private*/
void
setTargetVolatile
(
MethodHandle
newTarget
)
{
void
setTargetVolatile
(
MethodHandle
newTarget
)
{
unsafe
.
putObjectVolatile
(
this
,
TARGET_OFFSET
,
newTarget
);
unsafe
.
putObjectVolatile
(
this
,
TARGET_OFFSET
,
newTarget
);
//CallSiteImpl.setCallSiteTarget(IMPL_TOKEN, this, newTarget);
}
// this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite:
static
CallSite
makeSite
(
MethodHandle
bootstrapMethod
,
// Callee information:
String
name
,
MethodType
type
,
// Extra arguments for BSM, if any:
Object
info
,
// Caller information:
MemberName
callerMethod
,
int
callerBCI
)
{
Class
<?>
callerClass
=
callerMethod
.
getDeclaringClass
();
Object
caller
=
IMPL_LOOKUP
.
in
(
callerClass
);
CallSite
site
;
try
{
Object
binding
;
info
=
maybeReBox
(
info
);
if
(
info
==
null
)
{
binding
=
bootstrapMethod
.
invokeGeneric
(
caller
,
name
,
type
);
}
else
if
(!
info
.
getClass
().
isArray
())
{
binding
=
bootstrapMethod
.
invokeGeneric
(
caller
,
name
,
type
,
info
);
}
else
{
Object
[]
argv
=
(
Object
[])
info
;
maybeReBoxElements
(
argv
);
if
(
3
+
argv
.
length
>
255
)
throw
new
BootstrapMethodError
(
"too many bootstrap method arguments"
);
MethodType
bsmType
=
bootstrapMethod
.
type
();
if
(
bsmType
.
parameterCount
()
==
4
&&
bsmType
.
parameterType
(
3
)
==
Object
[].
class
)
binding
=
bootstrapMethod
.
invokeGeneric
(
caller
,
name
,
type
,
argv
);
else
binding
=
MethodHandles
.
spreadInvoker
(
bsmType
,
3
)
.
invokeGeneric
(
bootstrapMethod
,
caller
,
name
,
type
,
argv
);
}
//System.out.println("BSM for "+name+type+" => "+binding);
if
(
binding
instanceof
CallSite
)
{
site
=
(
CallSite
)
binding
;
}
else
{
throw
new
ClassCastException
(
"bootstrap method failed to produce a CallSite"
);
}
assert
(
site
.
getTarget
()
!=
null
);
assert
(
site
.
getTarget
().
type
().
equals
(
type
));
}
catch
(
Throwable
ex
)
{
BootstrapMethodError
bex
;
if
(
ex
instanceof
BootstrapMethodError
)
bex
=
(
BootstrapMethodError
)
ex
;
else
bex
=
new
BootstrapMethodError
(
"call site initialization exception"
,
ex
);
throw
bex
;
}
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
;
}
private
static
void
maybeReBoxElements
(
Object
[]
xa
)
{
for
(
int
i
=
0
;
i
<
xa
.
length
;
i
++)
{
xa
[
i
]
=
maybeReBox
(
xa
[
i
]);
}
}
}
}
}
src/share/classes/java/
dyn
/ConstantCallSite.java
→
src/share/classes/java/
lang/invoke
/ConstantCallSite.java
浏览文件 @
33ee9ccf
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
* questions.
* questions.
*/
*/
package
java.
dyn
;
package
java.
lang.invoke
;
/**
/**
* A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
* A {@code ConstantCallSite} is a {@link CallSite} whose target is permanent, and can never be changed.
...
...
src/share/classes/
sun/dyn
/DirectMethodHandle.java
→
src/share/classes/
java/lang/invoke
/DirectMethodHandle.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 20
09
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 20
11
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,10 +23,9 @@
...
@@ -23,10 +23,9 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
java.dyn.*
;
import
static
java
.
lang
.
invoke
.
MethodHandleNatives
.
Constants
.*;
import
static
sun
.
dyn
.
MethodHandleNatives
.
Constants
.*;
/**
/**
* The flavor of method handle which emulates invokespecial or invokestatic.
* The flavor of method handle which emulates invokespecial or invokestatic.
...
@@ -39,7 +38,7 @@ class DirectMethodHandle extends MethodHandle {
...
@@ -39,7 +38,7 @@ class DirectMethodHandle extends MethodHandle {
// Constructors in this class *must* be package scoped or private.
// Constructors in this class *must* be package scoped or private.
DirectMethodHandle
(
MethodType
mtype
,
MemberName
m
,
boolean
doDispatch
,
Class
<?>
lookupClass
)
{
DirectMethodHandle
(
MethodType
mtype
,
MemberName
m
,
boolean
doDispatch
,
Class
<?>
lookupClass
)
{
super
(
Access
.
TOKEN
,
mtype
);
super
(
mtype
);
assert
(
m
.
isMethod
()
||
!
doDispatch
&&
m
.
isConstructor
());
assert
(
m
.
isMethod
()
||
!
doDispatch
&&
m
.
isConstructor
());
if
(!
m
.
isResolved
())
if
(!
m
.
isResolved
())
...
...
src/share/classes/
sun/dyn
/FilterGeneric.java
→
src/share/classes/
java/lang/invoke
/FilterGeneric.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,11 +23,11 @@
...
@@ -23,11 +23,11 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
java.dyn.*
;
import
java.lang.reflect.*
;
import
java.lang.reflect.*
;
import
static
sun
.
dyn
.
MemberName
.
newIllegalArgumentException
;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
import
static
java
.
lang
.
invoke
.
MethodHandles
.
Lookup
.
IMPL_LOOKUP
;
/**
/**
* These adapters apply arbitrary conversions to arguments
* These adapters apply arbitrary conversions to arguments
...
@@ -123,7 +123,7 @@ class FilterGeneric {
...
@@ -123,7 +123,7 @@ class FilterGeneric {
MethodType
entryType
=
entryType
(
kind
,
pos
,
filterType
,
targetType
);
MethodType
entryType
=
entryType
(
kind
,
pos
,
filterType
,
targetType
);
if
(
entryType
.
generic
()
!=
entryType
)
if
(
entryType
.
generic
()
!=
entryType
)
throw
newIllegalArgumentException
(
"must be generic: "
+
entryType
);
throw
newIllegalArgumentException
(
"must be generic: "
+
entryType
);
MethodType
Impl
form
=
MethodTypeImpl
.
of
(
entryType
);
MethodType
Form
form
=
entryType
.
form
(
);
FilterGeneric
filterGen
=
form
.
filterGeneric
;
FilterGeneric
filterGen
=
form
.
filterGeneric
;
if
(
filterGen
==
null
)
if
(
filterGen
==
null
)
form
.
filterGeneric
=
filterGen
=
new
FilterGeneric
(
entryType
);
form
.
filterGeneric
=
filterGen
=
new
FilterGeneric
(
entryType
);
...
@@ -186,7 +186,7 @@ class FilterGeneric {
...
@@ -186,7 +186,7 @@ class FilterGeneric {
// see if it has the required invoke method
// see if it has the required invoke method
MethodHandle
entryPoint
=
null
;
MethodHandle
entryPoint
=
null
;
try
{
try
{
entryPoint
=
MethodHandleImpl
.
IMPL_LOOKUP
.
findSpecial
(
acls
,
iname
,
entryType
,
acls
);
entryPoint
=
IMPL_LOOKUP
.
findSpecial
(
acls
,
iname
,
entryType
,
acls
);
}
catch
(
ReflectiveOperationException
ex
)
{
}
catch
(
ReflectiveOperationException
ex
)
{
}
}
if
(
entryPoint
==
null
)
continue
;
if
(
entryPoint
==
null
)
continue
;
...
@@ -231,7 +231,7 @@ class FilterGeneric {
...
@@ -231,7 +231,7 @@ class FilterGeneric {
@Override
@Override
public
String
toString
()
{
public
String
toString
()
{
return
MethodHandleImpl
.
addTypeString
(
target
,
this
);
return
addTypeString
(
target
,
this
);
}
}
protected
boolean
isPrototype
()
{
return
target
==
null
;
}
protected
boolean
isPrototype
()
{
return
target
==
null
;
}
...
@@ -246,7 +246,7 @@ class FilterGeneric {
...
@@ -246,7 +246,7 @@ class FilterGeneric {
protected
Adapter
(
MethodHandle
entryPoint
,
protected
Adapter
(
MethodHandle
entryPoint
,
MethodHandle
filter
,
MethodHandle
target
)
{
MethodHandle
filter
,
MethodHandle
target
)
{
super
(
Access
.
TOKEN
,
entryPoint
);
super
(
entryPoint
);
this
.
filter
=
filter
;
this
.
filter
=
filter
;
this
.
target
=
target
;
this
.
target
=
target
;
}
}
...
@@ -256,7 +256,7 @@ class FilterGeneric {
...
@@ -256,7 +256,7 @@ class FilterGeneric {
MethodHandle
filter
,
MethodHandle
target
);
MethodHandle
filter
,
MethodHandle
target
);
// { return new ThisType(entryPoint, filter, target); }
// { return new ThisType(entryPoint, filter, target); }
static
private
final
String
CLASS_PREFIX
;
// "
sun.dyn
.FilterGeneric$"
static
private
final
String
CLASS_PREFIX
;
// "
java.lang.invoke
.FilterGeneric$"
static
{
static
{
String
aname
=
Adapter
.
class
.
getName
();
String
aname
=
Adapter
.
class
.
getName
();
String
sname
=
Adapter
.
class
.
getSimpleName
();
String
sname
=
Adapter
.
class
.
getSimpleName
();
...
...
src/share/classes/
sun/dyn
/FilterOneArgument.java
→
src/share/classes/
java/lang/invoke
/FilterOneArgument.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,10 +23,10 @@
...
@@ -23,10 +23,10 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
java.dyn
.*
;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
import
static
sun
.
dyn
.
MemberName
.
uncaughtException
;
import
static
java
.
lang
.
invoke
.
MethodHandles
.
Lookup
.
IMPL_LOOKUP
;
/**
/**
* Unary function composition, useful for many small plumbing jobs.
* Unary function composition, useful for many small plumbing jobs.
...
@@ -36,7 +36,7 @@ import static sun.dyn.MemberName.uncaughtException;
...
@@ -36,7 +36,7 @@ import static sun.dyn.MemberName.uncaughtException;
* final method type is the responsibility of a JVM-level adapter.
* final method type is the responsibility of a JVM-level adapter.
* @author jrose
* @author jrose
*/
*/
public
class
FilterOneArgument
extends
BoundMethodHandle
{
class
FilterOneArgument
extends
BoundMethodHandle
{
protected
final
MethodHandle
filter
;
// Object -> Object
protected
final
MethodHandle
filter
;
// Object -> Object
protected
final
MethodHandle
target
;
// Object -> Object
protected
final
MethodHandle
target
;
// Object -> Object
...
@@ -54,15 +54,15 @@ public class FilterOneArgument extends BoundMethodHandle {
...
@@ -54,15 +54,15 @@ public class FilterOneArgument extends BoundMethodHandle {
static
{
static
{
try
{
try
{
INVOKE
=
INVOKE
=
MethodHandleImpl
.
IMPL_LOOKUP
.
findVirtual
(
FilterOneArgument
.
class
,
"invoke"
,
IMPL_LOOKUP
.
findVirtual
(
FilterOneArgument
.
class
,
"invoke"
,
MethodType
.
genericMethodType
(
1
));
MethodType
.
genericMethodType
(
1
));
}
catch
(
ReflectiveOperationException
ex
)
{
}
catch
(
ReflectiveOperationException
ex
)
{
throw
uncaughtException
(
ex
);
throw
uncaughtException
(
ex
);
}
}
}
}
protected
FilterOneArgument
(
MethodHandle
filter
,
MethodHandle
target
)
{
protected
FilterOneArgument
(
MethodHandle
filter
,
MethodHandle
target
)
{
super
(
Access
.
TOKEN
,
INVOKE
);
super
(
INVOKE
);
this
.
filter
=
filter
;
this
.
filter
=
filter
;
this
.
target
=
target
;
this
.
target
=
target
;
}
}
...
...
src/share/classes/
sun/dyn
/FromGeneric.java
→
src/share/classes/
java/lang/invoke
/FromGeneric.java
浏览文件 @
33ee9ccf
...
@@ -23,12 +23,13 @@
...
@@ -23,12 +23,13 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
java.dyn.*
;
import
sun.invoke.util.ValueConversions
;
import
sun.invoke.util.Wrapper
;
import
java.lang.reflect.*
;
import
java.lang.reflect.*
;
import
s
un.dyn.util
.*
;
import
s
tatic
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
import
static
sun
.
dyn
.
MethodTypeImpl
.
invokers
;
import
static
java
.
lang
.
invoke
.
MethodHandles
.
Lookup
.
IMPL_LOOKUP
;
/**
/**
* Adapters which mediate between incoming calls which are generic
* Adapters which mediate between incoming calls which are generic
...
@@ -82,8 +83,8 @@ class FromGeneric {
...
@@ -82,8 +83,8 @@ class FromGeneric {
}
}
// outgoing primitive arguments will be wrapped; unwrap them
// outgoing primitive arguments will be wrapped; unwrap them
MethodType
primsAsObj
=
MethodTypeImpl
.
of
(
targetType
).
primArgsAsBoxes
();
MethodType
primsAsObj
=
targetType
.
form
(
).
primArgsAsBoxes
();
MethodType
objArgsRawRet
=
MethodTypeImpl
.
of
(
primsAsObj
).
primsAsInts
();
MethodType
objArgsRawRet
=
primsAsObj
.
form
(
).
primsAsInts
();
if
(
objArgsRawRet
!=
targetType
)
if
(
objArgsRawRet
!=
targetType
)
ad
=
findAdapter
(
internalType0
=
objArgsRawRet
);
ad
=
findAdapter
(
internalType0
=
objArgsRawRet
);
if
(
ad
==
null
)
{
if
(
ad
==
null
)
{
...
@@ -129,16 +130,16 @@ class FromGeneric {
...
@@ -129,16 +130,16 @@ class FromGeneric {
MethodType
targetType
,
MethodType
internalType
)
{
MethodType
targetType
,
MethodType
internalType
)
{
// All the adapters we have here have reference-untyped internal calls.
// All the adapters we have here have reference-untyped internal calls.
assert
(
internalType
==
internalType
.
erase
());
assert
(
internalType
==
internalType
.
erase
());
MethodHandle
invoker
=
invokers
(
targetType
).
exactInvoker
();
MethodHandle
invoker
=
targetType
.
invokers
(
).
exactInvoker
();
// cast all narrow reference types, unbox all primitive arguments:
// cast all narrow reference types, unbox all primitive arguments:
MethodType
fixArgsType
=
internalType
.
changeReturnType
(
targetType
.
returnType
());
MethodType
fixArgsType
=
internalType
.
changeReturnType
(
targetType
.
returnType
());
MethodHandle
fixArgs
=
AdapterMethodHandle
.
convertArguments
(
Access
.
TOKEN
,
MethodHandle
fixArgs
=
MethodHandleImpl
.
convertArguments
(
invoker
,
Invokers
.
invokerType
(
fixArgsType
),
invoker
,
Invokers
.
invokerType
(
fixArgsType
),
invoker
.
type
(),
null
);
invoker
.
type
(),
null
);
if
(
fixArgs
==
null
)
if
(
fixArgs
==
null
)
throw
new
InternalError
(
"bad fixArgs"
);
throw
new
InternalError
(
"bad fixArgs"
);
// reinterpret the calling sequence as raw:
// reinterpret the calling sequence as raw:
MethodHandle
retyper
=
AdapterMethodHandle
.
makeRetypeRaw
(
Access
.
TOKEN
,
MethodHandle
retyper
=
AdapterMethodHandle
.
makeRetypeRaw
(
Invokers
.
invokerType
(
internalType
),
fixArgs
);
Invokers
.
invokerType
(
internalType
),
fixArgs
);
if
(
retyper
==
null
)
if
(
retyper
==
null
)
throw
new
InternalError
(
"bad retyper"
);
throw
new
InternalError
(
"bad retyper"
);
...
@@ -171,7 +172,7 @@ class FromGeneric {
...
@@ -171,7 +172,7 @@ class FromGeneric {
/** Return the adapter information for this type's erasure. */
/** Return the adapter information for this type's erasure. */
static
FromGeneric
of
(
MethodType
type
)
{
static
FromGeneric
of
(
MethodType
type
)
{
MethodType
Impl
form
=
MethodTypeImpl
.
of
(
type
);
MethodType
Form
form
=
type
.
form
(
);
FromGeneric
fromGen
=
form
.
fromGeneric
;
FromGeneric
fromGen
=
form
.
fromGeneric
;
if
(
fromGen
==
null
)
if
(
fromGen
==
null
)
form
.
fromGeneric
=
fromGen
=
new
FromGeneric
(
form
.
erasedType
());
form
.
fromGeneric
=
fromGen
=
new
FromGeneric
(
form
.
erasedType
());
...
@@ -185,7 +186,7 @@ class FromGeneric {
...
@@ -185,7 +186,7 @@ class FromGeneric {
/* Create an adapter that handles spreading calls for the given type. */
/* Create an adapter that handles spreading calls for the given type. */
static
Adapter
findAdapter
(
MethodType
internalType
)
{
static
Adapter
findAdapter
(
MethodType
internalType
)
{
MethodType
entryType
=
internalType
.
generic
();
MethodType
entryType
=
internalType
.
generic
();
MethodType
Impl
form
=
MethodTypeImpl
.
of
(
internalType
);
MethodType
Form
form
=
internalType
.
form
(
);
Class
<?>
rtype
=
internalType
.
returnType
();
Class
<?>
rtype
=
internalType
.
returnType
();
int
argc
=
form
.
parameterCount
();
int
argc
=
form
.
parameterCount
();
int
lac
=
form
.
longPrimitiveParameterCount
();
int
lac
=
form
.
longPrimitiveParameterCount
();
...
@@ -203,7 +204,7 @@ class FromGeneric {
...
@@ -203,7 +204,7 @@ class FromGeneric {
// see if it has the required invoke method
// see if it has the required invoke method
MethodHandle
entryPoint
=
null
;
MethodHandle
entryPoint
=
null
;
try
{
try
{
entryPoint
=
MethodHandleImpl
.
IMPL_LOOKUP
.
findSpecial
(
acls
,
iname
,
entryType
,
acls
);
entryPoint
=
IMPL_LOOKUP
.
findSpecial
(
acls
,
iname
,
entryType
,
acls
);
}
catch
(
ReflectiveOperationException
ex
)
{
}
catch
(
ReflectiveOperationException
ex
)
{
}
}
if
(
entryPoint
==
null
)
continue
;
if
(
entryPoint
==
null
)
continue
;
...
@@ -257,7 +258,7 @@ class FromGeneric {
...
@@ -257,7 +258,7 @@ class FromGeneric {
@Override
@Override
public
String
toString
()
{
public
String
toString
()
{
return
MethodHandleImpl
.
addTypeString
(
target
,
this
);
return
addTypeString
(
target
,
this
);
}
}
protected
boolean
isPrototype
()
{
return
target
==
null
;
}
protected
boolean
isPrototype
()
{
return
target
==
null
;
}
...
@@ -272,7 +273,7 @@ class FromGeneric {
...
@@ -272,7 +273,7 @@ class FromGeneric {
protected
Adapter
(
MethodHandle
entryPoint
,
protected
Adapter
(
MethodHandle
entryPoint
,
MethodHandle
invoker
,
MethodHandle
convert
,
MethodHandle
target
)
{
MethodHandle
invoker
,
MethodHandle
convert
,
MethodHandle
target
)
{
super
(
Access
.
TOKEN
,
entryPoint
);
super
(
entryPoint
);
this
.
invoker
=
invoker
;
this
.
invoker
=
invoker
;
this
.
convert
=
convert
;
this
.
convert
=
convert
;
this
.
target
=
target
;
this
.
target
=
target
;
...
@@ -290,7 +291,7 @@ class FromGeneric {
...
@@ -290,7 +291,7 @@ class FromGeneric {
protected
Object
convert_F
(
float
result
)
throws
Throwable
{
return
convert
.
invokeExact
(
result
);
}
protected
Object
convert_F
(
float
result
)
throws
Throwable
{
return
convert
.
invokeExact
(
result
);
}
protected
Object
convert_D
(
double
result
)
throws
Throwable
{
return
convert
.
invokeExact
(
result
);
}
protected
Object
convert_D
(
double
result
)
throws
Throwable
{
return
convert
.
invokeExact
(
result
);
}
static
private
final
String
CLASS_PREFIX
;
// "
sun.dyn
.FromGeneric$"
static
private
final
String
CLASS_PREFIX
;
// "
java.lang.invoke
.FromGeneric$"
static
{
static
{
String
aname
=
Adapter
.
class
.
getName
();
String
aname
=
Adapter
.
class
.
getName
();
String
sname
=
Adapter
.
class
.
getSimpleName
();
String
sname
=
Adapter
.
class
.
getSimpleName
();
...
...
src/share/classes/java/
dyn
/InvokeDynamic.java
→
src/share/classes/java/
lang/invoke
/InvokeDynamic.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
* questions.
* questions.
*/
*/
package
java.
dyn
;
package
java.
lang.invoke
;
/**
/**
* This is a place-holder class. Some HotSpot implementations need to see it.
* This is a place-holder class. Some HotSpot implementations need to see it.
...
...
src/share/classes/
sun/dyn
/InvokeGeneric.java
→
src/share/classes/
java/lang/invoke
/InvokeGeneric.java
浏览文件 @
33ee9ccf
...
@@ -23,15 +23,13 @@
...
@@ -23,15 +23,13 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
java.dyn.*
;
import
sun.invoke.util.*
;
import
java.lang.reflect.*
;
import
static
java
.
lang
.
invoke
.
MethodHandles
.
Lookup
.
IMPL_LOOKUP
;
import
sun.dyn.util.*
;
import
static
sun
.
dyn
.
MethodTypeImpl
.
invokers
;
/**
/**
* Adapters which manage MethodHan
n
dle.invokeGeneric calls.
* Adapters which manage MethodHandle.invokeGeneric calls.
* The JVM calls one of these when the exact type match fails.
* The JVM calls one of these when the exact type match fails.
* @author jrose
* @author jrose
*/
*/
...
@@ -44,7 +42,8 @@ class InvokeGeneric {
...
@@ -44,7 +42,8 @@ class InvokeGeneric {
/** Compute and cache information for this adapter, so that it can
/** Compute and cache information for this adapter, so that it can
* call out to targets of the erasure-family of the given erased type.
* call out to targets of the erasure-family of the given erased type.
*/
*/
private
InvokeGeneric
(
MethodType
erasedCallerType
)
throws
ReflectiveOperationException
{
/*non-public*/
InvokeGeneric
(
MethodType
erasedCallerType
)
throws
ReflectiveOperationException
{
assert
(
erasedCallerType
.
equals
(
erasedCallerType
.
erase
()));
this
.
erasedCallerType
=
erasedCallerType
;
this
.
erasedCallerType
=
erasedCallerType
;
this
.
initialInvoker
=
makeInitialInvoker
();
this
.
initialInvoker
=
makeInitialInvoker
();
assert
initialInvoker
.
type
().
equals
(
erasedCallerType
assert
initialInvoker
.
type
().
equals
(
erasedCallerType
...
@@ -53,22 +52,13 @@ class InvokeGeneric {
...
@@ -53,22 +52,13 @@ class InvokeGeneric {
}
}
private
static
MethodHandles
.
Lookup
lookup
()
{
private
static
MethodHandles
.
Lookup
lookup
()
{
return
MethodHandleImpl
.
IMPL_LOOKUP
;
return
IMPL_LOOKUP
;
}
}
/** Return the adapter information for this type's erasure. */
/** Return the adapter information for this type's erasure. */
static
MethodHandle
genericInvokerOf
(
MethodType
type
)
{
/*non-public*/
static
MethodHandle
genericInvokerOf
(
MethodType
erasedCallerType
)
throws
ReflectiveOperationException
{
MethodTypeImpl
form
=
MethodTypeImpl
.
of
(
type
);
InvokeGeneric
gen
=
new
InvokeGeneric
(
erasedCallerType
);
MethodHandle
genericInvoker
=
form
.
genericInvoker
;
return
gen
.
initialInvoker
;
if
(
genericInvoker
==
null
)
{
try
{
InvokeGeneric
gen
=
new
InvokeGeneric
(
form
.
erasedType
());
form
.
genericInvoker
=
genericInvoker
=
gen
.
initialInvoker
;
}
catch
(
ReflectiveOperationException
ex
)
{
throw
new
RuntimeException
(
ex
);
}
}
return
genericInvoker
;
}
}
private
MethodHandle
makeInitialInvoker
()
throws
ReflectiveOperationException
{
private
MethodHandle
makeInitialInvoker
()
throws
ReflectiveOperationException
{
...
@@ -88,7 +78,7 @@ class InvokeGeneric {
...
@@ -88,7 +78,7 @@ class InvokeGeneric {
private
MethodHandle
makePostDispatchInvoker
()
{
private
MethodHandle
makePostDispatchInvoker
()
{
// Take (MH'; MT, MH; A...) and run MH'(MT, MH; A...).
// Take (MH'; MT, MH; A...) and run MH'(MT, MH; A...).
MethodType
invokerType
=
erasedCallerType
.
insertParameterTypes
(
0
,
EXTRA_ARGS
);
MethodType
invokerType
=
erasedCallerType
.
insertParameterTypes
(
0
,
EXTRA_ARGS
);
return
invoker
s
(
invokerType
).
exactInvoker
();
return
invoker
Type
.
invokers
(
).
exactInvoker
();
}
}
private
MethodHandle
dropDispatchArguments
(
MethodHandle
targetInvoker
)
{
private
MethodHandle
dropDispatchArguments
(
MethodHandle
targetInvoker
)
{
assert
(
targetInvoker
.
type
().
parameterType
(
0
)
==
MethodHandle
.
class
);
assert
(
targetInvoker
.
type
().
parameterType
(
0
)
==
MethodHandle
.
class
);
...
@@ -112,7 +102,7 @@ class InvokeGeneric {
...
@@ -112,7 +102,7 @@ class InvokeGeneric {
if
(
USE_AS_TYPE_PATH
||
target
.
isVarargsCollector
())
{
if
(
USE_AS_TYPE_PATH
||
target
.
isVarargsCollector
())
{
MethodHandle
newTarget
=
target
.
asType
(
callerType
);
MethodHandle
newTarget
=
target
.
asType
(
callerType
);
targetType
=
callerType
;
targetType
=
callerType
;
Invokers
invokers
=
MethodTypeImpl
.
invokers
(
Access
.
TOKEN
,
targetType
);
Invokers
invokers
=
targetType
.
invokers
(
);
MethodHandle
invoker
=
invokers
.
erasedInvokerWithDrops
;
MethodHandle
invoker
=
invokers
.
erasedInvokerWithDrops
;
if
(
invoker
==
null
)
{
if
(
invoker
==
null
)
{
invokers
.
erasedInvokerWithDrops
=
invoker
=
invokers
.
erasedInvokerWithDrops
=
invoker
=
...
...
src/share/classes/
sun/dyn
/Invokers.java
→
src/share/classes/
java/lang/invoke
/Invokers.java
浏览文件 @
33ee9ccf
...
@@ -23,16 +23,16 @@
...
@@ -23,16 +23,16 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
java.dyn.*
;
import
sun.invoke.empty.Empty
;
import
s
un.dyn.empty.Empty
;
import
s
tatic
java
.
lang
.
invoke
.
MethodHandles
.
Lookup
.
IMPL_LOOKUP
;
/**
/**
* Construction and caching of often-used invokers.
* Construction and caching of often-used invokers.
* @author jrose
* @author jrose
*/
*/
public
class
Invokers
{
class
Invokers
{
// exact type (sans leading taget MH) for the outgoing call
// exact type (sans leading taget MH) for the outgoing call
private
final
MethodType
targetType
;
private
final
MethodType
targetType
;
...
@@ -60,15 +60,15 @@ public class Invokers {
...
@@ -60,15 +60,15 @@ public class Invokers {
this
.
spreadInvokers
=
new
MethodHandle
[
targetType
.
parameterCount
()+
1
];
this
.
spreadInvokers
=
new
MethodHandle
[
targetType
.
parameterCount
()+
1
];
}
}
public
static
MethodType
invokerType
(
MethodType
targetType
)
{
/*non-public*/
static
MethodType
invokerType
(
MethodType
targetType
)
{
return
targetType
.
insertParameterTypes
(
0
,
MethodHandle
.
class
);
return
targetType
.
insertParameterTypes
(
0
,
MethodHandle
.
class
);
}
}
public
MethodHandle
exactInvoker
()
{
/*non-public*/
MethodHandle
exactInvoker
()
{
MethodHandle
invoker
=
exactInvoker
;
MethodHandle
invoker
=
exactInvoker
;
if
(
invoker
!=
null
)
return
invoker
;
if
(
invoker
!=
null
)
return
invoker
;
try
{
try
{
invoker
=
MethodHandleImpl
.
IMPL_LOOKUP
.
findVirtual
(
MethodHandle
.
class
,
"invokeExact"
,
targetType
);
invoker
=
IMPL_LOOKUP
.
findVirtual
(
MethodHandle
.
class
,
"invokeExact"
,
targetType
);
}
catch
(
ReflectiveOperationException
ex
)
{
}
catch
(
ReflectiveOperationException
ex
)
{
throw
new
InternalError
(
"JVM cannot find invoker for "
+
targetType
);
throw
new
InternalError
(
"JVM cannot find invoker for "
+
targetType
);
}
}
...
@@ -77,7 +77,7 @@ public class Invokers {
...
@@ -77,7 +77,7 @@ public class Invokers {
return
invoker
;
return
invoker
;
}
}
public
MethodHandle
genericInvoker
()
{
/*non-public*/
MethodHandle
genericInvoker
()
{
MethodHandle
invoker1
=
exactInvoker
();
MethodHandle
invoker1
=
exactInvoker
();
MethodHandle
invoker
=
genericInvoker
;
MethodHandle
invoker
=
genericInvoker
;
if
(
invoker
!=
null
)
return
invoker
;
if
(
invoker
!=
null
)
return
invoker
;
...
@@ -87,7 +87,7 @@ public class Invokers {
...
@@ -87,7 +87,7 @@ public class Invokers {
return
invoker
;
return
invoker
;
}
}
public
MethodHandle
erasedInvoker
()
{
/*non-public*/
MethodHandle
erasedInvoker
()
{
MethodHandle
invoker1
=
exactInvoker
();
MethodHandle
invoker1
=
exactInvoker
();
MethodHandle
invoker
=
erasedInvoker
;
MethodHandle
invoker
=
erasedInvoker
;
if
(
invoker
!=
null
)
return
invoker
;
if
(
invoker
!=
null
)
return
invoker
;
...
@@ -100,7 +100,7 @@ public class Invokers {
...
@@ -100,7 +100,7 @@ public class Invokers {
return
invoker
;
return
invoker
;
}
}
public
MethodHandle
spreadInvoker
(
int
objectArgCount
)
{
/*non-public*/
MethodHandle
spreadInvoker
(
int
objectArgCount
)
{
MethodHandle
vaInvoker
=
spreadInvokers
[
objectArgCount
];
MethodHandle
vaInvoker
=
spreadInvokers
[
objectArgCount
];
if
(
vaInvoker
!=
null
)
return
vaInvoker
;
if
(
vaInvoker
!=
null
)
return
vaInvoker
;
MethodHandle
gInvoker
=
genericInvoker
();
MethodHandle
gInvoker
=
genericInvoker
();
...
@@ -111,12 +111,12 @@ public class Invokers {
...
@@ -111,12 +111,12 @@ public class Invokers {
private
static
MethodHandle
THROW_UCS
=
null
;
private
static
MethodHandle
THROW_UCS
=
null
;
public
MethodHandle
uninitializedCallSite
()
{
/*non-public*/
MethodHandle
uninitializedCallSite
()
{
MethodHandle
invoker
=
uninitializedCallSite
;
MethodHandle
invoker
=
uninitializedCallSite
;
if
(
invoker
!=
null
)
return
invoker
;
if
(
invoker
!=
null
)
return
invoker
;
if
(
targetType
.
parameterCount
()
>
0
)
{
if
(
targetType
.
parameterCount
()
>
0
)
{
MethodType
type0
=
targetType
.
dropParameterTypes
(
0
,
targetType
.
parameterCount
());
MethodType
type0
=
targetType
.
dropParameterTypes
(
0
,
targetType
.
parameterCount
());
Invokers
invokers0
=
MethodTypeImpl
.
invokers
(
type0
);
Invokers
invokers0
=
type0
.
invokers
(
);
invoker
=
MethodHandles
.
dropArguments
(
invokers0
.
uninitializedCallSite
(),
invoker
=
MethodHandles
.
dropArguments
(
invokers0
.
uninitializedCallSite
(),
0
,
targetType
.
parameterList
());
0
,
targetType
.
parameterList
());
assert
(
invoker
.
type
().
equals
(
targetType
));
assert
(
invoker
.
type
().
equals
(
targetType
));
...
@@ -125,14 +125,14 @@ public class Invokers {
...
@@ -125,14 +125,14 @@ public class Invokers {
}
}
if
(
THROW_UCS
==
null
)
{
if
(
THROW_UCS
==
null
)
{
try
{
try
{
THROW_UCS
=
MethodHandleImpl
.
IMPL_LOOKUP
THROW_UCS
=
IMPL_LOOKUP
.
findStatic
(
CallSite
.
class
,
"uninitializedCallSite"
,
.
findStatic
(
CallSite
.
class
,
"uninitializedCallSite"
,
MethodType
.
methodType
(
Empty
.
class
));
MethodType
.
methodType
(
Empty
.
class
));
}
catch
(
ReflectiveOperationException
ex
)
{
}
catch
(
ReflectiveOperationException
ex
)
{
throw
new
RuntimeException
(
ex
);
throw
new
RuntimeException
(
ex
);
}
}
}
}
invoker
=
AdapterMethodHandle
.
makeRetypeRaw
(
Access
.
TOKEN
,
targetType
,
THROW_UCS
);
invoker
=
AdapterMethodHandle
.
makeRetypeRaw
(
targetType
,
THROW_UCS
);
assert
(
invoker
.
type
().
equals
(
targetType
));
assert
(
invoker
.
type
().
equals
(
targetType
));
uninitializedCallSite
=
invoker
;
uninitializedCallSite
=
invoker
;
return
invoker
;
return
invoker
;
...
...
src/share/classes/
sun/dyn
/MemberName.java
→
src/share/classes/
java/lang/invoke
/MemberName.java
浏览文件 @
33ee9ccf
...
@@ -23,10 +23,9 @@
...
@@ -23,10 +23,9 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
sun.dyn.util.BytecodeDescriptor
;
import
sun.invoke.util.BytecodeDescriptor
;
import
java.dyn.*
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Method
;
...
@@ -37,7 +36,8 @@ import java.util.Arrays;
...
@@ -37,7 +36,8 @@ import java.util.Arrays;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.Iterator
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.List
;
import
static
sun
.
dyn
.
MethodHandleNatives
.
Constants
.*;
import
static
java
.
lang
.
invoke
.
MethodHandleNatives
.
Constants
.*;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
/**
/**
* A {@code MemberName} is a compact symbolic datum which fully characterizes
* A {@code MemberName} is a compact symbolic datum which fully characterizes
...
@@ -66,7 +66,7 @@ import static sun.dyn.MethodHandleNatives.Constants.*;
...
@@ -66,7 +66,7 @@ import static sun.dyn.MethodHandleNatives.Constants.*;
* and those seven fields omit much of the information in Method.
* and those seven fields omit much of the information in Method.
* @author jrose
* @author jrose
*/
*/
public
final
class
MemberName
implements
Member
,
Cloneable
{
/*non-public*/
final
class
MemberName
implements
Member
,
Cloneable
{
private
Class
<?>
clazz
;
// class in which the method is defined
private
Class
<?>
clazz
;
// class in which the method is defined
private
String
name
;
// may be null if not yet materialized
private
String
name
;
// may be null if not yet materialized
private
Object
type
;
// may be null if not yet materialized
private
Object
type
;
// may be null if not yet materialized
...
@@ -435,7 +435,7 @@ public final class MemberName implements Member, Cloneable {
...
@@ -435,7 +435,7 @@ public final class MemberName implements Member, Cloneable {
/** Query whether this member name is resolved to a non-static, non-final method.
/** Query whether this member name is resolved to a non-static, non-final method.
*/
*/
public
boolean
hasReceiverTypeDispatch
()
{
public
boolean
hasReceiverTypeDispatch
()
{
return
(
isMethod
()
&&
getVMIndex
(
Access
.
TOKEN
)
>=
0
);
return
(
isMethod
()
&&
getVMIndex
()
>=
0
);
}
}
/** Produce a string form of this member name.
/** Produce a string form of this member name.
...
@@ -490,59 +490,38 @@ public final class MemberName implements Member, Cloneable {
...
@@ -490,59 +490,38 @@ public final class MemberName implements Member, Cloneable {
// Queries to the JVM:
// Queries to the JVM:
/** Document? */
/** Document? */
public
int
getVMIndex
(
Access
token
)
{
/*non-public*/
int
getVMIndex
()
{
Access
.
check
(
token
);
if
(!
isResolved
())
if
(!
isResolved
())
throw
newIllegalStateException
(
"not resolved"
);
throw
newIllegalStateException
(
"not resolved"
,
this
);
return
vmindex
;
return
vmindex
;
}
}
// public Object getVMTarget(Access token) {
// /*non-public*/ Object getVMTarget() {
// Access.check(token);
// if (!isResolved())
// if (!isResolved())
// throw newIllegalStateException("not resolved");
// throw newIllegalStateException("not resolved"
, this
);
// return vmtarget;
// return vmtarget;
// }
// }
private
RuntimeException
newIllegalStateException
(
String
message
)
{
return
new
IllegalStateException
(
message
+
": "
+
this
);
}
// handy shared exception makers (they simplify the common case code)
public
IllegalAccessException
makeAccessException
(
String
message
,
Object
from
)
{
public
static
RuntimeException
newIllegalArgumentException
(
String
message
)
{
message
=
message
+
": "
+
toString
();
return
new
IllegalArgumentException
(
message
);
}
public
static
IllegalAccessException
newNoAccessException
(
MemberName
name
,
Object
from
)
{
return
newNoAccessException
(
"cannot access"
,
name
,
from
);
}
public
static
IllegalAccessException
newNoAccessException
(
String
message
,
MemberName
name
,
Object
from
)
{
message
+=
": "
+
name
;
if
(
from
!=
null
)
message
+=
", from "
+
from
;
if
(
from
!=
null
)
message
+=
", from "
+
from
;
return
new
IllegalAccessException
(
message
);
return
new
IllegalAccessException
(
message
);
}
}
public
static
ReflectiveOperationException
newNoAccessException
(
MemberName
name
)
{
public
ReflectiveOperationException
makeAccessException
(
String
message
)
{
if
(
name
.
isResolved
())
message
=
message
+
": "
+
toString
();
return
new
IllegalAccessException
(
name
.
toString
());
if
(
isResolved
())
else
if
(
name
.
isConstructor
())
return
new
IllegalAccessException
(
message
);
return
new
NoSuchMethodException
(
name
.
toString
());
else
if
(
isConstructor
())
else
if
(
name
.
isMethod
())
return
new
NoSuchMethodException
(
message
);
return
new
NoSuchMethodException
(
name
.
toString
());
else
if
(
isMethod
())
return
new
NoSuchMethodException
(
message
);
else
else
return
new
NoSuchFieldException
(
name
.
toString
());
return
new
NoSuchFieldException
(
message
);
}
public
static
Error
uncaughtException
(
Exception
ex
)
{
Error
err
=
new
InternalError
(
"uncaught exception"
);
err
.
initCause
(
ex
);
return
err
;
}
}
/** Actually making a query requires an access check. */
/** Actually making a query requires an access check. */
public
static
Factory
getFactory
(
Access
token
)
{
/*non-public*/
static
Factory
getFactory
()
{
Access
.
check
(
token
);
return
Factory
.
INSTANCE
;
return
Factory
.
INSTANCE
;
}
}
public
static
Factory
getFactory
()
{
return
getFactory
(
Access
.
getToken
());
}
/** A factory type for resolving member names with the help of the VM.
/** A factory type for resolving member names with the help of the VM.
* TBD: Define access-safe public constructors for this factory.
* TBD: Define access-safe public constructors for this factory.
*/
*/
...
@@ -662,7 +641,7 @@ public final class MemberName implements Member, Cloneable {
...
@@ -662,7 +641,7 @@ public final class MemberName implements Member, Cloneable {
MemberName
result
=
resolveOrNull
(
m
,
searchSupers
,
lookupClass
);
MemberName
result
=
resolveOrNull
(
m
,
searchSupers
,
lookupClass
);
if
(
result
!=
null
)
if
(
result
!=
null
)
return
result
;
return
result
;
ReflectiveOperationException
ex
=
newNoAccessException
(
m
);
ReflectiveOperationException
ex
=
m
.
makeAccessException
(
"no access"
);
if
(
ex
instanceof
IllegalAccessException
)
throw
(
IllegalAccessException
)
ex
;
if
(
ex
instanceof
IllegalAccessException
)
throw
(
IllegalAccessException
)
ex
;
throw
nsmClass
.
cast
(
ex
);
throw
nsmClass
.
cast
(
ex
);
}
}
...
...
src/share/classes/java/
dyn
/MethodHandle.java
→
src/share/classes/java/
lang/invoke
/MethodHandle.java
浏览文件 @
33ee9ccf
...
@@ -23,15 +23,10 @@
...
@@ -23,15 +23,10 @@
* questions.
* questions.
*/
*/
package
java.
dyn
;
package
java.
lang.invoke
;
//import sun.dyn.*;
import
sun.dyn.Access
;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
import
sun.dyn.MethodHandleImpl
;
import
static
java
.
dyn
.
MethodHandles
.
invokers
;
// package-private API
import
static
sun
.
dyn
.
MemberName
.
newIllegalArgumentException
;
// utility
/**
/**
* A method handle is a typed, directly executable reference to an underlying method,
* A method handle is a typed, directly executable reference to an underlying method,
...
@@ -40,14 +35,8 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
...
@@ -40,14 +35,8 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
* These transformations are quite general, and include such patterns as
* These transformations are quite general, and include such patterns as
* {@linkplain #asType conversion},
* {@linkplain #asType conversion},
* {@linkplain #bindTo insertion},
* {@linkplain #bindTo insertion},
* {@linkplain java.dyn.MethodHandles#dropArguments deletion},
* {@linkplain java.lang.invoke.MethodHandles#dropArguments deletion},
* and {@linkplain java.dyn.MethodHandles#filterArguments substitution}.
* and {@linkplain java.lang.invoke.MethodHandles#filterArguments substitution}.
* <p>
* <em>Note: The super-class of MethodHandle is Object.
* Any other super-class visible in the Reference Implementation
* will be removed before the Proposed Final Draft.
* Also, the final version will not include any public or
* protected constructors.</em>
*
*
* <h3>Method handle contents</h3>
* <h3>Method handle contents</h3>
* Method handles are dynamically and strongly typed according to type descriptor.
* Method handles are dynamically and strongly typed according to type descriptor.
...
@@ -56,7 +45,7 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
...
@@ -56,7 +45,7 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
* the method handle's own {@linkplain #type method type}.
* the method handle's own {@linkplain #type method type}.
* <p>
* <p>
* Every method handle reports its type via the {@link #type type} accessor.
* Every method handle reports its type via the {@link #type type} accessor.
* This type descriptor is a {@link java.
dyn
.MethodType MethodType} object,
* This type descriptor is a {@link java.
lang.invoke
.MethodType MethodType} object,
* whose structure is a series of classes, one of which is
* whose structure is a series of classes, one of which is
* the return type of the method (or {@code void.class} if none).
* the return type of the method (or {@code void.class} if none).
* <p>
* <p>
...
@@ -156,7 +145,7 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
...
@@ -156,7 +145,7 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
* This allows a more powerful negotiation of method type
* This allows a more powerful negotiation of method type
* between caller and callee.
* between caller and callee.
* <p>
* <p>
* (
Note:
The adjusted method handle {@code M2} is not directly observable,
* (
<em>Note:</em>
The adjusted method handle {@code M2} is not directly observable,
* and implementations are therefore not required to materialize it.)
* and implementations are therefore not required to materialize it.)
*
*
* <h3>Invocation checking</h3>
* <h3>Invocation checking</h3>
...
@@ -204,11 +193,11 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
...
@@ -204,11 +193,11 @@ import static sun.dyn.MemberName.newIllegalArgumentException; // utility
* Java code can create a method handle that directly accesses
* Java code can create a method handle that directly accesses
* any method, constructor, or field that is accessible to that code.
* any method, constructor, or field that is accessible to that code.
* This is done via a reflective, capability-based API called
* This is done via a reflective, capability-based API called
* {@link java.
dyn
.MethodHandles.Lookup MethodHandles.Lookup}
* {@link java.
lang.invoke
.MethodHandles.Lookup MethodHandles.Lookup}
* For example, a static method handle can be obtained
* For example, a static method handle can be obtained
* from {@link java.
dyn
.MethodHandles.Lookup#findStatic Lookup.findStatic}.
* from {@link java.
lang.invoke
.MethodHandles.Lookup#findStatic Lookup.findStatic}.
* There are also conversion methods from Core Reflection API objects,
* There are also conversion methods from Core Reflection API objects,
* such as {@link java.
dyn
.MethodHandles.Lookup#unreflect Lookup.unreflect}.
* such as {@link java.
lang.invoke
.MethodHandles.Lookup#unreflect Lookup.unreflect}.
* <p>
* <p>
* Like classes and strings, method handles that correspond to accessible
* Like classes and strings, method handles that correspond to accessible
* fields, methods, and constructors can also be represented directly
* fields, methods, and constructors can also be represented directly
...
@@ -269,7 +258,7 @@ mh = mh.asType(mt);
...
@@ -269,7 +258,7 @@ mh = mh.asType(mt);
x = mh.invokeExact((Object)1, (Object)2, (Object)3);
x = mh.invokeExact((Object)1, (Object)2, (Object)3);
// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
// invokeExact(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
assert(x.equals(java.util.Arrays.asList(1,2,3)));
assert(x.equals(java.util.Arrays.asList(1,2,3)));
// mt is
{ => int}
// mt is
int()
mt = MethodType.methodType(int.class);
mt = MethodType.methodType(int.class);
mh = lookup.findVirtual(java.util.List.class, "size", mt);
mh = lookup.findVirtual(java.util.List.class, "size", mt);
i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
i = (int) mh.invokeExact(java.util.Arrays.asList(1,2,3));
...
@@ -325,15 +314,15 @@ mh.invokeExact(System.out, "Hello, world.");
...
@@ -325,15 +314,15 @@ mh.invokeExact(System.out, "Hello, world.");
* <p>
* <p>
* For the sake of tools (but not as a programming API), the signature polymorphic
* For the sake of tools (but not as a programming API), the signature polymorphic
* methods are marked with a private yet standard annotation,
* methods are marked with a private yet standard annotation,
* {@code @java.
dyn
.MethodHandle.PolymorphicSignature}.
* {@code @java.
lang.invoke
.MethodHandle.PolymorphicSignature}.
* The annotation's retention is {@code RUNTIME}, so that all tools can see it.
* The annotation's retention is {@code RUNTIME}, so that all tools can see it.
*
*
* <h3>Formal rules for processing signature polymorphic methods</h3>
* <h3>Formal rules for processing signature polymorphic methods</h3>
* <p>
* <p>
* The following methods (and no others) are signature polymorphic:
* The following methods (and no others) are signature polymorphic:
* <ul>
* <ul>
* <li>{@link java.
dyn
.MethodHandle#invokeExact MethodHandle.invokeExact}
* <li>{@link java.
lang.invoke
.MethodHandle#invokeExact MethodHandle.invokeExact}
* <li>{@link java.
dyn
.MethodHandle#invokeGeneric MethodHandle.invokeGeneric}
* <li>{@link java.
lang.invoke
.MethodHandle#invokeGeneric MethodHandle.invokeGeneric}
* </ul>
* </ul>
* <p>
* <p>
* A signature polymorphic method will be declared with the following properties:
* A signature polymorphic method will be declared with the following properties:
...
@@ -341,7 +330,7 @@ mh.invokeExact(System.out, "Hello, world.");
...
@@ -341,7 +330,7 @@ mh.invokeExact(System.out, "Hello, world.");
* <li>It must be native.
* <li>It must be native.
* <li>It must take a single varargs parameter of the form {@code Object...}.
* <li>It must take a single varargs parameter of the form {@code Object...}.
* <li>It must produce a return value of type {@code Object}.
* <li>It must produce a return value of type {@code Object}.
* <li>It must be contained within the {@code java.
dyn
} package.
* <li>It must be contained within the {@code java.
lang.invoke
} package.
* </ul>
* </ul>
* Because of these requirements, a signature polymorphic method is able to accept
* Because of these requirements, a signature polymorphic method is able to accept
* any number and type of actual arguments, and can, with a cast, produce a value of any type.
* any number and type of actual arguments, and can, with a cast, produce a value of any type.
...
@@ -354,7 +343,7 @@ mh.invokeExact(System.out, "Hello, world.");
...
@@ -354,7 +343,7 @@ mh.invokeExact(System.out, "Hello, world.");
* <p>
* <p>
* In an argument position of a method invocation on a signature polymorphic method,
* In an argument position of a method invocation on a signature polymorphic method,
* a null literal has type {@code java.lang.Void}, unless cast to a reference type.
* a null literal has type {@code java.lang.Void}, unless cast to a reference type.
* (
Note:
This typing rule allows the null type to have its own encoding in linkage information
* (
<em>Note:</em>
This typing rule allows the null type to have its own encoding in linkage information
* distinct from other types.
* distinct from other types.
* <p>
* <p>
* The linkage information for the return type is derived from a context-dependent target typing convention.
* The linkage information for the return type is derived from a context-dependent target typing convention.
...
@@ -374,12 +363,12 @@ mh.invokeExact(System.out, "Hello, world.");
...
@@ -374,12 +363,12 @@ mh.invokeExact(System.out, "Hello, world.");
* and without implicit boxing or unboxing.
* and without implicit boxing or unboxing.
*
*
* <h3>Interoperation between method handles and the Core Reflection API</h3>
* <h3>Interoperation between method handles and the Core Reflection API</h3>
* Using factory methods in the {@link java.
dyn
.MethodHandles.Lookup Lookup} API,
* Using factory methods in the {@link java.
lang.invoke
.MethodHandles.Lookup Lookup} API,
* any class member represented by a Core Reflection API object
* any class member represented by a Core Reflection API object
* can be converted to a behaviorally equivalent method handle.
* can be converted to a behaviorally equivalent method handle.
* For example, a reflective {@link java.lang.reflect.Method Method} can
* For example, a reflective {@link java.lang.reflect.Method Method} can
* be converted to a method handle using
* be converted to a method handle using
* {@link java.
dyn
.MethodHandles.Lookup#unreflect Lookup.unreflect}.
* {@link java.
lang.invoke
.MethodHandles.Lookup#unreflect Lookup.unreflect}.
* The resulting method handles generally provide more direct and efficient
* The resulting method handles generally provide more direct and efficient
* access to the underlying class members.
* access to the underlying class members.
* <p>
* <p>
...
@@ -398,9 +387,9 @@ mh.invokeExact(System.out, "Hello, world.");
...
@@ -398,9 +387,9 @@ mh.invokeExact(System.out, "Hello, world.");
* they will throw {@code UnsupportedOperationException}.
* they will throw {@code UnsupportedOperationException}.
* <p>
* <p>
* In order to obtain an invoker method for a particular type descriptor,
* In order to obtain an invoker method for a particular type descriptor,
* use {@link java.
dyn
.MethodHandles#exactInvoker MethodHandles.exactInvoker},
* use {@link java.
lang.invoke
.MethodHandles#exactInvoker MethodHandles.exactInvoker},
* or {@link java.
dyn
.MethodHandles#genericInvoker MethodHandles.genericInvoker}.
* or {@link java.
lang.invoke
.MethodHandles#genericInvoker MethodHandles.genericInvoker}.
* The {@link java.
dyn
.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
* The {@link java.
lang.invoke
.MethodHandles.Lookup#findVirtual Lookup.findVirtual}
* API is also able to return a method handle
* API is also able to return a method handle
* to call {@code invokeExact} or {@code invokeGeneric},
* to call {@code invokeExact} or {@code invokeGeneric},
* for any specified type descriptor .
* for any specified type descriptor .
...
@@ -436,12 +425,35 @@ mh.invokeExact(System.out, "Hello, world.");
...
@@ -436,12 +425,35 @@ mh.invokeExact(System.out, "Hello, world.");
* @see MethodHandles
* @see MethodHandles
* @author John Rose, JSR 292 EG
* @author John Rose, JSR 292 EG
*/
*/
public
abstract
class
MethodHandle
public
abstract
class
MethodHandle
{
// Note: This is an implementation inheritance hack, and will be removed
// { JVM internals:
// with a JVM change which moves the required hidden state onto this class.
extends
MethodHandleImpl
private
byte
vmentry
;
// adapter stub or method entry point
{
//private int vmslots; // optionally, hoist type.form.vmslots
private
static
Access
IMPL_TOKEN
=
Access
.
getToken
();
/*non-public*/
Object
vmtarget
;
// VM-specific, class-specific target value
// TO DO: vmtarget should be invisible to Java, since the JVM puts internal
// managed pointers into it. Making it visible exposes it to debuggers,
// which can cause errors when they treat the pointer as an Object.
// These two dummy fields are present to force 'I' and 'J' signatures
// into this class's constant pool, so they can be transferred
// to vmentry when this class is loaded.
static
final
int
INT_FIELD
=
0
;
static
final
long
LONG_FIELD
=
0
;
// vmentry (a void* field) is used *only* by the JVM.
// The JVM adjusts its type to int or long depending on system wordsize.
// Since it is statically typed as neither int nor long, it is impossible
// to use this field from Java bytecode. (Please don't try to, either.)
// The vmentry is an assembly-language stub which is jumped to
// immediately after the method type is verified.
// For a direct MH, this stub loads the vmtarget's entry point
// and jumps to it.
// } End of JVM internals.
static
{
MethodHandleImpl
.
initStatics
();
}
static
{
MethodHandleImpl
.
initStatics
();
}
// interface MethodHandle<R throws X extends Exception,A...>
// interface MethodHandle<R throws X extends Exception,A...>
...
@@ -458,7 +470,7 @@ public abstract class MethodHandle
...
@@ -458,7 +470,7 @@ public abstract class MethodHandle
private
MethodType
type
;
private
MethodType
type
;
/**
/**
* Report the type of this method handle.
* Report
s
the type of this method handle.
* Every invocation of this method handle via {@code invokeExact} must exactly match this type.
* Every invocation of this method handle via {@code invokeExact} must exactly match this type.
* @return the method handle type
* @return the method handle type
*/
*/
...
@@ -467,39 +479,18 @@ public abstract class MethodHandle
...
@@ -467,39 +479,18 @@ public abstract class MethodHandle
}
}
/**
/**
* <em>CONSTRUCTOR WILL BE REMOVED FOR PFD:</em>
* Package-private constructor for the method handle implementation hierarchy.
* Temporary constructor in early versions of the Reference Implementation.
* Method handle inheritance will be contained completely within
* Method handle inheritance (if any) will be contained completely within
* the {@code java.lang.invoke} package.
* the {@code java.dyn} package.
*/
*/
// The constructor for MethodHandle may only be called by privileged code.
// Subclasses may be in other packages, but must possess
// a token which they obtained from MH with a security check.
// @param token non-null object which proves access permission
// @param type type (permanently assigned) of the new method handle
// @param type type (permanently assigned) of the new method handle
protected
MethodHandle
(
Access
token
,
MethodType
type
)
{
/*non-public*/
MethodHandle
(
MethodType
type
)
{
super
(
token
);
Access
.
check
(
token
);
this
.
type
=
type
;
}
private
void
initType
(
MethodType
type
)
{
type
.
getClass
();
// elicit NPE
type
.
getClass
();
// elicit NPE
if
(
this
.
type
!=
null
)
throw
new
InternalError
();
this
.
type
=
type
;
this
.
type
=
type
;
}
}
static
{
// This hack allows the implementation package special access to
// the internals of MethodHandle. In particular, the MTImpl has all sorts
// of cached information useful to the implementation code.
MethodHandleImpl
.
setMethodHandleFriend
(
IMPL_TOKEN
,
new
MethodHandleImpl
.
MethodHandleFriend
()
{
public
void
initType
(
MethodHandle
mh
,
MethodType
type
)
{
mh
.
initType
(
type
);
}
});
}
/**
/**
* Invoke the method handle, allowing any caller type descriptor, but requiring an exact type match.
* Invoke
s
the method handle, allowing any caller type descriptor, but requiring an exact type match.
* The type descriptor at the call site of {@code invokeExact} must
* The type descriptor at the call site of {@code invokeExact} must
* exactly match this method handle's {@link #type type}.
* exactly match this method handle's {@link #type type}.
* No conversions are allowed on arguments or return values.
* No conversions are allowed on arguments or return values.
...
@@ -508,7 +499,7 @@ public abstract class MethodHandle
...
@@ -508,7 +499,7 @@ public abstract class MethodHandle
* it will appear as a single native method, taking an object array and returning an object.
* it will appear as a single native method, taking an object array and returning an object.
* If this native method is invoked directly via
* If this native method is invoked directly via
* {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
* {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
* or indirectly via {@link java.
dyn
.MethodHandles.Lookup#unreflect Lookup.unreflect},
* or indirectly via {@link java.
lang.invoke
.MethodHandles.Lookup#unreflect Lookup.unreflect},
* it will throw an {@code UnsupportedOperationException}.
* it will throw an {@code UnsupportedOperationException}.
* @throws WrongMethodTypeException if the target's type is not identical with the caller's type descriptor
* @throws WrongMethodTypeException if the target's type is not identical with the caller's type descriptor
* @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
* @throws Throwable anything thrown by the underlying method propagates unchanged through the method handle call
...
@@ -516,7 +507,7 @@ public abstract class MethodHandle
...
@@ -516,7 +507,7 @@ public abstract class MethodHandle
public
final
native
@PolymorphicSignature
Object
invokeExact
(
Object
...
args
)
throws
Throwable
;
public
final
native
@PolymorphicSignature
Object
invokeExact
(
Object
...
args
)
throws
Throwable
;
/**
/**
* Invoke the method handle, allowing any caller type descriptor,
* Invoke
s
the method handle, allowing any caller type descriptor,
* and optionally performing conversions on arguments and return values.
* and optionally performing conversions on arguments and return values.
* <p>
* <p>
* If the call site type descriptor exactly matches this method handle's {@link #type type},
* If the call site type descriptor exactly matches this method handle's {@link #type type},
...
@@ -542,7 +533,7 @@ public abstract class MethodHandle
...
@@ -542,7 +533,7 @@ public abstract class MethodHandle
* it will appear as a single native method, taking an object array and returning an object.
* it will appear as a single native method, taking an object array and returning an object.
* If this native method is invoked directly via
* If this native method is invoked directly via
* {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
* {@link java.lang.reflect.Method#invoke Method.invoke}, via JNI,
* or indirectly via {@link java.
dyn
.MethodHandles.Lookup#unreflect Lookup.unreflect},
* or indirectly via {@link java.
lang.invoke
.MethodHandles.Lookup#unreflect Lookup.unreflect},
* it will throw an {@code UnsupportedOperationException}.
* it will throw an {@code UnsupportedOperationException}.
* @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type descriptor
* @throws WrongMethodTypeException if the target's type cannot be adjusted to the caller's type descriptor
* @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
* @throws ClassCastException if the target's type can be adjusted to the caller, but a reference cast fails
...
@@ -551,7 +542,7 @@ public abstract class MethodHandle
...
@@ -551,7 +542,7 @@ public abstract class MethodHandle
public
final
native
@PolymorphicSignature
Object
invokeGeneric
(
Object
...
args
)
throws
Throwable
;
public
final
native
@PolymorphicSignature
Object
invokeGeneric
(
Object
...
args
)
throws
Throwable
;
/**
/**
* Perform a varargs invocation, passing the arguments in the given array
* Perform
s
a varargs invocation, passing the arguments in the given array
* to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site
* to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site
* which mentions only the type {@code Object}, and whose arity is the length
* which mentions only the type {@code Object}, and whose arity is the length
* of the argument array.
* of the argument array.
...
@@ -608,7 +599,7 @@ public abstract class MethodHandle
...
@@ -608,7 +599,7 @@ public abstract class MethodHandle
return
asType
(
MethodType
.
genericMethodType
(
argc
)).
invokeWithArguments
(
arguments
);
return
asType
(
MethodType
.
genericMethodType
(
argc
)).
invokeWithArguments
(
arguments
);
}
}
if
(
argc
<=
10
)
{
if
(
argc
<=
10
)
{
MethodHandle
invoker
=
invokers
(
type
).
genericInvoker
();
MethodHandle
invoker
=
type
.
invokers
(
).
genericInvoker
();
switch
(
argc
)
{
switch
(
argc
)
{
case
0
:
return
invoker
.
invokeExact
(
this
);
case
0
:
return
invoker
.
invokeExact
(
this
);
case
1
:
return
invoker
.
invokeExact
(
this
,
case
1
:
return
invoker
.
invokeExact
(
this
,
...
@@ -647,17 +638,34 @@ public abstract class MethodHandle
...
@@ -647,17 +638,34 @@ public abstract class MethodHandle
}
}
// more than ten arguments get boxed in a varargs list:
// more than ten arguments get boxed in a varargs list:
MethodHandle
invoker
=
invokers
(
type
).
spreadInvoker
(
0
);
MethodHandle
invoker
=
type
.
invokers
(
).
spreadInvoker
(
0
);
return
invoker
.
invokeExact
(
this
,
arguments
);
return
invoker
.
invokeExact
(
this
,
arguments
);
}
}
/** Equivalent to {@code invokeWithArguments(arguments.toArray())}. */
/**
* Performs a varargs invocation, passing the arguments in the given array
* to the method handle, as if via {@link #invokeGeneric invokeGeneric} from a call site
* which mentions only the type {@code Object}, and whose arity is the length
* of the argument array.
* <p>
* This method is also equivalent to the following code:
* <p><blockquote><pre>
* {@link #invokeWithArguments(Object...) invokeWithArguments}(arguments.toArray())
* </pre></blockquote>
*
* @param arguments the arguments to pass to the target
* @return the result returned by the target
* @throws ClassCastException if an argument cannot be converted by reference casting
* @throws WrongMethodTypeException if the target's type cannot be adjusted to take the given number of {@code Object} arguments
* @throws Throwable anything thrown by the target method invocation
*/
public
Object
invokeWithArguments
(
java
.
util
.
List
<?>
arguments
)
throws
Throwable
{
public
Object
invokeWithArguments
(
java
.
util
.
List
<?>
arguments
)
throws
Throwable
{
return
invokeWithArguments
(
arguments
.
toArray
());
return
invokeWithArguments
(
arguments
.
toArray
());
}
}
/**
/**
* Produce an adapter method handle which adapts the type of the
* Produce
s
an adapter method handle which adapts the type of the
* current method handle to a new type
* current method handle to a new type
.
* The resulting method handle is guaranteed to report a type
* The resulting method handle is guaranteed to report a type
* which is equal to the desired new type.
* which is equal to the desired new type.
* <p>
* <p>
...
@@ -685,7 +693,7 @@ public abstract class MethodHandle
...
@@ -685,7 +693,7 @@ public abstract class MethodHandle
}
}
/**
/**
* Make an adapter which accepts a trailing array argument
* Make
s
an adapter which accepts a trailing array argument
* and spreads its elements as positional arguments.
* and spreads its elements as positional arguments.
* The new method handle adapts, as its <i>target</i>,
* The new method handle adapts, as its <i>target</i>,
* the current method handle. The type of the adapter will be
* the current method handle. The type of the adapter will be
...
@@ -733,7 +741,7 @@ public abstract class MethodHandle
...
@@ -733,7 +741,7 @@ public abstract class MethodHandle
}
}
/**
/**
* Make an adapter which accepts a given number of trailing
* Make
s
an adapter which accepts a given number of trailing
* positional arguments and collects them into an array argument.
* positional arguments and collects them into an array argument.
* The new method handle adapts, as its <i>target</i>,
* The new method handle adapts, as its <i>target</i>,
* the current method handle. The type of the adapter will be
* the current method handle. The type of the adapter will be
...
@@ -784,7 +792,7 @@ public abstract class MethodHandle
...
@@ -784,7 +792,7 @@ public abstract class MethodHandle
}
}
/**
/**
* Make a <em>variable arity</em> adapter which is able to accept
* Make
s
a <em>variable arity</em> adapter which is able to accept
* any number of trailing positional arguments and collect them
* any number of trailing positional arguments and collect them
* into an array argument.
* into an array argument.
* <p>
* <p>
...
@@ -942,12 +950,12 @@ assert(failed);
...
@@ -942,12 +950,12 @@ assert(failed);
}
}
/**
/**
* Determine if this method handle
* Determine
s
if this method handle
* supports {@linkplain #asVarargsCollector variable arity} calls.
* supports {@linkplain #asVarargsCollector variable arity} calls.
* Such method handles arise from the following sources:
* Such method handles arise from the following sources:
* <ul>
* <ul>
* <li>a call to {@linkplain #asVarargsCollector asVarargsCollector}
* <li>a call to {@linkplain #asVarargsCollector asVarargsCollector}
* <li>a call to a {@linkplain java.
dyn
.MethodHandles.Lookup lookup method}
* <li>a call to a {@linkplain java.
lang.invoke
.MethodHandles.Lookup lookup method}
* which resolves to a variable arity Java method or constructor
* which resolves to a variable arity Java method or constructor
* <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle}
* <li>an {@code ldc} instruction of a {@code CONSTANT_MethodHandle}
* which resolves to a variable arity Java method or constructor
* which resolves to a variable arity Java method or constructor
...
@@ -960,9 +968,9 @@ assert(failed);
...
@@ -960,9 +968,9 @@ assert(failed);
}
}
/**
/**
* Bind a value {@code x} to the first argument of a method handle, without invoking it.
* Bind
s
a value {@code x} to the first argument of a method handle, without invoking it.
* The new method handle adapts, as its <i>target</i>,
* The new method handle adapts, as its <i>target</i>,
* t
o the current method handle
.
* t
he current method handle by binding it to the given argument
.
* The type of the bound handle will be
* The type of the bound handle will be
* the same as the type of the target, except that a single leading
* the same as the type of the target, except that a single leading
* reference parameter will be omitted.
* reference parameter will be omitted.
...
@@ -974,9 +982,12 @@ assert(failed);
...
@@ -974,9 +982,12 @@ assert(failed);
* <p>
* <p>
* The reference {@code x} must be convertible to the first parameter
* The reference {@code x} must be convertible to the first parameter
* type of the target.
* type of the target.
* <p>
* (<em>Note:</em> Because method handles are immutable, the target method handle
* retains its original type and behavior.)
* @param x the value to bind to the first argument of the target
* @param x the value to bind to the first argument of the target
* @return a new method handle which
collects some trailing argument
* @return a new method handle which
prepends the given value to the incoming
*
into an array
, before calling the original method handle
*
argument list
, before calling the original method handle
* @throws IllegalArgumentException if the target does not have a
* @throws IllegalArgumentException if the target does not have a
* leading parameter type that is a reference type
* leading parameter type that is a reference type
* @throws ClassCastException if {@code x} cannot be converted
* @throws ClassCastException if {@code x} cannot be converted
...
@@ -984,7 +995,15 @@ assert(failed);
...
@@ -984,7 +995,15 @@ assert(failed);
* @see MethodHandles#insertArguments
* @see MethodHandles#insertArguments
*/
*/
public
MethodHandle
bindTo
(
Object
x
)
{
public
MethodHandle
bindTo
(
Object
x
)
{
return
MethodHandles
.
insertArguments
(
this
,
0
,
x
);
Class
<?>
ptype
;
if
(
type
().
parameterCount
()
==
0
||
(
ptype
=
type
().
parameterType
(
0
)).
isPrimitive
())
throw
newIllegalArgumentException
(
"no leading reference parameter"
,
x
);
x
=
MethodHandles
.
checkValue
(
ptype
,
x
);
// Cf. MethodHandles.insertArguments for the following logic:
MethodHandle
bmh
=
MethodHandleImpl
.
bindReceiver
(
this
,
x
);
if
(
bmh
!=
null
)
return
bmh
;
return
MethodHandleImpl
.
bindArgument
(
this
,
0
,
x
);
}
}
/**
/**
...
@@ -996,14 +1015,14 @@ assert(failed);
...
@@ -996,14 +1015,14 @@ assert(failed);
* "MethodHandle" + type().toString()
* "MethodHandle" + type().toString()
* </pre></blockquote>
* </pre></blockquote>
* <p>
* <p>
*
Note:
Future releases of this API may add further information
*
(<em>Note:</em>
Future releases of this API may add further information
* to the string representation.
* to the string representation.
* Therefore, the present syntax should not be parsed by applications.
* Therefore, the present syntax should not be parsed by applications.
)
*
*
* @return a string representation of the method handle
* @return a string representation of the method handle
*/
*/
@Override
@Override
public
String
toString
()
{
public
String
toString
()
{
return
MethodHandleImpl
.
getNameString
(
IMPL_TOKEN
,
this
);
return
getNameString
(
this
);
}
}
}
}
src/share/classes/
sun/dyn
/MethodHandleImpl.java
→
src/share/classes/
java/lang/invoke
/MethodHandleImpl.java
浏览文件 @
33ee9ccf
...
@@ -23,136 +23,36 @@
...
@@ -23,136 +23,36 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
java.dyn.*
;
import
sun.invoke.util.VerifyType
;
import
java.dyn.MethodHandles.Lookup
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
sun.dyn.util.VerifyType
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.List
;
import
sun.
dyn
.empty.Empty
;
import
sun.
invoke
.empty.Empty
;
import
sun.
dyn
.util.ValueConversions
;
import
sun.
invoke
.util.ValueConversions
;
import
sun.
dyn
.util.Wrapper
;
import
sun.
invoke
.util.Wrapper
;
import
sun.misc.Unsafe
;
import
sun.misc.Unsafe
;
import
static
sun
.
dyn
.
MemberName
.
newIllegalArgumentException
;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
import
static
sun
.
dyn
.
MemberName
.
newNoAccessException
;
import
static
java
.
lang
.
invoke
.
MethodHandles
.
Lookup
.
IMPL_LOOKUP
;
import
static
sun
.
dyn
.
MemberName
.
uncaughtException
;
/**
/**
* Base class for method handles, containing JVM-specific fields and logic.
* Trusted implementation code for MethodHandle.
* TO DO: It should not be a base class.
* @author jrose
* @author jrose
*/
*/
public
abstract
class
MethodHandleImpl
{
/*non-public*/
abstract
class
MethodHandleImpl
{
// Fields which really belong in MethodHandle:
private
byte
vmentry
;
// adapter stub or method entry point
//private int vmslots; // optionally, hoist type.form.vmslots
protected
Object
vmtarget
;
// VM-specific, class-specific target value
//MethodType type; // defined in MethodHandle
// TO DO: vmtarget should be invisible to Java, since the JVM puts internal
// managed pointers into it. Making it visible exposes it to debuggers,
// which can cause errors when they treat the pointer as an Object.
// These two dummy fields are present to force 'I' and 'J' signatures
// into this class's constant pool, so they can be transferred
// to vmentry when this class is loaded.
static
final
int
INT_FIELD
=
0
;
static
final
long
LONG_FIELD
=
0
;
/** Access methods for the internals of MethodHandle, supplied to
* MethodHandleImpl as a trusted agent.
*/
static
public
interface
MethodHandleFriend
{
void
initType
(
MethodHandle
mh
,
MethodType
type
);
}
public
static
void
setMethodHandleFriend
(
Access
token
,
MethodHandleFriend
am
)
{
Access
.
check
(
token
);
if
(
METHOD_HANDLE_FRIEND
!=
null
)
throw
new
InternalError
();
// just once
METHOD_HANDLE_FRIEND
=
am
;
}
static
private
MethodHandleFriend
METHOD_HANDLE_FRIEND
;
// NOT public
static
void
initType
(
MethodHandle
mh
,
MethodType
type
)
{
METHOD_HANDLE_FRIEND
.
initType
(
mh
,
type
);
}
// type is defined in java.dyn.MethodHandle, which is platform-independent
// vmentry (a void* field) is used *only* by by the JVM.
// The JVM adjusts its type to int or long depending on system wordsize.
// Since it is statically typed as neither int nor long, it is impossible
// to use this field from Java bytecode. (Please don't try to, either.)
// The vmentry is an assembly-language stub which is jumped to
// immediately after the method type is verified.
// For a direct MH, this stub loads the vmtarget's entry point
// and jumps to it.
/**
* VM-based method handles must have a security token.
* This security token can only be obtained by trusted code.
* Do not create method handles directly; use factory methods.
*/
public
MethodHandleImpl
(
Access
token
)
{
Access
.
check
(
token
);
}
/** Initialize the method type form to participate in JVM calls.
* This is done once for each erased type.
*/
public
static
void
init
(
Access
token
,
MethodType
self
)
{
Access
.
check
(
token
);
if
(
MethodHandleNatives
.
JVM_SUPPORT
)
MethodHandleNatives
.
init
(
self
);
}
/// Factory methods to create method handles:
/// Factory methods to create method handles:
private
static
final
MemberName
.
Factory
LOOKUP
=
MemberName
.
Factory
.
INSTANCE
;
private
static
final
MemberName
.
Factory
LOOKUP
=
MemberName
.
Factory
.
INSTANCE
;
static
private
Lookup
IMPL_LOOKUP_INIT
;
static
void
initStatics
()
{
public
static
void
initLookup
(
Access
token
,
Lookup
lookup
)
{
Access
.
check
(
token
);
if
(
IMPL_LOOKUP_INIT
!=
null
)
throw
new
InternalError
();
IMPL_LOOKUP_INIT
=
lookup
;
}
public
static
Lookup
getLookup
(
Access
token
)
{
Access
.
check
(
token
);
return
IMPL_LOOKUP
;
}
static
{
if
(!
MethodHandleNatives
.
JVM_SUPPORT
)
// force init of native API
throw
new
InternalError
(
"No JVM support for JSR 292"
);
// Force initialization of Lookup, so it calls us back as initLookup:
MethodHandles
.
publicLookup
();
if
(
IMPL_LOOKUP_INIT
==
null
)
throw
new
InternalError
();
}
public
static
void
initStatics
()
{
// Trigger preceding sequence.
// Trigger preceding sequence.
}
}
/** Shared secret with MethodHandles.Lookup, a copy of Lookup.IMPL_LOOKUP. */
static
final
Lookup
IMPL_LOOKUP
=
IMPL_LOOKUP_INIT
;
/** Look up a given method.
/** Look up a given method.
* Callable only from
java.dyn
and related packages.
* Callable only from
sun.invoke
and related packages.
* <p>
* <p>
* The resulting method handle type will be of the given type,
* The resulting method handle type will be of the given type,
* with a receiver type {@code rcvc} prepended if the member is not static.
* with a receiver type {@code rcvc} prepended if the member is not static.
...
@@ -170,10 +70,9 @@ public abstract class MethodHandleImpl {
...
@@ -170,10 +70,9 @@ public abstract class MethodHandleImpl {
* @return a direct handle to the matching method
* @return a direct handle to the matching method
* @throws IllegalAccessException if the given method cannot be accessed by the lookup class
* @throws IllegalAccessException if the given method cannot be accessed by the lookup class
*/
*/
public
static
static
MethodHandle
findMethod
(
Access
token
,
MemberName
method
,
MethodHandle
findMethod
(
MemberName
method
,
boolean
doDispatch
,
Class
<?>
lookupClass
)
throws
IllegalAccessException
{
boolean
doDispatch
,
Class
<?>
lookupClass
)
throws
IllegalAccessException
{
Access
.
check
(
token
);
// only trusted calls
MethodType
mtype
=
method
.
getMethodType
();
MethodType
mtype
=
method
.
getMethodType
();
if
(!
method
.
isStatic
())
{
if
(!
method
.
isStatic
())
{
// adjust the advertised receiver type to be exactly the one requested
// adjust the advertised receiver type to be exactly the one requested
...
@@ -183,7 +82,7 @@ public abstract class MethodHandleImpl {
...
@@ -183,7 +82,7 @@ public abstract class MethodHandleImpl {
}
}
DirectMethodHandle
mh
=
new
DirectMethodHandle
(
mtype
,
method
,
doDispatch
,
lookupClass
);
DirectMethodHandle
mh
=
new
DirectMethodHandle
(
mtype
,
method
,
doDispatch
,
lookupClass
);
if
(!
mh
.
isValid
())
if
(!
mh
.
isValid
())
throw
newNoAccessException
(
method
,
lookupClass
);
throw
method
.
makeAccessException
(
"no access"
,
lookupClass
);
assert
(
mh
.
type
()
==
mtype
);
assert
(
mh
.
type
()
==
mtype
);
if
(!
method
.
isVarargs
())
if
(!
method
.
isVarargs
())
return
mh
;
return
mh
;
...
@@ -191,13 +90,12 @@ public abstract class MethodHandleImpl {
...
@@ -191,13 +90,12 @@ public abstract class MethodHandleImpl {
return
mh
.
asVarargsCollector
(
mtype
.
parameterType
(
mtype
.
parameterCount
()-
1
));
return
mh
.
asVarargsCollector
(
mtype
.
parameterType
(
mtype
.
parameterCount
()-
1
));
}
}
public
static
static
MethodHandle
makeAllocator
(
Access
token
,
MethodHandle
rawConstructor
)
{
MethodHandle
makeAllocator
(
MethodHandle
rawConstructor
)
{
Access
.
check
(
token
);
MethodType
rawConType
=
rawConstructor
.
type
();
MethodType
rawConType
=
rawConstructor
.
type
();
// Wrap the raw (unsafe) constructor with the allocation of a suitable object.
// Wrap the raw (unsafe) constructor with the allocation of a suitable object.
MethodHandle
allocator
MethodHandle
allocator
=
AllocateObject
.
make
(
token
,
rawConType
.
parameterType
(
0
),
rawConstructor
);
=
AllocateObject
.
make
(
rawConType
.
parameterType
(
0
),
rawConstructor
);
assert
(
allocator
.
type
()
assert
(
allocator
.
type
()
.
equals
(
rawConType
.
dropParameterTypes
(
0
,
1
).
changeReturnType
(
rawConType
.
parameterType
(
0
))));
.
equals
(
rawConType
.
dropParameterTypes
(
0
,
1
).
changeReturnType
(
rawConType
.
parameterType
(
0
))));
return
allocator
;
return
allocator
;
...
@@ -211,13 +109,11 @@ public abstract class MethodHandleImpl {
...
@@ -211,13 +109,11 @@ public abstract class MethodHandleImpl {
private
AllocateObject
(
MethodHandle
invoker
,
private
AllocateObject
(
MethodHandle
invoker
,
Class
<
C
>
allocateClass
,
MethodHandle
rawConstructor
)
{
Class
<
C
>
allocateClass
,
MethodHandle
rawConstructor
)
{
super
(
Access
.
TOKEN
,
invoker
);
super
(
invoker
);
this
.
allocateClass
=
allocateClass
;
this
.
allocateClass
=
allocateClass
;
this
.
rawConstructor
=
rawConstructor
;
this
.
rawConstructor
=
rawConstructor
;
}
}
static
MethodHandle
make
(
Access
token
,
static
MethodHandle
make
(
Class
<?>
allocateClass
,
MethodHandle
rawConstructor
)
{
Class
<?>
allocateClass
,
MethodHandle
rawConstructor
)
{
Access
.
check
(
token
);
MethodType
rawConType
=
rawConstructor
.
type
();
MethodType
rawConType
=
rawConstructor
.
type
();
assert
(
rawConType
.
parameterType
(
0
)
==
allocateClass
);
assert
(
rawConType
.
parameterType
(
0
)
==
allocateClass
);
MethodType
newType
=
rawConType
.
dropParameterTypes
(
0
,
1
).
changeReturnType
(
allocateClass
);
MethodType
newType
=
rawConType
.
dropParameterTypes
(
0
,
1
).
changeReturnType
(
allocateClass
);
...
@@ -225,18 +121,18 @@ public abstract class MethodHandleImpl {
...
@@ -225,18 +121,18 @@ public abstract class MethodHandleImpl {
if
(
nargs
<
INVOKES
.
length
)
{
if
(
nargs
<
INVOKES
.
length
)
{
MethodHandle
invoke
=
INVOKES
[
nargs
];
MethodHandle
invoke
=
INVOKES
[
nargs
];
MethodType
conType
=
CON_TYPES
[
nargs
];
MethodType
conType
=
CON_TYPES
[
nargs
];
MethodHandle
gcon
=
convertArguments
(
token
,
rawConstructor
,
conType
,
rawConType
,
null
);
MethodHandle
gcon
=
convertArguments
(
rawConstructor
,
conType
,
rawConType
,
null
);
if
(
gcon
==
null
)
return
null
;
if
(
gcon
==
null
)
return
null
;
MethodHandle
galloc
=
new
AllocateObject
(
invoke
,
allocateClass
,
gcon
);
MethodHandle
galloc
=
new
AllocateObject
(
invoke
,
allocateClass
,
gcon
);
assert
(
galloc
.
type
()
==
newType
.
generic
());
assert
(
galloc
.
type
()
==
newType
.
generic
());
return
convertArguments
(
token
,
galloc
,
newType
,
galloc
.
type
(),
null
);
return
convertArguments
(
galloc
,
newType
,
galloc
.
type
(),
null
);
}
else
{
}
else
{
MethodHandle
invoke
=
VARARGS_INVOKE
;
MethodHandle
invoke
=
VARARGS_INVOKE
;
MethodType
conType
=
CON_TYPES
[
nargs
];
MethodType
conType
=
CON_TYPES
[
nargs
];
MethodHandle
gcon
=
spreadArguments
(
token
,
rawConstructor
,
conType
,
1
);
MethodHandle
gcon
=
spreadArguments
(
rawConstructor
,
conType
,
1
);
if
(
gcon
==
null
)
return
null
;
if
(
gcon
==
null
)
return
null
;
MethodHandle
galloc
=
new
AllocateObject
(
invoke
,
allocateClass
,
gcon
);
MethodHandle
galloc
=
new
AllocateObject
(
invoke
,
allocateClass
,
gcon
);
return
collectArguments
(
token
,
galloc
,
newType
,
1
,
null
);
return
collectArguments
(
galloc
,
newType
,
1
,
null
);
}
}
}
}
@Override
@Override
...
@@ -338,20 +234,16 @@ public abstract class MethodHandleImpl {
...
@@ -338,20 +234,16 @@ public abstract class MethodHandleImpl {
}
}
}
}
public
static
static
MethodHandle
accessField
(
Access
token
,
MethodHandle
accessField
(
MemberName
member
,
boolean
isSetter
,
MemberName
member
,
boolean
isSetter
,
Class
<?>
lookupClass
)
{
Class
<?>
lookupClass
)
{
Access
.
check
(
token
);
// Use sun. misc.Unsafe to dig up the dirt on the field.
// Use sun. misc.Unsafe to dig up the dirt on the field.
MethodHandle
mh
=
new
FieldAccessor
(
token
,
member
,
isSetter
);
MethodHandle
mh
=
new
FieldAccessor
(
member
,
isSetter
);
return
mh
;
return
mh
;
}
}
public
static
static
MethodHandle
accessArrayElement
(
Access
token
,
MethodHandle
accessArrayElement
(
Class
<?>
arrayClass
,
boolean
isSetter
)
{
Class
<?>
arrayClass
,
boolean
isSetter
)
{
Access
.
check
(
token
);
if
(!
arrayClass
.
isArray
())
if
(!
arrayClass
.
isArray
())
throw
newIllegalArgumentException
(
"not an array: "
+
arrayClass
);
throw
newIllegalArgumentException
(
"not an array: "
+
arrayClass
);
Class
<?>
elemClass
=
arrayClass
.
getComponentType
();
Class
<?>
elemClass
=
arrayClass
.
getComponentType
();
...
@@ -379,12 +271,13 @@ public abstract class MethodHandleImpl {
...
@@ -379,12 +271,13 @@ public abstract class MethodHandleImpl {
final
long
offset
;
final
long
offset
;
final
String
name
;
final
String
name
;
public
FieldAccessor
(
Access
token
,
MemberName
field
,
boolean
isSetter
)
{
FieldAccessor
(
MemberName
field
,
boolean
isSetter
)
{
super
(
Access
.
TOKEN
,
fhandle
(
field
.
getDeclaringClass
(),
field
.
getFieldType
(),
isSetter
,
field
.
isStatic
()));
super
(
fhandle
(
field
.
getDeclaringClass
(),
field
.
getFieldType
(),
isSetter
,
field
.
isStatic
()));
this
.
offset
=
(
long
)
field
.
getVMIndex
(
token
);
this
.
offset
=
(
long
)
field
.
getVMIndex
();
this
.
name
=
field
.
getName
();
this
.
name
=
field
.
getName
();
this
.
base
=
staticBase
(
field
);
this
.
base
=
staticBase
(
field
);
}
}
@Override
public
String
toString
()
{
return
addTypeString
(
name
,
this
);
}
public
String
toString
()
{
return
addTypeString
(
name
,
this
);
}
int
getFieldI
(
C
obj
)
{
return
unsafe
.
getInt
(
obj
,
offset
);
}
int
getFieldI
(
C
obj
)
{
return
unsafe
.
getInt
(
obj
,
offset
);
}
...
@@ -560,10 +453,8 @@ public abstract class MethodHandleImpl {
...
@@ -560,10 +453,8 @@ public abstract class MethodHandleImpl {
* @param receiver Receiver (or first static method argument) to pre-bind.
* @param receiver Receiver (or first static method argument) to pre-bind.
* @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
* @return a BoundMethodHandle for the given DirectMethodHandle, or null if it does not exist
*/
*/
public
static
static
MethodHandle
bindReceiver
(
Access
token
,
MethodHandle
bindReceiver
(
MethodHandle
target
,
Object
receiver
)
{
MethodHandle
target
,
Object
receiver
)
{
Access
.
check
(
token
);
if
(
target
instanceof
AdapterMethodHandle
&&
if
(
target
instanceof
AdapterMethodHandle
&&
((
AdapterMethodHandle
)
target
).
conversionOp
()
==
MethodHandleNatives
.
Constants
.
OP_RETYPE_ONLY
((
AdapterMethodHandle
)
target
).
conversionOp
()
==
MethodHandleNatives
.
Constants
.
OP_RETYPE_ONLY
)
{
)
{
...
@@ -574,7 +465,7 @@ public abstract class MethodHandleImpl {
...
@@ -574,7 +465,7 @@ public abstract class MethodHandleImpl {
dmh
.
type
().
parameterType
(
0
).
isAssignableFrom
(
receiver
.
getClass
()))
{
dmh
.
type
().
parameterType
(
0
).
isAssignableFrom
(
receiver
.
getClass
()))
{
MethodHandle
bmh
=
new
BoundMethodHandle
(
dmh
,
receiver
,
0
);
MethodHandle
bmh
=
new
BoundMethodHandle
(
dmh
,
receiver
,
0
);
MethodType
newType
=
target
.
type
().
dropParameterTypes
(
0
,
1
);
MethodType
newType
=
target
.
type
().
dropParameterTypes
(
0
,
1
);
return
convertArguments
(
token
,
bmh
,
newType
,
bmh
.
type
(),
null
);
return
convertArguments
(
bmh
,
newType
,
bmh
.
type
(),
null
);
}
}
}
}
}
}
...
@@ -590,19 +481,15 @@ public abstract class MethodHandleImpl {
...
@@ -590,19 +481,15 @@ public abstract class MethodHandleImpl {
* @param receiver Argument (which can be a boxed primitive) to pre-bind.
* @param receiver Argument (which can be a boxed primitive) to pre-bind.
* @return a suitable BoundMethodHandle
* @return a suitable BoundMethodHandle
*/
*/
public
static
static
MethodHandle
bindArgument
(
Access
token
,
MethodHandle
bindArgument
(
MethodHandle
target
,
int
argnum
,
Object
receiver
)
{
MethodHandle
target
,
int
argnum
,
Object
receiver
)
{
Access
.
check
(
token
);
return
new
BoundMethodHandle
(
target
,
receiver
,
argnum
);
return
new
BoundMethodHandle
(
target
,
receiver
,
argnum
);
}
}
public
static
MethodHandle
convertArguments
(
Access
token
,
static
MethodHandle
convertArguments
(
MethodHandle
target
,
MethodHandle
target
,
MethodType
newType
,
MethodType
newType
,
MethodType
oldType
,
MethodType
oldType
,
int
[]
permutationOrNull
)
{
int
[]
permutationOrNull
)
{
Access
.
check
(
token
);
assert
(
oldType
.
parameterCount
()
==
target
.
type
().
parameterCount
());
assert
(
oldType
.
parameterCount
()
==
target
.
type
().
parameterCount
());
if
(
permutationOrNull
!=
null
)
{
if
(
permutationOrNull
!=
null
)
{
int
outargs
=
oldType
.
parameterCount
(),
inargs
=
newType
.
parameterCount
();
int
outargs
=
oldType
.
parameterCount
(),
inargs
=
newType
.
parameterCount
();
...
@@ -613,7 +500,7 @@ public abstract class MethodHandleImpl {
...
@@ -613,7 +500,7 @@ public abstract class MethodHandleImpl {
for
(
int
i
=
0
;
i
<
outargs
;
i
++)
for
(
int
i
=
0
;
i
<
outargs
;
i
++)
callTypeArgs
[
i
]
=
newType
.
parameterType
(
permutationOrNull
[
i
]);
callTypeArgs
[
i
]
=
newType
.
parameterType
(
permutationOrNull
[
i
]);
MethodType
callType
=
MethodType
.
methodType
(
oldType
.
returnType
(),
callTypeArgs
);
MethodType
callType
=
MethodType
.
methodType
(
oldType
.
returnType
(),
callTypeArgs
);
target
=
convertArguments
(
t
oken
,
t
arget
,
callType
,
oldType
,
null
);
target
=
convertArguments
(
target
,
callType
,
oldType
,
null
);
assert
(
target
!=
null
);
assert
(
target
!=
null
);
oldType
=
target
.
type
();
oldType
=
target
.
type
();
List
<
Integer
>
goal
=
new
ArrayList
<
Integer
>();
// i*TOKEN
List
<
Integer
>
goal
=
new
ArrayList
<
Integer
>();
// i*TOKEN
...
@@ -710,7 +597,7 @@ public abstract class MethodHandleImpl {
...
@@ -710,7 +597,7 @@ public abstract class MethodHandleImpl {
Collections
.
rotate
(
ptypes
.
subList
(
rotBeg
,
rotEnd
+
1
),
-
rotBy
);
Collections
.
rotate
(
ptypes
.
subList
(
rotBeg
,
rotEnd
+
1
),
-
rotBy
);
MethodType
rotType
=
MethodType
.
methodType
(
oldType
.
returnType
(),
ptypes
);
MethodType
rotType
=
MethodType
.
methodType
(
oldType
.
returnType
(),
ptypes
);
MethodHandle
nextTarget
MethodHandle
nextTarget
=
AdapterMethodHandle
.
makeRotateArguments
(
token
,
rotType
,
target
,
=
AdapterMethodHandle
.
makeRotateArguments
(
rotType
,
target
,
rotBeg
,
rotSpan
.
size
(),
rotBy
);
rotBeg
,
rotSpan
.
size
(),
rotBy
);
if
(
nextTarget
!=
null
)
{
if
(
nextTarget
!=
null
)
{
//System.out.println("Rot: "+rotSpan+" by "+rotBy);
//System.out.println("Rot: "+rotSpan+" by "+rotBy);
...
@@ -733,7 +620,7 @@ public abstract class MethodHandleImpl {
...
@@ -733,7 +620,7 @@ public abstract class MethodHandleImpl {
int
j
=
state
.
indexOf
(
arg
);
int
j
=
state
.
indexOf
(
arg
);
Collections
.
swap
(
ptypes
,
i
,
j
);
Collections
.
swap
(
ptypes
,
i
,
j
);
MethodType
swapType
=
MethodType
.
methodType
(
oldType
.
returnType
(),
ptypes
);
MethodType
swapType
=
MethodType
.
methodType
(
oldType
.
returnType
(),
ptypes
);
target
=
AdapterMethodHandle
.
makeSwapArguments
(
token
,
swapType
,
target
,
i
,
j
);
target
=
AdapterMethodHandle
.
makeSwapArguments
(
swapType
,
target
,
i
,
j
);
if
(
target
==
null
)
throw
newIllegalArgumentException
(
"cannot swap"
);
if
(
target
==
null
)
throw
newIllegalArgumentException
(
"cannot swap"
);
assert
(
target
.
type
()
==
swapType
);
assert
(
target
.
type
()
==
swapType
);
oldType
=
swapType
;
oldType
=
swapType
;
...
@@ -760,7 +647,7 @@ public abstract class MethodHandleImpl {
...
@@ -760,7 +647,7 @@ public abstract class MethodHandleImpl {
List
<
Class
<?>>
ptypes
=
oldType
.
parameterList
();
List
<
Class
<?>>
ptypes
=
oldType
.
parameterList
();
ptypes
=
ptypes
.
subList
(
0
,
ptypes
.
size
()
-
dupArgCount
);
ptypes
=
ptypes
.
subList
(
0
,
ptypes
.
size
()
-
dupArgCount
);
MethodType
dupType
=
MethodType
.
methodType
(
oldType
.
returnType
(),
ptypes
);
MethodType
dupType
=
MethodType
.
methodType
(
oldType
.
returnType
(),
ptypes
);
target
=
AdapterMethodHandle
.
makeDupArguments
(
token
,
dupType
,
target
,
dupArgPos
,
dupArgCount
);
target
=
AdapterMethodHandle
.
makeDupArguments
(
dupType
,
target
,
dupArgPos
,
dupArgCount
);
if
(
target
==
null
)
if
(
target
==
null
)
throw
newIllegalArgumentException
(
"cannot dup"
);
throw
newIllegalArgumentException
(
"cannot dup"
);
oldType
=
target
.
type
();
oldType
=
target
.
type
();
...
@@ -778,7 +665,7 @@ public abstract class MethodHandleImpl {
...
@@ -778,7 +665,7 @@ public abstract class MethodHandleImpl {
List
<
Class
<?>>
dropTypes
=
newType
.
parameterList
()
List
<
Class
<?>>
dropTypes
=
newType
.
parameterList
()
.
subList
(
dropArgPos
,
dropArgPos
+
dropArgCount
);
.
subList
(
dropArgPos
,
dropArgPos
+
dropArgCount
);
MethodType
dropType
=
oldType
.
insertParameterTypes
(
dropArgPos
,
dropTypes
);
MethodType
dropType
=
oldType
.
insertParameterTypes
(
dropArgPos
,
dropTypes
);
target
=
AdapterMethodHandle
.
makeDropArguments
(
token
,
dropType
,
target
,
dropArgPos
,
dropArgCount
);
target
=
AdapterMethodHandle
.
makeDropArguments
(
dropType
,
target
,
dropArgPos
,
dropArgCount
);
if
(
target
==
null
)
throw
newIllegalArgumentException
(
"cannot drop"
);
if
(
target
==
null
)
throw
newIllegalArgumentException
(
"cannot drop"
);
oldType
=
target
.
type
();
oldType
=
target
.
type
();
}
}
...
@@ -787,7 +674,7 @@ public abstract class MethodHandleImpl {
...
@@ -787,7 +674,7 @@ public abstract class MethodHandleImpl {
return
target
;
return
target
;
if
(
oldType
.
parameterCount
()
!=
newType
.
parameterCount
())
if
(
oldType
.
parameterCount
()
!=
newType
.
parameterCount
())
throw
newIllegalArgumentException
(
"mismatched parameter count"
);
throw
newIllegalArgumentException
(
"mismatched parameter count"
);
MethodHandle
res
=
AdapterMethodHandle
.
makePairwiseConvert
(
token
,
newType
,
target
);
MethodHandle
res
=
AdapterMethodHandle
.
makePairwiseConvert
(
newType
,
target
);
if
(
res
!=
null
)
if
(
res
!=
null
)
return
res
;
return
res
;
int
argc
=
oldType
.
parameterCount
();
int
argc
=
oldType
.
parameterCount
();
...
@@ -797,26 +684,24 @@ public abstract class MethodHandleImpl {
...
@@ -797,26 +684,24 @@ public abstract class MethodHandleImpl {
// then back to the desired types. We might have to use Java-based
// then back to the desired types. We might have to use Java-based
// method handles to do this.
// method handles to do this.
MethodType
objType
=
MethodType
.
genericMethodType
(
argc
);
MethodType
objType
=
MethodType
.
genericMethodType
(
argc
);
MethodHandle
objTarget
=
AdapterMethodHandle
.
makePairwiseConvert
(
token
,
objType
,
target
);
MethodHandle
objTarget
=
AdapterMethodHandle
.
makePairwiseConvert
(
objType
,
target
);
if
(
objTarget
==
null
)
if
(
objTarget
==
null
)
objTarget
=
FromGeneric
.
make
(
target
);
objTarget
=
FromGeneric
.
make
(
target
);
res
=
AdapterMethodHandle
.
makePairwiseConvert
(
token
,
newType
,
objTarget
);
res
=
AdapterMethodHandle
.
makePairwiseConvert
(
newType
,
objTarget
);
if
(
res
!=
null
)
if
(
res
!=
null
)
return
res
;
return
res
;
return
ToGeneric
.
make
(
newType
,
objTarget
);
return
ToGeneric
.
make
(
newType
,
objTarget
);
}
}
public
static
MethodHandle
spreadArguments
(
Access
token
,
static
MethodHandle
spreadArguments
(
MethodHandle
target
,
MethodHandle
target
,
MethodType
newType
,
MethodType
newType
,
int
spreadArg
)
{
int
spreadArg
)
{
Access
.
check
(
token
);
// TO DO: maybe allow the restarg to be Object and implicitly cast to Object[]
// TO DO: maybe allow the restarg to be Object and implicitly cast to Object[]
MethodType
oldType
=
target
.
type
();
MethodType
oldType
=
target
.
type
();
// spread the last argument of newType to oldType
// spread the last argument of newType to oldType
int
spreadCount
=
oldType
.
parameterCount
()
-
spreadArg
;
int
spreadCount
=
oldType
.
parameterCount
()
-
spreadArg
;
Class
<
Object
[]>
spreadArgType
=
Object
[].
class
;
Class
<
Object
[]>
spreadArgType
=
Object
[].
class
;
MethodHandle
res
=
AdapterMethodHandle
.
makeSpreadArguments
(
token
,
newType
,
target
,
spreadArgType
,
spreadArg
,
spreadCount
);
MethodHandle
res
=
AdapterMethodHandle
.
makeSpreadArguments
(
newType
,
target
,
spreadArgType
,
spreadArg
,
spreadCount
);
if
(
res
!=
null
)
if
(
res
!=
null
)
return
res
;
return
res
;
// try an intermediate adapter
// try an intermediate adapter
...
@@ -829,20 +714,19 @@ public abstract class MethodHandleImpl {
...
@@ -829,20 +714,19 @@ public abstract class MethodHandleImpl {
ptypes
[
spreadArg
+
i
]
=
VerifyType
.
spreadArgElementType
(
spreadType
,
i
);
ptypes
[
spreadArg
+
i
]
=
VerifyType
.
spreadArgElementType
(
spreadType
,
i
);
MethodType
midType
=
MethodType
.
methodType
(
newType
.
returnType
(),
ptypes
);
MethodType
midType
=
MethodType
.
methodType
(
newType
.
returnType
(),
ptypes
);
// after spreading, some arguments may need further conversion
// after spreading, some arguments may need further conversion
MethodHandle
target2
=
convertArguments
(
t
oken
,
t
arget
,
midType
,
oldType
,
null
);
MethodHandle
target2
=
convertArguments
(
target
,
midType
,
oldType
,
null
);
if
(
target2
==
null
)
if
(
target2
==
null
)
throw
new
UnsupportedOperationException
(
"NYI: convert "
+
midType
+
" =calls=> "
+
oldType
);
throw
new
UnsupportedOperationException
(
"NYI: convert "
+
midType
+
" =calls=> "
+
oldType
);
res
=
AdapterMethodHandle
.
makeSpreadArguments
(
token
,
newType
,
target2
,
spreadArgType
,
spreadArg
,
spreadCount
);
res
=
AdapterMethodHandle
.
makeSpreadArguments
(
newType
,
target2
,
spreadArgType
,
spreadArg
,
spreadCount
);
if
(
res
!=
null
)
if
(
res
!=
null
)
return
res
;
return
res
;
res
=
SpreadGeneric
.
make
(
target2
,
spreadCount
);
res
=
SpreadGeneric
.
make
(
target2
,
spreadCount
);
if
(
res
!=
null
)
if
(
res
!=
null
)
res
=
convertArguments
(
token
,
res
,
newType
,
res
.
type
(),
null
);
res
=
convertArguments
(
res
,
newType
,
res
.
type
(),
null
);
return
res
;
return
res
;
}
}
public
static
MethodHandle
collectArguments
(
Access
token
,
static
MethodHandle
collectArguments
(
MethodHandle
target
,
MethodHandle
target
,
MethodType
newType
,
MethodType
newType
,
int
collectArg
,
int
collectArg
,
MethodHandle
collector
)
{
MethodHandle
collector
)
{
...
@@ -856,29 +740,27 @@ public abstract class MethodHandleImpl {
...
@@ -856,29 +740,27 @@ public abstract class MethodHandleImpl {
// oldType // (a..., b...)=>r
// oldType // (a..., b...)=>r
assert
(
newType
.
parameterCount
()
==
collectArg
+
colType
.
parameterCount
());
assert
(
newType
.
parameterCount
()
==
collectArg
+
colType
.
parameterCount
());
assert
(
oldType
.
parameterCount
()
==
collectArg
+
1
);
assert
(
oldType
.
parameterCount
()
==
collectArg
+
1
);
MethodHandle
gtarget
=
convertArguments
(
t
oken
,
t
arget
,
oldType
.
generic
(),
oldType
,
null
);
MethodHandle
gtarget
=
convertArguments
(
target
,
oldType
.
generic
(),
oldType
,
null
);
MethodHandle
gcollector
=
convertArguments
(
token
,
collector
,
colType
.
generic
(),
colType
,
null
);
MethodHandle
gcollector
=
convertArguments
(
collector
,
colType
.
generic
(),
colType
,
null
);
if
(
gtarget
==
null
||
gcollector
==
null
)
return
null
;
if
(
gtarget
==
null
||
gcollector
==
null
)
return
null
;
MethodHandle
gresult
=
FilterGeneric
.
makeArgumentCollector
(
gcollector
,
gtarget
);
MethodHandle
gresult
=
FilterGeneric
.
makeArgumentCollector
(
gcollector
,
gtarget
);
MethodHandle
result
=
convertArguments
(
token
,
gresult
,
newType
,
gresult
.
type
(),
null
);
MethodHandle
result
=
convertArguments
(
gresult
,
newType
,
gresult
.
type
(),
null
);
return
result
;
return
result
;
}
}
public
static
MethodHandle
filterArgument
(
Access
token
,
static
MethodHandle
filterArgument
(
MethodHandle
target
,
MethodHandle
target
,
int
pos
,
int
pos
,
MethodHandle
filter
)
{
MethodHandle
filter
)
{
Access
.
check
(
token
);
MethodType
ttype
=
target
.
type
(),
gttype
=
ttype
.
generic
();
MethodType
ttype
=
target
.
type
(),
gttype
=
ttype
.
generic
();
if
(
ttype
!=
gttype
)
{
if
(
ttype
!=
gttype
)
{
target
=
convertArguments
(
t
oken
,
t
arget
,
gttype
,
ttype
,
null
);
target
=
convertArguments
(
target
,
gttype
,
ttype
,
null
);
ttype
=
gttype
;
ttype
=
gttype
;
}
}
MethodType
ftype
=
filter
.
type
(),
gftype
=
ftype
.
generic
();
MethodType
ftype
=
filter
.
type
(),
gftype
=
ftype
.
generic
();
if
(
ftype
.
parameterCount
()
!=
1
)
if
(
ftype
.
parameterCount
()
!=
1
)
throw
new
InternalError
();
throw
new
InternalError
();
if
(
ftype
!=
gftype
)
{
if
(
ftype
!=
gftype
)
{
filter
=
convertArguments
(
token
,
filter
,
gftype
,
ftype
,
null
);
filter
=
convertArguments
(
filter
,
gftype
,
ftype
,
null
);
ftype
=
gftype
;
ftype
=
gftype
;
}
}
if
(
ftype
==
ttype
)
{
if
(
ftype
==
ttype
)
{
...
@@ -888,27 +770,24 @@ public abstract class MethodHandleImpl {
...
@@ -888,27 +770,24 @@ public abstract class MethodHandleImpl {
return
FilterGeneric
.
makeArgumentFilter
(
pos
,
filter
,
target
);
return
FilterGeneric
.
makeArgumentFilter
(
pos
,
filter
,
target
);
}
}
public
static
MethodHandle
foldArguments
(
Access
token
,
static
MethodHandle
foldArguments
(
MethodHandle
target
,
MethodHandle
target
,
MethodType
newType
,
MethodType
newType
,
MethodHandle
combiner
)
{
MethodHandle
combiner
)
{
Access
.
check
(
token
);
MethodType
oldType
=
target
.
type
();
MethodType
oldType
=
target
.
type
();
MethodType
ctype
=
combiner
.
type
();
MethodType
ctype
=
combiner
.
type
();
MethodHandle
gtarget
=
convertArguments
(
t
oken
,
t
arget
,
oldType
.
generic
(),
oldType
,
null
);
MethodHandle
gtarget
=
convertArguments
(
target
,
oldType
.
generic
(),
oldType
,
null
);
MethodHandle
gcombiner
=
convertArguments
(
token
,
combiner
,
ctype
.
generic
(),
ctype
,
null
);
MethodHandle
gcombiner
=
convertArguments
(
combiner
,
ctype
.
generic
(),
ctype
,
null
);
if
(
gtarget
==
null
||
gcombiner
==
null
)
return
null
;
if
(
gtarget
==
null
||
gcombiner
==
null
)
return
null
;
MethodHandle
gresult
=
FilterGeneric
.
makeArgumentFolder
(
gcombiner
,
gtarget
);
MethodHandle
gresult
=
FilterGeneric
.
makeArgumentFolder
(
gcombiner
,
gtarget
);
MethodHandle
result
=
convertArguments
(
token
,
gresult
,
newType
,
gresult
.
type
(),
null
);
MethodHandle
result
=
convertArguments
(
gresult
,
newType
,
gresult
.
type
(),
null
);
return
result
;
return
result
;
}
}
public
static
static
MethodHandle
dropArguments
(
Access
token
,
MethodHandle
target
,
MethodHandle
dropArguments
(
MethodHandle
target
,
MethodType
newType
,
int
argnum
)
{
MethodType
newType
,
int
argnum
)
{
Access
.
check
(
token
);
int
drops
=
newType
.
parameterCount
()
-
target
.
type
().
parameterCount
();
int
drops
=
newType
.
parameterCount
()
-
target
.
type
().
parameterCount
();
MethodHandle
res
=
AdapterMethodHandle
.
makeDropArguments
(
token
,
newType
,
target
,
argnum
,
drops
);
MethodHandle
res
=
AdapterMethodHandle
.
makeDropArguments
(
newType
,
target
,
argnum
,
drops
);
if
(
res
!=
null
)
if
(
res
!=
null
)
return
res
;
return
res
;
throw
new
UnsupportedOperationException
(
"NYI"
);
throw
new
UnsupportedOperationException
(
"NYI"
);
...
@@ -918,36 +797,34 @@ public abstract class MethodHandleImpl {
...
@@ -918,36 +797,34 @@ public abstract class MethodHandleImpl {
private
final
MethodHandle
test
,
target
,
fallback
;
private
final
MethodHandle
test
,
target
,
fallback
;
private
GuardWithTest
(
MethodHandle
invoker
,
private
GuardWithTest
(
MethodHandle
invoker
,
MethodHandle
test
,
MethodHandle
target
,
MethodHandle
fallback
)
{
MethodHandle
test
,
MethodHandle
target
,
MethodHandle
fallback
)
{
super
(
Access
.
TOKEN
,
invoker
);
super
(
invoker
);
this
.
test
=
test
;
this
.
test
=
test
;
this
.
target
=
target
;
this
.
target
=
target
;
this
.
fallback
=
fallback
;
this
.
fallback
=
fallback
;
}
}
static
MethodHandle
make
(
Access
token
,
static
MethodHandle
make
(
MethodHandle
test
,
MethodHandle
target
,
MethodHandle
fallback
)
{
MethodHandle
test
,
MethodHandle
target
,
MethodHandle
fallback
)
{
Access
.
check
(
token
);
MethodType
type
=
target
.
type
();
MethodType
type
=
target
.
type
();
int
nargs
=
type
.
parameterCount
();
int
nargs
=
type
.
parameterCount
();
if
(
nargs
<
INVOKES
.
length
)
{
if
(
nargs
<
INVOKES
.
length
)
{
MethodHandle
invoke
=
INVOKES
[
nargs
];
MethodHandle
invoke
=
INVOKES
[
nargs
];
MethodType
gtype
=
type
.
generic
();
MethodType
gtype
=
type
.
generic
();
assert
(
invoke
.
type
().
dropParameterTypes
(
0
,
1
)
==
gtype
);
assert
(
invoke
.
type
().
dropParameterTypes
(
0
,
1
)
==
gtype
);
MethodHandle
gtest
=
convertArguments
(
t
oken
,
t
est
,
gtype
.
changeReturnType
(
boolean
.
class
),
test
.
type
(),
null
);
MethodHandle
gtest
=
convertArguments
(
test
,
gtype
.
changeReturnType
(
boolean
.
class
),
test
.
type
(),
null
);
MethodHandle
gtarget
=
convertArguments
(
t
oken
,
t
arget
,
gtype
,
type
,
null
);
MethodHandle
gtarget
=
convertArguments
(
target
,
gtype
,
type
,
null
);
MethodHandle
gfallback
=
convertArguments
(
token
,
fallback
,
gtype
,
type
,
null
);
MethodHandle
gfallback
=
convertArguments
(
fallback
,
gtype
,
type
,
null
);
if
(
gtest
==
null
||
gtarget
==
null
||
gfallback
==
null
)
return
null
;
if
(
gtest
==
null
||
gtarget
==
null
||
gfallback
==
null
)
return
null
;
MethodHandle
gguard
=
new
GuardWithTest
(
invoke
,
gtest
,
gtarget
,
gfallback
);
MethodHandle
gguard
=
new
GuardWithTest
(
invoke
,
gtest
,
gtarget
,
gfallback
);
return
convertArguments
(
token
,
gguard
,
type
,
gtype
,
null
);
return
convertArguments
(
gguard
,
type
,
gtype
,
null
);
}
else
{
}
else
{
MethodHandle
invoke
=
VARARGS_INVOKE
;
MethodHandle
invoke
=
VARARGS_INVOKE
;
MethodType
gtype
=
MethodType
.
genericMethodType
(
1
);
MethodType
gtype
=
MethodType
.
genericMethodType
(
1
);
assert
(
invoke
.
type
().
dropParameterTypes
(
0
,
1
)
==
gtype
);
assert
(
invoke
.
type
().
dropParameterTypes
(
0
,
1
)
==
gtype
);
MethodHandle
gtest
=
spreadArguments
(
t
oken
,
t
est
,
gtype
.
changeReturnType
(
boolean
.
class
),
0
);
MethodHandle
gtest
=
spreadArguments
(
test
,
gtype
.
changeReturnType
(
boolean
.
class
),
0
);
MethodHandle
gtarget
=
spreadArguments
(
t
oken
,
t
arget
,
gtype
,
0
);
MethodHandle
gtarget
=
spreadArguments
(
target
,
gtype
,
0
);
MethodHandle
gfallback
=
spreadArguments
(
token
,
fallback
,
gtype
,
0
);
MethodHandle
gfallback
=
spreadArguments
(
fallback
,
gtype
,
0
);
MethodHandle
gguard
=
new
GuardWithTest
(
invoke
,
gtest
,
gtarget
,
gfallback
);
MethodHandle
gguard
=
new
GuardWithTest
(
invoke
,
gtest
,
gtarget
,
gfallback
);
if
(
gtest
==
null
||
gtarget
==
null
||
gfallback
==
null
)
return
null
;
if
(
gtest
==
null
||
gtarget
==
null
||
gfallback
==
null
)
return
null
;
return
collectArguments
(
token
,
gguard
,
type
,
0
,
null
);
return
collectArguments
(
gguard
,
type
,
0
,
null
);
}
}
}
}
@Override
@Override
...
@@ -1034,24 +911,23 @@ public abstract class MethodHandleImpl {
...
@@ -1034,24 +911,23 @@ public abstract class MethodHandleImpl {
}
}
}
}
public
static
static
MethodHandle
makeGuardWithTest
(
Access
token
,
MethodHandle
makeGuardWithTest
(
MethodHandle
test
,
MethodHandle
test
,
MethodHandle
target
,
MethodHandle
target
,
MethodHandle
fallback
)
{
MethodHandle
fallback
)
{
return
GuardWithTest
.
make
(
t
oken
,
t
est
,
target
,
fallback
);
return
GuardWithTest
.
make
(
test
,
target
,
fallback
);
}
}
private
static
class
GuardWithCatch
extends
BoundMethodHandle
{
private
static
class
GuardWithCatch
extends
BoundMethodHandle
{
private
final
MethodHandle
target
;
private
final
MethodHandle
target
;
private
final
Class
<?
extends
Throwable
>
exType
;
private
final
Class
<?
extends
Throwable
>
exType
;
private
final
MethodHandle
catcher
;
private
final
MethodHandle
catcher
;
public
GuardWithCatch
(
MethodHandle
target
,
Class
<?
extends
Throwable
>
exType
,
MethodHandle
catcher
)
{
GuardWithCatch
(
MethodHandle
target
,
Class
<?
extends
Throwable
>
exType
,
MethodHandle
catcher
)
{
this
(
INVOKES
[
target
.
type
().
parameterCount
()],
target
,
exType
,
catcher
);
this
(
INVOKES
[
target
.
type
().
parameterCount
()],
target
,
exType
,
catcher
);
}
}
public
GuardWithCatch
(
MethodHandle
invoker
,
GuardWithCatch
(
MethodHandle
invoker
,
MethodHandle
target
,
Class
<?
extends
Throwable
>
exType
,
MethodHandle
catcher
)
{
MethodHandle
target
,
Class
<?
extends
Throwable
>
exType
,
MethodHandle
catcher
)
{
super
(
Access
.
TOKEN
,
invoker
);
super
(
invoker
);
this
.
target
=
target
;
this
.
target
=
target
;
this
.
exType
=
exType
;
this
.
exType
=
exType
;
this
.
catcher
=
catcher
;
this
.
catcher
=
catcher
;
...
@@ -1171,42 +1047,40 @@ public abstract class MethodHandleImpl {
...
@@ -1171,42 +1047,40 @@ public abstract class MethodHandleImpl {
}
}
public
static
static
MethodHandle
makeGuardWithCatch
(
Access
token
,
MethodHandle
makeGuardWithCatch
(
MethodHandle
target
,
MethodHandle
target
,
Class
<?
extends
Throwable
>
exType
,
Class
<?
extends
Throwable
>
exType
,
MethodHandle
catcher
)
{
MethodHandle
catcher
)
{
Access
.
check
(
token
);
MethodType
type
=
target
.
type
();
MethodType
type
=
target
.
type
();
MethodType
ctype
=
catcher
.
type
();
MethodType
ctype
=
catcher
.
type
();
int
nargs
=
type
.
parameterCount
();
int
nargs
=
type
.
parameterCount
();
if
(
nargs
<
GuardWithCatch
.
INVOKES
.
length
)
{
if
(
nargs
<
GuardWithCatch
.
INVOKES
.
length
)
{
MethodType
gtype
=
type
.
generic
();
MethodType
gtype
=
type
.
generic
();
MethodType
gcatchType
=
gtype
.
insertParameterTypes
(
0
,
Throwable
.
class
);
MethodType
gcatchType
=
gtype
.
insertParameterTypes
(
0
,
Throwable
.
class
);
MethodHandle
gtarget
=
convertArguments
(
t
oken
,
t
arget
,
gtype
,
type
,
null
);
MethodHandle
gtarget
=
convertArguments
(
target
,
gtype
,
type
,
null
);
MethodHandle
gcatcher
=
convertArguments
(
token
,
catcher
,
gcatchType
,
ctype
,
null
);
MethodHandle
gcatcher
=
convertArguments
(
catcher
,
gcatchType
,
ctype
,
null
);
MethodHandle
gguard
=
new
GuardWithCatch
(
gtarget
,
exType
,
gcatcher
);
MethodHandle
gguard
=
new
GuardWithCatch
(
gtarget
,
exType
,
gcatcher
);
if
(
gtarget
==
null
||
gcatcher
==
null
||
gguard
==
null
)
return
null
;
if
(
gtarget
==
null
||
gcatcher
==
null
||
gguard
==
null
)
return
null
;
return
convertArguments
(
token
,
gguard
,
type
,
gtype
,
null
);
return
convertArguments
(
gguard
,
type
,
gtype
,
null
);
}
else
{
}
else
{
MethodType
gtype
=
MethodType
.
genericMethodType
(
0
,
true
);
MethodType
gtype
=
MethodType
.
genericMethodType
(
0
,
true
);
MethodType
gcatchType
=
gtype
.
insertParameterTypes
(
0
,
Throwable
.
class
);
MethodType
gcatchType
=
gtype
.
insertParameterTypes
(
0
,
Throwable
.
class
);
MethodHandle
gtarget
=
spreadArguments
(
t
oken
,
t
arget
,
gtype
,
0
);
MethodHandle
gtarget
=
spreadArguments
(
target
,
gtype
,
0
);
MethodHandle
gcatcher
=
spreadArguments
(
token
,
catcher
,
gcatchType
,
1
);
MethodHandle
gcatcher
=
spreadArguments
(
catcher
,
gcatchType
,
1
);
MethodHandle
gguard
=
new
GuardWithCatch
(
GuardWithCatch
.
VARARGS_INVOKE
,
gtarget
,
exType
,
gcatcher
);
MethodHandle
gguard
=
new
GuardWithCatch
(
GuardWithCatch
.
VARARGS_INVOKE
,
gtarget
,
exType
,
gcatcher
);
if
(
gtarget
==
null
||
gcatcher
==
null
||
gguard
==
null
)
return
null
;
if
(
gtarget
==
null
||
gcatcher
==
null
||
gguard
==
null
)
return
null
;
return
collectArguments
(
token
,
gguard
,
type
,
0
,
null
);
return
collectArguments
(
gguard
,
type
,
0
,
null
);
}
}
}
}
public
static
static
MethodHandle
throwException
(
Access
token
,
MethodType
type
)
{
MethodHandle
throwException
(
MethodType
type
)
{
Access
.
check
(
token
);
return
AdapterMethodHandle
.
makeRetypeRaw
(
type
,
throwException
());
return
AdapterMethodHandle
.
makeRetypeRaw
(
token
,
type
,
THROW_EXCEPTION
);
}
}
static
final
MethodHandle
THROW_EXCEPTION
;
static
MethodHandle
THROW_EXCEPTION
;
static
{
static
MethodHandle
throwException
()
{
if
(
THROW_EXCEPTION
!=
null
)
return
THROW_EXCEPTION
;
try
{
try
{
THROW_EXCEPTION
THROW_EXCEPTION
=
IMPL_LOOKUP
.
findStatic
(
MethodHandleImpl
.
class
,
"throwException"
,
=
IMPL_LOOKUP
.
findStatic
(
MethodHandleImpl
.
class
,
"throwException"
,
...
@@ -1214,71 +1088,19 @@ public abstract class MethodHandleImpl {
...
@@ -1214,71 +1088,19 @@ public abstract class MethodHandleImpl {
}
catch
(
ReflectiveOperationException
ex
)
{
}
catch
(
ReflectiveOperationException
ex
)
{
throw
new
RuntimeException
(
ex
);
throw
new
RuntimeException
(
ex
);
}
}
return
THROW_EXCEPTION
;
}
}
static
<
T
extends
Throwable
>
Empty
throwException
(
T
t
)
throws
T
{
throw
t
;
}
static
<
T
extends
Throwable
>
Empty
throwException
(
T
t
)
throws
T
{
throw
t
;
}
public
static
String
getNameString
(
Access
token
,
MethodHandle
target
,
Object
type
)
{
Access
.
check
(
token
);
if
(!(
type
instanceof
MethodType
))
{
if
(
type
==
null
)
type
=
target
.
type
();
else
if
(
type
instanceof
MethodHandle
)
type
=
((
MethodHandle
)
type
).
type
();
}
MemberName
name
=
null
;
if
(
target
!=
null
)
name
=
MethodHandleNatives
.
getMethodName
(
target
);
if
(
name
==
null
)
return
"invoke"
+
type
;
return
name
.
getName
()
+
type
;
}
public
static
String
getNameString
(
Access
token
,
MethodHandle
target
)
{
return
getNameString
(
token
,
target
,
null
);
}
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
();
}
static
void
checkSpreadArgument
(
Object
av
,
int
n
)
{
if
(
av
==
null
?
n
!=
0
:
((
Object
[])
av
).
length
!=
n
)
throw
newIllegalArgumentException
(
"Array is not of length "
+
n
);
}
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
))
actual
=
actual
.
getClass
();
if
(
actual
!=
null
)
message
=
"required "
+
required
+
" but encountered "
+
actual
;
else
message
=
"required "
+
required
;
switch
(
code
)
{
case
192
:
// checkcast
throw
new
ClassCastException
(
message
);
default
:
throw
new
InternalError
(
"unexpected code "
+
code
+
": "
+
message
);
}
}
// Linkage support:
// Linkage support:
public
static
void
registerBootstrap
(
Access
token
,
Class
<?>
callerClass
,
MethodHandle
bootstrapMethod
)
{
static
void
registerBootstrap
(
Class
<?>
callerClass
,
MethodHandle
bootstrapMethod
)
{
Access
.
check
(
token
);
MethodHandleNatives
.
registerBootstrap
(
callerClass
,
bootstrapMethod
);
MethodHandleNatives
.
registerBootstrap
(
callerClass
,
bootstrapMethod
);
}
}
public
static
MethodHandle
getBootstrap
(
Access
token
,
Class
<?>
callerClass
)
{
static
MethodHandle
getBootstrap
(
Class
<?>
callerClass
)
{
Access
.
check
(
token
);
return
MethodHandleNatives
.
getBootstrap
(
callerClass
);
return
MethodHandleNatives
.
getBootstrap
(
callerClass
);
}
}
public
static
MethodHandle
asVarargsCollector
(
Access
token
,
MethodHandle
target
,
Class
<?>
arrayType
)
{
static
MethodHandle
asVarargsCollector
(
MethodHandle
target
,
Class
<?>
arrayType
)
{
Access
.
check
(
token
);
return
AdapterMethodHandle
.
makeVarargsCollector
(
target
,
arrayType
);
return
AdapterMethodHandle
.
makeVarargsCollector
(
token
,
target
,
arrayType
);
}
}
}
}
src/share/classes/
sun/dyn
/MethodHandleNatives.java
→
src/share/classes/
java/lang/invoke
/MethodHandleNatives.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,14 +23,13 @@
...
@@ -23,14 +23,13 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
java.dyn.*
;
import
java.lang.invoke.MethodHandles.Lookup
;
import
java.dyn.MethodHandles.Lookup
;
import
java.lang.reflect.AccessibleObject
;
import
java.lang.reflect.AccessibleObject
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Field
;
import
static
sun
.
dyn
.
MethodHandleNatives
.
Constants
.*;
import
static
java
.
lang
.
invoke
.
MethodHandleNatives
.
Constants
.*;
import
static
sun
.
dyn
.
MethodHandleImpl
.
IMPL_LOOKUP
;
import
static
java
.
lang
.
invoke
.
MethodHandles
.
Lookup
.
IMPL_LOOKUP
;
/**
/**
* The JVM interface for the method handles package is all here.
* The JVM interface for the method handles package is all here.
...
@@ -81,14 +80,12 @@ class MethodHandleNatives {
...
@@ -81,14 +80,12 @@ class MethodHandleNatives {
* This routine is for debugging and reflection.
* This routine is for debugging and reflection.
*/
*/
static
MemberName
getMethodName
(
MethodHandle
self
)
{
static
MemberName
getMethodName
(
MethodHandle
self
)
{
if
(!
JVM_SUPPORT
)
return
null
;
return
(
MemberName
)
getTarget
(
self
,
ETF_METHOD_NAME
);
return
(
MemberName
)
getTarget
(
self
,
ETF_METHOD_NAME
);
}
}
/** Fetch the reflective version of the handled method, if available.
/** Fetch the reflective version of the handled method, if available.
*/
*/
static
AccessibleObject
getTargetMethod
(
MethodHandle
self
)
{
static
AccessibleObject
getTargetMethod
(
MethodHandle
self
)
{
if
(!
JVM_SUPPORT
)
return
null
;
return
(
AccessibleObject
)
getTarget
(
self
,
ETF_REFLECT_METHOD
);
return
(
AccessibleObject
)
getTarget
(
self
,
ETF_REFLECT_METHOD
);
}
}
...
@@ -97,7 +94,6 @@ class MethodHandleNatives {
...
@@ -97,7 +94,6 @@ class MethodHandleNatives {
* If it is chained to another method handle, return that handle.
* If it is chained to another method handle, return that handle.
*/
*/
static
Object
getTargetInfo
(
MethodHandle
self
)
{
static
Object
getTargetInfo
(
MethodHandle
self
)
{
if
(!
JVM_SUPPORT
)
return
null
;
return
getTarget
(
self
,
ETF_HANDLE_OR_METHOD_NAME
);
return
getTarget
(
self
,
ETF_HANDLE_OR_METHOD_NAME
);
}
}
...
@@ -111,11 +107,6 @@ class MethodHandleNatives {
...
@@ -111,11 +107,6 @@ class MethodHandleNatives {
*/
*/
static
native
int
getConstant
(
int
which
);
static
native
int
getConstant
(
int
which
);
/** True iff this HotSpot JVM has built-in support for method handles.
* If false, some test cases might run, but functionality will be missing.
*/
public
static
final
boolean
JVM_SUPPORT
;
/** Java copy of MethodHandlePushLimit in range 2..255. */
/** Java copy of MethodHandlePushLimit in range 2..255. */
static
final
int
JVM_PUSH_LIMIT
;
static
final
int
JVM_PUSH_LIMIT
;
/** JVM stack motion (in words) after one slot is pushed, usually -1.
/** JVM stack motion (in words) after one slot is pushed, usually -1.
...
@@ -127,31 +118,24 @@ class MethodHandleNatives {
...
@@ -127,31 +118,24 @@ class MethodHandleNatives {
private
static
native
void
registerNatives
();
private
static
native
void
registerNatives
();
static
{
static
{
boolean
JVM_SUPPORT_
;
int
JVM_PUSH_LIMIT_
;
int
JVM_PUSH_LIMIT_
;
int
JVM_STACK_MOVE_UNIT_
;
int
JVM_STACK_MOVE_UNIT_
;
int
CONV_OP_IMPLEMENTED_MASK_
;
int
CONV_OP_IMPLEMENTED_MASK_
;
try
{
try
{
registerNatives
();
registerNatives
();
JVM_SUPPORT_
=
true
;
JVM_PUSH_LIMIT_
=
getConstant
(
Constants
.
GC_JVM_PUSH_LIMIT
);
JVM_PUSH_LIMIT_
=
getConstant
(
Constants
.
GC_JVM_PUSH_LIMIT
);
JVM_STACK_MOVE_UNIT_
=
getConstant
(
Constants
.
GC_JVM_STACK_MOVE_UNIT
);
JVM_STACK_MOVE_UNIT_
=
getConstant
(
Constants
.
GC_JVM_STACK_MOVE_UNIT
);
CONV_OP_IMPLEMENTED_MASK_
=
getConstant
(
Constants
.
GC_CONV_OP_IMPLEMENTED_MASK
);
CONV_OP_IMPLEMENTED_MASK_
=
getConstant
(
Constants
.
GC_CONV_OP_IMPLEMENTED_MASK
);
//sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
//sun.reflect.Reflection.registerMethodsToFilter(MethodHandleImpl.class, "init");
}
catch
(
UnsatisfiedLinkError
ee
)
{
}
catch
(
UnsatisfiedLinkError
ee
)
{
// ignore; if we use init() methods later we'll see linkage errors
// ignore; if we use init() methods later we'll see linkage errors
JVM_SUPPORT_
=
false
;
JVM_PUSH_LIMIT_
=
3
;
// arbitrary
JVM_PUSH_LIMIT_
=
3
;
// arbitrary
JVM_STACK_MOVE_UNIT_
=
-
1
;
// arbitrary
JVM_STACK_MOVE_UNIT_
=
-
1
;
// arbitrary
CONV_OP_IMPLEMENTED_MASK_
=
0
;
CONV_OP_IMPLEMENTED_MASK_
=
0
;
//System.out.println("Warning: Running with JVM_SUPPORT=false");
//System.out.println(ee);
JVM_SUPPORT
=
JVM_SUPPORT_
;
JVM_PUSH_LIMIT
=
JVM_PUSH_LIMIT_
;
JVM_PUSH_LIMIT
=
JVM_PUSH_LIMIT_
;
JVM_STACK_MOVE_UNIT
=
JVM_STACK_MOVE_UNIT_
;
JVM_STACK_MOVE_UNIT
=
JVM_STACK_MOVE_UNIT_
;
throw
ee
;
// just die; hopeless to try to run with an older JVM
throw
ee
;
// just die; hopeless to try to run with an older JVM
}
}
JVM_SUPPORT
=
JVM_SUPPORT_
;
JVM_PUSH_LIMIT
=
JVM_PUSH_LIMIT_
;
JVM_PUSH_LIMIT
=
JVM_PUSH_LIMIT_
;
JVM_STACK_MOVE_UNIT
=
JVM_STACK_MOVE_UNIT_
;
JVM_STACK_MOVE_UNIT
=
JVM_STACK_MOVE_UNIT_
;
if
(
CONV_OP_IMPLEMENTED_MASK_
==
0
)
if
(
CONV_OP_IMPLEMENTED_MASK_
==
0
)
...
@@ -189,9 +173,15 @@ class MethodHandleNatives {
...
@@ -189,9 +173,15 @@ class MethodHandleNatives {
MN_SEARCH_INTERFACES
=
0x00200000
,
// for MHN.getMembers
MN_SEARCH_INTERFACES
=
0x00200000
,
// for MHN.getMembers
VM_INDEX_UNINITIALIZED
=
-
99
;
VM_INDEX_UNINITIALIZED
=
-
99
;
// BoundMethodHandle
/** Constants for decoding the vmargslot field, which contains 2 values. */
static
final
int
ARG_SLOT_PUSH_SHIFT
=
16
,
ARG_SLOT_MASK
=
(
1
<<
ARG_SLOT_PUSH_SHIFT
)-
1
;
// AdapterMethodHandle
// AdapterMethodHandle
/** Conversions recognized by the JVM.
/** Conversions recognized by the JVM.
* They must align with the constants in
sun.dyn_
AdapterMethodHandle,
* They must align with the constants in
java.lang.invoke.
AdapterMethodHandle,
* in the JVM file hotspot/src/share/vm/classfile/javaClasses.hpp.
* in the JVM file hotspot/src/share/vm/classfile/javaClasses.hpp.
*/
*/
static
final
int
static
final
int
...
@@ -292,7 +282,7 @@ class MethodHandleNatives {
...
@@ -292,7 +282,7 @@ class MethodHandleNatives {
return
true
;
return
true
;
}
}
static
{
static
{
if
(
JVM_SUPPORT
)
verifyConstants
();
verifyConstants
();
}
}
// Up-calls from the JVM.
// Up-calls from the JVM.
...
@@ -305,28 +295,47 @@ class MethodHandleNatives {
...
@@ -305,28 +295,47 @@ class MethodHandleNatives {
String
name
,
MethodType
type
,
String
name
,
MethodType
type
,
Object
info
,
Object
info
,
MemberName
callerMethod
,
int
callerBCI
)
{
MemberName
callerMethod
,
int
callerBCI
)
{
return
CallSiteImpl
.
makeSite
(
bootstrapMethod
,
name
,
type
,
info
,
callerMethod
,
callerBCI
);
return
CallSite
.
makeSite
(
bootstrapMethod
,
name
,
type
,
info
,
callerMethod
,
callerBCI
);
}
/**
* Called by the JVM to check the length of a spread array.
*/
static
void
checkSpreadArgument
(
Object
av
,
int
n
)
{
MethodHandleStatics
.
checkSpreadArgument
(
av
,
n
);
}
}
/**
/**
* The JVM wants a pointer to a MethodType. Oblige it by finding or creating one.
* The JVM wants a pointer to a MethodType. Oblige it by finding or creating one.
*/
*/
static
MethodType
findMethodHandleType
(
Class
<?>
rtype
,
Class
<?>[]
ptypes
)
{
static
MethodType
findMethodHandleType
(
Class
<?>
rtype
,
Class
<?>[]
ptypes
)
{
MethodType
.
genericMethodType
(
0
);
// trigger initialization
return
MethodType
.
makeImpl
(
rtype
,
ptypes
,
true
);
return
MethodTypeImpl
.
makeImpl
(
Access
.
TOKEN
,
rtype
,
ptypes
,
true
);
}
}
/**
/**
* The JVM wants to use a MethodType with invokeGeneric. Give the runtime fair warning.
* The JVM wants to use a MethodType with invokeGeneric. Give the runtime fair warning.
*/
*/
static
void
notifyGenericMethodType
(
MethodType
type
)
{
static
void
notifyGenericMethodType
(
MethodType
type
)
{
try
{
type
.
form
().
notifyGenericMethodType
();
// Trigger adapter creation.
}
InvokeGeneric
.
genericInvokerOf
(
type
);
}
catch
(
Exception
ex
)
{
/**
Error
err
=
new
InternalError
(
"Exception while resolving invokeGeneric"
);
* The JVM wants to raise an exception. Here's the path.
err
.
initCause
(
ex
);
*/
throw
err
;
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
))
actual
=
actual
.
getClass
();
if
(
actual
!=
null
)
message
=
"required "
+
required
+
" but encountered "
+
actual
;
else
message
=
"required "
+
required
;
switch
(
code
)
{
case
192
:
// checkcast
throw
new
ClassCastException
(
message
);
default
:
throw
new
InternalError
(
"unexpected code "
+
code
+
": "
+
message
);
}
}
}
}
...
...
src/share/classes/java/lang/invoke/MethodHandleStatics.java
0 → 100644
浏览文件 @
33ee9ccf
/*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package
java.lang.invoke
;
/**
* This class consists exclusively of static names internal to the
* method handle implementation.
* Usage: {@code import static java.lang.invoke.MethodHandleStatics.*}
* @author John Rose, JSR 292 EG
*/
/*non-public*/
class
MethodHandleStatics
{
private
MethodHandleStatics
()
{
}
// do not instantiate
/*non-public*/
static
String
getNameString
(
MethodHandle
target
,
MethodType
type
)
{
if
(
type
==
null
)
type
=
target
.
type
();
MemberName
name
=
null
;
if
(
target
!=
null
)
name
=
MethodHandleNatives
.
getMethodName
(
target
);
if
(
name
==
null
)
return
"invoke"
+
type
;
return
name
.
getName
()
+
type
;
}
/*non-public*/
static
String
getNameString
(
MethodHandle
target
,
MethodHandle
typeHolder
)
{
return
getNameString
(
target
,
typeHolder
==
null
?
(
MethodType
)
null
:
typeHolder
.
type
());
}
/*non-public*/
static
String
getNameString
(
MethodHandle
target
)
{
return
getNameString
(
target
,
(
MethodType
)
null
);
}
/*non-public*/
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
();
}
static
void
checkSpreadArgument
(
Object
av
,
int
n
)
{
if
(
av
==
null
?
n
!=
0
:
((
Object
[])
av
).
length
!=
n
)
throw
newIllegalArgumentException
(
"Array is not of length "
+
n
);
}
// handy shared exception makers (they simplify the common case code)
/*non-public*/
static
RuntimeException
newIllegalStateException
(
String
message
)
{
return
new
IllegalStateException
(
message
);
}
/*non-public*/
static
RuntimeException
newIllegalStateException
(
String
message
,
Object
obj
)
{
return
new
IllegalStateException
(
message
(
message
,
obj
));
}
/*non-public*/
static
RuntimeException
newIllegalArgumentException
(
String
message
)
{
return
new
IllegalArgumentException
(
message
);
}
/*non-public*/
static
RuntimeException
newIllegalArgumentException
(
String
message
,
Object
obj
)
{
return
new
IllegalArgumentException
(
message
(
message
,
obj
));
}
/*non-public*/
static
Error
uncaughtException
(
Exception
ex
)
{
Error
err
=
new
InternalError
(
"uncaught exception"
);
err
.
initCause
(
ex
);
return
err
;
}
private
static
String
message
(
String
message
,
Object
obj
)
{
if
(
obj
!=
null
)
message
=
message
+
": "
+
obj
;
return
message
;
}
}
src/share/classes/java/
dyn
/MethodHandles.java
→
src/share/classes/java/
lang/invoke
/MethodHandles.java
浏览文件 @
33ee9ccf
...
@@ -23,24 +23,18 @@
...
@@ -23,24 +23,18 @@
* questions.
* questions.
*/
*/
package
java.
dyn
;
package
java.
lang.invoke
;
import
java.lang.reflect.*
;
import
java.lang.reflect.*
;
import
sun.dyn.Access
;
import
sun.invoke.WrapperInstance
;
import
sun.dyn.MemberName
;
import
sun.invoke.util.ValueConversions
;
import
sun.dyn.MethodHandleImpl
;
import
sun.invoke.util.VerifyAccess
;
import
sun.dyn.WrapperInstance
;
import
sun.invoke.util.Wrapper
;
import
sun.dyn.util.ValueConversions
;
import
sun.dyn.util.VerifyAccess
;
import
sun.dyn.util.Wrapper
;
import
java.util.List
;
import
java.util.List
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
sun.dyn.Invokers
;
import
sun.dyn.MethodTypeImpl
;
import
sun.reflect.Reflection
;
import
sun.reflect.Reflection
;
import
static
sun
.
dyn
.
MemberName
.
newIllegalArgumentException
;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
import
static
sun
.
dyn
.
MemberName
.
newNoAccessException
;
/**
/**
* This class consists exclusively of static methods that operate on or return
* This class consists exclusively of static methods that operate on or return
...
@@ -49,7 +43,7 @@ import static sun.dyn.MemberName.newNoAccessException;
...
@@ -49,7 +43,7 @@ import static sun.dyn.MemberName.newNoAccessException;
* <li>Lookup methods which help create method handles for methods and fields.
* <li>Lookup methods which help create method handles for methods and fields.
* <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
* <li>Combinator methods, which combine or transform pre-existing method handles into new ones.
* <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
* <li>Other factory methods to create method handles that emulate other common JVM operations or control flow patterns.
* <li>Wrapper methods which can convert between method handles and
other function-like "SAM types"
.
* <li>Wrapper methods which can convert between method handles and
interface types
.
* </ul>
* </ul>
* <p>
* <p>
* @author John Rose, JSR 292 EG
* @author John Rose, JSR 292 EG
...
@@ -58,15 +52,14 @@ public class MethodHandles {
...
@@ -58,15 +52,14 @@ public class MethodHandles {
private
MethodHandles
()
{
}
// do not instantiate
private
MethodHandles
()
{
}
// do not instantiate
private
static
final
Access
IMPL_TOKEN
=
Access
.
getToken
();
private
static
final
MemberName
.
Factory
IMPL_NAMES
=
MemberName
.
getFactory
();
private
static
final
MemberName
.
Factory
IMPL_NAMES
=
MemberName
.
getFactory
(
IMPL_TOKEN
);
static
{
MethodHandleImpl
.
initStatics
();
}
static
{
MethodHandleImpl
.
initStatics
();
}
// See IMPL_LOOKUP below.
// See IMPL_LOOKUP below.
//// Method handle creation from ordinary methods.
//// Method handle creation from ordinary methods.
/**
/**
* Return a {@link Lookup lookup object} on the caller,
* Return
s
a {@link Lookup lookup object} on the caller,
* which has the capability to access any method handle that the caller has access to,
* which has the capability to access any method handle that the caller has access to,
* including direct method handles to private fields and methods.
* including direct method handles to private fields and methods.
* This lookup object is a <em>capability</em> which may be delegated to trusted agents.
* This lookup object is a <em>capability</em> which may be delegated to trusted agents.
...
@@ -77,7 +70,7 @@ public class MethodHandles {
...
@@ -77,7 +70,7 @@ public class MethodHandles {
}
}
/**
/**
* Return a {@link Lookup lookup object} which is trusted minimally.
* Return
s
a {@link Lookup lookup object} which is trusted minimally.
* It can only be used to create method handles to
* It can only be used to create method handles to
* publicly accessible fields and methods.
* publicly accessible fields and methods.
* <p>
* <p>
...
@@ -120,55 +113,55 @@ public class MethodHandles {
...
@@ -120,55 +113,55 @@ public class MethodHandles {
* <table border=1 cellpadding=5 summary="lookup method behaviors">
* <table border=1 cellpadding=5 summary="lookup method behaviors">
* <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr>
* <tr><th>lookup expression</th><th>member</th><th>behavior</th></tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findGetter lookup.findGetter(C.class,"f",FT.class)}</td>
* <td>FT f;</td><td>(T) this.f;</td>
* <td>FT f;</td><td>(T) this.f;</td>
* </tr>
* </tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findStaticGetter lookup.findStaticGetter(C.class,"f",FT.class)}</td>
* <td>static<br>FT f;</td><td>(T) C.f;</td>
* <td>static<br>FT f;</td><td>(T) C.f;</td>
* </tr>
* </tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findSetter lookup.findSetter(C.class,"f",FT.class)}</td>
* <td>FT f;</td><td>this.f = x;</td>
* <td>FT f;</td><td>this.f = x;</td>
* </tr>
* </tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findStaticSetter lookup.findStaticSetter(C.class,"f",FT.class)}</td>
* <td>static<br>FT f;</td><td>C.f = arg;</td>
* <td>static<br>FT f;</td><td>C.f = arg;</td>
* </tr>
* </tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findVirtual lookup.findVirtual(C.class,"m",MT)}</td>
* <td>T m(A*);</td><td>(T) this.m(arg*);</td>
* <td>T m(A*);</td><td>(T) this.m(arg*);</td>
* </tr>
* </tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findStatic lookup.findStatic(C.class,"m",MT)}</td>
* <td>static<br>T m(A*);</td><td>(T) C.m(arg*);</td>
* <td>static<br>T m(A*);</td><td>(T) C.m(arg*);</td>
* </tr>
* </tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findSpecial lookup.findSpecial(C.class,"m",MT,this.class)}</td>
* <td>T m(A*);</td><td>(T) super.m(arg*);</td>
* <td>T m(A*);</td><td>(T) super.m(arg*);</td>
* </tr>
* </tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findConstructor lookup.findConstructor(C.class,MT)}</td>
* <td>C(A*);</td><td>(T) new C(arg*);</td>
* <td>C(A*);</td><td>(T) new C(arg*);</td>
* </tr>
* </tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#unreflectGetter lookup.unreflectGetter(aField)}</td>
* <td>(static)?<br>FT f;</td><td>(FT) aField.get(thisOrNull);</td>
* <td>(static)?<br>FT f;</td><td>(FT) aField.get(thisOrNull);</td>
* </tr>
* </tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#unreflectSetter lookup.unreflectSetter(aField)}</td>
* <td>(static)?<br>FT f;</td><td>aField.set(thisOrNull, arg);</td>
* <td>(static)?<br>FT f;</td><td>aField.set(thisOrNull, arg);</td>
* </tr>
* </tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
* <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
* <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
* </tr>
* </tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#unreflectConstructor lookup.unreflectConstructor(aConstructor)}</td>
* <td>C(A*);</td><td>(C) aConstructor.newInstance(arg*);</td>
* <td>C(A*);</td><td>(C) aConstructor.newInstance(arg*);</td>
* </tr>
* </tr>
* <tr>
* <tr>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#unreflect lookup.unreflect(aMethod)}</td>
* <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
* <td>(static)?<br>T m(A*);</td><td>(T) aMethod.invoke(thisOrNull, arg*);</td>
* </tr>
* </tr>
* </table>
* </table>
...
@@ -383,10 +376,10 @@ public class MethodHandles {
...
@@ -383,10 +376,10 @@ public class MethodHandles {
* and {@linkplain #PACKAGE PACKAGE (0x08)}.
* and {@linkplain #PACKAGE PACKAGE (0x08)}.
* <p>
* <p>
* A freshly-created lookup object
* A freshly-created lookup object
* on the {@linkplain java.
dyn
.MethodHandles#lookup() caller's class}
* on the {@linkplain java.
lang.invoke
.MethodHandles#lookup() caller's class}
* has all possible bits set, since the caller class can access all its own members.
* has all possible bits set, since the caller class can access all its own members.
* A lookup object on a new lookup class
* A lookup object on a new lookup class
* {@linkplain java.
dyn
.MethodHandles.Lookup#in created from a previous lookup object}
* {@linkplain java.
lang.invoke
.MethodHandles.Lookup#in created from a previous lookup object}
* may have some mode bits set to zero.
* may have some mode bits set to zero.
* The purpose of this is to restrict access via the new lookup object,
* The purpose of this is to restrict access via the new lookup object,
* so that it can access only names which can be reached by the original
* so that it can access only names which can be reached by the original
...
@@ -410,9 +403,8 @@ public class MethodHandles {
...
@@ -410,9 +403,8 @@ public class MethodHandles {
checkUnprivilegedlookupClass
(
lookupClass
);
checkUnprivilegedlookupClass
(
lookupClass
);
}
}
Lookup
(
Access
token
,
Class
<?>
lookupClass
)
{
Lookup
(
Class
<?>
lookupClass
)
{
this
(
lookupClass
,
ALL_MODES
);
this
(
lookupClass
,
ALL_MODES
);
Access
.
check
(
token
);
}
}
private
Lookup
(
Class
<?>
lookupClass
,
int
allowedModes
)
{
private
Lookup
(
Class
<?>
lookupClass
,
int
allowedModes
)
{
...
@@ -471,7 +463,7 @@ public class MethodHandles {
...
@@ -471,7 +463,7 @@ public class MethodHandles {
}
}
// Make sure outer class is initialized first.
// Make sure outer class is initialized first.
static
{
IMPL_
TOKEN
.
getClass
();
}
static
{
IMPL_
NAMES
.
getClass
();
}
/** Version of lookup which is trusted minimally.
/** Version of lookup which is trusted minimally.
* It can only be used to create method handles to
* It can only be used to create method handles to
...
@@ -481,11 +473,10 @@ public class MethodHandles {
...
@@ -481,11 +473,10 @@ public class MethodHandles {
/** Package-private version of lookup which is trusted. */
/** Package-private version of lookup which is trusted. */
static
final
Lookup
IMPL_LOOKUP
=
new
Lookup
(
Object
.
class
,
TRUSTED
);
static
final
Lookup
IMPL_LOOKUP
=
new
Lookup
(
Object
.
class
,
TRUSTED
);
static
{
MethodHandleImpl
.
initLookup
(
IMPL_TOKEN
,
IMPL_LOOKUP
);
}
private
static
void
checkUnprivilegedlookupClass
(
Class
<?>
lookupClass
)
{
private
static
void
checkUnprivilegedlookupClass
(
Class
<?>
lookupClass
)
{
String
name
=
lookupClass
.
getName
();
String
name
=
lookupClass
.
getName
();
if
(
name
.
startsWith
(
"java.
dyn."
)
||
name
.
startsWith
(
"sun.dyn
."
))
if
(
name
.
startsWith
(
"java.
lang.invoke
."
))
throw
newIllegalArgumentException
(
"illegal lookupClass: "
+
lookupClass
);
throw
newIllegalArgumentException
(
"illegal lookupClass: "
+
lookupClass
);
}
}
...
@@ -506,8 +497,8 @@ public class MethodHandles {
...
@@ -506,8 +497,8 @@ public class MethodHandles {
* access (public, package, private, and protected) is allowed.
* access (public, package, private, and protected) is allowed.
* In this case, no suffix is added.
* In this case, no suffix is added.
* This is true only of an object obtained originally from
* This is true only of an object obtained originally from
* {@link java.
dyn
.MethodHandles#lookup MethodHandles.lookup}.
* {@link java.
lang.invoke
.MethodHandles#lookup MethodHandles.lookup}.
* Objects created by {@link java.
dyn
.MethodHandles.Lookup#in Lookup.in}
* Objects created by {@link java.
lang.invoke
.MethodHandles.Lookup#in Lookup.in}
* always have restricted access, and will display a suffix.
* always have restricted access, and will display a suffix.
* <p>
* <p>
* (It may seem strange that protected access should be
* (It may seem strange that protected access should be
...
@@ -577,7 +568,7 @@ public class MethodHandles {
...
@@ -577,7 +568,7 @@ public class MethodHandles {
MethodHandle
findStatic
(
Class
<?>
refc
,
String
name
,
MethodType
type
)
throws
NoSuchMethodException
,
IllegalAccessException
{
MethodHandle
findStatic
(
Class
<?>
refc
,
String
name
,
MethodType
type
)
throws
NoSuchMethodException
,
IllegalAccessException
{
MemberName
method
=
resolveOrFail
(
refc
,
name
,
type
,
true
);
MemberName
method
=
resolveOrFail
(
refc
,
name
,
type
,
true
);
checkMethod
(
refc
,
method
,
true
);
checkMethod
(
refc
,
method
,
true
);
return
MethodHandleImpl
.
findMethod
(
IMPL_TOKEN
,
method
,
false
,
lookupClassOrNull
());
return
MethodHandleImpl
.
findMethod
(
method
,
false
,
lookupClassOrNull
());
}
}
/**
/**
...
@@ -601,8 +592,8 @@ public class MethodHandles {
...
@@ -601,8 +592,8 @@ public class MethodHandles {
* if the class is {@code MethodHandle} and the name string is
* if the class is {@code MethodHandle} and the name string is
* {@code invokeExact} or {@code invokeGeneric}, the resulting
* {@code invokeExact} or {@code invokeGeneric}, the resulting
* method handle is equivalent to one produced by
* method handle is equivalent to one produced by
* {@link java.
dyn
.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
* {@link java.
lang.invoke
.MethodHandles#exactInvoker MethodHandles.exactInvoker} or
* {@link java.
dyn
.MethodHandles#genericInvoker MethodHandles.genericInvoker}
* {@link java.
lang.invoke
.MethodHandles#genericInvoker MethodHandles.genericInvoker}
* with the same {@code type} argument.
* with the same {@code type} argument.
*
*
* @param refc the class or interface from which the method is accessed
* @param refc the class or interface from which the method is accessed
...
@@ -618,7 +609,7 @@ public class MethodHandles {
...
@@ -618,7 +609,7 @@ public class MethodHandles {
public
MethodHandle
findVirtual
(
Class
<?>
refc
,
String
name
,
MethodType
type
)
throws
NoSuchMethodException
,
IllegalAccessException
{
public
MethodHandle
findVirtual
(
Class
<?>
refc
,
String
name
,
MethodType
type
)
throws
NoSuchMethodException
,
IllegalAccessException
{
MemberName
method
=
resolveOrFail
(
refc
,
name
,
type
,
false
);
MemberName
method
=
resolveOrFail
(
refc
,
name
,
type
,
false
);
checkMethod
(
refc
,
method
,
false
);
checkMethod
(
refc
,
method
,
false
);
MethodHandle
mh
=
MethodHandleImpl
.
findMethod
(
IMPL_TOKEN
,
method
,
true
,
lookupClassOrNull
());
MethodHandle
mh
=
MethodHandleImpl
.
findMethod
(
method
,
true
,
lookupClassOrNull
());
return
restrictProtectedReceiver
(
method
,
mh
);
return
restrictProtectedReceiver
(
method
,
mh
);
}
}
...
@@ -651,8 +642,8 @@ public class MethodHandles {
...
@@ -651,8 +642,8 @@ public class MethodHandles {
MemberName
ctor
=
resolveOrFail
(
refc
,
name
,
type
,
false
,
false
,
lookupClassOrNull
());
MemberName
ctor
=
resolveOrFail
(
refc
,
name
,
type
,
false
,
false
,
lookupClassOrNull
());
assert
(
ctor
.
isConstructor
());
assert
(
ctor
.
isConstructor
());
checkAccess
(
refc
,
ctor
);
checkAccess
(
refc
,
ctor
);
MethodHandle
rawMH
=
MethodHandleImpl
.
findMethod
(
IMPL_TOKEN
,
ctor
,
false
,
lookupClassOrNull
());
MethodHandle
rawMH
=
MethodHandleImpl
.
findMethod
(
ctor
,
false
,
lookupClassOrNull
());
MethodHandle
allocMH
=
MethodHandleImpl
.
makeAllocator
(
IMPL_TOKEN
,
rawMH
);
MethodHandle
allocMH
=
MethodHandleImpl
.
makeAllocator
(
rawMH
);
return
fixVarargs
(
allocMH
,
rawMH
);
return
fixVarargs
(
allocMH
,
rawMH
);
}
}
...
@@ -708,7 +699,7 @@ public class MethodHandles {
...
@@ -708,7 +699,7 @@ public class MethodHandles {
checkSpecialCaller
(
specialCaller
);
checkSpecialCaller
(
specialCaller
);
MemberName
method
=
resolveOrFail
(
refc
,
name
,
type
,
false
,
false
,
specialCaller
);
MemberName
method
=
resolveOrFail
(
refc
,
name
,
type
,
false
,
false
,
specialCaller
);
checkMethod
(
refc
,
method
,
false
);
checkMethod
(
refc
,
method
,
false
);
MethodHandle
mh
=
MethodHandleImpl
.
findMethod
(
IMPL_TOKEN
,
method
,
false
,
specialCaller
);
MethodHandle
mh
=
MethodHandleImpl
.
findMethod
(
method
,
false
,
specialCaller
);
return
restrictReceiver
(
method
,
mh
,
specialCaller
);
return
restrictReceiver
(
method
,
mh
,
specialCaller
);
}
}
...
@@ -839,17 +830,17 @@ return mh1;
...
@@ -839,17 +830,17 @@ return mh1;
Class
<?
extends
Object
>
refc
=
receiver
.
getClass
();
// may get NPE
Class
<?
extends
Object
>
refc
=
receiver
.
getClass
();
// may get NPE
MemberName
method
=
resolveOrFail
(
refc
,
name
,
type
,
false
);
MemberName
method
=
resolveOrFail
(
refc
,
name
,
type
,
false
);
checkMethod
(
refc
,
method
,
false
);
checkMethod
(
refc
,
method
,
false
);
MethodHandle
dmh
=
MethodHandleImpl
.
findMethod
(
IMPL_TOKEN
,
method
,
true
,
lookupClassOrNull
());
MethodHandle
dmh
=
MethodHandleImpl
.
findMethod
(
method
,
true
,
lookupClassOrNull
());
MethodHandle
bmh
=
MethodHandleImpl
.
bindReceiver
(
IMPL_TOKEN
,
dmh
,
receiver
);
MethodHandle
bmh
=
MethodHandleImpl
.
bindReceiver
(
dmh
,
receiver
);
if
(
bmh
==
null
)
if
(
bmh
==
null
)
throw
newNoAccessException
(
method
,
this
);
throw
method
.
makeAccessException
(
"no access"
,
this
);
if
(
dmh
.
type
().
parameterCount
()
==
0
)
if
(
dmh
.
type
().
parameterCount
()
==
0
)
return
dmh
;
// bound the trailing parameter; no varargs possible
return
dmh
;
// bound the trailing parameter; no varargs possible
return
fixVarargs
(
bmh
,
dmh
);
return
fixVarargs
(
bmh
,
dmh
);
}
}
/**
/**
* Make a direct method handle to <i>m</i>, if the lookup class has permission.
* Make
s
a direct method handle to <i>m</i>, if the lookup class has permission.
* If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
* If <i>m</i> is non-static, the receiver argument is treated as an initial argument.
* If <i>m</i> is virtual, overriding is respected on every call.
* If <i>m</i> is virtual, overriding is respected on every call.
* Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
* Unlike the Core Reflection API, exceptions are <em>not</em> wrapped.
...
@@ -871,7 +862,7 @@ return mh1;
...
@@ -871,7 +862,7 @@ return mh1;
MemberName
method
=
new
MemberName
(
m
);
MemberName
method
=
new
MemberName
(
m
);
assert
(
method
.
isMethod
());
assert
(
method
.
isMethod
());
if
(!
m
.
isAccessible
())
checkMethod
(
method
.
getDeclaringClass
(),
method
,
method
.
isStatic
());
if
(!
m
.
isAccessible
())
checkMethod
(
method
.
getDeclaringClass
(),
method
,
method
.
isStatic
());
MethodHandle
mh
=
MethodHandleImpl
.
findMethod
(
IMPL_TOKEN
,
method
,
true
,
lookupClassOrNull
());
MethodHandle
mh
=
MethodHandleImpl
.
findMethod
(
method
,
true
,
lookupClassOrNull
());
if
(!
m
.
isAccessible
())
mh
=
restrictProtectedReceiver
(
method
,
mh
);
if
(!
m
.
isAccessible
())
mh
=
restrictProtectedReceiver
(
method
,
mh
);
return
mh
;
return
mh
;
}
}
...
@@ -901,7 +892,7 @@ return mh1;
...
@@ -901,7 +892,7 @@ return mh1;
assert
(
method
.
isMethod
());
assert
(
method
.
isMethod
());
// ignore m.isAccessible: this is a new kind of access
// ignore m.isAccessible: this is a new kind of access
checkMethod
(
m
.
getDeclaringClass
(),
method
,
false
);
checkMethod
(
m
.
getDeclaringClass
(),
method
,
false
);
MethodHandle
mh
=
MethodHandleImpl
.
findMethod
(
IMPL_TOKEN
,
method
,
false
,
lookupClassOrNull
());
MethodHandle
mh
=
MethodHandleImpl
.
findMethod
(
method
,
false
,
lookupClassOrNull
());
return
restrictReceiver
(
method
,
mh
,
specialCaller
);
return
restrictReceiver
(
method
,
mh
,
specialCaller
);
}
}
...
@@ -928,8 +919,8 @@ return mh1;
...
@@ -928,8 +919,8 @@ return mh1;
MemberName
ctor
=
new
MemberName
(
c
);
MemberName
ctor
=
new
MemberName
(
c
);
assert
(
ctor
.
isConstructor
());
assert
(
ctor
.
isConstructor
());
if
(!
c
.
isAccessible
())
checkAccess
(
c
.
getDeclaringClass
(),
ctor
);
if
(!
c
.
isAccessible
())
checkAccess
(
c
.
getDeclaringClass
(),
ctor
);
MethodHandle
rawCtor
=
MethodHandleImpl
.
findMethod
(
IMPL_TOKEN
,
ctor
,
false
,
lookupClassOrNull
());
MethodHandle
rawCtor
=
MethodHandleImpl
.
findMethod
(
ctor
,
false
,
lookupClassOrNull
());
MethodHandle
allocator
=
MethodHandleImpl
.
makeAllocator
(
IMPL_TOKEN
,
rawCtor
);
MethodHandle
allocator
=
MethodHandleImpl
.
makeAllocator
(
rawCtor
);
return
fixVarargs
(
allocator
,
rawCtor
);
return
fixVarargs
(
allocator
,
rawCtor
);
}
}
...
@@ -940,7 +931,7 @@ return mh1;
...
@@ -940,7 +931,7 @@ return mh1;
* If the field is static, the method handle will take no arguments.
* If the field is static, the method handle will take no arguments.
* Otherwise, its single argument will be the instance containing
* Otherwise, its single argument will be the instance containing
* the field.
* the field.
* If the
metho
d's {@code accessible} flag is not set,
* If the
fiel
d's {@code accessible} flag is not set,
* access checking is performed immediately on behalf of the lookup class.
* access checking is performed immediately on behalf of the lookup class.
* @param f the reflected field
* @param f the reflected field
* @return a method handle which can load values from the reflected field
* @return a method handle which can load values from the reflected field
...
@@ -958,7 +949,7 @@ return mh1;
...
@@ -958,7 +949,7 @@ return mh1;
* argument, of the field's value type, the value to be stored.
* argument, of the field's value type, the value to be stored.
* Otherwise, the two arguments will be the instance containing
* Otherwise, the two arguments will be the instance containing
* the field, and the value to be stored.
* the field, and the value to be stored.
* If the
metho
d's {@code accessible} flag is not set,
* If the
fiel
d's {@code accessible} flag is not set,
* access checking is performed immediately on behalf of the lookup class.
* access checking is performed immediately on behalf of the lookup class.
* @param f the reflected field
* @param f the reflected field
* @return a method handle which can store values into the reflected field
* @return a method handle which can store values into the reflected field
...
@@ -999,7 +990,7 @@ return mh1;
...
@@ -999,7 +990,7 @@ return mh1;
void
checkSymbolicClass
(
Class
<?>
refc
)
throws
IllegalAccessException
{
void
checkSymbolicClass
(
Class
<?>
refc
)
throws
IllegalAccessException
{
Class
<?>
caller
=
lookupClassOrNull
();
Class
<?>
caller
=
lookupClassOrNull
();
if
(
caller
!=
null
&&
!
VerifyAccess
.
isClassAccessible
(
refc
,
caller
))
if
(
caller
!=
null
&&
!
VerifyAccess
.
isClassAccessible
(
refc
,
caller
))
throw
new
NoAccessException
(
"symbolic reference class is not public"
,
new
MemberName
(
refc
)
,
this
);
throw
new
MemberName
(
refc
).
makeAccessException
(
"symbolic reference class is not public"
,
this
);
}
}
void
checkMethod
(
Class
<?>
refc
,
MemberName
m
,
boolean
wantStatic
)
throws
IllegalAccessException
{
void
checkMethod
(
Class
<?>
refc
,
MemberName
m
,
boolean
wantStatic
)
throws
IllegalAccessException
{
...
@@ -1012,7 +1003,7 @@ return mh1;
...
@@ -1012,7 +1003,7 @@ return mh1;
message
=
wantStatic
?
"expected a static method"
:
"expected a non-static method"
;
message
=
wantStatic
?
"expected a static method"
:
"expected a non-static method"
;
else
else
{
checkAccess
(
refc
,
m
);
return
;
}
{
checkAccess
(
refc
,
m
);
return
;
}
throw
newNoAccessException
(
message
,
m
,
this
);
throw
m
.
makeAccessException
(
message
,
this
);
}
}
void
checkAccess
(
Class
<?>
refc
,
MemberName
m
)
throws
IllegalAccessException
{
void
checkAccess
(
Class
<?>
refc
,
MemberName
m
)
throws
IllegalAccessException
{
...
@@ -1030,7 +1021,7 @@ return mh1;
...
@@ -1030,7 +1021,7 @@ return mh1;
&&
VerifyAccess
.
isSamePackage
(
m
.
getDeclaringClass
(),
lookupClass
()))
&&
VerifyAccess
.
isSamePackage
(
m
.
getDeclaringClass
(),
lookupClass
()))
// Protected members can also be checked as if they were package-private.
// Protected members can also be checked as if they were package-private.
return
;
return
;
throw
newNoAccessException
(
accessFailedMessage
(
refc
,
m
),
m
,
this
);
throw
m
.
makeAccessException
(
accessFailedMessage
(
refc
,
m
)
,
this
);
}
}
String
accessFailedMessage
(
Class
<?>
refc
,
MemberName
m
)
{
String
accessFailedMessage
(
Class
<?>
refc
,
MemberName
m
)
{
...
@@ -1064,8 +1055,8 @@ return mh1;
...
@@ -1064,8 +1055,8 @@ return mh1;
||
(
specialCaller
!=
lookupClass
()
||
(
specialCaller
!=
lookupClass
()
&&
!(
ALLOW_NESTMATE_ACCESS
&&
&&
!(
ALLOW_NESTMATE_ACCESS
&&
VerifyAccess
.
isSamePackageMember
(
specialCaller
,
lookupClass
()))))
VerifyAccess
.
isSamePackageMember
(
specialCaller
,
lookupClass
()))))
throw
new
NoAccessException
(
"no private access for invokespecial"
,
throw
new
MemberName
(
specialCaller
).
new
MemberName
(
specialCaller
)
,
this
);
makeAccessException
(
"no private access for invokespecial"
,
this
);
}
}
MethodHandle
restrictProtectedReceiver
(
MemberName
method
,
MethodHandle
mh
)
throws
IllegalAccessException
{
MethodHandle
restrictProtectedReceiver
(
MemberName
method
,
MethodHandle
mh
)
throws
IllegalAccessException
{
...
@@ -1084,12 +1075,12 @@ return mh1;
...
@@ -1084,12 +1075,12 @@ return mh1;
assert
(!
method
.
isStatic
());
assert
(!
method
.
isStatic
());
Class
<?>
defc
=
method
.
getDeclaringClass
();
// receiver type of mh is too wide
Class
<?>
defc
=
method
.
getDeclaringClass
();
// receiver type of mh is too wide
if
(
defc
.
isInterface
()
||
!
defc
.
isAssignableFrom
(
caller
))
{
if
(
defc
.
isInterface
()
||
!
defc
.
isAssignableFrom
(
caller
))
{
throw
newNoAccessException
(
"caller class must be a subclass below the method"
,
method
,
caller
);
throw
method
.
makeAccessException
(
"caller class must be a subclass below the method"
,
caller
);
}
}
MethodType
rawType
=
mh
.
type
();
MethodType
rawType
=
mh
.
type
();
if
(
rawType
.
parameterType
(
0
)
==
caller
)
return
mh
;
if
(
rawType
.
parameterType
(
0
)
==
caller
)
return
mh
;
MethodType
narrowType
=
rawType
.
changeParameterType
(
0
,
caller
);
MethodType
narrowType
=
rawType
.
changeParameterType
(
0
,
caller
);
MethodHandle
narrowMH
=
MethodHandleImpl
.
convertArguments
(
IMPL_TOKEN
,
mh
,
narrowType
,
rawType
,
null
);
MethodHandle
narrowMH
=
MethodHandleImpl
.
convertArguments
(
mh
,
narrowType
,
rawType
,
null
);
return
fixVarargs
(
narrowMH
,
mh
);
return
fixVarargs
(
narrowMH
,
mh
);
}
}
...
@@ -1097,10 +1088,9 @@ return mh1;
...
@@ -1097,10 +1088,9 @@ return mh1;
boolean
isStatic
,
boolean
isSetter
)
throws
NoSuchFieldException
,
IllegalAccessException
{
boolean
isStatic
,
boolean
isSetter
)
throws
NoSuchFieldException
,
IllegalAccessException
{
MemberName
field
=
resolveOrFail
(
refc
,
name
,
type
,
isStatic
);
MemberName
field
=
resolveOrFail
(
refc
,
name
,
type
,
isStatic
);
if
(
isStatic
!=
field
.
isStatic
())
if
(
isStatic
!=
field
.
isStatic
())
throw
newNoAccessException
(
isStatic
throw
field
.
makeAccessException
(
isStatic
?
"expected a static field"
?
"expected a static field"
:
"expected a non-static field"
,
:
"expected a non-static field"
,
this
);
field
,
this
);
return
makeAccessor
(
refc
,
field
,
false
,
isSetter
);
return
makeAccessor
(
refc
,
field
,
false
,
isSetter
);
}
}
...
@@ -1108,9 +1098,9 @@ return mh1;
...
@@ -1108,9 +1098,9 @@ return mh1;
boolean
trusted
,
boolean
isSetter
)
throws
IllegalAccessException
{
boolean
trusted
,
boolean
isSetter
)
throws
IllegalAccessException
{
assert
(
field
.
isField
());
assert
(
field
.
isField
());
if
(
trusted
)
if
(
trusted
)
return
MethodHandleImpl
.
accessField
(
IMPL_TOKEN
,
field
,
isSetter
,
lookupClassOrNull
());
return
MethodHandleImpl
.
accessField
(
field
,
isSetter
,
lookupClassOrNull
());
checkAccess
(
refc
,
field
);
checkAccess
(
refc
,
field
);
MethodHandle
mh
=
MethodHandleImpl
.
accessField
(
IMPL_TOKEN
,
field
,
isSetter
,
lookupClassOrNull
());
MethodHandle
mh
=
MethodHandleImpl
.
accessField
(
field
,
isSetter
,
lookupClassOrNull
());
return
restrictProtectedReceiver
(
field
,
mh
);
return
restrictProtectedReceiver
(
field
,
mh
);
}
}
}
}
...
@@ -1127,7 +1117,7 @@ return mh1;
...
@@ -1127,7 +1117,7 @@ return mh1;
*/
*/
public
static
public
static
MethodHandle
arrayElementGetter
(
Class
<?>
arrayClass
)
throws
IllegalArgumentException
{
MethodHandle
arrayElementGetter
(
Class
<?>
arrayClass
)
throws
IllegalArgumentException
{
return
MethodHandleImpl
.
accessArrayElement
(
IMPL_TOKEN
,
arrayClass
,
false
);
return
MethodHandleImpl
.
accessArrayElement
(
arrayClass
,
false
);
}
}
/**
/**
...
@@ -1141,7 +1131,7 @@ return mh1;
...
@@ -1141,7 +1131,7 @@ return mh1;
*/
*/
public
static
public
static
MethodHandle
arrayElementSetter
(
Class
<?>
arrayClass
)
throws
IllegalArgumentException
{
MethodHandle
arrayElementSetter
(
Class
<?>
arrayClass
)
throws
IllegalArgumentException
{
return
MethodHandleImpl
.
accessArrayElement
(
IMPL_TOKEN
,
arrayClass
,
true
);
return
MethodHandleImpl
.
accessArrayElement
(
arrayClass
,
true
);
}
}
/// method handle invocation (reflective style)
/// method handle invocation (reflective style)
...
@@ -1191,7 +1181,7 @@ return invoker;
...
@@ -1191,7 +1181,7 @@ return invoker;
MethodHandle
spreadInvoker
(
MethodType
type
,
int
objectArgCount
)
{
MethodHandle
spreadInvoker
(
MethodType
type
,
int
objectArgCount
)
{
if
(
objectArgCount
<
0
||
objectArgCount
>
type
.
parameterCount
())
if
(
objectArgCount
<
0
||
objectArgCount
>
type
.
parameterCount
())
throw
new
IllegalArgumentException
(
"bad argument count "
+
objectArgCount
);
throw
new
IllegalArgumentException
(
"bad argument count "
+
objectArgCount
);
return
invokers
(
type
).
spreadInvoker
(
objectArgCount
);
return
type
.
invokers
(
).
spreadInvoker
(
objectArgCount
);
}
}
/**
/**
...
@@ -1231,7 +1221,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
...
@@ -1231,7 +1221,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeExact", type)
*/
*/
static
public
static
public
MethodHandle
exactInvoker
(
MethodType
type
)
{
MethodHandle
exactInvoker
(
MethodType
type
)
{
return
invokers
(
type
).
exactInvoker
();
return
type
.
invokers
(
).
exactInvoker
();
}
}
/**
/**
...
@@ -1258,11 +1248,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
...
@@ -1258,11 +1248,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
*/
*/
static
public
static
public
MethodHandle
genericInvoker
(
MethodType
type
)
{
MethodHandle
genericInvoker
(
MethodType
type
)
{
return
invokers
(
type
).
genericInvoker
();
return
type
.
invokers
().
genericInvoker
();
}
static
Invokers
invokers
(
MethodType
type
)
{
return
MethodTypeImpl
.
invokers
(
IMPL_TOKEN
,
type
);
}
}
/**
/**
...
@@ -1387,7 +1373,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
...
@@ -1387,7 +1373,7 @@ publicLookup().findVirtual(MethodHandle.class, "invokeGeneric", type)
return
target
;
return
target
;
MethodHandle
res
=
null
;
MethodHandle
res
=
null
;
try
{
try
{
res
=
MethodHandleImpl
.
convertArguments
(
IMPL_TOKEN
,
target
,
res
=
MethodHandleImpl
.
convertArguments
(
target
,
newType
,
oldType
,
null
);
newType
,
oldType
,
null
);
}
catch
(
IllegalArgumentException
ex
)
{
}
catch
(
IllegalArgumentException
ex
)
{
}
}
...
@@ -1531,7 +1517,7 @@ assert((int)twice.invokeExact(21) == 42);
...
@@ -1531,7 +1517,7 @@ assert((int)twice.invokeExact(21) == 42);
MethodHandle
permuteArguments
(
MethodHandle
target
,
MethodType
newType
,
int
...
reorder
)
{
MethodHandle
permuteArguments
(
MethodHandle
target
,
MethodType
newType
,
int
...
reorder
)
{
MethodType
oldType
=
target
.
type
();
MethodType
oldType
=
target
.
type
();
checkReorder
(
reorder
,
newType
,
oldType
);
checkReorder
(
reorder
,
newType
,
oldType
);
return
MethodHandleImpl
.
convertArguments
(
IMPL_TOKEN
,
target
,
return
MethodHandleImpl
.
convertArguments
(
target
,
newType
,
oldType
,
newType
,
oldType
,
reorder
);
reorder
);
}
}
...
@@ -1574,7 +1560,7 @@ assert((int)twice.invokeExact(21) == 42);
...
@@ -1574,7 +1560,7 @@ assert((int)twice.invokeExact(21) == 42);
int
numSpread
=
(
outargs
-
spreadPos
);
int
numSpread
=
(
outargs
-
spreadPos
);
MethodHandle
res
=
null
;
MethodHandle
res
=
null
;
if
(
spreadPos
>=
0
&&
numSpread
>=
0
)
{
if
(
spreadPos
>=
0
&&
numSpread
>=
0
)
{
res
=
MethodHandleImpl
.
spreadArguments
(
IMPL_TOKEN
,
target
,
newType
,
spreadPos
);
res
=
MethodHandleImpl
.
spreadArguments
(
target
,
newType
,
spreadPos
);
}
}
if
(
res
==
null
)
{
if
(
res
==
null
)
{
throw
newIllegalArgumentException
(
"cannot spread "
+
newType
+
" to "
+
oldType
);
throw
newIllegalArgumentException
(
"cannot spread "
+
newType
+
" to "
+
oldType
);
...
@@ -1607,7 +1593,7 @@ assert((int)twice.invokeExact(21) == 42);
...
@@ -1607,7 +1593,7 @@ assert((int)twice.invokeExact(21) == 42);
int
numCollect
=
(
inargs
-
collectPos
);
int
numCollect
=
(
inargs
-
collectPos
);
if
(
collectPos
<
0
||
numCollect
<
0
)
if
(
collectPos
<
0
||
numCollect
<
0
)
throw
newIllegalArgumentException
(
"wrong number of arguments"
);
throw
newIllegalArgumentException
(
"wrong number of arguments"
);
MethodHandle
res
=
MethodHandleImpl
.
collectArguments
(
IMPL_TOKEN
,
target
,
newType
,
collectPos
,
null
);
MethodHandle
res
=
MethodHandleImpl
.
collectArguments
(
target
,
newType
,
collectPos
,
null
);
if
(
res
==
null
)
{
if
(
res
==
null
)
{
throw
newIllegalArgumentException
(
"cannot collect from "
+
newType
+
" to "
+
oldType
);
throw
newIllegalArgumentException
(
"cannot collect from "
+
newType
+
" to "
+
oldType
);
}
}
...
@@ -1654,7 +1640,13 @@ assert((int)twice.invokeExact(21) == 42);
...
@@ -1654,7 +1640,13 @@ assert((int)twice.invokeExact(21) == 42);
MethodHandle
identity
(
Class
<?>
type
)
{
MethodHandle
identity
(
Class
<?>
type
)
{
if
(
type
==
void
.
class
)
if
(
type
==
void
.
class
)
throw
newIllegalArgumentException
(
"void type"
);
throw
newIllegalArgumentException
(
"void type"
);
return
ValueConversions
.
identity
(
type
);
else
if
(
type
==
Object
.
class
)
return
ValueConversions
.
identity
();
else
if
(
type
.
isPrimitive
())
return
ValueConversions
.
identity
(
Wrapper
.
forPrimitiveType
(
type
));
else
return
AdapterMethodHandle
.
makeRetypeRaw
(
MethodType
.
methodType
(
type
,
type
),
ValueConversions
.
identity
());
}
}
/**
/**
...
@@ -1686,8 +1678,6 @@ assert((int)twice.invokeExact(21) == 42);
...
@@ -1686,8 +1678,6 @@ assert((int)twice.invokeExact(21) == 42);
MethodHandle
insertArguments
(
MethodHandle
target
,
int
pos
,
Object
...
values
)
{
MethodHandle
insertArguments
(
MethodHandle
target
,
int
pos
,
Object
...
values
)
{
int
insCount
=
values
.
length
;
int
insCount
=
values
.
length
;
MethodType
oldType
=
target
.
type
();
MethodType
oldType
=
target
.
type
();
ArrayList
<
Class
<?>>
ptypes
=
new
ArrayList
<
Class
<?>>(
oldType
.
parameterList
());
int
outargs
=
oldType
.
parameterCount
();
int
outargs
=
oldType
.
parameterCount
();
int
inargs
=
outargs
-
insCount
;
int
inargs
=
outargs
-
insCount
;
if
(
inargs
<
0
)
if
(
inargs
<
0
)
...
@@ -1701,14 +1691,14 @@ assert((int)twice.invokeExact(21) == 42);
...
@@ -1701,14 +1691,14 @@ assert((int)twice.invokeExact(21) == 42);
value
=
checkValue
(
valueType
,
value
);
value
=
checkValue
(
valueType
,
value
);
if
(
pos
==
0
&&
!
valueType
.
isPrimitive
())
{
if
(
pos
==
0
&&
!
valueType
.
isPrimitive
())
{
// At least for now, make bound method handles a special case.
// At least for now, make bound method handles a special case.
MethodHandle
bmh
=
MethodHandleImpl
.
bindReceiver
(
IMPL_TOKEN
,
result
,
value
);
MethodHandle
bmh
=
MethodHandleImpl
.
bindReceiver
(
result
,
value
);
if
(
bmh
!=
null
)
{
if
(
bmh
!=
null
)
{
result
=
bmh
;
result
=
bmh
;
continue
;
continue
;
}
}
// else fall through to general adapter machinery
// else fall through to general adapter machinery
}
}
result
=
MethodHandleImpl
.
bindArgument
(
IMPL_TOKEN
,
result
,
pos
,
value
);
result
=
MethodHandleImpl
.
bindArgument
(
result
,
pos
,
value
);
}
}
return
result
;
return
result
;
}
}
...
@@ -1726,20 +1716,21 @@ assert((int)twice.invokeExact(21) == 42);
...
@@ -1726,20 +1716,21 @@ assert((int)twice.invokeExact(21) == 42);
* <p>
* <p>
* <b>Example:</b>
* <b>Example:</b>
* <p><blockquote><pre>
* <p><blockquote><pre>
import static java.
dyn
.MethodHandles.*;
import static java.
lang.invoke
.MethodHandles.*;
import static java.
dyn
.MethodType.*;
import static java.
lang.invoke
.MethodType.*;
...
...
MethodHandle cat = lookup().findVirtual(String.class,
MethodHandle cat = lookup().findVirtual(String.class,
"concat", methodType(String.class, String.class));
"concat", methodType(String.class, String.class));
assertEquals("xy", (String) cat.invokeExact("x", "y"));
assertEquals("xy", (String) cat.invokeExact("x", "y"));
MethodHandle d0 = dropArguments(cat, 0, String.class);
MethodType bigType = cat.type().insertParameterTypes(0, int.class, String.class);
assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
MethodHandle d0 = dropArguments(cat, 0, bigType.parameterList().subList(0,2));
MethodHandle d1 = dropArguments(cat, 1, String.class);
assertEquals(bigType, d0.type());
assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
MethodHandle d2 = dropArguments(cat, 2, String.class);
* </pre></blockquote>
assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
* <p>
MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
* This method is also equivalent to the following code:
assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
* <p><blockquote><pre>
* {@link #dropArguments(MethodHandle,int,Class...) dropArguments}(target, pos, valueTypes.toArray(new Class[0]))
* </pre></blockquote>
* </pre></blockquote>
* @param target the method handle to invoke after the arguments are dropped
* @param target the method handle to invoke after the arguments are dropped
* @param valueTypes the type(s) of the argument(s) to drop
* @param valueTypes the type(s) of the argument(s) to drop
...
@@ -1762,7 +1753,7 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
...
@@ -1762,7 +1753,7 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
new
ArrayList
<
Class
<?>>(
oldType
.
parameterList
());
new
ArrayList
<
Class
<?>>(
oldType
.
parameterList
());
ptypes
.
addAll
(
pos
,
valueTypes
);
ptypes
.
addAll
(
pos
,
valueTypes
);
MethodType
newType
=
MethodType
.
methodType
(
oldType
.
returnType
(),
ptypes
);
MethodType
newType
=
MethodType
.
methodType
(
oldType
.
returnType
(),
ptypes
);
return
MethodHandleImpl
.
dropArguments
(
IMPL_TOKEN
,
target
,
newType
,
pos
);
return
MethodHandleImpl
.
dropArguments
(
target
,
newType
,
pos
);
}
}
/**
/**
...
@@ -1770,10 +1761,34 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
...
@@ -1770,10 +1761,34 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
* after dropping the given argument(s) at the given position.
* after dropping the given argument(s) at the given position.
* The type of the new method handle will insert the given argument
* The type of the new method handle will insert the given argument
* type(s), at that position, into the original handle's type.
* type(s), at that position, into the original handle's type.
* This method is equivalent to the following code:
* <p>
* <code>
* The <i>pos</i> may range between zero and <i>N</i>,
* where <i>N</i> is the number of argument types in <i>target</i>,
* meaning to drop the first or last argument (respectively),
* or an argument somewhere in between.
* <p>
* <b>Example:</b>
* <p><blockquote><pre>
import static java.lang.invoke.MethodHandles.*;
import static java.lang.invoke.MethodType.*;
...
MethodHandle cat = lookup().findVirtual(String.class,
"concat", methodType(String.class, String.class));
assertEquals("xy", (String) cat.invokeExact("x", "y"));
MethodHandle d0 = dropArguments(cat, 0, String.class);
assertEquals("yz", (String) d0.invokeExact("x", "y", "z"));
MethodHandle d1 = dropArguments(cat, 1, String.class);
assertEquals("xz", (String) d1.invokeExact("x", "y", "z"));
MethodHandle d2 = dropArguments(cat, 2, String.class);
assertEquals("xy", (String) d2.invokeExact("x", "y", "z"));
MethodHandle d12 = dropArguments(cat, 1, int.class, boolean.class);
assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
* </pre></blockquote>
* <p>
* This method is also equivalent to the following code:
* <p><blockquote><pre>
* {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes))
* {@link #dropArguments(MethodHandle,int,List) dropArguments}(target, pos, Arrays.asList(valueTypes))
* </
cod
e>
* </
pre></blockquot
e>
* @param target the method handle to invoke after the arguments are dropped
* @param target the method handle to invoke after the arguments are dropped
* @param valueTypes the type(s) of the argument(s) to drop
* @param valueTypes the type(s) of the argument(s) to drop
* @param pos position of first argument to drop (zero for the leftmost)
* @param pos position of first argument to drop (zero for the leftmost)
...
@@ -1789,7 +1804,7 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
...
@@ -1789,7 +1804,7 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
}
}
/**
/**
* Adapt a target method handle {@code target} by pre-processing
* Adapt
s
a target method handle {@code target} by pre-processing
* one or more of its arguments, each with its own unary filter function,
* one or more of its arguments, each with its own unary filter function,
* and then calling the target with each pre-processed argument
* and then calling the target with each pre-processed argument
* replaced by the result of its corresponding filter function.
* replaced by the result of its corresponding filter function.
...
@@ -1812,8 +1827,8 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
...
@@ -1812,8 +1827,8 @@ assertEquals("xz", (String) d12.invokeExact("x", 12, true, "z"));
* which do not correspond to argument positions in the target.
* which do not correspond to argument positions in the target.
* <b>Example:</b>
* <b>Example:</b>
* <p><blockquote><pre>
* <p><blockquote><pre>
import static java.
dyn
.MethodHandles.*;
import static java.
lang.invoke
.MethodHandles.*;
import static java.
dyn
.MethodType.*;
import static java.
lang.invoke
.MethodType.*;
...
...
MethodHandle cat = lookup().findVirtual(String.class,
MethodHandle cat = lookup().findVirtual(String.class,
"concat", methodType(String.class, String.class));
"concat", methodType(String.class, String.class));
...
@@ -1855,16 +1870,16 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
...
@@ -1855,16 +1870,16 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
||
filterType
.
returnType
()
!=
targetType
.
parameterType
(
curPos
))
||
filterType
.
returnType
()
!=
targetType
.
parameterType
(
curPos
))
throw
newIllegalArgumentException
(
"target and filter types do not match"
);
throw
newIllegalArgumentException
(
"target and filter types do not match"
);
adapterType
=
adapterType
.
changeParameterType
(
curPos
,
filterType
.
parameterType
(
0
));
adapterType
=
adapterType
.
changeParameterType
(
curPos
,
filterType
.
parameterType
(
0
));
adapter
=
MethodHandleImpl
.
filterArgument
(
IMPL_TOKEN
,
adapter
,
curPos
,
filter
);
adapter
=
MethodHandleImpl
.
filterArgument
(
adapter
,
curPos
,
filter
);
}
}
MethodType
midType
=
adapter
.
type
();
MethodType
midType
=
adapter
.
type
();
if
(
midType
!=
adapterType
)
if
(
midType
!=
adapterType
)
adapter
=
MethodHandleImpl
.
convertArguments
(
IMPL_TOKEN
,
adapter
,
adapterType
,
midType
,
null
);
adapter
=
MethodHandleImpl
.
convertArguments
(
adapter
,
adapterType
,
midType
,
null
);
return
adapter
;
return
adapter
;
}
}
/**
/**
* Adapt a target method handle {@code target} by post-processing
* Adapt
s
a target method handle {@code target} by post-processing
* its return value with a unary filter function.
* its return value with a unary filter function.
* <p>
* <p>
* If a filter {@code F} applies to the return value of
* If a filter {@code F} applies to the return value of
...
@@ -1876,8 +1891,8 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
...
@@ -1876,8 +1891,8 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
* return type of the target.
* return type of the target.
* <b>Example:</b>
* <b>Example:</b>
* <p><blockquote><pre>
* <p><blockquote><pre>
import static java.
dyn
.MethodHandles.*;
import static java.
lang.invoke
.MethodHandles.*;
import static java.
dyn
.MethodType.*;
import static java.
lang.invoke
.MethodType.*;
...
...
MethodHandle cat = lookup().findVirtual(String.class,
MethodHandle cat = lookup().findVirtual(String.class,
"concat", methodType(String.class, String.class));
"concat", methodType(String.class, String.class));
...
@@ -1909,7 +1924,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -1909,7 +1924,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
}
}
/**
/**
* Adapt a target method handle {@code target} by pre-processing
* Adapt
s
a target method handle {@code target} by pre-processing
* some of its arguments, and then calling the target with
* some of its arguments, and then calling the target with
* the result of the pre-processing, plus all original arguments.
* the result of the pre-processing, plus all original arguments.
* <p>
* <p>
...
@@ -1966,11 +1981,11 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -1966,11 +1981,11 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
if
(!
ok
)
if
(!
ok
)
throw
misMatchedTypes
(
"target and combiner types"
,
targetType
,
combinerType
);
throw
misMatchedTypes
(
"target and combiner types"
,
targetType
,
combinerType
);
MethodType
newType
=
targetType
.
dropParameterTypes
(
0
,
1
);
MethodType
newType
=
targetType
.
dropParameterTypes
(
0
,
1
);
return
MethodHandleImpl
.
foldArguments
(
IMPL_TOKEN
,
target
,
newType
,
combiner
);
return
MethodHandleImpl
.
foldArguments
(
target
,
newType
,
combiner
);
}
}
/**
/**
* Make a method handle which adapts a target method handle,
* Make
s
a method handle which adapts a target method handle,
* by guarding it with a test, a boolean-valued method handle.
* by guarding it with a test, a boolean-valued method handle.
* If the guard fails, a fallback handle is called instead.
* If the guard fails, a fallback handle is called instead.
* All three method handles must have the same corresponding
* All three method handles must have the same corresponding
...
@@ -2021,7 +2036,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -2021,7 +2036,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
test
=
dropArguments
(
test
,
gpc
,
targs
.
subList
(
gpc
,
tpc
));
test
=
dropArguments
(
test
,
gpc
,
targs
.
subList
(
gpc
,
tpc
));
gtype
=
test
.
type
();
gtype
=
test
.
type
();
}
}
return
MethodHandleImpl
.
makeGuardWithTest
(
IMPL_TOKEN
,
test
,
target
,
fallback
);
return
MethodHandleImpl
.
makeGuardWithTest
(
test
,
target
,
fallback
);
}
}
static
RuntimeException
misMatchedTypes
(
String
what
,
MethodType
t1
,
MethodType
t2
)
{
static
RuntimeException
misMatchedTypes
(
String
what
,
MethodType
t1
,
MethodType
t2
)
{
...
@@ -2029,7 +2044,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -2029,7 +2044,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
}
}
/**
/**
* Make a method handle which adapts a target method handle,
* Make
s
a method handle which adapts a target method handle,
* by running it inside an exception handler.
* by running it inside an exception handler.
* If the target returns normally, the adapter returns that value.
* If the target returns normally, the adapter returns that value.
* If an exception matching the specified type is thrown, the fallback
* If an exception matching the specified type is thrown, the fallback
...
@@ -2092,7 +2107,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -2092,7 +2107,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
handler
=
dropArguments
(
handler
,
hpc
,
hargs
.
subList
(
hpc
,
tpc
));
handler
=
dropArguments
(
handler
,
hpc
,
hargs
.
subList
(
hpc
,
tpc
));
htype
=
handler
.
type
();
htype
=
handler
.
type
();
}
}
return
MethodHandleImpl
.
makeGuardWithCatch
(
IMPL_TOKEN
,
target
,
exType
,
handler
);
return
MethodHandleImpl
.
makeGuardWithCatch
(
target
,
exType
,
handler
);
}
}
/**
/**
...
@@ -2107,51 +2122,45 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -2107,51 +2122,45 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
*/
*/
public
static
public
static
MethodHandle
throwException
(
Class
<?>
returnType
,
Class
<?
extends
Throwable
>
exType
)
{
MethodHandle
throwException
(
Class
<?>
returnType
,
Class
<?
extends
Throwable
>
exType
)
{
return
MethodHandleImpl
.
throwException
(
IMPL_TOKEN
,
MethodType
.
methodType
(
returnType
,
exType
));
return
MethodHandleImpl
.
throwException
(
MethodType
.
methodType
(
returnType
,
exType
));
}
}
/**
/**
* Produces an instance of the given
"SAM"
interface which redirects
* Produces an instance of the given
single-method
interface which redirects
* its calls to the given method handle.
* its calls to the given method handle.
* <p>
* <p>
* A
SAM interface is an interface which declares a single abstract
method.
* A
single-method interface is an interface which declares a unique
method.
* When determining the unique
abstract method of a SAM
interface,
* When determining the unique
method of a single-method
interface,
* the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
* the public {@code Object} methods ({@code toString}, {@code equals}, {@code hashCode})
* are disregarded. For example, {@link java.util.Comparator} is a
SAM
interface,
* are disregarded. For example, {@link java.util.Comparator} is a
single-method
interface,
* even though it re-declares the {@code Object.equals} method.
* even though it re-declares the {@code Object.equals} method.
* Also, if the SAM interface has a supertype,
* the SAM interface may override an inherited method.
* Any such overrides are respected, and the method handle will be accessible
* by either the inherited method or the SAM method.
* In particular, a {@linkplain java.lang.reflect.Method#isBridge bridge method}
* may be created if the methods have different return types.
* <p>
* <p>
* The type must be public. No additional access checks are performed.
* The type must be public. No additional access checks are performed.
* <p>
* <p>
* The resulting instance of the required
SAM
type will respond to
* The resulting instance of the required type will respond to
* invocation of the
SAM
type's single abstract method by calling
* invocation of the type's single abstract method by calling
* the given {@code target} on the incoming arguments,
* the given {@code target} on the incoming arguments,
* and returning or throwing whatever the {@code target}
* and returning or throwing whatever the {@code target}
* returns or throws. The invocation will be as if by
* returns or throws. The invocation will be as if by
* {@code target.invokeGeneric}.
* {@code target.invokeGeneric}.
* The target's type will be checked before the
SAM
* The target's type will be checked before the
* instance is created, as if by a call to {@code asType},
* instance is created, as if by a call to {@code asType},
* which may result in a {@code WrongMethodTypeException}.
* which may result in a {@code WrongMethodTypeException}.
* <p>
* <p>
* The wrapper instance will implement the requested
SAM
interface
* The wrapper instance will implement the requested interface
* and its super-types, but no other
SAM typ
es.
* and its super-types, but no other
single-method interfac
es.
* This means that the
SAM
instance will not unexpectedly
* This means that the instance will not unexpectedly
* pass an {@code instanceof} test for any unrequested type.
* pass an {@code instanceof} test for any unrequested type.
* <p style="font-size:smaller;">
* <p style="font-size:smaller;">
* <em>Implementation Note:</em>
* <em>Implementation Note:</em>
* Therefore, each
SAM instance must implement a unique SAM typ
e.
* Therefore, each
instance must implement a unique single-method interfac
e.
* Implementations may not bundle together
* Implementations may not bundle together
* multiple
SAM typ
es onto single implementation classes
* multiple
single-method interfac
es onto single implementation classes
* in the style of {@link java.awt.AWTEventMulticaster}.
* in the style of {@link java.awt.AWTEventMulticaster}.
* <p>
* <p>
* The method handle may throw an <em>undeclared exception</em>,
* The method handle may throw an <em>undeclared exception</em>,
* which means any checked exception (or other checked throwable)
* which means any checked exception (or other checked throwable)
* not declared by the
SAM
type's single abstract method.
* not declared by the
requested
type's single abstract method.
* If this happens, the throwable will be wrapped in an instance of
* If this happens, the throwable will be wrapped in an instance of
* {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
* {@link java.lang.reflect.UndeclaredThrowableException UndeclaredThrowableException}
* and thrown in that wrapped form.
* and thrown in that wrapped form.
...
@@ -2161,28 +2170,37 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -2161,28 +2170,37 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
* by their behavior.
* by their behavior.
* It is not guaranteed to return a new instance for every call.
* It is not guaranteed to return a new instance for every call.
* <p>
* <p>
* Because of the possibility of {@linkplain java.lang.reflect.Method#isBridge bridge methods}
* and other corner cases, the interface may also have several abstract methods
* with the same name but having distinct descriptors (types of returns and parameters).
* In this case, all the methods are bound in common to the one given {@code target}.
* The type check and effective {@code asType} conversion is applied to each
* method type descriptor, and all abstract methods are bound to the {@code target} in common.
* Beyond this type check, no further checks are made to determine that the
* abstract methods are related in any way.
* <p>
* Future versions of this API may accept additional types,
* Future versions of this API may accept additional types,
* such as abstract classes with single abstract methods.
* such as abstract classes with single abstract methods.
* Future versions of this API may also equip wrapper instances
* Future versions of this API may also equip wrapper instances
* with one or more additional public "marker" interfaces.
* with one or more additional public "marker" interfaces.
*
*
* @param target the method handle to invoke from the wrapper
* @param target the method handle to invoke from the wrapper
* @param s
amType the desired type of the wrapper, a SAM typ
e
* @param s
mType the desired type of the wrapper, a single-method interfac
e
* @return a correctly-typed wrapper for the given {@code target}
* @return a correctly-typed wrapper for the given {@code target}
* @throws NullPointerException if either argument is null
* @throws NullPointerException if either argument is null
* @throws IllegalArgumentException if the {@code s
a
mType} is not a
* @throws IllegalArgumentException if the {@code smType} is not a
* valid argument to this method
* valid argument to this method
* @throws WrongMethodTypeException if the {@code target} cannot
* @throws WrongMethodTypeException if the {@code target} cannot
* be converted to the type required by the
SAM typ
e
* be converted to the type required by the
requested interfac
e
*/
*/
// Other notes to implementors:
// Other notes to implementors:
// <p>
// <p>
// No stable mapping is promised between the
SAM typ
e and
// No stable mapping is promised between the
single-method interfac
e and
// the implementation class C. Over time, several implementation
// the implementation class C. Over time, several implementation
// classes might be used for the same
SAM
type.
// classes might be used for the same type.
// <p>
// <p>
// If the implementation is able
// If the implementation is able
// to prove that a wrapper of the required
SAM
type
// to prove that a wrapper of the required type
// has already been created for a given
// has already been created for a given
// method handle, or for another method handle with the
// method handle, or for another method handle with the
// same behavior, the implementation may return that wrapper in place of
// same behavior, the implementation may return that wrapper in place of
...
@@ -2191,34 +2209,34 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -2191,34 +2209,34 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
// This method is designed to apply to common use cases
// This method is designed to apply to common use cases
// where a single method handle must interoperate with
// where a single method handle must interoperate with
// an interface that implements a function-like
// an interface that implements a function-like
// API. Additional variations, such as
SAM
classes with
// API. Additional variations, such as
single-abstract-method
classes with
// private constructors, or interfaces with multiple but related
// private constructors, or interfaces with multiple but related
// entry points, must be covered by hand-written or automatically
// entry points, must be covered by hand-written or automatically
// generated adapter classes.
// generated adapter classes.
//
//
public
static
public
static
<
T
>
T
asInstance
(
final
MethodHandle
target
,
final
Class
<
T
>
s
a
mType
)
{
<
T
>
T
asInstance
(
final
MethodHandle
target
,
final
Class
<
T
>
smType
)
{
// POC implementation only; violates the above contract several ways
// POC implementation only; violates the above contract several ways
final
Method
s
am
=
getSamMethod
(
sa
mType
);
final
Method
s
m
=
getSingleMethod
(
s
mType
);
if
(
s
a
m
==
null
)
if
(
sm
==
null
)
throw
new
IllegalArgumentException
(
"not a
SAM type: "
+
sa
mType
.
getName
());
throw
new
IllegalArgumentException
(
"not a
single-method interface: "
+
s
mType
.
getName
());
MethodType
s
amMT
=
MethodType
.
methodType
(
sam
.
getReturnType
(),
sa
m
.
getParameterTypes
());
MethodType
s
mMT
=
MethodType
.
methodType
(
sm
.
getReturnType
(),
s
m
.
getParameterTypes
());
MethodHandle
checkTarget
=
target
.
asType
(
s
a
mMT
);
// make throw WMT
MethodHandle
checkTarget
=
target
.
asType
(
smMT
);
// make throw WMT
checkTarget
=
checkTarget
.
asType
(
checkTarget
.
type
().
changeReturnType
(
Object
.
class
));
checkTarget
=
checkTarget
.
asType
(
checkTarget
.
type
().
changeReturnType
(
Object
.
class
));
final
MethodHandle
vaTarget
=
checkTarget
.
asSpreader
(
Object
[].
class
,
s
a
mMT
.
parameterCount
());
final
MethodHandle
vaTarget
=
checkTarget
.
asSpreader
(
Object
[].
class
,
smMT
.
parameterCount
());
return
s
a
mType
.
cast
(
Proxy
.
newProxyInstance
(
return
smType
.
cast
(
Proxy
.
newProxyInstance
(
s
a
mType
.
getClassLoader
(),
smType
.
getClassLoader
(),
new
Class
[]{
s
a
mType
,
WrapperInstance
.
class
},
new
Class
[]{
smType
,
WrapperInstance
.
class
},
new
InvocationHandler
()
{
new
InvocationHandler
()
{
private
Object
getArg
(
String
name
)
{
private
Object
getArg
(
String
name
)
{
if
((
Object
)
name
==
"getWrapperInstanceTarget"
)
return
target
;
if
((
Object
)
name
==
"getWrapperInstanceTarget"
)
return
target
;
if
((
Object
)
name
==
"getWrapperInstanceType"
)
return
s
a
mType
;
if
((
Object
)
name
==
"getWrapperInstanceType"
)
return
smType
;
throw
new
AssertionError
();
throw
new
AssertionError
();
}
}
public
Object
invoke
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
public
Object
invoke
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
if
(
method
.
getDeclaringClass
()
==
WrapperInstance
.
class
)
if
(
method
.
getDeclaringClass
()
==
WrapperInstance
.
class
)
return
getArg
(
method
.
getName
());
return
getArg
(
method
.
getName
());
if
(
method
.
equals
(
s
a
m
))
if
(
method
.
equals
(
sm
))
return
vaTarget
.
invokeExact
(
args
);
return
vaTarget
.
invokeExact
(
args
);
if
(
isObjectMethod
(
method
))
if
(
isObjectMethod
(
method
))
return
callObjectMethod
(
this
,
method
,
args
);
return
callObjectMethod
(
this
,
method
,
args
);
...
@@ -2228,7 +2246,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -2228,7 +2246,7 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
}
}
/**
/**
* Determine if the given object was produced by a call to {@link #asInstance asInstance}.
* Determine
s
if the given object was produced by a call to {@link #asInstance asInstance}.
* @param x any reference
* @param x any reference
* @return true if the reference is not null and points to an object produced by {@code asInstance}
* @return true if the reference is not null and points to an object produced by {@code asInstance}
*/
*/
...
@@ -2248,11 +2266,11 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -2248,11 +2266,11 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
/**
/**
* Produces or recovers a target method handle which is behaviorally
* Produces or recovers a target method handle which is behaviorally
* equivalent to the
SAM
method of this wrapper instance.
* equivalent to the
unique
method of this wrapper instance.
* The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
* The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
* This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
* This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
* @param x any reference
* @param x any reference
* @return a method handle implementing the
SAM
method
* @return a method handle implementing the
unique
method
* @throws IllegalArgumentException if the reference x is not to a wrapper instance
* @throws IllegalArgumentException if the reference x is not to a wrapper instance
*/
*/
public
static
public
static
...
@@ -2261,11 +2279,11 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -2261,11 +2279,11 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
}
}
/**
/**
* Recover
the SAM
type for which this wrapper instance was created.
* Recover
s the unique single-method interface
type for which this wrapper instance was created.
* The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
* The object {@code x} must have been produced by a call to {@link #asInstance asInstance}.
* This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
* This requirement may be tested via {@link #isWrapperInstance isWrapperInstance}.
* @param x any reference
* @param x any reference
* @return the
SAM
type for which the wrapper was created
* @return the
single-method interface
type for which the wrapper was created
* @throws IllegalArgumentException if the reference x is not to a wrapper instance
* @throws IllegalArgumentException if the reference x is not to a wrapper instance
*/
*/
public
static
public
static
...
@@ -2305,24 +2323,24 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -2305,24 +2323,24 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
}
}
private
static
private
static
Method
getS
amMethod
(
Class
<?>
sa
mType
)
{
Method
getS
ingleMethod
(
Class
<?>
s
mType
)
{
Method
s
a
m
=
null
;
Method
sm
=
null
;
for
(
Method
m
:
s
a
mType
.
getMethods
())
{
for
(
Method
m
:
smType
.
getMethods
())
{
int
mod
=
m
.
getModifiers
();
int
mod
=
m
.
getModifiers
();
if
(
Modifier
.
isAbstract
(
mod
))
{
if
(
Modifier
.
isAbstract
(
mod
))
{
if
(
s
am
!=
null
&&
!
isObjectMethod
(
sa
m
))
if
(
s
m
!=
null
&&
!
isObjectMethod
(
s
m
))
return
null
;
// too many abstract methods
return
null
;
// too many abstract methods
s
a
m
=
m
;
sm
=
m
;
}
}
}
}
if
(!
s
amType
.
isInterface
()
&&
getSamConstructor
(
sa
mType
)
==
null
)
if
(!
s
mType
.
isInterface
()
&&
getSingleConstructor
(
s
mType
)
==
null
)
return
null
;
// wrong kind of constructor
return
null
;
// wrong kind of constructor
return
s
a
m
;
return
sm
;
}
}
private
static
private
static
Constructor
getS
amConstructor
(
Class
<?>
sa
mType
)
{
Constructor
getS
ingleConstructor
(
Class
<?>
s
mType
)
{
for
(
Constructor
c
:
s
a
mType
.
getDeclaredConstructors
())
{
for
(
Constructor
c
:
smType
.
getDeclaredConstructors
())
{
if
(
c
.
getParameterTypes
().
length
==
0
)
{
if
(
c
.
getParameterTypes
().
length
==
0
)
{
int
mod
=
c
.
getModifiers
();
int
mod
=
c
.
getModifiers
();
if
(
Modifier
.
isPublic
(
mod
)
||
Modifier
.
isProtected
(
mod
))
if
(
Modifier
.
isPublic
(
mod
)
||
Modifier
.
isProtected
(
mod
))
...
@@ -2334,6 +2352,6 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
...
@@ -2334,6 +2352,6 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
/*non-public*/
/*non-public*/
static
MethodHandle
asVarargsCollector
(
MethodHandle
target
,
Class
<?>
arrayType
)
{
static
MethodHandle
asVarargsCollector
(
MethodHandle
target
,
Class
<?>
arrayType
)
{
return
MethodHandleImpl
.
asVarargsCollector
(
IMPL_TOKEN
,
target
,
arrayType
);
return
MethodHandleImpl
.
asVarargsCollector
(
target
,
arrayType
);
}
}
}
}
src/share/classes/java/
dyn
/MethodType.java
→
src/share/classes/java/
lang/invoke
/MethodType.java
浏览文件 @
33ee9ccf
...
@@ -23,18 +23,14 @@
...
@@ -23,18 +23,14 @@
* questions.
* questions.
*/
*/
package
java.
dyn
;
package
java.
lang.invoke
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.List
;
import
sun.dyn.Access
;
import
sun.invoke.util.BytecodeDescriptor
;
import
sun.dyn.Invokers
;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
import
sun.dyn.MethodHandleImpl
;
import
sun.dyn.MethodTypeImpl
;
import
sun.dyn.util.BytecodeDescriptor
;
import
static
sun
.
dyn
.
MemberName
.
newIllegalArgumentException
;
/**
/**
* A method type represents the arguments and return type accepted and
* A method type represents the arguments and return type accepted and
...
@@ -96,34 +92,6 @@ class MethodType implements java.io.Serializable {
...
@@ -96,34 +92,6 @@ class MethodType implements java.io.Serializable {
private
MethodType
wrapAlt
;
// alternative wrapped/unwrapped version
private
MethodType
wrapAlt
;
// alternative wrapped/unwrapped version
private
Invokers
invokers
;
// cache of handy higher-order adapters
private
Invokers
invokers
;
// cache of handy higher-order adapters
private
static
final
Access
IMPL_TOKEN
=
Access
.
getToken
();
// share a cache with a friend in this package
Invokers
getInvokers
()
{
return
invokers
;
}
void
setInvokers
(
Invokers
inv
)
{
invokers
=
inv
;
}
static
{
// This hack allows the implementation package special access to
// the internals of MethodType. In particular, the MTImpl has all sorts
// of cached information useful to the implementation code.
MethodTypeImpl
.
setMethodTypeFriend
(
IMPL_TOKEN
,
new
MethodTypeImpl
.
MethodTypeFriend
()
{
public
Class
<?>[]
ptypes
(
MethodType
mt
)
{
return
mt
.
ptypes
;
}
public
MethodTypeImpl
form
(
MethodType
mt
)
{
return
mt
.
form
;
}
public
void
setForm
(
MethodType
mt
,
MethodTypeImpl
form
)
{
assert
(
mt
.
form
==
null
);
mt
.
form
=
(
MethodTypeForm
)
form
;
}
public
MethodType
makeImpl
(
Class
<?>
rtype
,
Class
<?>[]
ptypes
,
boolean
trusted
)
{
return
MethodType
.
makeImpl
(
rtype
,
ptypes
,
trusted
);
}
public
MethodTypeImpl
newMethodTypeForm
(
MethodType
mt
)
{
return
new
MethodTypeForm
(
mt
);
}
public
Invokers
getInvokers
(
MethodType
mt
)
{
return
mt
.
invokers
;
}
public
void
setInvokers
(
MethodType
mt
,
Invokers
inv
)
{
mt
.
invokers
=
inv
;
}
});
}
/**
/**
* Check the given parameters for validity and store them into the final fields.
* Check the given parameters for validity and store them into the final fields.
*/
*/
...
@@ -134,6 +102,10 @@ class MethodType implements java.io.Serializable {
...
@@ -134,6 +102,10 @@ class MethodType implements java.io.Serializable {
this
.
ptypes
=
ptypes
;
this
.
ptypes
=
ptypes
;
}
}
/*trusted*/
MethodTypeForm
form
()
{
return
form
;
}
/*trusted*/
Class
<?>
rtype
()
{
return
rtype
;
}
/*trusted*/
Class
<?>[]
ptypes
()
{
return
ptypes
;
}
private
static
void
checkRtype
(
Class
<?>
rtype
)
{
private
static
void
checkRtype
(
Class
<?>
rtype
)
{
rtype
.
equals
(
rtype
);
// null check
rtype
.
equals
(
rtype
);
// null check
}
}
...
@@ -168,7 +140,7 @@ class MethodType implements java.io.Serializable {
...
@@ -168,7 +140,7 @@ class MethodType implements java.io.Serializable {
static
final
Class
<?>[]
NO_PTYPES
=
{};
static
final
Class
<?>[]
NO_PTYPES
=
{};
/**
/**
* Find
or create
an instance of the given method type.
* Find
s or creates
an instance of the given method type.
* @param rtype the return type
* @param rtype the return type
* @param ptypes the parameter types
* @param ptypes the parameter types
* @return a method type with the given components
* @return a method type with the given components
...
@@ -253,7 +225,7 @@ class MethodType implements java.io.Serializable {
...
@@ -253,7 +225,7 @@ class MethodType implements java.io.Serializable {
* @param trusted whether the ptypes can be used without cloning
* @param trusted whether the ptypes can be used without cloning
* @return the unique method type of the desired structure
* @return the unique method type of the desired structure
*/
*/
private
static
/*trusted*/
static
MethodType
makeImpl
(
Class
<?>
rtype
,
Class
<?>[]
ptypes
,
boolean
trusted
)
{
MethodType
makeImpl
(
Class
<?>
rtype
,
Class
<?>[]
ptypes
,
boolean
trusted
)
{
if
(
ptypes
==
null
||
ptypes
.
length
==
0
)
{
if
(
ptypes
==
null
||
ptypes
.
length
==
0
)
{
ptypes
=
NO_PTYPES
;
trusted
=
true
;
ptypes
=
NO_PTYPES
;
trusted
=
true
;
...
@@ -269,7 +241,12 @@ class MethodType implements java.io.Serializable {
...
@@ -269,7 +241,12 @@ class MethodType implements java.io.Serializable {
// defensively copy the array passed in by the user
// defensively copy the array passed in by the user
mt1
=
new
MethodType
(
rtype
,
ptypes
.
clone
());
mt1
=
new
MethodType
(
rtype
,
ptypes
.
clone
());
// promote the object to the Real Thing, and reprobe
// promote the object to the Real Thing, and reprobe
MethodTypeImpl
.
initForm
(
IMPL_TOKEN
,
mt1
);
MethodTypeForm
form
=
MethodTypeForm
.
findForm
(
mt1
);
mt1
.
form
=
form
;
if
(
form
.
erasedType
==
mt1
)
{
// This is a principal (erased) type; show it to the JVM.
MethodHandleNatives
.
init
(
mt1
);
}
synchronized
(
internTable
)
{
synchronized
(
internTable
)
{
mt0
=
internTable
.
get
(
mt1
);
mt0
=
internTable
.
get
(
mt1
);
if
(
mt0
!=
null
)
if
(
mt0
!=
null
)
...
@@ -279,12 +256,6 @@ class MethodType implements java.io.Serializable {
...
@@ -279,12 +256,6 @@ class MethodType implements java.io.Serializable {
return
mt1
;
return
mt1
;
}
}
// Entry point from JVM. TODO: Change the name & signature.
private
static
MethodType
makeImpl
(
Class
<?>
rtype
,
Class
<?>[]
ptypes
,
boolean
ignore1
,
boolean
ignore2
)
{
return
makeImpl
(
rtype
,
ptypes
,
true
);
}
private
static
final
MethodType
[]
objectOnlyTypes
=
new
MethodType
[
20
];
private
static
final
MethodType
[]
objectOnlyTypes
=
new
MethodType
[
20
];
/**
/**
...
@@ -519,7 +490,7 @@ class MethodType implements java.io.Serializable {
...
@@ -519,7 +490,7 @@ class MethodType implements java.io.Serializable {
}
}
/**
/**
* Convert all wrapper types to their corresponding primitive types.
* Convert
s
all wrapper types to their corresponding primitive types.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* All primitive types (including {@code void}) will remain unchanged.
* All primitive types (including {@code void}) will remain unchanged.
* A return type of {@code java.lang.Void} is changed to {@code void}.
* A return type of {@code java.lang.Void} is changed to {@code void}.
...
@@ -535,7 +506,7 @@ class MethodType implements java.io.Serializable {
...
@@ -535,7 +506,7 @@ class MethodType implements java.io.Serializable {
MethodType
wt
=
pt
.
wrapAlt
;
MethodType
wt
=
pt
.
wrapAlt
;
if
(
wt
==
null
)
{
if
(
wt
==
null
)
{
// fill in lazily
// fill in lazily
wt
=
MethodType
Impl
.
canonicalize
(
pt
,
MethodTypeImpl
.
WRAP
,
MethodTypeImpl
.
WRAP
);
wt
=
MethodType
Form
.
canonicalize
(
pt
,
MethodTypeForm
.
WRAP
,
MethodTypeForm
.
WRAP
);
assert
(
wt
!=
null
);
assert
(
wt
!=
null
);
pt
.
wrapAlt
=
wt
;
pt
.
wrapAlt
=
wt
;
}
}
...
@@ -547,7 +518,7 @@ class MethodType implements java.io.Serializable {
...
@@ -547,7 +518,7 @@ class MethodType implements java.io.Serializable {
MethodType
uwt
=
wt
.
wrapAlt
;
MethodType
uwt
=
wt
.
wrapAlt
;
if
(
uwt
==
null
)
{
if
(
uwt
==
null
)
{
// fill in lazily
// fill in lazily
uwt
=
MethodType
Impl
.
canonicalize
(
wt
,
MethodTypeImpl
.
UNWRAP
,
MethodTypeImpl
.
UNWRAP
);
uwt
=
MethodType
Form
.
canonicalize
(
wt
,
MethodTypeForm
.
UNWRAP
,
MethodTypeForm
.
UNWRAP
);
if
(
uwt
==
null
)
if
(
uwt
==
null
)
uwt
=
wt
;
// type has no wrappers or prims at all
uwt
=
wt
;
// type has no wrappers or prims at all
wt
.
wrapAlt
=
uwt
;
wt
.
wrapAlt
=
uwt
;
...
@@ -658,7 +629,7 @@ class MethodType implements java.io.Serializable {
...
@@ -658,7 +629,7 @@ class MethodType implements java.io.Serializable {
/// Queries which have to do with the bytecode architecture
/// Queries which have to do with the bytecode architecture
/** Reports the number of JVM stack slots required to invoke a method
/** Reports the number of JVM stack slots required to invoke a method
* of this type. Note that (for historic reasons) the JVM requires
* of this type. Note that (for historic
al
reasons) the JVM requires
* a second stack slot to pass long and double arguments.
* a second stack slot to pass long and double arguments.
* So this method returns {@link #parameterCount() parameterCount} plus the
* So this method returns {@link #parameterCount() parameterCount} plus the
* number of long and double parameters (if any).
* number of long and double parameters (if any).
...
@@ -666,12 +637,18 @@ class MethodType implements java.io.Serializable {
...
@@ -666,12 +637,18 @@ class MethodType implements java.io.Serializable {
* This method is included for the benfit of applications that must
* This method is included for the benfit of applications that must
* generate bytecodes that process method handles and invokedynamic.
* generate bytecodes that process method handles and invokedynamic.
* @return the number of JVM stack slots for this type's parameters
* @return the number of JVM stack slots for this type's parameters
* @deprecated Will be removed for PFD.
*/
*/
public
int
parameterSlotCount
()
{
/*non-public*/
int
parameterSlotCount
()
{
return
form
.
parameterSlotCount
();
return
form
.
parameterSlotCount
();
}
}
/*non-public*/
Invokers
invokers
()
{
Invokers
inv
=
invokers
;
if
(
inv
!=
null
)
return
inv
;
invokers
=
inv
=
new
Invokers
(
this
);
return
inv
;
}
/** Reports the number of JVM stack slots which carry all parameters including and after
/** Reports the number of JVM stack slots which carry all parameters including and after
* the given position, which must be in the range of 0 to
* the given position, which must be in the range of 0 to
* {@code parameterCount} inclusive. Successive parameters are
* {@code parameterCount} inclusive. Successive parameters are
...
@@ -694,9 +671,8 @@ class MethodType implements java.io.Serializable {
...
@@ -694,9 +671,8 @@ class MethodType implements java.io.Serializable {
* @return the index of the (shallowest) JVM stack slot transmitting the
* @return the index of the (shallowest) JVM stack slot transmitting the
* given parameter
* given parameter
* @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
* @throws IllegalArgumentException if {@code num} is negative or greater than {@code parameterCount()}
* @deprecated Will be removed for PFD.
*/
*/
public
int
parameterSlotDepth
(
int
num
)
{
/*non-public*/
int
parameterSlotDepth
(
int
num
)
{
if
(
num
<
0
||
num
>
ptypes
.
length
)
if
(
num
<
0
||
num
>
ptypes
.
length
)
parameterType
(
num
);
// force a range check
parameterType
(
num
);
// force a range check
return
form
.
parameterToArgSlot
(
num
-
1
);
return
form
.
parameterToArgSlot
(
num
-
1
);
...
@@ -710,14 +686,14 @@ class MethodType implements java.io.Serializable {
...
@@ -710,14 +686,14 @@ class MethodType implements java.io.Serializable {
* This method is included for the benfit of applications that must
* This method is included for the benfit of applications that must
* generate bytecodes that process method handles and invokedynamic.
* generate bytecodes that process method handles and invokedynamic.
* @return the number of JVM stack slots (0, 1, or 2) for this type's return value
* @return the number of JVM stack slots (0, 1, or 2) for this type's return value
*
@deprecated
Will be removed for PFD.
* Will be removed for PFD.
*/
*/
public
int
returnSlotCount
()
{
/*non-public*/
int
returnSlotCount
()
{
return
form
.
returnSlotCount
();
return
form
.
returnSlotCount
();
}
}
/**
/**
* Find
or create
an instance of a method type, given the spelling of its bytecode descriptor.
* Find
s or creates
an instance of a method type, given the spelling of its bytecode descriptor.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
* Any class or interface name embedded in the descriptor string
* Any class or interface name embedded in the descriptor string
* will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
* will be resolved by calling {@link ClassLoader#loadClass(java.lang.String)}
...
...
src/share/classes/
sun/dyn/MethodTypeImpl
.java
→
src/share/classes/
java/lang/invoke/MethodTypeForm
.java
浏览文件 @
33ee9ccf
...
@@ -23,11 +23,10 @@
...
@@ -23,11 +23,10 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
java.dyn.*
;
import
sun.invoke.util.Wrapper
;
import
sun.dyn.util.Wrapper
;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*;
import
static
sun
.
dyn
.
MemberName
.
newIllegalArgumentException
;
/**
/**
* Shared information for a group of method types, which differ
* Shared information for a group of method types, which differ
...
@@ -42,7 +41,7 @@ import static sun.dyn.MemberName.newIllegalArgumentException;
...
@@ -42,7 +41,7 @@ import static sun.dyn.MemberName.newIllegalArgumentException;
* No more than half of these are likely to be loaded at once.
* No more than half of these are likely to be loaded at once.
* @author John Rose
* @author John Rose
*/
*/
public
class
MethodTypeImpl
{
class
MethodTypeForm
{
final
int
[]
argToSlotTable
,
slotToArgTable
;
final
int
[]
argToSlotTable
,
slotToArgTable
;
final
long
argCounts
;
// packed slot & value counts
final
long
argCounts
;
// packed slot & value counts
final
long
primCounts
;
// packed prim & double counts
final
long
primCounts
;
// packed prim & double counts
...
@@ -66,39 +65,10 @@ public class MethodTypeImpl {
...
@@ -66,39 +65,10 @@ public class MethodTypeImpl {
return
erasedType
;
return
erasedType
;
}
}
public
static
MethodTypeImpl
of
(
MethodType
type
)
{
protected
MethodTypeForm
(
MethodType
erasedType
)
{
return
METHOD_TYPE_FRIEND
.
form
(
type
);
}
/** Access methods for the internals of MethodType, supplied to
* MethodTypeImpl as a trusted agent.
*/
static
public
interface
MethodTypeFriend
{
Class
<?>[]
ptypes
(
MethodType
mt
);
MethodTypeImpl
form
(
MethodType
mt
);
void
setForm
(
MethodType
mt
,
MethodTypeImpl
form
);
MethodType
makeImpl
(
Class
<?>
rtype
,
Class
<?>[]
ptypes
,
boolean
trusted
);
MethodTypeImpl
newMethodTypeForm
(
MethodType
mt
);
Invokers
getInvokers
(
MethodType
mt
);
void
setInvokers
(
MethodType
mt
,
Invokers
inv
);
}
public
static
void
setMethodTypeFriend
(
Access
token
,
MethodTypeFriend
am
)
{
Access
.
check
(
token
);
if
(
METHOD_TYPE_FRIEND
!=
null
)
throw
new
InternalError
();
// just once
METHOD_TYPE_FRIEND
=
am
;
}
static
private
MethodTypeFriend
METHOD_TYPE_FRIEND
;
static
MethodType
makeImpl
(
Access
token
,
Class
<?>
rtype
,
Class
<?>[]
ptypes
,
boolean
trusted
)
{
Access
.
check
(
token
);
return
METHOD_TYPE_FRIEND
.
makeImpl
(
rtype
,
ptypes
,
trusted
);
}
protected
MethodTypeImpl
(
MethodType
erasedType
)
{
this
.
erasedType
=
erasedType
;
this
.
erasedType
=
erasedType
;
Class
<?>[]
ptypes
=
METHOD_TYPE_FRIEND
.
ptypes
(
erasedType
);
Class
<?>[]
ptypes
=
erasedType
.
ptypes
(
);
int
ptypeCount
=
ptypes
.
length
;
int
ptypeCount
=
ptypes
.
length
;
int
pslotCount
=
ptypeCount
;
// temp. estimate
int
pslotCount
=
ptypeCount
;
// temp. estimate
int
rtypeCount
=
1
;
// temp. estimate
int
rtypeCount
=
1
;
// temp. estimate
...
@@ -260,7 +230,7 @@ public class MethodTypeImpl {
...
@@ -260,7 +230,7 @@ public class MethodTypeImpl {
* the type {@code (Object,int)Object} produces {@code null}.
* the type {@code (Object,int)Object} produces {@code null}.
*/
*/
public
static
int
[]
primsAtEndOrder
(
MethodType
mt
)
{
public
static
int
[]
primsAtEndOrder
(
MethodType
mt
)
{
MethodType
Impl
form
=
METHOD_TYPE_FRIEND
.
form
(
mt
);
MethodType
Form
form
=
mt
.
form
(
);
if
(
form
.
primsAtEnd
==
form
.
erasedType
)
if
(
form
.
primsAtEnd
==
form
.
erasedType
)
// quick check shows no reordering is necessary
// quick check shows no reordering is necessary
return
null
;
return
null
;
...
@@ -273,7 +243,7 @@ public class MethodTypeImpl {
...
@@ -273,7 +243,7 @@ public class MethodTypeImpl {
int
lac
=
form
.
longPrimitiveParameterCount
();
int
lac
=
form
.
longPrimitiveParameterCount
();
int
rfill
=
0
,
ifill
=
argc
-
pac
,
lfill
=
argc
-
lac
;
int
rfill
=
0
,
ifill
=
argc
-
pac
,
lfill
=
argc
-
lac
;
Class
<?>[]
ptypes
=
METHOD_TYPE_FRIEND
.
ptypes
(
mt
);
Class
<?>[]
ptypes
=
mt
.
ptypes
(
);
boolean
changed
=
false
;
boolean
changed
=
false
;
for
(
int
i
=
0
;
i
<
ptypes
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
ptypes
.
length
;
i
++)
{
Class
<?>
pt
=
ptypes
[
i
];
Class
<?>
pt
=
ptypes
[
i
];
...
@@ -300,7 +270,7 @@ public class MethodTypeImpl {
...
@@ -300,7 +270,7 @@ public class MethodTypeImpl {
*/
*/
public
static
MethodType
reorderParameters
(
MethodType
mt
,
int
[]
newParamOrder
,
Class
<?>[]
moreParams
)
{
public
static
MethodType
reorderParameters
(
MethodType
mt
,
int
[]
newParamOrder
,
Class
<?>[]
moreParams
)
{
if
(
newParamOrder
==
null
)
return
mt
;
// no-op reordering
if
(
newParamOrder
==
null
)
return
mt
;
// no-op reordering
Class
<?>[]
ptypes
=
METHOD_TYPE_FRIEND
.
ptypes
(
mt
);
Class
<?>[]
ptypes
=
mt
.
ptypes
(
);
Class
<?>[]
ntypes
=
new
Class
<?>[
newParamOrder
.
length
];
Class
<?>[]
ntypes
=
new
Class
<?>[
newParamOrder
.
length
];
int
maxParam
=
ptypes
.
length
+
(
moreParams
==
null
?
0
:
moreParams
.
length
);
int
maxParam
=
ptypes
.
length
+
(
moreParams
==
null
?
0
:
moreParams
.
length
);
boolean
changed
=
(
ntypes
.
length
!=
ptypes
.
length
);
boolean
changed
=
(
ntypes
.
length
!=
ptypes
.
length
);
...
@@ -314,7 +284,7 @@ public class MethodTypeImpl {
...
@@ -314,7 +284,7 @@ public class MethodTypeImpl {
ntypes
[
i
]
=
nt
;
ntypes
[
i
]
=
nt
;
}
}
if
(!
changed
)
return
mt
;
if
(!
changed
)
return
mt
;
return
M
ETHOD_TYPE_FRIEND
.
makeImpl
(
mt
.
returnType
(),
ntypes
,
true
);
return
M
ethodType
.
makeImpl
(
mt
.
returnType
(),
ntypes
,
true
);
}
}
private
static
boolean
hasTwoArgSlots
(
Class
<?>
type
)
{
private
static
boolean
hasTwoArgSlots
(
Class
<?>
type
)
{
...
@@ -376,28 +346,18 @@ public class MethodTypeImpl {
...
@@ -376,28 +346,18 @@ public class MethodTypeImpl {
return
slotToArgTable
[
argSlot
]
-
1
;
return
slotToArgTable
[
argSlot
]
-
1
;
}
}
public
static
void
initForm
(
Access
token
,
MethodType
mt
)
{
static
MethodTypeForm
findForm
(
MethodType
mt
)
{
Access
.
check
(
token
);
MethodTypeImpl
form
=
findForm
(
mt
);
METHOD_TYPE_FRIEND
.
setForm
(
mt
,
form
);
if
(
form
.
erasedType
==
mt
)
{
// This is a principal (erased) type; show it to the JVM.
MethodHandleImpl
.
init
(
token
,
mt
);
}
}
static
MethodTypeImpl
findForm
(
MethodType
mt
)
{
MethodType
erased
=
canonicalize
(
mt
,
ERASE
,
ERASE
);
MethodType
erased
=
canonicalize
(
mt
,
ERASE
,
ERASE
);
if
(
erased
==
null
)
{
if
(
erased
==
null
)
{
// It is already erased. Make a new MethodType
Impl
.
// It is already erased. Make a new MethodType
Form
.
return
METHOD_TYPE_FRIEND
.
new
MethodTypeForm
(
mt
);
return
new
MethodTypeForm
(
mt
);
}
else
{
}
else
{
// Share the MethodType
Impl
with the erased version.
// Share the MethodType
Form
with the erased version.
return
METHOD_TYPE_FRIEND
.
form
(
erased
);
return
erased
.
form
(
);
}
}
}
}
/** Codes for {@link #canonicalize(java.lang.Class, int).
/** Codes for {@link #canonicalize(java.lang.Class, int)
}
.
* ERASE means change every reference to {@code Object}.
* ERASE means change every reference to {@code Object}.
* WRAP means convert primitives (including {@code void} to their
* WRAP means convert primitives (including {@code void} to their
* corresponding wrapper types. UNWRAP means the reverse of WRAP.
* corresponding wrapper types. UNWRAP means the reverse of WRAP.
...
@@ -414,10 +374,10 @@ public class MethodTypeImpl {
...
@@ -414,10 +374,10 @@ public class MethodTypeImpl {
* Otherwise return null.
* Otherwise return null.
*/
*/
public
static
MethodType
canonicalize
(
MethodType
mt
,
int
howRet
,
int
howArgs
)
{
public
static
MethodType
canonicalize
(
MethodType
mt
,
int
howRet
,
int
howArgs
)
{
Class
<?>[]
ptypes
=
METHOD_TYPE_FRIEND
.
ptypes
(
mt
);
Class
<?>[]
ptypes
=
mt
.
ptypes
(
);
Class
<?>[]
ptc
=
MethodType
Impl
.
canonicalizes
(
ptypes
,
howArgs
);
Class
<?>[]
ptc
=
MethodType
Form
.
canonicalizes
(
ptypes
,
howArgs
);
Class
<?>
rtype
=
mt
.
returnType
();
Class
<?>
rtype
=
mt
.
returnType
();
Class
<?>
rtc
=
MethodType
Impl
.
canonicalize
(
rtype
,
howRet
);
Class
<?>
rtc
=
MethodType
Form
.
canonicalize
(
rtype
,
howRet
);
if
(
ptc
==
null
&&
rtc
==
null
)
{
if
(
ptc
==
null
&&
rtc
==
null
)
{
// It is already canonical.
// It is already canonical.
return
null
;
return
null
;
...
@@ -425,7 +385,7 @@ public class MethodTypeImpl {
...
@@ -425,7 +385,7 @@ public class MethodTypeImpl {
// Find the erased version of the method type:
// Find the erased version of the method type:
if
(
rtc
==
null
)
rtc
=
rtype
;
if
(
rtc
==
null
)
rtc
=
rtype
;
if
(
ptc
==
null
)
ptc
=
ptypes
;
if
(
ptc
==
null
)
ptc
=
ptypes
;
return
M
ETHOD_TYPE_FRIEND
.
makeImpl
(
rtc
,
ptc
,
true
);
return
M
ethodType
.
makeImpl
(
rtc
,
ptc
,
true
);
}
}
/** Canonicalize the given return or param type.
/** Canonicalize the given return or param type.
...
@@ -496,16 +456,16 @@ public class MethodTypeImpl {
...
@@ -496,16 +456,16 @@ public class MethodTypeImpl {
return
cs
;
return
cs
;
}
}
public
static
Invokers
invokers
(
Access
token
,
MethodType
type
)
{
/*non-public*/
void
notifyGenericMethodType
(
)
{
Access
.
check
(
token
)
;
if
(
genericInvoker
!=
null
)
return
;
return
invokers
(
type
);
try
{
}
// Trigger adapter creation.
/*non-public*/
static
Invokers
invokers
(
MethodType
type
)
{
genericInvoker
=
InvokeGeneric
.
genericInvokerOf
(
erasedType
);
Invokers
inv
=
METHOD_TYPE_FRIEND
.
getInvokers
(
type
);
}
catch
(
Exception
ex
)
{
if
(
inv
!=
null
)
return
inv
;
Error
err
=
new
InternalError
(
"Exception while resolving invokeGeneric"
)
;
inv
=
new
Invokers
(
type
);
err
.
initCause
(
ex
);
METHOD_TYPE_FRIEND
.
setInvokers
(
type
,
inv
)
;
throw
err
;
return
inv
;
}
}
}
@Override
@Override
...
...
src/share/classes/java/
dyn
/MutableCallSite.java
→
src/share/classes/java/
lang/invoke
/MutableCallSite.java
浏览文件 @
33ee9ccf
...
@@ -23,10 +23,8 @@
...
@@ -23,10 +23,8 @@
* questions.
* questions.
*/
*/
package
java.
dyn
;
package
java.
lang.invoke
;
import
sun.dyn.*
;
import
sun.dyn.empty.Empty
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
java.util.concurrent.atomic.AtomicInteger
;
/**
/**
...
...
src/share/classes/
sun/dyn
/SpreadGeneric.java
→
src/share/classes/
java/lang/invoke
/SpreadGeneric.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,14 +23,14 @@
...
@@ -23,14 +23,14 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
java.dyn.*
;
import
sun.invoke.util.ValueConversions
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.InvocationTargetException
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
s
un.dyn.util.ValueConversions
;
import
s
tatic
java
.
lang
.
invoke
.
MethodHandleStatics
.*
;
import
static
sun
.
dyn
.
MemberName
.
newIllegalArgumentException
;
import
static
java
.
lang
.
invoke
.
MethodHandles
.
Lookup
.
IMPL_LOOKUP
;
/**
/**
* Generic spread adapter.
* Generic spread adapter.
...
@@ -110,7 +110,7 @@ class SpreadGeneric {
...
@@ -110,7 +110,7 @@ class SpreadGeneric {
static
SpreadGeneric
of
(
MethodType
targetType
,
int
spreadCount
)
{
static
SpreadGeneric
of
(
MethodType
targetType
,
int
spreadCount
)
{
if
(
targetType
!=
targetType
.
generic
())
if
(
targetType
!=
targetType
.
generic
())
throw
new
UnsupportedOperationException
(
"NYI type="
+
targetType
);
throw
new
UnsupportedOperationException
(
"NYI type="
+
targetType
);
MethodType
Impl
form
=
MethodTypeImpl
.
of
(
targetType
);
MethodType
Form
form
=
targetType
.
form
(
);
int
outcount
=
form
.
parameterCount
();
int
outcount
=
form
.
parameterCount
();
assert
(
spreadCount
<=
outcount
);
assert
(
spreadCount
<=
outcount
);
SpreadGeneric
[]
spreadGens
=
form
.
spreadGeneric
;
SpreadGeneric
[]
spreadGens
=
form
.
spreadGeneric
;
...
@@ -129,7 +129,7 @@ class SpreadGeneric {
...
@@ -129,7 +129,7 @@ class SpreadGeneric {
// This mini-api is called from an Adapter to manage the spread.
// This mini-api is called from an Adapter to manage the spread.
/** A check/coercion that happens once before any selections. */
/** A check/coercion that happens once before any selections. */
protected
Object
check
(
Object
av
,
int
n
)
{
protected
Object
check
(
Object
av
,
int
n
)
{
MethodHandleImpl
.
checkSpreadArgument
(
av
,
n
);
checkSpreadArgument
(
av
,
n
);
return
av
;
return
av
;
}
}
...
@@ -166,7 +166,7 @@ class SpreadGeneric {
...
@@ -166,7 +166,7 @@ class SpreadGeneric {
// see if it has the required invoke method
// see if it has the required invoke method
MethodHandle
entryPoint
=
null
;
MethodHandle
entryPoint
=
null
;
try
{
try
{
entryPoint
=
MethodHandleImpl
.
IMPL_LOOKUP
.
findSpecial
(
acls
,
iname
,
entryType
,
acls
);
entryPoint
=
IMPL_LOOKUP
.
findSpecial
(
acls
,
iname
,
entryType
,
acls
);
}
catch
(
ReflectiveOperationException
ex
)
{
}
catch
(
ReflectiveOperationException
ex
)
{
}
}
if
(
entryPoint
==
null
)
continue
;
if
(
entryPoint
==
null
)
continue
;
...
@@ -221,21 +221,21 @@ class SpreadGeneric {
...
@@ -221,21 +221,21 @@ class SpreadGeneric {
@Override
@Override
public
String
toString
()
{
public
String
toString
()
{
return
MethodHandleImpl
.
addTypeString
(
target
,
this
);
return
addTypeString
(
target
,
this
);
}
}
static
final
MethodHandle
NO_ENTRY
=
ValueConversions
.
identity
();
static
final
MethodHandle
NO_ENTRY
=
ValueConversions
.
identity
();
protected
boolean
isPrototype
()
{
return
target
==
null
;
}
protected
boolean
isPrototype
()
{
return
target
==
null
;
}
protected
Adapter
(
SpreadGeneric
outer
)
{
protected
Adapter
(
SpreadGeneric
outer
)
{
super
(
Access
.
TOKEN
,
NO_ENTRY
);
super
(
NO_ENTRY
);
this
.
outer
=
outer
;
this
.
outer
=
outer
;
this
.
target
=
null
;
this
.
target
=
null
;
assert
(
isPrototype
());
assert
(
isPrototype
());
}
}
protected
Adapter
(
SpreadGeneric
outer
,
MethodHandle
target
)
{
protected
Adapter
(
SpreadGeneric
outer
,
MethodHandle
target
)
{
super
(
Access
.
TOKEN
,
outer
.
entryPoint
);
super
(
outer
.
entryPoint
);
this
.
outer
=
outer
;
this
.
outer
=
outer
;
this
.
target
=
target
;
this
.
target
=
target
;
}
}
...
@@ -251,7 +251,7 @@ class SpreadGeneric {
...
@@ -251,7 +251,7 @@ class SpreadGeneric {
return
outer
.
select
(
av
,
n
);
return
outer
.
select
(
av
,
n
);
}
}
static
private
final
String
CLASS_PREFIX
;
// "
sun.dyn
.SpreadGeneric$"
static
private
final
String
CLASS_PREFIX
;
// "
java.lang.invoke
.SpreadGeneric$"
static
{
static
{
String
aname
=
Adapter
.
class
.
getName
();
String
aname
=
Adapter
.
class
.
getName
();
String
sname
=
Adapter
.
class
.
getSimpleName
();
String
sname
=
Adapter
.
class
.
getSimpleName
();
...
...
src/share/classes/java/
dyn
/SwitchPoint.java
→
src/share/classes/java/
lang/invoke
/SwitchPoint.java
浏览文件 @
33ee9ccf
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
* questions.
* questions.
*/
*/
package
java.
dyn
;
package
java.
lang.invoke
;
/**
/**
* <p>
* <p>
...
@@ -73,6 +73,10 @@ assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
...
@@ -73,6 +73,10 @@ assertEquals("hodmet", (String) worker.invokeExact("met", "hod"));
* Switch points are useful without subclassing. They may also be subclassed.
* Switch points are useful without subclassing. They may also be subclassed.
* This may be useful in order to associate application-specific invalidation logic
* This may be useful in order to associate application-specific invalidation logic
* with the switch point.
* with the switch point.
* Notice that there is no permanent association between a switch point and
* the method handles it produces and consumes.
* The garbage collector may collect method handles produced or consumed
* by a switch point independently of the lifetime of the switch point itself.
* <p style="font-size:smaller;">
* <p style="font-size:smaller;">
* <em>Implementation Note:</em>
* <em>Implementation Note:</em>
* A switch point behaves as if implemented on top of {@link MutableCallSite},
* A switch point behaves as if implemented on top of {@link MutableCallSite},
...
...
src/share/classes/
sun/dyn
/ToGeneric.java
→
src/share/classes/
java/lang/invoke
/ToGeneric.java
浏览文件 @
33ee9ccf
...
@@ -23,15 +23,14 @@
...
@@ -23,15 +23,14 @@
* questions.
* questions.
*/
*/
package
sun.dyn
;
package
java.lang.invoke
;
import
java.dyn.*
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.Constructor
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.InvocationTargetException
;
import
sun.
dyn
.util.ValueConversions
;
import
sun.
invoke
.util.ValueConversions
;
import
sun.
dyn
.util.Wrapper
;
import
sun.
invoke
.util.Wrapper
;
import
static
sun
.
dyn
.
MemberName
.
newIllegalArgumentException
;
import
static
java
.
lang
.
invoke
.
MethodHandleStatics
.*
;
import
static
sun
.
dyn
.
MethodTypeImpl
.
invokers
;
import
static
java
.
lang
.
invoke
.
MethodHandles
.
Lookup
.
IMPL_LOOKUP
;
/**
/**
* Adapters which mediate between incoming calls which are not generic
* Adapters which mediate between incoming calls which are not generic
...
@@ -73,7 +72,7 @@ class ToGeneric {
...
@@ -73,7 +72,7 @@ class ToGeneric {
assert
(
entryType
.
erase
()
==
entryType
);
// for now
assert
(
entryType
.
erase
()
==
entryType
);
// for now
// incoming call will first "forget" all reference types except Object
// incoming call will first "forget" all reference types except Object
this
.
entryType
=
entryType
;
this
.
entryType
=
entryType
;
MethodHandle
invoker0
=
invokers
(
entryType
.
generic
()
).
exactInvoker
();
MethodHandle
invoker0
=
entryType
.
generic
().
invokers
(
).
exactInvoker
();
MethodType
rawEntryTypeInit
;
MethodType
rawEntryTypeInit
;
Adapter
ad
=
findAdapter
(
rawEntryTypeInit
=
entryType
);
Adapter
ad
=
findAdapter
(
rawEntryTypeInit
=
entryType
);
if
(
ad
!=
null
)
{
if
(
ad
!=
null
)
{
...
@@ -89,15 +88,15 @@ class ToGeneric {
...
@@ -89,15 +88,15 @@ class ToGeneric {
}
}
// next, it will reorder primitives after references
// next, it will reorder primitives after references
MethodType
primsAtEnd
=
MethodTypeImpl
.
of
(
entryType
).
primsAtEnd
();
MethodType
primsAtEnd
=
entryType
.
form
(
).
primsAtEnd
();
// at the same time, it will "forget" all primitive types except int/long
// at the same time, it will "forget" all primitive types except int/long
this
.
primsAtEndOrder
=
MethodType
Impl
.
primsAtEndOrder
(
entryType
);
this
.
primsAtEndOrder
=
MethodType
Form
.
primsAtEndOrder
(
entryType
);
if
(
primsAtEndOrder
!=
null
)
{
if
(
primsAtEndOrder
!=
null
)
{
// reordering is required; build on top of a simpler ToGeneric
// reordering is required; build on top of a simpler ToGeneric
ToGeneric
va2
=
ToGeneric
.
of
(
primsAtEnd
);
ToGeneric
va2
=
ToGeneric
.
of
(
primsAtEnd
);
this
.
adapter
=
va2
.
adapter
;
this
.
adapter
=
va2
.
adapter
;
if
(
true
)
throw
new
UnsupportedOperationException
(
"NYI: primitive parameters must follow references; entryType = "
+
entryType
);
if
(
true
)
throw
new
UnsupportedOperationException
(
"NYI: primitive parameters must follow references; entryType = "
+
entryType
);
this
.
entryPoint
=
MethodHandleImpl
.
convertArguments
(
Access
.
TOKEN
,
this
.
entryPoint
=
MethodHandleImpl
.
convertArguments
(
va2
.
entryPoint
,
primsAtEnd
,
entryType
,
primsAtEndOrder
);
va2
.
entryPoint
,
primsAtEnd
,
entryType
,
primsAtEndOrder
);
// example: for entryType of (int,Object,Object), the reordered
// example: for entryType of (int,Object,Object), the reordered
// type is (Object,Object,int) and the order is {1,2,0},
// type is (Object,Object,int) and the order is {1,2,0},
...
@@ -107,7 +106,7 @@ class ToGeneric {
...
@@ -107,7 +106,7 @@ class ToGeneric {
// after any needed argument reordering, it will reinterpret
// after any needed argument reordering, it will reinterpret
// primitive arguments according to their "raw" types int/long
// primitive arguments according to their "raw" types int/long
MethodType
intsAtEnd
=
MethodTypeImpl
.
of
(
primsAtEnd
).
primsAsInts
();
MethodType
intsAtEnd
=
primsAtEnd
.
form
(
).
primsAsInts
();
ad
=
findAdapter
(
rawEntryTypeInit
=
intsAtEnd
);
ad
=
findAdapter
(
rawEntryTypeInit
=
intsAtEnd
);
MethodHandle
rawEntryPoint
;
MethodHandle
rawEntryPoint
;
if
(
ad
!=
null
)
{
if
(
ad
!=
null
)
{
...
@@ -116,7 +115,7 @@ class ToGeneric {
...
@@ -116,7 +115,7 @@ class ToGeneric {
// Perhaps the adapter is available only for longs.
// Perhaps the adapter is available only for longs.
// If so, we can use it, but there will have to be a little
// If so, we can use it, but there will have to be a little
// more stack motion on each call.
// more stack motion on each call.
MethodType
longsAtEnd
=
MethodTypeImpl
.
of
(
primsAtEnd
).
primsAsLongs
();
MethodType
longsAtEnd
=
primsAtEnd
.
form
(
).
primsAsLongs
();
ad
=
findAdapter
(
rawEntryTypeInit
=
longsAtEnd
);
ad
=
findAdapter
(
rawEntryTypeInit
=
longsAtEnd
);
if
(
ad
!=
null
)
{
if
(
ad
!=
null
)
{
MethodType
eptWithLongs
=
longsAtEnd
.
insertParameterTypes
(
0
,
ad
.
getClass
());
MethodType
eptWithLongs
=
longsAtEnd
.
insertParameterTypes
(
0
,
ad
.
getClass
());
...
@@ -128,7 +127,7 @@ class ToGeneric {
...
@@ -128,7 +127,7 @@ class ToGeneric {
assert
(
midType
.
parameterType
(
i
)
==
long
.
class
);
assert
(
midType
.
parameterType
(
i
)
==
long
.
class
);
assert
(
eptWithInts
.
parameterType
(
i
)
==
int
.
class
);
assert
(
eptWithInts
.
parameterType
(
i
)
==
int
.
class
);
MethodType
nextType
=
midType
.
changeParameterType
(
i
,
int
.
class
);
MethodType
nextType
=
midType
.
changeParameterType
(
i
,
int
.
class
);
rawEntryPoint
=
MethodHandle
.
convertArguments
(
Access
.
TOKEN
,
rawEntryPoint
=
MethodHandle
Impl
.
convertArguments
(
rawEntryPoint
,
nextType
,
midType
,
null
);
rawEntryPoint
,
nextType
,
midType
,
null
);
midType
=
nextType
;
midType
=
nextType
;
}
}
...
@@ -143,7 +142,7 @@ class ToGeneric {
...
@@ -143,7 +142,7 @@ class ToGeneric {
}
}
MethodType
tepType
=
entryType
.
insertParameterTypes
(
0
,
ad
.
getClass
());
MethodType
tepType
=
entryType
.
insertParameterTypes
(
0
,
ad
.
getClass
());
this
.
entryPoint
=
this
.
entryPoint
=
AdapterMethodHandle
.
makeRetypeRaw
(
Access
.
TOKEN
,
tepType
,
rawEntryPoint
);
AdapterMethodHandle
.
makeRetypeRaw
(
tepType
,
rawEntryPoint
);
if
(
this
.
entryPoint
==
null
)
if
(
this
.
entryPoint
==
null
)
throw
new
UnsupportedOperationException
(
"cannot retype to "
+
entryType
throw
new
UnsupportedOperationException
(
"cannot retype to "
+
entryType
+
" from "
+
rawEntryPoint
.
type
().
dropParameterTypes
(
0
,
1
));
+
" from "
+
rawEntryPoint
.
type
().
dropParameterTypes
(
0
,
1
));
...
@@ -168,7 +167,7 @@ class ToGeneric {
...
@@ -168,7 +167,7 @@ class ToGeneric {
assert
(
src
.
isPrimitive
()
&&
dst
.
isPrimitive
());
assert
(
src
.
isPrimitive
()
&&
dst
.
isPrimitive
());
if
(
filteredInvoker
==
null
)
{
if
(
filteredInvoker
==
null
)
{
filteredInvoker
=
filteredInvoker
=
AdapterMethodHandle
.
makeCheckCast
(
Access
.
TOKEN
,
AdapterMethodHandle
.
makeCheckCast
(
invoker
.
type
().
generic
(),
invoker
,
0
,
MethodHandle
.
class
);
invoker
.
type
().
generic
(),
invoker
,
0
,
MethodHandle
.
class
);
if
(
filteredInvoker
==
null
)
throw
new
UnsupportedOperationException
(
"NYI"
);
if
(
filteredInvoker
==
null
)
throw
new
UnsupportedOperationException
(
"NYI"
);
}
}
...
@@ -177,7 +176,7 @@ class ToGeneric {
...
@@ -177,7 +176,7 @@ class ToGeneric {
if
(
filteredInvoker
==
null
)
throw
new
InternalError
();
if
(
filteredInvoker
==
null
)
throw
new
InternalError
();
}
}
if
(
filteredInvoker
==
null
)
return
invoker
;
if
(
filteredInvoker
==
null
)
return
invoker
;
return
AdapterMethodHandle
.
makeRetypeOnly
(
Access
.
TOKEN
,
invoker
.
type
(),
filteredInvoker
);
return
AdapterMethodHandle
.
makeRetypeOnly
(
invoker
.
type
(),
filteredInvoker
);
}
}
/**
/**
...
@@ -227,7 +226,7 @@ class ToGeneric {
...
@@ -227,7 +226,7 @@ class ToGeneric {
// retype erased reference arguments (the cast makes it safe to do this)
// retype erased reference arguments (the cast makes it safe to do this)
MethodType
tepType
=
type
.
insertParameterTypes
(
0
,
adapter
.
getClass
());
MethodType
tepType
=
type
.
insertParameterTypes
(
0
,
adapter
.
getClass
());
MethodHandle
typedEntryPoint
=
MethodHandle
typedEntryPoint
=
AdapterMethodHandle
.
makeRetypeRaw
(
Access
.
TOKEN
,
tepType
,
entryPoint
);
AdapterMethodHandle
.
makeRetypeRaw
(
tepType
,
entryPoint
);
return
adapter
.
makeInstance
(
typedEntryPoint
,
invoker
,
convert
,
genericTarget
);
return
adapter
.
makeInstance
(
typedEntryPoint
,
invoker
,
convert
,
genericTarget
);
}
}
...
@@ -248,7 +247,7 @@ class ToGeneric {
...
@@ -248,7 +247,7 @@ class ToGeneric {
/** Return the adapter information for this type's erasure. */
/** Return the adapter information for this type's erasure. */
static
ToGeneric
of
(
MethodType
type
)
{
static
ToGeneric
of
(
MethodType
type
)
{
MethodType
Impl
form
=
MethodTypeImpl
.
of
(
type
);
MethodType
Form
form
=
type
.
form
(
);
ToGeneric
toGen
=
form
.
toGeneric
;
ToGeneric
toGen
=
form
.
toGeneric
;
if
(
toGen
==
null
)
if
(
toGen
==
null
)
form
.
toGeneric
=
toGen
=
new
ToGeneric
(
form
.
erasedType
());
form
.
toGeneric
=
toGen
=
new
ToGeneric
(
form
.
erasedType
());
...
@@ -262,7 +261,7 @@ class ToGeneric {
...
@@ -262,7 +261,7 @@ class ToGeneric {
/* Create an adapter for the given incoming call type. */
/* Create an adapter for the given incoming call type. */
static
Adapter
findAdapter
(
MethodType
entryPointType
)
{
static
Adapter
findAdapter
(
MethodType
entryPointType
)
{
MethodType
Impl
form
=
MethodTypeImpl
.
of
(
entryPointType
);
MethodType
Form
form
=
entryPointType
.
form
(
);
Class
<?>
rtype
=
entryPointType
.
returnType
();
Class
<?>
rtype
=
entryPointType
.
returnType
();
int
argc
=
form
.
parameterCount
();
int
argc
=
form
.
parameterCount
();
int
lac
=
form
.
longPrimitiveParameterCount
();
int
lac
=
form
.
longPrimitiveParameterCount
();
...
@@ -283,7 +282,7 @@ class ToGeneric {
...
@@ -283,7 +282,7 @@ class ToGeneric {
for
(
String
iname
:
inames
)
{
for
(
String
iname
:
inames
)
{
MethodHandle
entryPoint
=
null
;
MethodHandle
entryPoint
=
null
;
try
{
try
{
entryPoint
=
MethodHandleImpl
.
IMPL_LOOKUP
.
entryPoint
=
IMPL_LOOKUP
.
findSpecial
(
acls
,
iname
,
entryPointType
,
acls
);
findSpecial
(
acls
,
iname
,
entryPointType
,
acls
);
}
catch
(
ReflectiveOperationException
ex
)
{
}
catch
(
ReflectiveOperationException
ex
)
{
}
}
...
@@ -338,13 +337,13 @@ class ToGeneric {
...
@@ -338,13 +337,13 @@ class ToGeneric {
@Override
@Override
public
String
toString
()
{
public
String
toString
()
{
return
target
==
null
?
"prototype:"
+
convert
:
MethodHandleImpl
.
addTypeString
(
target
,
this
);
return
target
==
null
?
"prototype:"
+
convert
:
addTypeString
(
target
,
this
);
}
}
protected
boolean
isPrototype
()
{
return
target
==
null
;
}
protected
boolean
isPrototype
()
{
return
target
==
null
;
}
/* Prototype constructor. */
/* Prototype constructor. */
protected
Adapter
(
MethodHandle
entryPoint
)
{
protected
Adapter
(
MethodHandle
entryPoint
)
{
super
(
Access
.
TOKEN
,
entryPoint
);
super
(
entryPoint
);
this
.
invoker
=
null
;
this
.
invoker
=
null
;
this
.
convert
=
entryPoint
;
this
.
convert
=
entryPoint
;
this
.
target
=
null
;
this
.
target
=
null
;
...
@@ -356,7 +355,7 @@ class ToGeneric {
...
@@ -356,7 +355,7 @@ class ToGeneric {
}
}
protected
Adapter
(
MethodHandle
entryPoint
,
MethodHandle
invoker
,
MethodHandle
convert
,
MethodHandle
target
)
{
protected
Adapter
(
MethodHandle
entryPoint
,
MethodHandle
invoker
,
MethodHandle
convert
,
MethodHandle
target
)
{
super
(
Access
.
TOKEN
,
entryPoint
);
super
(
entryPoint
);
this
.
invoker
=
invoker
;
this
.
invoker
=
invoker
;
this
.
convert
=
convert
;
this
.
convert
=
convert
;
this
.
target
=
target
;
this
.
target
=
target
;
...
@@ -396,7 +395,7 @@ class ToGeneric {
...
@@ -396,7 +395,7 @@ class ToGeneric {
protected
float
return_F
(
Object
res
)
throws
Throwable
{
return
(
float
)
convert
.
invokeExact
(
res
);
}
protected
float
return_F
(
Object
res
)
throws
Throwable
{
return
(
float
)
convert
.
invokeExact
(
res
);
}
protected
double
return_D
(
Object
res
)
throws
Throwable
{
return
(
double
)
convert
.
invokeExact
(
res
);
}
protected
double
return_D
(
Object
res
)
throws
Throwable
{
return
(
double
)
convert
.
invokeExact
(
res
);
}
static
private
final
String
CLASS_PREFIX
;
// "
sun.dyn
.ToGeneric$"
static
private
final
String
CLASS_PREFIX
;
// "
java.lang.invoke
.ToGeneric$"
static
{
static
{
String
aname
=
Adapter
.
class
.
getName
();
String
aname
=
Adapter
.
class
.
getName
();
String
sname
=
Adapter
.
class
.
getSimpleName
();
String
sname
=
Adapter
.
class
.
getSimpleName
();
...
@@ -452,14 +451,15 @@ class genclasses {
...
@@ -452,14 +451,15 @@ class genclasses {
static String[] TCHARS = { "L", "I", "J", "F", "D", "A" };
static String[] TCHARS = { "L", "I", "J", "F", "D", "A" };
static String[][] TEMPLATES = { {
static String[][] TEMPLATES = { {
"@for@ arity=0..3 rcat<=4 nrefs<=99 nints<=99 nlongs<=99",
"@for@ arity=0..3 rcat<=4 nrefs<=99 nints<=99 nlongs<=99",
"@for@ arity=4..5 rcat<=2 nrefs<=99 nints<=99 nlongs<=99",
"@for@ arity=4..4 rcat<=4 nrefs<=99 nints<=99 nlongs<=99",
"@for@ arity=5..5 rcat<=2 nrefs<=99 nints<=99 nlongs<=99",
"@for@ arity=6..10 rcat<=2 nrefs<=99 nints=0 nlongs<=99",
"@for@ arity=6..10 rcat<=2 nrefs<=99 nints=0 nlongs<=99",
" //@each-cat@",
" //@each-cat@",
" static class @cat@ extends Adapter {",
" static class @cat@ extends Adapter {",
" protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype",
" protected @cat@(MethodHandle entryPoint) { super(entryPoint); } // to build prototype",
" protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }",
" protected @cat@(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { super(e, i, c, t); }",
" protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new @cat@(e, i, c, t); }",
" protected @cat@ makeInstance(MethodHandle e, MethodHandle i, MethodHandle c, MethodHandle t) { return new @cat@(e, i, c, t); }",
" protected Object target(@Ovav@) throws Throwable { return invoker.invokeExact(target
,
@av@); }",
" protected Object target(@Ovav@) throws Throwable { return invoker.invokeExact(target
@comma@
@av@); }",
" //@each-Tv@",
" //@each-Tv@",
" protected Object target@cat@(@Tvav@) throws Throwable { return target(@av@); }",
" protected Object target@cat@(@Tvav@) throws Throwable { return target(@av@); }",
" //@end-Tv@",
" //@end-Tv@",
...
@@ -471,7 +471,7 @@ class genclasses {
...
@@ -471,7 +471,7 @@ class genclasses {
" }",
" }",
} };
} };
enum VAR {
enum VAR {
cat, R, Rc, Tv, av, Tvav, Ovav;
cat, R, Rc, Tv, av,
comma,
Tvav, Ovav;
public final String pattern = "@"+toString().replace('_','.')+"@";
public final String pattern = "@"+toString().replace('_','.')+"@";
public String binding;
public String binding;
static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
static void makeBindings(boolean topLevel, int rcat, int nrefs, int nints, int nlongs) {
...
@@ -493,12 +493,13 @@ class genclasses {
...
@@ -493,12 +493,13 @@ class genclasses {
}
}
VAR.Tv.binding = comma(Tv);
VAR.Tv.binding = comma(Tv);
VAR.av.binding = comma(av);
VAR.av.binding = comma(av);
VAR.comma.binding = (av.length == 0 ? "" : ", ");
VAR.Tvav.binding = comma(Tvav);
VAR.Tvav.binding = comma(Tvav);
VAR.Ovav.binding = comma(Ovav);
VAR.Ovav.binding = comma(Ovav);
}
}
static String arg(int i) { return "a"+i; }
static String arg(int i) { return "a"+i; }
static String param(String t, String a) { return t+" "+a; }
static String param(String t, String a) { return t+" "+a; }
static String comma(String[] v) { return comma(
v, ""
); }
static String comma(String[] v) { return comma(
"", v
); }
static String comma(String sep, String[] v) {
static String comma(String sep, String[] v) {
if (v.length == 0) return "";
if (v.length == 0) return "";
String res = sep+v[0];
String res = sep+v[0];
...
@@ -735,7 +736,7 @@ class genclasses {
...
@@ -735,7 +736,7 @@ class genclasses {
protected
float
invoke_F
(
long
a0
,
long
a1
,
long
a2
)
throws
Throwable
{
return
return_F
(
targetA3
(
a0
,
a1
,
a2
));
}
protected
float
invoke_F
(
long
a0
,
long
a1
,
long
a2
)
throws
Throwable
{
return
return_F
(
targetA3
(
a0
,
a1
,
a2
));
}
protected
double
invoke_D
(
long
a0
,
long
a1
,
long
a2
)
throws
Throwable
{
return
return_D
(
targetA3
(
a0
,
a1
,
a2
));
}
protected
double
invoke_D
(
long
a0
,
long
a1
,
long
a2
)
throws
Throwable
{
return
return_D
(
targetA3
(
a0
,
a1
,
a2
));
}
}
}
//params=[4,
5, 2
, 99, 99, 99]
//params=[4,
4, 4
, 99, 99, 99]
static
class
A4
extends
Adapter
{
static
class
A4
extends
Adapter
{
protected
A4
(
MethodHandle
entryPoint
)
{
super
(
entryPoint
);
}
// to build prototype
protected
A4
(
MethodHandle
entryPoint
)
{
super
(
entryPoint
);
}
// to build prototype
protected
A4
(
MethodHandle
e
,
MethodHandle
i
,
MethodHandle
c
,
MethodHandle
t
)
{
super
(
e
,
i
,
c
,
t
);
}
protected
A4
(
MethodHandle
e
,
MethodHandle
i
,
MethodHandle
c
,
MethodHandle
t
)
{
super
(
e
,
i
,
c
,
t
);
}
...
@@ -753,31 +754,50 @@ class genclasses {
...
@@ -753,31 +754,50 @@ class genclasses {
protected
Object
invoke_L
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
float
invoke_F
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
)
throws
Throwable
{
return
return_F
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
double
invoke_D
(
Object
a0
,
Object
a1
,
Object
a2
,
Object
a3
)
throws
Throwable
{
return
return_D
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
Object
a1
,
Object
a2
,
int
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
Object
a1
,
Object
a2
,
int
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
Object
a1
,
Object
a2
,
int
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
Object
a1
,
Object
a2
,
int
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
Object
a1
,
Object
a2
,
int
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
Object
a1
,
Object
a2
,
int
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
float
invoke_F
(
Object
a0
,
Object
a1
,
Object
a2
,
int
a3
)
throws
Throwable
{
return
return_F
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
double
invoke_D
(
Object
a0
,
Object
a1
,
Object
a2
,
int
a3
)
throws
Throwable
{
return
return_D
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
Object
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
Object
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
Object
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
Object
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
Object
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
Object
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
float
invoke_F
(
Object
a0
,
Object
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_F
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
double
invoke_D
(
Object
a0
,
Object
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_D
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
float
invoke_F
(
Object
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_F
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
double
invoke_D
(
Object
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_D
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
int
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
int
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
int
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
int
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
int
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
int
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
float
invoke_F
(
int
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_F
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
double
invoke_D
(
int
a0
,
int
a1
,
int
a2
,
int
a3
)
throws
Throwable
{
return
return_D
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
Object
a1
,
Object
a2
,
long
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
Object
a1
,
Object
a2
,
long
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
Object
a1
,
Object
a2
,
long
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
Object
a1
,
Object
a2
,
long
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
Object
a1
,
Object
a2
,
long
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
Object
a1
,
Object
a2
,
long
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
float
invoke_F
(
Object
a0
,
Object
a1
,
Object
a2
,
long
a3
)
throws
Throwable
{
return
return_F
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
double
invoke_D
(
Object
a0
,
Object
a1
,
Object
a2
,
long
a3
)
throws
Throwable
{
return
return_D
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
Object
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
Object
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
Object
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
Object
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
Object
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
Object
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
float
invoke_F
(
Object
a0
,
Object
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_F
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
double
invoke_D
(
Object
a0
,
Object
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_D
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
Object
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
Object
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
Object
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
float
invoke_F
(
Object
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_F
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
double
invoke_D
(
Object
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_D
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
long
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
Object
invoke_L
(
long
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_L
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
long
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
int
invoke_I
(
long
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_I
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
long
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
long
invoke_J
(
long
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_J
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
float
invoke_F
(
long
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_F
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
protected
double
invoke_D
(
long
a0
,
long
a1
,
long
a2
,
long
a3
)
throws
Throwable
{
return
return_D
(
targetA4
(
a0
,
a1
,
a2
,
a3
));
}
}
}
//params=[5, 5, 2, 99, 99, 99]
static
class
A5
extends
Adapter
{
static
class
A5
extends
Adapter
{
protected
A5
(
MethodHandle
entryPoint
)
{
super
(
entryPoint
);
}
// to build prototype
protected
A5
(
MethodHandle
entryPoint
)
{
super
(
entryPoint
);
}
// to build prototype
protected
A5
(
MethodHandle
e
,
MethodHandle
i
,
MethodHandle
c
,
MethodHandle
t
)
{
super
(
e
,
i
,
c
,
t
);
}
protected
A5
(
MethodHandle
e
,
MethodHandle
i
,
MethodHandle
c
,
MethodHandle
t
)
{
super
(
e
,
i
,
c
,
t
);
}
...
...
src/share/classes/java/
dyn
/VolatileCallSite.java
→
src/share/classes/java/
lang/invoke
/VolatileCallSite.java
浏览文件 @
33ee9ccf
...
@@ -23,9 +23,7 @@
...
@@ -23,9 +23,7 @@
* questions.
* questions.
*/
*/
package
java.dyn
;
package
java.lang.invoke
;
import
java.util.List
;
/**
/**
* A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable.
* A {@code VolatileCallSite} is a {@link CallSite} whose target acts like a volatile variable.
...
...
src/share/classes/java/
dyn
/WrongMethodTypeException.java
→
src/share/classes/java/
lang/invoke
/WrongMethodTypeException.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
* questions.
* questions.
*/
*/
package
java.
dyn
;
package
java.
lang.invoke
;
/**
/**
* Thrown to indicate that code has attempted to call a method handle
* Thrown to indicate that code has attempted to call a method handle
...
...
src/share/classes/java/
dyn
/package-info.java
→
src/share/classes/java/
lang/invoke
/package-info.java
浏览文件 @
33ee9ccf
...
@@ -27,21 +27,18 @@
...
@@ -27,21 +27,18 @@
* The {@code java.lang.invoke} package contains dynamic language support provided directly by
* The {@code java.lang.invoke} package contains dynamic language support provided directly by
* the Java core class libraries and virtual machine.
* the Java core class libraries and virtual machine.
*
*
* <p style="font-size:smaller;">
* <em>Historic Note:</em> In some early versions of Java SE 7,
* the name of this package is {@code java.dyn}.
* <p>
* <p>
* Certain types in this package have special relations to dynamic
* Certain types in this package have special relations to dynamic
* language support in the virtual machine:
* language support in the virtual machine:
* <ul>
* <ul>
* <li>The class {@link java.
dyn
.MethodHandle MethodHandle} contains
* <li>The class {@link java.
lang.invoke
.MethodHandle MethodHandle} contains
* <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
* <a href="MethodHandle.html#sigpoly">signature polymorphic methods</a>
* which can be linked regardless of their type descriptor.
* which can be linked regardless of their type descriptor.
* Normally, method linkage requires exact matching of type descriptors.
* Normally, method linkage requires exact matching of type descriptors.
* </li>
* </li>
*
*
* <li>The JVM bytecode format supports immediate constants of
* <li>The JVM bytecode format supports immediate constants of
* the classes {@link java.
dyn.MethodHandle MethodHandle} and {@link java.dyn
.MethodType MethodType}.
* the classes {@link java.
lang.invoke.MethodHandle MethodHandle} and {@link java.lang.invoke
.MethodType MethodType}.
* </li>
* </li>
* </ul>
* </ul>
*
*
...
@@ -59,7 +56,7 @@
...
@@ -59,7 +56,7 @@
* with tag {@code CONSTANT_InvokeDynamic} (decimal 18). See below for its format.
* with tag {@code CONSTANT_InvokeDynamic} (decimal 18). See below for its format.
* The entry specifies the following information:
* The entry specifies the following information:
* <ul>
* <ul>
* <li>a bootstrap method (a {@link java.
dyn
.MethodHandle MethodHandle} constant)</li>
* <li>a bootstrap method (a {@link java.
lang.invoke
.MethodHandle MethodHandle} constant)</li>
* <li>the dynamic invocation name (a UTF8 string)</li>
* <li>the dynamic invocation name (a UTF8 string)</li>
* <li>the argument and return types of the call (encoded as a type descriptor in a UTF8 string)</li>
* <li>the argument and return types of the call (encoded as a type descriptor in a UTF8 string)</li>
* <li>optionally, a sequence of additional <em>static arguments</em> to the bootstrap method ({@code ldc}-type constants)</li>
* <li>optionally, a sequence of additional <em>static arguments</em> to the bootstrap method ({@code ldc}-type constants)</li>
...
@@ -75,11 +72,6 @@
...
@@ -75,11 +72,6 @@
* A dynamic call site is linked by means of a bootstrap method,
* A dynamic call site is linked by means of a bootstrap method,
* as <a href="#bsm">described below</a>.
* as <a href="#bsm">described below</a>.
*
*
* <p style="font-size:smaller;">
* <em>Historic Note:</em> Some older JVMs may allow the index of a {@code CONSTANT_NameAndType}
* instead of a {@code CONSTANT_InvokeDynamic}. In earlier, obsolete versions of this API, the
* bootstrap method was specified dynamically, in a per-class basis, during class initialization.
*
* <h3><a name="indycon"></a>constant pool entries for {@code invokedynamic} instructions</h3>
* <h3><a name="indycon"></a>constant pool entries for {@code invokedynamic} instructions</h3>
* If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 18),
* If a constant pool entry has the tag {@code CONSTANT_InvokeDynamic} (decimal 18),
* it must contain exactly four more bytes after the tag.
* it must contain exactly four more bytes after the tag.
...
@@ -95,20 +87,20 @@
...
@@ -95,20 +87,20 @@
* except that the bootstrap method specifier reference replaces
* except that the bootstrap method specifier reference replaces
* the {@code CONSTANT_Class} reference of a {@code CONSTANT_Methodref} entry.
* the {@code CONSTANT_Class} reference of a {@code CONSTANT_Methodref} entry.
*
*
* <h3><a name="mtcon"></a>constant pool entries for {@linkplain java.
dyn
.MethodType method types}</h3>
* <h3><a name="mtcon"></a>constant pool entries for {@linkplain java.
lang.invoke
.MethodType method types}</h3>
* If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
* If a constant pool entry has the tag {@code CONSTANT_MethodType} (decimal 16),
* it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
* it must contain exactly two more bytes, which must be an index to a {@code CONSTANT_Utf8}
* entry which represents a method type descriptor.
* entry which represents a method type descriptor.
* <p>
* <p>
* The JVM will ensure that on first
* The JVM will ensure that on first
* execution of an {@code ldc} instruction for this entry, a {@link java.
dyn
.MethodType MethodType}
* execution of an {@code ldc} instruction for this entry, a {@link java.
lang.invoke
.MethodType MethodType}
* will be created which represents the type descriptor.
* will be created which represents the type descriptor.
* Any classes mentioned in the {@code MethodType} will be loaded if necessary,
* Any classes mentioned in the {@code MethodType} will be loaded if necessary,
* but not initialized.
* but not initialized.
* Access checking and error reporting is performed exactly as it is for
* Access checking and error reporting is performed exactly as it is for
* references by {@code ldc} instructions to {@code CONSTANT_Class} constants.
* references by {@code ldc} instructions to {@code CONSTANT_Class} constants.
*
*
* <h3><a name="mhcon"></a>constant pool entries for {@linkplain java.
dyn
.MethodHandle method handles}</h3>
* <h3><a name="mhcon"></a>constant pool entries for {@linkplain java.
lang.invoke
.MethodHandle method handles}</h3>
* If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
* If a constant pool entry has the tag {@code CONSTANT_MethodHandle} (decimal 15),
* it must contain exactly three more bytes. The first byte after the tag is a subtag
* it must contain exactly three more bytes. The first byte after the tag is a subtag
* value which must be in the range 1 through 9, and the last two must be an index to a
* value which must be in the range 1 through 9, and the last two must be an index to a
...
@@ -119,7 +111,7 @@
...
@@ -119,7 +111,7 @@
* must agree according to the table below.
* must agree according to the table below.
* <p>
* <p>
* The JVM will ensure that on first execution of an {@code ldc} instruction
* The JVM will ensure that on first execution of an {@code ldc} instruction
* for this entry, a {@link java.
dyn
.MethodHandle MethodHandle} will be created which represents
* for this entry, a {@link java.
lang.invoke
.MethodHandle MethodHandle} will be created which represents
* the field or method reference, according to the specific mode implied by the subtag.
* the field or method reference, according to the specific mode implied by the subtag.
* <p>
* <p>
* As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
* As with {@code CONSTANT_Class} and {@code CONSTANT_MethodType} constants,
...
@@ -135,23 +127,23 @@
...
@@ -135,23 +127,23 @@
* <table border=1 cellpadding=5 summary="CONSTANT_MethodHandle subtypes">
* <table border=1 cellpadding=5 summary="CONSTANT_MethodHandle subtypes">
* <tr><th>N</th><th>subtag name</th><th>member</th><th>MH type</th><th>bytecode behavior</th><th>lookup expression</th></tr>
* <tr><th>N</th><th>subtag name</th><th>member</th><th>MH type</th><th>bytecode behavior</th><th>lookup expression</th></tr>
* <tr><td>1</td><td>REF_getField</td><td>C.f:T</td><td>(C)T</td><td>getfield C.f:T</td>
* <tr><td>1</td><td>REF_getField</td><td>C.f:T</td><td>(C)T</td><td>getfield C.f:T</td>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findGetter findGetter(C.class,"f",T.class)}</td></tr>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findGetter findGetter(C.class,"f",T.class)}</td></tr>
* <tr><td>2</td><td>REF_getStatic</td><td>C.f:T</td><td>( )T</td><td>getstatic C.f:T</td>
* <tr><td>2</td><td>REF_getStatic</td><td>C.f:T</td><td>( )T</td><td>getstatic C.f:T</td>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findStaticGetter findStaticGetter(C.class,"f",T.class)}</td></tr>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findStaticGetter findStaticGetter(C.class,"f",T.class)}</td></tr>
* <tr><td>3</td><td>REF_putField</td><td>C.f:T</td><td>(C,T)void</td><td>putfield C.f:T</td>
* <tr><td>3</td><td>REF_putField</td><td>C.f:T</td><td>(C,T)void</td><td>putfield C.f:T</td>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findSetter findSetter(C.class,"f",T.class)}</td></tr>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findSetter findSetter(C.class,"f",T.class)}</td></tr>
* <tr><td>4</td><td>REF_putStatic</td><td>C.f:T</td><td>(T)void</td><td>putstatic C.f:T</td>
* <tr><td>4</td><td>REF_putStatic</td><td>C.f:T</td><td>(T)void</td><td>putstatic C.f:T</td>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findStaticSetter findStaticSetter(C.class,"f",T.class)}</td></tr>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findStaticSetter findStaticSetter(C.class,"f",T.class)}</td></tr>
* <tr><td>5</td><td>REF_invokeVirtual</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokevirtual C.m(A*)T</td>
* <tr><td>5</td><td>REF_invokeVirtual</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokevirtual C.m(A*)T</td>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
* <tr><td>6</td><td>REF_invokeStatic</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokestatic C.m(A*)T</td>
* <tr><td>6</td><td>REF_invokeStatic</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokestatic C.m(A*)T</td>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findStatic findStatic(C.class,"m",MT)}</td></tr>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findStatic findStatic(C.class,"m",MT)}</td></tr>
* <tr><td>7</td><td>REF_invokeSpecial</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokespecial C.m(A*)T</td>
* <tr><td>7</td><td>REF_invokeSpecial</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokespecial C.m(A*)T</td>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findSpecial findSpecial(C.class,"m",MT,this.class)}</td></tr>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findSpecial findSpecial(C.class,"m",MT,this.class)}</td></tr>
* <tr><td>8</td><td>REF_newInvokeSpecial</td><td>C.<init>(A*)void</td><td>(A*)C</td><td>new C; dup; invokespecial C.<init>(A*)void</td>
* <tr><td>8</td><td>REF_newInvokeSpecial</td><td>C.<init>(A*)void</td><td>(A*)C</td><td>new C; dup; invokespecial C.<init>(A*)void</td>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findConstructor findConstructor(C.class,MT)}</td></tr>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findConstructor findConstructor(C.class,MT)}</td></tr>
* <tr><td>9</td><td>REF_invokeInterface</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokeinterface C.m(A*)T</td>
* <tr><td>9</td><td>REF_invokeInterface</td><td>C.m(A*)T</td><td>(C,A*)T</td><td>invokeinterface C.m(A*)T</td>
* <td>{@linkplain java.
dyn
.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
* <td>{@linkplain java.
lang.invoke
.MethodHandles.Lookup#findVirtual findVirtual(C.class,"m",MT)}</td></tr>
* </table>
* </table>
* </code>
* </code>
* Here, the type {@code C} is taken from the {@code CONSTANT_Class} reference associated
* Here, the type {@code C} is taken from the {@code CONSTANT_Class} reference associated
...
@@ -169,7 +161,7 @@
...
@@ -169,7 +161,7 @@
* and returns the same result (if any) as the corresponding <em>bytecode behavior</em>.
* and returns the same result (if any) as the corresponding <em>bytecode behavior</em>.
* <p>
* <p>
* Each method handle constant also has an equivalent reflective <em>lookup expression</em>,
* Each method handle constant also has an equivalent reflective <em>lookup expression</em>,
* which is a query to a method in {@link java.
dyn
.MethodHandles.Lookup}.
* which is a query to a method in {@link java.
lang.invoke
.MethodHandles.Lookup}.
* In the example lookup method expression given in the table above, the name {@code MT}
* In the example lookup method expression given in the table above, the name {@code MT}
* stands for a {@code MethodType} built from {@code T} and the sequence of argument types {@code A*}.
* stands for a {@code MethodType} built from {@code T} and the sequence of argument types {@code A*}.
* (Note that the type {@code C} is not prepended to the query type {@code MT} even if the member is non-static.)
* (Note that the type {@code C} is not prepended to the query type {@code MT} even if the member is non-static.)
...
@@ -191,7 +183,7 @@
...
@@ -191,7 +183,7 @@
* A constant may refer to a method or constructor with the {@code varargs}
* A constant may refer to a method or constructor with the {@code varargs}
* bit (hexadecimal {@code 0x0080}) set in its modifier bitmask.
* bit (hexadecimal {@code 0x0080}) set in its modifier bitmask.
* The method handle constant produced for such a method behaves as if
* The method handle constant produced for such a method behaves as if
* it were created by {@link java.
dyn
.MethodHandle#asVarargsCollector asVarargsCollector}.
* it were created by {@link java.
lang.invoke
.MethodHandle#asVarargsCollector asVarargsCollector}.
* In other words, the constant method handle will exhibit variable arity,
* In other words, the constant method handle will exhibit variable arity,
* when invoked via {@code invokeGeneric}.
* when invoked via {@code invokeGeneric}.
* On the other hand, its behavior with respect to {@code invokeExact} will be the same
* On the other hand, its behavior with respect to {@code invokeExact} will be the same
...
@@ -225,7 +217,7 @@
...
@@ -225,7 +217,7 @@
* the call site must first be <em>linked</em>.
* the call site must first be <em>linked</em>.
* Linking is accomplished by calling a <em>bootstrap method</em>
* Linking is accomplished by calling a <em>bootstrap method</em>
* which is given the static information content of the call site,
* which is given the static information content of the call site,
* and which must produce a {@link java.
dyn
.MethodHandle method handle}
* and which must produce a {@link java.
lang.invoke
.MethodHandle method handle}
* that gives the behavior of the call site.
* that gives the behavior of the call site.
* <p>
* <p>
* Each {@code invokedynamic} instruction statically specifies its own
* Each {@code invokedynamic} instruction statically specifies its own
...
@@ -234,7 +226,7 @@
...
@@ -234,7 +226,7 @@
* just like {@code invokevirtual} and the other invoke instructions.
* just like {@code invokevirtual} and the other invoke instructions.
* <p>
* <p>
* Linking starts with resolving the constant pool entry for the
* Linking starts with resolving the constant pool entry for the
* bootstrap method, and resolving a {@link java.
dyn
.MethodType MethodType} object for
* bootstrap method, and resolving a {@link java.
lang.invoke
.MethodType MethodType} object for
* the type descriptor of the dynamic call site.
* the type descriptor of the dynamic call site.
* This resolution process may trigger class loading.
* This resolution process may trigger class loading.
* It may therefore throw an error if a class fails to load.
* It may therefore throw an error if a class fails to load.
...
@@ -251,8 +243,8 @@
...
@@ -251,8 +243,8 @@
* <li>optionally, one or more <a href="#args">additional static arguments</a> </li>
* <li>optionally, one or more <a href="#args">additional static arguments</a> </li>
* </ul>
* </ul>
* The method handle is then applied to the other values as if by
* The method handle is then applied to the other values as if by
* {@link java.
dyn
.MethodHandle#invokeGeneric invokeGeneric}.
* {@link java.
lang.invoke
.MethodHandle#invokeGeneric invokeGeneric}.
* The returned result must be a {@link java.
dyn
.CallSite CallSite} (or a subclass).
* The returned result must be a {@link java.
lang.invoke
.CallSite CallSite} (or a subclass).
* The type of the call site's target must be exactly equal to the type
* The type of the call site's target must be exactly equal to the type
* derived from the dynamic call site's type descriptor and passed to
* derived from the dynamic call site's type descriptor and passed to
* the bootstrap method.
* the bootstrap method.
...
@@ -263,18 +255,12 @@
...
@@ -263,18 +255,12 @@
* For example, the first argument could be {@code Object}
* For example, the first argument could be {@code Object}
* instead of {@code MethodHandles.Lookup}, and the return type
* instead of {@code MethodHandles.Lookup}, and the return type
* could also be {@code Object} instead of {@code CallSite}.
* could also be {@code Object} instead of {@code CallSite}.
* <p>
* (Note that the types and number of the stacked arguments limit
* As with any method handle constant, a {@code varargs} modifier bit
* the legal kinds of bootstrap methods to appropriately typed
* on the bootstrap method is ignored.
* static methods and constructors of {@code CallSite} subclasses.)
* <p>
* Note that the first argument of the bootstrap method cannot be
* a simple {@code Class} reference. (This is a change from earlier
* versions of this specification. If the caller class is needed,
* it is easy to {@linkplain java.dyn.MethodHandles.Lookup#lookupClass() extract it}
* from the {@code Lookup} object.)
* <p>
* <p>
* After resolution, the linkage process may fail in a variety of ways.
* After resolution, the linkage process may fail in a variety of ways.
* All failures are reported by a
n {@link java.dyn.InvokeDynamicBootstrapError InvokeDynamicBootstrap
Error},
* All failures are reported by a
{@link java.lang.BootstrapMethodError BootstrapMethod
Error},
* which is thrown as the abnormal termination of the dynamic call
* which is thrown as the abnormal termination of the dynamic call
* site execution.
* site execution.
* The following circumstances will cause this:
* The following circumstances will cause this:
...
@@ -290,7 +276,7 @@
...
@@ -290,7 +276,7 @@
* <li>the bootstrap method has a wrong argument or return type </li>
* <li>the bootstrap method has a wrong argument or return type </li>
* <li>the bootstrap method invocation completes abnormally </li>
* <li>the bootstrap method invocation completes abnormally </li>
* <li>the result from the bootstrap invocation is not a reference to
* <li>the result from the bootstrap invocation is not a reference to
* an object of type {@link java.
dyn
.CallSite CallSite} </li>
* an object of type {@link java.
lang.invoke
.CallSite CallSite} </li>
* <li>the target of the {@code CallSite} does not have a target of
* <li>the target of the {@code CallSite} does not have a target of
* the expected {@code MethodType} </li>
* the expected {@code MethodType} </li>
* </ul>
* </ul>
...
@@ -309,7 +295,7 @@
...
@@ -309,7 +295,7 @@
* <p>
* <p>
* In an application which requires dynamic call sites with individually
* In an application which requires dynamic call sites with individually
* mutable behaviors, their bootstrap methods should produce distinct
* mutable behaviors, their bootstrap methods should produce distinct
* {@link java.
dyn
.CallSite CallSite} objects, one for each linkage request.
* {@link java.
lang.invoke
.CallSite CallSite} objects, one for each linkage request.
* Alternatively, an application can link a single {@code CallSite} object
* Alternatively, an application can link a single {@code CallSite} object
* to several {@code invokedynamic} instructions, in which case
* to several {@code invokedynamic} instructions, in which case
* a change to the target method will become visible at each of
* a change to the target method will become visible at each of
...
@@ -322,11 +308,12 @@
...
@@ -322,11 +308,12 @@
* chosen target object.
* chosen target object.
*
*
* <p style="font-size:smaller;">
* <p style="font-size:smaller;">
* <em>
Historic Note:</em> Unlike some previous versions of this specification,
* <em>
Discussion:</em>
*
t
hese rules do not enable the JVM to duplicate dynamic call sites,
*
T
hese rules do not enable the JVM to duplicate dynamic call sites,
* or to issue “causeless” bootstrap method calls.
* or to issue “causeless” bootstrap method calls.
* Every dynamic call site transitions at most once from unlinked to linked,
* Every dynamic call site transitions at most once from unlinked to linked,
* just before its first invocation.
* just before its first invocation.
* There is no way to undo the effect of a completed bootstrap method call.
*
*
* <h3><a name="bsmattr">the {@code BootstrapMethods} attribute </h3>
* <h3><a name="bsmattr">the {@code BootstrapMethods} attribute </h3>
* Each {@code CONSTANT_InvokeDynamic} entry contains an index which references
* Each {@code CONSTANT_InvokeDynamic} entry contains an index which references
...
@@ -354,7 +341,7 @@
...
@@ -354,7 +341,7 @@
* <h3><a name="args">static arguments to the bootstrap method</h3>
* <h3><a name="args">static arguments to the bootstrap method</h3>
* An {@code invokedynamic} instruction specifies at least three arguments
* An {@code invokedynamic} instruction specifies at least three arguments
* to pass to its bootstrap method:
* to pass to its bootstrap method:
* The caller class (expressed as a {@link java.
dyn
.MethodHandles.Lookup Lookup object},
* The caller class (expressed as a {@link java.
lang.invoke
.MethodHandles.Lookup Lookup object},
* the name (extracted from the {@code CONSTANT_NameAndType} entry),
* the name (extracted from the {@code CONSTANT_NameAndType} entry),
* and the type (also extracted from the {@code CONSTANT_NameAndType} entry).
* and the type (also extracted from the {@code CONSTANT_NameAndType} entry).
* The {@code invokedynamic} instruction may specify additional metadata values
* The {@code invokedynamic} instruction may specify additional metadata values
...
@@ -382,8 +369,8 @@
...
@@ -382,8 +369,8 @@
* <tr><td>CONSTANT_Long</td><td><code>java.lang.Long</code></td><td>the indexed long value</td></tr>
* <tr><td>CONSTANT_Long</td><td><code>java.lang.Long</code></td><td>the indexed long value</td></tr>
* <tr><td>CONSTANT_Float</td><td><code>java.lang.Float</code></td><td>the indexed float value</td></tr>
* <tr><td>CONSTANT_Float</td><td><code>java.lang.Float</code></td><td>the indexed float value</td></tr>
* <tr><td>CONSTANT_Double</td><td><code>java.lang.Double</code></td><td>the indexed double value</td></tr>
* <tr><td>CONSTANT_Double</td><td><code>java.lang.Double</code></td><td>the indexed double value</td></tr>
* <tr><td>CONSTANT_MethodHandle</td><td><code>java.
dyn
.MethodHandle</code></td><td>the indexed method handle constant</td></tr>
* <tr><td>CONSTANT_MethodHandle</td><td><code>java.
lang.invoke
.MethodHandle</code></td><td>the indexed method handle constant</td></tr>
* <tr><td>CONSTANT_MethodType</td><td><code>java.
dyn
.MethodType</code></td><td>the indexed method type constant</td></tr>
* <tr><td>CONSTANT_MethodType</td><td><code>java.
lang.invoke
.MethodType</code></td><td>the indexed method type constant</td></tr>
* </table>
* </table>
* </code>
* </code>
* <p>
* <p>
...
@@ -403,7 +390,7 @@
...
@@ -403,7 +390,7 @@
* then some or all of the arguments specified here may be collected into a trailing array parameter.
* then some or all of the arguments specified here may be collected into a trailing array parameter.
* (This is not a special rule, but rather a useful consequence of the interaction
* (This is not a special rule, but rather a useful consequence of the interaction
* between {@code CONSTANT_MethodHandle} constants, the modifier bit for variable arity methods,
* between {@code CONSTANT_MethodHandle} constants, the modifier bit for variable arity methods,
* and the {@code java.
dyn
.MethodHandle#asVarargsCollector asVarargsCollector} transformation.)
* and the {@code java.
lang.invoke
.MethodHandle#asVarargsCollector asVarargsCollector} transformation.)
* <p>
* <p>
* Given these rules, here are examples of legal bootstrap method declarations,
* Given these rules, here are examples of legal bootstrap method declarations,
* given various numbers {@code N} of extra arguments.
* given various numbers {@code N} of extra arguments.
...
@@ -436,7 +423,7 @@
...
@@ -436,7 +423,7 @@
* constant as an {@code Object}, but the type matching machinery of {@code invokeGeneric}
* constant as an {@code Object}, but the type matching machinery of {@code invokeGeneric}
* will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
* will cast the reference back to {@code MethodHandle} before invoking the bootstrap method.
* (If a string constant were passed instead, by badly generated code, that cast would then fail,
* (If a string constant were passed instead, by badly generated code, that cast would then fail,
* resulting in a
n {@code InvokeDynamicBootstrap
Error}.)
* resulting in a
{@code BootstrapMethod
Error}.)
* <p>
* <p>
* Extra bootstrap method arguments are intended to allow language implementors
* Extra bootstrap method arguments are intended to allow language implementors
* to safely and compactly encode metadata.
* to safely and compactly encode metadata.
...
@@ -473,6 +460,7 @@ struct BootstrapMethods_attr {
...
@@ -473,6 +460,7 @@ struct BootstrapMethods_attr {
* </pre></blockquote>
* </pre></blockquote>
*
*
* @author John Rose, JSR 292 EG
* @author John Rose, JSR 292 EG
* @since 1.7
*/
*/
package
java.
dyn
;
package
java.
lang.invoke
;
src/share/classes/sun/dyn/Access.java
已删除
100644 → 0
浏览文件 @
a43c1c0e
/*
* 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
sun.reflect.Reflection
;
/**
* Access control to this package.
* Classes in other packages can attempt to acquire the access token,
* but will fail if they are not recognized as friends.
* Certain methods in this package, although public, require a non-null
* access token in order to proceed; they act like package-private methods.
* @author jrose
*/
public
class
Access
{
private
Access
()
{
}
/**
* The heart of this pattern: The list of classes which are
* permitted to acquire the access token, and become honorary
* members of this package.
*/
private
static
final
String
[]
FRIENDS
=
{
"java.dyn."
,
"sun.dyn."
};
/**
* The following object is NOT public. That's the point of the pattern.
* It is package-private, so that any member of this package
* can acquire the access token, and give it away to trusted friends.
*/
static
final
Access
TOKEN
=
new
Access
();
/**
* @return Access.TOKEN, if the caller is a friend of this package
*/
public
static
Access
getToken
()
{
Class
<?>
callc
=
Reflection
.
getCallerClass
(
2
);
if
(
isFriend
(
callc
))
return
TOKEN
;
else
throw
new
IllegalAccessError
(
"bad caller: "
+
callc
);
}
/** Is the given name the name of a class which could be our friend? */
public
static
boolean
isFriendName
(
String
name
)
{
for
(
String
friend
:
FRIENDS
)
{
if
(
name
.
startsWith
(
friend
))
return
true
;
}
return
false
;
}
/** Is the given class a friend? True if {@link #isFriendName},
* and the given class also shares a class loader with us.
*/
public
static
boolean
isFriend
(
Class
<?>
c
)
{
return
isFriendName
(
c
.
getName
())
&&
c
.
getClassLoader
()
==
CLASS_LOADER
;
}
private
static
final
ClassLoader
CLASS_LOADER
=
Access
.
class
.
getClassLoader
();
/**
* Throw an IllegalAccessError if the caller does not possess
* the Access.TOKEN.
* @param must be Access.TOKEN
*/
public
static
void
check
(
Access
token
)
{
if
(
token
==
null
)
fail
();
// else it must be the unique Access.TOKEN
assert
(
token
==
Access
.
TOKEN
);
}
private
static
void
fail
()
{
final
int
CALLER_DEPTH
=
3
;
// 0: Reflection.getCC, 1: this.fail, 2: Access.*, 3: caller
Class
<?>
callc
=
Reflection
.
getCallerClass
(
CALLER_DEPTH
);
throw
new
IllegalAccessError
(
"bad caller: "
+
callc
);
}
static
{
//sun.reflect.Reflection.registerMethodsToFilter(MH.class, "getToken");
}
}
src/share/classes/sun/dyn/CallSiteImpl.java
已删除
100644 → 0
浏览文件 @
a43c1c0e
/*
* 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
sun.dyn
;
import
java.dyn.*
;
import
static
sun
.
dyn
.
MemberName
.
uncaughtException
;
/**
* Parts of CallSite known to the JVM.
* @author jrose
*/
public
class
CallSiteImpl
{
// this implements the upcall from the JVM, MethodHandleNatives.makeDynamicCallSite:
static
CallSite
makeSite
(
MethodHandle
bootstrapMethod
,
// Callee information:
String
name
,
MethodType
type
,
// Extra arguments for BSM, if any:
Object
info
,
// Caller information:
MemberName
callerMethod
,
int
callerBCI
)
{
Class
<?>
callerClass
=
callerMethod
.
getDeclaringClass
();
Object
caller
;
if
(
bootstrapMethod
.
type
().
parameterType
(
0
)
==
Class
.
class
&&
TRANSITIONAL_BEFORE_PFD
)
caller
=
callerClass
;
// remove for PFD
else
caller
=
MethodHandleImpl
.
IMPL_LOOKUP
.
in
(
callerClass
);
if
(
bootstrapMethod
==
null
&&
TRANSITIONAL_BEFORE_PFD
)
{
// 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 "
+
callerClass
.
getName
()+
" has not declared a bootstrap method for invokedynamic"
);
}
CallSite
site
;
try
{
Object
binding
;
info
=
maybeReBox
(
info
);
if
(
info
==
null
)
{
binding
=
bootstrapMethod
.
invokeGeneric
(
caller
,
name
,
type
);
}
else
if
(!
info
.
getClass
().
isArray
())
{
binding
=
bootstrapMethod
.
invokeGeneric
(
caller
,
name
,
type
,
info
);
}
else
{
Object
[]
argv
=
(
Object
[])
info
;
if
(
3
+
argv
.
length
>
255
)
new
InvokeDynamicBootstrapError
(
"too many bootstrap method arguments"
);
MethodType
bsmType
=
bootstrapMethod
.
type
();
if
(
bsmType
.
parameterCount
()
==
4
&&
bsmType
.
parameterType
(
3
)
==
Object
[].
class
)
binding
=
bootstrapMethod
.
invokeGeneric
(
caller
,
name
,
type
,
argv
);
else
binding
=
MethodHandles
.
spreadInvoker
(
bsmType
,
3
)
.
invokeGeneric
(
bootstrapMethod
,
caller
,
name
,
type
,
argv
);
}
//System.out.println("BSM for "+name+type+" => "+binding);
if
(
binding
instanceof
CallSite
)
{
site
=
(
CallSite
)
binding
;
}
else
if
(
binding
instanceof
MethodHandle
&&
TRANSITIONAL_BEFORE_PFD
)
{
// Transitional!
MethodHandle
target
=
(
MethodHandle
)
binding
;
site
=
new
ConstantCallSite
(
target
);
}
else
{
throw
new
ClassCastException
(
"bootstrap method failed to produce a CallSite"
);
}
if
(
TRANSITIONAL_BEFORE_PFD
)
PRIVATE_INITIALIZE_CALL_SITE
.
invokeExact
(
site
,
name
,
type
,
callerMethod
,
callerBCI
);
assert
(
site
.
getTarget
()
!=
null
);
assert
(
site
.
getTarget
().
type
().
equals
(
type
));
}
catch
(
Throwable
ex
)
{
InvokeDynamicBootstrapError
bex
;
if
(
ex
instanceof
InvokeDynamicBootstrapError
)
bex
=
(
InvokeDynamicBootstrapError
)
ex
;
else
bex
=
new
InvokeDynamicBootstrapError
(
"call site initialization exception"
,
ex
);
throw
bex
;
}
return
site
;
}
private
static
boolean
TRANSITIONAL_BEFORE_PFD
=
true
;
// FIXME: remove for PFD
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
;
static
{
try
{
PRIVATE_INITIALIZE_CALL_SITE
=
!
TRANSITIONAL_BEFORE_PFD
?
null
:
MethodHandleImpl
.
IMPL_LOOKUP
.
findVirtual
(
CallSite
.
class
,
"initializeFromJVM"
,
MethodType
.
methodType
(
void
.
class
,
String
.
class
,
MethodType
.
class
,
MemberName
.
class
,
int
.
class
));
}
catch
(
ReflectiveOperationException
ex
)
{
throw
uncaughtException
(
ex
);
}
}
public
static
void
setCallSiteTarget
(
Access
token
,
CallSite
site
,
MethodHandle
target
)
{
Access
.
check
(
token
);
MethodHandleNatives
.
setCallSiteTarget
(
site
,
target
);
}
}
src/share/classes/sun/
dyn
/WrapperInstance.java
→
src/share/classes/sun/
invoke
/WrapperInstance.java
浏览文件 @
33ee9ccf
...
@@ -23,14 +23,14 @@
...
@@ -23,14 +23,14 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
;
package
sun.
invoke
;
import
java.
dyn
.MethodHandle
;
import
java.
lang.invoke
.MethodHandle
;
/**
/**
* Private API used inside of java.
dyn
.MethodHandles.
* Private API used inside of java.
lang.invoke
.MethodHandles.
* Interface implemented by every object which is produced by
* Interface implemented by every object which is produced by
* {@link java.
dyn
.MethodHandles#asInstance MethodHandles.asInstance}.
* {@link java.
lang.invoke
.MethodHandles#asInstance MethodHandles.asInstance}.
* The methods of this interface allow a caller to recover the parameters
* The methods of this interface allow a caller to recover the parameters
* to {@code asInstance}.
* to {@code asInstance}.
* This allows applications to repeatedly convert between method handles
* This allows applications to repeatedly convert between method handles
...
...
src/share/classes/sun/
dyn
/anon/AnonymousClassLoader.java
→
src/share/classes/sun/
invoke
/anon/AnonymousClassLoader.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 20
09
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 20
11
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
.anon
;
package
sun.
invoke
.anon
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.InvocationTargetException
;
...
...
src/share/classes/sun/
dyn
/anon/ConstantPoolParser.java
→
src/share/classes/sun/
invoke
/anon/ConstantPoolParser.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 20
09
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 20
11
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,14 +23,14 @@
...
@@ -23,14 +23,14 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
.anon
;
package
sun.
invoke
.anon
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.io.OutputStream
;
import
java.nio.BufferUnderflowException
;
import
java.nio.BufferUnderflowException
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteBuffer
;
import
static
sun
.
dyn
.
anon
.
ConstantPoolVisitor
.*;
import
static
sun
.
invoke
.
anon
.
ConstantPoolVisitor
.*;
/** A constant pool parser.
/** A constant pool parser.
*/
*/
...
...
src/share/classes/sun/
dyn
/anon/ConstantPoolPatch.java
→
src/share/classes/sun/
invoke
/anon/ConstantPoolPatch.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 20
09
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 20
11
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
.anon
;
package
sun.
invoke
.anon
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.io.OutputStream
;
...
@@ -32,7 +32,7 @@ import java.util.HashSet;
...
@@ -32,7 +32,7 @@ import java.util.HashSet;
import
java.util.IdentityHashMap
;
import
java.util.IdentityHashMap
;
import
java.util.Map
;
import
java.util.Map
;
import
static
sun
.
dyn
.
anon
.
ConstantPoolVisitor
.*;
import
static
sun
.
invoke
.
anon
.
ConstantPoolVisitor
.*;
/** A class and its patched constant pool.
/** A class and its patched constant pool.
*
*
...
...
src/share/classes/sun/
dyn
/anon/ConstantPoolVisitor.java
→
src/share/classes/sun/
invoke
/anon/ConstantPoolVisitor.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 20
09
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 20
11
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
.anon
;
package
sun.
invoke
.anon
;
/**
/**
* A visitor called by {@link ConstantPoolParser#parse(ConstantPoolVisitor)}
* A visitor called by {@link ConstantPoolParser#parse(ConstantPoolVisitor)}
...
...
src/share/classes/sun/
dyn
/anon/InvalidConstantPoolFormatException.java
→
src/share/classes/sun/
invoke
/anon/InvalidConstantPoolFormatException.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 20
09
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 20
11
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
.anon
;
package
sun.
invoke
.anon
;
/** Exception used when there is an error in the constant pool
/** Exception used when there is an error in the constant pool
* format.
* format.
...
...
src/share/classes/sun/
dyn
/empty/Empty.java
→
src/share/classes/sun/
invoke
/empty/Empty.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2009, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,14 +23,14 @@
...
@@ -23,14 +23,14 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
.empty
;
package
sun.
invoke
.empty
;
/**
/**
* An empty class in an empty package.
* An empty class in an empty package.
* Used as a proxy for unprivileged code, since making access checks
* Used as a proxy for unprivileged code, since making access checks
* against it will only succeed against public methods in public types.
* against it will only succeed against public methods in public types.
* <p>
* <p>
* This class also stands (internally to sun.
dyn
) for the type of a
* This class also stands (internally to sun.
invoke
) for the type of a
* value that cannot be produced, because the expression of this type
* value that cannot be produced, because the expression of this type
* always returns abnormally. (Cf. Nothing in the closures proposal.)
* always returns abnormally. (Cf. Nothing in the closures proposal.)
* @author jrose
* @author jrose
...
...
src/share/classes/sun/
dyn
/package-info.java
→
src/share/classes/sun/
invoke
/package-info.java
浏览文件 @
33ee9ccf
...
@@ -24,8 +24,8 @@
...
@@ -24,8 +24,8 @@
*/
*/
/**
/**
* Implementation details for JSR 292 RI, package java.
dyn
.
* Implementation details for JSR 292 RI, package java.
lang.invoke
.
* @author jrose
* @author jrose
*/
*/
package
sun.
dyn
;
package
sun.
invoke
;
src/share/classes/sun/
dyn
/util/BytecodeDescriptor.java
→
src/share/classes/sun/
invoke
/util/BytecodeDescriptor.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,9 +23,9 @@
...
@@ -23,9 +23,9 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
.util
;
package
sun.
invoke
.util
;
import
java.
dyn
.MethodType
;
import
java.
lang.invoke
.MethodType
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.List
;
import
java.util.List
;
...
...
src/share/classes/sun/
dyn
/util/BytecodeName.java
→
src/share/classes/sun/
invoke
/util/BytecodeName.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2007, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
.util
;
package
sun.
invoke
.util
;
/**
/**
* Utility routines for dealing with bytecode-level names.
* Utility routines for dealing with bytecode-level names.
...
...
src/share/classes/sun/
dyn
/util/ValueConversions.java
→
src/share/classes/sun/
invoke
/util/ValueConversions.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,22 +23,19 @@
...
@@ -23,22 +23,19 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
.util
;
package
sun.
invoke
.util
;
import
java.dyn.*
;
import
java.lang.invoke.MethodHandle
;
import
java.dyn.MethodHandles.Lookup
;
import
java.lang.invoke.MethodHandles
;
import
java.lang.invoke.MethodHandles.Lookup
;
import
java.lang.invoke.MethodType
;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.EnumMap
;
import
java.util.EnumMap
;
import
java.util.List
;
import
java.util.List
;
import
sun.dyn.Access
;
import
sun.dyn.AdapterMethodHandle
;
import
sun.dyn.MethodHandleImpl
;
import
static
sun
.
dyn
.
MemberName
.
uncaughtException
;
public
class
ValueConversions
{
public
class
ValueConversions
{
private
static
final
Access
IMPL_TOKEN
=
Access
.
getToken
();
private
static
final
Lookup
IMPL_LOOKUP
=
MethodHandles
.
lookup
();
private
static
final
Lookup
IMPL_LOOKUP
=
MethodHandleImpl
.
getLookup
(
IMPL_TOKEN
);
private
static
EnumMap
<
Wrapper
,
MethodHandle
>[]
newWrapperCaches
(
int
n
)
{
private
static
EnumMap
<
Wrapper
,
MethodHandle
>[]
newWrapperCaches
(
int
n
)
{
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
...
@@ -157,7 +154,7 @@ public class ValueConversions {
...
@@ -157,7 +154,7 @@ public class ValueConversions {
mh
=
null
;
mh
=
null
;
}
}
}
else
{
}
else
{
mh
=
retype
(
type
,
unbox
(
wrap
,
!
exact
,
raw
)
);
mh
=
unbox
(
wrap
,
!
exact
,
raw
).
asType
(
type
);
}
}
if
(
mh
!=
null
)
{
if
(
mh
!=
null
)
{
cache
.
put
(
wrap
,
mh
);
cache
.
put
(
wrap
,
mh
);
...
@@ -293,7 +290,7 @@ public class ValueConversions {
...
@@ -293,7 +290,7 @@ public class ValueConversions {
mh
=
null
;
mh
=
null
;
}
}
}
else
{
}
else
{
mh
=
retype
(
type
.
erase
(),
box
(
wrap
,
!
exact
,
raw
));
mh
=
box
(
wrap
,
!
exact
,
raw
).
asType
(
type
.
erase
(
));
}
}
if
(
mh
!=
null
)
{
if
(
mh
!=
null
)
{
cache
.
put
(
wrap
,
mh
);
cache
.
put
(
wrap
,
mh
);
...
@@ -412,7 +409,7 @@ public class ValueConversions {
...
@@ -412,7 +409,7 @@ public class ValueConversions {
mh
=
null
;
mh
=
null
;
}
}
}
else
{
}
else
{
mh
=
re
type
(
IDENTITY
.
type
(),
rebox
(
wrap
,
!
exact
));
mh
=
re
box
(
wrap
,
!
exact
).
asType
(
IDENTITY
.
type
(
));
}
}
if
(
mh
!=
null
)
{
if
(
mh
!=
null
)
{
cache
.
put
(
wrap
,
mh
);
cache
.
put
(
wrap
,
mh
);
...
@@ -504,8 +501,8 @@ public class ValueConversions {
...
@@ -504,8 +501,8 @@ public class ValueConversions {
// use the raw method
// use the raw method
Wrapper
rawWrap
=
wrap
.
rawPrimitive
();
Wrapper
rawWrap
=
wrap
.
rawPrimitive
();
if
(
rawWrap
!=
wrap
)
{
if
(
mh
==
null
&&
rawWrap
!=
wrap
)
{
mh
=
retype
(
type
,
zeroConstantFunction
(
rawWrap
)
);
mh
=
MethodHandles
.
explicitCastArguments
(
zeroConstantFunction
(
rawWrap
),
type
);
}
}
if
(
mh
!=
null
)
{
if
(
mh
!=
null
)
{
cache
.
put
(
wrap
,
mh
);
cache
.
put
(
wrap
,
mh
);
...
@@ -552,6 +549,22 @@ public class ValueConversions {
...
@@ -552,6 +549,22 @@ public class ValueConversions {
return
x
;
return
x
;
}
}
static
byte
identity
(
byte
x
)
{
return
x
;
}
static
short
identity
(
short
x
)
{
return
x
;
}
static
boolean
identity
(
boolean
x
)
{
return
x
;
}
static
char
identity
(
char
x
)
{
return
x
;
}
/**
/**
* Identity function on longs.
* Identity function on longs.
* @param x an arbitrary long value
* @param x an arbitrary long value
...
@@ -561,6 +574,14 @@ public class ValueConversions {
...
@@ -561,6 +574,14 @@ public class ValueConversions {
return
x
;
return
x
;
}
}
static
float
identity
(
float
x
)
{
return
x
;
}
static
double
identity
(
double
x
)
{
return
x
;
}
/**
/**
* Identity function, with reference cast.
* Identity function, with reference cast.
* @param t an arbitrary reference type
* @param t an arbitrary reference type
...
@@ -590,7 +611,9 @@ public class ValueConversions {
...
@@ -590,7 +611,9 @@ public class ValueConversions {
IGNORE
=
IMPL_LOOKUP
.
findStatic
(
ValueConversions
.
class
,
"ignore"
,
ignoreType
);
IGNORE
=
IMPL_LOOKUP
.
findStatic
(
ValueConversions
.
class
,
"ignore"
,
ignoreType
);
EMPTY
=
IMPL_LOOKUP
.
findStatic
(
ValueConversions
.
class
,
"empty"
,
ignoreType
.
dropParameterTypes
(
0
,
1
));
EMPTY
=
IMPL_LOOKUP
.
findStatic
(
ValueConversions
.
class
,
"empty"
,
ignoreType
.
dropParameterTypes
(
0
,
1
));
}
catch
(
Exception
ex
)
{
}
catch
(
Exception
ex
)
{
throw
uncaughtException
(
ex
);
Error
err
=
new
InternalError
(
"uncaught exception"
);
err
.
initCause
(
ex
);
throw
err
;
}
}
}
}
...
@@ -622,7 +645,8 @@ public class ValueConversions {
...
@@ -622,7 +645,8 @@ public class ValueConversions {
mh
=
MethodHandles
.
insertArguments
(
CAST_REFERENCE
,
0
,
type
);
mh
=
MethodHandles
.
insertArguments
(
CAST_REFERENCE
,
0
,
type
);
if
(
exact
)
{
if
(
exact
)
{
MethodType
xmt
=
MethodType
.
methodType
(
type
,
Object
.
class
);
MethodType
xmt
=
MethodType
.
methodType
(
type
,
Object
.
class
);
mh
=
AdapterMethodHandle
.
makeRetypeRaw
(
IMPL_TOKEN
,
xmt
,
mh
);
mh
=
MethodHandles
.
explicitCastArguments
(
mh
,
xmt
);
//mh = AdapterMethodHandle.makeRetypeRaw(IMPL_TOKEN, xmt, mh);
}
}
if
(
cache
!=
null
)
if
(
cache
!=
null
)
cache
.
put
(
wrap
,
mh
);
cache
.
put
(
wrap
,
mh
);
...
@@ -634,15 +658,11 @@ public class ValueConversions {
...
@@ -634,15 +658,11 @@ public class ValueConversions {
}
}
public
static
MethodHandle
identity
(
Class
<?>
type
)
{
public
static
MethodHandle
identity
(
Class
<?>
type
)
{
if
(
type
==
Object
.
class
)
// This stuff has been moved into MethodHandles:
return
IDENTITY
;
return
MethodHandles
.
identity
(
type
);
else
if
(!
type
.
isPrimitive
())
return
retype
(
MethodType
.
methodType
(
type
,
type
),
IDENTITY
);
else
return
identity
(
Wrapper
.
forPrimitiveType
(
type
));
}
}
static
MethodHandle
identity
(
Wrapper
wrap
)
{
public
static
MethodHandle
identity
(
Wrapper
wrap
)
{
EnumMap
<
Wrapper
,
MethodHandle
>
cache
=
CONSTANT_FUNCTIONS
[
1
];
EnumMap
<
Wrapper
,
MethodHandle
>
cache
=
CONSTANT_FUNCTIONS
[
1
];
MethodHandle
mh
=
cache
.
get
(
wrap
);
MethodHandle
mh
=
cache
.
get
(
wrap
);
if
(
mh
!=
null
)
{
if
(
mh
!=
null
)
{
...
@@ -665,12 +685,6 @@ public class ValueConversions {
...
@@ -665,12 +685,6 @@ public class ValueConversions {
return
mh
;
return
mh
;
}
}
// use a raw conversion
if
(
wrap
.
isSingleWord
()
&&
wrap
!=
Wrapper
.
INT
)
{
mh
=
retype
(
type
,
identity
(
Wrapper
.
INT
));
}
else
if
(
wrap
.
isDoubleWord
()
&&
wrap
!=
Wrapper
.
LONG
)
{
mh
=
retype
(
type
,
identity
(
Wrapper
.
LONG
));
}
if
(
mh
!=
null
)
{
if
(
mh
!=
null
)
{
cache
.
put
(
wrap
,
mh
);
cache
.
put
(
wrap
,
mh
);
return
mh
;
return
mh
;
...
@@ -678,10 +692,6 @@ public class ValueConversions {
...
@@ -678,10 +692,6 @@ public class ValueConversions {
throw
new
IllegalArgumentException
(
"cannot find identity for "
+
wrap
);
throw
new
IllegalArgumentException
(
"cannot find identity for "
+
wrap
);
}
}
private
static
MethodHandle
retype
(
MethodType
type
,
MethodHandle
mh
)
{
return
AdapterMethodHandle
.
makeRetypeRaw
(
IMPL_TOKEN
,
type
,
mh
);
}
private
static
final
Object
[]
NO_ARGS_ARRAY
=
{};
private
static
final
Object
[]
NO_ARGS_ARRAY
=
{};
private
static
Object
[]
makeArray
(
Object
...
args
)
{
return
args
;
}
private
static
Object
[]
makeArray
(
Object
...
args
)
{
return
args
;
}
private
static
Object
[]
array
()
{
return
NO_ARGS_ARRAY
;
}
private
static
Object
[]
array
()
{
return
NO_ARGS_ARRAY
;
}
...
...
src/share/classes/sun/
dyn
/util/VerifyAccess.java
→
src/share/classes/sun/
invoke
/util/VerifyAccess.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,12 +23,9 @@
...
@@ -23,12 +23,9 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
.util
;
package
sun.
invoke
.util
;
import
java.lang.reflect.Modifier
;
import
java.lang.reflect.Modifier
;
import
sun.dyn.MemberName
;
import
sun.dyn.MethodHandleImpl
;
import
sun.dyn.empty.Empty
;
import
static
java
.
lang
.
reflect
.
Modifier
.*;
import
static
java
.
lang
.
reflect
.
Modifier
.*;
/**
/**
...
...
src/share/classes/sun/
dyn
/util/VerifyType.java
→
src/share/classes/sun/
invoke
/util/VerifyType.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,10 +23,10 @@
...
@@ -23,10 +23,10 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
.util
;
package
sun.
invoke
.util
;
import
java.
dyn
.MethodType
;
import
java.
lang.invoke
.MethodType
;
import
sun.
dyn
.empty.Empty
;
import
sun.
invoke
.empty.Empty
;
/**
/**
* This class centralizes information about the JVM verifier
* This class centralizes information about the JVM verifier
...
...
src/share/classes/sun/
dyn
/util/Wrapper.java
→
src/share/classes/sun/
invoke
/util/Wrapper.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
* questions.
* questions.
*/
*/
package
sun.
dyn
.util
;
package
sun.
invoke
.util
;
public
enum
Wrapper
{
public
enum
Wrapper
{
BOOLEAN
(
Boolean
.
class
,
boolean
.
class
,
'Z'
,
(
Boolean
)
false
,
Format
.
unsigned
(
1
)),
BOOLEAN
(
Boolean
.
class
,
boolean
.
class
,
'Z'
,
(
Boolean
)
false
,
Format
.
unsigned
(
1
)),
...
@@ -267,7 +267,7 @@ public enum Wrapper {
...
@@ -267,7 +267,7 @@ public enum Wrapper {
FROM_WRAP
[
wi
]
=
w
;
FROM_WRAP
[
wi
]
=
w
;
FROM_CHAR
[
ci
]
=
w
;
FROM_CHAR
[
ci
]
=
w
;
}
}
//assert(jdk.sun.
dyn
.util.WrapperTest.test(false));
//assert(jdk.sun.
invoke
.util.WrapperTest.test(false));
}
}
/** What is the primitive type wrapped by this wrapper? */
/** What is the primitive type wrapped by this wrapper? */
...
...
src/share/classes/sun/
dyn
/util/package-info.java
→
src/share/classes/sun/
invoke
/util/package-info.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2008, 20
09
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 20
11
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -24,8 +24,8 @@
...
@@ -24,8 +24,8 @@
*/
*/
/**
/**
* Extra support for using JSR 292 RI, package java.
dyn
.
* Extra support for using JSR 292 RI, package java.
lang.invoke
.
* @author jrose
* @author jrose
*/
*/
package
sun.
dyn
.util
;
package
sun.
invoke
.util
;
src/share/native/common/check_code.c
浏览文件 @
33ee9ccf
...
@@ -2685,11 +2685,11 @@ push_stack(context_type *context, unsigned int inumber, stack_info_type *new_sta
...
@@ -2685,11 +2685,11 @@ push_stack(context_type *context, unsigned int inumber, stack_info_type *new_sta
switch
(
type_table
[
operand
])
{
switch
(
type_table
[
operand
])
{
case
JVM_CONSTANT_MethodType
:
case
JVM_CONSTANT_MethodType
:
full_info
=
make_class_info_from_name
(
context
,
full_info
=
make_class_info_from_name
(
context
,
"java/
dyn
/MethodType"
);
"java/
lang/invoke
/MethodType"
);
break
;
break
;
default:
//JVM_CONSTANT_MethodHandle
default:
//JVM_CONSTANT_MethodHandle
full_info
=
make_class_info_from_name
(
context
,
full_info
=
make_class_info_from_name
(
context
,
"java/
dyn
/MethodHandle"
);
"java/
lang/invoke
/MethodHandle"
);
break
;
break
;
}
}
break
;
break
;
...
...
test/java/lang/invoke/6987555/Test6987555.java
0 → 100644
浏览文件 @
33ee9ccf
/*
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/**
* @test
* @bug 6987555
* @summary JSR 292 unboxing to a boolean value fails on big-endian SPARC
*
* @run main/othervm -Xint -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6987555
*/
import
java.lang.invoke.*
;
public
class
Test6987555
{
private
static
final
Class
CLASS
=
Test6987555
.
class
;
private
static
final
String
NAME
=
"foo"
;
private
static
final
boolean
DEBUG
=
false
;
public
static
void
main
(
String
[]
args
)
throws
Throwable
{
testboolean
();
testbyte
();
testchar
();
testshort
();
testint
();
}
// boolean
static
void
testboolean
()
throws
Throwable
{
doboolean
(
false
);
doboolean
(
true
);
}
static
void
doboolean
(
boolean
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"boolean="
+
x
);
MethodHandle
mh1
=
MethodHandles
.
lookup
().
findStatic
(
CLASS
,
NAME
,
MethodType
.
methodType
(
boolean
.
class
,
boolean
.
class
));
MethodHandle
mh2
=
mh1
.
asType
(
MethodType
.
methodType
(
boolean
.
class
,
Boolean
.
class
));
boolean
a
=
(
boolean
)
mh1
.
invokeExact
(
x
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
Boolean
.
valueOf
(
x
));
assert
a
==
b
:
a
+
" != "
+
b
;
}
// byte
static
void
testbyte
()
throws
Throwable
{
byte
[]
a
=
new
byte
[]
{
Byte
.
MIN_VALUE
,
Byte
.
MIN_VALUE
+
1
,
-
0x0F
,
-
1
,
0
,
1
,
0x0F
,
Byte
.
MAX_VALUE
-
1
,
Byte
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
dobyte
(
a
[
i
]);
}
}
static
void
dobyte
(
byte
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"byte="
+
x
);
MethodHandle
mh1
=
MethodHandles
.
lookup
().
findStatic
(
CLASS
,
NAME
,
MethodType
.
methodType
(
byte
.
class
,
byte
.
class
));
MethodHandle
mh2
=
mh1
.
asType
(
MethodType
.
methodType
(
byte
.
class
,
Byte
.
class
));
byte
a
=
(
byte
)
mh1
.
invokeExact
(
x
);
byte
b
=
(
byte
)
mh2
.
invokeExact
(
Byte
.
valueOf
(
x
));
assert
a
==
b
:
a
+
" != "
+
b
;
}
// char
static
void
testchar
()
throws
Throwable
{
char
[]
a
=
new
char
[]
{
Character
.
MIN_VALUE
,
Character
.
MIN_VALUE
+
1
,
0x000F
,
0x00FF
,
0x0FFF
,
Character
.
MAX_VALUE
-
1
,
Character
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
dochar
(
a
[
i
]);
}
}
static
void
dochar
(
char
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"char="
+
x
);
MethodHandle
mh1
=
MethodHandles
.
lookup
().
findStatic
(
CLASS
,
NAME
,
MethodType
.
methodType
(
char
.
class
,
char
.
class
));
MethodHandle
mh2
=
mh1
.
asType
(
MethodType
.
methodType
(
char
.
class
,
Character
.
class
));
char
a
=
(
char
)
mh1
.
invokeExact
(
x
);
char
b
=
(
char
)
mh2
.
invokeExact
(
Character
.
valueOf
(
x
));
assert
a
==
b
:
a
+
" != "
+
b
;
}
// short
static
void
testshort
()
throws
Throwable
{
short
[]
a
=
new
short
[]
{
Short
.
MIN_VALUE
,
Short
.
MIN_VALUE
+
1
,
-
0x0FFF
,
-
0x00FF
,
-
0x000F
,
-
1
,
0
,
1
,
0x000F
,
0x00FF
,
0x0FFF
,
Short
.
MAX_VALUE
-
1
,
Short
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
doshort
(
a
[
i
]);
}
}
static
void
doshort
(
short
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"short="
+
x
);
MethodHandle
mh1
=
MethodHandles
.
lookup
().
findStatic
(
CLASS
,
NAME
,
MethodType
.
methodType
(
short
.
class
,
short
.
class
));
MethodHandle
mh2
=
mh1
.
asType
(
MethodType
.
methodType
(
short
.
class
,
Short
.
class
));
short
a
=
(
short
)
mh1
.
invokeExact
(
x
);
short
b
=
(
short
)
mh2
.
invokeExact
(
Short
.
valueOf
(
x
));
assert
a
==
b
:
a
+
" != "
+
b
;
}
// int
static
void
testint
()
throws
Throwable
{
int
[]
a
=
new
int
[]
{
Integer
.
MIN_VALUE
,
Integer
.
MIN_VALUE
+
1
,
-
0x00000FFF
,
-
0x000000FF
,
-
0x0000000F
,
-
1
,
0
,
1
,
0x0000000F
,
0x000000FF
,
0x00000FFF
,
Integer
.
MAX_VALUE
-
1
,
Integer
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
doint
(
a
[
i
]);
}
}
static
void
doint
(
int
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"int="
+
x
);
MethodHandle
mh1
=
MethodHandles
.
lookup
().
findStatic
(
CLASS
,
NAME
,
MethodType
.
methodType
(
int
.
class
,
int
.
class
));
MethodHandle
mh2
=
mh1
.
asType
(
MethodType
.
methodType
(
int
.
class
,
Integer
.
class
));
int
a
=
(
int
)
mh1
.
invokeExact
(
x
);
int
b
=
(
int
)
mh2
.
invokeExact
(
Integer
.
valueOf
(
x
));
assert
a
==
b
:
a
+
" != "
+
b
;
}
public
static
boolean
foo
(
boolean
i
)
{
return
i
;
}
public
static
byte
foo
(
byte
i
)
{
return
i
;
}
public
static
char
foo
(
char
i
)
{
return
i
;
}
public
static
short
foo
(
short
i
)
{
return
i
;
}
public
static
int
foo
(
int
i
)
{
return
i
;
}
}
test/java/lang/invoke/6991596/Test6991596.java
0 → 100644
浏览文件 @
33ee9ccf
/*
* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/**
* @test
* @bug 6991596
* @summary JSR 292 unimplemented adapter_opt_i2i and adapter_opt_l2i on SPARC
*
* @run main/othervm -ea -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles -XX:+EnableInvokeDynamic -XX:+UnlockDiagnosticVMOptions -XX:+VerifyMethodHandles Test6991596
*/
import
java.lang.invoke.*
;
public
class
Test6991596
{
private
static
final
Class
CLASS
=
Test6991596
.
class
;
private
static
final
String
NAME
=
"foo"
;
private
static
final
boolean
DEBUG
=
System
.
getProperty
(
"DEBUG"
,
"false"
).
equals
(
"true"
);
public
static
void
main
(
String
[]
args
)
throws
Throwable
{
testboolean
();
testbyte
();
testchar
();
testshort
();
testint
();
testlong
();
}
// Helpers to get various methods.
static
MethodHandle
getmh1
(
Class
ret
,
Class
arg
)
throws
ReflectiveOperationException
{
return
MethodHandles
.
lookup
().
findStatic
(
CLASS
,
NAME
,
MethodType
.
methodType
(
ret
,
arg
));
}
static
MethodHandle
getmh2
(
MethodHandle
mh1
,
Class
ret
,
Class
arg
)
{
return
MethodHandles
.
convertArguments
(
mh1
,
MethodType
.
methodType
(
ret
,
arg
));
}
static
MethodHandle
getmh3
(
MethodHandle
mh1
,
Class
ret
,
Class
arg
)
{
return
MethodHandles
.
convertArguments
(
mh1
,
MethodType
.
methodType
(
ret
,
arg
));
}
// test adapter_opt_i2i
static
void
testboolean
()
throws
Throwable
{
boolean
[]
a
=
new
boolean
[]
{
true
,
false
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
doboolean
(
a
[
i
]);
}
}
static
void
doboolean
(
boolean
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"boolean="
+
x
);
// boolean
{
MethodHandle
mh1
=
getmh1
(
boolean
.
class
,
boolean
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
boolean
.
class
,
boolean
.
class
);
// TODO add this for all cases when the bugs are fixed.
//MethodHandle mh3 = getmh3(mh1, boolean.class, boolean.class);
boolean
a
=
(
boolean
)
mh1
.
invokeExact
((
boolean
)
x
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
x
);
//boolean c = mh3.<boolean>invokeExact((boolean) x);
check
(
x
,
a
,
b
);
//check(x, c, x);
}
// byte
{
MethodHandle
mh1
=
getmh1
(
byte
.
class
,
byte
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
byte
.
class
,
boolean
.
class
);
byte
a
=
(
byte
)
mh1
.
invokeExact
((
byte
)
(
x
?
1
:
0
));
byte
b
=
(
byte
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// char
{
MethodHandle
mh1
=
getmh1
(
char
.
class
,
char
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
char
.
class
,
boolean
.
class
);
char
a
=
(
char
)
mh1
.
invokeExact
((
char
)
(
x
?
1
:
0
));
char
b
=
(
char
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// short
{
MethodHandle
mh1
=
getmh1
(
short
.
class
,
short
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
short
.
class
,
boolean
.
class
);
short
a
=
(
short
)
mh1
.
invokeExact
((
short
)
(
x
?
1
:
0
));
short
b
=
(
short
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
}
static
void
testbyte
()
throws
Throwable
{
byte
[]
a
=
new
byte
[]
{
Byte
.
MIN_VALUE
,
Byte
.
MIN_VALUE
+
1
,
-
0x0F
,
-
1
,
0
,
1
,
0x0F
,
Byte
.
MAX_VALUE
-
1
,
Byte
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
dobyte
(
a
[
i
]);
}
}
static
void
dobyte
(
byte
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"byte="
+
x
);
// boolean
{
MethodHandle
mh1
=
getmh1
(
boolean
.
class
,
boolean
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
boolean
.
class
,
byte
.
class
);
boolean
a
=
(
boolean
)
mh1
.
invokeExact
((
x
&
1
)
==
1
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// byte
{
MethodHandle
mh1
=
getmh1
(
byte
.
class
,
byte
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
byte
.
class
,
byte
.
class
);
byte
a
=
(
byte
)
mh1
.
invokeExact
((
byte
)
x
);
byte
b
=
(
byte
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// char
{
MethodHandle
mh1
=
getmh1
(
char
.
class
,
char
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
char
.
class
,
byte
.
class
);
char
a
=
(
char
)
mh1
.
invokeExact
((
char
)
x
);
char
b
=
(
char
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// short
{
MethodHandle
mh1
=
getmh1
(
short
.
class
,
short
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
short
.
class
,
byte
.
class
);
short
a
=
(
short
)
mh1
.
invokeExact
((
short
)
x
);
short
b
=
(
short
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
}
static
void
testchar
()
throws
Throwable
{
char
[]
a
=
new
char
[]
{
Character
.
MIN_VALUE
,
Character
.
MIN_VALUE
+
1
,
0x000F
,
0x00FF
,
0x0FFF
,
Character
.
MAX_VALUE
-
1
,
Character
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
dochar
(
a
[
i
]);
}
}
static
void
dochar
(
char
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"char="
+
x
);
// boolean
{
MethodHandle
mh1
=
getmh1
(
boolean
.
class
,
boolean
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
boolean
.
class
,
char
.
class
);
boolean
a
=
(
boolean
)
mh1
.
invokeExact
((
x
&
1
)
==
1
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// byte
{
MethodHandle
mh1
=
getmh1
(
byte
.
class
,
byte
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
byte
.
class
,
char
.
class
);
byte
a
=
(
byte
)
mh1
.
invokeExact
((
byte
)
x
);
byte
b
=
(
byte
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// char
{
MethodHandle
mh1
=
getmh1
(
char
.
class
,
char
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
char
.
class
,
char
.
class
);
char
a
=
(
char
)
mh1
.
invokeExact
((
char
)
x
);
char
b
=
(
char
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// short
{
MethodHandle
mh1
=
getmh1
(
short
.
class
,
short
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
short
.
class
,
char
.
class
);
short
a
=
(
short
)
mh1
.
invokeExact
((
short
)
x
);
short
b
=
(
short
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
}
static
void
testshort
()
throws
Throwable
{
short
[]
a
=
new
short
[]
{
Short
.
MIN_VALUE
,
Short
.
MIN_VALUE
+
1
,
-
0x0FFF
,
-
0x00FF
,
-
0x000F
,
-
1
,
0
,
1
,
0x000F
,
0x00FF
,
0x0FFF
,
Short
.
MAX_VALUE
-
1
,
Short
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
doshort
(
a
[
i
]);
}
}
static
void
doshort
(
short
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"short="
+
x
);
// boolean
{
MethodHandle
mh1
=
getmh1
(
boolean
.
class
,
boolean
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
boolean
.
class
,
short
.
class
);
boolean
a
=
(
boolean
)
mh1
.
invokeExact
((
x
&
1
)
==
1
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// byte
{
MethodHandle
mh1
=
getmh1
(
byte
.
class
,
byte
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
byte
.
class
,
short
.
class
);
byte
a
=
(
byte
)
mh1
.
invokeExact
((
byte
)
x
);
byte
b
=
(
byte
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// char
{
MethodHandle
mh1
=
getmh1
(
char
.
class
,
char
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
char
.
class
,
short
.
class
);
char
a
=
(
char
)
mh1
.
invokeExact
((
char
)
x
);
char
b
=
(
char
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// short
{
MethodHandle
mh1
=
getmh1
(
short
.
class
,
short
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
short
.
class
,
short
.
class
);
short
a
=
(
short
)
mh1
.
invokeExact
((
short
)
x
);
short
b
=
(
short
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
}
static
void
testint
()
throws
Throwable
{
int
[]
a
=
new
int
[]
{
Integer
.
MIN_VALUE
,
Integer
.
MIN_VALUE
+
1
,
-
0x0FFFFFFF
,
-
0x00FFFFFF
,
-
0x000FFFFF
,
-
0x0000FFFF
,
-
0x00000FFF
,
-
0x000000FF
,
-
0x0000000F
,
-
1
,
0
,
1
,
0x0000000F
,
0x000000FF
,
0x00000FFF
,
0x0000FFFF
,
0x000FFFFF
,
0x00FFFFFF
,
0x0FFFFFFF
,
Integer
.
MAX_VALUE
-
1
,
Integer
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
doint
(
a
[
i
]);
}
}
static
void
doint
(
int
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"int="
+
x
);
// boolean
{
MethodHandle
mh1
=
getmh1
(
boolean
.
class
,
boolean
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
boolean
.
class
,
int
.
class
);
boolean
a
=
(
boolean
)
mh1
.
invokeExact
((
x
&
1
)
==
1
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// byte
{
MethodHandle
mh1
=
getmh1
(
byte
.
class
,
byte
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
byte
.
class
,
int
.
class
);
byte
a
=
(
byte
)
mh1
.
invokeExact
((
byte
)
x
);
byte
b
=
(
byte
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// char
{
MethodHandle
mh1
=
getmh1
(
char
.
class
,
char
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
char
.
class
,
int
.
class
);
char
a
=
(
char
)
mh1
.
invokeExact
((
char
)
x
);
char
b
=
(
char
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// short
{
MethodHandle
mh1
=
getmh1
(
short
.
class
,
short
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
short
.
class
,
int
.
class
);
short
a
=
(
short
)
mh1
.
invokeExact
((
short
)
x
);
short
b
=
(
short
)
mh2
.
invokeExact
(
x
);
assert
a
==
b
:
a
+
" != "
+
b
;
check
(
x
,
a
,
b
);
}
// int
{
MethodHandle
mh1
=
getmh1
(
int
.
class
,
int
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
int
.
class
,
int
.
class
);
int
a
=
(
int
)
mh1
.
invokeExact
((
int
)
x
);
int
b
=
(
int
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
}
// test adapter_opt_l2i
static
void
testlong
()
throws
Throwable
{
long
[]
a
=
new
long
[]
{
Long
.
MIN_VALUE
,
Long
.
MIN_VALUE
+
1
,
-
0x000000000FFFFFFF
L
,
-
0x0000000000FFFFFF
L
,
-
0x00000000000FFFFF
L
,
-
0x000000000000FFFF
L
,
-
0x0000000000000FFF
L
,
-
0x00000000000000FF
L
,
-
0x000000000000000F
L
,
-
1L
,
0L
,
1L
,
0x000000000000000F
L
,
0x00000000000000FF
L
,
0x0000000000000FFF
L
,
0x0000000000000FFF
L
,
0x000000000000FFFF
L
,
0x00000000000FFFFF
L
,
0x0000000000FFFFFF
L
,
0x000000000FFFFFFF
L
,
Long
.
MAX_VALUE
-
1
,
Long
.
MAX_VALUE
};
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
dolong
(
a
[
i
]);
}
}
static
void
dolong
(
long
x
)
throws
Throwable
{
if
(
DEBUG
)
System
.
out
.
println
(
"long="
+
x
);
// boolean
{
MethodHandle
mh1
=
getmh1
(
boolean
.
class
,
boolean
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
boolean
.
class
,
long
.
class
);
boolean
a
=
(
boolean
)
mh1
.
invokeExact
((
x
&
1L
)
==
1L
);
boolean
b
=
(
boolean
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// byte
{
MethodHandle
mh1
=
getmh1
(
byte
.
class
,
byte
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
byte
.
class
,
long
.
class
);
byte
a
=
(
byte
)
mh1
.
invokeExact
((
byte
)
x
);
byte
b
=
(
byte
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// char
{
MethodHandle
mh1
=
getmh1
(
char
.
class
,
char
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
char
.
class
,
long
.
class
);
char
a
=
(
char
)
mh1
.
invokeExact
((
char
)
x
);
char
b
=
(
char
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// short
{
MethodHandle
mh1
=
getmh1
(
short
.
class
,
short
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
short
.
class
,
long
.
class
);
short
a
=
(
short
)
mh1
.
invokeExact
((
short
)
x
);
short
b
=
(
short
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
// int
{
MethodHandle
mh1
=
getmh1
(
int
.
class
,
int
.
class
);
MethodHandle
mh2
=
getmh2
(
mh1
,
int
.
class
,
long
.
class
);
int
a
=
(
int
)
mh1
.
invokeExact
((
int
)
x
);
int
b
=
(
int
)
mh2
.
invokeExact
(
x
);
check
(
x
,
a
,
b
);
}
}
static
void
check
(
boolean
x
,
boolean
e
,
boolean
a
)
{
p
(
z2h
(
x
),
z2h
(
e
),
z2h
(
a
));
assert
e
==
a
:
z2h
(
x
)
+
": "
+
z2h
(
e
)
+
" != "
+
z2h
(
a
);
}
static
void
check
(
boolean
x
,
byte
e
,
byte
a
)
{
p
(
z2h
(
x
),
i2h
(
e
),
i2h
(
a
));
assert
e
==
a
:
z2h
(
x
)
+
": "
+
i2h
(
e
)
+
" != "
+
i2h
(
a
);
}
static
void
check
(
boolean
x
,
int
e
,
int
a
)
{
p
(
z2h
(
x
),
i2h
(
e
),
i2h
(
a
));
assert
e
==
a
:
z2h
(
x
)
+
": "
+
i2h
(
e
)
+
" != "
+
i2h
(
a
);
}
static
void
check
(
int
x
,
boolean
e
,
boolean
a
)
{
p
(
i2h
(
x
),
z2h
(
e
),
z2h
(
a
));
assert
e
==
a
:
i2h
(
x
)
+
": "
+
z2h
(
e
)
+
" != "
+
z2h
(
a
);
}
static
void
check
(
int
x
,
byte
e
,
byte
a
)
{
p
(
i2h
(
x
),
i2h
(
e
),
i2h
(
a
));
assert
e
==
a
:
i2h
(
x
)
+
": "
+
i2h
(
e
)
+
" != "
+
i2h
(
a
);
}
static
void
check
(
int
x
,
int
e
,
int
a
)
{
p
(
i2h
(
x
),
i2h
(
e
),
i2h
(
a
));
assert
e
==
a
:
i2h
(
x
)
+
": "
+
i2h
(
e
)
+
" != "
+
i2h
(
a
);
}
static
void
check
(
long
x
,
boolean
e
,
boolean
a
)
{
p
(
l2h
(
x
),
z2h
(
e
),
z2h
(
a
));
assert
e
==
a
:
l2h
(
x
)
+
": "
+
z2h
(
e
)
+
" != "
+
z2h
(
a
);
}
static
void
check
(
long
x
,
byte
e
,
byte
a
)
{
p
(
l2h
(
x
),
i2h
(
e
),
i2h
(
a
));
assert
e
==
a
:
l2h
(
x
)
+
": "
+
i2h
(
e
)
+
" != "
+
i2h
(
a
);
}
static
void
check
(
long
x
,
int
e
,
int
a
)
{
p
(
l2h
(
x
),
i2h
(
e
),
i2h
(
a
));
assert
e
==
a
:
l2h
(
x
)
+
": "
+
i2h
(
e
)
+
" != "
+
i2h
(
a
);
}
static
void
p
(
String
x
,
String
e
,
String
a
)
{
if
(
DEBUG
)
System
.
out
.
println
(
x
+
": expected: "
+
e
+
", actual: "
+
a
);
}
static
String
z2h
(
boolean
x
)
{
return
x
?
"1"
:
"0"
;
}
static
String
i2h
(
int
x
)
{
return
Integer
.
toHexString
(
x
);
}
static
String
l2h
(
long
x
)
{
return
Long
.
toHexString
(
x
);
}
// to int
public
static
boolean
foo
(
boolean
i
)
{
return
i
;
}
public
static
byte
foo
(
byte
i
)
{
return
i
;
}
public
static
char
foo
(
char
i
)
{
return
i
;
}
public
static
short
foo
(
short
i
)
{
return
i
;
}
public
static
int
foo
(
int
i
)
{
return
i
;
}
}
test/java/
dyn
/ClassValueTest.java
→
test/java/
lang/invoke
/ClassValueTest.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -26,21 +26,21 @@
...
@@ -26,21 +26,21 @@
/* @test
/* @test
* @summary tests for class-specific values
* @summary tests for class-specific values
* @compile ClassValueTest.java
* @compile ClassValueTest.java
* @run junit/othervm test.java.
dyn
.ClassValueTest
* @run junit/othervm test.java.
lang.invoke
.ClassValueTest
*/
*/
/*
/*
Manually:
Manually:
$ $JAVA7X_HOME/bin/javac -d foo -cp $JUNIT4_JAR test/java/
dyn
/ClassValueTest.java
$ $JAVA7X_HOME/bin/javac -d foo -cp $JUNIT4_JAR test/java/
lang/invoke
/ClassValueTest.java
$ $JAVA7X_HOME/bin/java -cp foo:$JUNIT4_JAR org.junit.runner.JUnitCore test.java.
dyn
.ClassValueTest
$ $JAVA7X_HOME/bin/java -cp foo:$JUNIT4_JAR org.junit.runner.JUnitCore test.java.
lang.invoke
.ClassValueTest
Output: .testAdd => 1000 : Integer
Output: .testAdd => 1000 : Integer
*/
*/
package
test.java.
dyn
;
package
test.java.
lang.invoke
;
import
java.util.*
;
import
java.util.*
;
import
java.
dyn
.*
;
import
java.
lang.invoke
.*
;
import
org.junit.*
;
import
org.junit.*
;
import
static
org
.
junit
.
Assert
.*;
import
static
org
.
junit
.
Assert
.*;
...
...
test/java/
dyn
/InvokeDynamicPrintArgs.java
→
test/java/
lang/invoke
/InvokeDynamicPrintArgs.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010,
2011,
Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -29,19 +29,19 @@
...
@@ -29,19 +29,19 @@
* indify.Indify
* indify.Indify
* --verify-specifier-count=3 --transitionalJSR292=false
* --verify-specifier-count=3 --transitionalJSR292=false
* --expand-properties --classpath ${test.classes}
* --expand-properties --classpath ${test.classes}
* --java test.java.
dyn
.InvokeDynamicPrintArgs --check-output
* --java test.java.
lang.invoke
.InvokeDynamicPrintArgs --check-output
*/
*/
package
test.java.
dyn
;
package
test.java.
lang.invoke
;
import
org.junit.Test
;
import
org.junit.Test
;
import
java.util.*
;
import
java.util.*
;
import
java.io.*
;
import
java.io.*
;
import
java.
dyn
.*
;
import
java.
lang.invoke
.*
;
import
static
java
.
dyn
.
MethodHandles
.*;
import
static
java
.
lang
.
invoke
.
MethodHandles
.*;
import
static
java
.
dyn
.
MethodType
.*;
import
static
java
.
lang
.
invoke
.
MethodType
.*;
public
class
InvokeDynamicPrintArgs
{
public
class
InvokeDynamicPrintArgs
{
public
static
void
main
(
String
...
av
)
throws
Throwable
{
public
static
void
main
(
String
...
av
)
throws
Throwable
{
...
@@ -65,7 +65,7 @@ public class InvokeDynamicPrintArgs {
...
@@ -65,7 +65,7 @@ public class InvokeDynamicPrintArgs {
String
[]
args
=
new
String
[]{
String
[]
args
=
new
String
[]{
"--verify-specifier-count=3"
,
"--transitionalJSR292=false"
,
"--verify-specifier-count=3"
,
"--transitionalJSR292=false"
,
"--expand-properties"
,
"--classpath"
,
testClassPath
,
"--expand-properties"
,
"--classpath"
,
testClassPath
,
"--java"
,
"test.java.
dyn
.InvokeDynamicPrintArgs"
,
"--check-output"
"--java"
,
"test.java.
lang.invoke
.InvokeDynamicPrintArgs"
,
"--check-output"
};
};
System
.
err
.
println
(
"Indify: "
+
Arrays
.
toString
(
args
));
System
.
err
.
println
(
"Indify: "
+
Arrays
.
toString
(
args
));
indify
.
Indify
.
main
(
args
);
indify
.
Indify
.
main
(
args
);
...
@@ -97,11 +97,11 @@ public class InvokeDynamicPrintArgs {
...
@@ -97,11 +97,11 @@ public class InvokeDynamicPrintArgs {
}
}
private
static
final
String
[]
EXPECT_OUTPUT
=
{
private
static
final
String
[]
EXPECT_OUTPUT
=
{
"Printing some argument lists, starting with a empty one:"
,
"Printing some argument lists, starting with a empty one:"
,
"[test.java.
dyn
.InvokeDynamicPrintArgs, nothing, ()void][]"
,
"[test.java.
lang.invoke
.InvokeDynamicPrintArgs, nothing, ()void][]"
,
"[test.java.
dyn
.InvokeDynamicPrintArgs, bar, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar arg, 1]"
,
"[test.java.
lang.invoke
.InvokeDynamicPrintArgs, bar, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar arg, 1]"
,
"[test.java.
dyn
.InvokeDynamicPrintArgs, bar2, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar2 arg, 222]"
,
"[test.java.
lang.invoke
.InvokeDynamicPrintArgs, bar2, (String,int)void, class java.lang.Void, void type!, 1, 234.5, 67.5, 89][bar2 arg, 222]"
,
"[test.java.
dyn
.InvokeDynamicPrintArgs, baz, (String,int,double)void, 1234.5][baz arg, 2, 3.14]"
,
"[test.java.
lang.invoke
.InvokeDynamicPrintArgs, baz, (String,int,double)void, 1234.5][baz arg, 2, 3.14]"
,
"[test.java.
dyn
.InvokeDynamicPrintArgs, foo, (String)void][foo arg]"
,
"[test.java.
lang.invoke
.InvokeDynamicPrintArgs, foo, (String)void][foo arg]"
,
"Done printing argument lists."
"Done printing argument lists."
};
};
...
...
test/java/
dyn
/InvokeGenericTest.java
→
test/java/
lang/invoke
/InvokeGenericTest.java
浏览文件 @
33ee9ccf
/*
/*
* Copyright (c) 2009, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 201
1
, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
*
* This code is free software; you can redistribute it and/or modify it
* This code is free software; you can redistribute it and/or modify it
...
@@ -24,16 +24,16 @@
...
@@ -24,16 +24,16 @@
*/
*/
/* @test
/* @test
* @summary unit tests for java.
dyn
.MethodHandle.invokeGeneric
* @summary unit tests for java.
lang.invoke
.MethodHandle.invokeGeneric
* @compile -XDallowTransitionalJSR292=no -target 7 InvokeGenericTest.java
* @compile -XDallowTransitionalJSR292=no -target 7 InvokeGenericTest.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.
dyn
.InvokeGenericTest
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.
lang.invoke
.InvokeGenericTest
*/
*/
package
test.java.
dyn
;
package
test.java.
lang.invoke
;
import
java.
dyn
.*
;
import
java.
lang.invoke
.*
;
import
static
java
.
dyn
.
MethodHandles
.*;
import
static
java
.
lang
.
invoke
.
MethodHandles
.*;
import
static
java
.
dyn
.
MethodType
.*;
import
static
java
.
lang
.
invoke
.
MethodType
.*;
import
java.lang.reflect.*
;
import
java.lang.reflect.*
;
import
java.util.*
;
import
java.util.*
;
import
org.junit.*
;
import
org.junit.*
;
...
@@ -49,7 +49,7 @@ public class InvokeGenericTest {
...
@@ -49,7 +49,7 @@ public class InvokeGenericTest {
// How much output?
// How much output?
static
int
verbosity
=
0
;
static
int
verbosity
=
0
;
static
{
static
{
String
vstr
=
System
.
getProperty
(
"test.java.
dyn
.InvokeGenericTest.verbosity"
);
String
vstr
=
System
.
getProperty
(
"test.java.
lang.invoke
.InvokeGenericTest.verbosity"
);
if
(
vstr
!=
null
)
verbosity
=
Integer
.
parseInt
(
vstr
);
if
(
vstr
!=
null
)
verbosity
=
Integer
.
parseInt
(
vstr
);
}
}
...
@@ -216,7 +216,7 @@ public class InvokeGenericTest {
...
@@ -216,7 +216,7 @@ public class InvokeGenericTest {
if
(
wrap
!=
null
)
{
if
(
wrap
!=
null
)
{
return
wrap
;
return
wrap
;
}
}
// import sun.
dyn
.util.Wrapper;
// import sun.
invoke
.util.Wrapper;
// Wrapper wrap = Wrapper.forBasicType(dst);
// Wrapper wrap = Wrapper.forBasicType(dst);
// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
// wrap = Wrapper.forWrapperType(dst);
// wrap = Wrapper.forWrapperType(dst);
...
...
test/java/
dyn
/JavaDocExamplesTest.java
→
test/java/
lang/invoke
/JavaDocExamplesTest.java
浏览文件 @
33ee9ccf
...
@@ -24,27 +24,27 @@
...
@@ -24,27 +24,27 @@
*/
*/
/* @test
/* @test
* @summary example code used in javadoc for java.
dyn
API
* @summary example code used in javadoc for java.
lang.invoke
API
* @compile -XDallowTransitionalJSR292=no JavaDocExamplesTest.java
* @compile -XDallowTransitionalJSR292=no JavaDocExamplesTest.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.
dyn
.JavaDocExamplesTest
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.
lang.invoke
.JavaDocExamplesTest
*/
*/
/*
/*
---- To run outside jtreg:
---- To run outside jtreg:
$ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \
$ $JAVA7X_HOME/bin/javac -cp $JUNIT4_JAR -d /tmp/Classes \
$DAVINCI/sources/jdk/test/java/
dyn
/JavaDocExamplesTest.java
$DAVINCI/sources/jdk/test/java/
lang/invoke
/JavaDocExamplesTest.java
$ $JAVA7X_HOME/bin/java -cp $JUNIT4_JAR:/tmp/Classes \
$ $JAVA7X_HOME/bin/java -cp $JUNIT4_JAR:/tmp/Classes \
-XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \
-XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles \
-Dtest.java.
dyn
.JavaDocExamplesTest.verbosity=1 \
-Dtest.java.
lang.invoke
.JavaDocExamplesTest.verbosity=1 \
test.java.
dyn
.JavaDocExamplesTest
test.java.
lang.invoke
.JavaDocExamplesTest
----
----
*/
*/
package
test.java.
dyn
;
package
test.java.
lang.invoke
;
import
java.
dyn
.*
;
import
java.
lang.invoke
.*
;
import
static
java
.
dyn
.
MethodHandles
.*;
import
static
java
.
lang
.
invoke
.
MethodHandles
.*;
import
static
java
.
dyn
.
MethodType
.*;
import
static
java
.
lang
.
invoke
.
MethodType
.*;
import
java.lang.reflect.*
;
import
java.lang.reflect.*
;
import
java.util.*
;
import
java.util.*
;
...
@@ -65,7 +65,7 @@ public class JavaDocExamplesTest {
...
@@ -65,7 +65,7 @@ public class JavaDocExamplesTest {
org
.
junit
.
runner
.
JUnitCore
.
runClasses
(
JavaDocExamplesTest
.
class
);
org
.
junit
.
runner
.
JUnitCore
.
runClasses
(
JavaDocExamplesTest
.
class
);
}
}
// How much output?
// How much output?
static
int
verbosity
=
Integer
.
getInteger
(
"test.java.
dyn
.JavaDocExamplesTest.verbosity"
,
0
);
static
int
verbosity
=
Integer
.
getInteger
(
"test.java.
lang.invoke
.JavaDocExamplesTest.verbosity"
,
0
);
{}
{}
static
final
private
Lookup
LOOKUP
=
lookup
();
static
final
private
Lookup
LOOKUP
=
lookup
();
...
@@ -108,6 +108,16 @@ assertEquals("xy".hashCode(), (int) HASHCODE_3.invokeExact((Object)"xy"));
...
@@ -108,6 +108,16 @@ assertEquals("xy".hashCode(), (int) HASHCODE_3.invokeExact((Object)"xy"));
MethodHandle
cat
=
lookup
().
findVirtual
(
String
.
class
,
MethodHandle
cat
=
lookup
().
findVirtual
(
String
.
class
,
"concat"
,
methodType
(
String
.
class
,
String
.
class
));
"concat"
,
methodType
(
String
.
class
,
String
.
class
));
assertEquals
(
"xy"
,
(
String
)
cat
.
invokeExact
(
"x"
,
"y"
));
assertEquals
(
"xy"
,
(
String
)
cat
.
invokeExact
(
"x"
,
"y"
));
MethodType
bigType
=
cat
.
type
().
insertParameterTypes
(
0
,
int
.
class
,
String
.
class
);
MethodHandle
d0
=
dropArguments
(
cat
,
0
,
bigType
.
parameterList
().
subList
(
0
,
2
));
assertEquals
(
bigType
,
d0
.
type
());
assertEquals
(
"yz"
,
(
String
)
d0
.
invokeExact
(
123
,
"x"
,
"y"
,
"z"
));
}}
{{
{}
/// JAVADOC
MethodHandle
cat
=
lookup
().
findVirtual
(
String
.
class
,
"concat"
,
methodType
(
String
.
class
,
String
.
class
));
assertEquals
(
"xy"
,
(
String
)
cat
.
invokeExact
(
"x"
,
"y"
));
MethodHandle
d0
=
dropArguments
(
cat
,
0
,
String
.
class
);
MethodHandle
d0
=
dropArguments
(
cat
,
0
,
String
.
class
);
assertEquals
(
"yz"
,
(
String
)
d0
.
invokeExact
(
"x"
,
"y"
,
"z"
));
assertEquals
(
"yz"
,
(
String
)
d0
.
invokeExact
(
"x"
,
"y"
,
"z"
));
MethodHandle
d1
=
dropArguments
(
cat
,
1
,
String
.
class
);
MethodHandle
d1
=
dropArguments
(
cat
,
1
,
String
.
class
);
...
...
test/java/
dyn
/MethodHandlesTest.java
→
test/java/
lang/invoke
/MethodHandlesTest.java
浏览文件 @
33ee9ccf
...
@@ -24,15 +24,15 @@
...
@@ -24,15 +24,15 @@
*/
*/
/* @test
/* @test
* @summary unit tests for java.
dyn
.MethodHandles
* @summary unit tests for java.
lang.invoke
.MethodHandles
* @compile -source 7 -target 7 -XDallowTransitionalJSR292=no MethodHandlesTest.java
* @compile -source 7 -target 7 -XDallowTransitionalJSR292=no MethodHandlesTest.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.
dyn
.MethodHandlesTest
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.
lang.invoke
.MethodHandlesTest
*/
*/
package
test.java.
dyn
;
package
test.java.
lang.invoke
;
import
java.
dyn
.*
;
import
java.
lang.invoke
.*
;
import
java.
dyn
.MethodHandles.Lookup
;
import
java.
lang.invoke
.MethodHandles.Lookup
;
import
java.lang.reflect.*
;
import
java.lang.reflect.*
;
import
java.util.*
;
import
java.util.*
;
import
org.junit.*
;
import
org.junit.*
;
...
@@ -48,7 +48,7 @@ public class MethodHandlesTest {
...
@@ -48,7 +48,7 @@ public class MethodHandlesTest {
// How much output?
// How much output?
static
int
verbosity
=
0
;
static
int
verbosity
=
0
;
static
{
static
{
String
vstr
=
System
.
getProperty
(
"test.java.
dyn
.MethodHandlesTest.verbosity"
);
String
vstr
=
System
.
getProperty
(
"test.java.
lang.invoke
.MethodHandlesTest.verbosity"
);
if
(
vstr
!=
null
)
verbosity
=
Integer
.
parseInt
(
vstr
);
if
(
vstr
!=
null
)
verbosity
=
Integer
.
parseInt
(
vstr
);
}
}
...
@@ -258,7 +258,7 @@ public class MethodHandlesTest {
...
@@ -258,7 +258,7 @@ public class MethodHandlesTest {
if
(
wrap
!=
null
)
{
if
(
wrap
!=
null
)
{
return
wrap
;
return
wrap
;
}
}
// import sun.
dyn
.util.Wrapper;
// import sun.
invoke
.util.Wrapper;
// Wrapper wrap = Wrapper.forBasicType(dst);
// Wrapper wrap = Wrapper.forBasicType(dst);
// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
// if (wrap == Wrapper.OBJECT && Wrapper.isWrapperType(dst))
// wrap = Wrapper.forWrapperType(dst);
// wrap = Wrapper.forWrapperType(dst);
...
@@ -2264,7 +2264,7 @@ public class MethodHandlesTest {
...
@@ -2264,7 +2264,7 @@ public class MethodHandlesTest {
}
}
}
}
}
}
// Local abbreviated copy of sun.
dyn
.util.ValueConversions
// Local abbreviated copy of sun.
invoke
.util.ValueConversions
class
ValueConversions
{
class
ValueConversions
{
private
static
final
Lookup
IMPL_LOOKUP
=
MethodHandles
.
lookup
();
private
static
final
Lookup
IMPL_LOOKUP
=
MethodHandles
.
lookup
();
private
static
final
Object
[]
NO_ARGS_ARRAY
=
{};
private
static
final
Object
[]
NO_ARGS_ARRAY
=
{};
...
...
test/java/
dyn
/MethodTypeTest.java
→
test/java/
lang/invoke
/MethodTypeTest.java
浏览文件 @
33ee9ccf
...
@@ -24,15 +24,14 @@
...
@@ -24,15 +24,14 @@
*/
*/
/* @test
/* @test
* @summary unit tests for java.
dyn
.MethodType
* @summary unit tests for java.
lang.invoke
.MethodType
* @compile MethodTypeTest.java
* @compile MethodTypeTest.java
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.
dyn
.MethodTypeTest
* @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableMethodHandles test.java.
lang.invoke
.MethodTypeTest
*/
*/
package
test.java.
dyn
;
package
test.java.
lang.invoke
;
import
sun.dyn.MemberName
;
import
java.lang.invoke.MethodType
;
import
java.dyn.MethodType
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Method
;
import
java.util.*
;
import
java.util.*
;
...
@@ -163,18 +162,6 @@ public class MethodTypeTest {
...
@@ -163,18 +162,6 @@ public class MethodTypeTest {
assertSame
(
expResult
,
result
);
assertSame
(
expResult
,
result
);
}
}
/**
* Test of make method, of class MethodType.
*/
@Test
public
void
testMake_Method
()
{
System
.
out
.
println
(
"make (via MemberName.getMethodType)"
);
MethodType
expResult
=
MethodType
.
methodType
(
int
.
class
,
String
.
class
);
MemberName
name
=
new
MemberName
(
compareTo
);
MethodType
result
=
name
.
getMethodType
();
assertSame
(
expResult
,
result
);
}
/**
/**
* Test of make method, of class MethodType.
* Test of make method, of class MethodType.
*/
*/
...
@@ -476,10 +463,13 @@ public class MethodTypeTest {
...
@@ -476,10 +463,13 @@ public class MethodTypeTest {
@Test
@Test
public
void
testPortableSerialFormat
()
throws
Throwable
{
public
void
testPortableSerialFormat
()
throws
Throwable
{
System
.
out
.
println
(
"portable serial format"
);
System
.
out
.
println
(
"portable serial format"
);
boolean
generateData
=
false
;
//generateData = true; // set this true to generate the following input data:
Object
[][]
cases
=
{
Object
[][]
cases
=
{
{
mt_vv
,
new
byte
[]
{
// ()void
{
mt_vv
,
new
byte
[]
{
// ()void
(
byte
)
0xac
,
(
byte
)
0xed
,
(
byte
)
0x00
,
(
byte
)
0x05
,
(
byte
)
0x73
,
(
byte
)
0x72
,
(
byte
)
0x00
,
(
byte
)
0x13
,
(
byte
)
0xac
,
(
byte
)
0xed
,
(
byte
)
0x00
,
(
byte
)
0x05
,
(
byte
)
0x73
,
(
byte
)
0x72
,
(
byte
)
0x00
,
(
byte
)
0x1b
,
(
byte
)
0x6a
,
(
byte
)
0x61
,
(
byte
)
0x76
,
(
byte
)
0x61
,
(
byte
)
0x2e
,
(
byte
)
0x64
,
(
byte
)
0x79
,
(
byte
)
0x6e
,
(
byte
)
0x6a
,
(
byte
)
0x61
,
(
byte
)
0x76
,
(
byte
)
0x61
,
(
byte
)
0x2e
,
(
byte
)
0x6c
,
(
byte
)
0x61
,
(
byte
)
0x6e
,
(
byte
)
0x67
,
(
byte
)
0x2e
,
(
byte
)
0x69
,
(
byte
)
0x6e
,
(
byte
)
0x76
,
(
byte
)
0x6f
,
(
byte
)
0x6b
,
(
byte
)
0x65
,
(
byte
)
0x2e
,
(
byte
)
0x4d
,
(
byte
)
0x65
,
(
byte
)
0x74
,
(
byte
)
0x68
,
(
byte
)
0x6f
,
(
byte
)
0x64
,
(
byte
)
0x54
,
(
byte
)
0x2e
,
(
byte
)
0x4d
,
(
byte
)
0x65
,
(
byte
)
0x74
,
(
byte
)
0x68
,
(
byte
)
0x6f
,
(
byte
)
0x64
,
(
byte
)
0x54
,
(
byte
)
0x79
,
(
byte
)
0x70
,
(
byte
)
0x65
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x79
,
(
byte
)
0x70
,
(
byte
)
0x65
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x01
,
(
byte
)
0x24
,
(
byte
)
0x03
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
(
byte
)
0x00
,
(
byte
)
0x01
,
(
byte
)
0x24
,
(
byte
)
0x03
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
...
@@ -493,8 +483,9 @@ public class MethodTypeTest {
...
@@ -493,8 +483,9 @@ public class MethodTypeTest {
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
}
},
}
},
{
mt_OO
,
new
byte
[]
{
// (Object)Object
{
mt_OO
,
new
byte
[]
{
// (Object)Object
(
byte
)
0xac
,
(
byte
)
0xed
,
(
byte
)
0x00
,
(
byte
)
0x05
,
(
byte
)
0x73
,
(
byte
)
0x72
,
(
byte
)
0x00
,
(
byte
)
0x13
,
(
byte
)
0xac
,
(
byte
)
0xed
,
(
byte
)
0x00
,
(
byte
)
0x05
,
(
byte
)
0x73
,
(
byte
)
0x72
,
(
byte
)
0x00
,
(
byte
)
0x1b
,
(
byte
)
0x6a
,
(
byte
)
0x61
,
(
byte
)
0x76
,
(
byte
)
0x61
,
(
byte
)
0x2e
,
(
byte
)
0x64
,
(
byte
)
0x79
,
(
byte
)
0x6e
,
(
byte
)
0x6a
,
(
byte
)
0x61
,
(
byte
)
0x76
,
(
byte
)
0x61
,
(
byte
)
0x2e
,
(
byte
)
0x6c
,
(
byte
)
0x61
,
(
byte
)
0x6e
,
(
byte
)
0x67
,
(
byte
)
0x2e
,
(
byte
)
0x69
,
(
byte
)
0x6e
,
(
byte
)
0x76
,
(
byte
)
0x6f
,
(
byte
)
0x6b
,
(
byte
)
0x65
,
(
byte
)
0x2e
,
(
byte
)
0x4d
,
(
byte
)
0x65
,
(
byte
)
0x74
,
(
byte
)
0x68
,
(
byte
)
0x6f
,
(
byte
)
0x64
,
(
byte
)
0x54
,
(
byte
)
0x2e
,
(
byte
)
0x4d
,
(
byte
)
0x65
,
(
byte
)
0x74
,
(
byte
)
0x68
,
(
byte
)
0x6f
,
(
byte
)
0x64
,
(
byte
)
0x54
,
(
byte
)
0x79
,
(
byte
)
0x70
,
(
byte
)
0x65
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x79
,
(
byte
)
0x70
,
(
byte
)
0x65
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x01
,
(
byte
)
0x24
,
(
byte
)
0x03
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
(
byte
)
0x00
,
(
byte
)
0x01
,
(
byte
)
0x24
,
(
byte
)
0x03
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
...
@@ -509,14 +500,47 @@ public class MethodTypeTest {
...
@@ -509,14 +500,47 @@ public class MethodTypeTest {
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x01
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x01
,
(
byte
)
0x71
,
(
byte
)
0x00
,
(
byte
)
0x7e
,
(
byte
)
0x00
,
(
byte
)
0x03
,
(
byte
)
0x78
,
(
byte
)
0x71
,
(
byte
)
0x00
,
(
byte
)
0x7e
,
(
byte
)
0x00
,
(
byte
)
0x03
,
(
byte
)
0x78
,
}
},
}
},
{
mt_vOiSzA
,
new
byte
[]
{
// (Object,int,String,boolean,Object[])void
(
byte
)
0xac
,
(
byte
)
0xed
,
(
byte
)
0x00
,
(
byte
)
0x05
,
(
byte
)
0x73
,
(
byte
)
0x72
,
(
byte
)
0x00
,
(
byte
)
0x1b
,
(
byte
)
0x6a
,
(
byte
)
0x61
,
(
byte
)
0x76
,
(
byte
)
0x61
,
(
byte
)
0x2e
,
(
byte
)
0x6c
,
(
byte
)
0x61
,
(
byte
)
0x6e
,
(
byte
)
0x67
,
(
byte
)
0x2e
,
(
byte
)
0x69
,
(
byte
)
0x6e
,
(
byte
)
0x76
,
(
byte
)
0x6f
,
(
byte
)
0x6b
,
(
byte
)
0x65
,
(
byte
)
0x2e
,
(
byte
)
0x4d
,
(
byte
)
0x65
,
(
byte
)
0x74
,
(
byte
)
0x68
,
(
byte
)
0x6f
,
(
byte
)
0x64
,
(
byte
)
0x54
,
(
byte
)
0x79
,
(
byte
)
0x70
,
(
byte
)
0x65
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x01
,
(
byte
)
0x24
,
(
byte
)
0x03
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
(
byte
)
0x76
,
(
byte
)
0x72
,
(
byte
)
0x00
,
(
byte
)
0x04
,
(
byte
)
0x76
,
(
byte
)
0x6f
,
(
byte
)
0x69
,
(
byte
)
0x64
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
(
byte
)
0x75
,
(
byte
)
0x72
,
(
byte
)
0x00
,
(
byte
)
0x12
,
(
byte
)
0x5b
,
(
byte
)
0x4c
,
(
byte
)
0x6a
,
(
byte
)
0x61
,
(
byte
)
0x76
,
(
byte
)
0x61
,
(
byte
)
0x2e
,
(
byte
)
0x6c
,
(
byte
)
0x61
,
(
byte
)
0x6e
,
(
byte
)
0x67
,
(
byte
)
0x2e
,
(
byte
)
0x43
,
(
byte
)
0x6c
,
(
byte
)
0x61
,
(
byte
)
0x73
,
(
byte
)
0x73
,
(
byte
)
0x3b
,
(
byte
)
0xab
,
(
byte
)
0x16
,
(
byte
)
0xd7
,
(
byte
)
0xae
,
(
byte
)
0xcb
,
(
byte
)
0xcd
,
(
byte
)
0x5a
,
(
byte
)
0x99
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x05
,
(
byte
)
0x76
,
(
byte
)
0x72
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x6a
,
(
byte
)
0x61
,
(
byte
)
0x76
,
(
byte
)
0x61
,
(
byte
)
0x2e
,
(
byte
)
0x6c
,
(
byte
)
0x61
,
(
byte
)
0x6e
,
(
byte
)
0x67
,
(
byte
)
0x2e
,
(
byte
)
0x4f
,
(
byte
)
0x62
,
(
byte
)
0x6a
,
(
byte
)
0x65
,
(
byte
)
0x63
,
(
byte
)
0x74
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
(
byte
)
0x76
,
(
byte
)
0x72
,
(
byte
)
0x00
,
(
byte
)
0x03
,
(
byte
)
0x69
,
(
byte
)
0x6e
,
(
byte
)
0x74
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
(
byte
)
0x76
,
(
byte
)
0x72
,
(
byte
)
0x00
,
(
byte
)
0x10
,
(
byte
)
0x6a
,
(
byte
)
0x61
,
(
byte
)
0x76
,
(
byte
)
0x61
,
(
byte
)
0x2e
,
(
byte
)
0x6c
,
(
byte
)
0x61
,
(
byte
)
0x6e
,
(
byte
)
0x67
,
(
byte
)
0x2e
,
(
byte
)
0x53
,
(
byte
)
0x74
,
(
byte
)
0x72
,
(
byte
)
0x69
,
(
byte
)
0x6e
,
(
byte
)
0x67
,
(
byte
)
0xa0
,
(
byte
)
0xf0
,
(
byte
)
0xa4
,
(
byte
)
0x38
,
(
byte
)
0x7a
,
(
byte
)
0x3b
,
(
byte
)
0xb3
,
(
byte
)
0x42
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
(
byte
)
0x76
,
(
byte
)
0x72
,
(
byte
)
0x00
,
(
byte
)
0x07
,
(
byte
)
0x62
,
(
byte
)
0x6f
,
(
byte
)
0x6f
,
(
byte
)
0x6c
,
(
byte
)
0x65
,
(
byte
)
0x61
,
(
byte
)
0x6e
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
(
byte
)
0x76
,
(
byte
)
0x72
,
(
byte
)
0x00
,
(
byte
)
0x13
,
(
byte
)
0x5b
,
(
byte
)
0x4c
,
(
byte
)
0x6a
,
(
byte
)
0x61
,
(
byte
)
0x76
,
(
byte
)
0x61
,
(
byte
)
0x2e
,
(
byte
)
0x6c
,
(
byte
)
0x61
,
(
byte
)
0x6e
,
(
byte
)
0x67
,
(
byte
)
0x2e
,
(
byte
)
0x4f
,
(
byte
)
0x62
,
(
byte
)
0x6a
,
(
byte
)
0x65
,
(
byte
)
0x63
,
(
byte
)
0x74
,
(
byte
)
0x3b
,
(
byte
)
0x90
,
(
byte
)
0xce
,
(
byte
)
0x58
,
(
byte
)
0x9f
,
(
byte
)
0x10
,
(
byte
)
0x73
,
(
byte
)
0x29
,
(
byte
)
0x6c
,
(
byte
)
0x02
,
(
byte
)
0x00
,
(
byte
)
0x00
,
(
byte
)
0x78
,
(
byte
)
0x70
,
(
byte
)
0x78
,
}
},
};
};
boolean
generateData
=
false
;
//generateData = true;
for
(
Object
[]
c
:
cases
)
{
for
(
Object
[]
c
:
cases
)
{
MethodType
mt
=
(
MethodType
)
c
[
0
];
MethodType
mt
=
(
MethodType
)
c
[
0
];
System
.
out
.
println
(
"deserialize "
+
mt
);
System
.
out
.
println
(
"deserialize "
+
mt
);
byte
[]
wire
=
(
byte
[])
c
[
1
];
byte
[]
wire
=
(
byte
[])
c
[
1
];
if
(
generateData
)
{
if
(
generateData
)
{
System
.
out
.
println
(
"<generateData>"
);
wire
=
writeSerial
(
mt
);
wire
=
writeSerial
(
mt
);
final
String
INDENT
=
" "
;
final
String
INDENT
=
" "
;
System
.
out
.
print
(
"{ // "
+
mt
);
System
.
out
.
print
(
"{ // "
+
mt
);
...
@@ -528,6 +552,7 @@ public class MethodTypeTest {
...
@@ -528,6 +552,7 @@ public class MethodTypeTest {
}
}
System
.
out
.
println
();
System
.
out
.
println
();
System
.
out
.
println
(
INDENT
+
"}"
);
System
.
out
.
println
(
INDENT
+
"}"
);
System
.
out
.
println
(
"</generateData>"
);
System
.
out
.
flush
();
System
.
out
.
flush
();
}
}
Object
decode
;
Object
decode
;
...
...
test/java/
dyn
/indify/Indify.java
→
test/java/
lang/invoke
/indify/Indify.java
浏览文件 @
33ee9ccf
...
@@ -47,9 +47,9 @@ import java.util.regex.*;
...
@@ -47,9 +47,9 @@ import java.util.regex.*;
* and {@code CONSTANT_MethodType} "ldc" instructions.
* and {@code CONSTANT_MethodType} "ldc" instructions.
* The stereotyped code must create method types by calls to {@code methodType} or
* The stereotyped code must create method types by calls to {@code methodType} or
* {@code fromMethodDescriptorString}. The "lookup" argument must be created
* {@code fromMethodDescriptorString}. The "lookup" argument must be created
* by calls to {@code java.
dyn
.MethodHandles#lookup MethodHandles.lookup}.
* by calls to {@code java.
lang.invoke
.MethodHandles#lookup MethodHandles.lookup}.
* The class and string arguments must be constant.
* The class and string arguments must be constant.
* The following methods of {@code java.
dyn
.MethodHandle.Lookup Lookup} are
* The following methods of {@code java.
lang.invoke
.MethodHandle.Lookup Lookup} are
* allowed for method handle creation: {@code findStatic}, {@code findVirtual},
* allowed for method handle creation: {@code findStatic}, {@code findVirtual},
* {@code findConstructor}, {@code findSpecial},
* {@code findConstructor}, {@code findSpecial},
* {@code findGetter}, {@code findSetter},
* {@code findGetter}, {@code findSetter},
...
@@ -350,10 +350,15 @@ public class Indify {
...
@@ -350,10 +350,15 @@ public class Indify {
}
}
protected
Class
<?>
findClass
(
String
name
)
throws
ClassNotFoundException
{
protected
Class
<?>
findClass
(
String
name
)
throws
ClassNotFoundException
{
try
{
try
{
return
transformAndLoadClass
(
findClassInPath
(
name
));
File
f
=
findClassInPath
(
name
);
if
(
f
!=
null
)
{
Class
<?>
c
=
transformAndLoadClass
(
f
);
if
(
c
!=
null
)
return
c
;
}
}
catch
(
IOException
ex
)
{
}
catch
(
IOException
ex
)
{
throw
new
ClassNotFoundException
(
"IO error"
,
ex
);
throw
new
ClassNotFoundException
(
"IO error"
,
ex
);
}
}
throw
new
ClassNotFoundException
();
}
}
private
Class
<?>
transformAndLoadClass
(
File
f
)
throws
ClassNotFoundException
,
IOException
{
private
Class
<?>
transformAndLoadClass
(
File
f
)
throws
ClassNotFoundException
,
IOException
{
if
(
verbose
)
System
.
err
.
println
(
"Loading class from "
+
f
);
if
(
verbose
)
System
.
err
.
println
(
"Loading class from "
+
f
);
...
@@ -592,7 +597,9 @@ public class Indify {
...
@@ -592,7 +597,9 @@ public class Indify {
if
(
s
.
startsWith
(
"MT_"
))
return
'T'
;
if
(
s
.
startsWith
(
"MT_"
))
return
'T'
;
else
if
(
s
.
startsWith
(
"MH_"
))
return
'H'
;
else
if
(
s
.
startsWith
(
"MH_"
))
return
'H'
;
else
if
(
s
.
startsWith
(
"INDY_"
))
return
'I'
;
else
if
(
s
.
startsWith
(
"INDY_"
))
return
'I'
;
else
if
(
s
.
startsWith
(
"java/dyn/"
))
return
'D'
;
else
if
(
transitionalJSR292
&&
s
.
startsWith
(
"java/dyn/"
))
return
'D'
;
else
if
(
s
.
startsWith
(
"java/lang/invoke/"
))
return
'D'
;
else
if
(
s
.
startsWith
(
"java/lang/"
))
return
'J'
;
else
if
(
s
.
startsWith
(
"java/lang/"
))
return
'J'
;
return
0
;
return
0
;
}
}
...
@@ -605,15 +612,24 @@ public class Indify {
...
@@ -605,15 +612,24 @@ public class Indify {
String
descr
=
cf
.
pool
.
getString
(
CONSTANT_Utf8
,
n2
);
String
descr
=
cf
.
pool
.
getString
(
CONSTANT_Utf8
,
n2
);
String
requiredType
;
String
requiredType
;
switch
(
poolMarks
[(
char
)
n1
])
{
switch
(
poolMarks
[(
char
)
n1
])
{
case
'H'
:
requiredType
=
"()Ljava/
dyn
/MethodHandle;"
;
break
;
case
'H'
:
requiredType
=
"()Ljava/
lang/invoke
/MethodHandle;"
;
break
;
case
'T'
:
requiredType
=
"()Ljava/
dyn
/MethodType;"
;
break
;
case
'T'
:
requiredType
=
"()Ljava/
lang/invoke
/MethodType;"
;
break
;
case
'I'
:
requiredType
=
"()Ljava/
dyn
/MethodHandle;"
;
break
;
case
'I'
:
requiredType
=
"()Ljava/
lang/invoke
/MethodHandle;"
;
break
;
default
:
return
0
;
default
:
return
0
;
}
}
if
(
descr
.
equals
(
requiredType
))
return
mark
;
if
(
matchType
(
descr
,
requiredType
))
return
mark
;
return
0
;
return
0
;
}
}
boolean
matchType
(
String
descr
,
String
requiredType
)
{
if
(
descr
.
equals
(
requiredType
))
return
true
;
if
(
transitionalJSR292
)
{
String
oldType
=
requiredType
.
replace
(
"Ljava/lang/invoke/"
,
"Ljava/dyn/"
);
if
(
descr
.
equals
(
oldType
))
return
true
;
}
return
false
;
}
private
class
JVMState
{
private
class
JVMState
{
final
List
<
Object
>
stack
=
new
ArrayList
<>();
final
List
<
Object
>
stack
=
new
ArrayList
<>();
int
sp
()
{
return
stack
.
size
();
}
int
sp
()
{
return
stack
.
size
();
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录