8008085: Integrate Dynalink source code into Nashorn codebase

Reviewed-by: jlaskey, lagergren, sundar
This commit is contained in:
Attila Szegedi 2013-02-14 13:22:26 +01:00
parent 7c466c84eb
commit 82f8cef55c
110 changed files with 12230 additions and 168 deletions

View File

@ -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 ---

View File

@ -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"/>

View File

@ -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>

View File

@ -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}:\

View 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);
}

View 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
}
}
}

View 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)));
}
}

View 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;
}
}

View 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());
}
}
}

View 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);
}
}

View File

@ -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);
}
}

View 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);
}

View 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;
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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;
}
};
}

View 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;
}
}

View 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.");
}
}
}

View 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);
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}
}

View 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));
}

View 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);
}
}

View 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() + "]";
}
}

View 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;
}
}

View 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() {
}
}

View File

@ -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())) + "]";
}
}
}

View 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);
}
}

View File

@ -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);
}
}

View 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("...");
}
}
}

View File

@ -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;
}
}

View 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);
}
}

View 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);
}
}

View File

@ -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;
}
}

View 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;
}
}

View 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.

View 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>

View File

@ -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);
}

View 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());
}
}
}

View File

@ -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;
}

View File

@ -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;
}

View 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);
}

View 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);
}

View File

@ -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);
}

View 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>

View 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>

View File

@ -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();
}
}

View File

@ -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);
}
}

View 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;
}
}

View 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() {
}
}

View 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.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;
}
}

View File

@ -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));
}
}

View 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;
}
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}
}

View File

@ -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));
}
}

View 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));
}
}

View 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);
}
}

View File

@ -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);
}
}

View 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));
}
}

View File

@ -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);
}
}

View 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;
}
}

View File

@ -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));
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View 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);
}
}

View File

@ -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));
}
}

View 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.
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

View 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>

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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;
/**

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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
/**

View File

@ -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.

View File

@ -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;
/**

View File

@ -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 {

View File

@ -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) {

View File

@ -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.

View File

@ -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;
/**

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
/**

View File

@ -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