# HG changeset patch # User attila # Date 1360844546 -3600 # Node ID 5a820fb118140f98367ca4542f0a413e37592188 # Parent 43e32b36153cbe4dca0e6262e71c34408d938ab6 8008085: Integrate Dynalink source code into Nashorn codebase Reviewed-by: jlaskey, lagergren, sundar diff -r 43e32b36153c -r 5a820fb11814 THIRD_PARTY_README --- a/THIRD_PARTY_README Thu Feb 14 13:01:52 2013 +0100 +++ b/THIRD_PARTY_README Thu Feb 14 13:22:26 2013 +0100 @@ -67,3 +67,34 @@ 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 --- diff -r 43e32b36153c -r 5a820fb11814 make/build.xml --- a/make/build.xml Thu Feb 14 13:01:52 2013 +0100 +++ b/make/build.xml Thu Feb 14 13:22:26 2013 +0100 @@ -54,19 +54,11 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + ${line.separator} @@ -134,7 +106,6 @@ - @@ -152,12 +123,10 @@ - - diff -r 43e32b36153c -r 5a820fb11814 make/nbproject/project.xml --- a/make/nbproject/project.xml Thu Feb 14 13:01:52 2013 +0100 +++ b/make/nbproject/project.xml Thu Feb 14 13:22:26 2013 +0100 @@ -164,7 +164,6 @@ ../src - ../build/dynalink/dynalink.jar 1.7 diff -r 43e32b36153c -r 5a820fb11814 make/project.properties --- a/make/project.properties Thu Feb 14 13:01:52 2013 +0100 +++ b/make/project.properties Thu Feb 14 13:22:26 2013 +0100 @@ -87,23 +87,10 @@ 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}:\ diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/CallSiteDescriptor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/CallSiteDescriptor.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 ith 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 ith 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); + +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/ChainedCallSite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/ChainedCallSite.java Thu Feb 14 13:22:26 2013 +0100 @@ -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> 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 currentInvocations = invocations.get(); + @SuppressWarnings({ "unchecked", "rawtypes" }) + final LinkedList newInvocations = + currentInvocations == null || reset ? new LinkedList<>() : (LinkedList)currentInvocations.clone(); + + // First, prune the chain of invalidated switchpoints. + for(Iterator 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 + } + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/DefaultBootstrapper.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/DefaultBootstrapper.java Thu Feb 14 13:22:26 2013 +0100 @@ -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))); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/DynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/DynamicLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -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: + * + *
+ * 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)));
+ *     }
+ * }
+ * 
+ * + * Note how there are three components you will need to provide here: + *
    + *
  • 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}.
  • + *
  • 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.
  • + *
  • 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.
  • + *
+ * + * @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 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> 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; + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/DynamicLinkerFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/DynamicLinkerFactory.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 prioritizedLinkers; + private List 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 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 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> knownLinkerClasses = new HashSet<>(); + addClasses(knownLinkerClasses, prioritizedLinkers); + addClasses(knownLinkerClasses, fallbackLinkers); + + final List discovered = AutoDiscovery.loadLinkers(classLoader); + // Now, concatenate ... + final List 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 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 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> knownLinkerClasses, + List linkers) { + for(GuardingDynamicLinker linker: linkers) { + knownLinkerClasses.add(linker.getClass()); + } + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/MonomorphicCallSite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/MonomorphicCallSite.java Thu Feb 14 13:22:26 2013 +0100 @@ -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); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/NoSuchDynamicMethodException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java Thu Feb 14 13:22:26 2013 +0100 @@ -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); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/RelinkableCallSite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/RelinkableCallSite.java Thu Feb 14 13:22:26 2013 +0100 @@ -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); +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/AbstractJavaLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 propertyGetters = new HashMap<>(); + private final Map propertySetters = new HashMap<>(); + private final Map 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 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 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 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 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 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 List pop(List 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 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 methodMap) { + final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap); + return dynaMethod != null ? dynaMethod.getInvocation(callSiteType, linkerServices) : null; + } + + private static DynamicMethod getDynamicMethod(String methodName, Map methodMap) { + final DynamicMethod dynaMethod = methodMap.get(methodName); + return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap); + } + + private static SimpleDynamicMethod getExplicitSignatureDynamicMethod(String methodName, + Map 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 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 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 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; + } + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 methods; + private final Set> 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 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); + } + } + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 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 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 getMethods() { + return methods; + } + + /** + * Returns a list of all methods in this objects that are maximally specific. + * + * @return a list of maximally specific methods. + */ + List 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; + } + }; +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/BeanIntrospector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/BeanIntrospector.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 getInnerClassGetters() { + return Collections.emptyMap(); // NOTE: non-static inner classes are also on StaticClassIntrospector. + } + + @Override + MethodHandle editMethodHandle(MethodHandle mh) { + return mh; + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/BeanLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/BeanLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 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 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 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."); + } + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/BeansLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/BeansLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -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: + *
    + *
  • 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;
  • + *
  • expose all property getters and setters declared by the class' {@link BeanInfo};
  • + *
  • expose all public methods and methods declared by the class' {@link BeanInfo} for invocation through + * {@code dyn:callMethod} operation;
  • + *
  • 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};
  • + *
  • expose all public fields as properties, unless there are getters or setters for the properties of the same name;
  • + *
  • 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});
  • + *
  • expose a virtual property named {@code length} on Java arrays;
  • + *
  • 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);
  • + *
  • 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.
  • + *
  • expose a virtual property named {@code static} on instances of {@link java.lang.Class} to access their + * {@link StaticClass}.
  • + *
