8008085: Integrate Dynalink source code into Nashorn codebase
Reviewed-by: jlaskey, lagergren, sundar
This commit is contained in:
parent
7c466c84eb
commit
82f8cef55c
@ -67,3 +67,34 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
--- end of LICENSE ---
|
||||
|
||||
%% This notice is provided with respect to Dynalink library which is included
|
||||
with the Nashorn technology.
|
||||
|
||||
--- begin of LICENSE ---
|
||||
Copyright (c) 2009-2013, Attila Szegedi
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
--- end of LICENSE ---
|
||||
|
@ -54,19 +54,11 @@
|
||||
|
||||
<target name="clean" depends="init, clean-nasgen">
|
||||
<delete includeemptydirs="true">
|
||||
<fileset dir="${build.dir}" excludes="${dynalink.dir.name}/**/*" erroronmissingdir="false"/>
|
||||
<fileset dir="${build.dir}" erroronmissingdir="false"/>
|
||||
</delete>
|
||||
<delete dir="${dist.dir}"/>
|
||||
</target>
|
||||
|
||||
<target name="clean-dynalink">
|
||||
<delete dir="${dynalink.dir}"/>
|
||||
</target>
|
||||
|
||||
<target name="clean-all" depends="clean-dynalink, clean">
|
||||
<delete dir="${build.dir}"/>
|
||||
</target>
|
||||
|
||||
<!-- do it only if ASM is not available -->
|
||||
<target name="compile-asm" depends="prepare" unless="asm.available">
|
||||
<javac srcdir="${jdk.asm.src.dir}"
|
||||
@ -79,29 +71,7 @@
|
||||
includeantruntime="false"/>
|
||||
</target>
|
||||
|
||||
<target name="check-dynalink-uptodate" depends="init">
|
||||
<property name="versioned.dynalink.jar" value="${dynalink.dir}/dynalink-${dynalink.jar.version}.jar"/>
|
||||
<condition property="dynalink.uptodate">
|
||||
<and>
|
||||
<available file="${versioned.dynalink.jar}"/>
|
||||
<filesmatch file1="${versioned.dynalink.jar}" file2="${dynalink.jar}"/>
|
||||
</and>
|
||||
</condition>
|
||||
</target>
|
||||
|
||||
<target name="get-dynalink" depends="check-dynalink-uptodate" unless="dynalink.uptodate">
|
||||
<mkdir dir="${dynalink.dir}"/>
|
||||
<!-- Delete previous snapshots, if any -->
|
||||
<delete>
|
||||
<fileset dir="${dynalink.dir}" includes="*"/>
|
||||
</delete>
|
||||
<property name="dynalink.download.base.url" value="http://oss.sonatype.org/content/repositories/${dynalink.version.type}s/org/dynalang/dynalink/${dynalink.version}/dynalink-${dynalink.jar.version}"/>
|
||||
<get src="${dynalink.download.base.url}.jar" dest="${versioned.dynalink.jar}" usetimestamp="true"/>
|
||||
<get src="${dynalink.download.base.url}-sources.jar" dest="${dynalink.dir}/dynalink-sources.jar" usetimestamp="true"/>
|
||||
<copy file="${versioned.dynalink.jar}" tofile="${dynalink.jar}" overwrite="true"/>
|
||||
</target>
|
||||
|
||||
<target name="compile" depends="compile-asm, get-dynalink" description="Compiles nashorn">
|
||||
<target name="compile" depends="compile-asm" description="Compiles nashorn">
|
||||
<javac srcdir="${src.dir}"
|
||||
destdir="${build.classes.dir}"
|
||||
classpath="${javac.classpath}"
|
||||
@ -126,6 +96,8 @@
|
||||
<copy todir="${build.classes.dir}/jdk/nashorn/tools/resources">
|
||||
<fileset dir="${src.dir}/jdk/nashorn/tools/resources/"/>
|
||||
</copy>
|
||||
<copy file="${src.dir}/jdk/internal/dynalink/support/messages.properties" todir="${build.classes.dir}/jdk/internal/dynalink/support"/>
|
||||
|
||||
<echo message="full=${nashorn.fullversion}" file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties"/>
|
||||
<echo file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties" append="true">${line.separator}</echo>
|
||||
<echo message="release=${nashorn.version}" file="${build.classes.dir}/jdk/nashorn/internal/runtime/resources/version.properties" append="true"/>
|
||||
@ -134,7 +106,6 @@
|
||||
<target name="jar" depends="compile, run-nasgen" description="Creates nashorn.jar">
|
||||
<jar jarfile="${dist.jar}" manifest="${meta.inf.dir}/MANIFEST.MF" index="true" filesetmanifest="merge">
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
<zipfileset src="${dynalink.jar}"/>
|
||||
<manifest>
|
||||
<attribute name="Archiver-Version" value="n/a"/>
|
||||
<attribute name="Build-Jdk" value="${java.runtime.version}"/>
|
||||
@ -152,12 +123,10 @@
|
||||
<javadoc destdir="${dist.javadoc.dir}" use="yes" overview="src/overview.html" windowtitle="${nashorn.product.name} ${nashorn.version}" additionalparam="-quiet" failonerror="true">
|
||||
<classpath>
|
||||
<pathelement location="${build.classes.dir}"/>
|
||||
<pathelement location="${dynalink.jar}"/>
|
||||
</classpath>
|
||||
<fileset dir="${src.dir}" includes="**/*.java"/>
|
||||
<fileset dir="${jdk.asm.src.dir}" includes="**/*.java"/>
|
||||
<link href="http://docs.oracle.com/javase/7/docs/api/"/>
|
||||
<link href="http://szegedi.github.com/dynalink/0.4/javadoc/"/>
|
||||
<!-- The following tags are used only in ASM sources - just ignore these -->
|
||||
<tag name="label" description="label tag in ASM sources" enabled="false"/>
|
||||
<tag name="linked" description="linked tag in ASM sources" enabled="false"/>
|
||||
|
@ -164,7 +164,6 @@
|
||||
</compilation-unit>
|
||||
<compilation-unit>
|
||||
<package-root>../src</package-root>
|
||||
<classpath mode="compile">../build/dynalink/dynalink.jar</classpath>
|
||||
<source-level>1.7</source-level>
|
||||
</compilation-unit>
|
||||
<compilation-unit>
|
||||
|
@ -87,23 +87,10 @@ testng.listeners=\
|
||||
org.testng.reporters.EmailableReporter, \
|
||||
jdk.nashorn.internal.test.framework.JSJUnitReportReporter
|
||||
|
||||
# Define the version of Dynalink that is used. Version types are either
|
||||
# 'snapshot' or 'release'. When it is 'snapshot', the version must have
|
||||
# "-SNAPSHOT" suffix and the jar version will have a timestamp in it. When
|
||||
# it's 'release', the version has no suffix, and the jar version is
|
||||
# identical to version - fun with Maven central.
|
||||
dynalink.version=0.5-SNAPSHOT
|
||||
dynalink.version.type=snapshot
|
||||
dynalink.jar.version=0.5-20130109.113843-12
|
||||
dynalink.dir.name=dynalink
|
||||
dynalink.dir=build/${dynalink.dir.name}
|
||||
dynalink.jar=${dynalink.dir}/dynalink.jar
|
||||
|
||||
javac.debug=true
|
||||
javac.encoding=ascii
|
||||
javac.classpath=\
|
||||
${build.classes.dir}:\
|
||||
${dynalink.jar}
|
||||
${build.classes.dir}
|
||||
javac.test.classpath=\
|
||||
${build.classes.dir}:\
|
||||
${build.test.classes.dir}:\
|
||||
|
175
nashorn/src/jdk/internal/dynalink/CallSiteDescriptor.java
Normal file
175
nashorn/src/jdk/internal/dynalink/CallSiteDescriptor.java
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink;
|
||||
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
|
||||
|
||||
|
||||
/**
|
||||
* An immutable descriptor of a call site. It is an immutable object that contains all the information about a call
|
||||
* site: the class performing the lookups, the name of the method being invoked, and the method signature. The library
|
||||
* has a default {@link CallSiteDescriptorFactory} for descriptors that you can use, or you can create your own
|
||||
* descriptor classes, especially if you need to add further information (values passed in additional parameters to the
|
||||
* bootstrap method) to them. Call site descriptors are used in this library in place of passing a real call site to
|
||||
* guarding linkers so they aren't tempted to directly manipulate the call sites. The constructors of built-in
|
||||
* {@link RelinkableCallSite} implementations all need a call site descriptor. Even if you create your own call site
|
||||
* descriptors consider using {@link CallSiteDescriptorFactory#tokenizeName(String)} in your implementation.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public interface CallSiteDescriptor {
|
||||
/**
|
||||
* The index of the name token that will carry the operation scheme prefix (usually, "dyn").
|
||||
*/
|
||||
public static final int SCHEME = 0;
|
||||
/**
|
||||
* The index of the name token that will usually carry the operation name.
|
||||
*/
|
||||
|
||||
public static final int OPERATOR=1;
|
||||
/**
|
||||
* The index of the name token that will usually carry a name of an operand (of a property, method, etc.)
|
||||
*/
|
||||
|
||||
public static final int NAME_OPERAND=2;
|
||||
|
||||
/**
|
||||
* Character used to delimit tokens in an call site name.
|
||||
*/
|
||||
public static final String TOKEN_DELIMITER = ":";
|
||||
|
||||
/**
|
||||
* Character used to delimit operation names in a composite operation specification.
|
||||
*/
|
||||
public static final String OPERATOR_DELIMITER = "|";
|
||||
|
||||
/**
|
||||
* Returns the number of tokens in the name of the method at the call site. Method names are tokenized with the
|
||||
* colon ":" character, i.e. "dyn:getProp:color" would be the name used to describe a method that retrieves the
|
||||
* property named "color" on the object it is invoked on.
|
||||
* @return the number of tokens in the name of the method at the call site.
|
||||
*/
|
||||
public int getNameTokenCount();
|
||||
|
||||
/**
|
||||
* Returns the <i>i<sup>th</sup></i> token in the method name at the call site. Method names are tokenized with the
|
||||
* colon ":" character.
|
||||
* @param i the index of the token. Must be between 0 (inclusive) and {@link #getNameTokenCount()} (exclusive)
|
||||
* @throws IllegalArgumentException if the index is outside the allowed range.
|
||||
* @return the <i>i<sup>th</sup></i> token in the method name at the call site. The returned strings are interned.
|
||||
*/
|
||||
public String getNameToken(int i);
|
||||
|
||||
/**
|
||||
* Returns the name of the method at the call site. Note that the object internally only stores the tokenized name,
|
||||
* and has to reconstruct the full name from tokens on each invocation.
|
||||
* @return the name of the method at the call site.
|
||||
*/
|
||||
public String getName();
|
||||
|
||||
/**
|
||||
* The type of the method at the call site.
|
||||
*
|
||||
* @return type of the method at the call site.
|
||||
*/
|
||||
public MethodType getMethodType();
|
||||
|
||||
/**
|
||||
* Returns the lookup passed to the bootstrap method.
|
||||
* @return the lookup passed to the bootstrap method.
|
||||
*/
|
||||
public Lookup getLookup();
|
||||
|
||||
/**
|
||||
* Creates a new call site descriptor from this descriptor, which is identical to this, except it changes the method
|
||||
* type.
|
||||
*
|
||||
* @param newMethodType the new method type
|
||||
* @return a new call site descriptor, with the method type changed.
|
||||
*/
|
||||
public CallSiteDescriptor changeMethodType(MethodType newMethodType);
|
||||
|
||||
}
|
212
nashorn/src/jdk/internal/dynalink/ChainedCallSite.java
Normal file
212
nashorn/src/jdk/internal/dynalink/ChainedCallSite.java
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.support.AbstractRelinkableCallSite;
|
||||
|
||||
|
||||
/**
|
||||
* A relinkable call site that maintains a chain of linked method handles. In the default implementation, up to 8 method
|
||||
* handles can be chained, cascading from one to the other through
|
||||
* {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. When this call site has to link a new
|
||||
* method handle and the length of the chain is already at the maximum, it will throw away the oldest method handle.
|
||||
* Switchpoint-invalidated handles in the chain are removed eagerly (on each linking request, and whenever a
|
||||
* switchpoint-invalidated method handle is traversed during invocation). There is currently no profiling
|
||||
* attached to the handles in the chain, so they are never reordered based on usage; the most recently linked method
|
||||
* handle is always at the start of the chain.
|
||||
*/
|
||||
public class ChainedCallSite extends AbstractRelinkableCallSite {
|
||||
private final AtomicReference<LinkedList<GuardedInvocation>> invocations = new AtomicReference<>();
|
||||
|
||||
/**
|
||||
* Creates a new chained call site.
|
||||
* @param descriptor the descriptor for the call site.
|
||||
*/
|
||||
public ChainedCallSite(CallSiteDescriptor descriptor) {
|
||||
super(descriptor);
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum number of method handles in the chain. Defaults to 8. You can override it in a subclass if you need
|
||||
* to change the value. If your override returns a value less than 1, the code will break.
|
||||
* @return the maximum number of method handles in the chain.
|
||||
*/
|
||||
@SuppressWarnings("static-method")
|
||||
protected int getMaxChainLength() {
|
||||
return 8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relink(GuardedInvocation guardedInvocation, MethodHandle fallback) {
|
||||
relinkInternal(guardedInvocation, fallback, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle fallback) {
|
||||
relinkInternal(guardedInvocation, fallback, true);
|
||||
}
|
||||
|
||||
private MethodHandle relinkInternal(GuardedInvocation invocation, MethodHandle relink, boolean reset) {
|
||||
final LinkedList<GuardedInvocation> currentInvocations = invocations.get();
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
final LinkedList<GuardedInvocation> newInvocations =
|
||||
currentInvocations == null || reset ? new LinkedList<>() : (LinkedList)currentInvocations.clone();
|
||||
|
||||
// First, prune the chain of invalidated switchpoints.
|
||||
for(Iterator<GuardedInvocation> it = newInvocations.iterator(); it.hasNext();) {
|
||||
if(it.next().hasBeenInvalidated()) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// prune() is allowed to invoke this method with invocation == null meaning we're just pruning the chain and not
|
||||
// adding any new invocations to it.
|
||||
if(invocation != null) {
|
||||
// Remove oldest entry if we're at max length
|
||||
if(newInvocations.size() == getMaxChainLength()) {
|
||||
newInvocations.removeFirst();
|
||||
}
|
||||
newInvocations.addLast(invocation);
|
||||
}
|
||||
|
||||
// prune-and-invoke is used as the fallback for invalidated switchpoints. If a switchpoint gets invalidated, we
|
||||
// rebuild the chain and get rid of all invalidated switchpoints instead of letting them linger.
|
||||
final MethodHandle pruneAndInvoke = makePruneAndInvokeMethod(relink);
|
||||
|
||||
// Fold the new chain
|
||||
MethodHandle target = relink;
|
||||
for(GuardedInvocation inv: newInvocations) {
|
||||
target = inv.compose(pruneAndInvoke, target);
|
||||
}
|
||||
|
||||
// If nobody else updated the call site while we were rebuilding the chain, set the target to our chain. In case
|
||||
// we lost the race for multithreaded update, just do nothing. Either the other thread installed the same thing
|
||||
// we wanted to install, or otherwise, we'll be asked to relink again.
|
||||
if(invocations.compareAndSet(currentInvocations, newInvocations)) {
|
||||
setTarget(target);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a method that rebuilds our call chain, pruning it of any invalidated switchpoints, and then invokes that
|
||||
* chain.
|
||||
* @param relink the ultimate fallback for the chain (the {@code DynamicLinker}'s relink).
|
||||
* @return a method handle for prune-and-invoke
|
||||
*/
|
||||
private MethodHandle makePruneAndInvokeMethod(MethodHandle relink) {
|
||||
// Bind prune to (this, relink)
|
||||
final MethodHandle boundPrune = MethodHandles.insertArguments(PRUNE, 0, this, relink);
|
||||
// Make it ignore all incoming arguments
|
||||
final MethodHandle ignoreArgsPrune = MethodHandles.dropArguments(boundPrune, 0, type().parameterList());
|
||||
// Invoke prune, then invoke the call site target with original arguments
|
||||
return MethodHandles.foldArguments(MethodHandles.exactInvoker(type()), ignoreArgsPrune);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private MethodHandle prune(MethodHandle relink) {
|
||||
return relinkInternal(null, relink, false);
|
||||
}
|
||||
|
||||
private static final MethodHandle PRUNE;
|
||||
static {
|
||||
try {
|
||||
PRUNE = MethodHandles.lookup().findSpecial(ChainedCallSite.class, "prune", MethodType.methodType(
|
||||
MethodHandle.class, MethodHandle.class), ChainedCallSite.class);
|
||||
// NOTE: using two catch blocks so we don't introduce a reference to 1.7 ReflectiveOperationException, allowing
|
||||
// Dynalink to be used on 1.6 JVMs with Remi's backport library.
|
||||
} catch(IllegalAccessException e) {
|
||||
throw new AssertionError(e.getMessage(), e); // Can not happen
|
||||
} catch(NoSuchMethodException e) {
|
||||
throw new AssertionError(e.getMessage(), e); // Can not happen
|
||||
}
|
||||
}
|
||||
}
|
144
nashorn/src/jdk/internal/dynalink/DefaultBootstrapper.java
Normal file
144
nashorn/src/jdk/internal/dynalink/DefaultBootstrapper.java
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink;
|
||||
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
|
||||
|
||||
|
||||
/**
|
||||
* A convenience default bootstrapper that exposes static bootstrap methods which language runtimes that need the very
|
||||
* default behavior can use with minimal setup. When first referenced, it will create a dynamic linker with default
|
||||
* settings for the {@link DynamicLinkerFactory}, and its bootstrap methods will create {@link MonomorphicCallSite} for
|
||||
* all call sites. It has two bootstrap methods: one creates call sites that use the
|
||||
* {@link MethodHandles#publicLookup()} as the lookup for all call sites and disregard the one passed in as the caller,
|
||||
* and one that just uses the passed caller as the lookup scope. Using the public lookup one is advised if your language
|
||||
* runtime has no concept of interacting with Java visibility scopes, as it results in a more lightweight runtime
|
||||
* information.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class DefaultBootstrapper {
|
||||
private static final DynamicLinker dynamicLinker = new DynamicLinkerFactory().createLinker();
|
||||
|
||||
private DefaultBootstrapper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method as your bootstrap method (see the documentation of the java.lang.invoke package for how to do
|
||||
* this). In case your language runtime doesn't have a concept of interaction with Java access scopes, you might
|
||||
* want to consider using
|
||||
* {@link #publicBootstrap(java.lang.invoke.MethodHandles.Lookup, String, MethodType)} instead.
|
||||
*
|
||||
* @param caller the caller's lookup
|
||||
* @param name the name of the method at the call site
|
||||
* @param type the method signature at the call site
|
||||
* @return a new {@link MonomorphicCallSite} linked with the default dynamic linker.
|
||||
*/
|
||||
public static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) {
|
||||
return bootstrapInternal(caller, name, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this method as your bootstrap method (see the documentation of the java.lang.invoke package for how to do
|
||||
* this) when your language runtime doesn't have a concept of interaction with Java access scopes. If you need to
|
||||
* preserve the different caller Lookup objects in the call sites, use
|
||||
* {@link #bootstrap(java.lang.invoke.MethodHandles.Lookup, String, MethodType)} instead
|
||||
*
|
||||
* @param caller the caller's lookup. It is ignored as the call sites will be created with
|
||||
* {@link MethodHandles#publicLookup()} instead.
|
||||
* @param name the name of the method at the call site
|
||||
* @param type the method signature at the call site
|
||||
* @return a new {@link MonomorphicCallSite} linked with the default dynamic linker.
|
||||
*/
|
||||
public static CallSite publicBootstrap(@SuppressWarnings("unused") MethodHandles.Lookup caller, String name, MethodType type) {
|
||||
return bootstrapInternal(MethodHandles.publicLookup(), name, type);
|
||||
}
|
||||
|
||||
private static CallSite bootstrapInternal(MethodHandles.Lookup caller, String name, MethodType type) {
|
||||
return dynamicLinker.link(new MonomorphicCallSite(CallSiteDescriptorFactory.create(caller, name, type)));
|
||||
}
|
||||
}
|
281
nashorn/src/jdk/internal/dynalink/DynamicLinker.java
Normal file
281
nashorn/src/jdk/internal/dynalink/DynamicLinker.java
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.MutableCallSite;
|
||||
import java.util.List;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
|
||||
import jdk.internal.dynalink.support.LinkRequestImpl;
|
||||
import jdk.internal.dynalink.support.Lookup;
|
||||
import jdk.internal.dynalink.support.RuntimeContextLinkRequestImpl;
|
||||
|
||||
|
||||
/**
|
||||
* The linker for {@link RelinkableCallSite} objects. Users of it (scripting frameworks and language runtimes) have to
|
||||
* create a linker using the {@link DynamicLinkerFactory} and invoke its link method from the invokedynamic bootstrap
|
||||
* methods to set the target of all the call sites in the code they generate. Usual usage would be to create one class
|
||||
* per language runtime to contain one linker instance as:
|
||||
*
|
||||
* <pre>
|
||||
* class MyLanguageRuntime {
|
||||
* private static final GuardingDynamicLinker myLanguageLinker = new MyLanguageLinker();
|
||||
* private static final DynamicLinker dynamicLinker = createDynamicLinker();
|
||||
*
|
||||
* private static DynamicLinker createDynamicLinker() {
|
||||
* final DynamicLinkerFactory factory = new DynamicLinkerFactory();
|
||||
* factory.setPrioritizedLinker(myLanguageLinker);
|
||||
* return factory.createLinker();
|
||||
* }
|
||||
*
|
||||
* public static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) {
|
||||
* return dynamicLinker.link(new MonomorphicCallSite(CallSiteDescriptorFactory.create(lookup, name, type)));
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* Note how there are three components you will need to provide here:
|
||||
* <ul>
|
||||
* <li>You're expected to provide a {@link GuardingDynamicLinker} for your own language. If your runtime doesn't
|
||||
* have its own language and/or object model (i.e. it's a generic scripting shell), you don't need to implement a
|
||||
* dynamic linker; you would simply not invoke the {@code setPrioritizedLinker} method on the factory, or even better,
|
||||
* simply use {@link DefaultBootstrapper}.</li>
|
||||
* <li>The performance of the programs can depend on your choice of the class to represent call sites. The above
|
||||
* example used {@link MonomorphicCallSite}, but you might want to use {@link ChainedCallSite} instead. You'll need to
|
||||
* experiment and decide what fits your language runtime the best. You can subclass either of these or roll your own if
|
||||
* you need to.</li>
|
||||
* <li>You also need to provide {@link CallSiteDescriptor}s to your call sites. They are immutable objects that contain
|
||||
* all the information about the call site: the class performing the lookups, the name of the method being invoked, and
|
||||
* the method signature. The library has a default {@link CallSiteDescriptorFactory} for descriptors that you can use,
|
||||
* or you can create your own descriptor classes, especially if you need to add further information (values passed in
|
||||
* additional parameters to the bootstrap method) to them.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class DynamicLinker {
|
||||
|
||||
private static final String CLASS_NAME = DynamicLinker.class.getName();
|
||||
private static final String RELINK_METHOD_NAME = "relink";
|
||||
|
||||
private final LinkerServices linkerServices;
|
||||
private final int runtimeContextArgCount;
|
||||
private final boolean syncOnRelink;
|
||||
private final int unstableRelinkThreshold;
|
||||
|
||||
/**
|
||||
* Creates a new dynamic linker.
|
||||
*
|
||||
* @param linkerServices the linkerServices used by the linker, created by the factory.
|
||||
* @param runtimeContextArgCount see {@link DynamicLinkerFactory#setRuntimeContextArgCount(int)}
|
||||
*/
|
||||
DynamicLinker(LinkerServices linkerServices, int runtimeContextArgCount, boolean syncOnRelink,
|
||||
int unstableRelinkThreshold) {
|
||||
if(runtimeContextArgCount < 0) {
|
||||
throw new IllegalArgumentException("runtimeContextArgCount < 0");
|
||||
}
|
||||
if(unstableRelinkThreshold < 0) {
|
||||
throw new IllegalArgumentException("unstableRelinkThreshold < 0");
|
||||
}
|
||||
this.runtimeContextArgCount = runtimeContextArgCount;
|
||||
this.linkerServices = linkerServices;
|
||||
this.syncOnRelink = syncOnRelink;
|
||||
this.unstableRelinkThreshold = unstableRelinkThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Links an invokedynamic call site. It will install a method handle into the call site that invokes the relinking
|
||||
* mechanism of this linker. Next time the call site is invoked, it will be linked for the actual arguments it was
|
||||
* invoked with.
|
||||
*
|
||||
* @param callSite the call site to link.
|
||||
* @return the callSite, for easy call chaining.
|
||||
*/
|
||||
public <T extends RelinkableCallSite> T link(final T callSite) {
|
||||
callSite.initialize(createRelinkAndInvokeMethod(callSite, 0));
|
||||
return callSite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object representing the lower level linker services of this class that are normally exposed to
|
||||
* individual language-specific linkers. While as a user of this class you normally only care about the
|
||||
* {@link #link(RelinkableCallSite)} method, in certain circumstances you might want to use the lower level services
|
||||
* directly; either to lookup specific method handles, to access the type converters, and so on.
|
||||
* @return the object representing the linker services of this class.
|
||||
*/
|
||||
public LinkerServices getLinkerServices() {
|
||||
return linkerServices;
|
||||
}
|
||||
|
||||
private static final MethodHandle RELINK = Lookup.findOwnSpecial(MethodHandles.lookup(), RELINK_METHOD_NAME,
|
||||
MethodHandle.class, RelinkableCallSite.class, int.class, Object[].class);
|
||||
|
||||
private MethodHandle createRelinkAndInvokeMethod(final RelinkableCallSite callSite, int relinkCount) {
|
||||
// Make a bound MH of invoke() for this linker and call site
|
||||
final MethodHandle boundRelinker = MethodHandles.insertArguments(RELINK, 0, this, callSite, Integer.valueOf(
|
||||
relinkCount));
|
||||
// Make a MH that gathers all arguments to the invocation into an Object[]
|
||||
final MethodType type = callSite.getDescriptor().getMethodType();
|
||||
final MethodHandle collectingRelinker = boundRelinker.asCollector(Object[].class, type.parameterCount());
|
||||
return MethodHandles.foldArguments(MethodHandles.exactInvoker(type), collectingRelinker.asType(
|
||||
type.changeReturnType(MethodHandle.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Relinks a call site conforming to the invocation arguments.
|
||||
*
|
||||
* @param callSite the call site itself
|
||||
* @param arguments arguments to the invocation
|
||||
* @return return the method handle for the invocation
|
||||
* @throws Exception rethrows any exception thrown by the linkers
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private MethodHandle relink(RelinkableCallSite callSite, int relinkCount, Object... arguments) throws Exception {
|
||||
final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor();
|
||||
final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0;
|
||||
final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold;
|
||||
final LinkRequest linkRequest =
|
||||
runtimeContextArgCount == 0 ? new LinkRequestImpl(callSiteDescriptor, callSiteUnstable, arguments)
|
||||
: new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSiteUnstable, arguments,
|
||||
runtimeContextArgCount);
|
||||
|
||||
// Find a suitable method handle with a guard
|
||||
GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest);
|
||||
|
||||
// None found - throw an exception
|
||||
if(guardedInvocation == null) {
|
||||
throw new NoSuchDynamicMethodException(callSiteDescriptor.toString());
|
||||
}
|
||||
|
||||
// If our call sites have a runtime context, and the linker produced a context-stripped invocation, adapt the
|
||||
// produced invocation into contextual invocation (by dropping the context...)
|
||||
if(runtimeContextArgCount > 0) {
|
||||
final MethodType origType = callSiteDescriptor.getMethodType();
|
||||
final MethodHandle invocation = guardedInvocation.getInvocation();
|
||||
if(invocation.type().parameterCount() == origType.parameterCount() - runtimeContextArgCount) {
|
||||
final List<Class<?>> prefix = origType.parameterList().subList(1, runtimeContextArgCount + 1);
|
||||
final MethodHandle guard = guardedInvocation.getGuard();
|
||||
guardedInvocation = guardedInvocation.dropArguments(1, prefix);
|
||||
}
|
||||
}
|
||||
|
||||
if(unstableDetectionEnabled && relinkCount <= unstableRelinkThreshold && relinkCount++ == unstableRelinkThreshold) {
|
||||
// Note that we'll increase the relinkCount until threshold+1 and not increase it beyond that. Threshold+1
|
||||
// is treated as a special value to signal that resetAndRelink has already executed once for the unstable
|
||||
// call site; we only want the call site to throw away its current linkage once, when it transitions to
|
||||
// unstable.
|
||||
callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, relinkCount));
|
||||
} else {
|
||||
callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, relinkCount));
|
||||
}
|
||||
if(syncOnRelink) {
|
||||
MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });
|
||||
}
|
||||
return guardedInvocation.getInvocation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stack trace element describing the location of the call site currently being relinked on the current
|
||||
* thread. The operation internally creates a Throwable object and inspects its stack trace, so it's potentially
|
||||
* expensive. The recommended usage for it is in writing diagnostics code.
|
||||
* @return a stack trace element describing the location of the call site currently being relinked, or null if it is
|
||||
* not invoked while a call site is being relinked.
|
||||
*/
|
||||
public static StackTraceElement getRelinkedCallSiteLocation() {
|
||||
final StackTraceElement[] trace = new Throwable().getStackTrace();
|
||||
for(int i = 0; i < trace.length - 1; ++i) {
|
||||
final StackTraceElement frame = trace[i];
|
||||
if(RELINK_METHOD_NAME.equals(frame.getMethodName()) && CLASS_NAME.equals(frame.getClassName())) {
|
||||
return trace[i + 1];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
311
nashorn/src/jdk/internal/dynalink/DynamicLinkerFactory.java
Normal file
311
nashorn/src/jdk/internal/dynalink/DynamicLinkerFactory.java
Normal file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink;
|
||||
|
||||
import java.lang.invoke.MutableCallSite;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import jdk.internal.dynalink.beans.BeansLinker;
|
||||
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.support.AutoDiscovery;
|
||||
import jdk.internal.dynalink.support.BottomGuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.support.CompositeGuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.support.CompositeTypeBasedGuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.support.LinkerServicesImpl;
|
||||
import jdk.internal.dynalink.support.TypeConverterFactory;
|
||||
|
||||
|
||||
/**
|
||||
* A factory class for creating {@link DynamicLinker}s. The most usual dynamic linker is a linker that is a composition
|
||||
* of all {@link GuardingDynamicLinker}s known and pre-created by the caller as well as any
|
||||
* {@link AutoDiscovery automatically discovered} guarding linkers and the standard fallback {@link BeansLinker}. See
|
||||
* {@link DynamicLinker} documentation for tips on how to use this class.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class DynamicLinkerFactory {
|
||||
|
||||
/**
|
||||
* Default value for {@link #setUnstableRelinkThreshold(int) unstable relink threshold}.
|
||||
*/
|
||||
public static final int DEFAULT_UNSTABLE_RELINK_THRESHOLD = 8;
|
||||
|
||||
private ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
private List<? extends GuardingDynamicLinker> prioritizedLinkers;
|
||||
private List<? extends GuardingDynamicLinker> fallbackLinkers;
|
||||
private int runtimeContextArgCount = 0;
|
||||
private boolean syncOnRelink = false;
|
||||
private int unstableRelinkThreshold = DEFAULT_UNSTABLE_RELINK_THRESHOLD;
|
||||
|
||||
/**
|
||||
* Sets the class loader for automatic discovery of available linkers. If not set explicitly, then the thread
|
||||
* context class loader at the time of the constructor invocation will be used.
|
||||
*
|
||||
* @param classLoader the class loader used for the autodiscovery of available linkers.
|
||||
*/
|
||||
public void setClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the prioritized linkers. Language runtimes using this framework will usually precreate at least the linker
|
||||
* for their own language. These linkers will be consulted first in the resulting dynamic linker, before any
|
||||
* autodiscovered linkers. If the framework also autodiscovers a linker of the same class as one of the prioritized
|
||||
* linkers, it will be ignored and the explicit prioritized instance will be used.
|
||||
*
|
||||
* @param prioritizedLinkers the list of prioritized linkers. Null can be passed to indicate no prioritized linkers
|
||||
* (this is also the default value).
|
||||
*/
|
||||
public void setPrioritizedLinkers(List<? extends GuardingDynamicLinker> prioritizedLinkers) {
|
||||
this.prioritizedLinkers =
|
||||
prioritizedLinkers == null ? null : new ArrayList<>(prioritizedLinkers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the prioritized linkers. Language runtimes using this framework will usually precreate at least the linker
|
||||
* for their own language. These linkers will be consulted first in the resulting dynamic linker, before any
|
||||
* autodiscovered linkers. If the framework also autodiscovers a linker of the same class as one of the prioritized
|
||||
* linkers, it will be ignored and the explicit prioritized instance will be used.
|
||||
*
|
||||
* @param prioritizedLinkers a list of prioritized linkers.
|
||||
*/
|
||||
public void setPrioritizedLinkers(GuardingDynamicLinker... prioritizedLinkers) {
|
||||
setPrioritizedLinkers(Arrays.asList(prioritizedLinkers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a single prioritized linker. Identical to calling {@link #setPrioritizedLinkers(List)} with a single-element
|
||||
* list.
|
||||
*
|
||||
* @param prioritizedLinker the single prioritized linker. Must not be null.
|
||||
* @throws IllegalArgumentException if null is passed.
|
||||
*/
|
||||
public void setPrioritizedLinker(GuardingDynamicLinker prioritizedLinker) {
|
||||
if(prioritizedLinker == null) {
|
||||
throw new IllegalArgumentException("prioritizedLinker == null");
|
||||
}
|
||||
this.prioritizedLinkers = Collections.singletonList(prioritizedLinker);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fallback linkers. These linkers will be consulted last in the resulting composite linker, after any
|
||||
* autodiscovered linkers. If the framework also autodiscovers a linker of the same class as one of the fallback
|
||||
* linkers, it will be ignored and the explicit fallback instance will be used.
|
||||
*
|
||||
* @param fallbackLinkers the list of fallback linkers. Can be empty to indicate the caller wishes to set no
|
||||
* fallback linkers.
|
||||
*/
|
||||
public void setFallbackLinkers(List<? extends GuardingDynamicLinker> fallbackLinkers) {
|
||||
this.fallbackLinkers = fallbackLinkers == null ? null : new ArrayList<>(fallbackLinkers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the fallback linkers. These linkers will be consulted last in the resulting composite linker, after any
|
||||
* autodiscovered linkers. If the framework also autodiscovers a linker of the same class as one of the fallback
|
||||
* linkers, it will be ignored and the explicit fallback instance will be used.
|
||||
*
|
||||
* @param fallbackLinkers the list of fallback linkers. Can be empty to indicate the caller wishes to set no
|
||||
* fallback linkers. If it is left as null, the standard fallback {@link BeansLinker} will be used.
|
||||
*/
|
||||
public void setFallbackLinkers(GuardingDynamicLinker... fallbackLinkers) {
|
||||
setFallbackLinkers(Arrays.asList(fallbackLinkers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of arguments in the call sites that represent the stack context of the language runtime creating
|
||||
* the linker. If the language runtime uses no context information passed on stack, then it should be zero
|
||||
* (the default value). If it is set to nonzero value, then every dynamic call site emitted by this runtime must
|
||||
* have the argument list of the form: {@code (this, contextArg1[, contextArg2[, ...]], normalArgs)}. It is
|
||||
* advisable to only pass one context-specific argument, though, of an easily recognizable, runtime specific type
|
||||
* encapsulating the runtime thread local state.
|
||||
*
|
||||
* @param runtimeContextArgCount the number of language runtime context arguments in call sites.
|
||||
*/
|
||||
public void setRuntimeContextArgCount(int runtimeContextArgCount) {
|
||||
if(runtimeContextArgCount < 0) {
|
||||
throw new IllegalArgumentException("runtimeContextArgCount < 0");
|
||||
}
|
||||
this.runtimeContextArgCount = runtimeContextArgCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the linker created by this factory will invoke {@link MutableCallSite#syncAll(MutableCallSite[])}
|
||||
* after a call site is relinked. Defaults to false. You probably want to set it to true if your runtime supports
|
||||
* multithreaded execution of dynamically linked code.
|
||||
* @param syncOnRelink true for invoking sync on relink, false otherwise.
|
||||
*/
|
||||
public void setSyncOnRelink(boolean syncOnRelink) {
|
||||
this.syncOnRelink = syncOnRelink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the unstable relink threshold; the number of times a call site is relinked after which it will be
|
||||
* considered unstable, and subsequent link requests for it will indicate this.
|
||||
* @param unstableRelinkThreshold the new threshold. Must not be less than zero. The value of zero means that
|
||||
* call sites will never be considered unstable.
|
||||
* @see LinkRequest#isCallSiteUnstable()
|
||||
*/
|
||||
public void setUnstableRelinkThreshold(int unstableRelinkThreshold) {
|
||||
if(unstableRelinkThreshold < 0) {
|
||||
throw new IllegalArgumentException("unstableRelinkThreshold < 0");
|
||||
}
|
||||
this.unstableRelinkThreshold = unstableRelinkThreshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new dynamic linker consisting of all the prioritized, autodiscovered, and fallback linkers.
|
||||
*
|
||||
* @return the new dynamic Linker
|
||||
*/
|
||||
public DynamicLinker createLinker() {
|
||||
// Treat nulls appropriately
|
||||
if(prioritizedLinkers == null) {
|
||||
prioritizedLinkers = Collections.emptyList();
|
||||
}
|
||||
if(fallbackLinkers == null) {
|
||||
fallbackLinkers = Collections.singletonList(new BeansLinker());
|
||||
}
|
||||
|
||||
// Gather classes of all precreated (prioritized and fallback) linkers.
|
||||
// We'll filter out any discovered linkers of the same class.
|
||||
final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses = new HashSet<>();
|
||||
addClasses(knownLinkerClasses, prioritizedLinkers);
|
||||
addClasses(knownLinkerClasses, fallbackLinkers);
|
||||
|
||||
final List<GuardingDynamicLinker> discovered = AutoDiscovery.loadLinkers(classLoader);
|
||||
// Now, concatenate ...
|
||||
final List<GuardingDynamicLinker> linkers = new ArrayList<>(prioritizedLinkers.size() + discovered.size()
|
||||
+ fallbackLinkers.size());
|
||||
// ... prioritized linkers, ...
|
||||
linkers.addAll(prioritizedLinkers);
|
||||
// ... filtered discovered linkers, ...
|
||||
for(GuardingDynamicLinker linker: discovered) {
|
||||
if(!knownLinkerClasses.contains(linker.getClass())) {
|
||||
linkers.add(linker);
|
||||
}
|
||||
}
|
||||
// ... and finally fallback linkers.
|
||||
linkers.addAll(fallbackLinkers);
|
||||
final List<GuardingDynamicLinker> optimized = CompositeTypeBasedGuardingDynamicLinker.optimize(linkers);
|
||||
final GuardingDynamicLinker composite;
|
||||
switch(linkers.size()) {
|
||||
case 0: {
|
||||
composite = BottomGuardingDynamicLinker.INSTANCE;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
composite = optimized.get(0);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
composite = new CompositeGuardingDynamicLinker(optimized);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
final List<GuardingTypeConverterFactory> typeConverters = new LinkedList<>();
|
||||
for(GuardingDynamicLinker linker: linkers) {
|
||||
if(linker instanceof GuardingTypeConverterFactory) {
|
||||
typeConverters.add((GuardingTypeConverterFactory)linker);
|
||||
}
|
||||
}
|
||||
|
||||
return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters), composite),
|
||||
runtimeContextArgCount, syncOnRelink, unstableRelinkThreshold);
|
||||
}
|
||||
|
||||
private static void addClasses(Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses,
|
||||
List<? extends GuardingDynamicLinker> linkers) {
|
||||
for(GuardingDynamicLinker linker: linkers) {
|
||||
knownLinkerClasses.add(linker.getClass());
|
||||
}
|
||||
}
|
||||
}
|
116
nashorn/src/jdk/internal/dynalink/MonomorphicCallSite.java
Normal file
116
nashorn/src/jdk/internal/dynalink/MonomorphicCallSite.java
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.support.AbstractRelinkableCallSite;
|
||||
|
||||
|
||||
/**
|
||||
* A relinkable call site that implements monomorphic inline caching strategy. After it linked a method, it will keep it
|
||||
* until either its guard evaluates to false, or its switchpoint is invalidated, at which time it will throw away the
|
||||
* previous linkage, and trigger relinking with its associated {@link DynamicLinker}.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class MonomorphicCallSite extends AbstractRelinkableCallSite {
|
||||
/**
|
||||
* Creates a new call site with monomorphic inline caching strategy.
|
||||
* @param descriptor the descriptor for this call site
|
||||
*/
|
||||
public MonomorphicCallSite(CallSiteDescriptor descriptor) {
|
||||
super(descriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relink(GuardedInvocation guardedInvocation, MethodHandle relink) {
|
||||
setTarget(guardedInvocation.compose(relink));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle relink) {
|
||||
relink(guardedInvocation, relink);
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink;
|
||||
|
||||
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
|
||||
|
||||
/**
|
||||
* Thrown at the invocation if the call site can not be linked by any available {@link GuardingDynamicLinker}.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class NoSuchDynamicMethodException extends RuntimeException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Creates a new NoSuchDynamicMethodException
|
||||
* @param message the message of the exception.
|
||||
*/
|
||||
public NoSuchDynamicMethodException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
148
nashorn/src/jdk/internal/dynalink/RelinkableCallSite.java
Normal file
148
nashorn/src/jdk/internal/dynalink/RelinkableCallSite.java
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink;
|
||||
|
||||
import java.lang.invoke.CallSite;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MutableCallSite;
|
||||
import java.lang.invoke.VolatileCallSite;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for relinkable call sites. Language runtimes wishing to use this framework must use subclasses of
|
||||
* {@link CallSite} that also implement this interface as their call sites. There is a readily usable
|
||||
* {@link MonomorphicCallSite} subclass that implements monomorphic inline caching strategy as well as a
|
||||
* {@link ChainedCallSite} that retains a chain of already linked method handles. The reason this is defined as an
|
||||
* interface instead of a concrete, albeit abstract class is that it allows independent implementations to choose
|
||||
* between {@link MutableCallSite} and {@link VolatileCallSite} as they see fit.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public interface RelinkableCallSite {
|
||||
/**
|
||||
* Initializes the relinkable call site by setting a relink-and-invoke method handle. The call site implementation
|
||||
* is supposed to set this method handle as its target.
|
||||
* @param relinkAndInvoke a relink-and-invoke method handle supplied by the {@link DynamicLinker}.
|
||||
*/
|
||||
public void initialize(MethodHandle relinkAndInvoke);
|
||||
|
||||
/**
|
||||
* Returns the descriptor for this call site.
|
||||
*
|
||||
* @return the descriptor for this call site.
|
||||
*/
|
||||
public CallSiteDescriptor getDescriptor();
|
||||
|
||||
/**
|
||||
* This method will be called by the dynamic linker every time the call site is normally relinked. It will be passed
|
||||
* a {@code GuardedInvocation} that the call site should incorporate into its target method handle. When this method
|
||||
* is called, the call site is allowed to keep other non-invalidated invocations around for implementation of
|
||||
* polymorphic inline caches and compose them with this invocation to form its final target.
|
||||
*
|
||||
* @param guardedInvocation the guarded invocation that the call site should incorporate into its target method
|
||||
* handle.
|
||||
* @param fallback the fallback method. This is a method matching the method type of the call site that is supplied
|
||||
* by the {@link DynamicLinker} to be used by this call site as a fallback when it can't invoke its target with the
|
||||
* passed arguments. The fallback method is such that when it's invoked, it'll try to discover the adequate target
|
||||
* for the invocation, subsequently invoke {@link #relink(GuardedInvocation, MethodHandle)} or
|
||||
* {@link #resetAndRelink(GuardedInvocation, MethodHandle)}, and finally invoke the target.
|
||||
*/
|
||||
public void relink(GuardedInvocation guardedInvocation, MethodHandle fallback);
|
||||
|
||||
/**
|
||||
* This method will be called by the dynamic linker every time the call site is relinked and the linker wishes the
|
||||
* call site to throw away any prior linkage state. It will be passed a {@code GuardedInvocation} that the call site
|
||||
* should use to build its target method handle. When this method is called, the call site is discouraged from
|
||||
* keeping previous state around, and is supposed to only link the current invocation.
|
||||
*
|
||||
* @param guardedInvocation the guarded invocation that the call site should use to build its target method handle.
|
||||
* @param fallback the fallback method. This is a method matching the method type of the call site that is supplied
|
||||
* by the {@link DynamicLinker} to be used by this call site as a fallback when it can't invoke its target with the
|
||||
* passed arguments. The fallback method is such that when it's invoked, it'll try to discover the adequate target
|
||||
* for the invocation, subsequently invoke {@link #relink(GuardedInvocation, MethodHandle)} or
|
||||
* {@link #resetAndRelink(GuardedInvocation, MethodHandle)}, and finally invoke the target.
|
||||
*/
|
||||
public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle fallback);
|
||||
}
|
690
nashorn/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java
Normal file
690
nashorn/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java
Normal file
@ -0,0 +1,690 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.beans.Introspector;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
|
||||
import jdk.internal.dynalink.support.Guards;
|
||||
import jdk.internal.dynalink.support.Lookup;
|
||||
|
||||
|
||||
/**
|
||||
* A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property
|
||||
* exposure and method calls for both static and instance facets of a class.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
abstract class AbstractJavaLinker implements GuardingDynamicLinker {
|
||||
final Class<?> clazz;
|
||||
private final MethodHandle classGuard;
|
||||
private final MethodHandle assignableGuard;
|
||||
private final Map<String, AnnotatedMethodHandle> propertyGetters = new HashMap<>();
|
||||
private final Map<String, DynamicMethod> propertySetters = new HashMap<>();
|
||||
private final Map<String, DynamicMethod> methods = new HashMap<>();
|
||||
|
||||
AbstractJavaLinker(Class<?> clazz, MethodHandle classGuard) {
|
||||
this(clazz, classGuard, classGuard);
|
||||
}
|
||||
|
||||
AbstractJavaLinker(Class<?> clazz, MethodHandle classGuard, MethodHandle assignableGuard) {
|
||||
this.clazz = clazz;
|
||||
this.classGuard = classGuard;
|
||||
this.assignableGuard = assignableGuard;
|
||||
|
||||
final FacetIntrospector introspector = createFacetIntrospector();
|
||||
try {
|
||||
// Add methods and properties
|
||||
for(Method method: introspector.getMethods()) {
|
||||
final String name = method.getName();
|
||||
final MethodHandle methodHandle = introspector.unreflect(method);
|
||||
// Add method
|
||||
addMember(name, methodHandle, methods);
|
||||
// Add the method as a property getter and/or setter
|
||||
if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) {
|
||||
// Property getter
|
||||
setPropertyGetter(Introspector.decapitalize(name.substring(3)), introspector.unreflect(
|
||||
getMostGenericGetter(method)), ValidationType.INSTANCE_OF);
|
||||
} else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 &&
|
||||
method.getReturnType() == boolean.class) {
|
||||
// Boolean property getter
|
||||
setPropertyGetter(Introspector.decapitalize(name.substring(2)), introspector.unreflect(
|
||||
getMostGenericGetter(method)), ValidationType.INSTANCE_OF);
|
||||
} else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) {
|
||||
// Property setter
|
||||
addMember(Introspector.decapitalize(name.substring(3)), methodHandle, propertySetters);
|
||||
}
|
||||
}
|
||||
|
||||
// Add field getter/setters as property getters/setters.
|
||||
for(Field field: introspector.getFields()) {
|
||||
final String name = field.getName();
|
||||
// Only add a property getter when one is not defined already as a getXxx()/isXxx() method.
|
||||
if(!propertyGetters.containsKey(name)) {
|
||||
setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS);
|
||||
}
|
||||
if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) {
|
||||
addMember(name, introspector.unreflectSetter(field), propertySetters);
|
||||
}
|
||||
}
|
||||
|
||||
// Add inner classes, but only those for which we don't hide a property with it
|
||||
for(Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) {
|
||||
final String name = innerClassSpec.getKey();
|
||||
if(!propertyGetters.containsKey(name)) {
|
||||
setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
introspector.close();
|
||||
}
|
||||
}
|
||||
|
||||
abstract FacetIntrospector createFacetIntrospector();
|
||||
|
||||
void setPropertyGetter(String name, MethodHandle handle, ValidationType validationType) {
|
||||
propertyGetters.put(name, new AnnotatedMethodHandle(handle, validationType));
|
||||
}
|
||||
|
||||
private void addMember(String name, MethodHandle mh, Map<String, DynamicMethod> methodMap) {
|
||||
final DynamicMethod existingMethod = methodMap.get(name);
|
||||
final DynamicMethod newMethod = addMember(mh, existingMethod, clazz, name);
|
||||
if(newMethod != existingMethod) {
|
||||
methodMap.put(name, newMethod);
|
||||
}
|
||||
}
|
||||
|
||||
static DynamicMethod createDynamicMethod(Iterable<MethodHandle> methodHandles, Class<?> clazz, String name) {
|
||||
DynamicMethod dynMethod = null;
|
||||
for(MethodHandle methodHandle: methodHandles) {
|
||||
dynMethod = addMember(methodHandle, dynMethod, clazz, name);
|
||||
}
|
||||
return dynMethod;
|
||||
}
|
||||
|
||||
private static DynamicMethod addMember(MethodHandle mh, DynamicMethod existing, Class<?> clazz, String name) {
|
||||
if(existing == null) {
|
||||
return new SimpleDynamicMethod(mh, clazz, name);
|
||||
} else if(existing.contains(mh)) {
|
||||
return existing;
|
||||
} else if(existing instanceof SimpleDynamicMethod) {
|
||||
final OverloadedDynamicMethod odm = new OverloadedDynamicMethod(clazz, name);
|
||||
odm.addMethod(((SimpleDynamicMethod)existing));
|
||||
odm.addMethod(mh);
|
||||
return odm;
|
||||
} else if(existing instanceof OverloadedDynamicMethod) {
|
||||
((OverloadedDynamicMethod)existing).addMethod(mh);
|
||||
return existing;
|
||||
}
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices)
|
||||
throws Exception {
|
||||
final LinkRequest ncrequest = request.withoutRuntimeContext();
|
||||
// BeansLinker already checked that the name is at least 2 elements long and the first element is "dyn".
|
||||
final CallSiteDescriptor callSiteDescriptor = ncrequest.getCallSiteDescriptor();
|
||||
final String op = callSiteDescriptor.getNameToken(CallSiteDescriptor.OPERATOR);
|
||||
// Either dyn:callMethod:name(this[,args]) or dyn:callMethod(this,name[,args]).
|
||||
if("callMethod" == op) {
|
||||
return getCallPropWithThis(callSiteDescriptor, linkerServices);
|
||||
}
|
||||
List<String> operations = CallSiteDescriptorFactory.tokenizeOperators(callSiteDescriptor);
|
||||
while(!operations.isEmpty()) {
|
||||
final GuardedInvocationComponent gic = getGuardedInvocationComponent(callSiteDescriptor, linkerServices,
|
||||
operations);
|
||||
if(gic != null) {
|
||||
return gic.getGuardedInvocation();
|
||||
}
|
||||
operations = pop(operations);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected GuardedInvocationComponent getGuardedInvocationComponent(CallSiteDescriptor callSiteDescriptor,
|
||||
LinkerServices linkerServices, List<String> operations) throws Exception {
|
||||
if(operations.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
final String op = operations.get(0);
|
||||
// Either dyn:getProp:name(this) or dyn:getProp(this, name)
|
||||
if("getProp".equals(op)) {
|
||||
return getPropertyGetter(callSiteDescriptor, linkerServices, pop(operations));
|
||||
}
|
||||
// Either dyn:setProp:name(this, value) or dyn:setProp(this, name, value)
|
||||
if("setProp".equals(op)) {
|
||||
return getPropertySetter(callSiteDescriptor, linkerServices, pop(operations));
|
||||
}
|
||||
// Either dyn:getMethod:name(this), or dyn:getMethod(this, name)
|
||||
if("getMethod".equals(op)) {
|
||||
return getMethodGetter(callSiteDescriptor, linkerServices, pop(operations));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static final <T> List<T> pop(List<T> l) {
|
||||
return l.subList(1, l.size());
|
||||
}
|
||||
|
||||
MethodHandle getClassGuard(CallSiteDescriptor desc) {
|
||||
return getClassGuard(desc.getMethodType());
|
||||
}
|
||||
|
||||
MethodHandle getClassGuard(MethodType type) {
|
||||
return Guards.asType(classGuard, type);
|
||||
}
|
||||
|
||||
GuardedInvocationComponent getClassGuardedInvocationComponent(MethodHandle invocation, MethodType type) {
|
||||
return new GuardedInvocationComponent(invocation, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
|
||||
}
|
||||
|
||||
private MethodHandle getAssignableGuard(MethodType type) {
|
||||
return Guards.asType(assignableGuard, type);
|
||||
}
|
||||
|
||||
private GuardedInvocation getCallPropWithThis(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices) {
|
||||
switch(callSiteDescriptor.getNameTokenCount()) {
|
||||
case 3: {
|
||||
return createGuardedDynamicMethodInvocation(callSiteDescriptor.getMethodType(), linkerServices,
|
||||
callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), methods);
|
||||
}
|
||||
default: {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private GuardedInvocation createGuardedDynamicMethodInvocation(MethodType callSiteType,
|
||||
LinkerServices linkerServices, String methodName, Map<String, DynamicMethod> methodMap){
|
||||
final MethodHandle inv = getDynamicMethodInvocation(callSiteType, linkerServices, methodName, methodMap);
|
||||
return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteType));
|
||||
}
|
||||
|
||||
private static MethodHandle getDynamicMethodInvocation(MethodType callSiteType, LinkerServices linkerServices,
|
||||
String methodName, Map<String, DynamicMethod> methodMap) {
|
||||
final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap);
|
||||
return dynaMethod != null ? dynaMethod.getInvocation(callSiteType, linkerServices) : null;
|
||||
}
|
||||
|
||||
private static DynamicMethod getDynamicMethod(String methodName, Map<String, DynamicMethod> methodMap) {
|
||||
final DynamicMethod dynaMethod = methodMap.get(methodName);
|
||||
return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap);
|
||||
}
|
||||
|
||||
private static SimpleDynamicMethod getExplicitSignatureDynamicMethod(String methodName,
|
||||
Map<String, DynamicMethod> methodsMap) {
|
||||
// What's below is meant to support the "name(type, type, ...)" syntax that programmers can use in a method name
|
||||
// to manually pin down an exact overloaded variant. This is not usually required, as the overloaded method
|
||||
// resolution works correctly in almost every situation. However, in presence of many language-specific
|
||||
// conversions with a radically dynamic language, most overloaded methods will end up being constantly selected
|
||||
// at invocation time, so a programmer knowledgable of the situation might choose to pin down an exact overload
|
||||
// for performance reasons.
|
||||
|
||||
// Is the method name lexically of the form "name(types)"?
|
||||
final int lastChar = methodName.length() - 1;
|
||||
if(methodName.charAt(lastChar) != ')') {
|
||||
return null;
|
||||
}
|
||||
final int openBrace = methodName.indexOf('(');
|
||||
if(openBrace == -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find an existing method for the "name" part
|
||||
final DynamicMethod simpleNamedMethod = methodsMap.get(methodName.substring(0, openBrace));
|
||||
if(simpleNamedMethod == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Try to get a narrowed dynamic method for the explicit parameter types.
|
||||
return simpleNamedMethod.getMethodForExactParamTypes(methodName.substring(openBrace + 1, lastChar));
|
||||
}
|
||||
|
||||
private static final MethodHandle IS_METHOD_HANDLE_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType(
|
||||
boolean.class, MethodHandle.class));
|
||||
private static final MethodHandle CONSTANT_NULL_DROP_METHOD_HANDLE = MethodHandles.dropArguments(
|
||||
MethodHandles.constant(Object.class, null), 0, MethodHandle.class);
|
||||
|
||||
private GuardedInvocationComponent getPropertySetter(CallSiteDescriptor callSiteDescriptor,
|
||||
LinkerServices linkerServices, List<String> operations) throws Exception {
|
||||
final MethodType type = callSiteDescriptor.getMethodType();
|
||||
switch(callSiteDescriptor.getNameTokenCount()) {
|
||||
case 2: {
|
||||
// Must have three arguments: target object, property name, and property value.
|
||||
assertParameterCount(callSiteDescriptor, 3);
|
||||
|
||||
// What's below is basically:
|
||||
// foldArguments(guardWithTest(isNotNull, invoke, null|nextComponent.invocation),
|
||||
// get_setter_handle(type, linkerServices))
|
||||
// only with a bunch of method signature adjustments. Basically, retrieve method setter
|
||||
// MethodHandle; if it is non-null, invoke it, otherwise either return null, or delegate to next
|
||||
// component's invocation.
|
||||
|
||||
// Call site type is "ret_type(object_type,property_name_type,property_value_type)", which we'll
|
||||
// abbreviate to R(O, N, V) going forward.
|
||||
// We want setters that conform to "R(O, V)"
|
||||
final MethodType setterType = type.dropParameterTypes(1, 2);
|
||||
// Bind property setter handle to the expected setter type and linker services. Type is
|
||||
// MethodHandle(Object, String, Object)
|
||||
final MethodHandle boundGetter = MethodHandles.insertArguments(getPropertySetterHandle, 0, setterType,
|
||||
linkerServices);
|
||||
|
||||
// Cast getter to MethodHandle(O, N, V)
|
||||
final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType(
|
||||
MethodHandle.class));
|
||||
|
||||
// Handle to invoke the setter R(MethodHandle, O, V)
|
||||
final MethodHandle invokeHandle = MethodHandles.exactInvoker(setterType);
|
||||
// Handle to invoke the setter, dropping unnecessary fold arguments R(MethodHandle, O, N, V)
|
||||
final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandle, 2, type.parameterType(
|
||||
1));
|
||||
final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
|
||||
linkerServices, operations);
|
||||
|
||||
final MethodHandle fallbackFolded;
|
||||
if(nextComponent == null) {
|
||||
// Object(MethodHandle)->R(MethodHandle, O, N, V); returns constant null
|
||||
fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_METHOD_HANDLE, 1,
|
||||
type.parameterList()).asType(type.insertParameterTypes(0, MethodHandle.class));
|
||||
} else {
|
||||
// R(O, N, V)->R(MethodHandle, O, N, V); adapts the next component's invocation to drop the
|
||||
// extra argument resulting from fold
|
||||
fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
|
||||
0, MethodHandle.class);
|
||||
}
|
||||
|
||||
// fold(R(MethodHandle, O, N, V), MethodHandle(O, N, V))
|
||||
final MethodHandle compositeSetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
|
||||
IS_METHOD_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
|
||||
if(nextComponent == null) {
|
||||
return getClassGuardedInvocationComponent(compositeSetter, type);
|
||||
} else {
|
||||
return nextComponent.compose(compositeSetter, getClassGuard(type), clazz,
|
||||
ValidationType.EXACT_CLASS);
|
||||
}
|
||||
}
|
||||
case 3: {
|
||||
// Must have two arguments: target object and property value
|
||||
assertParameterCount(callSiteDescriptor, 2);
|
||||
final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor.getMethodType(),
|
||||
linkerServices, callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND),
|
||||
propertySetters);
|
||||
// If we have a property setter with this name, this composite operation will always stop here
|
||||
if(gi != null) {
|
||||
return new GuardedInvocationComponent(gi, clazz, ValidationType.EXACT_CLASS);
|
||||
}
|
||||
// If we don't have a property setter with this name, always fall back to the next operation in the
|
||||
// composite (if any)
|
||||
return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, operations);
|
||||
}
|
||||
default: {
|
||||
// More than two name components; don't know what to do with it.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final Lookup privateLookup = new Lookup(MethodHandles.lookup());
|
||||
|
||||
private static final MethodHandle IS_ANNOTATED_HANDLE_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType(
|
||||
boolean.class, AnnotatedMethodHandle.class));
|
||||
private static final MethodHandle CONSTANT_NULL_DROP_ANNOTATED_HANDLE = MethodHandles.dropArguments(
|
||||
MethodHandles.constant(Object.class, null), 0, AnnotatedMethodHandle.class);
|
||||
private static final MethodHandle GET_ANNOTATED_HANDLE = privateLookup.findGetter(AnnotatedMethodHandle.class,
|
||||
"handle", MethodHandle.class);
|
||||
private static final MethodHandle GENERIC_PROPERTY_GETTER_HANDLER_INVOKER = MethodHandles.filterArguments(
|
||||
MethodHandles.invoker(MethodType.methodType(Object.class, Object.class)), 0, GET_ANNOTATED_HANDLE);
|
||||
|
||||
private GuardedInvocationComponent getPropertyGetter(CallSiteDescriptor callSiteDescriptor,
|
||||
LinkerServices linkerServices, List<String> ops) throws Exception {
|
||||
final MethodType type = callSiteDescriptor.getMethodType();
|
||||
switch(callSiteDescriptor.getNameTokenCount()) {
|
||||
case 2: {
|
||||
// Must have exactly two arguments: receiver and name
|
||||
assertParameterCount(callSiteDescriptor, 2);
|
||||
|
||||
// What's below is basically:
|
||||
// foldArguments(guardWithTest(isNotNull, invoke(get_handle), null|nextComponent.invocation), get_getter_handle)
|
||||
// only with a bunch of method signature adjustments. Basically, retrieve method getter
|
||||
// AnnotatedMethodHandle; if it is non-null, invoke its "handle" field, otherwise either return null,
|
||||
// or delegate to next component's invocation.
|
||||
|
||||
final MethodHandle typedGetter = linkerServices.asType(getPropertyGetterHandle, type.changeReturnType(
|
||||
AnnotatedMethodHandle.class));
|
||||
// Object(AnnotatedMethodHandle, Object)->R(AnnotatedMethodHandle, T0)
|
||||
final MethodHandle invokeHandleTyped = linkerServices.asType(GENERIC_PROPERTY_GETTER_HANDLER_INVOKER,
|
||||
MethodType.methodType(type.returnType(), AnnotatedMethodHandle.class, type.parameterType(0)));
|
||||
// Since it's in the target of a fold, drop the unnecessary second argument
|
||||
// R(AnnotatedMethodHandle, T0)->R(AnnotatedMethodHandle, T0, T1)
|
||||
final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2,
|
||||
type.parameterType(1));
|
||||
final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
|
||||
linkerServices, ops);
|
||||
|
||||
final MethodHandle fallbackFolded;
|
||||
if(nextComponent == null) {
|
||||
// Object(AnnotatedMethodHandle)->R(AnnotatedMethodHandle, T0, T1); returns constant null
|
||||
fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_HANDLE, 1,
|
||||
type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedMethodHandle.class));
|
||||
} else {
|
||||
// R(T0, T1)->R(AnnotatedMethodHAndle, T0, T1); adapts the next component's invocation to drop the
|
||||
// extra argument resulting from fold
|
||||
fallbackFolded = MethodHandles.dropArguments(nextComponent.getGuardedInvocation().getInvocation(),
|
||||
0, AnnotatedMethodHandle.class);
|
||||
}
|
||||
|
||||
// fold(R(AnnotatedMethodHandle, T0, T1), AnnotatedMethodHandle(T0, T1))
|
||||
final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
|
||||
IS_ANNOTATED_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
|
||||
if(nextComponent == null) {
|
||||
return getClassGuardedInvocationComponent(compositeGetter, type);
|
||||
} else {
|
||||
return nextComponent.compose(compositeGetter, getClassGuard(type), clazz,
|
||||
ValidationType.EXACT_CLASS);
|
||||
}
|
||||
}
|
||||
case 3: {
|
||||
// Must have exactly one argument: receiver
|
||||
assertParameterCount(callSiteDescriptor, 1);
|
||||
// Fixed name
|
||||
final AnnotatedMethodHandle annGetter = propertyGetters.get(callSiteDescriptor.getNameToken(
|
||||
CallSiteDescriptor.NAME_OPERAND));
|
||||
if(annGetter == null) {
|
||||
// We have no such property, always delegate to the next component operation
|
||||
return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops);
|
||||
}
|
||||
final MethodHandle getter = annGetter.handle;
|
||||
// NOTE: since property getters (not field getters!) are no-arg, we don't have to worry about them being
|
||||
// overloaded in a subclass. Therefore, we can discover the most abstract superclass that has the
|
||||
// method, and use that as the guard with Guards.isInstance() for a more stably linked call site. If
|
||||
// we're linking against a field getter, don't make the assumption.
|
||||
// NOTE: No delegation to the next component operation if we have a property with this name, even if its
|
||||
// value is null.
|
||||
final ValidationType validationType = annGetter.validationType;
|
||||
return new GuardedInvocationComponent(linkerServices.asType(getter, type), getGuard(validationType,
|
||||
type), clazz, validationType);
|
||||
}
|
||||
default: {
|
||||
// Can't do anything with more than 3 name components
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MethodHandle getGuard(ValidationType validationType, MethodType methodType) {
|
||||
switch(validationType) {
|
||||
case EXACT_CLASS: {
|
||||
return getClassGuard(methodType);
|
||||
}
|
||||
case INSTANCE_OF: {
|
||||
return getAssignableGuard(methodType);
|
||||
}
|
||||
case IS_ARRAY: {
|
||||
return Guards.isArray(0, methodType);
|
||||
}
|
||||
case NONE: {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
private static final MethodHandle IS_DYNAMIC_METHOD_NOT_NULL = Guards.asType(Guards.isNotNull(),
|
||||
MethodType.methodType(boolean.class, DynamicMethod.class));
|
||||
private static final MethodHandle DYNAMIC_METHOD_IDENTITY = MethodHandles.identity(DynamicMethod.class);
|
||||
|
||||
private GuardedInvocationComponent getMethodGetter(CallSiteDescriptor callSiteDescriptor,
|
||||
LinkerServices linkerServices, List<String> ops) throws Exception {
|
||||
final MethodType type = callSiteDescriptor.getMethodType();
|
||||
switch(callSiteDescriptor.getNameTokenCount()) {
|
||||
case 2: {
|
||||
// Must have exactly two arguments: receiver and name
|
||||
assertParameterCount(callSiteDescriptor, 2);
|
||||
final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
|
||||
linkerServices, ops);
|
||||
if(nextComponent == null) {
|
||||
// No next component operation; just return a component for this operation.
|
||||
return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type);
|
||||
} else {
|
||||
// What's below is basically:
|
||||
// foldArguments(guardWithTest(isNotNull, identity, nextComponent.invocation), getter)
|
||||
// only with a bunch of method signature adjustments. Basically, execute method getter; if
|
||||
// it returns a non-null DynamicMethod, use identity to return it, otherwise delegate to
|
||||
// nextComponent's invocation.
|
||||
|
||||
final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type.changeReturnType(
|
||||
DynamicMethod.class));
|
||||
// Since it is part of the foldArgument() target, it will have extra args that we need to drop.
|
||||
final MethodHandle returnMethodHandle = linkerServices.asType(MethodHandles.dropArguments(
|
||||
DYNAMIC_METHOD_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0,
|
||||
DynamicMethod.class));
|
||||
final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation();
|
||||
// The assumption is that getGuardedInvocationComponent() already asType()'d it correctly
|
||||
assert nextComponentInvocation.type().equals(type);
|
||||
// Since it is part of the foldArgument() target, we have to drop an extra arg it receives.
|
||||
final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0,
|
||||
DynamicMethod.class);
|
||||
// Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get)
|
||||
final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
|
||||
IS_DYNAMIC_METHOD_NOT_NULL, returnMethodHandle, nextCombinedInvocation), typedGetter);
|
||||
|
||||
return nextComponent.compose(compositeGetter, getClassGuard(type), clazz,
|
||||
ValidationType.EXACT_CLASS);
|
||||
}
|
||||
}
|
||||
case 3: {
|
||||
// Must have exactly one argument: receiver
|
||||
assertParameterCount(callSiteDescriptor, 1);
|
||||
final DynamicMethod method = getDynamicMethod(callSiteDescriptor.getNameToken(
|
||||
CallSiteDescriptor.NAME_OPERAND));
|
||||
if(method == null) {
|
||||
// We have no such method, always delegate to the next component
|
||||
return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops);
|
||||
}
|
||||
// No delegation to the next component of the composite operation; if we have a method with that name,
|
||||
// we'll always return it at this point.
|
||||
return getClassGuardedInvocationComponent(linkerServices.asType(MethodHandles.dropArguments(
|
||||
MethodHandles.constant(DynamicMethod.class, method), 0, type.parameterType(0)), type), type);
|
||||
}
|
||||
default: {
|
||||
// Can't do anything with more than 3 name components
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertParameterCount(CallSiteDescriptor descriptor, int paramCount) {
|
||||
if(descriptor.getMethodType().parameterCount() != paramCount) {
|
||||
throw new BootstrapMethodError(descriptor.getName() + " must have exactly " + paramCount + " parameters.");
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodHandle GET_PROPERTY_GETTER_HANDLE = MethodHandles.dropArguments(privateLookup.findOwnSpecial(
|
||||
"getPropertyGetterHandle", Object.class, Object.class), 1, Object.class);
|
||||
private final MethodHandle getPropertyGetterHandle = GET_PROPERTY_GETTER_HANDLE.bindTo(this);
|
||||
|
||||
/**
|
||||
* @param id the property ID
|
||||
* @return the method handle for retrieving the property, or null if the property does not exist
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private Object getPropertyGetterHandle(Object id) {
|
||||
return propertyGetters.get(id);
|
||||
}
|
||||
|
||||
// Type is MethodHandle(BeanLinker, MethodType, LinkerServices, Object, String, Object), of which the two "Object"
|
||||
// args are dropped; this makes handles with first three args conform to "Object, String, Object" though, which is
|
||||
// a typical property setter with variable name signature (target, name, value).
|
||||
private static final MethodHandle GET_PROPERTY_SETTER_HANDLE = MethodHandles.dropArguments(MethodHandles.dropArguments(
|
||||
privateLookup.findOwnSpecial("getPropertySetterHandle", MethodHandle.class, MethodType.class,
|
||||
LinkerServices.class, Object.class), 3, Object.class), 5, Object.class);
|
||||
// Type is MethodHandle(MethodType, LinkerServices, Object, String, Object)
|
||||
private final MethodHandle getPropertySetterHandle = GET_PROPERTY_SETTER_HANDLE.bindTo(this);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private MethodHandle getPropertySetterHandle(MethodType setterType, LinkerServices linkerServices, Object id) {
|
||||
return getDynamicMethodInvocation(setterType, linkerServices, String.valueOf(id), propertySetters);
|
||||
}
|
||||
|
||||
private static MethodHandle GET_DYNAMIC_METHOD = MethodHandles.dropArguments(privateLookup.findOwnSpecial(
|
||||
"getDynamicMethod", DynamicMethod.class, Object.class), 1, Object.class);
|
||||
private final MethodHandle getDynamicMethod = GET_DYNAMIC_METHOD.bindTo(this);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private DynamicMethod getDynamicMethod(Object name) {
|
||||
return getDynamicMethod(String.valueOf(name), methods);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a dynamic method of the specified name.
|
||||
*
|
||||
* @param name name of the method
|
||||
* @return the dynamic method (either {@link SimpleDynamicMethod} or {@link OverloadedDynamicMethod}, or null if the
|
||||
* method with the specified name does not exist.
|
||||
*/
|
||||
public DynamicMethod getDynamicMethod(String name) {
|
||||
return getDynamicMethod(name, methods);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the most generic superclass that declares this getter. Since getters have zero args (aside from the
|
||||
* receiver), they can't be overloaded, so we're free to link with an instanceof guard for the most generic one,
|
||||
* creating more stable call sites.
|
||||
* @param getter the getter
|
||||
* @return getter with same name, declared on the most generic superclass/interface of the declaring class
|
||||
*/
|
||||
private static Method getMostGenericGetter(Method getter) {
|
||||
return getMostGenericGetter(getter.getName(), getter.getReturnType(), getter.getDeclaringClass());
|
||||
}
|
||||
|
||||
private static Method getMostGenericGetter(String name, Class<?> returnType, Class<?> declaringClass) {
|
||||
if(declaringClass == null) {
|
||||
return null;
|
||||
}
|
||||
// Prefer interfaces
|
||||
for(Class<?> itf: declaringClass.getInterfaces()) {
|
||||
final Method itfGetter = getMostGenericGetter(name, returnType, itf);
|
||||
if(itfGetter != null) {
|
||||
return itfGetter;
|
||||
}
|
||||
}
|
||||
final Method superGetter = getMostGenericGetter(name, returnType, declaringClass.getSuperclass());
|
||||
if(superGetter != null) {
|
||||
return superGetter;
|
||||
}
|
||||
if(!CheckRestrictedPackage.isRestrictedClass(declaringClass)) {
|
||||
try {
|
||||
return declaringClass.getMethod(name);
|
||||
} catch(NoSuchMethodException e) {
|
||||
// Intentionally ignored, meant to fall through
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final class AnnotatedMethodHandle {
|
||||
final MethodHandle handle;
|
||||
/*private*/ final ValidationType validationType;
|
||||
|
||||
AnnotatedMethodHandle(MethodHandle handle, ValidationType validationType) {
|
||||
this.handle = handle;
|
||||
this.validationType = validationType;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Utility class for discovering accessible methods and inner classes. Normally, a public member declared on a class is
|
||||
* accessible (that is, it can be invoked from anywhere). However, this is not the case if the class itself is not
|
||||
* public, or belongs to a restricted-access package. In that case, it is required to lookup a member in a publicly
|
||||
* accessible superclass or implemented interface of the class, and use it instead of the member discovered on the
|
||||
* class.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
class AccessibleMembersLookup {
|
||||
private final Map<MethodSignature, Method> methods;
|
||||
private final Set<Class<?>> innerClasses;
|
||||
private boolean instance;
|
||||
|
||||
/**
|
||||
* Creates a mapping for all accessible methods and inner classes on a class.
|
||||
*
|
||||
* @param clazz the inspected class
|
||||
* @param instance true to inspect instance methods, false to inspect static methods.
|
||||
*/
|
||||
AccessibleMembersLookup(final Class<?> clazz, boolean instance) {
|
||||
this.methods = new HashMap<>();
|
||||
this.innerClasses = new LinkedHashSet<>();
|
||||
this.instance = instance;
|
||||
lookupAccessibleMembers(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an accessible method equivalent of a method.
|
||||
*
|
||||
* @param m the method whose accessible equivalent is requested.
|
||||
* @return the accessible equivalent for the method (can be the same as the passed in method), or null if there is
|
||||
* no accessible method equivalent.
|
||||
*/
|
||||
Method getAccessibleMethod(final Method m) {
|
||||
return m == null ? null : methods.get(new MethodSignature(m));
|
||||
}
|
||||
|
||||
Collection<Method> getMethods() {
|
||||
return methods.values();
|
||||
}
|
||||
|
||||
Class<?>[] getInnerClasses() {
|
||||
return innerClasses.toArray(new Class<?>[innerClasses.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper class that represents a method signature - name and argument types.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
static final class MethodSignature {
|
||||
private final String name;
|
||||
private final Class<?>[] args;
|
||||
|
||||
/**
|
||||
* Creates a new method signature from arbitrary data.
|
||||
*
|
||||
* @param name the name of the method this signature represents.
|
||||
* @param args the argument types of the method.
|
||||
*/
|
||||
MethodSignature(String name, Class<?>[] args) {
|
||||
this.name = name;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a signature for the given method.
|
||||
*
|
||||
* @param method the method for which a signature is created.
|
||||
*/
|
||||
MethodSignature(final Method method) {
|
||||
this(method.getName(), method.getParameterTypes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this object to another object
|
||||
*
|
||||
* @param o the other object
|
||||
* @return true if the other object is also a method signature with the same name, same number of arguments, and
|
||||
* same types of arguments.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if(o instanceof MethodSignature) {
|
||||
final MethodSignature ms = (MethodSignature)o;
|
||||
return ms.name.equals(name) && Arrays.equals(args, ms.args);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code, consistent with the overridden {@link #equals(Object)}.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode() ^ Arrays.hashCode(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder b = new StringBuilder();
|
||||
b.append("[MethodSignature ").append(name).append('(');
|
||||
if(args.length > 0) {
|
||||
b.append(args[0].getCanonicalName());
|
||||
for(int i = 1; i < args.length; ++i) {
|
||||
b.append(", ").append(args[i].getCanonicalName());
|
||||
}
|
||||
}
|
||||
return b.append(")]").toString();
|
||||
}
|
||||
}
|
||||
|
||||
private void lookupAccessibleMembers(final Class<?> clazz) {
|
||||
boolean searchSuperTypes;
|
||||
|
||||
if(!CheckRestrictedPackage.isRestrictedClass(clazz)) {
|
||||
searchSuperTypes = false;
|
||||
for(Method method: clazz.getMethods()) {
|
||||
if(instance != Modifier.isStatic(method.getModifiers())) {
|
||||
final MethodSignature sig = new MethodSignature(method);
|
||||
if(!methods.containsKey(sig)) {
|
||||
final Class<?> declaringClass = method.getDeclaringClass();
|
||||
if(declaringClass != clazz && CheckRestrictedPackage.isRestrictedClass(declaringClass)) {
|
||||
//Sometimes, the declaring class of a method (Method.getDeclaringClass())
|
||||
//retrieved through Class.getMethods() for a public class will be a
|
||||
//non-public superclass. For such a method, we need to find a method with
|
||||
//the same name and signature in a public superclass or implemented
|
||||
//interface.
|
||||
//This typically doesn't happen with classes emitted by a reasonably modern
|
||||
//javac, as it'll create synthetic delegator methods in all public
|
||||
//immediate subclasses of the non-public class. We have, however, observed
|
||||
//this in the wild with class files compiled with older javac that doesn't
|
||||
//generate the said synthetic delegators.
|
||||
searchSuperTypes = true;
|
||||
} else {
|
||||
methods.put(sig, method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for(Class<?> innerClass: clazz.getClasses()) {
|
||||
// Add both static and non-static classes, regardless of instance flag. StaticClassLinker will just
|
||||
// expose non-static classes with explicit constructor outer class argument.
|
||||
// NOTE: getting inner class objects through getClasses() does not resolve them, so if those classes
|
||||
// were not yet loaded, they'll only get loaded in a non-resolved state; no static initializers for
|
||||
// them will trigger just by doing this.
|
||||
innerClasses.add(innerClass);
|
||||
}
|
||||
} else {
|
||||
searchSuperTypes = true;
|
||||
}
|
||||
|
||||
if(searchSuperTypes) {
|
||||
// If we reach here, the class is either not public, or it is in a restricted package. Alternatively, it is
|
||||
// public, but some of its methods claim that their declaring class is non-public. We'll try superclasses
|
||||
// and implemented interfaces then looking for public ones.
|
||||
final Class<?>[] interfaces = clazz.getInterfaces();
|
||||
for(int i = 0; i < interfaces.length; i++) {
|
||||
lookupAccessibleMembers(interfaces[i]);
|
||||
}
|
||||
final Class<?> superclass = clazz.getSuperclass();
|
||||
if(superclass != null) {
|
||||
lookupAccessibleMembers(superclass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import jdk.internal.dynalink.support.TypeUtilities;
|
||||
|
||||
|
||||
/**
|
||||
* Represents overloaded methods applicable to a specific call site signature.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
class ApplicableOverloadedMethods {
|
||||
private final List<MethodHandle> methods;
|
||||
private final boolean varArgs;
|
||||
|
||||
/**
|
||||
* Creates a new ApplicableOverloadedMethods instance
|
||||
*
|
||||
* @param methods a list of all overloaded methods with the same name for a class.
|
||||
* @param callSiteType the type of the call site
|
||||
* @param test applicability test. One of {@link #APPLICABLE_BY_SUBTYPING},
|
||||
* {@link #APPLICABLE_BY_METHOD_INVOCATION_CONVERSION}, or {@link #APPLICABLE_BY_VARIABLE_ARITY}.
|
||||
*/
|
||||
ApplicableOverloadedMethods(final List<MethodHandle> methods, final MethodType callSiteType,
|
||||
final ApplicabilityTest test) {
|
||||
this.methods = new LinkedList<>();
|
||||
for(MethodHandle m: methods) {
|
||||
if(test.isApplicable(callSiteType, m)) {
|
||||
this.methods.add(m);
|
||||
}
|
||||
}
|
||||
varArgs = test == APPLICABLE_BY_VARIABLE_ARITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all the methods this object holds.
|
||||
*
|
||||
* @return list of all methods.
|
||||
*/
|
||||
List<MethodHandle> getMethods() {
|
||||
return methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all methods in this objects that are maximally specific.
|
||||
*
|
||||
* @return a list of maximally specific methods.
|
||||
*/
|
||||
List<MethodHandle> findMaximallySpecificMethods() {
|
||||
return MaximallySpecific.getMaximallySpecificMethods(methods, varArgs);
|
||||
}
|
||||
|
||||
abstract static class ApplicabilityTest {
|
||||
abstract boolean isApplicable(MethodType callSiteType, MethodHandle method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the applicability-by-subtyping test from JLS 15.12.2.2.
|
||||
*/
|
||||
static final ApplicabilityTest APPLICABLE_BY_SUBTYPING = new ApplicabilityTest() {
|
||||
@Override
|
||||
boolean isApplicable(MethodType callSiteType, MethodHandle method) {
|
||||
final MethodType methodType = method.type();
|
||||
final int methodArity = methodType.parameterCount();
|
||||
if(methodArity != callSiteType.parameterCount()) {
|
||||
return false;
|
||||
}
|
||||
// 0th arg is receiver; it doesn't matter for overload
|
||||
// resolution.
|
||||
for(int i = 1; i < methodArity; ++i) {
|
||||
if(!TypeUtilities.isSubtype(callSiteType.parameterType(i), methodType.parameterType(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements the applicability-by-method-invocation-conversion test from JLS 15.12.2.3.
|
||||
*/
|
||||
static final ApplicabilityTest APPLICABLE_BY_METHOD_INVOCATION_CONVERSION = new ApplicabilityTest() {
|
||||
@Override
|
||||
boolean isApplicable(MethodType callSiteType, MethodHandle method) {
|
||||
final MethodType methodType = method.type();
|
||||
final int methodArity = methodType.parameterCount();
|
||||
if(methodArity != callSiteType.parameterCount()) {
|
||||
return false;
|
||||
}
|
||||
// 0th arg is receiver; it doesn't matter for overload
|
||||
// resolution.
|
||||
for(int i = 1; i < methodArity; ++i) {
|
||||
if(!TypeUtilities.isMethodInvocationConvertible(callSiteType.parameterType(i),
|
||||
methodType.parameterType(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Implements the applicability-by-variable-arity test from JLS 15.12.2.4.
|
||||
*/
|
||||
static final ApplicabilityTest APPLICABLE_BY_VARIABLE_ARITY = new ApplicabilityTest() {
|
||||
@Override
|
||||
boolean isApplicable(MethodType callSiteType, MethodHandle method) {
|
||||
if(!method.isVarargsCollector()) {
|
||||
return false;
|
||||
}
|
||||
final MethodType methodType = method.type();
|
||||
final int methodArity = methodType.parameterCount();
|
||||
final int fixArity = methodArity - 1;
|
||||
final int callSiteArity = callSiteType.parameterCount();
|
||||
if(fixArity > callSiteArity) {
|
||||
return false;
|
||||
}
|
||||
// 0th arg is receiver; it doesn't matter for overload
|
||||
// resolution.
|
||||
for(int i = 1; i < fixArity; ++i) {
|
||||
if(!TypeUtilities.isMethodInvocationConvertible(callSiteType.parameterType(i),
|
||||
methodType.parameterType(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
final Class<?> varArgType = methodType.parameterType(fixArity).getComponentType();
|
||||
for(int i = fixArity; i < callSiteArity; ++i) {
|
||||
if(!TypeUtilities.isMethodInvocationConvertible(callSiteType.parameterType(i), varArgType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
104
nashorn/src/jdk/internal/dynalink/beans/BeanIntrospector.java
Normal file
104
nashorn/src/jdk/internal/dynalink/beans/BeanIntrospector.java
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
class BeanIntrospector extends FacetIntrospector {
|
||||
BeanIntrospector(Class<?> clazz) {
|
||||
super(clazz, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
Map<String, MethodHandle> getInnerClassGetters() {
|
||||
return Collections.emptyMap(); // NOTE: non-static inner classes are also on StaticClassIntrospector.
|
||||
}
|
||||
|
||||
@Override
|
||||
MethodHandle editMethodHandle(MethodHandle mh) {
|
||||
return mh;
|
||||
}
|
||||
}
|
493
nashorn/src/jdk/internal/dynalink/beans/BeanLinker.java
Normal file
493
nashorn/src/jdk/internal/dynalink/beans/BeanLinker.java
Normal file
@ -0,0 +1,493 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.support.Guards;
|
||||
import jdk.internal.dynalink.support.Lookup;
|
||||
import jdk.internal.dynalink.support.TypeUtilities;
|
||||
|
||||
|
||||
/**
|
||||
* A class that provides linking capabilities for a single POJO class. Normally not used directly, but managed by
|
||||
* {@link BeansLinker}.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicLinker {
|
||||
BeanLinker(Class<?> clazz) {
|
||||
super(clazz, Guards.getClassGuard(clazz), Guards.getInstanceOfGuard(clazz));
|
||||
if(clazz.isArray()) {
|
||||
// Some languages won't have a notion of manipulating collections. Exposing "length" on arrays as an
|
||||
// explicit property is beneficial for them.
|
||||
// REVISIT: is it maybe a code smell that "dyn:getLength" is not needed?
|
||||
setPropertyGetter("length", GET_ARRAY_LENGTH, ValidationType.IS_ARRAY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canLinkType(Class<?> type) {
|
||||
return type == clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
FacetIntrospector createFacetIntrospector() {
|
||||
return new BeanIntrospector(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GuardedInvocationComponent getGuardedInvocationComponent(CallSiteDescriptor callSiteDescriptor,
|
||||
LinkerServices linkerServices, List<String> operations) throws Exception {
|
||||
final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(callSiteDescriptor,
|
||||
linkerServices, operations);
|
||||
if(superGic != null) {
|
||||
return superGic;
|
||||
}
|
||||
if(operations.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
final String op = operations.get(0);
|
||||
// dyn:getElem(this, id)
|
||||
// id is typically either an int (for arrays and lists) or an object (for maps). linkerServices can provide
|
||||
// conversion from call site argument type though.
|
||||
if("getElem".equals(op)) {
|
||||
return getElementGetter(callSiteDescriptor, linkerServices, pop(operations));
|
||||
}
|
||||
if("setElem".equals(op)) {
|
||||
return getElementSetter(callSiteDescriptor, linkerServices, pop(operations));
|
||||
}
|
||||
// dyn:getLength(this) (works on Java arrays, collections, and maps)
|
||||
if("getLength".equals(op)) {
|
||||
return getLengthGetter(callSiteDescriptor);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static MethodHandle GET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "get",
|
||||
MethodType.methodType(Object.class, int.class));
|
||||
|
||||
private static MethodHandle GET_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "get",
|
||||
MethodType.methodType(Object.class, Object.class));
|
||||
|
||||
private static MethodHandle LIST_GUARD = Guards.getInstanceOfGuard(List.class);
|
||||
private static MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class);
|
||||
|
||||
private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor,
|
||||
final LinkerServices linkerServices, List<String> operations) throws Exception {
|
||||
final MethodType callSiteType = callSiteDescriptor.getMethodType();
|
||||
final Class<?> declaredType = callSiteType.parameterType(0);
|
||||
final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor,
|
||||
linkerServices, operations);
|
||||
|
||||
// If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
|
||||
// is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
|
||||
// dealing with an array, or a list or map, but hey...
|
||||
// Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
|
||||
// in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
|
||||
final GuardedInvocationComponent gic;;
|
||||
final boolean isMap;
|
||||
if(declaredType.isArray()) {
|
||||
gic = new GuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType));
|
||||
isMap = false;
|
||||
} else if(List.class.isAssignableFrom(declaredType)) {
|
||||
gic = new GuardedInvocationComponent(GET_LIST_ELEMENT);
|
||||
isMap = false;
|
||||
} else if(Map.class.isAssignableFrom(declaredType)) {
|
||||
gic = new GuardedInvocationComponent(GET_MAP_ELEMENT);
|
||||
isMap = true;
|
||||
} else if(clazz.isArray()) {
|
||||
gic = getClassGuardedInvocationComponent(MethodHandles.arrayElementGetter(clazz), callSiteType);
|
||||
isMap = false;
|
||||
} else if(List.class.isAssignableFrom(clazz)) {
|
||||
gic = new GuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class,
|
||||
ValidationType.INSTANCE_OF);
|
||||
isMap = false;
|
||||
} else if(Map.class.isAssignableFrom(clazz)) {
|
||||
gic = new GuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class,
|
||||
ValidationType.INSTANCE_OF);
|
||||
isMap = true;
|
||||
} else {
|
||||
// Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
|
||||
return nextComponent;
|
||||
}
|
||||
|
||||
// We can have "dyn:getElem:foo", especially in composites, i.e. "dyn:getElem|getProp|getMethod:foo"
|
||||
final String fixedKey = getFixedKey(callSiteDescriptor);
|
||||
// Convert the key to a number if we're working with a list or array
|
||||
final Object typedFixedKey;
|
||||
if(!isMap && fixedKey != null) {
|
||||
typedFixedKey = convertKeyToInteger(fixedKey, linkerServices);
|
||||
if(typedFixedKey == null) {
|
||||
// key is not numeric, it can never succeed
|
||||
return nextComponent;
|
||||
}
|
||||
} else {
|
||||
typedFixedKey = fixedKey;
|
||||
}
|
||||
|
||||
final GuardedInvocation gi = gic.getGuardedInvocation();
|
||||
final Binder binder = new Binder(linkerServices, callSiteType, typedFixedKey);
|
||||
final MethodHandle invocation = gi.getInvocation();
|
||||
|
||||
if(nextComponent == null) {
|
||||
return gic.replaceInvocation(binder.bind(invocation));
|
||||
} else {
|
||||
final MethodHandle checkGuard;
|
||||
if(invocation == GET_LIST_ELEMENT) {
|
||||
checkGuard = convertArgToInt(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
|
||||
} else if(invocation == GET_MAP_ELEMENT) {
|
||||
// TODO: A more complex solution could be devised for maps, one where we do a get() first, and fold it
|
||||
// into a GWT that tests if it returned null, and if it did, do another GWT with containsKey()
|
||||
// that returns constant null (on true), or falls back to next component (on false)
|
||||
checkGuard = CONTAINS_MAP;
|
||||
} else {
|
||||
checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
|
||||
}
|
||||
return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard),
|
||||
binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(),
|
||||
gic.getValidatorClass(), gic.getValidationType());
|
||||
}
|
||||
}
|
||||
|
||||
private static String getFixedKey(final CallSiteDescriptor callSiteDescriptor) {
|
||||
return callSiteDescriptor.getNameTokenCount() == 2 ? null : callSiteDescriptor.getNameToken(
|
||||
CallSiteDescriptor.NAME_OPERAND);
|
||||
}
|
||||
|
||||
private static Object convertKeyToInteger(String fixedKey, LinkerServices linkerServices) throws Exception {
|
||||
try {
|
||||
if(linkerServices.canConvert(String.class, Number.class)) {
|
||||
try {
|
||||
final Object val = linkerServices.getTypeConverter(String.class, Number.class).invoke(fixedKey);
|
||||
if(!(val instanceof Number)) {
|
||||
return null; // not a number
|
||||
}
|
||||
final Number n = (Number)val;
|
||||
if(n instanceof Integer) {
|
||||
return n;
|
||||
}
|
||||
final int intIndex = n.intValue();
|
||||
final double doubleValue = n.doubleValue();
|
||||
if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinites trigger IOOBE
|
||||
return null; // not an exact integer
|
||||
}
|
||||
return Integer.valueOf(intIndex);
|
||||
} catch(Exception|Error e) {
|
||||
throw e;
|
||||
} catch(Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
}
|
||||
return Integer.valueOf(fixedKey);
|
||||
} catch(NumberFormatException e) {
|
||||
// key is not a number
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodHandle convertArgToInt(MethodHandle mh, LinkerServices ls, CallSiteDescriptor desc) {
|
||||
final Class<?> sourceType = desc.getMethodType().parameterType(1);
|
||||
if(TypeUtilities.isMethodInvocationConvertible(sourceType, Number.class)) {
|
||||
return mh;
|
||||
} else if(ls.canConvert(sourceType, Number.class)) {
|
||||
final MethodHandle converter = ls.getTypeConverter(sourceType, Number.class);
|
||||
return MethodHandles.filterArguments(mh, 1, converter.asType(converter.type().changeReturnType(
|
||||
mh.type().parameterType(1))));
|
||||
}
|
||||
return mh;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains methods to adapt an item getter/setter method handle to the requested type, optionally binding it to a
|
||||
* fixed key first.
|
||||
* @author Attila Szegedi
|
||||
* @version $Id: $
|
||||
*/
|
||||
private static class Binder {
|
||||
private final LinkerServices linkerServices;
|
||||
private final MethodType methodType;
|
||||
private final Object fixedKey;
|
||||
|
||||
Binder(LinkerServices linkerServices, MethodType methodType, Object fixedKey) {
|
||||
this.linkerServices = linkerServices;
|
||||
this.methodType = fixedKey == null ? methodType : methodType.insertParameterTypes(1, fixedKey.getClass());
|
||||
this.fixedKey = fixedKey;
|
||||
}
|
||||
|
||||
/*private*/ MethodHandle bind(MethodHandle handle) {
|
||||
return bindToFixedKey(linkerServices.asType(handle, methodType));
|
||||
}
|
||||
|
||||
/*private*/ MethodHandle bindTest(MethodHandle handle) {
|
||||
return bindToFixedKey(Guards.asType(handle, methodType));
|
||||
}
|
||||
|
||||
private MethodHandle bindToFixedKey(MethodHandle handle) {
|
||||
return fixedKey == null ? handle : MethodHandles.insertArguments(handle, 1, fixedKey);
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodHandle RANGE_CHECK_ARRAY = findRangeCheck(Object.class);
|
||||
private static MethodHandle RANGE_CHECK_LIST = findRangeCheck(List.class);
|
||||
private static MethodHandle CONTAINS_MAP = Lookup.PUBLIC.findVirtual(Map.class, "containsKey",
|
||||
MethodType.methodType(boolean.class, Object.class));
|
||||
|
||||
private static MethodHandle findRangeCheck(Class<?> collectionType) {
|
||||
return Lookup.findOwnStatic(MethodHandles.lookup(), "rangeCheck", boolean.class, collectionType, Object.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final boolean rangeCheck(Object array, Object index) {
|
||||
if(!(index instanceof Number)) {
|
||||
return false;
|
||||
}
|
||||
final Number n = (Number)index;
|
||||
final int intIndex = n.intValue();
|
||||
final double doubleValue = n.doubleValue();
|
||||
if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinite trigger IOOBE
|
||||
return false;
|
||||
}
|
||||
if(0 <= intIndex && intIndex < Array.getLength(array)) {
|
||||
return true;
|
||||
}
|
||||
throw new ArrayIndexOutOfBoundsException("Array index out of range: " + n);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final boolean rangeCheck(List<?> list, Object index) {
|
||||
if(!(index instanceof Number)) {
|
||||
return false;
|
||||
}
|
||||
final Number n = (Number)index;
|
||||
final int intIndex = n.intValue();
|
||||
final double doubleValue = n.doubleValue();
|
||||
if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinite trigger IOOBE
|
||||
return false;
|
||||
}
|
||||
if(0 <= intIndex && intIndex < list.size()) {
|
||||
return true;
|
||||
}
|
||||
throw new IndexOutOfBoundsException("Index: " + n + ", Size: " + list.size());
|
||||
}
|
||||
|
||||
private static MethodHandle SET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "set",
|
||||
MethodType.methodType(Object.class, int.class, Object.class));
|
||||
|
||||
private static MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put",
|
||||
MethodType.methodType(Object.class, Object.class, Object.class));
|
||||
|
||||
private GuardedInvocationComponent getElementSetter(CallSiteDescriptor callSiteDescriptor,
|
||||
LinkerServices linkerServices, List<String> operations) throws Exception {
|
||||
final MethodType callSiteType = callSiteDescriptor.getMethodType();
|
||||
final Class<?> declaredType = callSiteType.parameterType(0);
|
||||
|
||||
final GuardedInvocationComponent gic;
|
||||
// If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
|
||||
// is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
|
||||
// dealing with an array, or a list or map, but hey...
|
||||
// Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
|
||||
// in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
|
||||
final boolean isMap;
|
||||
if(declaredType.isArray()) {
|
||||
gic = new GuardedInvocationComponent(MethodHandles.arrayElementSetter(declaredType));
|
||||
isMap = false;
|
||||
} else if(List.class.isAssignableFrom(declaredType)) {
|
||||
gic = new GuardedInvocationComponent(SET_LIST_ELEMENT);
|
||||
isMap = false;
|
||||
} else if(Map.class.isAssignableFrom(declaredType)) {
|
||||
gic = new GuardedInvocationComponent(PUT_MAP_ELEMENT);
|
||||
isMap = true;
|
||||
} else if(clazz.isArray()) {
|
||||
gic = getClassGuardedInvocationComponent(MethodHandles.arrayElementSetter(clazz), callSiteType);
|
||||
isMap = false;
|
||||
} else if(List.class.isAssignableFrom(clazz)) {
|
||||
gic = new GuardedInvocationComponent(SET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class,
|
||||
ValidationType.INSTANCE_OF);
|
||||
isMap = false;
|
||||
} else if(Map.class.isAssignableFrom(clazz)) {
|
||||
gic = new GuardedInvocationComponent(PUT_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class,
|
||||
ValidationType.INSTANCE_OF);
|
||||
isMap = true;
|
||||
} else {
|
||||
// Can't set elements for objects that are neither arrays, nor list, nor maps.
|
||||
gic = null;
|
||||
isMap = false;
|
||||
}
|
||||
|
||||
// In contrast to, say, getElementGetter, we only compute the nextComponent if the target object is not a map,
|
||||
// as maps will always succeed in setting the element and will never need to fall back to the next component
|
||||
// operation.
|
||||
final GuardedInvocationComponent nextComponent = isMap ? null : getGuardedInvocationComponent(
|
||||
callSiteDescriptor, linkerServices, operations);
|
||||
if(gic == null) {
|
||||
return nextComponent;
|
||||
}
|
||||
|
||||
// We can have "dyn:setElem:foo", especially in composites, i.e. "dyn:setElem|setProp:foo"
|
||||
final String fixedKey = getFixedKey(callSiteDescriptor);
|
||||
// Convert the key to a number if we're working with a list or array
|
||||
final Object typedFixedKey;
|
||||
if(!isMap && fixedKey != null) {
|
||||
typedFixedKey = convertKeyToInteger(fixedKey, linkerServices);
|
||||
if(typedFixedKey == null) {
|
||||
// key is not numeric, it can never succeed
|
||||
return nextComponent;
|
||||
}
|
||||
} else {
|
||||
typedFixedKey = fixedKey;
|
||||
}
|
||||
|
||||
final GuardedInvocation gi = gic.getGuardedInvocation();
|
||||
final Binder binder = new Binder(linkerServices, callSiteType, typedFixedKey);
|
||||
final MethodHandle invocation = gi.getInvocation();
|
||||
|
||||
if(nextComponent == null) {
|
||||
return gic.replaceInvocation(binder.bind(invocation));
|
||||
} else {
|
||||
final MethodHandle checkGuard = convertArgToInt(invocation == SET_LIST_ELEMENT ? RANGE_CHECK_LIST :
|
||||
RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
|
||||
return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard),
|
||||
binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(),
|
||||
gic.getValidatorClass(), gic.getValidationType());
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodHandle GET_ARRAY_LENGTH = Lookup.PUBLIC.findStatic(Array.class, "getLength",
|
||||
MethodType.methodType(int.class, Object.class));
|
||||
|
||||
private static MethodHandle GET_COLLECTION_LENGTH = Lookup.PUBLIC.findVirtual(Collection.class, "size",
|
||||
MethodType.methodType(int.class));
|
||||
|
||||
private static MethodHandle GET_MAP_LENGTH = Lookup.PUBLIC.findVirtual(Map.class, "size",
|
||||
MethodType.methodType(int.class));
|
||||
|
||||
private static MethodHandle COLLECTION_GUARD = Guards.getInstanceOfGuard(Collection.class);
|
||||
|
||||
private GuardedInvocationComponent getLengthGetter(CallSiteDescriptor callSiteDescriptor) {
|
||||
assertParameterCount(callSiteDescriptor, 1);
|
||||
final MethodType callSiteType = callSiteDescriptor.getMethodType();
|
||||
final Class<?> declaredType = callSiteType.parameterType(0);
|
||||
// If declared type of receiver at the call site is already an array, collection, or map, bind without guard.
|
||||
// Thing is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance
|
||||
// they're dealing with an array, collection, or map, but hey...
|
||||
if(declaredType.isArray()) {
|
||||
return new GuardedInvocationComponent(GET_ARRAY_LENGTH.asType(callSiteType));
|
||||
} else if(Collection.class.isAssignableFrom(declaredType)) {
|
||||
return new GuardedInvocationComponent(GET_COLLECTION_LENGTH.asType(callSiteType));
|
||||
} else if(Map.class.isAssignableFrom(declaredType)) {
|
||||
return new GuardedInvocationComponent(GET_MAP_LENGTH.asType(callSiteType));
|
||||
}
|
||||
|
||||
// Otherwise, create a binding based on the actual type of the argument with an appropriate guard.
|
||||
if(clazz.isArray()) {
|
||||
return new GuardedInvocationComponent(GET_ARRAY_LENGTH.asType(callSiteType), Guards.isArray(0,
|
||||
callSiteType), ValidationType.IS_ARRAY);
|
||||
} if(Collection.class.isAssignableFrom(clazz)) {
|
||||
return new GuardedInvocationComponent(GET_COLLECTION_LENGTH.asType(callSiteType), Guards.asType(
|
||||
COLLECTION_GUARD, callSiteType), Collection.class, ValidationType.INSTANCE_OF);
|
||||
} if(Map.class.isAssignableFrom(clazz)) {
|
||||
return new GuardedInvocationComponent(GET_MAP_LENGTH.asType(callSiteType), Guards.asType(MAP_GUARD,
|
||||
callSiteType), Map.class, ValidationType.INSTANCE_OF);
|
||||
}
|
||||
// Can't retrieve length for objects that are neither arrays, nor collections, nor maps.
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void assertParameterCount(CallSiteDescriptor descriptor, int paramCount) {
|
||||
if(descriptor.getMethodType().parameterCount() != paramCount) {
|
||||
throw new BootstrapMethodError(descriptor.getName() + " must have exactly " + paramCount + " parameters.");
|
||||
}
|
||||
}
|
||||
}
|
180
nashorn/src/jdk/internal/dynalink/beans/BeansLinker.java
Normal file
180
nashorn/src/jdk/internal/dynalink/beans/BeansLinker.java
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.DynamicLinkerFactory;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
|
||||
|
||||
|
||||
/**
|
||||
* A linker for POJOs. Normally used as the ultimate fallback linker by the {@link DynamicLinkerFactory} so it is given
|
||||
* the chance to link calls to all objects that no other language runtime recognizes. Specifically, this linker will:
|
||||
* <ul>
|
||||
* <li>expose all public methods of form {@code setXxx()}, {@code getXxx()}, and {@code isXxx()} as property setters and
|
||||
* getters for {@code dyn:setProp} and {@code dyn:getProp} operations;</li>
|
||||
* <li>expose all property getters and setters declared by the class' {@link BeanInfo};</li>
|
||||
* <li>expose all public methods and methods declared by the class' {@link BeanInfo} for invocation through
|
||||
* {@code dyn:callMethod} operation;</li>
|
||||
* <li>expose all public methods and methods declared by the class' {@link BeanInfo} for retrieval for
|
||||
* {@code dyn:getMethod} operation; the methods thus retrieved can then be invoked using {@code dyn:call};</li>
|
||||
* <li>expose all public fields as properties, unless there are getters or setters for the properties of the same name;</li>
|
||||
* <li>expose {@code dyn:getLength}, {@code dyn:getElem} and {@code dyn:setElem} on native Java arrays, as well as
|
||||
* {@link java.util.List} and {@link java.util.Map} objects; ({@code dyn:getLength} works on any
|
||||
* {@link java.util.Collection});</li>
|
||||
* <li>expose a virtual property named {@code length} on Java arrays;</li>
|
||||
* <li>expose {@code dyn:new} on instances of {@link StaticClass} as calls to constructors, including those static class
|
||||
* objects that represent Java arrays (their constructors take a single {@code int} parameter representing the length of
|
||||
* the array to create);</li>
|
||||
* <li>expose static methods, fields, and properties of classes in a similar manner to how instance method, fields, and
|
||||
* properties are exposed, on {@link StaticClass} objects.</li>
|
||||
* <li>expose a virtual property named {@code static} on instances of {@link java.lang.Class} to access their
|
||||
* {@link StaticClass}.</li>
|
||||
* </ul>
|
||||
* <p><strong>Overloaded method resolution</strong> is performed automatically for property setters, methods, and
|
||||
* constructors. Additionally, manual overloaded method selection is supported by having a call site specify a name for
|
||||
* a method that contains an explicit signature, i.e. {@code dyn:getMethod:parseInt(String,int)}. You can use
|
||||
* non-qualified class names in such signatures regardless of those classes' packages, they will match any class with
|
||||
* the same non-qualified name. You only have to use a fully qualified class name in case non-qualified class names
|
||||
* would cause selection ambiguity (that is extremely rare).</p>
|
||||
* <p><strong>Variable argument invocation</strong> is handled for both methods and constructors.</p>
|
||||
* <p>Currently, only public fields and methods are supported. Any Lookup objects passed in the
|
||||
* {@link LinkRequest}s are ignored and {@link MethodHandles#publicLookup()} is used instead.</p>
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class BeansLinker implements GuardingDynamicLinker {
|
||||
private static final ClassValue<TypeBasedGuardingDynamicLinker> linkers = new ClassValue<TypeBasedGuardingDynamicLinker>() {
|
||||
@Override
|
||||
protected TypeBasedGuardingDynamicLinker computeValue(Class<?> clazz) {
|
||||
// If ClassValue.put() were public, we could just pre-populate with these known mappings...
|
||||
return
|
||||
clazz == Class.class ? new ClassLinker() :
|
||||
clazz == StaticClass.class ? new StaticClassLinker() :
|
||||
DynamicMethod.class.isAssignableFrom(clazz) ? new DynamicMethodLinker() :
|
||||
new BeanLinker(clazz);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new POJO linker.
|
||||
*/
|
||||
public BeansLinker() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a bean linker for a particular single class. Useful when you need to override or extend the behavior of
|
||||
* linking for some classes in your language runtime's linker, but still want to delegate to the default behavior in
|
||||
* some cases.
|
||||
* @param clazz the class
|
||||
* @return a bean linker for that class
|
||||
*/
|
||||
public static TypeBasedGuardingDynamicLinker getLinkerForClass(Class<?> clazz) {
|
||||
return linkers.get(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices)
|
||||
throws Exception {
|
||||
final CallSiteDescriptor callSiteDescriptor = request.getCallSiteDescriptor();
|
||||
final int l = callSiteDescriptor.getNameTokenCount();
|
||||
// All names conforming to the dynalang MOP should have at least two tokens, the first one being "dyn"
|
||||
if(l < 2 || "dyn" != callSiteDescriptor.getNameToken(CallSiteDescriptor.SCHEME)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Object receiver = request.getReceiver();
|
||||
if(receiver == null) {
|
||||
// Can't operate on null
|
||||
return null;
|
||||
}
|
||||
return getLinkerForClass(receiver.getClass()).getGuardedInvocation(request, linkerServices);
|
||||
}
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* A utility class to check whether a given class is in a package with restricted access e.g. "sun.*" etc. See
|
||||
* {@link CheckRestrictedPackageInternal} for implementation details.
|
||||
*/
|
||||
class CheckRestrictedPackage {
|
||||
/**
|
||||
* Returns true if the class is either not public, or it resides in a package with restricted access.
|
||||
* @param clazz the class to test
|
||||
* @return true if the class is either not public, or it resides in a package with restricted access.
|
||||
*/
|
||||
static boolean isRestrictedClass(Class<?> clazz) {
|
||||
return !Modifier.isPublic(clazz.getModifiers()) ||
|
||||
(System.getSecurityManager() != null && isRestrictedPackage(clazz.getPackage()));
|
||||
}
|
||||
|
||||
private static boolean isRestrictedPackage(Package pkg) {
|
||||
// Note: we broke out the actual implementation into CheckRestrictedPackageInternal, so we only load it when
|
||||
// needed - that is, if we need to check a non-public class with a non-null package, in presence of a security
|
||||
// manager.
|
||||
return pkg == null ? false : CheckRestrictedPackageInternal.isRestrictedPackageName(pkg.getName());
|
||||
}
|
||||
}
|
@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.AccessController;
|
||||
import java.security.Permissions;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.security.SecureClassLoader;
|
||||
|
||||
/**
|
||||
* A utility class to check whether a given class is in a package with restricted access e.g. "sun.*". These packages
|
||||
* are normally listed in the security property "package.access" for most JRE implementations, although we fortunately
|
||||
* don't rely on it but solely on {@link SecurityManager#checkPackageAccess(String)}).
|
||||
*
|
||||
* This class accomplishes the check in a fashion that works reliably even if Dynalink itself (and all the code on the
|
||||
* stack that led to the invocation) has the permission to access the restricted package.
|
||||
*
|
||||
* If Dynalink has a broad set of privileges (notably, it is loaded from boot or extension class path), then it loads
|
||||
* the {@link RestrictedPackageTester} class into a isolated secure class loader that gives it no permissions
|
||||
* whatsoever, and uses this completely unprivileged class to subsequently invoke
|
||||
* {@link SecurityManager#checkPackageAccess(String)}. This will reliably throw a {@link SecurityException} for every
|
||||
* restricted package even if Dynalink and other code on the stack have the requisite {@code "accessClassInPackage.*"}
|
||||
* {@link RuntimePermission} privilege.
|
||||
*
|
||||
* On the other hand, if Dynalink does not have a broad set of privileges normally granted by the boot or extension
|
||||
* class path, it will probably lack the privilege to create a new secure class loader into which to load the tester
|
||||
* class. In this case, it will invoke {@link SecurityManager#checkPackageAccess(String)} itself with the reasoning that
|
||||
* it will also be sufficient to discover whether a package is restricted or not.
|
||||
*
|
||||
* The rationale for this design is that if Dynalink is running as part of a privileged classpath - boot or extension
|
||||
* class path, it will have all privileges, so a security manager's package access check might succeed if all other code
|
||||
* on the stack when requesting linking with a particular restricted class is also privileged. A subsequent linking
|
||||
* request from less privileged code would then also succeed in requesting methods in privileged package. On the other
|
||||
* hand, if Dynalink is privileged, it will be able to delegate the package access check to the unprivileged class and
|
||||
* narrow the access based on its result. Finally, if Dynalink itself is unprivileged, it will not be able to load the
|
||||
* unprivileged class, but then it will also fail the security manager's package access.
|
||||
*
|
||||
* With this design, Dynalink effectively restrains itself from giving unauthorized access to restricted packages from
|
||||
* classes doing the linking in case it itself has access to those packages. The only way to defeat it would be to
|
||||
* selectively give Dynalink some {@code "accessClassInPackage.*"} permissions while denying it the privilege to
|
||||
* manipulate class loaders.
|
||||
*/
|
||||
class CheckRestrictedPackageInternal {
|
||||
private static final MethodHandle PACKAGE_ACCESS_CHECK = getPackageAccessCheckMethod();
|
||||
private static final String TESTER_CLASS_NAME = "jdk.internal.dynalink.beans.RestrictedPackageTester";
|
||||
|
||||
/**
|
||||
* Returns true if the specified package has restricted access.
|
||||
* @param pkgName the name of the package to check.
|
||||
* @return true if the specified package has restricted access, false otherwise.
|
||||
* @throws NullPointerException if pkgName is null, or if there is {@link System#getSecurityManager()} returns null
|
||||
* as this method is only expected to be invoked in the presence of a security manager.
|
||||
*/
|
||||
static boolean isRestrictedPackageName(String pkgName) {
|
||||
try {
|
||||
if(PACKAGE_ACCESS_CHECK != null) {
|
||||
// If we were able to load our unprivileged tester class, use it to check package access
|
||||
try {
|
||||
PACKAGE_ACCESS_CHECK.invokeExact(pkgName);
|
||||
} catch(Error|RuntimeException e) {
|
||||
throw e;
|
||||
} catch(Throwable t) {
|
||||
throw new RuntimeException(t);
|
||||
}
|
||||
} else {
|
||||
// If we didn't have sufficient permissions to load our unprivileged tester class, we're definitely not
|
||||
// running in a privileged class path, so invoking SecurityManager.checkPackageAccess() directly should
|
||||
// have the same effect as going through an unprivileged tester.
|
||||
System.getSecurityManager().checkPackageAccess(pkgName);
|
||||
}
|
||||
return false;
|
||||
} catch(SecurityException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static MethodHandle getPackageAccessCheckMethod() {
|
||||
try {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<MethodHandle>() {
|
||||
@Override
|
||||
public MethodHandle run() {
|
||||
return getPackageAccessCheckMethodInternal();
|
||||
}
|
||||
});
|
||||
} catch(SecurityException e) {
|
||||
// We don't have sufficient privileges to load our tester class into a separate protection domain, so just
|
||||
// return null so isRestrictedPackageName() will default to itself invoking
|
||||
// SecurityManager.checkPackageAccess().
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static MethodHandle getPackageAccessCheckMethodInternal() {
|
||||
try {
|
||||
// Can't use MethodHandles.lookup().findStatic() -- even though both this class and the loaded class are in
|
||||
// the same package, findStatic() will throw an IllegalAccessException since they have different class
|
||||
// loaders. That's why we have to use unreflect with a setAccessible(true)...
|
||||
final Method m = getTesterClass().getDeclaredMethod("checkPackageAccess", String.class);
|
||||
m.setAccessible(true);
|
||||
return MethodHandles.lookup().unreflect(m);
|
||||
} catch(IllegalAccessException|NoSuchMethodException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Class<?> getTesterClass() {
|
||||
final ClassLoader loader = getTesterClassLoader();
|
||||
try {
|
||||
final Class<?> checkerClass = Class.forName(TESTER_CLASS_NAME, true, loader);
|
||||
// Sanity check to ensure we didn't accidentally pick up the class from elsewhere
|
||||
if(checkerClass.getClassLoader() != loader) {
|
||||
throw new AssertionError(TESTER_CLASS_NAME + " was loaded from a different class loader");
|
||||
}
|
||||
return checkerClass;
|
||||
} catch(ClassNotFoundException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static ClassLoader getTesterClassLoader() {
|
||||
// We deliberately override loadClass instead of findClass so that we don't give a chance to finding this
|
||||
// class already loaded anywhere else. Not that there's a big possibility for this, especially since the parent
|
||||
// class loader is the bootstrap class loader, but still...
|
||||
return new SecureClassLoader(null) {
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
if(name.equals(TESTER_CLASS_NAME)) {
|
||||
final byte[] bytes = getTesterClassBytes();
|
||||
// Define the class with a protection domain that grants no permissions.
|
||||
Class<?> clazz = defineClass(name, bytes, 0, bytes.length, new ProtectionDomain(null,
|
||||
new Permissions()));
|
||||
if(resolve) {
|
||||
resolveClass(clazz);
|
||||
}
|
||||
return clazz;
|
||||
} else {
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static byte[] getTesterClassBytes() {
|
||||
try {
|
||||
final InputStream in = CheckRestrictedPackage.class.getResourceAsStream("RestrictedPackageTester.class");
|
||||
try {
|
||||
final ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
|
||||
for(;;) {
|
||||
final int b = in.read();
|
||||
if(b == -1) {
|
||||
break;
|
||||
}
|
||||
out.write(b);
|
||||
}
|
||||
return out.toByteArray();
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
110
nashorn/src/jdk/internal/dynalink/beans/ClassLinker.java
Normal file
110
nashorn/src/jdk/internal/dynalink/beans/ClassLinker.java
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType;
|
||||
import jdk.internal.dynalink.support.Lookup;
|
||||
|
||||
|
||||
/**
|
||||
* A linker for java.lang.Class objects. Provides a synthetic property "static" that allows access to static fields and
|
||||
* methods on the class (respecting property getter/setter conventions). Note that Class objects are not recognized by
|
||||
* the Dynalink as constructors for the instances of the class, {@link StaticClass} is used for this purpose.
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
class ClassLinker extends BeanLinker {
|
||||
|
||||
ClassLinker() {
|
||||
super(Class.class);
|
||||
// Map "classObject.static" to StaticClass.forClass(classObject). Can use EXACT_CLASS since class Class is final.
|
||||
setPropertyGetter("static", FOR_CLASS, ValidationType.EXACT_CLASS);
|
||||
}
|
||||
|
||||
private static final MethodHandle FOR_CLASS = new Lookup(MethodHandles.lookup()).findStatic(StaticClass.class,
|
||||
"forClass", MethodType.methodType(StaticClass.class, Class.class));
|
||||
|
||||
}
|
209
nashorn/src/jdk/internal/dynalink/beans/ClassString.java
Normal file
209
nashorn/src/jdk/internal/dynalink/beans/ClassString.java
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.support.Guards;
|
||||
import jdk.internal.dynalink.support.TypeUtilities;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
final class ClassString {
|
||||
private final Class<?>[] classes;
|
||||
private int hashCode;
|
||||
|
||||
ClassString(Class<?>[] classes) {
|
||||
this.classes = classes;
|
||||
}
|
||||
|
||||
ClassString(MethodType type) {
|
||||
this(type.parameterArray());
|
||||
}
|
||||
|
||||
Class<?>[] getClasses() {
|
||||
return classes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if(!(other instanceof ClassString)) {
|
||||
return false;
|
||||
}
|
||||
final Class<?>[] otherClasses = ((ClassString)other).classes;
|
||||
if(otherClasses.length != classes.length) {
|
||||
return false;
|
||||
}
|
||||
for(int i = 0; i < otherClasses.length; ++i) {
|
||||
if(otherClasses[i] != classes[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if(hashCode == 0) {
|
||||
int h = 0;
|
||||
for(int i = 0; i < classes.length; ++i) {
|
||||
h ^= classes[i].hashCode();
|
||||
}
|
||||
hashCode = h;
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
boolean isVisibleFrom(final ClassLoader classLoader) {
|
||||
for(int i = 0; i < classes.length; ++i) {
|
||||
if(!Guards.canReferenceDirectly(classLoader, classes[i].getClassLoader())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
List<MethodHandle> getMaximallySpecifics(List<MethodHandle> methods, LinkerServices linkerServices, boolean varArg) {
|
||||
return MaximallySpecific.getMaximallySpecificMethods(getApplicables(methods, linkerServices, varArg), varArg,
|
||||
classes, linkerServices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all methods that are applicable to actual parameter classes represented by this ClassString object.
|
||||
*/
|
||||
LinkedList<MethodHandle> getApplicables(List<MethodHandle> methods, LinkerServices linkerServices, boolean varArg) {
|
||||
final LinkedList<MethodHandle> list = new LinkedList<>();
|
||||
for(final MethodHandle member: methods) {
|
||||
if(isApplicable(member, linkerServices, varArg)) {
|
||||
list.add(member);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the supplied method is applicable to actual parameter classes represented by this ClassString
|
||||
* object.
|
||||
*
|
||||
*/
|
||||
private boolean isApplicable(MethodHandle method, LinkerServices linkerServices, boolean varArg) {
|
||||
final Class<?>[] formalTypes = method.type().parameterArray();
|
||||
final int cl = classes.length;
|
||||
final int fl = formalTypes.length - (varArg ? 1 : 0);
|
||||
if(varArg) {
|
||||
if(cl < fl) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(cl != fl) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Starting from 1 as we ignore the receiver type
|
||||
for(int i = 1; i < fl; ++i) {
|
||||
if(!canConvert(linkerServices, classes[i], formalTypes[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(varArg) {
|
||||
final Class<?> varArgType = formalTypes[fl].getComponentType();
|
||||
for(int i = fl; i < cl; ++i) {
|
||||
if(!canConvert(linkerServices, classes[i], varArgType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean canConvert(LinkerServices ls, Class<?> from, Class<?> to) {
|
||||
return ls == null ? TypeUtilities.isMethodInvocationConvertible(from, to) : ls.canConvert(from, to);
|
||||
}
|
||||
}
|
169
nashorn/src/jdk/internal/dynalink/beans/DynamicMethod.java
Normal file
169
nashorn/src/jdk/internal/dynalink/beans/DynamicMethod.java
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.StringTokenizer;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a single dynamic method. A "dynamic" method can be bound to a single Java method, or can be bound to all
|
||||
* overloaded methods of the same name on a class. Getting an invocation of a dynamic method bound to multiple
|
||||
* overloaded methods will perform overload resolution (actually, it will perform partial overloaded resolution at link
|
||||
* time, but if that fails to identify exactly one target method, it will generate a method handle that will perform the
|
||||
* rest of the overload resolution at invocation time for actual argument types).
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
abstract class DynamicMethod {
|
||||
private final String name;
|
||||
|
||||
DynamicMethod(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an invocation for the dynamic method. If the method is overloaded, it will perform overloaded method
|
||||
* resolution based on the specified method type. The resulting resolution can either identify a single method to be
|
||||
* invoked among the overloads, or it can identify multiple ones. In the latter case, the returned method handle
|
||||
* will perform further overload resolution among these candidates at every invocation. If the method to be invoked
|
||||
* is a variable arguments (vararg) method, it will pack the extra arguments in an array before the invocation of
|
||||
* the underlying method if it is not already done.
|
||||
*
|
||||
* @param callSiteType the method type at a call site
|
||||
* @param linkerServices linker services. Used for language-specific type conversions.
|
||||
* @return an invocation suitable for calling the method from the specified call site.
|
||||
*/
|
||||
abstract MethodHandle getInvocation(MethodType callSiteType, LinkerServices linkerServices);
|
||||
|
||||
/**
|
||||
* Returns a simple dynamic method representing a single underlying Java method (possibly selected among several
|
||||
* overloads) with formal parameter types exactly matching the passed signature.
|
||||
* @param paramTypes the comma-separated list of requested parameter type names. The names will match both
|
||||
* qualified and unqualified type names.
|
||||
* @return a simple dynamic method representing a single underlying Java method, or null if none of the Java methods
|
||||
* behind this dynamic method exactly match the requested parameter types.
|
||||
*/
|
||||
abstract SimpleDynamicMethod getMethodForExactParamTypes(String paramTypes);
|
||||
|
||||
/**
|
||||
* True if this dynamic method already contains a method handle with an identical signature as the passed in method
|
||||
* handle.
|
||||
* @param mh the method handle to check
|
||||
* @return true if it already contains an equivalent method handle.
|
||||
*/
|
||||
abstract boolean contains(MethodHandle mh);
|
||||
|
||||
static boolean typeMatchesDescription(String paramTypes, MethodType type) {
|
||||
final StringTokenizer tok = new StringTokenizer(paramTypes, ", ");
|
||||
for(int i = 1; i < type.parameterCount(); ++i) { // i = 1 as we ignore the receiver
|
||||
if(!(tok.hasMoreTokens() && typeNameMatches(tok.nextToken(), type.parameterType(i)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !tok.hasMoreTokens();
|
||||
}
|
||||
|
||||
private static boolean typeNameMatches(String typeName, Class<?> type) {
|
||||
final int lastDot = typeName.lastIndexOf('.');
|
||||
final String fullTypeName = type.getCanonicalName();
|
||||
return lastDot != -1 && fullTypeName.endsWith(typeName.substring(lastDot)) || typeName.equals(fullTypeName);
|
||||
}
|
||||
|
||||
static String getClassAndMethodName(Class<?> clazz, String name) {
|
||||
final String clazzName = clazz.getCanonicalName();
|
||||
return (clazzName == null ? clazz.getName() : clazzName) + "." + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + getClass().getName() + " " + getName() + "]";
|
||||
}
|
||||
}
|
130
nashorn/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java
Normal file
130
nashorn/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.support.Guards;
|
||||
|
||||
|
||||
/**
|
||||
* Simple linker that implements the "dyn:call" operation for {@link DynamicMethod} objects - the objects returned by
|
||||
* "dyn:getMethod" from {@link AbstractJavaLinker}.
|
||||
*/
|
||||
class DynamicMethodLinker implements TypeBasedGuardingDynamicLinker {
|
||||
@Override
|
||||
public boolean canLinkType(Class<?> type) {
|
||||
return DynamicMethod.class.isAssignableFrom(type);
|
||||
};
|
||||
|
||||
@Override
|
||||
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) {
|
||||
final Object receiver = linkRequest.getReceiver();
|
||||
if(!(receiver instanceof DynamicMethod)) {
|
||||
return null;
|
||||
}
|
||||
final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
|
||||
if(desc.getNameTokenCount() != 2 && desc.getNameToken(CallSiteDescriptor.SCHEME) != "dyn") {
|
||||
return null;
|
||||
}
|
||||
final String operator = desc.getNameToken(CallSiteDescriptor.OPERATOR);
|
||||
if(operator == "call") {
|
||||
final MethodType type = desc.getMethodType();
|
||||
final MethodHandle invocation = ((DynamicMethod)receiver).getInvocation(type.dropParameterTypes(0, 1),
|
||||
linkerServices);
|
||||
if(invocation == null) {
|
||||
return null;
|
||||
}
|
||||
return new GuardedInvocation(MethodHandles.dropArguments(invocation, 0, type.parameterType(0)),
|
||||
Guards.getIdentityGuard(receiver));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
188
nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java
Normal file
188
nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import jdk.internal.dynalink.support.Lookup;
|
||||
|
||||
|
||||
/**
|
||||
* Base for classes that expose class field and method information to an {@link AbstractJavaLinker}. There are
|
||||
* subclasses for instance (bean) and static facet of a class.
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
abstract class FacetIntrospector implements AutoCloseable {
|
||||
private final Class<?> clazz;
|
||||
private final boolean instance;
|
||||
private final boolean isRestricted;
|
||||
|
||||
protected final AccessibleMembersLookup membersLookup;
|
||||
|
||||
FacetIntrospector(Class<?> clazz, boolean instance) {
|
||||
this.clazz = clazz;
|
||||
this.instance = instance;
|
||||
isRestricted = CheckRestrictedPackage.isRestrictedClass(clazz);
|
||||
membersLookup = new AccessibleMembersLookup(clazz, instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns getters for inner classes.
|
||||
* @return getters for inner classes.
|
||||
*/
|
||||
abstract Map<String, MethodHandle> getInnerClassGetters();
|
||||
|
||||
/**
|
||||
* Returns the fields for the class facet.
|
||||
* @return the fields for the class facet.
|
||||
*/
|
||||
Collection<Field> getFields() {
|
||||
if(isRestricted) {
|
||||
// NOTE: we can't do anything here. Unlike with methods in AccessibleMethodsLookup, we can't just return
|
||||
// the fields from a public superclass, because this class might define same-named fields which will shadow
|
||||
// the superclass fields, and we have no way to know if they do, since we're denied invocation of
|
||||
// getFields(). Therefore, the only correct course of action is to not expose any public fields from a class
|
||||
// defined in a restricted package.
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
final Field[] fields = clazz.getFields();
|
||||
final Collection<Field> cfields = new ArrayList<>(fields.length);
|
||||
for(Field field: fields) {
|
||||
if(instance != Modifier.isStatic(field.getModifiers()) && isAccessible(field)) {
|
||||
cfields.add(field);
|
||||
}
|
||||
}
|
||||
return cfields;
|
||||
}
|
||||
|
||||
boolean isAccessible(Member m) {
|
||||
final Class<?> declaring = m.getDeclaringClass();
|
||||
// (declaring == clazz) is just an optimization - we're calling this only from code that operates on a
|
||||
// non-restriced class, so if the declaring class is identical to the class being inspected, then forego
|
||||
// a potentially expensive restricted-package check.
|
||||
return declaring == clazz || !CheckRestrictedPackage.isRestrictedClass(declaring);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the methods in the facet.
|
||||
* @return all the methods in the facet.
|
||||
*/
|
||||
Collection<Method> getMethods() {
|
||||
return membersLookup.getMethods();
|
||||
}
|
||||
|
||||
|
||||
MethodHandle unreflectGetter(Field field) {
|
||||
return editMethodHandle(Lookup.PUBLIC.unreflectGetter(field));
|
||||
}
|
||||
|
||||
MethodHandle unreflectSetter(Field field) {
|
||||
return editMethodHandle(Lookup.PUBLIC.unreflectSetter(field));
|
||||
}
|
||||
|
||||
MethodHandle unreflect(Method method) {
|
||||
return editMethodHandle(Lookup.PUBLIC.unreflect(method));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an edited method handle. A facet might need to edit an unreflected method handle before it is usable with
|
||||
* the facet. By default, returns the passed method handle unchanged. The class' static facet will introduce a
|
||||
* dropArguments.
|
||||
* @param mh the method handle to edit.
|
||||
* @return the edited method handle.
|
||||
*/
|
||||
abstract MethodHandle editMethodHandle(MethodHandle mh);
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
}
|
||||
}
|
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
|
||||
|
||||
/**
|
||||
* Represents one component for a GuardedInvocation of a potentially composite operation of an
|
||||
* {@link AbstractJavaLinker}. In addition to holding a guarded invocation, it holds semantic information about its
|
||||
* guard. All guards produced in the AbstractJavaLinker are either "Class.isInstance()" or "getClass() == clazz"
|
||||
* expressions. This allows choosing the most restrictive guard as the guard for the composition of two components.
|
||||
* @author Attila Szegedi
|
||||
* @version $Id: $
|
||||
*/
|
||||
class GuardedInvocationComponent {
|
||||
enum ValidationType {
|
||||
NONE, // No guard; the operation can be linked unconditionally (quite rare); least strict.
|
||||
INSTANCE_OF, // "validatorClass.isInstance(obj)" guard
|
||||
EXACT_CLASS, // "obj.getClass() == validatorClass" guard; most strict.
|
||||
IS_ARRAY, // "obj.getClass().isArray()"
|
||||
}
|
||||
|
||||
private final GuardedInvocation guardedInvocation;
|
||||
private final Validator validator;
|
||||
|
||||
GuardedInvocationComponent(MethodHandle invocation) {
|
||||
this(invocation, null, ValidationType.NONE);
|
||||
}
|
||||
|
||||
GuardedInvocationComponent(MethodHandle invocation, MethodHandle guard, ValidationType validationType) {
|
||||
this(invocation, guard, null, validationType);
|
||||
}
|
||||
|
||||
GuardedInvocationComponent(MethodHandle invocation, MethodHandle guard, Class<?> validatorClass,
|
||||
ValidationType validationType) {
|
||||
this(invocation, guard, new Validator(validatorClass, validationType));
|
||||
}
|
||||
|
||||
GuardedInvocationComponent(GuardedInvocation guardedInvocation, Class<?> validatorClass,
|
||||
ValidationType validationType) {
|
||||
this(guardedInvocation, new Validator(validatorClass, validationType));
|
||||
}
|
||||
|
||||
GuardedInvocationComponent replaceInvocation(MethodHandle newInvocation) {
|
||||
return replaceInvocation(newInvocation, guardedInvocation.getGuard());
|
||||
}
|
||||
|
||||
GuardedInvocationComponent replaceInvocation(MethodHandle newInvocation, MethodHandle newGuard) {
|
||||
return new GuardedInvocationComponent(guardedInvocation.replaceMethods(newInvocation,
|
||||
newGuard), validator);
|
||||
}
|
||||
|
||||
private GuardedInvocationComponent(MethodHandle invocation, MethodHandle guard, Validator validator) {
|
||||
this(new GuardedInvocation(invocation, guard), validator);
|
||||
}
|
||||
|
||||
private GuardedInvocationComponent(GuardedInvocation guardedInvocation, Validator validator) {
|
||||
this.guardedInvocation = guardedInvocation;
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
GuardedInvocation getGuardedInvocation() {
|
||||
return guardedInvocation;
|
||||
}
|
||||
|
||||
Class<?> getValidatorClass() {
|
||||
return validator.validatorClass;
|
||||
}
|
||||
|
||||
ValidationType getValidationType() {
|
||||
return validator.validationType;
|
||||
}
|
||||
|
||||
GuardedInvocationComponent compose(MethodHandle compositeInvocation, MethodHandle otherGuard,
|
||||
Class<?> otherValidatorClass, ValidationType otherValidationType) {
|
||||
final Validator compositeValidator = validator.compose(new Validator(otherValidatorClass, otherValidationType));
|
||||
final MethodHandle compositeGuard = compositeValidator == validator ? guardedInvocation.getGuard() : otherGuard;
|
||||
return new GuardedInvocationComponent(compositeInvocation, compositeGuard, compositeValidator);
|
||||
}
|
||||
|
||||
private static class Validator {
|
||||
/*private*/ final Class<?> validatorClass;
|
||||
/*private*/ final ValidationType validationType;
|
||||
|
||||
Validator(Class<?> validatorClass, ValidationType validationType) {
|
||||
this.validatorClass = validatorClass;
|
||||
this.validationType = validationType;
|
||||
}
|
||||
|
||||
Validator compose(Validator other) {
|
||||
if(other.validationType == ValidationType.NONE) {
|
||||
return this;
|
||||
}
|
||||
switch(validationType) {
|
||||
case NONE:
|
||||
return other;
|
||||
case INSTANCE_OF:
|
||||
switch(other.validationType) {
|
||||
case INSTANCE_OF:
|
||||
if(isAssignableFrom(other)) {
|
||||
return other;
|
||||
} else if(other.isAssignableFrom(this)) {
|
||||
return this;
|
||||
}
|
||||
break;
|
||||
case EXACT_CLASS:
|
||||
if(isAssignableFrom(other)) {
|
||||
return other;
|
||||
}
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
if(validatorClass.isArray()) {
|
||||
return this;
|
||||
}
|
||||
break;
|
||||
case NONE:
|
||||
throw new AssertionError(); // Not possible
|
||||
}
|
||||
break;
|
||||
case EXACT_CLASS:
|
||||
switch(other.validationType) {
|
||||
case INSTANCE_OF:
|
||||
if(other.isAssignableFrom(this)) {
|
||||
return this;
|
||||
}
|
||||
break;
|
||||
case EXACT_CLASS:
|
||||
if(validatorClass == other.validatorClass) {
|
||||
return this;
|
||||
}
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
if(validatorClass.isArray()) {
|
||||
return this;
|
||||
}
|
||||
break;
|
||||
case NONE:
|
||||
throw new AssertionError(); // Not possible
|
||||
}
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
switch(other.validationType) {
|
||||
case INSTANCE_OF:
|
||||
case EXACT_CLASS:
|
||||
if(other.validatorClass.isArray()) {
|
||||
return other;
|
||||
}
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
return this;
|
||||
case NONE:
|
||||
throw new AssertionError(); // Not possible
|
||||
}
|
||||
break;
|
||||
}
|
||||
throw new AssertionError("Incompatible composition " + this + " vs " + other);
|
||||
}
|
||||
|
||||
private boolean isAssignableFrom(Validator other) {
|
||||
return validatorClass.isAssignableFrom(other.validatorClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Validator[" + validationType + (validatorClass == null ? "" : (" " + validatorClass.getName())) + "]";
|
||||
}
|
||||
}
|
||||
}
|
211
nashorn/src/jdk/internal/dynalink/beans/MaximallySpecific.java
Normal file
211
nashorn/src/jdk/internal/dynalink/beans/MaximallySpecific.java
Normal file
@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.support.TypeUtilities;
|
||||
|
||||
|
||||
/**
|
||||
* Utility class that encapsulates the algorithm for choosing the maximally specific methods.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
class MaximallySpecific {
|
||||
/**
|
||||
* Given a list of methods, returns a list of maximally specific methods.
|
||||
*
|
||||
* @param methods the list of methods
|
||||
* @param varArgs whether to assume the methods are varargs
|
||||
* @return the list of maximally specific methods.
|
||||
*/
|
||||
static List<MethodHandle> getMaximallySpecificMethods(List<MethodHandle> methods, boolean varArgs) {
|
||||
return getMaximallySpecificMethods(methods, varArgs, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of methods, returns a list of maximally specific methods, applying language-runtime specific
|
||||
* conversion preferences.
|
||||
*
|
||||
* @param methods the list of methods
|
||||
* @param varArgs whether to assume the methods are varargs
|
||||
* @param argTypes concrete argument types for the invocation
|
||||
* @return the list of maximally specific methods.
|
||||
*/
|
||||
static List<MethodHandle> getMaximallySpecificMethods(List<MethodHandle> methods, boolean varArgs,
|
||||
Class<?>[] argTypes, LinkerServices ls) {
|
||||
if(methods.size() < 2) {
|
||||
return methods;
|
||||
}
|
||||
final LinkedList<MethodHandle> maximals = new LinkedList<>();
|
||||
for(MethodHandle m: methods) {
|
||||
final MethodType methodType = m.type();
|
||||
boolean lessSpecific = false;
|
||||
for(Iterator<MethodHandle> maximal = maximals.iterator(); maximal.hasNext();) {
|
||||
final MethodHandle max = maximal.next();
|
||||
switch(isMoreSpecific(methodType, max.type(), varArgs, argTypes, ls)) {
|
||||
case TYPE_1_BETTER: {
|
||||
maximal.remove();
|
||||
break;
|
||||
}
|
||||
case TYPE_2_BETTER: {
|
||||
lessSpecific = true;
|
||||
break;
|
||||
}
|
||||
case INDETERMINATE: {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!lessSpecific) {
|
||||
maximals.addLast(m);
|
||||
}
|
||||
}
|
||||
return maximals;
|
||||
}
|
||||
|
||||
private static Comparison isMoreSpecific(MethodType t1, MethodType t2, boolean varArgs, Class<?>[] argTypes,
|
||||
LinkerServices ls) {
|
||||
final int pc1 = t1.parameterCount();
|
||||
final int pc2 = t2.parameterCount();
|
||||
assert varArgs || (pc1 == pc2) && (argTypes == null || argTypes.length == pc1);
|
||||
assert (argTypes == null) == (ls == null);
|
||||
final int maxPc = Math.max(Math.max(pc1, pc2), argTypes == null ? 0 : argTypes.length);
|
||||
boolean t1MoreSpecific = false;
|
||||
boolean t2MoreSpecific = false;
|
||||
// NOTE: Starting from 1 as overloaded method resolution doesn't depend on 0th element, which is the type of
|
||||
// 'this'. We're only dealing with instance methods here, not static methods. Actually, static methods will have
|
||||
// a fake 'this' of type StaticClass.
|
||||
for(int i = 1; i < maxPc; ++i) {
|
||||
final Class<?> c1 = getParameterClass(t1, pc1, i, varArgs);
|
||||
final Class<?> c2 = getParameterClass(t2, pc2, i, varArgs);
|
||||
if(c1 != c2) {
|
||||
final Comparison cmp = compare(c1, c2, argTypes, i, ls);
|
||||
if(cmp == Comparison.TYPE_1_BETTER && !t1MoreSpecific) {
|
||||
t1MoreSpecific = true;
|
||||
if(t2MoreSpecific) {
|
||||
return Comparison.INDETERMINATE;
|
||||
}
|
||||
}
|
||||
if(cmp == Comparison.TYPE_2_BETTER && !t2MoreSpecific) {
|
||||
t2MoreSpecific = true;
|
||||
if(t1MoreSpecific) {
|
||||
return Comparison.INDETERMINATE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(t1MoreSpecific) {
|
||||
return Comparison.TYPE_1_BETTER;
|
||||
} else if(t2MoreSpecific) {
|
||||
return Comparison.TYPE_2_BETTER;
|
||||
}
|
||||
return Comparison.INDETERMINATE;
|
||||
}
|
||||
|
||||
private static Comparison compare(Class<?> c1, Class<?> c2, Class<?>[] argTypes, int i, LinkerServices cmp) {
|
||||
if(cmp != null) {
|
||||
final Comparison c = cmp.compareConversion(argTypes[i], c1, c2);
|
||||
if(c != Comparison.INDETERMINATE) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
if(TypeUtilities.isSubtype(c1, c2)) {
|
||||
return Comparison.TYPE_1_BETTER;
|
||||
} if(TypeUtilities.isSubtype(c2, c1)) {
|
||||
return Comparison.TYPE_2_BETTER;
|
||||
}
|
||||
return Comparison.INDETERMINATE;
|
||||
}
|
||||
|
||||
private static Class<?> getParameterClass(MethodType t, int l, int i, boolean varArgs) {
|
||||
return varArgs && i >= l - 1 ? t.parameterType(l - 1).getComponentType() : t.parameterType(i);
|
||||
}
|
||||
}
|
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import jdk.internal.dynalink.beans.ApplicableOverloadedMethods.ApplicabilityTest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.support.TypeUtilities;
|
||||
|
||||
|
||||
/**
|
||||
* Represents an overloaded method.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
class OverloadedDynamicMethod extends DynamicMethod {
|
||||
/**
|
||||
* Holds a list of all methods.
|
||||
*/
|
||||
private final LinkedList<MethodHandle> methods;
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
/**
|
||||
* Creates a new overloaded dynamic method.
|
||||
*
|
||||
* @param clazz the class this method belongs to
|
||||
* @param name the name of the method
|
||||
*/
|
||||
OverloadedDynamicMethod(Class<?> clazz, String name) {
|
||||
this(new LinkedList<MethodHandle>(), clazz.getClassLoader(), getClassAndMethodName(clazz, name));
|
||||
}
|
||||
|
||||
private OverloadedDynamicMethod(LinkedList<MethodHandle> methods, ClassLoader classLoader, String name) {
|
||||
super(name);
|
||||
this.methods = methods;
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
SimpleDynamicMethod getMethodForExactParamTypes(String paramTypes) {
|
||||
final LinkedList<MethodHandle> matchingMethods = new LinkedList<>();
|
||||
for(MethodHandle method: methods) {
|
||||
if(typeMatchesDescription(paramTypes, method.type())) {
|
||||
matchingMethods.add(method);
|
||||
}
|
||||
}
|
||||
switch(matchingMethods.size()) {
|
||||
case 0: {
|
||||
return null;
|
||||
}
|
||||
case 1: {
|
||||
final MethodHandle target = matchingMethods.get(0);
|
||||
return new SimpleDynamicMethod(target, SimpleDynamicMethod.getMethodNameWithSignature(target, getName()));
|
||||
}
|
||||
default: {
|
||||
throw new BootstrapMethodError("Can't choose among " + matchingMethods + " for argument types "
|
||||
+ paramTypes + " for method " + getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodHandle getInvocation(final MethodType callSiteType, final LinkerServices linkerServices) {
|
||||
// First, find all methods applicable to the call site by subtyping (JLS 15.12.2.2)
|
||||
final ApplicableOverloadedMethods subtypingApplicables = getApplicables(callSiteType,
|
||||
ApplicableOverloadedMethods.APPLICABLE_BY_SUBTYPING);
|
||||
// Next, find all methods applicable by method invocation conversion to the call site (JLS 15.12.2.3).
|
||||
final ApplicableOverloadedMethods methodInvocationApplicables = getApplicables(callSiteType,
|
||||
ApplicableOverloadedMethods.APPLICABLE_BY_METHOD_INVOCATION_CONVERSION);
|
||||
// Finally, find all methods applicable by variable arity invocation. (JLS 15.12.2.4).
|
||||
final ApplicableOverloadedMethods variableArityApplicables = getApplicables(callSiteType,
|
||||
ApplicableOverloadedMethods.APPLICABLE_BY_VARIABLE_ARITY);
|
||||
|
||||
// Find the methods that are maximally specific based on the call site signature
|
||||
List<MethodHandle> maximallySpecifics = subtypingApplicables.findMaximallySpecificMethods();
|
||||
if(maximallySpecifics.isEmpty()) {
|
||||
maximallySpecifics = methodInvocationApplicables.findMaximallySpecificMethods();
|
||||
if(maximallySpecifics.isEmpty()) {
|
||||
maximallySpecifics = variableArityApplicables.findMaximallySpecificMethods();
|
||||
}
|
||||
}
|
||||
|
||||
// Now, get a list of the rest of the methods; those that are *not* applicable to the call site signature based
|
||||
// on JLS rules. As paradoxical as that might sound, we have to consider these for dynamic invocation, as they
|
||||
// might match more concrete types passed in invocations. That's why we provisionally call them "invokables".
|
||||
// This is typical for very generic signatures at call sites. Typical example: call site specifies
|
||||
// (Object, Object), and we have a method whose parameter types are (String, int). None of the JLS applicability
|
||||
// rules will trigger, but we must consider the method, as it can be the right match for a concrete invocation.
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
final List<MethodHandle> invokables = (List)methods.clone();
|
||||
invokables.removeAll(subtypingApplicables.getMethods());
|
||||
invokables.removeAll(methodInvocationApplicables.getMethods());
|
||||
invokables.removeAll(variableArityApplicables.getMethods());
|
||||
for(final Iterator<MethodHandle> it = invokables.iterator(); it.hasNext();) {
|
||||
final MethodHandle m = it.next();
|
||||
if(!isApplicableDynamically(linkerServices, callSiteType, m)) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// If no additional methods can apply at invocation time, and there's more than one maximally specific method
|
||||
// based on call site signature, that is a link-time ambiguity. In a static scenario, javac would report an
|
||||
// ambiguity error.
|
||||
if(invokables.isEmpty() && maximallySpecifics.size() > 1) {
|
||||
throw new BootstrapMethodError("Can't choose among " + maximallySpecifics + " for argument types "
|
||||
+ callSiteType);
|
||||
}
|
||||
|
||||
// Merge them all.
|
||||
invokables.addAll(maximallySpecifics);
|
||||
switch(invokables.size()) {
|
||||
case 0: {
|
||||
// No overloads can ever match the call site type
|
||||
return null;
|
||||
}
|
||||
case 1: {
|
||||
// Very lucky, we ended up with a single candidate method handle based on the call site signature; we
|
||||
// can link it very simply by delegating to a SimpleDynamicMethod.
|
||||
final MethodHandle mh = invokables.iterator().next();
|
||||
return new SimpleDynamicMethod(mh).getInvocation(callSiteType, linkerServices);
|
||||
}
|
||||
}
|
||||
|
||||
// We have more than one candidate. We have no choice but to link to a method that resolves overloads on every
|
||||
// invocation (alternatively, we could opportunistically link the one method that resolves for the current
|
||||
// arguments, but we'd need to install a fairly complex guard for that and when it'd fail, we'd go back all the
|
||||
// way to candidate selection.
|
||||
// TODO: cache per call site type
|
||||
return new OverloadedMethod(invokables, this, callSiteType, linkerServices).getInvoker();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(MethodHandle mh) {
|
||||
final MethodType type = mh.type();
|
||||
for(MethodHandle method: methods) {
|
||||
if(typesEqualNoReceiver(type, method.type())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean typesEqualNoReceiver(MethodType type1, MethodType type2) {
|
||||
final int pc = type1.parameterCount();
|
||||
if(pc != type2.parameterCount()) {
|
||||
return false;
|
||||
}
|
||||
for(int i = 1; i < pc; ++i) { // i = 1: ignore receiver
|
||||
if(type1.parameterType(i) != type2.parameterType(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
private static boolean isApplicableDynamically(LinkerServices linkerServices, MethodType callSiteType,
|
||||
MethodHandle m) {
|
||||
final MethodType methodType = m.type();
|
||||
final boolean varArgs = m.isVarargsCollector();
|
||||
final int fixedArgLen = methodType.parameterCount() - (varArgs ? 1 : 0);
|
||||
final int callSiteArgLen = callSiteType.parameterCount();
|
||||
if(varArgs) {
|
||||
if(callSiteArgLen < fixedArgLen) {
|
||||
return false;
|
||||
}
|
||||
} else if(callSiteArgLen != fixedArgLen) {
|
||||
return false;
|
||||
}
|
||||
// Starting from 1, as receiver type doesn't participate
|
||||
for(int i = 1; i < fixedArgLen; ++i) {
|
||||
if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), methodType.parameterType(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(varArgs) {
|
||||
final Class<?> varArgArrayType = methodType.parameterType(fixedArgLen);
|
||||
final Class<?> varArgType = varArgArrayType.getComponentType();
|
||||
if(fixedArgLen == callSiteArgLen - 1) {
|
||||
final Class<?> callSiteArgType = callSiteType.parameterType(fixedArgLen);
|
||||
// Exactly one vararg; check both exact matching and component
|
||||
// matching.
|
||||
return isApplicableDynamically(linkerServices, callSiteArgType, varArgArrayType)
|
||||
|| isApplicableDynamically(linkerServices, callSiteArgType, varArgType);
|
||||
} else {
|
||||
for(int i = fixedArgLen; i < callSiteArgLen; ++i) {
|
||||
if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), varArgType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isApplicableDynamically(LinkerServices linkerServices, Class<?> callSiteType,
|
||||
Class<?> methodType) {
|
||||
return TypeUtilities.isPotentiallyConvertible(callSiteType, methodType)
|
||||
|| linkerServices.canConvert(callSiteType, methodType);
|
||||
}
|
||||
|
||||
private ApplicableOverloadedMethods getApplicables(MethodType callSiteType, ApplicabilityTest test) {
|
||||
return new ApplicableOverloadedMethods(methods, callSiteType, test);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a method identified by a {@link SimpleDynamicMethod} to this overloaded method's set.
|
||||
*
|
||||
* @param method the method to add.
|
||||
*/
|
||||
public void addMethod(SimpleDynamicMethod method) {
|
||||
addMethod(method.getTarget());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a method to this overloaded method's set.
|
||||
*
|
||||
* @param method a method to add
|
||||
*/
|
||||
public void addMethod(MethodHandle method) {
|
||||
methods.add(method);
|
||||
}
|
||||
}
|
266
nashorn/src/jdk/internal/dynalink/beans/OverloadedMethod.java
Normal file
266
nashorn/src/jdk/internal/dynalink/beans/OverloadedMethod.java
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.support.Lookup;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a subset of overloaded methods for a certain method name on a certain class. It can be either a fixarg or
|
||||
* a vararg subset depending on the subclass. The method is for a fixed number of arguments though (as it is generated
|
||||
* for a concrete call site). As such, all methods in the subset can be invoked with the specified number of arguments
|
||||
* (exactly matching for fixargs, or having less than or equal fixed arguments, for varargs).
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
class OverloadedMethod {
|
||||
private final Map<ClassString, MethodHandle> argTypesToMethods = new ConcurrentHashMap<>();
|
||||
private final OverloadedDynamicMethod parent;
|
||||
private final MethodType callSiteType;
|
||||
private final MethodHandle invoker;
|
||||
private final LinkerServices linkerServices;
|
||||
private final ArrayList<MethodHandle> fixArgMethods;
|
||||
private final ArrayList<MethodHandle> varArgMethods;
|
||||
|
||||
OverloadedMethod(List<MethodHandle> methodHandles, OverloadedDynamicMethod parent, MethodType callSiteType,
|
||||
LinkerServices linkerServices) {
|
||||
this.parent = parent;
|
||||
this.callSiteType = callSiteType;
|
||||
this.linkerServices = linkerServices;
|
||||
|
||||
fixArgMethods = new ArrayList<>(methodHandles.size());
|
||||
varArgMethods = new ArrayList<>(methodHandles.size());
|
||||
final int argNum = callSiteType.parameterCount();
|
||||
for(MethodHandle mh: methodHandles) {
|
||||
if(mh.isVarargsCollector()) {
|
||||
final MethodHandle asFixed = mh.asFixedArity();
|
||||
if(argNum == asFixed.type().parameterCount()) {
|
||||
fixArgMethods.add(asFixed);
|
||||
}
|
||||
varArgMethods.add(mh);
|
||||
} else {
|
||||
fixArgMethods.add(mh);
|
||||
}
|
||||
}
|
||||
fixArgMethods.trimToSize();
|
||||
varArgMethods.trimToSize();
|
||||
|
||||
final MethodHandle bound = SELECT_METHOD.bindTo(this);
|
||||
final MethodHandle collecting = SimpleDynamicMethod.collectArguments(bound, argNum).asType(
|
||||
callSiteType.changeReturnType(MethodHandle.class));
|
||||
invoker = MethodHandles.foldArguments(MethodHandles.exactInvoker(callSiteType), collecting);
|
||||
}
|
||||
|
||||
MethodHandle getInvoker() {
|
||||
return invoker;
|
||||
}
|
||||
|
||||
private static final MethodHandle SELECT_METHOD = Lookup.findOwnSpecial(MethodHandles.lookup(), "selectMethod",
|
||||
MethodHandle.class, Object[].class);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private MethodHandle selectMethod(Object[] args) throws NoSuchMethodException {
|
||||
final Class<?>[] argTypes = new Class[args.length];
|
||||
for(int i = 0; i < argTypes.length; ++i) {
|
||||
final Object arg = args[i];
|
||||
argTypes[i] = arg == null ? callSiteType.parameterType(i) : arg.getClass();
|
||||
}
|
||||
final ClassString classString = new ClassString(argTypes);
|
||||
MethodHandle method = argTypesToMethods.get(classString);
|
||||
if(method == null) {
|
||||
List<MethodHandle> methods = classString.getMaximallySpecifics(fixArgMethods, linkerServices, false);
|
||||
if(methods.isEmpty()) {
|
||||
methods = classString.getMaximallySpecifics(varArgMethods, linkerServices, true);
|
||||
}
|
||||
switch(methods.size()) {
|
||||
case 0: {
|
||||
method = getNoSuchMethodThrower(argTypes);
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
method = new SimpleDynamicMethod(methods.get(0)).getInvocation(callSiteType, linkerServices);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// This is unfortunate - invocation time ambiguity. We can still save the day if
|
||||
method = getAmbiguousMethodThrower(argTypes, methods);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Avoid keeping references to unrelated classes; this ruins the performance a bit, but avoids class loader
|
||||
// memory leaks.
|
||||
if(classString.isVisibleFrom(parent.getClassLoader())) {
|
||||
argTypesToMethods.put(classString, method);
|
||||
}
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
private MethodHandle getNoSuchMethodThrower(Class<?>[] argTypes) {
|
||||
return adaptThrower(MethodHandles.insertArguments(THROW_NO_SUCH_METHOD, 0, this, argTypes));
|
||||
}
|
||||
|
||||
private static final MethodHandle THROW_NO_SUCH_METHOD = Lookup.findOwnSpecial(MethodHandles.lookup(),
|
||||
"throwNoSuchMethod", void.class, Class[].class);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void throwNoSuchMethod(Class<?>[] argTypes) throws NoSuchMethodException {
|
||||
if(varArgMethods.isEmpty()) {
|
||||
throw new NoSuchMethodException("None of the fixed arity signatures " + getSignatureList(fixArgMethods) +
|
||||
" of method " + parent.getName() + " match the argument types " + argTypesString(argTypes));
|
||||
}
|
||||
throw new NoSuchMethodException("None of the fixed arity signatures " + getSignatureList(fixArgMethods) +
|
||||
" or the variable arity signatures " + getSignatureList(varArgMethods) + " of the method " +
|
||||
parent.getName() + " match the argument types " + argTypesString(argTypes));
|
||||
}
|
||||
|
||||
private MethodHandle getAmbiguousMethodThrower(Class<?>[] argTypes, List<MethodHandle> methods) {
|
||||
return adaptThrower(MethodHandles.insertArguments(THROW_AMBIGUOUS_METHOD, 0, this, argTypes, methods));
|
||||
}
|
||||
|
||||
private MethodHandle adaptThrower(MethodHandle rawThrower) {
|
||||
return MethodHandles.dropArguments(rawThrower, 0, callSiteType.parameterList()).asType(callSiteType);
|
||||
}
|
||||
|
||||
private static final MethodHandle THROW_AMBIGUOUS_METHOD = Lookup.findOwnSpecial(MethodHandles.lookup(),
|
||||
"throwAmbiguousMethod", void.class, Class[].class, List.class);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private void throwAmbiguousMethod(Class<?>[] argTypes, List<MethodHandle> methods) throws NoSuchMethodException {
|
||||
final String arity = methods.get(0).isVarargsCollector() ? "variable" : "fixed";
|
||||
throw new NoSuchMethodException("Can't unambiguously select between " + arity + " arity signatures " +
|
||||
getSignatureList(methods) + " of the method " + parent.getName() + " for argument types " +
|
||||
argTypesString(argTypes));
|
||||
}
|
||||
|
||||
private static String argTypesString(Class<?>[] classes) {
|
||||
final StringBuilder b = new StringBuilder().append('[');
|
||||
appendTypes(b, classes, false);
|
||||
return b.append(']').toString();
|
||||
}
|
||||
|
||||
private static String getSignatureList(List<MethodHandle> methods) {
|
||||
final StringBuilder b = new StringBuilder().append('[');
|
||||
final Iterator<MethodHandle> it = methods.iterator();
|
||||
if(it.hasNext()) {
|
||||
appendSig(b, it.next());
|
||||
while(it.hasNext()) {
|
||||
appendSig(b.append(", "), it.next());
|
||||
}
|
||||
}
|
||||
return b.append(']').toString();
|
||||
}
|
||||
|
||||
private static void appendSig(StringBuilder b, MethodHandle m) {
|
||||
b.append('(');
|
||||
appendTypes(b, m.type().parameterArray(), m.isVarargsCollector());
|
||||
b.append(')');
|
||||
}
|
||||
|
||||
private static void appendTypes(StringBuilder b, Class<?>[] classes, boolean varArg) {
|
||||
final int l = classes.length;
|
||||
if(!varArg) {
|
||||
if(l > 1) {
|
||||
b.append(classes[1].getCanonicalName());
|
||||
for(int i = 2; i < l; ++i) {
|
||||
b.append(", ").append(classes[i].getCanonicalName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(int i = 1; i < l - 1; ++i) {
|
||||
b.append(classes[i].getCanonicalName()).append(", ");
|
||||
}
|
||||
b.append(classes[l - 1].getComponentType().getCanonicalName()).append("...");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* This class is never referenced directly from code of any other class, but is loaded into a secure class loader that
|
||||
* gives it no permissions whatsoever, so it can be used to reliably test whether a given package has restricted access
|
||||
* or not. See {@link CheckRestrictedPackageInternal} for details.
|
||||
* @author Attila Szegedi
|
||||
* @version $Id: $
|
||||
*/
|
||||
class RestrictedPackageTester implements PrivilegedAction<Void> {
|
||||
|
||||
private final String pkgName;
|
||||
|
||||
private RestrictedPackageTester(String pkgName) {
|
||||
this.pkgName = pkgName;
|
||||
}
|
||||
|
||||
static void checkPackageAccess(String pkgName) {
|
||||
AccessController.doPrivileged(new RestrictedPackageTester(pkgName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void run() {
|
||||
System.getSecurityManager().checkPackageAccess(pkgName);
|
||||
return null;
|
||||
}
|
||||
}
|
241
nashorn/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java
Normal file
241
nashorn/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java
Normal file
@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Array;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.support.Guards;
|
||||
|
||||
|
||||
/**
|
||||
* A dynamic method bound to exactly one, non-overloaded Java method. Handles varargs.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
class SimpleDynamicMethod extends DynamicMethod {
|
||||
private final MethodHandle target;
|
||||
|
||||
/**
|
||||
* Creates a simple dynamic method with no name.
|
||||
* @param target the target method handle
|
||||
*/
|
||||
SimpleDynamicMethod(MethodHandle target) {
|
||||
this(target, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new simple dynamic method, with a name constructed from the class name, method name, and handle
|
||||
* signature.
|
||||
*
|
||||
* @param target the target method handle
|
||||
* @param clazz the class declaring the method
|
||||
* @param name the simple name of the method
|
||||
*/
|
||||
SimpleDynamicMethod(MethodHandle target, Class<?> clazz, String name) {
|
||||
this(target, getName(target, clazz, name));
|
||||
}
|
||||
|
||||
SimpleDynamicMethod(MethodHandle target, String name) {
|
||||
super(name);
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
private static String getName(MethodHandle target, Class<?> clazz, String name) {
|
||||
return getMethodNameWithSignature(target, getClassAndMethodName(clazz, name));
|
||||
}
|
||||
|
||||
static String getMethodNameWithSignature(MethodHandle target, String methodName) {
|
||||
final String typeStr = target.type().toString();
|
||||
final int retTypeIndex = typeStr.lastIndexOf(')') + 1;
|
||||
int secondParamIndex = typeStr.indexOf(',') + 1;
|
||||
if(secondParamIndex == 0) {
|
||||
secondParamIndex = retTypeIndex - 1;
|
||||
}
|
||||
return typeStr.substring(retTypeIndex) + " " + methodName + "(" + typeStr.substring(secondParamIndex, retTypeIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the target of this dynamic method
|
||||
*
|
||||
* @return the target of this dynamic method
|
||||
*/
|
||||
MethodHandle getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override
|
||||
SimpleDynamicMethod getMethodForExactParamTypes(String paramTypes) {
|
||||
return typeMatchesDescription(paramTypes, target.type()) ? this : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
MethodHandle getInvocation(MethodType callSiteType, LinkerServices linkerServices) {
|
||||
final MethodType methodType = target.type();
|
||||
final int paramsLen = methodType.parameterCount();
|
||||
final boolean varArgs = target.isVarargsCollector();
|
||||
final MethodHandle fixTarget = varArgs ? target.asFixedArity() : target;
|
||||
final int fixParamsLen = varArgs ? paramsLen - 1 : paramsLen;
|
||||
final int argsLen = callSiteType.parameterCount();
|
||||
if(argsLen < fixParamsLen) {
|
||||
// Less actual arguments than number of fixed declared arguments; can't invoke.
|
||||
return null;
|
||||
}
|
||||
// Method handle of the same number of arguments as the call site type
|
||||
if(argsLen == fixParamsLen) {
|
||||
// Method handle that matches the number of actual arguments as the number of fixed arguments
|
||||
final MethodHandle matchedMethod;
|
||||
if(varArgs) {
|
||||
// If vararg, add a zero-length array of the expected type as the last argument to signify no variable
|
||||
// arguments.
|
||||
// TODO: check whether collectArguments() would handle this too.
|
||||
matchedMethod = MethodHandles.insertArguments(fixTarget, fixParamsLen, Array.newInstance(
|
||||
methodType.parameterType(fixParamsLen).getComponentType(), 0));
|
||||
} else {
|
||||
// Otherwise, just use the method
|
||||
matchedMethod = fixTarget;
|
||||
}
|
||||
return createConvertingInvocation(matchedMethod, linkerServices, callSiteType);
|
||||
}
|
||||
|
||||
// What's below only works for varargs
|
||||
if(!varArgs) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Class<?> varArgType = methodType.parameterType(fixParamsLen);
|
||||
// Handle a somewhat sinister corner case: caller passes exactly one argument in the vararg position, and we
|
||||
// must handle both a prepacked vararg array as well as a genuine 1-long vararg sequence.
|
||||
if(argsLen == paramsLen) {
|
||||
final Class<?> callSiteLastArgType = callSiteType.parameterType(fixParamsLen);
|
||||
if(varArgType.isAssignableFrom(callSiteLastArgType)) {
|
||||
// Call site signature guarantees we'll always be passed a single compatible array; just link directly
|
||||
// to the method.
|
||||
return createConvertingInvocation(fixTarget, linkerServices, callSiteType);
|
||||
} else if(!linkerServices.canConvert(callSiteLastArgType, varArgType)) {
|
||||
// Call site signature guarantees the argument can definitely not be an array (i.e. it is primitive);
|
||||
// link immediately to a vararg-packing method handle.
|
||||
return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType);
|
||||
} else {
|
||||
// Call site signature makes no guarantees that the single argument in the vararg position will be
|
||||
// compatible across all invocations. Need to insert an appropriate guard and fall back to generic
|
||||
// vararg method when it is not.
|
||||
return MethodHandles.guardWithTest(Guards.isInstance(varArgType, fixParamsLen, callSiteType),
|
||||
createConvertingInvocation(fixTarget, linkerServices, callSiteType),
|
||||
createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType));
|
||||
}
|
||||
} else {
|
||||
// Remaining case: more than one vararg.
|
||||
return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(MethodHandle mh) {
|
||||
return target.type().parameterList().equals(mh.type().parameterList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a method handle out of the original target that will collect the varargs for the exact component type of
|
||||
* the varArg array. Note that this will nicely trigger language-specific type converters for exactly those varargs
|
||||
* for which it is necessary when later passed to linkerServices.convertArguments().
|
||||
*
|
||||
* @param target the original method handle
|
||||
* @param parameterCount the total number of arguments in the new method handle
|
||||
* @return a collecting method handle
|
||||
*/
|
||||
static MethodHandle collectArguments(MethodHandle target, final int parameterCount) {
|
||||
final MethodType methodType = target.type();
|
||||
final int fixParamsLen = methodType.parameterCount() - 1;
|
||||
final Class<?> arrayType = methodType.parameterType(fixParamsLen);
|
||||
return target.asCollector(arrayType, parameterCount - fixParamsLen);
|
||||
}
|
||||
|
||||
private static MethodHandle createConvertingInvocation(final MethodHandle sizedMethod,
|
||||
final LinkerServices linkerServices, final MethodType callSiteType) {
|
||||
return linkerServices.asType(sizedMethod, callSiteType);
|
||||
}
|
||||
}
|
138
nashorn/src/jdk/internal/dynalink/beans/StaticClass.java
Normal file
138
nashorn/src/jdk/internal/dynalink/beans/StaticClass.java
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* Object that represents the static facet of a class (its static methods, properties, and fields, as well as
|
||||
* construction of instances using "dyn:new"). Objects of this class are recognized by the {@link BeansLinker} as being
|
||||
* special, and operations on them will be linked against the represented class' static facet. The "class" synthetic
|
||||
* property is additionally recognized and returns the Java {@link Class} object, as per {@link #getRepresentedClass()}
|
||||
* method. Conversely, {@link Class} objects exposed through {@link BeansLinker} expose the "static" synthetic property
|
||||
* which returns an instance of this class.
|
||||
*/
|
||||
public class StaticClass implements Serializable {
|
||||
private static final ClassValue<StaticClass> staticClasses = new ClassValue<StaticClass>() {
|
||||
@Override
|
||||
protected StaticClass computeValue(Class<?> type) {
|
||||
return new StaticClass(type);
|
||||
}
|
||||
};
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final Class<?> clazz;
|
||||
|
||||
/*private*/ StaticClass(Class<?> clazz) {
|
||||
clazz.getClass(); // NPE check
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@link StaticClass} instance for the specified class.
|
||||
* @param clazz the class for which the static facet is requested.
|
||||
* @return the {@link StaticClass} instance representing the specified class.
|
||||
*/
|
||||
public static StaticClass forClass(Class<?> clazz) {
|
||||
return staticClasses.get(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the represented Java class.
|
||||
* @return the represented Java class.
|
||||
*/
|
||||
public Class<?> getRepresentedClass() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JavaClassStatics[" + clazz.getName() + "]";
|
||||
}
|
||||
|
||||
private Object readResolve() {
|
||||
return forClass(clazz);
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
class StaticClassIntrospector extends FacetIntrospector {
|
||||
StaticClassIntrospector(Class<?> clazz) {
|
||||
super(clazz, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
Map<String, MethodHandle> getInnerClassGetters() {
|
||||
final Map<String, MethodHandle> map = new HashMap<>();
|
||||
for(Class<?> innerClass: membersLookup.getInnerClasses()) {
|
||||
map.put(innerClass.getSimpleName(), editMethodHandle(MethodHandles.constant(StaticClass.class,
|
||||
StaticClass.forClass(innerClass))));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
MethodHandle editMethodHandle(MethodHandle mh) {
|
||||
MethodHandle newHandle = MethodHandles.dropArguments(mh, 0, Object.class);
|
||||
// NOTE: this is a workaround for the fact that dropArguments doesn't preserve vararg collector state.
|
||||
if(mh.isVarargsCollector() && !newHandle.isVarargsCollector()) {
|
||||
final MethodType type = mh.type();
|
||||
newHandle = newHandle.asVarargsCollector(type.parameterType(type.parameterCount() - 1));
|
||||
}
|
||||
return newHandle;
|
||||
}
|
||||
}
|
204
nashorn/src/jdk/internal/dynalink/beans/StaticClassLinker.java
Normal file
204
nashorn/src/jdk/internal/dynalink/beans/StaticClassLinker.java
Normal file
@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.beans;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.support.Lookup;
|
||||
|
||||
|
||||
/**
|
||||
* Provides a linker for the {@link StaticClass} objects.
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
class StaticClassLinker implements TypeBasedGuardingDynamicLinker {
|
||||
private final ClassValue<GuardingDynamicLinker> linkers = new ClassValue<GuardingDynamicLinker>() {
|
||||
@Override
|
||||
protected GuardingDynamicLinker computeValue(Class<?> clazz) {
|
||||
return new SingleClassStaticsLinker(clazz);
|
||||
}
|
||||
};
|
||||
|
||||
private static class SingleClassStaticsLinker extends AbstractJavaLinker {
|
||||
private final DynamicMethod constructor;
|
||||
|
||||
SingleClassStaticsLinker(Class<?> clazz) {
|
||||
super(clazz, IS_CLASS.bindTo(clazz));
|
||||
// Map "staticClassObject.class" to StaticClass.getRepresentedClass(). Some adventurous soul could subclass
|
||||
// StaticClass, so we use INSTANCE_OF validation instead of EXACT_CLASS.
|
||||
setPropertyGetter("class", GET_CLASS, ValidationType.INSTANCE_OF);
|
||||
constructor = createConstructorMethod(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dynamic method containing all overloads of a class' public constructor
|
||||
* @param clazz the target class
|
||||
* @return a dynamic method containing all overloads of a class' public constructor. If the class has no public
|
||||
* constructors, returns null.
|
||||
*/
|
||||
private static DynamicMethod createConstructorMethod(Class<?> clazz) {
|
||||
if(clazz.isArray()) {
|
||||
final MethodHandle boundArrayCtor = ARRAY_CTOR.bindTo(clazz.getComponentType());
|
||||
return new SimpleDynamicMethod(drop(boundArrayCtor.asType(boundArrayCtor.type().changeReturnType(
|
||||
clazz))), clazz, "<init>");
|
||||
}
|
||||
|
||||
final Constructor<?>[] ctrs = clazz.getConstructors();
|
||||
final List<MethodHandle> mhs = new ArrayList<>(ctrs.length);
|
||||
for(int i = 0; i < ctrs.length; ++i) {
|
||||
mhs.add(drop(Lookup.PUBLIC.unreflectConstructor(ctrs[i])));
|
||||
}
|
||||
return createDynamicMethod(mhs, clazz, "<init>");
|
||||
}
|
||||
|
||||
private static MethodHandle drop(MethodHandle mh) {
|
||||
return MethodHandles.dropArguments(mh, 0, StaticClass.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
FacetIntrospector createFacetIntrospector() {
|
||||
return new StaticClassIntrospector(clazz);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedInvocation getGuardedInvocation(LinkRequest request, LinkerServices linkerServices)
|
||||
throws Exception {
|
||||
final GuardedInvocation gi = super.getGuardedInvocation(request, linkerServices);
|
||||
if(gi != null) {
|
||||
return gi;
|
||||
}
|
||||
final CallSiteDescriptor desc = request.getCallSiteDescriptor();
|
||||
final String op = desc.getNameToken(CallSiteDescriptor.OPERATOR);
|
||||
final MethodType methodType = desc.getMethodType();
|
||||
if("new" == op && constructor != null) {
|
||||
final MethodHandle ctorInvocation = constructor.getInvocation(methodType, linkerServices);
|
||||
if(ctorInvocation != null) {
|
||||
return new GuardedInvocation(ctorInvocation, getClassGuard(methodType));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedInvocation getGuardedInvocation(LinkRequest request, LinkerServices linkerServices) throws Exception {
|
||||
final Object receiver = request.getReceiver();
|
||||
if(receiver instanceof StaticClass) {
|
||||
return linkers.get(((StaticClass)receiver).getRepresentedClass()).getGuardedInvocation(request,
|
||||
linkerServices);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canLinkType(Class<?> type) {
|
||||
return type == StaticClass.class;
|
||||
}
|
||||
|
||||
/*private*/ static final MethodHandle GET_CLASS = new Lookup(MethodHandles.lookup()).findVirtual(StaticClass.class,
|
||||
"getRepresentedClass", MethodType.methodType(Class.class));
|
||||
|
||||
/*private*/ static final MethodHandle IS_CLASS = new Lookup(MethodHandles.lookup()).findStatic(StaticClassLinker.class,
|
||||
"isClass", MethodType.methodType(Boolean.TYPE, Class.class, Object.class));
|
||||
|
||||
/*private*/ static final MethodHandle ARRAY_CTOR = Lookup.PUBLIC.findStatic(Array.class, "newInstance",
|
||||
MethodType.methodType(Object.class, Class.class, int.class));
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static boolean isClass(Class<?> clazz, Object obj) {
|
||||
return obj instanceof StaticClass && ((StaticClass)obj).getRepresentedClass() == clazz;
|
||||
}
|
||||
}
|
25
nashorn/src/jdk/internal/dynalink/beans/messages.properties
Normal file
25
nashorn/src/jdk/internal/dynalink/beans/messages.properties
Normal file
@ -0,0 +1,25 @@
|
||||
# Copyright 2009-2013 Attila Szegedi
|
||||
#
|
||||
# Licensed under either the Apache License, Version 2.0 (the "Apache
|
||||
# License") or the BSD License (the "BSD License"), with licensee
|
||||
# being free to choose either of the two at their discretion.
|
||||
#
|
||||
# You may not use this file except in compliance with either the Apache
|
||||
# License or the BSD License.
|
||||
#
|
||||
# A copy of the BSD License is available in the root directory of the
|
||||
# source distribution of the project under the file name
|
||||
# "Dynalink-License-BSD.txt".
|
||||
#
|
||||
# A copy of the Apache License is available in the root directory of the
|
||||
# source distribution of the project under the file name
|
||||
# "Dynalink-License-Apache-2.0.txt". Alternatively, you may obtain a
|
||||
# copy of the Apache License at <http://www.apache.org/licenses/LICENSE-2.0>
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See your chosen License for the specific language governing permissions
|
||||
# and limitations under that License.
|
||||
|
||||
couldNotDiscoverAccessibleMethods=Could not discover accessible methods of class {0}, trying its superclasses and interfaces.
|
86
nashorn/src/jdk/internal/dynalink/beans/package.html
Normal file
86
nashorn/src/jdk/internal/dynalink/beans/package.html
Normal file
@ -0,0 +1,86 @@
|
||||
<!--
|
||||
Copyright (c) 2010, 2013, 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.
|
||||
-->
|
||||
|
||||
<!--
|
||||
This file is available under and governed by the GNU General Public
|
||||
License version 2 only, as published by the Free Software Foundation.
|
||||
However, the following notice accompanied the original version of this
|
||||
file, and Oracle licenses the original version of this file under the BSD
|
||||
license:
|
||||
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-->
|
||||
<body>
|
||||
<p>
|
||||
Contains the linker for POJOs.
|
||||
</p>
|
||||
</body>
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.linker;
|
||||
|
||||
|
||||
/**
|
||||
* Optional interface to be implemented by {@link GuardingTypeConverterFactory} implementers. Language-specific
|
||||
* conversions can cause increased overloaded method resolution ambiguity, as many methods can become applicable because
|
||||
* of additional conversions. The static way of selecting the "most specific" method will fail more often, because there
|
||||
* will be multiple maximally specific method with unrelated signatures. In these cases, language runtimes can be asked
|
||||
* to resolve the ambiguity by expressing preferences for one conversion over the other.
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public interface ConversionComparator {
|
||||
/**
|
||||
* Enumeration of possible outcomes of comparing one conversion to another.
|
||||
*/
|
||||
enum Comparison {
|
||||
INDETERMINATE,
|
||||
TYPE_1_BETTER,
|
||||
TYPE_2_BETTER,
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines which of the two target types is the preferred conversion target from a source type.
|
||||
* @param sourceType the source type.
|
||||
* @param targetType1 one potential target type
|
||||
* @param targetType2 another potential target type.
|
||||
* @return one of Comparison constants that establish which - if any - of the target types is preferred for the
|
||||
* conversion.
|
||||
*/
|
||||
public Comparison compareConversion(Class<?> sourceType, Class<?> targetType1, Class<?> targetType2);
|
||||
}
|
315
nashorn/src/jdk/internal/dynalink/linker/GuardedInvocation.java
Normal file
315
nashorn/src/jdk/internal/dynalink/linker/GuardedInvocation.java
Normal file
@ -0,0 +1,315 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.linker;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.SwitchPoint;
|
||||
import java.lang.invoke.WrongMethodTypeException;
|
||||
import java.util.List;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.support.Guards;
|
||||
|
||||
|
||||
/**
|
||||
* Represents a conditionally valid method handle. It is an immutable triple of an invocation method handle, a guard
|
||||
* method handle that defines the applicability of the invocation handle, and a switch point that can be used for
|
||||
* external invalidation of the invocation handle. The invocation handle is suitable for invocation if the guard
|
||||
* handle returns true for its arguments, and as long as the switch point is not invalidated. Both the guard and the
|
||||
* switch point are optional; neither, one, or both can be present.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class GuardedInvocation {
|
||||
private final MethodHandle invocation;
|
||||
private final MethodHandle guard;
|
||||
private final SwitchPoint switchPoint;
|
||||
|
||||
/**
|
||||
* Creates a new guarded invocation.
|
||||
*
|
||||
* @param invocation the method handle representing the invocation. Must not be null.
|
||||
* @param guard the method handle representing the guard. Must have the same method type as the invocation, except
|
||||
* it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null to represent
|
||||
* an unconditional invocation, although that is unusual.
|
||||
* @throws NullPointerException if invocation is null.
|
||||
*/
|
||||
public GuardedInvocation(MethodHandle invocation, MethodHandle guard) {
|
||||
this(invocation, guard, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new guarded invocation.
|
||||
*
|
||||
* @param invocation the method handle representing the invocation. Must not be null.
|
||||
* @param guard the method handle representing the guard. Must have the same method type as the invocation, except
|
||||
* it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it
|
||||
* and the switch point are null, this represents an unconditional invocation, which is legal but unusual.
|
||||
* @param switchPoint the optional switch point that can be used to invalidate this linkage.
|
||||
* @throws NullPointerException if invocation is null.
|
||||
*/
|
||||
public GuardedInvocation(MethodHandle invocation, MethodHandle guard, SwitchPoint switchPoint) {
|
||||
invocation.getClass(); // NPE check
|
||||
this.invocation = invocation;
|
||||
this.guard = guard;
|
||||
this.switchPoint = switchPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new guarded invocation.
|
||||
*
|
||||
* @param invocation the method handle representing the invocation. Must not be null.
|
||||
* @param switchPoint the optional switch point that can be used to invalidate this linkage.
|
||||
* @param guard the method handle representing the guard. Must have the same method type as the invocation, except
|
||||
* it must return boolean. For some useful guards, check out the {@link Guards} class. It can be null. If both it
|
||||
* and the switch point are null, this represents an unconditional invocation, which is legal but unusual.
|
||||
* @throws NullPointerException if invocation is null.
|
||||
*/
|
||||
public GuardedInvocation(MethodHandle invocation, SwitchPoint switchPoint, MethodHandle guard) {
|
||||
this(invocation, guard, switchPoint);
|
||||
}
|
||||
/**
|
||||
* Returns the invocation method handle.
|
||||
*
|
||||
* @return the invocation method handle. It will never be null.
|
||||
*/
|
||||
public MethodHandle getInvocation() {
|
||||
return invocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the guard method handle.
|
||||
*
|
||||
* @return the guard method handle. Can be null.
|
||||
*/
|
||||
public MethodHandle getGuard() {
|
||||
return guard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the switch point that can be used to invalidate the invocation handle.
|
||||
*
|
||||
* @return the switch point that can be used to invalidate the invocation handle. Can be null.
|
||||
*/
|
||||
public SwitchPoint getSwitchPoint() {
|
||||
return switchPoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if and only if this guarded invocation has a switchpoint, and that switchpoint has been invalidated.
|
||||
* @return true if and only if this guarded invocation has a switchpoint, and that switchpoint has been invalidated.
|
||||
*/
|
||||
public boolean hasBeenInvalidated() {
|
||||
return switchPoint != null && switchPoint.hasBeenInvalidated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the invocation is of the specified type, and the guard (if present) is of the specified type with a
|
||||
* boolean return type.
|
||||
*
|
||||
* @param type the asserted type
|
||||
* @throws WrongMethodTypeException if the invocation and the guard are not of the expected method type.
|
||||
*/
|
||||
public void assertType(MethodType type) {
|
||||
assertType(invocation, type);
|
||||
if(guard != null) {
|
||||
assertType(guard, type.changeReturnType(Boolean.TYPE));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new guarded invocation with different methods, preserving the switch point.
|
||||
*
|
||||
* @param newInvocation the new invocation
|
||||
* @param newGuard the new guard
|
||||
* @return a new guarded invocation with the replaced methods and the same switch point as this invocation.
|
||||
*/
|
||||
public GuardedInvocation replaceMethods(MethodHandle newInvocation, MethodHandle newGuard) {
|
||||
return new GuardedInvocation(newInvocation, newGuard, switchPoint);
|
||||
}
|
||||
|
||||
private GuardedInvocation replaceMethodsOrThis(MethodHandle newInvocation, MethodHandle newGuard) {
|
||||
if(newInvocation == invocation && newGuard == guard) {
|
||||
return this;
|
||||
}
|
||||
return replaceMethods(newInvocation, newGuard);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the type of the invocation, as if {@link MethodHandle#asType(MethodType)} was applied to its invocation
|
||||
* and its guard, if it has one (with return type changed to boolean, and parameter count potentially truncated for
|
||||
* the guard). If the invocation already is of the required type, returns this object.
|
||||
* @param newType the new type of the invocation.
|
||||
* @return a guarded invocation with the new type applied to it.
|
||||
*/
|
||||
public GuardedInvocation asType(MethodType newType) {
|
||||
return replaceMethodsOrThis(invocation.asType(newType), guard == null ? null : Guards.asType(guard, newType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the type of the invocation, as if {@link LinkerServices#asType(MethodHandle, MethodType)} was applied to
|
||||
* its invocation and its guard, if it has one (with return type changed to boolean, and parameter count potentially
|
||||
* truncated for the guard). If the invocation already is of the required type, returns this object.
|
||||
* @param linkerServices the linker services to use for the conversion
|
||||
* @param newType the new type of the invocation.
|
||||
* @return a guarded invocation with the new type applied to it.
|
||||
*/
|
||||
public GuardedInvocation asType(LinkerServices linkerServices, MethodType newType) {
|
||||
return replaceMethodsOrThis(linkerServices.asType(invocation, newType), guard == null ? null :
|
||||
Guards.asType(linkerServices, guard, newType));
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the type of the invocation, as if {@link MethodHandle#asType(MethodType)} was applied to its invocation
|
||||
* and its guard, if it has one (with return type changed to boolean for guard). If the invocation already is of the
|
||||
* required type, returns this object.
|
||||
* @param desc a call descriptor whose method type is adapted.
|
||||
* @return a guarded invocation with the new type applied to it.
|
||||
*/
|
||||
public GuardedInvocation asType(CallSiteDescriptor desc) {
|
||||
return asType(desc.getMethodType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies argument filters to both the invocation and the guard (if there is one).
|
||||
* @param pos the position of the first argumen being filtered
|
||||
* @param filters the argument filters
|
||||
* @return a filtered invocation
|
||||
*/
|
||||
public GuardedInvocation filterArguments(int pos, MethodHandle... filters) {
|
||||
return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters), guard == null ? null :
|
||||
MethodHandles.filterArguments(guard, pos, filters));
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an invocation that drops arguments in both the invocation and the guard (if there is one).
|
||||
* @param pos the position of the first argument being dropped
|
||||
* @param valueTypes the types of the values being dropped
|
||||
* @return an invocation that drops arguments
|
||||
*/
|
||||
public GuardedInvocation dropArguments(int pos, List<Class<?>> valueTypes) {
|
||||
return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null :
|
||||
MethodHandles.dropArguments(guard, pos, valueTypes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an invocation that drops arguments in both the invocation and the guard (if there is one).
|
||||
* @param pos the position of the first argument being dropped
|
||||
* @param valueTypes the types of the values being dropped
|
||||
* @return an invocation that drops arguments
|
||||
*/
|
||||
public GuardedInvocation dropArguments(int pos, Class<?>... valueTypes) {
|
||||
return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null :
|
||||
MethodHandles.dropArguments(guard, pos, valueTypes));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Composes the invocation, switchpoint, and the guard into a composite method handle that knows how to fall back.
|
||||
* @param fallback the fallback method handle in case switchpoint is invalidated or guard returns false.
|
||||
* @return a composite method handle.
|
||||
*/
|
||||
public MethodHandle compose(MethodHandle fallback) {
|
||||
return compose(fallback, fallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes the invocation, switchpoint, and the guard into a composite method handle that knows how to fall back.
|
||||
* @param switchpointFallback the fallback method handle in case switchpoint is invalidated.
|
||||
* @param guardFallback the fallback method handle in case guard returns false.
|
||||
* @return a composite method handle.
|
||||
*/
|
||||
public MethodHandle compose(MethodHandle switchpointFallback, MethodHandle guardFallback) {
|
||||
final MethodHandle guarded =
|
||||
guard == null ? invocation : MethodHandles.guardWithTest(guard, invocation, guardFallback);
|
||||
return switchPoint == null ? guarded : switchPoint.guardWithTest(guarded, switchpointFallback);
|
||||
}
|
||||
|
||||
private static void assertType(MethodHandle mh, MethodType type) {
|
||||
if(!mh.type().equals(type)) {
|
||||
throw new WrongMethodTypeException("Expected type: " + type + " actual type: " + mh.type());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.linker;
|
||||
|
||||
/**
|
||||
* The base interface for language-specific dynamic linkers. Such linkers always have to produce method handles with
|
||||
* guards, as the validity of the method handle for calls at a call site inevitably depends on some condition (at the
|
||||
* very least, it depends on the receiver belonging to the language runtime of the linker). Language runtime
|
||||
* implementors will normally implement one for their own language, and declare it in the
|
||||
* <tt>META-INF/services/jdk.internal.dynalink.linker.GuardingDynamicLinker</tt> file within their JAR file.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public interface GuardingDynamicLinker {
|
||||
/**
|
||||
* Creates a guarded invocation appropriate for a particular invocation with the specified arguments at a call site.
|
||||
*
|
||||
* @param linkRequest the object describing the request for linking a particular invocation
|
||||
* @param linkerServices linker services
|
||||
* @return a guarded invocation with a method handle suitable for the arguments, as well as a guard condition that
|
||||
* if fails should trigger relinking. Must return null if it can't resolve the invocation. If the returned
|
||||
* invocation is unconditional (which is actually quite rare), the guard in the return value can be null. The
|
||||
* invocation can also have a switch point for asynchronous invalidation of the linkage. If the linker does not
|
||||
* recognize any native language runtime contexts in arguments, or does recognize its own, but receives a call site
|
||||
* descriptor without its recognized context in the arguments, it should invoke
|
||||
* {@link LinkRequest#withoutRuntimeContext()} and link for that.
|
||||
* @throws Exception if the operation fails for whatever reason
|
||||
*/
|
||||
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices)
|
||||
throws Exception;
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.linker;
|
||||
|
||||
import jdk.internal.dynalink.support.TypeUtilities;
|
||||
|
||||
/**
|
||||
* Optional interface that can be implemented by {@link GuardingDynamicLinker} implementations to provide
|
||||
* language-runtime specific implicit type conversion capabilities. Note that if you implement this interface, you will
|
||||
* very likely want to implement {@link ConversionComparator} interface too, as your additional language-specific
|
||||
* conversions, in absence of a strategy for prioritizing these conversions, will cause more ambiguity in selecting the
|
||||
* correct overload when trying to link to an overloaded POJO method.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public interface GuardingTypeConverterFactory {
|
||||
/**
|
||||
* Returns a guarded invocation that receives an Object of the specified source type and returns an Object converted
|
||||
* to the specified target type. The type of the invocation is targetType(sourceType), while the type of the guard
|
||||
* is boolean(sourceType). Note that this will never be invoked for type conversions allowed by the JLS 5.3 "Method
|
||||
* Invocation Conversion", see {@link TypeUtilities#isMethodInvocationConvertible(Class, Class)} for details. An
|
||||
* implementation can assume it is never requested to produce a converter for these conversions.
|
||||
*
|
||||
* @param sourceType source type
|
||||
* @param targetType the target type.
|
||||
* @return a guarded invocation that can take an object (if it passes guard) and returns another object that is its
|
||||
* representation coerced into the target type. In case the factory is certain it is unable to handle a conversion,
|
||||
* it can return null. In case the factory is certain that it can always handle the conversion, it can return an
|
||||
* unconditional invocation (one whose guard is null).
|
||||
* @throws Exception if there was an error during creation of the converter
|
||||
*/
|
||||
public GuardedInvocation convertToType(Class<?> sourceType, Class<?> targetType) throws Exception;
|
||||
}
|
149
nashorn/src/jdk/internal/dynalink/linker/LinkRequest.java
Normal file
149
nashorn/src/jdk/internal/dynalink/linker/LinkRequest.java
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.linker;
|
||||
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.DynamicLinkerFactory;
|
||||
|
||||
/**
|
||||
* Represents a request to link a particular invocation at a particular call site. Instances of these requests are being
|
||||
* passed to {@link GuardingDynamicLinker}.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public interface LinkRequest {
|
||||
/**
|
||||
* Returns the call site descriptor for the call site being linked.
|
||||
*
|
||||
* @return the call site descriptor for the call site being linked.
|
||||
*/
|
||||
public CallSiteDescriptor getCallSiteDescriptor();
|
||||
|
||||
/**
|
||||
* Returns the arguments for the invocation being linked. The returned array is a clone; modifications to it won't
|
||||
* affect the arguments in this request.
|
||||
*
|
||||
* @return the arguments for the invocation being linked.
|
||||
*/
|
||||
public Object[] getArguments();
|
||||
|
||||
/**
|
||||
* Returns the 0th argument for the invocation being linked; this is typically the receiver object.
|
||||
*
|
||||
* @return the receiver object.
|
||||
*/
|
||||
public Object getReceiver();
|
||||
|
||||
/**
|
||||
* Returns true if the call site is considered unstable, that is, it has been relinked more times than was
|
||||
* specified in {@link DynamicLinkerFactory#setUnstableRelinkThreshold(int)}. Linkers should use this as a
|
||||
* hint to prefer producing linkage that is more stable (its guard fails less frequently), even if that assumption
|
||||
* causes a less effective version of an operation to be linked. This is just a hint, of course, and linkers are
|
||||
* free to ignore this property.
|
||||
* @return true if the call site is considered unstable.
|
||||
*/
|
||||
public boolean isCallSiteUnstable();
|
||||
|
||||
/**
|
||||
* Returns a request stripped from runtime context arguments. Some language runtimes will include runtime-specific
|
||||
* context parameters in their call sites as few arguments between 0th argument "this" and the normal arguments. If
|
||||
* a linker does not recognize such contexts at all, or does not recognize the call site as one with its own
|
||||
* context, it can ask for the alternative link request with context parameters and arguments removed, and link
|
||||
* against it instead.
|
||||
*
|
||||
* @return the context-stripped request. If the link request does not have any language runtime specific context
|
||||
* parameters, the same link request is returned.
|
||||
*/
|
||||
public LinkRequest withoutRuntimeContext();
|
||||
|
||||
/**
|
||||
* Returns a request identical to this one with call site descriptor and arguments replaced with the ones specified.
|
||||
*
|
||||
* @param callSiteDescriptor the new call site descriptor
|
||||
* @param arguments the new arguments
|
||||
* @return a new request identical to this one, except with the call site descriptor and arguments replaced with the
|
||||
* specified ones.
|
||||
*/
|
||||
public LinkRequest replaceArguments(CallSiteDescriptor callSiteDescriptor, Object[] arguments);
|
||||
}
|
165
nashorn/src/jdk/internal/dynalink/linker/LinkerServices.java
Normal file
165
nashorn/src/jdk/internal/dynalink/linker/LinkerServices.java
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.linker;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.DynamicLinker;
|
||||
import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
|
||||
|
||||
|
||||
/**
|
||||
* Interface for services provided to {@link GuardingDynamicLinker} instances by the {@link DynamicLinker} that owns
|
||||
* them. You can think of it as the interface of the {@link DynamicLinker} that faces the {@link GuardingDynamicLinker}
|
||||
* s.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public interface LinkerServices {
|
||||
/**
|
||||
* Similar to {@link MethodHandle#asType(MethodType)} except it also hooks in method handles produced by
|
||||
* {@link GuardingTypeConverterFactory} implementations, providing for language-specific type coercing of
|
||||
* parameters. It will apply {@link MethodHandle#asType(MethodType)} for all primitive-to-primitive,
|
||||
* wrapper-to-primitive, primitive-to-wrapper conversions as well as for all upcasts. For all other conversions,
|
||||
* it'll insert {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters
|
||||
* provided by {@link GuardingTypeConverterFactory} implementations. It doesn't use language-specific conversions on
|
||||
* the return type.
|
||||
*
|
||||
* @param handle target method handle
|
||||
* @param fromType the types of source arguments
|
||||
* @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)} and
|
||||
* {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with
|
||||
* {@link GuardingTypeConverterFactory} produced type converters as filters.
|
||||
*/
|
||||
public MethodHandle asType(MethodHandle handle, MethodType fromType);
|
||||
|
||||
/**
|
||||
* Given a source and target type, returns a method handle that converts between them. Never returns null; in worst
|
||||
* case it will return an identity conversion (that might fail for some values at runtime). You rarely need to use
|
||||
* this method directly; you should mostly rely on {@link #asType(MethodHandle, MethodType)} instead. You really
|
||||
* only need this method if you have a piece of your program that is written in Java, and you need to reuse existing
|
||||
* type conversion machinery in a non-invokedynamic context.
|
||||
* @param sourceType the type to convert from
|
||||
* @param targetType the type to convert to
|
||||
* @return a method handle performing the conversion.
|
||||
*/
|
||||
public MethodHandle getTypeConverter(Class<?> sourceType, Class<?> targetType);
|
||||
|
||||
/**
|
||||
* Returns true if there might exist a conversion between the requested types (either an automatic JVM conversion,
|
||||
* or one provided by any available {@link GuardingTypeConverterFactory}), or false if there definitely does not
|
||||
* exist a conversion between the requested types. Note that returning true does not guarantee that the conversion
|
||||
* will succeed at runtime (notably, if the "from" or "to" types are sufficiently generic), but returning false
|
||||
* guarantees that it would fail.
|
||||
*
|
||||
* @param from the source type for the conversion
|
||||
* @param to the target type for the conversion
|
||||
* @return true if there can be a conversion, false if there can not.
|
||||
*/
|
||||
public boolean canConvert(Class<?> from, Class<?> to);
|
||||
|
||||
/**
|
||||
* Creates a guarded invocation using the {@link DynamicLinker} that exposes this linker services interface. Linkers
|
||||
* can typically use them to delegate linking of wrapped objects.
|
||||
*
|
||||
* @param linkRequest a request for linking the invocation
|
||||
* @return a guarded invocation linked by the top-level linker (or any of its delegates). Can be null if no
|
||||
* available linker is able to link the invocation.
|
||||
* @throws Exception in case the top-level linker throws an exception
|
||||
*/
|
||||
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest) throws Exception;
|
||||
|
||||
/**
|
||||
* Determines which of the two type conversions from a source type to the two target types is preferred. This is
|
||||
* used for dynamic overloaded method resolution. If the source type is convertible to exactly one target type with
|
||||
* a method invocation conversion, it is chosen, otherwise available {@link ConversionComparator}s are consulted.
|
||||
* @param sourceType the source type.
|
||||
* @param targetType1 one potential target type
|
||||
* @param targetType2 another potential target type.
|
||||
* @return one of Comparison constants that establish which - if any - of the target types is preferable for the
|
||||
* conversion.
|
||||
*/
|
||||
public Comparison compareConversion(Class<?> sourceType, Class<?> targetType1, Class<?> targetType2);
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.linker;
|
||||
|
||||
/**
|
||||
* A guarding dynamic linker that can determine whether it can link the call site solely based on the type of the first
|
||||
* argument at linking invocation time. (The first argument is usually the receiver class). Most language-specific
|
||||
* linkers will fall into this category, as they recognize their native objects as Java objects of classes implementing
|
||||
* a specific language-native interface or superclass. The linker mechanism can optimize the dispatch for these linkers.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public interface TypeBasedGuardingDynamicLinker extends GuardingDynamicLinker {
|
||||
/**
|
||||
* Returns true if the linker can link an invocation where the first argument (receiver) is of the specified type.
|
||||
*
|
||||
* @param type the type to link
|
||||
* @return true if the linker can link calls for the receiver type, or false otherwise.
|
||||
*/
|
||||
public boolean canLinkType(Class<?> type);
|
||||
}
|
87
nashorn/src/jdk/internal/dynalink/linker/package.html
Normal file
87
nashorn/src/jdk/internal/dynalink/linker/package.html
Normal file
@ -0,0 +1,87 @@
|
||||
<!--
|
||||
Copyright (c) 2010, 2013, 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.
|
||||
-->
|
||||
|
||||
<!--
|
||||
This file is available under and governed by the GNU General Public
|
||||
License version 2 only, as published by the Free Software Foundation.
|
||||
However, the following notice accompanied the original version of this
|
||||
file, and Oracle licenses the original version of this file under the BSD
|
||||
license:
|
||||
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-->
|
||||
<body>
|
||||
<p>
|
||||
Contains interfaces and classes needed by language runtimes to implement
|
||||
their own language-specific linkers.
|
||||
</p>
|
||||
</body>
|
93
nashorn/src/jdk/internal/dynalink/package.html
Normal file
93
nashorn/src/jdk/internal/dynalink/package.html
Normal file
@ -0,0 +1,93 @@
|
||||
<!--
|
||||
Copyright (c) 2010, 2013, 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.
|
||||
-->
|
||||
|
||||
<!--
|
||||
This file is available under and governed by the GNU General Public
|
||||
License version 2 only, as published by the Free Software Foundation.
|
||||
However, the following notice accompanied the original version of this
|
||||
file, and Oracle licenses the original version of this file under the BSD
|
||||
license:
|
||||
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-->
|
||||
<body>
|
||||
<p>
|
||||
Contains the main API for using the dynamic linking facilities. A
|
||||
scripting framework or a language runtime that does not define its own
|
||||
linker but only uses linkers available in the system will only need to
|
||||
use classes and interfaces from this package.
|
||||
</p>
|
||||
<p>
|
||||
Languages that wish to define and use their own linkers will also need to
|
||||
use the {@link jdk.internal.dynalink.linker} package.
|
||||
</p>
|
||||
</body>
|
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.util.Objects;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
|
||||
|
||||
/**
|
||||
* A base class for call site descriptor implementations. Provides reconstruction of the name from the tokens, as well
|
||||
* as a generally useful {@code equals} and {@code hashCode} methods.
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public abstract class AbstractCallSiteDescriptor implements CallSiteDescriptor {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return appendName(new StringBuilder(getNameLength())).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lookup getLookup() {
|
||||
return MethodHandles.publicLookup();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof CallSiteDescriptor && equals((CallSiteDescriptor)obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this call site descriptor is equal to the passed call site descriptor.
|
||||
* @param csd the other call site descriptor.
|
||||
* @return true if they are equal.
|
||||
*/
|
||||
public boolean equals(CallSiteDescriptor csd) {
|
||||
if(csd == null) {
|
||||
return false;
|
||||
}
|
||||
if(csd == this) {
|
||||
return true;
|
||||
}
|
||||
final int ntc = getNameTokenCount();
|
||||
if(ntc != csd.getNameTokenCount()) {
|
||||
return false;
|
||||
}
|
||||
for(int i = ntc; i-- > 0;) { // Reverse order as variability is higher at the end
|
||||
if(!Objects.equals(getNameToken(i), csd.getNameToken(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!getMethodType().equals(csd.getMethodType())) {
|
||||
return false;
|
||||
}
|
||||
return lookupsEqual(getLookup(), csd.getLookup());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int c = getNameTokenCount();
|
||||
int h = 0;
|
||||
for(int i = 0; i < c; ++i) {
|
||||
h = h * 31 + getNameToken(i).hashCode();
|
||||
}
|
||||
return h * 31 + getMethodType().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final String mt = getMethodType().toString();
|
||||
final String l = getLookup().toString();
|
||||
final StringBuilder b = new StringBuilder(l.length() + 1 + mt.length() + getNameLength());
|
||||
return appendName(b).append(mt).append("@").append(l).toString();
|
||||
}
|
||||
|
||||
private int getNameLength() {
|
||||
final int c = getNameTokenCount();
|
||||
int l = 0;
|
||||
for(int i = 0; i < c; ++i) {
|
||||
l += getNameToken(i).length();
|
||||
}
|
||||
return l + c - 1;
|
||||
}
|
||||
|
||||
private StringBuilder appendName(StringBuilder b) {
|
||||
b.append(getNameToken(0));
|
||||
final int c = getNameTokenCount();
|
||||
for(int i = 1; i < c; ++i) {
|
||||
b.append(':').append(getNameToken(i));
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
private static boolean lookupsEqual(Lookup l1, Lookup l2) {
|
||||
if(l1 == l2) {
|
||||
return true;
|
||||
}
|
||||
if(l1.lookupClass() != l2.lookupClass()) {
|
||||
return false;
|
||||
}
|
||||
return l1.lookupModes() == l2.lookupModes();
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MutableCallSite;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.RelinkableCallSite;
|
||||
|
||||
|
||||
/**
|
||||
* A basic implementation of the {@link RelinkableCallSite} as a {@link MutableCallSite} subclass.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public abstract class AbstractRelinkableCallSite extends MutableCallSite implements RelinkableCallSite {
|
||||
private final CallSiteDescriptor descriptor;
|
||||
|
||||
/**
|
||||
* Creates a new relinkable call site.
|
||||
* @param descriptor the descriptor for this call site
|
||||
*/
|
||||
protected AbstractRelinkableCallSite(CallSiteDescriptor descriptor) {
|
||||
super(descriptor.getMethodType());
|
||||
this.descriptor = descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallSiteDescriptor getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(MethodHandle relinkAndInvoke) {
|
||||
setTarget(relinkAndInvoke);
|
||||
}
|
||||
}
|
134
nashorn/src/jdk/internal/dynalink/support/AutoDiscovery.java
Normal file
134
nashorn/src/jdk/internal/dynalink/support/AutoDiscovery.java
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import jdk.internal.dynalink.DynamicLinkerFactory;
|
||||
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
|
||||
|
||||
|
||||
/**
|
||||
* Provides methods for automatic discovery of all guarding dynamic linkers listed in the
|
||||
* <tt>/META-INF/services/jdk.internal.dynalink.linker.GuardingDynamicLinker</tt> resources of all JAR files for a
|
||||
* particular class loader. Ordinarily, you will not use this class directly, but you will use a
|
||||
* {@link DynamicLinkerFactory} instead.
|
||||
*/
|
||||
public class AutoDiscovery {
|
||||
|
||||
private AutoDiscovery() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Discovers all guarding dynamic linkers listed in JAR files of the context class loader of the current thread.
|
||||
*
|
||||
* @return a list of available linkers. Can be zero-length list but not null.
|
||||
*/
|
||||
public static List<GuardingDynamicLinker> loadLinkers() {
|
||||
return getLinkers(ServiceLoader.load(GuardingDynamicLinker.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Discovers all guarding dynamic linkers listed in JAR files of the specified class loader.
|
||||
*
|
||||
* @param cl the class loader to use
|
||||
* @return a list of guarding dynamic linkers available through the specified class loader. Can be zero-length list
|
||||
* but not null.
|
||||
*/
|
||||
public static List<GuardingDynamicLinker> loadLinkers(ClassLoader cl) {
|
||||
return getLinkers(ServiceLoader.load(GuardingDynamicLinker.class, cl));
|
||||
}
|
||||
|
||||
/**
|
||||
* I can't believe there's no Collections API for making a List given an Iterator...
|
||||
*/
|
||||
private static <T> List<T> getLinkers(ServiceLoader<T> loader) {
|
||||
final List<T> list = new LinkedList<>();
|
||||
for(final T linker: loader) {
|
||||
list.add(linker);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
99
nashorn/src/jdk/internal/dynalink/support/Backport.java
Normal file
99
nashorn/src/jdk/internal/dynalink/support/Backport.java
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
/**
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class Backport {
|
||||
/**
|
||||
* True if Remi's JSR-292 backport agent is active; false if we're using native OpenJDK JSR-292 support.
|
||||
*/
|
||||
public static final boolean inUse = MethodHandles.class.getName().startsWith("jsr292");
|
||||
|
||||
private Backport() {
|
||||
}
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
|
||||
|
||||
/**
|
||||
* A linker that can't link any call site. Only used internally by {@link CompositeTypeBasedGuardingDynamicLinker}. Can
|
||||
* be used by other language runtimes if they need it though.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class BottomGuardingDynamicLinker implements TypeBasedGuardingDynamicLinker {
|
||||
|
||||
/**
|
||||
* The sole instance of this stateless linker.
|
||||
*/
|
||||
public static final BottomGuardingDynamicLinker INSTANCE = new BottomGuardingDynamicLinker();
|
||||
|
||||
private BottomGuardingDynamicLinker() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canLinkType(Class<?> type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.WeakHashMap;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
|
||||
|
||||
/**
|
||||
* Usable as a default factory for call site descriptor implementations. It is weakly canonicalizing, meaning it will
|
||||
* return the same immutable call site descriptor for identical inputs, i.e. repeated requests for a descriptor
|
||||
* signifying public lookup for "dyn:getProp:color" of type "Object(Object)" will return the same object as long as
|
||||
* a previously created, at least softly reachable one exists. It also uses several different implementations of the
|
||||
* {@link CallSiteDescriptor} internally, and chooses the most space-efficient one based on the input.
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class CallSiteDescriptorFactory {
|
||||
private static final WeakHashMap<CallSiteDescriptor, WeakReference<CallSiteDescriptor>> publicDescs =
|
||||
new WeakHashMap<>();
|
||||
|
||||
|
||||
private CallSiteDescriptorFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new call site descriptor instance. The actual underlying class of the instance is dependent on the
|
||||
* passed arguments to be space efficient; i.e. if you only use the public lookup, you'll get back an
|
||||
* implementation that doesn't waste space on storing the lookup object.
|
||||
* @param lookup the lookup that determines access rights at the call site. If your language runtime doesn't have
|
||||
* equivalents of Java access concepts, just use {@link MethodHandles#publicLookup()}. Must not be null.
|
||||
* @param name the name of the method at the call site. Must not be null.
|
||||
* @param methodType the type of the method at the call site. Must not be null.
|
||||
* @return a call site descriptor representing the input. Note that although the method name is "create", it will
|
||||
* in fact return a weakly-referenced canonical instance.
|
||||
*/
|
||||
public static CallSiteDescriptor create(Lookup lookup, String name, MethodType methodType) {
|
||||
name.getClass(); // NPE check
|
||||
methodType.getClass(); // NPE check
|
||||
lookup.getClass(); // NPE check
|
||||
final String[] tokenizedName = tokenizeName(name);
|
||||
if(isPublicLookup(lookup)) {
|
||||
return getCanonicalPublicDescriptor(createPublicCallSiteDescriptor(tokenizedName, methodType));
|
||||
} else {
|
||||
return new LookupCallSiteDescriptor(tokenizedName, methodType, lookup);
|
||||
}
|
||||
}
|
||||
|
||||
static CallSiteDescriptor getCanonicalPublicDescriptor(final CallSiteDescriptor desc) {
|
||||
synchronized(publicDescs) {
|
||||
final WeakReference<CallSiteDescriptor> ref = publicDescs.get(desc);
|
||||
if(ref != null) {
|
||||
final CallSiteDescriptor canonical = ref.get();
|
||||
if(canonical != null) {
|
||||
return canonical;
|
||||
}
|
||||
}
|
||||
publicDescs.put(desc, new WeakReference<>(desc));
|
||||
}
|
||||
return desc;
|
||||
}
|
||||
|
||||
private static CallSiteDescriptor createPublicCallSiteDescriptor(String[] tokenizedName, MethodType methodType) {
|
||||
final int l = tokenizedName.length;
|
||||
if(l > 0 && tokenizedName[0] == "dyn") {
|
||||
if(l == 2) {
|
||||
return new UnnamedDynCallSiteDescriptor(tokenizedName[1], methodType);
|
||||
} if (l == 3) {
|
||||
return new NamedDynCallSiteDescriptor(tokenizedName[1], tokenizedName[2], methodType);
|
||||
}
|
||||
}
|
||||
return new DefaultCallSiteDescriptor(tokenizedName, methodType);
|
||||
}
|
||||
|
||||
private static boolean isPublicLookup(Lookup lookup) {
|
||||
return lookup == MethodHandles.publicLookup();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tokenizes the composite name along colons, as well as {@link NameCodec#decode(String) demangles} and interns
|
||||
* the tokens. The first two tokens are not demangled as they are supposed to be the naming scheme and the name of
|
||||
* the operation which can be expected to consist of just alphabetical characters.
|
||||
* @param name the composite name consisting of colon-separated, possibly mangled tokens.
|
||||
* @return an array of tokens
|
||||
*/
|
||||
public static String[] tokenizeName(String name) {
|
||||
final StringTokenizer tok = new StringTokenizer(name, CallSiteDescriptor.TOKEN_DELIMITER);
|
||||
final String[] tokens = new String[tok.countTokens()];
|
||||
for(int i = 0; i < tokens.length; ++i) {
|
||||
String token = tok.nextToken();
|
||||
if(i > 1) {
|
||||
token = NameCodec.decode(token);
|
||||
}
|
||||
tokens[i] = token.intern();
|
||||
}
|
||||
return tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tokenizes a composite operation name along pipe characters. I.e. if you have a "dyn:getElem|getProp|getMethod"
|
||||
* operation, returns a list of ["getElem", "getProp", "getMethod"]. The tokens are not interned.
|
||||
* @param desc the call site descriptor with the operation
|
||||
* @return a list of tokens
|
||||
*/
|
||||
public static List<String> tokenizeOperators(CallSiteDescriptor desc) {
|
||||
final String ops = desc.getNameToken(CallSiteDescriptor.OPERATOR);
|
||||
final StringTokenizer tok = new StringTokenizer(ops, CallSiteDescriptor.OPERATOR_DELIMITER);
|
||||
final int count = tok.countTokens();
|
||||
if(count == 1) {
|
||||
return Collections.singletonList(ops);
|
||||
}
|
||||
final String[] tokens = new String[count];
|
||||
for(int i = 0; i < count; ++i) {
|
||||
tokens[i] = tok.nextToken();
|
||||
}
|
||||
return Arrays.asList(tokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new call site descriptor that is identical to the passed one, except that it has some parameter types
|
||||
* removed from its method type.
|
||||
* @param desc the original call site descriptor
|
||||
* @param start index of the first parameter to remove
|
||||
* @param end index of the first parameter to not remove
|
||||
* @return a new call site descriptor with modified method type
|
||||
*/
|
||||
public static CallSiteDescriptor dropParameterTypes(CallSiteDescriptor desc, int start, int end) {
|
||||
return desc.changeMethodType(desc.getMethodType().dropParameterTypes(start, end));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new call site descriptor that is identical to the passed one, except that it has a single parameter
|
||||
* type changed in its method type.
|
||||
* @param desc the original call site descriptor
|
||||
* @param num index of the parameter to change
|
||||
* @param nptype the new parameter type
|
||||
* @return a new call site descriptor with modified method type
|
||||
*/
|
||||
public static CallSiteDescriptor changeParameterType(CallSiteDescriptor desc, int num, Class<?> nptype) {
|
||||
return desc.changeMethodType(desc.getMethodType().changeParameterType(num, nptype));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new call site descriptor that is identical to the passed one, except that it has the return type
|
||||
* changed in its method type.
|
||||
* @param desc the original call site descriptor
|
||||
* @param nrtype the new return type
|
||||
* @return a new call site descriptor with modified method type
|
||||
*/
|
||||
public static CallSiteDescriptor changeReturnType(CallSiteDescriptor desc, Class<?> nrtype) {
|
||||
return desc.changeMethodType(desc.getMethodType().changeReturnType(nrtype));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new call site descriptor that is identical to the passed one, except that it has additional parameter
|
||||
* types inserted into its method type.
|
||||
* @param desc the original call site descriptor
|
||||
* @param num index at which the new parameters are inserted
|
||||
* @param ptypesToInsert the new types to insert
|
||||
* @return a new call site descriptor with modified method type
|
||||
*/
|
||||
public static CallSiteDescriptor insertParameterTypes(CallSiteDescriptor desc, int num, Class<?>... ptypesToInsert) {
|
||||
return desc.changeMethodType(desc.getMethodType().insertParameterTypes(num, ptypesToInsert));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new call site descriptor that is identical to the passed one, except that it has additional parameter
|
||||
* types inserted into its method type.
|
||||
* @param desc the original call site descriptor
|
||||
* @param num index at which the new parameters are inserted
|
||||
* @param ptypesToInsert the new types to insert
|
||||
* @return a new call site descriptor with modified method type
|
||||
*/
|
||||
public static CallSiteDescriptor insertParameterTypes(CallSiteDescriptor desc, int num, List<Class<?>> ptypesToInsert) {
|
||||
return desc.changeMethodType(desc.getMethodType().insertParameterTypes(num, ptypesToInsert));
|
||||
}
|
||||
}
|
177
nashorn/src/jdk/internal/dynalink/support/ClassMap.java
Normal file
177
nashorn/src/jdk/internal/dynalink/support/ClassMap.java
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* A dual map that can either strongly or weakly reference a given class depending on whether the class is visible from
|
||||
* a class loader or not.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
* @param <T> the type of the values in the map
|
||||
*/
|
||||
public abstract class ClassMap<T> {
|
||||
private final ConcurrentMap<Class<?>, T> map = new ConcurrentHashMap<>();
|
||||
private final Map<Class<?>, Reference<T>> weakMap = new WeakHashMap<>();
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
/**
|
||||
* Creates a new class map. It will use strong references for all keys and values where the key is a class visible
|
||||
* from the class loader, and will use weak keys and soft values for all other classes.
|
||||
*
|
||||
* @param classLoader the classloader that determines strong referenceability.
|
||||
*/
|
||||
protected ClassMap(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the value associated with the given class. It is possible that the method will be invoked several times
|
||||
* (or even concurrently) for the same class parameter.
|
||||
*
|
||||
* @param clazz the class to compute the value for
|
||||
* @return the return value. Must not be null.
|
||||
*/
|
||||
protected abstract T computeValue(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Returns the class loader that governs the strong referenceability of this class map.
|
||||
*
|
||||
* @return the class loader that governs the strong referenceability of this class map.
|
||||
*/
|
||||
public ClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value associated with the class
|
||||
*
|
||||
* @param clazz the class
|
||||
* @return the value associated with the class
|
||||
*/
|
||||
public T get(Class<?> clazz) {
|
||||
// Check in fastest first - objects we're allowed to strongly reference
|
||||
final T v = map.get(clazz);
|
||||
if(v != null) {
|
||||
return v;
|
||||
}
|
||||
// Check objects we're not allowed to strongly reference
|
||||
Reference<T> ref;
|
||||
synchronized(weakMap) {
|
||||
ref = weakMap.get(clazz);
|
||||
}
|
||||
if(ref != null) {
|
||||
final T refv = ref.get();
|
||||
if(refv != null) {
|
||||
return refv;
|
||||
}
|
||||
}
|
||||
// Not found in either place; create a new value
|
||||
final T newV = computeValue(clazz);
|
||||
assert newV != null;
|
||||
// If allowed to strongly reference, put it in the fast map
|
||||
if(Guards.canReferenceDirectly(classLoader, clazz.getClassLoader())) {
|
||||
final T oldV = map.putIfAbsent(clazz, newV);
|
||||
return oldV != null ? oldV : newV;
|
||||
}
|
||||
// Otherwise, put it into the weak map
|
||||
synchronized(weakMap) {
|
||||
ref = weakMap.get(clazz);
|
||||
if(ref != null) {
|
||||
final T oldV = ref.get();
|
||||
if(oldV != null) {
|
||||
return oldV;
|
||||
}
|
||||
}
|
||||
weakMap.put(clazz, new SoftReference<>(newV));
|
||||
return newV;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
|
||||
|
||||
/**
|
||||
* A {@link GuardingDynamicLinker} that delegates sequentially to a list of other guarding dynamic linkers. The first
|
||||
* value returned from a component linker other than null is returned. If no component linker returns an invocation,
|
||||
* null is returned.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class CompositeGuardingDynamicLinker implements GuardingDynamicLinker, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final GuardingDynamicLinker[] linkers;
|
||||
|
||||
/**
|
||||
* Creates a new composite linker.
|
||||
*
|
||||
* @param linkers a list of component linkers.
|
||||
*/
|
||||
public CompositeGuardingDynamicLinker(Iterable<? extends GuardingDynamicLinker> linkers) {
|
||||
final List<GuardingDynamicLinker> l = new LinkedList<>();
|
||||
for(GuardingDynamicLinker linker: linkers) {
|
||||
l.add(linker);
|
||||
}
|
||||
this.linkers = l.toArray(new GuardingDynamicLinker[l.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, final LinkerServices linkerServices)
|
||||
throws Exception {
|
||||
for(final GuardingDynamicLinker linker: linkers) {
|
||||
final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices);
|
||||
if(invocation != null) {
|
||||
return invocation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
|
||||
|
||||
|
||||
/**
|
||||
* A composite type-based guarding dynamic linker. When a receiver of a not yet seen class is encountered, all linkers
|
||||
* are queried sequentially on their {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)} method. The linkers
|
||||
* returning true are then bound to the class, and next time a receiver of same type is encountered, the linking is
|
||||
* delegated to those linkers only, speeding up dispatch.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardingDynamicLinker, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// Using a separate static class instance so there's no strong reference from the class value back to the composite
|
||||
// linker.
|
||||
private static class ClassToLinker extends ClassValue<List<TypeBasedGuardingDynamicLinker>> {
|
||||
private static final List<TypeBasedGuardingDynamicLinker> NO_LINKER = Collections.emptyList();
|
||||
private final TypeBasedGuardingDynamicLinker[] linkers;
|
||||
private final List<TypeBasedGuardingDynamicLinker>[] singletonLinkers;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
ClassToLinker(TypeBasedGuardingDynamicLinker[] linkers) {
|
||||
this.linkers = linkers;
|
||||
singletonLinkers = new List[linkers.length];
|
||||
for(int i = 0; i < linkers.length; ++i) {
|
||||
singletonLinkers[i] = Collections.singletonList(linkers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<TypeBasedGuardingDynamicLinker> computeValue(Class<?> clazz) {
|
||||
List<TypeBasedGuardingDynamicLinker> list = NO_LINKER;
|
||||
for(int i = 0; i < linkers.length; ++i) {
|
||||
final TypeBasedGuardingDynamicLinker linker = linkers[i];
|
||||
if(linker.canLinkType(clazz)) {
|
||||
switch(list.size()) {
|
||||
case 0: {
|
||||
list = singletonLinkers[i];
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
list = new LinkedList<>(list);
|
||||
}
|
||||
//$FALL-THROUGH$
|
||||
default: {
|
||||
list.add(linker);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
private final ClassValue<List<TypeBasedGuardingDynamicLinker>> classToLinker;
|
||||
|
||||
/**
|
||||
* Creates a new composite type-based linker.
|
||||
*
|
||||
* @param linkers the component linkers
|
||||
*/
|
||||
public CompositeTypeBasedGuardingDynamicLinker(Iterable<? extends TypeBasedGuardingDynamicLinker> linkers) {
|
||||
final List<TypeBasedGuardingDynamicLinker> l = new LinkedList<>();
|
||||
for(TypeBasedGuardingDynamicLinker linker: linkers) {
|
||||
l.add(linker);
|
||||
}
|
||||
this.classToLinker = new ClassToLinker(l.toArray(new TypeBasedGuardingDynamicLinker[l.size()]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canLinkType(Class<?> type) {
|
||||
return !classToLinker.get(type).isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, final LinkerServices linkerServices)
|
||||
throws Exception {
|
||||
final Object obj = linkRequest.getReceiver();
|
||||
if(obj == null) {
|
||||
return null;
|
||||
}
|
||||
for(TypeBasedGuardingDynamicLinker linker: classToLinker.get(obj.getClass())) {
|
||||
final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices);
|
||||
if(invocation != null) {
|
||||
return invocation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimizes a list of type-based linkers. If a group of adjacent linkers in the list all implement
|
||||
* {@link TypeBasedGuardingDynamicLinker}, they will be replaced with a single instance of
|
||||
* {@link CompositeTypeBasedGuardingDynamicLinker} that contains them.
|
||||
*
|
||||
* @param linkers the list of linkers to optimize
|
||||
* @return the optimized list
|
||||
*/
|
||||
public static List<GuardingDynamicLinker> optimize(Iterable<? extends GuardingDynamicLinker> linkers) {
|
||||
final List<GuardingDynamicLinker> llinkers = new LinkedList<>();
|
||||
final List<TypeBasedGuardingDynamicLinker> tblinkers = new LinkedList<>();
|
||||
for(GuardingDynamicLinker linker: linkers) {
|
||||
if(linker instanceof TypeBasedGuardingDynamicLinker) {
|
||||
tblinkers.add((TypeBasedGuardingDynamicLinker)linker);
|
||||
} else {
|
||||
addTypeBased(llinkers, tblinkers);
|
||||
llinkers.add(linker);
|
||||
}
|
||||
}
|
||||
addTypeBased(llinkers, tblinkers);
|
||||
return llinkers;
|
||||
}
|
||||
|
||||
private static void addTypeBased(List<GuardingDynamicLinker> llinkers,
|
||||
List<TypeBasedGuardingDynamicLinker> tblinkers) {
|
||||
switch(tblinkers.size()) {
|
||||
case 0: {
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
llinkers.addAll(tblinkers);
|
||||
tblinkers.clear();
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
llinkers.add(new CompositeTypeBasedGuardingDynamicLinker(tblinkers));
|
||||
tblinkers.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
|
||||
|
||||
/**
|
||||
* A default, fairly light implementation of a call site descriptor used for describing non-standard operations. It does
|
||||
* not store {@link Lookup} objects but always returns the public lookup from its {@link #getLookup()} method. If you
|
||||
* need to support non-public lookup, you can use {@link LookupCallSiteDescriptor}.
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
class DefaultCallSiteDescriptor extends AbstractCallSiteDescriptor {
|
||||
|
||||
private final String[] tokenizedName;
|
||||
private final MethodType methodType;
|
||||
|
||||
DefaultCallSiteDescriptor(String[] tokenizedName, MethodType methodType) {
|
||||
this.tokenizedName = tokenizedName;
|
||||
this.methodType = methodType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNameTokenCount() {
|
||||
return tokenizedName.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameToken(int i) {
|
||||
try {
|
||||
return tokenizedName[i];
|
||||
} catch(ArrayIndexOutOfBoundsException e) {
|
||||
throw new IllegalArgumentException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
String[] getTokenizedName() {
|
||||
return tokenizedName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodType getMethodType() {
|
||||
return methodType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallSiteDescriptor changeMethodType(MethodType newMethodType) {
|
||||
return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new DefaultCallSiteDescriptor(tokenizedName,
|
||||
newMethodType));
|
||||
}
|
||||
}
|
360
nashorn/src/jdk/internal/dynalink/support/Guards.java
Normal file
360
nashorn/src/jdk/internal/dynalink/support/Guards.java
Normal file
@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
|
||||
|
||||
/**
|
||||
* Utility methods for creating typical guards. TODO: introduce reasonable caching of created guards.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class Guards {
|
||||
private static final Logger LOG = Logger
|
||||
.getLogger(Guards.class.getName(), "jdk.internal.dynalink.support.messages");
|
||||
|
||||
private Guards() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a guard method handle with arguments of a specified type, but with boolean return value. When invoked, it
|
||||
* returns true if the first argument is of the specified class (exactly of it, not a subclass). The rest of the
|
||||
* arguments will be ignored.
|
||||
*
|
||||
* @param clazz the class of the first argument to test for
|
||||
* @param type the method type
|
||||
* @return a method handle testing whether its first argument is of the specified class.
|
||||
*/
|
||||
@SuppressWarnings("boxing")
|
||||
public static MethodHandle isOfClass(Class<?> clazz, MethodType type) {
|
||||
final Class<?> declaredType = type.parameterType(0);
|
||||
if(clazz == declaredType) {
|
||||
LOG.log(Level.WARNING, "isOfClassGuardAlwaysTrue", new Object[] { clazz.getName(), 0, type });
|
||||
return constantTrue(type);
|
||||
}
|
||||
if(!declaredType.isAssignableFrom(clazz)) {
|
||||
LOG.log(Level.WARNING, "isOfClassGuardAlwaysFalse", new Object[] { clazz.getName(), 0, type });
|
||||
return constantFalse(type);
|
||||
}
|
||||
return getClassBoundArgumentTest(IS_OF_CLASS, clazz, 0, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a method handle with arguments of a specified type, but with boolean return value. When invoked, it
|
||||
* returns true if the first argument is instance of the specified class or its subclass). The rest of the arguments
|
||||
* will be ignored.
|
||||
*
|
||||
* @param clazz the class of the first argument to test for
|
||||
* @param type the method type
|
||||
* @return a method handle testing whether its first argument is of the specified class or subclass.
|
||||
*/
|
||||
public static MethodHandle isInstance(Class<?> clazz, MethodType type) {
|
||||
return isInstance(clazz, 0, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a method handle with arguments of a specified type, but with boolean return value. When invoked, it
|
||||
* returns true if the n'th argument is instance of the specified class or its subclass). The rest of the arguments
|
||||
* will be ignored.
|
||||
*
|
||||
* @param clazz the class of the first argument to test for
|
||||
* @param pos the position on the argument list to test
|
||||
* @param type the method type
|
||||
* @return a method handle testing whether its first argument is of the specified class or subclass.
|
||||
*/
|
||||
@SuppressWarnings("boxing")
|
||||
public static MethodHandle isInstance(Class<?> clazz, int pos, MethodType type) {
|
||||
final Class<?> declaredType = type.parameterType(pos);
|
||||
if(clazz.isAssignableFrom(declaredType)) {
|
||||
LOG.log(Level.WARNING, "isInstanceGuardAlwaysTrue", new Object[] { clazz.getName(), pos, type });
|
||||
return constantTrue(type);
|
||||
}
|
||||
if(!declaredType.isAssignableFrom(clazz)) {
|
||||
LOG.log(Level.WARNING, "isInstanceGuardAlwaysFalse", new Object[] { clazz.getName(), pos, type });
|
||||
return constantFalse(type);
|
||||
}
|
||||
return getClassBoundArgumentTest(IS_INSTANCE, clazz, pos, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a method handle that returns true if the argument in the specified position is a Java array.
|
||||
*
|
||||
* @param pos the position in the argument lit
|
||||
* @param type the method type of the handle
|
||||
* @return a method handle that returns true if the argument in the specified position is a Java array; the rest of
|
||||
* the arguments are ignored.
|
||||
*/
|
||||
@SuppressWarnings("boxing")
|
||||
public static MethodHandle isArray(int pos, MethodType type) {
|
||||
final Class<?> declaredType = type.parameterType(pos);
|
||||
if(declaredType.isArray()) {
|
||||
LOG.log(Level.WARNING, "isArrayGuardAlwaysTrue", new Object[] { pos, type });
|
||||
return constantTrue(type);
|
||||
}
|
||||
if(!declaredType.isAssignableFrom(Object[].class)) {
|
||||
LOG.log(Level.WARNING, "isArrayGuardAlwaysFalse", new Object[] { pos, type });
|
||||
return constantFalse(type);
|
||||
}
|
||||
return asType(IS_ARRAY, pos, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if it is safe to strongly reference a class from the referred class loader from a class associated
|
||||
* with the referring class loader without risking a class loader memory leak.
|
||||
*
|
||||
* @param referrerLoader the referrer class loader
|
||||
* @param referredLoader the referred class loader
|
||||
* @return true if it is safe to strongly reference the class
|
||||
*/
|
||||
public static boolean canReferenceDirectly(ClassLoader referrerLoader, final ClassLoader referredLoader) {
|
||||
if(referredLoader == null) {
|
||||
// Can always refer directly to a system class
|
||||
return true;
|
||||
}
|
||||
if(referrerLoader == null) {
|
||||
// System classes can't refer directly to any non-system class
|
||||
return false;
|
||||
}
|
||||
// Otherwise, can only refer directly to classes residing in same or
|
||||
// parent class loader.
|
||||
|
||||
ClassLoader referrer = referrerLoader;
|
||||
do {
|
||||
if(referrer == referredLoader) {
|
||||
return true;
|
||||
}
|
||||
referrer = referrer.getParent();
|
||||
} while(referrer != null);
|
||||
return false;
|
||||
}
|
||||
|
||||
private static MethodHandle getClassBoundArgumentTest(MethodHandle test, Class<?> clazz, int pos, MethodType type) {
|
||||
// Bind the class to the first argument of the test
|
||||
return asType(test.bindTo(clazz), pos, type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a guard-test method handle, and adapts it to the requested type, returning a boolean. Only applies
|
||||
* conversions as per {@link MethodHandle#asType(MethodType)}.
|
||||
* @param test the test method handle
|
||||
* @param type the type to adapt the method handle to
|
||||
* @return the adapted method handle
|
||||
*/
|
||||
public static MethodHandle asType(MethodHandle test, MethodType type) {
|
||||
return test.asType(getTestType(test, type));
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a guard-test method handle, and adapts it to the requested type, returning a boolean. Applies the passed
|
||||
* {@link LinkerServices} object's {@link LinkerServices#asType(MethodHandle, MethodType)}.
|
||||
* @param linkerServices the linker services to use for type conversions
|
||||
* @param test the test method handle
|
||||
* @param type the type to adapt the method handle to
|
||||
* @return the adapted method handle
|
||||
*/
|
||||
public static MethodHandle asType(LinkerServices linkerServices, MethodHandle test, MethodType type) {
|
||||
return linkerServices.asType(test, getTestType(test, type));
|
||||
}
|
||||
|
||||
private static MethodType getTestType(MethodHandle test, MethodType type) {
|
||||
return type.dropParameterTypes(test.type().parameterCount(),
|
||||
type.parameterCount()).changeReturnType(boolean.class);
|
||||
}
|
||||
|
||||
private static MethodHandle asType(MethodHandle test, int pos, MethodType type) {
|
||||
assert test != null;
|
||||
assert type != null;
|
||||
assert type.parameterCount() > 0;
|
||||
assert pos >= 0 && pos < type.parameterCount();
|
||||
assert test.type().parameterCount() == 1;
|
||||
assert test.type().returnType() == Boolean.TYPE;
|
||||
return MethodHandles.permuteArguments(test.asType(test.type().changeParameterType(0, type.parameterType(pos))),
|
||||
type.changeReturnType(Boolean.TYPE), new int[] { pos });
|
||||
}
|
||||
|
||||
private static final MethodHandle IS_OF_CLASS = new Lookup(MethodHandles.lookup()).findStatic(Guards.class,
|
||||
"isOfClass", MethodType.methodType(Boolean.TYPE, Class.class, Object.class));
|
||||
|
||||
private static final MethodHandle IS_INSTANCE = Lookup.PUBLIC.findVirtual(Class.class, "isInstance",
|
||||
MethodType.methodType(Boolean.TYPE, Object.class));
|
||||
|
||||
private static final MethodHandle IS_ARRAY = new Lookup(MethodHandles.lookup()).findStatic(Guards.class, "isArray",
|
||||
MethodType.methodType(Boolean.TYPE, Object.class));
|
||||
|
||||
private static final MethodHandle IS_IDENTICAL = new Lookup(MethodHandles.lookup()).findStatic(Guards.class,
|
||||
"isIdentical", MethodType.methodType(Boolean.TYPE, Object.class, Object.class));
|
||||
|
||||
private static final MethodHandle IS_NULL = new Lookup(MethodHandles.lookup()).findStatic(Guards.class,
|
||||
"isNull", MethodType.methodType(Boolean.TYPE, Object.class));
|
||||
|
||||
private static final MethodHandle IS_NOT_NULL = new Lookup(MethodHandles.lookup()).findStatic(Guards.class,
|
||||
"isNotNull", MethodType.methodType(Boolean.TYPE, Object.class));
|
||||
|
||||
/**
|
||||
* Creates a guard method that tests its only argument for being of an exact particular class.
|
||||
* @param clazz the class to test for.
|
||||
* @return the desired guard method.
|
||||
*/
|
||||
public static MethodHandle getClassGuard(Class<?> clazz) {
|
||||
return IS_OF_CLASS.bindTo(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a guard method that tests its only argument for being an instance of a particular class.
|
||||
* @param clazz the class to test for.
|
||||
* @return the desired guard method.
|
||||
*/
|
||||
public static MethodHandle getInstanceOfGuard(Class<?> clazz) {
|
||||
return IS_INSTANCE.bindTo(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a guard method that tests its only argument for being referentially identical to another object
|
||||
* @param obj the object used as referential identity test
|
||||
* @return the desired guard method.
|
||||
*/
|
||||
public static MethodHandle getIdentityGuard(Object obj) {
|
||||
return IS_IDENTICAL.bindTo(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a guard that tests whether the first argument is null.
|
||||
* @return a guard that tests whether the first argument is null.
|
||||
*/
|
||||
public static MethodHandle isNull() {
|
||||
return IS_NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a guard that tests whether the first argument is not null.
|
||||
* @return a guard that tests whether the first argument is not null.
|
||||
*/
|
||||
public static MethodHandle isNotNull() {
|
||||
return IS_NOT_NULL;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static boolean isNull(Object obj) {
|
||||
return obj == null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static boolean isNotNull(Object obj) {
|
||||
return obj != null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static boolean isArray(Object o) {
|
||||
return o != null && o.getClass().isArray();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static boolean isOfClass(Class<?> c, Object o) {
|
||||
return o != null && o.getClass() == c;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static boolean isIdentical(Object o1, Object o2) {
|
||||
return o1 == o2;
|
||||
}
|
||||
|
||||
private static MethodHandle constantTrue(MethodType type) {
|
||||
return constantBoolean(Boolean.TRUE, type);
|
||||
}
|
||||
|
||||
private static MethodHandle constantFalse(MethodType type) {
|
||||
return constantBoolean(Boolean.FALSE, type);
|
||||
}
|
||||
|
||||
private static MethodHandle constantBoolean(Boolean value, MethodType type) {
|
||||
return MethodHandles.permuteArguments(MethodHandles.constant(Boolean.TYPE, value),
|
||||
type.changeReturnType(Boolean.TYPE));
|
||||
}
|
||||
}
|
143
nashorn/src/jdk/internal/dynalink/support/LinkRequestImpl.java
Normal file
143
nashorn/src/jdk/internal/dynalink/support/LinkRequestImpl.java
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link LinkRequest}, representing a link request to a call site that passes no language
|
||||
* runtime specific native context arguments on the stack.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class LinkRequestImpl implements LinkRequest {
|
||||
|
||||
private final CallSiteDescriptor callSiteDescriptor;
|
||||
private final Object[] arguments;
|
||||
private final boolean callSiteUnstable;
|
||||
|
||||
/**
|
||||
* Creates a new link request.
|
||||
*
|
||||
* @param callSiteDescriptor the descriptor for the call site being linked
|
||||
* @param callSiteUnstable true if the call site being linked is considered unstable
|
||||
* @param arguments the arguments for the invocation
|
||||
*/
|
||||
public LinkRequestImpl(CallSiteDescriptor callSiteDescriptor, boolean callSiteUnstable, Object... arguments) {
|
||||
this.callSiteDescriptor = callSiteDescriptor;
|
||||
this.callSiteUnstable = callSiteUnstable;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getArguments() {
|
||||
return arguments != null ? arguments.clone() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getReceiver() {
|
||||
return arguments != null && arguments.length > 0 ? arguments[0] : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallSiteDescriptor getCallSiteDescriptor() {
|
||||
return callSiteDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCallSiteUnstable() {
|
||||
return callSiteUnstable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkRequest withoutRuntimeContext() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkRequest replaceArguments(CallSiteDescriptor newCallSiteDescriptor, Object[] newArguments) {
|
||||
return new LinkRequestImpl(newCallSiteDescriptor, callSiteUnstable, newArguments);
|
||||
}
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link LinkerServices} interface.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class LinkerServicesImpl implements LinkerServices {
|
||||
|
||||
private final TypeConverterFactory typeConverterFactory;
|
||||
private final GuardingDynamicLinker topLevelLinker;
|
||||
|
||||
/**
|
||||
* Creates a new linker services object.
|
||||
*
|
||||
* @param typeConverterFactory the type converter factory exposed by the services.
|
||||
* @param topLevelLinker the top level linker used by the services.
|
||||
*/
|
||||
public LinkerServicesImpl(final TypeConverterFactory typeConverterFactory,
|
||||
final GuardingDynamicLinker topLevelLinker) {
|
||||
this.typeConverterFactory = typeConverterFactory;
|
||||
this.topLevelLinker = topLevelLinker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConvert(Class<?> from, Class<?> to) {
|
||||
return typeConverterFactory.canConvert(from, to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodHandle asType(MethodHandle handle, MethodType fromType) {
|
||||
return typeConverterFactory.asType(handle, fromType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodHandle getTypeConverter(Class<?> sourceType, Class<?> targetType) {
|
||||
return typeConverterFactory.getTypeConverter(sourceType, targetType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparison compareConversion(Class<?> sourceType, Class<?> targetType1, Class<?> targetType2) {
|
||||
return typeConverterFactory.compareConversion(sourceType, targetType1, targetType2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest) throws Exception {
|
||||
return topLevelLinker.getGuardedInvocation(linkRequest, this);
|
||||
}
|
||||
}
|
361
nashorn/src/jdk/internal/dynalink/support/Lookup.java
Normal file
361
nashorn/src/jdk/internal/dynalink/support/Lookup.java
Normal file
@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* A wrapper around MethodHandles.Lookup that masks checked exceptions in those cases when you're looking up methods
|
||||
* within your own codebase (therefore it is an error if they are not present).
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class Lookup {
|
||||
private final MethodHandles.Lookup lookup;
|
||||
|
||||
/**
|
||||
* Creates a new instance, bound to an instance of {@link java.lang.invoke.MethodHandles.Lookup}.
|
||||
*
|
||||
* @param lookup the {@link java.lang.invoke.MethodHandles.Lookup} it delegates to.
|
||||
*/
|
||||
public Lookup(MethodHandles.Lookup lookup) {
|
||||
this.lookup = lookup;
|
||||
}
|
||||
|
||||
/**
|
||||
* A canonical Lookup object that wraps {@link MethodHandles#publicLookup()}.
|
||||
*/
|
||||
public static final Lookup PUBLIC = new Lookup(MethodHandles.publicLookup());
|
||||
|
||||
/**
|
||||
* Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, converting any encountered
|
||||
* {@link IllegalAccessException} into an {@link IllegalAccessError}.
|
||||
*
|
||||
* @param m the method to unreflect
|
||||
* @return the unreflected method handle.
|
||||
*/
|
||||
public MethodHandle unreflect(Method m) {
|
||||
try {
|
||||
return lookup.unreflect(m);
|
||||
} catch(IllegalAccessException e) {
|
||||
final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect method " + m);
|
||||
ee.initCause(e);
|
||||
throw ee;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter(Field)}, converting any encountered
|
||||
* {@link IllegalAccessException} into an {@link IllegalAccessError}.
|
||||
*
|
||||
* @param f the field for which a getter is unreflected
|
||||
* @return the unreflected field getter handle.
|
||||
*/
|
||||
public MethodHandle unreflectGetter(Field f) {
|
||||
try {
|
||||
return lookup.unreflectGetter(f);
|
||||
} catch(IllegalAccessException e) {
|
||||
final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect getter for field " + f);
|
||||
ee.initCause(e);
|
||||
throw ee;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a {@link java.lang.invoke.MethodHandles.Lookup#findGetter(Class, String, Class)}, converting any
|
||||
* encountered {@link IllegalAccessException} into an {@link IllegalAccessError} and {@link NoSuchFieldException}
|
||||
* into a {@link NoSuchFieldError}.
|
||||
*
|
||||
* @param refc the class declaring the field
|
||||
* @param name the name of the field
|
||||
* @param type the type of the field
|
||||
* @return the unreflected field getter handle.
|
||||
* @throws IllegalAccessError if the field is inaccessible.
|
||||
* @throws NoSuchFieldError if the field does not exist.
|
||||
*/
|
||||
public MethodHandle findGetter(Class<?>refc, String name, Class<?> type) {
|
||||
try {
|
||||
return lookup.findGetter(refc, name, type);
|
||||
} catch(IllegalAccessException e) {
|
||||
final IllegalAccessError ee = new IllegalAccessError("Failed to access getter for field " + refc.getName() +
|
||||
"." + name + " of type " + type.getName());
|
||||
ee.initCause(e);
|
||||
throw ee;
|
||||
} catch(NoSuchFieldException e) {
|
||||
final NoSuchFieldError ee = new NoSuchFieldError("Failed to find getter for field " + refc.getName() +
|
||||
"." + name + " of type " + type.getName());
|
||||
ee.initCause(e);
|
||||
throw ee;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectSetter(Field)}, converting any encountered
|
||||
* {@link IllegalAccessException} into an {@link IllegalAccessError}.
|
||||
*
|
||||
* @param f the field for which a setter is unreflected
|
||||
* @return the unreflected field setter handle.
|
||||
*/
|
||||
public MethodHandle unreflectSetter(Field f) {
|
||||
try {
|
||||
return lookup.unreflectSetter(f);
|
||||
} catch(IllegalAccessException e) {
|
||||
final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect setter for field " + f);
|
||||
ee.initCause(e);
|
||||
throw ee;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, converting any
|
||||
* encountered {@link IllegalAccessException} into an {@link IllegalAccessError}.
|
||||
*
|
||||
* @param c the constructor to unreflect
|
||||
* @return the unreflected constructor handle.
|
||||
*/
|
||||
public MethodHandle unreflectConstructor(Constructor<?> c) {
|
||||
try {
|
||||
return lookup.unreflectConstructor(c);
|
||||
} catch(IllegalAccessException e) {
|
||||
final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect constructor " + c);
|
||||
ee.initCause(e);
|
||||
throw ee;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a findSpecial on the underlying lookup, except for the backport where it rather uses unreflect. Converts
|
||||
* any encountered {@link IllegalAccessException} into an {@link IllegalAccessError} and a
|
||||
* {@link NoSuchMethodException} into a {@link NoSuchMethodError}.
|
||||
*
|
||||
* @param declaringClass class declaring the method
|
||||
* @param name the name of the method
|
||||
* @param type the type of the method
|
||||
* @return a method handle for the method
|
||||
* @throws IllegalAccessError if the method is inaccessible.
|
||||
* @throws NoSuchMethodError if the method does not exist.
|
||||
*/
|
||||
public MethodHandle findSpecial(Class<?> declaringClass, String name, MethodType type) {
|
||||
try {
|
||||
if(Backport.inUse) {
|
||||
final Method m = declaringClass.getDeclaredMethod(name, type.parameterArray());
|
||||
if(!Modifier.isPublic(declaringClass.getModifiers()) || !Modifier.isPublic(m.getModifiers())) {
|
||||
m.setAccessible(true);
|
||||
}
|
||||
return unreflect(m);
|
||||
} else {
|
||||
return lookup.findSpecial(declaringClass, name, type, declaringClass);
|
||||
}
|
||||
} catch(IllegalAccessException e) {
|
||||
final IllegalAccessError ee = new IllegalAccessError("Failed to access special method " + methodDescription(
|
||||
declaringClass, name, type));
|
||||
ee.initCause(e);
|
||||
throw ee;
|
||||
} catch(NoSuchMethodException e) {
|
||||
final NoSuchMethodError ee = new NoSuchMethodError("Failed to find special method " + methodDescription(
|
||||
declaringClass, name, type));
|
||||
ee.initCause(e);
|
||||
throw ee;
|
||||
}
|
||||
}
|
||||
|
||||
private static String methodDescription(Class<?> declaringClass, String name, MethodType type) {
|
||||
return declaringClass.getName() + "#" + name + type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a findStatic on the underlying lookup. Converts any encountered {@link IllegalAccessException} into an
|
||||
* {@link IllegalAccessError} and a {@link NoSuchMethodException} into a {@link NoSuchMethodError}.
|
||||
*
|
||||
* @param declaringClass class declaring the method
|
||||
* @param name the name of the method
|
||||
* @param type the type of the method
|
||||
* @return a method handle for the method
|
||||
* @throws IllegalAccessError if the method is inaccessible.
|
||||
* @throws NoSuchMethodError if the method does not exist.
|
||||
*/
|
||||
public MethodHandle findStatic(Class<?> declaringClass, String name, MethodType type) {
|
||||
try {
|
||||
return lookup.findStatic(declaringClass, name, type);
|
||||
} catch(IllegalAccessException e) {
|
||||
final IllegalAccessError ee = new IllegalAccessError("Failed to access static method " + methodDescription(
|
||||
declaringClass, name, type));
|
||||
ee.initCause(e);
|
||||
throw ee;
|
||||
} catch(NoSuchMethodException e) {
|
||||
final NoSuchMethodError ee = new NoSuchMethodError("Failed to find static method " + methodDescription(
|
||||
declaringClass, name, type));
|
||||
ee.initCause(e);
|
||||
throw ee;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a findVirtual on the underlying lookup. Converts any encountered {@link IllegalAccessException} into an
|
||||
* {@link IllegalAccessError} and a {@link NoSuchMethodException} into a {@link NoSuchMethodError}.
|
||||
*
|
||||
* @param declaringClass class declaring the method
|
||||
* @param name the name of the method
|
||||
* @param type the type of the method
|
||||
* @return a method handle for the method
|
||||
* @throws IllegalAccessError if the method is inaccessible.
|
||||
* @throws NoSuchMethodError if the method does not exist.
|
||||
*/
|
||||
public MethodHandle findVirtual(Class<?> declaringClass, String name, MethodType type) {
|
||||
try {
|
||||
return lookup.findVirtual(declaringClass, name, type);
|
||||
} catch(IllegalAccessException e) {
|
||||
final IllegalAccessError ee = new IllegalAccessError("Failed to access virtual method " + methodDescription(
|
||||
declaringClass, name, type));
|
||||
ee.initCause(e);
|
||||
throw ee;
|
||||
} catch(NoSuchMethodException e) {
|
||||
final NoSuchMethodError ee = new NoSuchMethodError("Failed to find virtual method " + methodDescription(
|
||||
declaringClass, name, type));
|
||||
ee.initCause(e);
|
||||
throw ee;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a lookup, finds using {@link #findSpecial(Class, String, MethodType)} a method on that lookup's class.
|
||||
* Useful in classes' code for convenient linking to their own privates.
|
||||
* @param lookup the lookup for the class
|
||||
* @param name the name of the method
|
||||
* @param rtype the return type of the method
|
||||
* @param ptypes the parameter types of the method
|
||||
* @return the method handle for the method
|
||||
*/
|
||||
public static MethodHandle findOwnSpecial(MethodHandles.Lookup lookup, String name, Class<?> rtype, Class<?>... ptypes) {
|
||||
return new Lookup(lookup).findOwnSpecial(name, rtype, ptypes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds using {@link #findSpecial(Class, String, MethodType)} a method on that lookup's class. Useful in classes'
|
||||
* code for convenient linking to their own privates. It's easier to use than {@code findSpecial} in that you can
|
||||
* just list the parameter types, and don't have to specify lookup class.
|
||||
* @param name the name of the method
|
||||
* @param rtype the return type of the method
|
||||
* @param ptypes the parameter types of the method
|
||||
* @return the method handle for the method
|
||||
*/
|
||||
public MethodHandle findOwnSpecial(String name, Class<?> rtype, Class<?>... ptypes) {
|
||||
return findSpecial(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a lookup, finds using {@link #findStatic(Class, String, MethodType)} a method on that lookup's class.
|
||||
* Useful in classes' code for convenient linking to their own privates. It's easier to use than {@code findStatic}
|
||||
* in that you can just list the parameter types, and don't have to specify lookup class.
|
||||
* @param lookup the lookup for the class
|
||||
* @param name the name of the method
|
||||
* @param rtype the return type of the method
|
||||
* @param ptypes the parameter types of the method
|
||||
* @return the method handle for the method
|
||||
*/
|
||||
public static MethodHandle findOwnStatic(MethodHandles.Lookup lookup, String name, Class<?> rtype, Class<?>... ptypes) {
|
||||
return new Lookup(lookup).findOwnStatic(name, rtype, ptypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds using {@link #findStatic(Class, String, MethodType)} a method on that lookup's class. Useful in classes'
|
||||
* code for convenient linking to their own privates. It's easier to use than {@code findStatic} in that you can
|
||||
* just list the parameter types, and don't have to specify lookup class.
|
||||
* @param name the name of the method
|
||||
* @param rtype the return type of the method
|
||||
* @param ptypes the parameter types of the method
|
||||
* @return the method handle for the method
|
||||
*/
|
||||
public MethodHandle findOwnStatic(String name, Class<?> rtype, Class<?>... ptypes) {
|
||||
return findStatic(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes));
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
|
||||
|
||||
/**
|
||||
* A call site descriptor that stores a specific {@link Lookup}. It does not, however, store static bootstrap arguments.
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
class LookupCallSiteDescriptor extends DefaultCallSiteDescriptor {
|
||||
private Lookup lookup;
|
||||
|
||||
/**
|
||||
* Create a new call site descriptor from explicit information.
|
||||
* @param tokenizedName the name of the method
|
||||
* @param methodType the method type
|
||||
* @param lookup the lookup
|
||||
*/
|
||||
LookupCallSiteDescriptor(String[] tokenizedName, MethodType methodType, Lookup lookup) {
|
||||
super(tokenizedName, methodType);
|
||||
this.lookup = lookup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Lookup getLookup() {
|
||||
return lookup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallSiteDescriptor changeMethodType(MethodType newMethodType) {
|
||||
return new LookupCallSiteDescriptor(getTokenizedName(), newMethodType, lookup);
|
||||
}
|
||||
}
|
218
nashorn/src/jdk/internal/dynalink/support/NameCodec.java
Normal file
218
nashorn/src/jdk/internal/dynalink/support/NameCodec.java
Normal file
@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
|
||||
/**
|
||||
* Implements the name mangling and demangling as specified by John Rose's
|
||||
* <a href="https://blogs.oracle.com/jrose/entry/symbolic_freedom_in_the_vm" target="_blank">"Symbolic Freedom in the
|
||||
* VM"</a> article. It is recommended that implementers of languages on the JVM uniformly adopt this for symbolic
|
||||
* interoperability between languages. Normally, you would mangle the names as you're generating bytecode, and then
|
||||
* demangle them when you're creating {@link CallSiteDescriptor} objects. Note that you are expected to mangle
|
||||
* individual tokens, and not the whole name at the call site, i.e. the colon character normally separating the tokens
|
||||
* is never mangled. I.e. you wouldn't mangle {@code dyn:getProp:color} into {@code dyn\!getProp\!color}, but you would
|
||||
* mangle {@code dyn:getProp:color$} into {@code dyn:getProp:\=color\%} (only mangling the individual token containing
|
||||
* the symbol {@code color$}). {@link CallSiteDescriptorFactory#tokenizeName(String)} (and by implication, all call site
|
||||
* descriptors it creates) will automatically perform demangling on the passed names. If you use this factory, or you
|
||||
* have your own way of creating call site descriptors, but you still delegate to this method of the default factory
|
||||
* (it is recommended that you do), then you have demangling handled for you already, and only need to ensure that you
|
||||
* mangle the names when you're emitting them in the bytecode.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class NameCodec {
|
||||
private static final char ESCAPE_CHAR = '\\';
|
||||
private static final char EMPTY_ESCAPE = '=';
|
||||
private static final String EMPTY_NAME = new String(new char[] { ESCAPE_CHAR, EMPTY_ESCAPE });
|
||||
private static final char EMPTY_CHAR = 0xFEFF;
|
||||
|
||||
private static final int MIN_ENCODING = '$';
|
||||
private static final int MAX_ENCODING = ']';
|
||||
private static final char[] ENCODING = new char[MAX_ENCODING - MIN_ENCODING + 1];
|
||||
private static final int MIN_DECODING = '!';
|
||||
private static final int MAX_DECODING = '}';
|
||||
private static final char[] DECODING = new char[MAX_DECODING - MIN_DECODING + 1];
|
||||
|
||||
static {
|
||||
addEncoding('/', '|');
|
||||
addEncoding('.', ',');
|
||||
addEncoding(';', '?');
|
||||
addEncoding('$', '%');
|
||||
addEncoding('<', '^');
|
||||
addEncoding('>', '_');
|
||||
addEncoding('[', '{');
|
||||
addEncoding(']', '}');
|
||||
addEncoding(':', '!');
|
||||
addEncoding('\\', '-');
|
||||
DECODING[EMPTY_ESCAPE - MIN_DECODING] = EMPTY_CHAR;
|
||||
}
|
||||
|
||||
private NameCodec() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes ("mangles") an unencoded symbolic name.
|
||||
* @param name the symbolic name to mangle
|
||||
* @return the mangled form of the symbolic name.
|
||||
*/
|
||||
public static String encode(String name) {
|
||||
final int l = name.length();
|
||||
if(l == 0) {
|
||||
return EMPTY_NAME;
|
||||
}
|
||||
StringBuilder b = null;
|
||||
int lastEscape = -1;
|
||||
for(int i = 0; i < l; ++i) {
|
||||
final int encodeIndex = name.charAt(i) - MIN_ENCODING;
|
||||
if(encodeIndex >= 0 && encodeIndex < ENCODING.length) {
|
||||
final char e = ENCODING[encodeIndex];
|
||||
if(e != 0) {
|
||||
if(b == null) {
|
||||
b = new StringBuilder(name.length() + 3);
|
||||
if(name.charAt(0) != ESCAPE_CHAR && i > 0) {
|
||||
b.append(EMPTY_NAME);
|
||||
}
|
||||
b.append(name, 0, i);
|
||||
} else {
|
||||
b.append(name, lastEscape + 1, i);
|
||||
}
|
||||
b.append(ESCAPE_CHAR).append(e);
|
||||
lastEscape = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(b == null) {
|
||||
return name.toString();
|
||||
}
|
||||
assert lastEscape != -1;
|
||||
b.append(name, lastEscape + 1, l);
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes ("demangles") an encoded symbolic name.
|
||||
* @param name the symbolic name to demangle
|
||||
* @return the demangled form of the symbolic name.
|
||||
*/
|
||||
public static String decode(String name) {
|
||||
if(name.charAt(0) != ESCAPE_CHAR) {
|
||||
return name;
|
||||
}
|
||||
final int l = name.length();
|
||||
if(l == 2 && name.charAt(1) == EMPTY_CHAR) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder b = new StringBuilder(name.length());
|
||||
int lastEscape = -2;
|
||||
int lastBackslash = -1;
|
||||
for(;;) {
|
||||
int nextBackslash = name.indexOf(ESCAPE_CHAR, lastBackslash + 1);
|
||||
if(nextBackslash == -1 || nextBackslash == l - 1) {
|
||||
break;
|
||||
}
|
||||
final int decodeIndex = name.charAt(nextBackslash + 1) - MIN_DECODING;
|
||||
if(decodeIndex >= 0 && decodeIndex < DECODING.length) {
|
||||
final char d = DECODING[decodeIndex];
|
||||
if(d == EMPTY_CHAR) {
|
||||
// "\=" is only valid at the beginning of a mangled string
|
||||
if(nextBackslash == 0) {
|
||||
lastEscape = 0;
|
||||
}
|
||||
} else if(d != 0) {
|
||||
b.append(name, lastEscape + 2, nextBackslash).append(d);
|
||||
lastEscape = nextBackslash;
|
||||
}
|
||||
}
|
||||
lastBackslash = nextBackslash;
|
||||
}
|
||||
b.append(name, lastEscape + 2, l);
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
private static void addEncoding(char from, char to) {
|
||||
ENCODING[from - MIN_ENCODING] = to;
|
||||
DECODING[to - MIN_DECODING] = from;
|
||||
}
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
|
||||
|
||||
class NamedDynCallSiteDescriptor extends UnnamedDynCallSiteDescriptor {
|
||||
private final String name;
|
||||
|
||||
NamedDynCallSiteDescriptor(String op, String name, MethodType methodType) {
|
||||
super(op, methodType);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNameTokenCount() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameToken(int i) {
|
||||
switch(i) {
|
||||
case 0: return "dyn";
|
||||
case 1: return getOp();
|
||||
case 2: return name;
|
||||
default: throw new IndexOutOfBoundsException(String.valueOf(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallSiteDescriptor changeMethodType(MethodType newMethodType) {
|
||||
return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new NamedDynCallSiteDescriptor(getOp(), name,
|
||||
newMethodType));
|
||||
}
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
|
||||
/**
|
||||
* A link request implementation for call sites that pass language runtime specific context arguments on the stack. The
|
||||
* context specific arguments should be the first "n" arguments.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class RuntimeContextLinkRequestImpl extends LinkRequestImpl {
|
||||
|
||||
private final int runtimeContextArgCount;
|
||||
private LinkRequestImpl contextStrippedRequest;
|
||||
|
||||
/**
|
||||
* Creates a new link request.
|
||||
*
|
||||
* @param callSiteDescriptor the descriptor for the call site being linked
|
||||
* @param arguments the arguments for the invocation
|
||||
* @param callSiteUnstable true if the call site being linked is considered unstable
|
||||
* @param runtimeContextArgCount the number of the leading arguments on the stack that represent the language
|
||||
* runtime specific context arguments.
|
||||
* @throws IllegalArgumentException if runtimeContextArgCount is less than 1.
|
||||
*/
|
||||
public RuntimeContextLinkRequestImpl(CallSiteDescriptor callSiteDescriptor, boolean callSiteUnstable,
|
||||
Object[] arguments, int runtimeContextArgCount) {
|
||||
super(callSiteDescriptor, callSiteUnstable, arguments);
|
||||
if(runtimeContextArgCount < 1) {
|
||||
throw new IllegalArgumentException("runtimeContextArgCount < 1");
|
||||
}
|
||||
this.runtimeContextArgCount = runtimeContextArgCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkRequest withoutRuntimeContext() {
|
||||
if(contextStrippedRequest == null) {
|
||||
contextStrippedRequest =
|
||||
new LinkRequestImpl(CallSiteDescriptorFactory.dropParameterTypes(getCallSiteDescriptor(), 1,
|
||||
runtimeContextArgCount + 1), isCallSiteUnstable(), getTruncatedArguments());
|
||||
}
|
||||
return contextStrippedRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkRequest replaceArguments(CallSiteDescriptor callSiteDescriptor, Object[] arguments) {
|
||||
return new RuntimeContextLinkRequestImpl(callSiteDescriptor, isCallSiteUnstable(), arguments,
|
||||
runtimeContextArgCount);
|
||||
}
|
||||
|
||||
private Object[] getTruncatedArguments() {
|
||||
final Object[] args = getArguments();
|
||||
final Object[] newargs = new Object[args.length - runtimeContextArgCount];
|
||||
newargs[0] = args[0]; // "this" remains at the 0th position
|
||||
System.arraycopy(args, runtimeContextArgCount + 1, newargs, 1, newargs.length - 1);
|
||||
return newargs;
|
||||
}
|
||||
}
|
@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.lang.invoke.WrongMethodTypeException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import jdk.internal.dynalink.linker.ConversionComparator;
|
||||
import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
|
||||
|
||||
/**
|
||||
* A factory for type converters. This class is the main implementation behind the
|
||||
* {@link LinkerServices#asType(MethodHandle, MethodType)}. It manages the known {@link GuardingTypeConverterFactory}
|
||||
* instances and creates appropriate converters for method handles.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class TypeConverterFactory {
|
||||
|
||||
private final GuardingTypeConverterFactory[] factories;
|
||||
private final ConversionComparator[] comparators;
|
||||
|
||||
private final ClassValue<ClassMap<MethodHandle>> converterMap = new ClassValue<ClassMap<MethodHandle>>() {
|
||||
@Override
|
||||
protected ClassMap<MethodHandle> computeValue(final Class<?> sourceType) {
|
||||
return new ClassMap<MethodHandle>(sourceType.getClassLoader()) {
|
||||
@Override
|
||||
protected MethodHandle computeValue(Class<?> targetType) {
|
||||
try {
|
||||
return createConverter(sourceType, targetType);
|
||||
} catch (RuntimeException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
private final ClassValue<ClassMap<MethodHandle>> converterIdentityMap = new ClassValue<ClassMap<MethodHandle>>() {
|
||||
@Override
|
||||
protected ClassMap<MethodHandle> computeValue(final Class<?> sourceType) {
|
||||
return new ClassMap<MethodHandle>(sourceType.getClassLoader()) {
|
||||
@Override
|
||||
protected MethodHandle computeValue(Class<?> targetType) {
|
||||
if(!canAutoConvert(sourceType, targetType)) {
|
||||
final MethodHandle converter = getTypeConverterNull(sourceType, targetType);
|
||||
if(converter != null) {
|
||||
return converter;
|
||||
}
|
||||
}
|
||||
return IDENTITY_CONVERSION.asType(MethodType.methodType(targetType, sourceType));
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances.
|
||||
*
|
||||
* @param factories the {@link GuardingTypeConverterFactory} instances to compose.
|
||||
*/
|
||||
public TypeConverterFactory(Iterable<? extends GuardingTypeConverterFactory> factories) {
|
||||
final List<GuardingTypeConverterFactory> l = new LinkedList<>();
|
||||
final List<ConversionComparator> c = new LinkedList<>();
|
||||
for(GuardingTypeConverterFactory factory: factories) {
|
||||
l.add(factory);
|
||||
if(factory instanceof ConversionComparator) {
|
||||
c.add((ConversionComparator)factory);
|
||||
}
|
||||
}
|
||||
this.factories = l.toArray(new GuardingTypeConverterFactory[l.size()]);
|
||||
this.comparators = c.toArray(new ConversionComparator[c.size()]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to {@link MethodHandle#asType(MethodType)} except it also hooks in method handles produced by
|
||||
* {@link GuardingTypeConverterFactory} implementations, providing for language-specific type coercing of
|
||||
* parameters. It will apply {@link MethodHandle#asType(MethodType)} for all primitive-to-primitive,
|
||||
* wrapper-to-primitive, primitive-to-wrapper conversions as well as for all upcasts. For all other conversions,
|
||||
* it'll insert {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters
|
||||
* provided by {@link GuardingTypeConverterFactory} implementations.
|
||||
*
|
||||
* @param handle target method handle
|
||||
* @param fromType the types of source arguments
|
||||
* @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)} and
|
||||
* {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with
|
||||
* {@link GuardingTypeConverterFactory} produced type converters as filters.
|
||||
*/
|
||||
public MethodHandle asType(MethodHandle handle, final MethodType fromType) {
|
||||
MethodHandle newHandle = handle;
|
||||
final MethodType toType = newHandle.type();
|
||||
final int l = toType.parameterCount();
|
||||
if(l != fromType.parameterCount()) {
|
||||
throw new WrongMethodTypeException("Parameter counts differ: " + handle.type() + " vs. " + fromType);
|
||||
}
|
||||
int pos = 0;
|
||||
final List<MethodHandle> converters = new LinkedList<>();
|
||||
for(int i = 0; i < l; ++i) {
|
||||
final Class<?> fromParamType = fromType.parameterType(i);
|
||||
final Class<?> toParamType = toType.parameterType(i);
|
||||
if(canAutoConvert(fromParamType, toParamType)) {
|
||||
newHandle = applyConverters(newHandle, pos, converters);
|
||||
} else {
|
||||
final MethodHandle converter = getTypeConverterNull(fromParamType, toParamType);
|
||||
if(converter != null) {
|
||||
if(converters.isEmpty()) {
|
||||
pos = i;
|
||||
}
|
||||
converters.add(converter);
|
||||
} else {
|
||||
newHandle = applyConverters(newHandle, pos, converters);
|
||||
}
|
||||
}
|
||||
}
|
||||
newHandle = applyConverters(newHandle, pos, converters);
|
||||
|
||||
// Convert return type
|
||||
final Class<?> fromRetType = fromType.returnType();
|
||||
final Class<?> toRetType = toType.returnType();
|
||||
if(fromRetType != Void.TYPE && toRetType != Void.TYPE) {
|
||||
if(!canAutoConvert(toRetType, fromRetType)) {
|
||||
final MethodHandle converter = getTypeConverterNull(toRetType, fromRetType);
|
||||
if(converter != null) {
|
||||
newHandle = MethodHandles.filterReturnValue(newHandle, converter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Take care of automatic conversions
|
||||
return newHandle.asType(fromType);
|
||||
}
|
||||
|
||||
private static MethodHandle applyConverters(MethodHandle handle, int pos, List<MethodHandle> converters) {
|
||||
if(converters.isEmpty()) {
|
||||
return handle;
|
||||
}
|
||||
final MethodHandle newHandle =
|
||||
MethodHandles.filterArguments(handle, pos, converters.toArray(new MethodHandle[converters.size()]));
|
||||
converters.clear();
|
||||
return newHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there might exist a conversion between the requested types (either an automatic JVM conversion,
|
||||
* or one provided by any available {@link GuardingTypeConverterFactory}), or false if there definitely does not
|
||||
* exist a conversion between the requested types. Note that returning true does not guarantee that the conversion
|
||||
* will succeed at runtime (notably, if the "from" or "to" types are sufficiently generic), but returning false
|
||||
* guarantees that it would fail.
|
||||
*
|
||||
* @param from the source type for the conversion
|
||||
* @param to the target type for the conversion
|
||||
* @return true if there can be a conversion, false if there can not.
|
||||
*/
|
||||
public boolean canConvert(final Class<?> from, final Class<?> to) {
|
||||
return canAutoConvert(from, to) || getTypeConverterNull(from, to) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines which of the two type conversions from a source type to the two target types is preferred. This is
|
||||
* used for dynamic overloaded method resolution. If the source type is convertible to exactly one target type with
|
||||
* a method invocation conversion, it is chosen, otherwise available {@link ConversionComparator}s are consulted.
|
||||
* @param sourceType the source type.
|
||||
* @param targetType1 one potential target type
|
||||
* @param targetType2 another potential target type.
|
||||
* @return one of Comparison constants that establish which - if any - of the target types is preferable for the
|
||||
* conversion.
|
||||
*/
|
||||
public Comparison compareConversion(Class<?> sourceType, Class<?> targetType1, Class<?> targetType2) {
|
||||
for(ConversionComparator comparator: comparators) {
|
||||
final Comparison result = comparator.compareConversion(sourceType, targetType1, targetType2);
|
||||
if(result != Comparison.INDETERMINATE) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if(TypeUtilities.isMethodInvocationConvertible(sourceType, targetType1)) {
|
||||
if(!TypeUtilities.isMethodInvocationConvertible(sourceType, targetType2)) {
|
||||
return Comparison.TYPE_1_BETTER;
|
||||
}
|
||||
} else if(TypeUtilities.isMethodInvocationConvertible(sourceType, targetType2)) {
|
||||
return Comparison.TYPE_2_BETTER;
|
||||
}
|
||||
return Comparison.INDETERMINATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether it's safe to perform an automatic conversion between the source and target class.
|
||||
*
|
||||
* @param fromType convert from this class
|
||||
* @param toType convert to this class
|
||||
* @return true if it's safe to let MethodHandles.convertArguments() to handle this conversion.
|
||||
*/
|
||||
/*private*/ static boolean canAutoConvert(final Class<?> fromType, final Class<?> toType) {
|
||||
return TypeUtilities.isMethodInvocationConvertible(fromType, toType);
|
||||
}
|
||||
|
||||
/*private*/ MethodHandle getTypeConverterNull(Class<?> sourceType, Class<?> targetType) {
|
||||
final MethodHandle converter = converterMap.get(sourceType).get(targetType);
|
||||
return converter == IDENTITY_CONVERSION ? null : converter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a source and target type, returns a method handle that converts between them. Never returns null; in worst
|
||||
* case it will return an identity conversion (that might fail for some values at runtime). You can use this method
|
||||
* if you have a piece of your program that is written in Java, and you need to reuse existing type conversion
|
||||
* machinery in a non-invokedynamic context.
|
||||
* @param sourceType the type to convert from
|
||||
* @param targetType the type to convert to
|
||||
* @return a method handle performing the conversion.
|
||||
*/
|
||||
public MethodHandle getTypeConverter(Class<?> sourceType, Class<?> targetType) {
|
||||
return converterIdentityMap.get(sourceType).get(targetType);
|
||||
}
|
||||
|
||||
/*private*/ MethodHandle createConverter(Class<?> sourceType, Class<?> targetType) throws Exception {
|
||||
final MethodType type = MethodType.methodType(targetType, sourceType);
|
||||
final MethodHandle identity = IDENTITY_CONVERSION.asType(type);
|
||||
MethodHandle last = identity;
|
||||
for(int i = factories.length; i-- > 0;) {
|
||||
final GuardedInvocation next = factories[i].convertToType(sourceType, targetType);
|
||||
if(next != null) {
|
||||
next.assertType(type);
|
||||
last = next.compose(last);
|
||||
}
|
||||
}
|
||||
return last == identity ? IDENTITY_CONVERSION : last;
|
||||
}
|
||||
|
||||
/*private*/ static final MethodHandle IDENTITY_CONVERSION = MethodHandles.identity(Object.class);
|
||||
}
|
442
nashorn/src/jdk/internal/dynalink/support/TypeUtilities.java
Normal file
442
nashorn/src/jdk/internal/dynalink/support/TypeUtilities.java
Normal file
@ -0,0 +1,442 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Various static utility methods for testing type relationships.
|
||||
*
|
||||
* @author Attila Szegedi
|
||||
*/
|
||||
public class TypeUtilities {
|
||||
static final Class<Object> OBJECT_CLASS = Object.class;
|
||||
|
||||
private TypeUtilities() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Given two types represented by c1 and c2, returns a type that is their most specific common superclass or
|
||||
* superinterface.
|
||||
*
|
||||
* @param c1 one type
|
||||
* @param c2 another type
|
||||
* @return their most common superclass or superinterface. If they have several unrelated superinterfaces as their
|
||||
* most specific common type, or the types themselves are completely unrelated interfaces, {@link java.lang.Object}
|
||||
* is returned.
|
||||
*/
|
||||
public static Class<?> getMostSpecificCommonType(Class<?> c1, Class<?> c2) {
|
||||
if(c1 == c2) {
|
||||
return c1;
|
||||
}
|
||||
Class<?> c3 = c2;
|
||||
if(c3.isPrimitive()) {
|
||||
if(c3 == Byte.TYPE)
|
||||
c3 = Byte.class;
|
||||
else if(c3 == Short.TYPE)
|
||||
c3 = Short.class;
|
||||
else if(c3 == Character.TYPE)
|
||||
c3 = Character.class;
|
||||
else if(c3 == Integer.TYPE)
|
||||
c3 = Integer.class;
|
||||
else if(c3 == Float.TYPE)
|
||||
c3 = Float.class;
|
||||
else if(c3 == Long.TYPE)
|
||||
c3 = Long.class;
|
||||
else if(c3 == Double.TYPE)
|
||||
c3 = Double.class;
|
||||
}
|
||||
Set<Class<?>> a1 = getAssignables(c1, c3);
|
||||
Set<Class<?>> a2 = getAssignables(c3, c1);
|
||||
a1.retainAll(a2);
|
||||
if(a1.isEmpty()) {
|
||||
// Can happen when at least one of the arguments is an interface,
|
||||
// as they don't have Object at the root of their hierarchy.
|
||||
return Object.class;
|
||||
}
|
||||
// Gather maximally specific elements. Yes, there can be more than one
|
||||
// thank to interfaces. I.e., if you call this method for String.class
|
||||
// and Number.class, you'll have Comparable, Serializable, and Object
|
||||
// as maximal elements.
|
||||
List<Class<?>> max = new ArrayList<>();
|
||||
outer: for(Class<?> clazz: a1) {
|
||||
for(Iterator<Class<?>> maxiter = max.iterator(); maxiter.hasNext();) {
|
||||
Class<?> maxClazz = maxiter.next();
|
||||
if(isSubtype(maxClazz, clazz)) {
|
||||
// It can't be maximal, if there's already a more specific
|
||||
// maximal than it.
|
||||
continue outer;
|
||||
}
|
||||
if(isSubtype(clazz, maxClazz)) {
|
||||
// If it's more specific than a currently maximal element,
|
||||
// that currently maximal is no longer a maximal.
|
||||
maxiter.remove();
|
||||
}
|
||||
}
|
||||
// If we get here, no current maximal is more specific than the
|
||||
// current class, so it is considered maximal as well
|
||||
max.add(clazz);
|
||||
}
|
||||
if(max.size() > 1) {
|
||||
return OBJECT_CLASS;
|
||||
}
|
||||
return max.get(0);
|
||||
}
|
||||
|
||||
private static Set<Class<?>> getAssignables(Class<?> c1, Class<?> c2) {
|
||||
Set<Class<?>> s = new HashSet<>();
|
||||
collectAssignables(c1, c2, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
private static void collectAssignables(Class<?> c1, Class<?> c2, Set<Class<?>> s) {
|
||||
if(c1.isAssignableFrom(c2)) {
|
||||
s.add(c1);
|
||||
}
|
||||
Class<?> sc = c1.getSuperclass();
|
||||
if(sc != null) {
|
||||
collectAssignables(sc, c2, s);
|
||||
}
|
||||
Class<?>[] itf = c1.getInterfaces();
|
||||
for(int i = 0; i < itf.length; ++i) {
|
||||
collectAssignables(itf[i], c2, s);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<Class<?>, Class<?>> WRAPPER_TYPES = createWrapperTypes();
|
||||
private static final Map<Class<?>, Class<?>> PRIMITIVE_TYPES = invertMap(WRAPPER_TYPES);
|
||||
private static final Map<String, Class<?>> PRIMITIVE_TYPES_BY_NAME = createClassNameMapping(WRAPPER_TYPES.keySet());
|
||||
|
||||
private static Map<Class<?>, Class<?>> createWrapperTypes() {
|
||||
final Map<Class<?>, Class<?>> wrapperTypes = new IdentityHashMap<>(8);
|
||||
wrapperTypes.put(Boolean.TYPE, Boolean.class);
|
||||
wrapperTypes.put(Byte.TYPE, Byte.class);
|
||||
wrapperTypes.put(Character.TYPE, Character.class);
|
||||
wrapperTypes.put(Short.TYPE, Short.class);
|
||||
wrapperTypes.put(Integer.TYPE, Integer.class);
|
||||
wrapperTypes.put(Long.TYPE, Long.class);
|
||||
wrapperTypes.put(Float.TYPE, Float.class);
|
||||
wrapperTypes.put(Double.TYPE, Double.class);
|
||||
return Collections.unmodifiableMap(wrapperTypes);
|
||||
}
|
||||
|
||||
private static Map<String, Class<?>> createClassNameMapping(Collection<Class<?>> classes) {
|
||||
final Map<String, Class<?>> map = new HashMap<>();
|
||||
for(Class<?> clazz: classes) {
|
||||
map.put(clazz.getName(), clazz);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static <K, V> Map<V, K> invertMap(Map<K, V> map) {
|
||||
final Map<V, K> inverted = new IdentityHashMap<>(map.size());
|
||||
for(Map.Entry<K, V> entry: map.entrySet()) {
|
||||
inverted.put(entry.getValue(), entry.getKey());
|
||||
}
|
||||
return Collections.unmodifiableMap(inverted);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether one type can be converted to another type using a method invocation conversion, as per JLS 5.3
|
||||
* "Method Invocation Conversion". This is basically all conversions allowed by subtyping (see
|
||||
* {@link #isSubtype(Class, Class)}) as well as boxing conversion (JLS 5.1.7) optionally followed by widening
|
||||
* reference conversion and unboxing conversion (JLS 5.1.8) optionally followed by widening primitive conversion.
|
||||
*
|
||||
* @param callSiteType the parameter type at the call site
|
||||
* @param methodType the parameter type in the method declaration
|
||||
* @return true if callSiteType is method invocation convertible to the methodType.
|
||||
*/
|
||||
public static boolean isMethodInvocationConvertible(Class<?> callSiteType, Class<?> methodType) {
|
||||
if(methodType.isAssignableFrom(callSiteType)) {
|
||||
return true;
|
||||
}
|
||||
if(callSiteType.isPrimitive()) {
|
||||
if(methodType.isPrimitive()) {
|
||||
return isProperPrimitiveSubtype(callSiteType, methodType);
|
||||
}
|
||||
// Boxing + widening reference conversion
|
||||
return methodType.isAssignableFrom(WRAPPER_TYPES.get(callSiteType));
|
||||
}
|
||||
if(methodType.isPrimitive()) {
|
||||
final Class<?> unboxedCallSiteType = PRIMITIVE_TYPES.get(callSiteType);
|
||||
return unboxedCallSiteType != null
|
||||
&& (unboxedCallSiteType == methodType || isProperPrimitiveSubtype(unboxedCallSiteType, methodType));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether one type can be potentially converted to another type at runtime. Allows a conversion between
|
||||
* any subtype and supertype in either direction, and also allows a conversion between any two primitive types, as
|
||||
* well as between any primitive type and any reference type that can hold a boxed primitive.
|
||||
*
|
||||
* @param callSiteType the parameter type at the call site
|
||||
* @param methodType the parameter type in the method declaration
|
||||
* @return true if callSiteType is potentially convertible to the methodType.
|
||||
*/
|
||||
public static boolean isPotentiallyConvertible(Class<?> callSiteType, Class<?> methodType) {
|
||||
// Widening or narrowing reference conversion
|
||||
if(methodType.isAssignableFrom(callSiteType) || callSiteType.isAssignableFrom(methodType)) {
|
||||
return true;
|
||||
}
|
||||
if(callSiteType.isPrimitive()) {
|
||||
// Allow any conversion among primitives, as well as from any
|
||||
// primitive to any type that can receive a boxed primitive.
|
||||
// TODO: narrow this a bit, i.e. allow, say, boolean to Character?
|
||||
// MethodHandles.convertArguments() allows it, so we might need to
|
||||
// too.
|
||||
return methodType.isPrimitive() || isAssignableFromBoxedPrimitive(methodType);
|
||||
}
|
||||
if(methodType.isPrimitive()) {
|
||||
// Allow conversion from any reference type that can contain a
|
||||
// boxed primitive to any primitive.
|
||||
// TODO: narrow this a bit too?
|
||||
return isAssignableFromBoxedPrimitive(callSiteType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether one type is a subtype of another type, as per JLS 4.10 "Subtyping". Note: this is not strict
|
||||
* or proper subtype, therefore true is also returned for identical types; to be completely precise, it allows
|
||||
* identity conversion (JLS 5.1.1), widening primitive conversion (JLS 5.1.2) and widening reference conversion (JLS
|
||||
* 5.1.5).
|
||||
*
|
||||
* @param subType the supposed subtype
|
||||
* @param superType the supposed supertype of the subtype
|
||||
* @return true if subType can be converted by identity conversion, widening primitive conversion, or widening
|
||||
* reference conversion to superType.
|
||||
*/
|
||||
public static boolean isSubtype(Class<?> subType, Class<?> superType) {
|
||||
// Covers both JLS 4.10.2 "Subtyping among Class and Interface Types"
|
||||
// and JLS 4.10.3 "Subtyping among Array Types", as well as primitive
|
||||
// type identity.
|
||||
if(superType.isAssignableFrom(subType)) {
|
||||
return true;
|
||||
}
|
||||
// JLS 4.10.1 "Subtyping among Primitive Types". Note we don't test for
|
||||
// identity, as identical types were taken care of in the
|
||||
// isAssignableFrom test. As per 4.10.1, the supertype relation is as
|
||||
// follows:
|
||||
// double > float
|
||||
// float > long
|
||||
// long > int
|
||||
// int > short
|
||||
// int > char
|
||||
// short > byte
|
||||
if(superType.isPrimitive() && subType.isPrimitive()) {
|
||||
return isProperPrimitiveSubtype(subType, superType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a supposed primitive subtype is a proper subtype ( meaning, subtype and not identical) of the
|
||||
* supposed primitive supertype
|
||||
*
|
||||
* @param subType the supposed subtype
|
||||
* @param superType the supposed supertype
|
||||
* @return true if subType is a proper (not identical to) primitive subtype of the superType
|
||||
*/
|
||||
private static boolean isProperPrimitiveSubtype(Class<?> subType, Class<?> superType) {
|
||||
if(superType == boolean.class || subType == boolean.class) {
|
||||
return false;
|
||||
}
|
||||
if(subType == byte.class) {
|
||||
return superType != char.class;
|
||||
}
|
||||
if(subType == char.class) {
|
||||
return superType != short.class && superType != byte.class;
|
||||
}
|
||||
if(subType == short.class) {
|
||||
return superType != char.class && superType != byte.class;
|
||||
}
|
||||
if(subType == int.class) {
|
||||
return superType == long.class || superType == float.class || superType == double.class;
|
||||
}
|
||||
if(subType == long.class) {
|
||||
return superType == float.class || superType == double.class;
|
||||
}
|
||||
if(subType == float.class) {
|
||||
return superType == double.class;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPES = createWrapperToPrimitiveTypes();
|
||||
|
||||
private static Map<Class<?>, Class<?>> createWrapperToPrimitiveTypes() {
|
||||
final Map<Class<?>, Class<?>> classes = new IdentityHashMap<>();
|
||||
classes.put(Void.class, Void.TYPE);
|
||||
classes.put(Boolean.class, Boolean.TYPE);
|
||||
classes.put(Byte.class, Byte.TYPE);
|
||||
classes.put(Character.class, Character.TYPE);
|
||||
classes.put(Short.class, Short.TYPE);
|
||||
classes.put(Integer.class, Integer.TYPE);
|
||||
classes.put(Long.class, Long.TYPE);
|
||||
classes.put(Float.class, Float.TYPE);
|
||||
classes.put(Double.class, Double.TYPE);
|
||||
return classes;
|
||||
}
|
||||
|
||||
private static final Set<Class<?>> PRIMITIVE_WRAPPER_TYPES = createPrimitiveWrapperTypes();
|
||||
|
||||
private static Set<Class<?>> createPrimitiveWrapperTypes() {
|
||||
final Map<Class<?>, Class<?>> classes = new IdentityHashMap<>();
|
||||
addClassHierarchy(classes, Boolean.class);
|
||||
addClassHierarchy(classes, Byte.class);
|
||||
addClassHierarchy(classes, Character.class);
|
||||
addClassHierarchy(classes, Short.class);
|
||||
addClassHierarchy(classes, Integer.class);
|
||||
addClassHierarchy(classes, Long.class);
|
||||
addClassHierarchy(classes, Float.class);
|
||||
addClassHierarchy(classes, Double.class);
|
||||
return classes.keySet();
|
||||
}
|
||||
|
||||
private static void addClassHierarchy(Map<Class<?>, Class<?>> map, Class<?> clazz) {
|
||||
if(clazz == null) {
|
||||
return;
|
||||
}
|
||||
map.put(clazz, clazz);
|
||||
addClassHierarchy(map, clazz.getSuperclass());
|
||||
for(Class<?> itf: clazz.getInterfaces()) {
|
||||
addClassHierarchy(map, itf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the class can be assigned from any boxed primitive.
|
||||
*
|
||||
* @param clazz the class
|
||||
* @return true if the class can be assigned from any boxed primitive. Basically, it is true if the class is any
|
||||
* primitive wrapper class, or a superclass or superinterface of any primitive wrapper class.
|
||||
*/
|
||||
private static boolean isAssignableFromBoxedPrimitive(Class<?> clazz) {
|
||||
return PRIMITIVE_WRAPPER_TYPES.contains(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a name of a primitive type (except "void"), returns the class representing it. I.e. when invoked with
|
||||
* "int", returns {@link Integer#TYPE}.
|
||||
* @param name the name of the primitive type
|
||||
* @return the class representing the primitive type, or null if the name does not correspond to a primitive type
|
||||
* or is "void".
|
||||
*/
|
||||
public static Class<?> getPrimitiveTypeByName(String name) {
|
||||
return PRIMITIVE_TYPES_BY_NAME.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* When passed a class representing a wrapper for a primitive type, returns the class representing the corresponding
|
||||
* primitive type. I.e. calling it with {@code Integer.class} will return {@code Integer.TYPE}. If passed a class
|
||||
* that is not a wrapper for primitive type, returns null.
|
||||
* @param wrapperType the class object representing a wrapper for a primitive type
|
||||
* @return the class object representing the primitive type, or null if the passed class is not a primitive wrapper.
|
||||
*/
|
||||
public static Class<?> getPrimitiveType(Class<?> wrapperType) {
|
||||
return WRAPPER_TO_PRIMITIVE_TYPES.get(wrapperType);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When passed a class representing a primitive type, returns the class representing the corresponding
|
||||
* wrapper type. I.e. calling it with {@code int.class} will return {@code Integer.class}. If passed a class
|
||||
* that is not a primitive type, returns null.
|
||||
* @param primitiveType the class object representing a primitive type
|
||||
* @return the class object representing the wrapper type, or null if the passed class is not a primitive.
|
||||
*/
|
||||
public static Class<?> getWrapperType(Class<?> primitiveType) {
|
||||
return WRAPPER_TYPES.get(primitiveType);
|
||||
}
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2010, 2013, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is available under and governed by the GNU General Public
|
||||
* License version 2 only, as published by the Free Software Foundation.
|
||||
* However, the following notice accompanied the original version of this
|
||||
* file, and Oracle licenses the original version of this file under the BSD
|
||||
* license:
|
||||
*/
|
||||
/*
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package jdk.internal.dynalink.support;
|
||||
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
|
||||
|
||||
class UnnamedDynCallSiteDescriptor extends AbstractCallSiteDescriptor {
|
||||
private final MethodType methodType;
|
||||
private final String op;
|
||||
|
||||
UnnamedDynCallSiteDescriptor(String op, MethodType methodType) {
|
||||
this.op = op;
|
||||
this.methodType = methodType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNameTokenCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
String getOp() {
|
||||
return op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNameToken(int i) {
|
||||
switch(i) {
|
||||
case 0: return "dyn";
|
||||
case 1: return op;
|
||||
default: throw new IndexOutOfBoundsException(String.valueOf(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodType getMethodType() {
|
||||
return methodType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallSiteDescriptor changeMethodType(MethodType newMethodType) {
|
||||
return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new UnnamedDynCallSiteDescriptor(op,
|
||||
newMethodType));
|
||||
}
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
# Copyright (c) 2010, 2013, 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.
|
||||
|
||||
# This file is available under and governed by the GNU General Public
|
||||
# License version 2 only, as published by the Free Software Foundation.
|
||||
# However, the following notice accompanied the original version of this
|
||||
# file, and Oracle licenses the original version of this file under the BSD
|
||||
# license:
|
||||
#
|
||||
# Copyright 2009-2013 Attila Szegedi
|
||||
#
|
||||
# Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
# and the BSD License (the "BSD License"), with licensee being free to
|
||||
# choose either of the two at their discretion.
|
||||
#
|
||||
# You may not use this file except in compliance with either the Apache
|
||||
# License or the BSD License.
|
||||
#
|
||||
# If you choose to use this file in compliance with the Apache License, the
|
||||
# following notice applies to you:
|
||||
#
|
||||
# You may obtain a copy of the Apache License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
# implied. See the License for the specific language governing
|
||||
# permissions and limitations under the License.
|
||||
#
|
||||
# If you choose to use this file in compliance with the BSD License, the
|
||||
# following notice applies to you:
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# * Neither the name of the copyright holder nor the names of
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
isInstanceGuardAlwaysTrue=isInstance guard for {0} in position {1} in method type {2} will always return true
|
||||
isInstanceGuardAlwaysFalse=isInstance guard for {0} in position {1} in method type {2} will always return false
|
||||
|
||||
isOfClassGuardAlwaysTrue=isOfClass guard for {0} in position {1} in method type {2} will always return true
|
||||
isOfClassGuardAlwaysFalse=isOfClass guard for {0} in position {1} in method type {2} will always return false
|
||||
|
||||
isArrayGuardAlwaysTrue=isArray guard in position {0} in method type {1} will always return true
|
||||
isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} will always return false
|
89
nashorn/src/jdk/internal/dynalink/support/package.html
Normal file
89
nashorn/src/jdk/internal/dynalink/support/package.html
Normal file
@ -0,0 +1,89 @@
|
||||
<!--
|
||||
Copyright (c) 2010, 2013, 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.
|
||||
-->
|
||||
|
||||
<!--
|
||||
This file is available under and governed by the GNU General Public
|
||||
License version 2 only, as published by the Free Software Foundation.
|
||||
However, the following notice accompanied the original version of this
|
||||
file, and Oracle licenses the original version of this file under the BSD
|
||||
license:
|
||||
|
||||
Copyright 2009-2013 Attila Szegedi
|
||||
|
||||
Licensed under both the Apache License, Version 2.0 (the "Apache License")
|
||||
and the BSD License (the "BSD License"), with licensee being free to
|
||||
choose either of the two at their discretion.
|
||||
|
||||
You may not use this file except in compliance with either the Apache
|
||||
License or the BSD License.
|
||||
|
||||
If you choose to use this file in compliance with the Apache License, the
|
||||
following notice applies to you:
|
||||
|
||||
You may obtain a copy of the Apache License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied. See the License for the specific language governing
|
||||
permissions and limitations under the License.
|
||||
|
||||
If you choose to use this file in compliance with the BSD License, the
|
||||
following notice applies to you:
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the names of
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
|
||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
-->
|
||||
<body>
|
||||
<p>
|
||||
Contains supporting classes for other packages. There is no guarantee that
|
||||
any of these classes or interfaces will not change in a manner that breaks
|
||||
backwards compatibility; they are not considered to be part of the public
|
||||
API.
|
||||
</p>
|
||||
</body>
|
@ -31,6 +31,7 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.LAZY;
|
||||
import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
|
||||
import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
|
||||
import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
@ -40,6 +41,7 @@ import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import jdk.internal.dynalink.support.NameCodec;
|
||||
import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
|
||||
import jdk.nashorn.internal.codegen.types.Type;
|
||||
import jdk.nashorn.internal.ir.FunctionNode;
|
||||
@ -49,7 +51,6 @@ import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.DebugLogger;
|
||||
import jdk.nashorn.internal.runtime.Source;
|
||||
import jdk.nashorn.internal.runtime.options.Options;
|
||||
import org.dynalang.dynalink.support.NameCodec;
|
||||
|
||||
/**
|
||||
* Responsible for converting JavaScripts to java byte code. Main entry
|
||||
|
@ -71,6 +71,7 @@ import java.lang.reflect.Array;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import jdk.internal.dynalink.support.NameCodec;
|
||||
import jdk.internal.org.objectweb.asm.Handle;
|
||||
import jdk.internal.org.objectweb.asm.MethodVisitor;
|
||||
import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
|
||||
@ -94,7 +95,6 @@ import jdk.nashorn.internal.runtime.Scope;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.linker.Bootstrap;
|
||||
import jdk.nashorn.internal.runtime.options.Options;
|
||||
import org.dynalang.dynalink.support.NameCodec;
|
||||
|
||||
/**
|
||||
* This is the main function responsible for emitting method code
|
||||
|
@ -27,7 +27,6 @@ package jdk.nashorn.internal.codegen;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.nashorn.internal.codegen.types.Type;
|
||||
import jdk.nashorn.internal.ir.AccessNode;
|
||||
import jdk.nashorn.internal.ir.BinaryNode;
|
||||
|
@ -39,7 +39,6 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.nashorn.internal.codegen.Frame;
|
||||
import jdk.nashorn.internal.codegen.MethodEmitter.Label;
|
||||
import jdk.nashorn.internal.ir.annotations.Ignore;
|
||||
|
@ -28,7 +28,6 @@ package jdk.nashorn.internal.ir;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.nashorn.internal.codegen.types.Type;
|
||||
import jdk.nashorn.internal.ir.annotations.Ignore;
|
||||
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
|
||||
|
@ -26,7 +26,6 @@
|
||||
package jdk.nashorn.internal.ir;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
|
||||
import jdk.nashorn.internal.codegen.types.Type;
|
||||
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
|
||||
import jdk.nashorn.internal.parser.Token;
|
||||
|
@ -29,7 +29,6 @@ import java.io.PrintWriter;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import jdk.nashorn.internal.codegen.types.Type;
|
||||
import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.options.Options;
|
||||
|
@ -37,6 +37,8 @@ import java.lang.ref.SoftReference;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.nashorn.internal.objects.annotations.Attribute;
|
||||
import jdk.nashorn.internal.objects.annotations.Property;
|
||||
import jdk.nashorn.internal.objects.annotations.ScriptClass;
|
||||
@ -57,8 +59,6 @@ import jdk.nashorn.internal.runtime.ScriptingFunctions;
|
||||
import jdk.nashorn.internal.runtime.Source;
|
||||
import jdk.nashorn.internal.runtime.linker.InvokeByName;
|
||||
import jdk.nashorn.internal.scripts.JO$;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
|
||||
/**
|
||||
* Representation of global scope.
|
||||
|
@ -30,6 +30,8 @@ import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.nashorn.internal.objects.annotations.Attribute;
|
||||
import jdk.nashorn.internal.objects.annotations.Constructor;
|
||||
import jdk.nashorn.internal.objects.annotations.Function;
|
||||
@ -39,8 +41,6 @@ import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.linker.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.runtime.linker.PrimitiveLookup;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
|
||||
/**
|
||||
* ECMA 15.6 Boolean Objects.
|
||||
|
@ -35,6 +35,9 @@ import java.lang.invoke.MethodType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.nashorn.internal.objects.annotations.Constructor;
|
||||
import jdk.nashorn.internal.objects.annotations.ScriptClass;
|
||||
import jdk.nashorn.internal.runtime.FindProperty;
|
||||
@ -45,9 +48,6 @@ import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
|
||||
import jdk.nashorn.internal.runtime.linker.Lookup;
|
||||
import jdk.nashorn.internal.runtime.linker.MethodHandleFactory;
|
||||
import org.dynalang.dynalink.CallSiteDescriptor;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
|
||||
/**
|
||||
* This class is the implementation of the Nashorn-specific global object named {@code JSAdapter}. It can be
|
||||
|
@ -30,6 +30,8 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.Collection;
|
||||
import jdk.internal.dynalink.beans.StaticClass;
|
||||
import jdk.internal.dynalink.support.TypeUtilities;
|
||||
import jdk.nashorn.internal.objects.annotations.Attribute;
|
||||
import jdk.nashorn.internal.objects.annotations.Function;
|
||||
import jdk.nashorn.internal.objects.annotations.ScriptClass;
|
||||
@ -37,8 +39,6 @@ import jdk.nashorn.internal.objects.annotations.Where;
|
||||
import jdk.nashorn.internal.runtime.JSType;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
|
||||
import org.dynalang.dynalink.beans.StaticClass;
|
||||
import org.dynalang.dynalink.support.TypeUtilities;
|
||||
|
||||
/**
|
||||
* This class is the implementation for the {@code Java} global object exposed to programs running under Nashorn. This
|
||||
|
@ -25,16 +25,16 @@
|
||||
|
||||
package jdk.nashorn.internal.objects;
|
||||
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.beans.StaticClass;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.nashorn.internal.objects.annotations.Attribute;
|
||||
import jdk.nashorn.internal.objects.annotations.Constructor;
|
||||
import jdk.nashorn.internal.objects.annotations.Function;
|
||||
import jdk.nashorn.internal.objects.annotations.ScriptClass;
|
||||
import jdk.nashorn.internal.runtime.NativeJavaPackage;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import org.dynalang.dynalink.CallSiteDescriptor;
|
||||
import org.dynalang.dynalink.beans.StaticClass;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
|
||||
/**
|
||||
* This is "JavaImporter" constructor. This constructor allows you to use Java types omitting explicit package names.
|
||||
|
@ -36,6 +36,8 @@ import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Locale;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.nashorn.internal.objects.annotations.Attribute;
|
||||
import jdk.nashorn.internal.objects.annotations.Constructor;
|
||||
import jdk.nashorn.internal.objects.annotations.Function;
|
||||
@ -47,8 +49,6 @@ import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.linker.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.runtime.linker.PrimitiveLookup;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
|
||||
/**
|
||||
* ECMA 15.7 Number Objects.
|
||||
|
@ -39,6 +39,9 @@ import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.nashorn.internal.objects.annotations.Attribute;
|
||||
import jdk.nashorn.internal.objects.annotations.Constructor;
|
||||
import jdk.nashorn.internal.objects.annotations.Function;
|
||||
@ -56,9 +59,6 @@ import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
|
||||
import jdk.nashorn.internal.runtime.linker.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornGuards;
|
||||
import jdk.nashorn.internal.runtime.linker.PrimitiveLookup;
|
||||
import org.dynalang.dynalink.CallSiteDescriptor;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -31,6 +31,7 @@ import static jdk.nashorn.internal.parser.TokenType.EOF;
|
||||
import static jdk.nashorn.internal.parser.TokenType.EOL;
|
||||
import static jdk.nashorn.internal.parser.TokenType.ERROR;
|
||||
import static jdk.nashorn.internal.parser.TokenType.ESCSTRING;
|
||||
import static jdk.nashorn.internal.parser.TokenType.EXECSTRING;
|
||||
import static jdk.nashorn.internal.parser.TokenType.FLOATING;
|
||||
import static jdk.nashorn.internal.parser.TokenType.HEXADECIMAL;
|
||||
import static jdk.nashorn.internal.parser.TokenType.LBRACE;
|
||||
@ -40,7 +41,6 @@ import static jdk.nashorn.internal.parser.TokenType.RBRACE;
|
||||
import static jdk.nashorn.internal.parser.TokenType.REGEX;
|
||||
import static jdk.nashorn.internal.parser.TokenType.RPAREN;
|
||||
import static jdk.nashorn.internal.parser.TokenType.STRING;
|
||||
import static jdk.nashorn.internal.parser.TokenType.EXECSTRING;
|
||||
import static jdk.nashorn.internal.parser.TokenType.XML;
|
||||
|
||||
import jdk.nashorn.internal.runtime.ECMAErrors;
|
||||
|
@ -26,8 +26,8 @@
|
||||
package jdk.nashorn.internal.runtime;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
|
||||
/**
|
||||
* Runtime interface to the global scope of the current context.
|
||||
|
@ -28,9 +28,9 @@ package jdk.nashorn.internal.runtime;
|
||||
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
|
||||
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
|
||||
|
||||
import jdk.internal.dynalink.beans.StaticClass;
|
||||
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
|
||||
import jdk.nashorn.internal.parser.Lexer;
|
||||
import org.dynalang.dynalink.beans.StaticClass;
|
||||
|
||||
/**
|
||||
* Representation for ECMAScript types - this maps directly to the ECMA script standard
|
||||
|
@ -25,13 +25,13 @@
|
||||
|
||||
package jdk.nashorn.internal.runtime;
|
||||
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.beans.StaticClass;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.nashorn.internal.objects.NativeJava;
|
||||
import jdk.nashorn.internal.objects.annotations.Attribute;
|
||||
import jdk.nashorn.internal.objects.annotations.Function;
|
||||
import org.dynalang.dynalink.CallSiteDescriptor;
|
||||
import org.dynalang.dynalink.beans.StaticClass;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
|
||||
/**
|
||||
* An object that exposes Java packages and classes as its properties. Packages are exposed as objects that have further
|
||||
|
@ -33,14 +33,14 @@ import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
|
||||
import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
|
||||
import jdk.nashorn.internal.runtime.linker.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornGuards;
|
||||
import org.dynalang.dynalink.CallSiteDescriptor;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
|
||||
/**
|
||||
* Runtime representation of a JavaScript function.
|
||||
|
@ -39,6 +39,12 @@ final class ScriptLoader extends NashornLoader {
|
||||
super(parent, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
checkPackageAccess(name);
|
||||
return super.loadClassTrusted(name, resolve);
|
||||
}
|
||||
|
||||
// package-private and private stuff below this point
|
||||
|
||||
/**
|
||||
|
@ -55,6 +55,10 @@ import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
|
||||
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
|
||||
import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator;
|
||||
import jdk.nashorn.internal.objects.AccessorPropertyDescriptor;
|
||||
@ -65,10 +69,6 @@ import jdk.nashorn.internal.runtime.linker.Lookup;
|
||||
import jdk.nashorn.internal.runtime.linker.MethodHandleFactory;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornGuards;
|
||||
import org.dynalang.dynalink.CallSiteDescriptor;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
import org.dynalang.dynalink.support.CallSiteDescriptorFactory;
|
||||
|
||||
/**
|
||||
* Base class for generic JavaScript objects.
|
||||
|
@ -38,11 +38,11 @@ import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import jdk.internal.dynalink.beans.StaticClass;
|
||||
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
|
||||
import jdk.nashorn.internal.ir.debug.JSONWriter;
|
||||
import jdk.nashorn.internal.parser.Lexer;
|
||||
import jdk.nashorn.internal.runtime.linker.Bootstrap;
|
||||
import org.dynalang.dynalink.beans.StaticClass;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -29,18 +29,17 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
|
||||
import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.nashorn.internal.codegen.objects.ObjectClassGenerator;
|
||||
import jdk.nashorn.internal.runtime.linker.Lookup;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornGuards;
|
||||
|
||||
import org.dynalang.dynalink.CallSiteDescriptor;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
|
||||
/**
|
||||
* Instances of this class are quite ephemeral; they only exist for the duration of an invocation of
|
||||
* {@link ScriptObject#findSetMethod(CallSiteDescriptor, org.dynalang.dynalink.linker.LinkRequest)} and
|
||||
* {@link ScriptObject#findSetMethod(CallSiteDescriptor, jdk.internal.dynalink.linker.LinkRequest)} and
|
||||
* serve as the actual encapsulation of the algorithm for creating an appropriate property setter method.
|
||||
*/
|
||||
final class SetMethodCreator {
|
||||
|
@ -58,8 +58,6 @@ final class StructureLoader extends NashornLoader {
|
||||
|
||||
@Override
|
||||
protected synchronized Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
|
||||
checkPackageAccess(name);
|
||||
|
||||
// check the cache first
|
||||
final Class<?> loadedClass = findLoadedClass(name);
|
||||
if (loadedClass != null) {
|
||||
|
@ -31,10 +31,10 @@ import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import org.dynalang.dynalink.CallSiteDescriptor;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.support.CallSiteDescriptorFactory;
|
||||
import org.dynalang.dynalink.support.Guards;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
|
||||
import jdk.internal.dynalink.support.Guards;
|
||||
|
||||
/**
|
||||
* Unique instance of this class is used to represent JavaScript undefined.
|
||||
|
@ -29,11 +29,11 @@ import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
|
||||
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
|
||||
import org.dynalang.dynalink.CallSiteDescriptor;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
import org.dynalang.dynalink.support.CallSiteDescriptorFactory;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -32,15 +32,15 @@ import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.MethodType;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.DynamicLinker;
|
||||
import jdk.internal.dynalink.DynamicLinkerFactory;
|
||||
import jdk.internal.dynalink.beans.BeansLinker;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
|
||||
import jdk.nashorn.internal.codegen.RuntimeCallSite;
|
||||
import jdk.nashorn.internal.runtime.options.Options;
|
||||
import org.dynalang.dynalink.CallSiteDescriptor;
|
||||
import org.dynalang.dynalink.DynamicLinker;
|
||||
import org.dynalang.dynalink.DynamicLinkerFactory;
|
||||
import org.dynalang.dynalink.beans.BeansLinker;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkerServices;
|
||||
|
||||
/**
|
||||
* This class houses bootstrap method for invokedynamic instructions generated by compiler.
|
||||
|
@ -29,14 +29,14 @@ import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.util.Objects;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
|
||||
import jdk.nashorn.internal.runtime.JSType;
|
||||
import netscape.javascript.JSObject;
|
||||
import org.dynalang.dynalink.CallSiteDescriptor;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
import org.dynalang.dynalink.linker.LinkerServices;
|
||||
import org.dynalang.dynalink.linker.TypeBasedGuardingDynamicLinker;
|
||||
import org.dynalang.dynalink.support.CallSiteDescriptorFactory;
|
||||
|
||||
/**
|
||||
* A Dynalink linker to handle web browser built-in JS (DOM etc.) objects as well
|
||||
|
@ -70,6 +70,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import jdk.internal.dynalink.beans.StaticClass;
|
||||
import jdk.internal.dynalink.support.LinkRequestImpl;
|
||||
import jdk.internal.org.objectweb.asm.ClassWriter;
|
||||
import jdk.internal.org.objectweb.asm.Label;
|
||||
import jdk.internal.org.objectweb.asm.Opcodes;
|
||||
@ -83,8 +85,6 @@ import jdk.nashorn.internal.runtime.ScriptFunction;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.Undefined;
|
||||
import org.dynalang.dynalink.beans.StaticClass;
|
||||
import org.dynalang.dynalink.support.LinkRequestImpl;
|
||||
|
||||
/**
|
||||
* A factory class that generates adapter classes. Adapter classes allow implementation of Java interfaces and
|
||||
|
@ -33,10 +33,10 @@ import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import jdk.internal.dynalink.support.TypeUtilities;
|
||||
import jdk.nashorn.internal.runtime.ConsString;
|
||||
import jdk.nashorn.internal.runtime.JSType;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import org.dynalang.dynalink.support.TypeUtilities;
|
||||
|
||||
/**
|
||||
* Utility class shared by {@link NashornLinker} and {@code NashornPrimitiveLinker} for converting JS values to Java
|
||||
|
@ -43,14 +43,14 @@ import java.util.Map.Entry;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import jdk.internal.dynalink.ChainedCallSite;
|
||||
import jdk.internal.dynalink.DynamicLinker;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.nashorn.internal.runtime.Context;
|
||||
import jdk.nashorn.internal.runtime.Debug;
|
||||
import jdk.nashorn.internal.runtime.ScriptObject;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import jdk.nashorn.internal.runtime.options.Options;
|
||||
import org.dynalang.dynalink.ChainedCallSite;
|
||||
import org.dynalang.dynalink.DynamicLinker;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -30,13 +30,13 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
|
||||
import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import jdk.internal.dynalink.CallSiteDescriptor;
|
||||
import jdk.internal.dynalink.linker.GuardedInvocation;
|
||||
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
|
||||
import jdk.internal.dynalink.linker.LinkRequest;
|
||||
import jdk.internal.dynalink.linker.LinkerServices;
|
||||
import jdk.internal.dynalink.support.Guards;
|
||||
import jdk.nashorn.internal.runtime.ScriptRuntime;
|
||||
import org.dynalang.dynalink.CallSiteDescriptor;
|
||||
import org.dynalang.dynalink.linker.GuardedInvocation;
|
||||
import org.dynalang.dynalink.linker.GuardingDynamicLinker;
|
||||
import org.dynalang.dynalink.linker.LinkRequest;
|
||||
import org.dynalang.dynalink.linker.LinkerServices;
|
||||
import org.dynalang.dynalink.support.Guards;
|
||||
|
||||
/**
|
||||
* Nashorn bottom linker; used as a last-resort catch-all linker for all linking requests that fall through all other
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user