+ *

Overloaded method resolution 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).

+ *

Variable argument invocation is handled for both methods and constructors.

+ *

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.

+ * + * @author Attila Szegedi + */ +public class BeansLinker implements GuardingDynamicLinker { + private static final ClassValue linkers = new ClassValue() { + @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); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java Thu Feb 14 13:22:26 2013 +0100 @@ -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()); + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/CheckRestrictedPackageInternal.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/CheckRestrictedPackageInternal.java Thu Feb 14 13:22:26 2013 +0100 @@ -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() { + @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); + } + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/ClassLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/ClassLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -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)); + +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/ClassString.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/ClassString.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 getMaximallySpecifics(List 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 getApplicables(List methods, LinkerServices linkerServices, boolean varArg) { + final LinkedList 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); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/DynamicMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/DynamicMethod.java Thu Feb 14 13:22:26 2013 +0100 @@ -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() + "]"; + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/DynamicMethodLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -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; + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/FacetIntrospector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/FacetIntrospector.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 getInnerClassGetters(); + + /** + * Returns the fields for the class facet. + * @return the fields for the class facet. + */ + Collection 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 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 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() { + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java Thu Feb 14 13:22:26 2013 +0100 @@ -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())) + "]"; + } + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/MaximallySpecific.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/MaximallySpecific.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 getMaximallySpecificMethods(List 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 getMaximallySpecificMethods(List methods, boolean varArgs, + Class[] argTypes, LinkerServices ls) { + if(methods.size() < 2) { + return methods; + } + final LinkedList maximals = new LinkedList<>(); + for(MethodHandle m: methods) { + final MethodType methodType = m.type(); + boolean lessSpecific = false; + for(Iterator 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); + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 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(), clazz.getClassLoader(), getClassAndMethodName(clazz, name)); + } + + private OverloadedDynamicMethod(LinkedList methods, ClassLoader classLoader, String name) { + super(name); + this.methods = methods; + this.classLoader = classLoader; + } + + @Override + SimpleDynamicMethod getMethodForExactParamTypes(String paramTypes) { + final LinkedList 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 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 invokables = (List)methods.clone(); + invokables.removeAll(subtypingApplicables.getMethods()); + invokables.removeAll(methodInvocationApplicables.getMethods()); + invokables.removeAll(variableArityApplicables.getMethods()); + for(final Iterator 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); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/OverloadedMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/OverloadedMethod.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 argTypesToMethods = new ConcurrentHashMap<>(); + private final OverloadedDynamicMethod parent; + private final MethodType callSiteType; + private final MethodHandle invoker; + private final LinkerServices linkerServices; + private final ArrayList fixArgMethods; + private final ArrayList varArgMethods; + + OverloadedMethod(List 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 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 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 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 methods) { + final StringBuilder b = new StringBuilder().append('['); + final Iterator 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("..."); + } + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/RestrictedPackageTester.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/RestrictedPackageTester.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 { + + 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; + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Thu Feb 14 13:22:26 2013 +0100 @@ -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); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/StaticClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/StaticClass.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 staticClasses = new ClassValue() { + @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); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/StaticClassIntrospector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 getInnerClassGetters() { + final Map 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; + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/StaticClassLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/StaticClassLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 linkers = new ClassValue() { + @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, ""); + } + + final Constructor[] ctrs = clazz.getConstructors(); + final List 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, ""); + } + + 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; + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/messages.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/messages.properties Thu Feb 14 13:22:26 2013 +0100 @@ -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 +# +# 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. \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/beans/package.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/beans/package.html Thu Feb 14 13:22:26 2013 +0100 @@ -0,0 +1,86 @@ + + + + +

+ Contains the linker for POJOs. +

+ diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/linker/ConversionComparator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/linker/ConversionComparator.java Thu Feb 14 13:22:26 2013 +0100 @@ -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); +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/linker/GuardedInvocation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/linker/GuardedInvocation.java Thu Feb 14 13:22:26 2013 +0100 @@ -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> 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()); + } + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 + * META-INF/services/jdk.internal.dynalink.linker.GuardingDynamicLinker 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; +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java Thu Feb 14 13:22:26 2013 +0100 @@ -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; +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/linker/LinkRequest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/linker/LinkRequest.java Thu Feb 14 13:22:26 2013 +0100 @@ -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); +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/linker/LinkerServices.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/linker/LinkerServices.java Thu Feb 14 13:22:26 2013 +0100 @@ -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); +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/linker/TypeBasedGuardingDynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/linker/TypeBasedGuardingDynamicLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -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); +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/linker/package.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/linker/package.html Thu Feb 14 13:22:26 2013 +0100 @@ -0,0 +1,87 @@ + + + + +

+ Contains interfaces and classes needed by language runtimes to implement + their own language-specific linkers. +

+ diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/package.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/package.html Thu Feb 14 13:22:26 2013 +0100 @@ -0,0 +1,93 @@ + + + + +

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

+

+ Languages that wish to define and use their own linkers will also need to + use the {@link jdk.internal.dynalink.linker} package. +

+ diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java Thu Feb 14 13:22:26 2013 +0100 @@ -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(); + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java Thu Feb 14 13:22:26 2013 +0100 @@ -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); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/AutoDiscovery.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/AutoDiscovery.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 + * /META-INF/services/jdk.internal.dynalink.linker.GuardingDynamicLinker 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 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 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 List getLinkers(ServiceLoader loader) { + final List list = new LinkedList<>(); + for(final T linker: loader) { + list.add(linker); + } + return list; + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/Backport.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/Backport.java Thu Feb 14 13:22:26 2013 +0100 @@ -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() { + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -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; + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java Thu Feb 14 13:22:26 2013 +0100 @@ -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> 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 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 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> ptypesToInsert) { + return desc.changeMethodType(desc.getMethodType().insertParameterTypes(num, ptypesToInsert)); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/ClassMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/ClassMap.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 the type of the values in the map + */ +public abstract class ClassMap { + private final ConcurrentMap, T> map = new ConcurrentHashMap<>(); + private final Map, Reference> 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 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; + } + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 linkers) { + final List 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; + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -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> { + private static final List NO_LINKER = Collections.emptyList(); + private final TypeBasedGuardingDynamicLinker[] linkers; + private final List[] 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 computeValue(Class clazz) { + List 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> classToLinker; + + /** + * Creates a new composite type-based linker. + * + * @param linkers the component linkers + */ + public CompositeTypeBasedGuardingDynamicLinker(Iterable linkers) { + final List 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 optimize(Iterable linkers) { + final List llinkers = new LinkedList<>(); + final List 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 llinkers, + List tblinkers) { + switch(tblinkers.size()) { + case 0: { + break; + } + case 1: { + llinkers.addAll(tblinkers); + tblinkers.clear(); + break; + } + default: { + llinkers.add(new CompositeTypeBasedGuardingDynamicLinker(tblinkers)); + tblinkers.clear(); + break; + } + } + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java Thu Feb 14 13:22:26 2013 +0100 @@ -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)); + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/Guards.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/Guards.java Thu Feb 14 13:22:26 2013 +0100 @@ -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)); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/LinkRequestImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/LinkRequestImpl.java Thu Feb 14 13:22:26 2013 +0100 @@ -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); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/LinkerServicesImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/LinkerServicesImpl.java Thu Feb 14 13:22:26 2013 +0100 @@ -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); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/Lookup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/Lookup.java Thu Feb 14 13:22:26 2013 +0100 @@ -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(Classrefc, 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)); + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java Thu Feb 14 13:22:26 2013 +0100 @@ -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); + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/NameCodec.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/NameCodec.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 + * "Symbolic Freedom in the + * VM" 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; + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java Thu Feb 14 13:22:26 2013 +0100 @@ -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)); + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java Thu Feb 14 13:22:26 2013 +0100 @@ -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; + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/TypeConverterFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/TypeConverterFactory.java Thu Feb 14 13:22:26 2013 +0100 @@ -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> converterMap = new ClassValue>() { + @Override + protected ClassMap computeValue(final Class sourceType) { + return new ClassMap(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> converterIdentityMap = new ClassValue>() { + @Override + protected ClassMap computeValue(final Class sourceType) { + return new ClassMap(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 factories) { + final List l = new LinkedList<>(); + final List 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 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 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); +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/TypeUtilities.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/TypeUtilities.java Thu Feb 14 13:22:26 2013 +0100 @@ -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_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> a1 = getAssignables(c1, c3); + Set> 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> max = new ArrayList<>(); + outer: for(Class clazz: a1) { + for(Iterator> 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> getAssignables(Class c1, Class c2) { + Set> s = new HashSet<>(); + collectAssignables(c1, c2, s); + return s; + } + + private static void collectAssignables(Class c1, Class c2, Set> 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> WRAPPER_TYPES = createWrapperTypes(); + private static final Map, Class> PRIMITIVE_TYPES = invertMap(WRAPPER_TYPES); + private static final Map> PRIMITIVE_TYPES_BY_NAME = createClassNameMapping(WRAPPER_TYPES.keySet()); + + private static Map, Class> createWrapperTypes() { + final Map, 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> createClassNameMapping(Collection> classes) { + final Map> map = new HashMap<>(); + for(Class clazz: classes) { + map.put(clazz.getName(), clazz); + } + return map; + } + + private static Map invertMap(Map map) { + final Map inverted = new IdentityHashMap<>(map.size()); + for(Map.Entry 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> WRAPPER_TO_PRIMITIVE_TYPES = createWrapperToPrimitiveTypes(); + + private static Map, Class> createWrapperToPrimitiveTypes() { + final Map, 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> PRIMITIVE_WRAPPER_TYPES = createPrimitiveWrapperTypes(); + + private static Set> createPrimitiveWrapperTypes() { + final Map, 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> 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); + } +} \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java Thu Feb 14 13:22:26 2013 +0100 @@ -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)); + } +} diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/messages.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/messages.properties Thu Feb 14 13:22:26 2013 +0100 @@ -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 \ No newline at end of file diff -r 43e32b36153c -r 5a820fb11814 src/jdk/internal/dynalink/support/package.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/internal/dynalink/support/package.html Thu Feb 14 13:22:26 2013 +0100 @@ -0,0 +1,89 @@ + + + + +

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

+ diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/codegen/Compiler.java --- a/src/jdk/nashorn/internal/codegen/Compiler.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/Compiler.java Thu Feb 14 13:22:26 2013 +0100 @@ -31,6 +31,7 @@ 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.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.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 diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/codegen/MethodEmitter.java --- a/src/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Feb 14 13:22:26 2013 +0100 @@ -71,6 +71,7 @@ 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.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 diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/codegen/WeighNodes.java --- a/src/jdk/nashorn/internal/codegen/WeighNodes.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/codegen/WeighNodes.java Thu Feb 14 13:22:26 2013 +0100 @@ -27,7 +27,6 @@ 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; diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/ir/Block.java --- a/src/jdk/nashorn/internal/ir/Block.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/Block.java Thu Feb 14 13:22:26 2013 +0100 @@ -39,7 +39,6 @@ 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; diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/ir/CallNode.java --- a/src/jdk/nashorn/internal/ir/CallNode.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/CallNode.java Thu Feb 14 13:22:26 2013 +0100 @@ -28,7 +28,6 @@ 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; diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/ir/Node.java --- a/src/jdk/nashorn/internal/ir/Node.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/Node.java Thu Feb 14 13:22:26 2013 +0100 @@ -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; diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/ir/Symbol.java --- a/src/jdk/nashorn/internal/ir/Symbol.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/ir/Symbol.java Thu Feb 14 13:22:26 2013 +0100 @@ -29,7 +29,6 @@ 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; diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/objects/Global.java --- a/src/jdk/nashorn/internal/objects/Global.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/objects/Global.java Thu Feb 14 13:22:26 2013 +0100 @@ -37,6 +37,8 @@ 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.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. diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/objects/NativeBoolean.java --- a/src/jdk/nashorn/internal/objects/NativeBoolean.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/objects/NativeBoolean.java Thu Feb 14 13:22:26 2013 +0100 @@ -30,6 +30,8 @@ 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.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. diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/objects/NativeJSAdapter.java --- a/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/objects/NativeJSAdapter.java Thu Feb 14 13:22:26 2013 +0100 @@ -35,6 +35,9 @@ 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.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 diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/objects/NativeJava.java --- a/src/jdk/nashorn/internal/objects/NativeJava.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/objects/NativeJava.java Thu Feb 14 13:22:26 2013 +0100 @@ -30,6 +30,8 @@ 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.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 diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/objects/NativeJavaImporter.java --- a/src/jdk/nashorn/internal/objects/NativeJavaImporter.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/objects/NativeJavaImporter.java Thu Feb 14 13:22:26 2013 +0100 @@ -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. diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/objects/NativeNumber.java --- a/src/jdk/nashorn/internal/objects/NativeNumber.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/objects/NativeNumber.java Thu Feb 14 13:22:26 2013 +0100 @@ -36,6 +36,8 @@ 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.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. diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/objects/NativeString.java --- a/src/jdk/nashorn/internal/objects/NativeString.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/objects/NativeString.java Thu Feb 14 13:22:26 2013 +0100 @@ -39,6 +39,9 @@ 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.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; /** diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/parser/Lexer.java --- a/src/jdk/nashorn/internal/parser/Lexer.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/parser/Lexer.java Thu Feb 14 13:22:26 2013 +0100 @@ -31,6 +31,7 @@ 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.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; diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/GlobalObject.java --- a/src/jdk/nashorn/internal/runtime/GlobalObject.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/GlobalObject.java Thu Feb 14 13:22:26 2013 +0100 @@ -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. diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/JSType.java --- a/src/jdk/nashorn/internal/runtime/JSType.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/JSType.java Thu Feb 14 13:22:26 2013 +0100 @@ -28,9 +28,9 @@ 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 diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/NativeJavaPackage.java --- a/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java Thu Feb 14 13:22:26 2013 +0100 @@ -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 diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/ScriptFunction.java --- a/src/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/ScriptFunction.java Thu Feb 14 13:22:26 2013 +0100 @@ -33,14 +33,14 @@ 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. diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/ScriptLoader.java --- a/src/jdk/nashorn/internal/runtime/ScriptLoader.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/ScriptLoader.java Thu Feb 14 13:22:26 2013 +0100 @@ -39,6 +39,12 @@ 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 /** diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/ScriptObject.java --- a/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/ScriptObject.java Thu Feb 14 13:22:26 2013 +0100 @@ -55,6 +55,10 @@ 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.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. diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/ScriptRuntime.java --- a/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/ScriptRuntime.java Thu Feb 14 13:22:26 2013 +0100 @@ -38,11 +38,11 @@ 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; /** diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/SetMethodCreator.java --- a/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/SetMethodCreator.java Thu Feb 14 13:22:26 2013 +0100 @@ -29,18 +29,17 @@ 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 { diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/StructureLoader.java --- a/src/jdk/nashorn/internal/runtime/StructureLoader.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/StructureLoader.java Thu Feb 14 13:22:26 2013 +0100 @@ -58,8 +58,6 @@ @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) { diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/Undefined.java --- a/src/jdk/nashorn/internal/runtime/Undefined.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/Undefined.java Thu Feb 14 13:22:26 2013 +0100 @@ -31,10 +31,10 @@ 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. diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/WithObject.java --- a/src/jdk/nashorn/internal/runtime/WithObject.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/WithObject.java Thu Feb 14 13:22:26 2013 +0100 @@ -29,11 +29,11 @@ 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; /** diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/linker/Bootstrap.java --- a/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java Thu Feb 14 13:22:26 2013 +0100 @@ -32,15 +32,15 @@ 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. diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -29,14 +29,14 @@ 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 diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java --- a/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Thu Feb 14 13:22:26 2013 +0100 @@ -70,6 +70,8 @@ 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.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 diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java --- a/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Thu Feb 14 13:22:26 2013 +0100 @@ -33,10 +33,10 @@ 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 diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java --- a/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java Thu Feb 14 13:22:26 2013 +0100 @@ -43,14 +43,14 @@ 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; /** diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -30,13 +30,13 @@ 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 diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java --- a/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Thu Feb 14 13:22:26 2013 +0100 @@ -28,9 +28,9 @@ import java.lang.invoke.MethodType; import java.lang.ref.WeakReference; import java.util.WeakHashMap; -import org.dynalang.dynalink.CallSiteDescriptor; -import org.dynalang.dynalink.support.AbstractCallSiteDescriptor; -import org.dynalang.dynalink.support.CallSiteDescriptorFactory; +import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.support.AbstractCallSiteDescriptor; +import jdk.internal.dynalink.support.CallSiteDescriptorFactory; /** * Nashorn-specific implementation of Dynalink's {@link CallSiteDescriptor}. The reason we have our own subclass is that diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/linker/NashornLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -29,23 +29,22 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; - +import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.linker.ConversionComparator; +import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; +import jdk.internal.dynalink.linker.LinkRequest; +import jdk.internal.dynalink.linker.LinkerServices; +import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.internal.dynalink.support.Guards; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.Undefined; -import org.dynalang.dynalink.CallSiteDescriptor; -import org.dynalang.dynalink.linker.ConversionComparator; -import org.dynalang.dynalink.linker.GuardedInvocation; -import org.dynalang.dynalink.linker.GuardingTypeConverterFactory; -import org.dynalang.dynalink.linker.LinkRequest; -import org.dynalang.dynalink.linker.LinkerServices; -import org.dynalang.dynalink.linker.TypeBasedGuardingDynamicLinker; -import org.dynalang.dynalink.support.Guards; /** * This is the main dynamic linker for Nashorn. It is used for linking all {@link ScriptObject} and its subclasses (this * includes {@link ScriptFunction} and its subclasses) as well as {@link Undefined}. This linker is exported to other - * language runtimes by being declared in {@code META-INF/services/org.dynalang.dynalink.linker.GuardingDynamicLinker} + * language runtimes by being declared in {@code META-INF/services/jdk.internal.dynalink.linker.GuardingDynamicLinker} * file of Nashorn's distribution. */ public class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory, ConversionComparator { diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -29,16 +29,16 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; +import jdk.internal.dynalink.linker.ConversionComparator; +import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; +import jdk.internal.dynalink.linker.LinkRequest; +import jdk.internal.dynalink.linker.LinkerServices; +import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.internal.dynalink.support.TypeUtilities; import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.GlobalObject; -import org.dynalang.dynalink.linker.ConversionComparator; -import org.dynalang.dynalink.linker.GuardedInvocation; -import org.dynalang.dynalink.linker.GuardingTypeConverterFactory; -import org.dynalang.dynalink.linker.LinkRequest; -import org.dynalang.dynalink.linker.LinkerServices; -import org.dynalang.dynalink.linker.TypeBasedGuardingDynamicLinker; -import org.dynalang.dynalink.support.TypeUtilities; /** * Internal linker for String, Boolean, and Number objects, only ever used by Nashorn engine and not exposed to other @@ -90,7 +90,7 @@ * @param sourceType the source type to convert from * @param targetType1 one candidate target type * @param targetType2 another candidate target type - * @return one of {@link org.dynalang.dynalink.linker.ConversionComparator.Comparison} values signifying which + * @return one of {@link jdk.internal.dynalink.linker.ConversionComparator.Comparison} values signifying which * target type should be favored for conversion. */ @Override diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java --- a/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Thu Feb 14 13:22:26 2013 +0100 @@ -25,16 +25,16 @@ package jdk.nashorn.internal.runtime.linker; +import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.beans.BeansLinker; +import jdk.internal.dynalink.beans.StaticClass; +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.Guards; import jdk.nashorn.internal.runtime.ECMAErrors; -import org.dynalang.dynalink.CallSiteDescriptor; -import org.dynalang.dynalink.beans.BeansLinker; -import org.dynalang.dynalink.beans.StaticClass; -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.linker.TypeBasedGuardingDynamicLinker; -import org.dynalang.dynalink.support.Guards; /** * Internal linker for {@link StaticClass} objects, only ever used by Nashorn engine and not exposed to other engines. diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java --- a/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Thu Feb 14 13:22:26 2013 +0100 @@ -29,12 +29,12 @@ import java.lang.invoke.MethodHandle; 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.support.CallSiteDescriptorFactory; +import jdk.internal.dynalink.support.Guards; import jdk.nashorn.internal.runtime.ScriptObject; -import org.dynalang.dynalink.CallSiteDescriptor; -import org.dynalang.dynalink.linker.GuardedInvocation; -import org.dynalang.dynalink.linker.LinkRequest; -import org.dynalang.dynalink.support.CallSiteDescriptorFactory; -import org.dynalang.dynalink.support.Guards; /** * Implements lookup of methods to link for dynamic operations on JavaScript primitive values (booleans, strings, and diff -r 43e32b36153c -r 5a820fb11814 src/jdk/nashorn/internal/runtime/options/Options.java --- a/src/jdk/nashorn/internal/runtime/options/Options.java Thu Feb 14 13:01:52 2013 +0100 +++ b/src/jdk/nashorn/internal/runtime/options/Options.java Thu Feb 14 13:22:26 2013 +0100 @@ -44,7 +44,6 @@ import java.util.TimeZone; import java.util.TreeMap; import java.util.TreeSet; - import jdk.nashorn.internal.runtime.Logging; import jdk.nashorn.internal.runtime.QuotedStringTokenizer; diff -r 43e32b36153c -r 5a820fb11814 test/script/sandbox/nashorninternals.js --- a/test/script/sandbox/nashorninternals.js Thu Feb 14 13:01:52 2013 +0100 +++ b/test/script/sandbox/nashorninternals.js Thu Feb 14 13:22:26 2013 +0100 @@ -55,3 +55,7 @@ checkClass("jdk.nashorn.internal.parser.JSONParser"); checkClass("jdk.nashorn.internal.parser.Lexer"); checkClass("jdk.nashorn.internal.parser.Scanner"); +checkClass("jdk.internal.dynalink.CallSiteDescriptor"); +checkClass("jdk.internal.dynalink.beans.StaticClass"); +checkClass("jdk.internal.dynalink.linker.LinkRequest"); +checkClass("jdk.internal.dynalink.support.AbstractRelinkableCallSite"); diff -r 43e32b36153c -r 5a820fb11814 test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java --- a/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Thu Feb 14 13:01:52 2013 +0100 +++ b/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java Thu Feb 14 13:22:26 2013 +0100 @@ -26,8 +26,8 @@ package jdk.nashorn.api.scripting; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; diff -r 43e32b36153c -r 5a820fb11814 test/src/jdk/nashorn/internal/runtime/ContextTest.java --- a/test/src/jdk/nashorn/internal/runtime/ContextTest.java Thu Feb 14 13:01:52 2013 +0100 +++ b/test/src/jdk/nashorn/internal/runtime/ContextTest.java Thu Feb 14 13:22:26 2013 +0100 @@ -35,7 +35,6 @@ import javax.script.ScriptEngineManager; import javax.script.ScriptException; import jdk.nashorn.api.scripting.NashornScriptEngineFactory; -import jdk.nashorn.api.scripting.ScriptEngineTest; import jdk.nashorn.internal.runtime.options.Options; import org.testng.annotations.Test; diff -r 43e32b36153c -r 5a820fb11814 test/src/jdk/nashorn/internal/runtime/JSTypeTest.java --- a/test/src/jdk/nashorn/internal/runtime/JSTypeTest.java Thu Feb 14 13:01:52 2013 +0100 +++ b/test/src/jdk/nashorn/internal/runtime/JSTypeTest.java Thu Feb 14 13:22:26 2013 +0100 @@ -26,8 +26,8 @@ package jdk.nashorn.internal.runtime; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; -import static org.testng.Assert.assertFalse; import org.testng.annotations.Test;