# HG changeset patch # User lana # Date 1445537559 25200 # Node ID 1c5439fcdc265aa1ad9a6b29fbad07c9563e46bd # Parent 15a50c5e06685c8fd38745b984b47bfe50aefcdb# Parent ef8c859f7992f5a2ad6b45bff2b7aafe79bcb9e3 Merge diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PackagesHelper.java --- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PackagesHelper.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/PackagesHelper.java Thu Oct 22 11:12:39 2015 -0700 @@ -51,7 +51,11 @@ */ final class PackagesHelper { // JavaCompiler may be null on certain platforms (eg. JRE) - private static final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + private static final JavaCompiler compiler; + static { + // Use javac only if security manager is not around! + compiler = System.getSecurityManager() == null? ToolProvider.getSystemJavaCompiler() : null; + } /** * Is Java package properties helper available? diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CallSiteDescriptor.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CallSiteDescriptor.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CallSiteDescriptor.java Thu Oct 22 11:12:39 2015 -0700 @@ -83,92 +83,205 @@ package jdk.internal.dynalink; +import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; -import jdk.internal.dynalink.support.CallSiteDescriptorFactory; +import java.util.Objects; /** - * 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. + * Call site descriptors contain all the information necessary for linking a + * call site. This information is normally passed as parameters to bootstrap + * methods and consists of the {@code MethodHandles.Lookup} object on the caller + * class in which the call site occurs, the dynamic operation at the call + * site, and the method type of the call site. {@code CallSiteDescriptor} + * objects are used in Dynalink to capture and store these parameters for + * subsequent use by the {@link DynamicLinker}. + *

+ * The constructors of built-in {@link RelinkableCallSite} implementations all + * take a call site descriptor. + *

+ * Call site descriptors must be immutable. You can use this class as-is or you + * can subclass it, especially if you need to add further information to the + * descriptors (typically, values passed in additional parameters to the + * bootstrap method. Since the descriptors must be immutable, you can set up a + * cache for equivalent descriptors to have the call sites share them. */ -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; +public class CallSiteDescriptor { + private final MethodHandles.Lookup lookup; + private final Operation operation; + private final MethodType methodType; /** - * Character used to delimit tokens in an call site name. + * The name of a runtime permission to invoke the {@link #getLookup()} + * method. */ - public static final String TOKEN_DELIMITER = ":"; + public static final String GET_LOOKUP_PERMISSION_NAME = "dynalink.getLookup"; - /** - * Character used to delimit operation names in a composite operation specification. - */ - public static final String OPERATOR_DELIMITER = "|"; + private static final RuntimePermission GET_LOOKUP_PERMISSION = new RuntimePermission(GET_LOOKUP_PERMISSION_NAME); /** - * 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. + * Creates a new call site descriptor. + * @param lookup the lookup object describing the class the call site belongs to. + * @param operation the dynamic operation at the call site. + * @param methodType the method type of the call site. */ - public int getNameTokenCount(); + public CallSiteDescriptor(final Lookup lookup, final Operation operation, final MethodType methodType) { + this.lookup = Objects.requireNonNull(lookup, "lookup"); + this.operation = Objects.requireNonNull(operation, "name"); + this.methodType = Objects.requireNonNull(methodType, "methodType"); + } /** - * 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. + * Returns the operation at the call site. + * @return the operation at the call site. */ - 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(); + public final Operation getOperation() { + return operation; + } /** * The type of the method at the call site. * * @return type of the method at the call site. */ - public MethodType getMethodType(); + public final MethodType getMethodType() { + return methodType; + } + + /** + * Returns the lookup that should be used to find method handles to set as + * targets of the call site described by this descriptor. When creating + * descriptors from a {@link java.lang.invoke} bootstrap method, it should + * be the lookup passed to the bootstrap. + * @return the lookup that should be used to find method handles to set as + * targets of the call site described by this descriptor. + * @throws SecurityException if the lookup isn't the + * {@link MethodHandles#publicLookup()} and a security manager is present, + * and a check for {@code RuntimePermission("dynalink.getLookup")} fails. + */ + public final Lookup getLookup() { + final SecurityManager sm = System.getSecurityManager(); + if (sm != null && lookup != MethodHandles.publicLookup()) { + sm.checkPermission(GET_LOOKUP_PERMISSION); + } + return lookup; + } /** - * Returns the lookup passed to the bootstrap method. If the lookup isn't the public lookup, the - * implementation must check the {@code RuntimePermission("dynalink.getLookup")} permission if a security - * manager is present. - * @return the lookup passed to the bootstrap method. + * Returns the value of {@link #getLookup()} without a security check. Can + * be used by subclasses to access the lookup quickly. + * @return same as returned value of {@link #getLookup()}. */ - public Lookup getLookup(); + protected final Lookup getLookupPrivileged() { + return lookup; + } /** - * Creates a new call site descriptor from this descriptor, which is identical to this, except it changes the method - * type. + * Creates a new call site descriptor from this descriptor, which is + * identical to this, except it changes the method type. Invokes + * {@link #changeMethodTypeInternal(MethodType)} and checks that it returns + * a descriptor of the same class as this descriptor. + * + * @param newMethodType the new method type + * @return a new call site descriptor, with the method type changed. + * @throws RuntimeException if {@link #changeMethodTypeInternal(MethodType)} + * returned a descriptor of different class than this object. + * @throws NullPointerException if {@link #changeMethodTypeInternal(MethodType)} + * returned null. + */ + public final CallSiteDescriptor changeMethodType(final MethodType newMethodType) { + final CallSiteDescriptor changed = Objects.requireNonNull( + changeMethodTypeInternal(newMethodType), + "changeMethodTypeInternal() must not return null."); + + if (getClass() != changed.getClass()) { + throw new RuntimeException( + "changeMethodTypeInternal() must return an object of the same class it is invoked on."); + } + + return changed; + } + + /** + * Creates a new call site descriptor from this descriptor, which is + * identical to this, except it changes the method type. Subclasses must + * override this method to return an object of their exact class. * * @param newMethodType the new method type * @return a new call site descriptor, with the method type changed. */ - public CallSiteDescriptor changeMethodType(MethodType newMethodType); + protected CallSiteDescriptor changeMethodTypeInternal(final MethodType newMethodType) { + return new CallSiteDescriptor(lookup, operation, newMethodType); + } + + /** + * Returns true if this call site descriptor is equal to the passed object. + * It is considered equal if the other object is of the exact same class, + * their operations and method types are equal, and their lookups have the + * same {@link java.lang.invoke.MethodHandles.Lookup#lookupClass()} and + * {@link java.lang.invoke.MethodHandles.Lookup#lookupModes()}. + */ + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } else if (obj == null) { + return false; + } else if (obj.getClass() != getClass()) { + return false; + } + final CallSiteDescriptor other = (CallSiteDescriptor)obj; + return operation.equals(other.operation) && + methodType.equals(other.methodType) && + lookupsEqual(lookup, other.lookup); + } + /** + * Compares two lookup objects for value-based equality. They are considered + * equal if they have the same + * {@link java.lang.invoke.MethodHandles.Lookup#lookupClass()} and + * {@link java.lang.invoke.MethodHandles.Lookup#lookupModes()}. + * @param l1 first lookup + * @param l2 second lookup + * @return true if the two lookups are equal, false otherwise. + */ + private static boolean lookupsEqual(final Lookup l1, final Lookup l2) { + return l1.lookupClass() == l2.lookupClass() && l1.lookupModes() == l2.lookupModes(); + } + + /** + * Returns a value-based hash code of this call site descriptor computed + * from its operation, method type, and lookup object's lookup class and + * lookup modes. + * @return value-based hash code for this call site descriptor. + */ + @Override + public int hashCode() { + return operation.hashCode() + 31 * methodType.hashCode() + 31 * 31 * lookupHashCode(lookup); + } + + /** + * Returns a value-based hash code for the passed lookup object. It is + * based on the lookup object's + * {@link java.lang.invoke.MethodHandles.Lookup#lookupClass()} and + * {@link java.lang.invoke.MethodHandles.Lookup#lookupModes()} values. + * @param lookup the lookup object. + * @return a hash code for the object.. + */ + private static int lookupHashCode(final Lookup lookup) { + return lookup.lookupClass().hashCode() + 31 * lookup.lookupModes(); + } + + /** + * Returns the string representation of this call site descriptor, of the + * format {@code name(parameterTypes)returnType@lookup}. + */ + @Override + public String toString() { + final String mt = methodType.toString(); + final String l = lookup.toString(); + final String o = operation.toString(); + final StringBuilder b = new StringBuilder(o.length() + mt.length() + 1 + l.length()); + return b.append(o).append(mt).append('@').append(l).toString(); + } } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ChainedCallSite.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ChainedCallSite.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,228 +0,0 @@ -/* - * 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.util.Arrays; -import java.util.Iterator; -import java.util.LinkedList; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.support.AbstractRelinkableCallSite; -import jdk.internal.dynalink.support.Lookup; - -/** - * 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 static final MethodHandle PRUNE_CATCHES; - private static final MethodHandle PRUNE_SWITCHPOINTS; - static { - final MethodHandle PRUNE = Lookup.findOwnSpecial(MethodHandles.lookup(), "prune", MethodHandle.class, - MethodHandle.class, boolean.class); - PRUNE_CATCHES = MethodHandles.insertArguments(PRUNE, 2, true); - PRUNE_SWITCHPOINTS = MethodHandles.insertArguments(PRUNE, 2, false); - } - - /** - * Contains the invocations currently linked into this call site's target. They are used when we are - * relinking to rebuild the guardWithTest chain. Valid values for this field are: {@code null} if there's - * no linked invocations, or an instance of {@link GuardedInvocation} if there is exactly one previous - * invocation, or an instance of {@code GuardedInvocation[]} if there is more than one previous - * invocation. - */ - private Object invocations; - - /** - * Creates a new chained call site. - * @param descriptor the descriptor for the call site. - */ - public ChainedCallSite(final 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. - */ - protected int getMaxChainLength() { - return 8; - } - - @Override - public void relink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) { - relinkInternal(guardedInvocation, fallback, false, false); - } - - @Override - public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle fallback) { - relinkInternal(guardedInvocation, fallback, true, false); - } - - private MethodHandle relinkInternal(final GuardedInvocation invocation, final MethodHandle relink, final boolean reset, final boolean removeCatches) { - final Object currentInvocations = invocations; - final LinkedList newInvocations; - if (currentInvocations == null || reset) { - newInvocations = new LinkedList<>(); - } else if (currentInvocations instanceof GuardedInvocation) { - newInvocations = new LinkedList<>(); - newInvocations.add((GuardedInvocation)currentInvocations); - } else if (currentInvocations instanceof GuardedInvocation[]) { - newInvocations = new LinkedList<>(Arrays.asList(((GuardedInvocation[])currentInvocations))); - } else { - throw new AssertionError(); - } - - // First, prune the chain of invalidated switchpoints, we always do this - // We also remove any catches if the remove catches flag is set - for(final Iterator it = newInvocations.iterator(); it.hasNext();) { - final GuardedInvocation inv = it.next(); - if(inv.hasBeenInvalidated() || (removeCatches && inv.getException() != null)) { - 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 pruneAndInvokeSwitchPoints = makePruneAndInvokeMethod(relink, PRUNE_SWITCHPOINTS); - final MethodHandle pruneAndInvokeCatches = makePruneAndInvokeMethod(relink, PRUNE_CATCHES); - - // Fold the new chain - MethodHandle target = relink; - for(final GuardedInvocation inv: newInvocations) { - target = inv.compose(target, pruneAndInvokeSwitchPoints, pruneAndInvokeCatches); - } - - switch (newInvocations.size()) { - case 0: - invocations = null; - break; - case 1: - invocations = newInvocations.getFirst(); - break; - default: - invocations = newInvocations.toArray(new GuardedInvocation[newInvocations.size()]); - } - 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(final MethodHandle relink, final MethodHandle prune) { - // 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(final MethodHandle relink, final boolean catches) { - return relinkInternal(null, relink, false, catches); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ClassMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ClassMap.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,183 @@ +/* + * 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.ref.Reference; +import java.lang.ref.SoftReference; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import jdk.internal.dynalink.internal.AccessControlContextFactory; +import jdk.internal.dynalink.internal.InternalTypeUtilities; + +/** + * 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. + * + * @param the type of the values in the map + */ +abstract class ClassMap { + private static final AccessControlContext GET_CLASS_LOADER_CONTEXT = + AccessControlContextFactory.createAccessControlContext("getClassLoader"); + + 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. + */ + ClassMap(final 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. + */ + abstract T computeValue(Class clazz); + + /** + * Returns the value associated with the class + * + * @param clazz the class + * @return the value associated with the class + */ + T get(final 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; + + final Boolean canReferenceDirectly = AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Boolean run() { + return InternalTypeUtilities.canReferenceDirectly(classLoader, clazz.getClassLoader()); + } + }, GET_CLASS_LOADER_CONTEXT); + + // If allowed to strongly reference, put it in the fast map + if(canReferenceDirectly) { + 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 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CompositeOperation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CompositeOperation.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2015, 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 2015 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.util.Arrays; +import java.util.Objects; + +/** + * Describes an operation that is composed of at least two other operations. The + * component operations are treated as alternatives to each other in order of + * preference. The semantics of the composite operation is "first successful". + * That is, a composite of {@code GET_PROPERTY|GET_ELEMENT:color} should be + * interpreted as get the property named "color" on the object, but if the + * property does not exist, then get the collection element named "color" + * instead. + *

+ * Composite operations are helpful in implementation of languages that + * don't distinguish between one or more of the property, method, and element + * namespaces, or when expressing operations against objects that can be + * considered both ordinary objects and collections, e.g. Java + * {@link java.util.Map} objects. A composite operation + * {@code GET_PROPERTY|GET_ELEMENT:empty} against a Java map will always match + * the {@link java.util.Map#isEmpty()} property, but + * {@code GET_ELEMENT|GET_PROPERTY:empty} will actually match a map element with + * key {@code "empty"} if the map contains that key, and only fall back to the + * {@code isEmpty()} property getter if the map does not contain the key. If + * the source language mandates this semantics, it can be easily achieved using + * composite operations. + *

+ * Even if the language itself doesn't distinguish between some of the + * namespaces, it can be helpful to map different syntaxes to different + * compositions. E.g. the source expression {@code obj.color} could map to + * {@code GET_PROPERTY|GET_ELEMENT|GET_METHOD:color}, but a different source + * expression that looks like collection element access {@code obj[key]} could + * be expressed instead as {@code GET_ELEMENT|GET_PROPERTY|GET_METHOD}. + * Finally, if the retrieved value is subsequently called, then it makes sense + * to bring {@code GET_METHOD} to the front of the list: the getter part of the + * source expression {@code obj.color()} should be + * {@code GET_METHOD|GET_PROPERTY|GET_ELEMENT:color} and the one for + * {@code obj[key]()} should be {@code GET_METHOD|GET_ELEMENT|GET_PROPERTY}. + *

+ * The elements of a composite operation can not be composites or named + * operations, but rather simple operations such are elements of + * {@link StandardOperation}. A composite operation itself can serve as the base + * operation of a named operation, though; a typical way to construct e.g. the + * {@code GET_ELEMENT|GET_PROPERTY:empty} from above would be: + *

+ * Operation getElementOrPropertyEmpty = new NamedOperation(
+ *     new CompositeOperation(
+ *         StandardOperation.GET_ELEMENT,
+ *         StandardOperation.GET_PROPERTY),
+ *     "empty");
+ * 
+ *

+ * Not all compositions make sense. Typically, any combination in any order of + * standard getter operations {@code GET_PROPERTY}, {@code GET_ELEMENT}, and + * {@code GET_METHOD} make sense, as do combinations of {@code SET_PROPERTY} and + * {@code SET_ELEMENT}; other standard operations should not be combined. The + * constructor will allow any combination of operations, though. + */ +public class CompositeOperation implements Operation { + private final Operation[] operations; + + /** + * Constructs a new composite operation. + * @param operations the components for this composite operation. The passed + * array will be cloned. + * @throws IllegalArgumentException if less than two components are + * specified, or any component is itself a {@link CompositeOperation} or a + * {@link NamedOperation}. + * @throws NullPointerException if either the operations array or any of its + * elements are {@code null}. + */ + public CompositeOperation(final Operation... operations) { + Objects.requireNonNull(operations, "operations array is null"); + if (operations.length < 2) { + throw new IllegalArgumentException("Must have at least two operations"); + } + final Operation[] clonedOps = operations.clone(); + for(int i = 0; i < clonedOps.length; ++i) { + final Operation op = clonedOps[i]; + if (op == null) { + throw new NullPointerException("operations[" + i + "] is null"); + } else if (op instanceof NamedOperation) { + throw new IllegalArgumentException("operations[" + i + "] is a NamedOperation"); + } else if (op instanceof CompositeOperation) { + throw new IllegalArgumentException("operations[" + i + "] is a CompositeOperation"); + } + } + this.operations = clonedOps; + } + + /** + * Returns the component operations in this composite operation. The + * returned array is a copy and changes to it don't have effect on this + * object. + * @return the component operations in this composite operation. + */ + public Operation[] getOperations() { + return operations.clone(); + } + + /** + * Returns the number of component operations in this composite operation. + * @return the number of component operations in this composite operation. + */ + public int getOperationCount() { + return operations.length; + } + + /** + * Returns the i-th component operation in this composite operation. + * @param i the operation index + * @return the i-th component operation in this composite operation. + * @throws IndexOutOfBoundsException if the index is out of range. + */ + public Operation getOperation(final int i) { + try { + return operations[i]; + } catch (final ArrayIndexOutOfBoundsException e) { + throw new IndexOutOfBoundsException(Integer.toString(i)); + } + } + + /** + * Returns true if this composite operation contains an operation equal to + * the specified operation. + * @param operation the operation being searched for. Must not be null. + * @return true if the if this composite operation contains an operation + * equal to the specified operation. + */ + public boolean contains(final Operation operation) { + Objects.requireNonNull(operation); + for(final Operation component: operations) { + if (component.equals(operation)) { + return true; + } + } + return false; + } + + /** + * Returns true if the other object is also a composite operation and their + * component operations are equal. + * @param obj the object to compare to + * @return true if this object is equal to the other one, false otherwise. + */ + @Override + public boolean equals(final Object obj) { + if (obj == null || obj.getClass() != CompositeOperation.class) { + return false; + } + return Arrays.equals(operations, ((CompositeOperation)obj).operations); + } + + /** + * Returns the hash code of this composite operation. Defined to be equal + * to {@code java.util.Arrays.hashCode(operations)}. + */ + @Override + public int hashCode() { + return Arrays.hashCode(operations); + }; + + /** + * Returns the string representation of this composite operation. Defined to + * be the {@code toString} of its component operations, each separated by + * the vertical line character (e.g. {@code "GET_PROPERTY|GET_ELEMENT"}). + * @return the string representation of this composite operation. + */ + @Override + public String toString() { + final StringBuilder b = new StringBuilder(); + b.append(operations[0]); + for(int i = 1; i < operations.length; ++i) { + b.append('|').append(operations[i]); + } + return b.toString(); + } + + /** + * Returns the components of the passed operation if it is a composite + * operation, otherwise returns an array containing the operation itself. + * This allows for returning an array of component even if it is not known + * whether the operation is itself a composite (treating a non-composite + * operation as if it were a single-element composite of itself). + * @param op the operation whose components are retrieved. + * @return if the passed operation is a composite operation, returns its + * {@link #getOperations()}, otherwise returns the operation itself. + */ + public static Operation[] getOperations(final Operation op) { + return op instanceof CompositeOperation + ? ((CompositeOperation)op).operations.clone() + : new Operation[] { op }; + } + + /** + * Returns true if the specified potentially composite operation is a + * {@link CompositeOperation} and contains an operation equal to the + * specified operation. If {@code composite} is not a + * {@link CompositeOperation}, then the two operations are compared for + * equality. + * @param composite the potentially composite operation. Must not be null. + * @param operation the operation being searched for. Must not be null. + * @return true if the if the passed operation is a + * {@link CompositeOperation} and contains a component operation equal to + * the specified operation, or if it is not a {@link CompositeOperation} and + * is equal to {@code operation}. + */ + public static boolean contains(final Operation composite, final Operation operation) { + if (composite instanceof CompositeOperation) { + return ((CompositeOperation)composite).contains(operation); + } + return composite.equals(Objects.requireNonNull(operation)); + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DefaultBootstrapper.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DefaultBootstrapper.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,141 +0,0 @@ -/* - * 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. - */ -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(final MethodHandles.Lookup caller, final String name, final 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(final MethodHandles.Lookup caller, final String name, final MethodType type) { - return bootstrapInternal(MethodHandles.publicLookup(), name, type); - } - - private static CallSite bootstrapInternal(final MethodHandles.Lookup caller, final String name, final MethodType type) { - return dynamicLinker.link(new MonomorphicCallSite(CallSiteDescriptorFactory.create(caller, name, type))); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinker.java Thu Oct 22 11:12:39 2015 -0700 @@ -87,26 +87,31 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.MutableCallSite; -import java.util.List; import java.util.Objects; import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.internal.dynalink.linker.GuardedInvocationTransformer; 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; +import jdk.internal.dynalink.linker.support.Lookup; +import jdk.internal.dynalink.linker.support.SimpleLinkRequest; +import jdk.internal.dynalink.support.ChainedCallSite; +import jdk.internal.dynalink.support.SimpleRelinkableCallSite; /** - * 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: + * The linker for {@link RelinkableCallSite} objects. A dynamic linker is a main + * objects when using Dynalink, it coordinates linking of call sites with + * linkers of available language runtimes that are represented by + * {@link GuardingDynamicLinker} objects (you only need to deal with these if + * you are yourself implementing a language runtime with its own object model + * and/or type conversions). To use Dynalink, you have to create one or more + * dynamic linkers using a {@link DynamicLinkerFactory}. Subsequently, you need + * to invoke its {@link #link(RelinkableCallSite)} method from + * {@code invokedynamic} bootstrap methods to let it manage all the call sites + * they create. Usual usage would be to create at least 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();
@@ -118,33 +123,44 @@
  *     }
  *
  *     public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {
- *         return dynamicLinker.link(new MonomorphicCallSite(CallSiteDescriptorFactory.create(lookup, name, type)));
+ *         return dynamicLinker.link(
+ *             new SimpleRelinkableCallSite(
+ *                 new CallSiteDescriptor(lookup, parseOperation(name), type)));
+ *     }
+ *
+ *     private static Operation parseOperation(String name) {
+ *         ...
  *     }
  * }
  * 
- * - * Note how there are three components you will need to provide here: + * The above setup of one static linker instance is often too simple. You will + * often have your language runtime have a concept of some kind of + * "context class loader" and you will want to create one dynamic linker per + * such class loader, to ensure it incorporates linkers for all other language + * runtimes visible to that class loader (see + * {@link DynamicLinkerFactory#setClassLoader(ClassLoader)}). + *

+ * There are three components you need to provide in the above example: *

*/ @@ -157,8 +173,7 @@ private static final String INVOKE_PACKAGE_PREFIX = "java.lang.invoke."; private final LinkerServices linkerServices; - private final GuardedInvocationFilter prelinkFilter; - private final int runtimeContextArgCount; + private final GuardedInvocationTransformer prelinkTransformer; private final boolean syncOnRelink; private final int unstableRelinkThreshold; @@ -166,20 +181,17 @@ * Creates a new dynamic linker. * * @param linkerServices the linkerServices used by the linker, created by the factory. - * @param prelinkFilter see {@link DynamicLinkerFactory#setPrelinkFilter(GuardedInvocationFilter)} - * @param runtimeContextArgCount see {@link DynamicLinkerFactory#setRuntimeContextArgCount(int)} + * @param prelinkTransformer see {@link DynamicLinkerFactory#setPrelinkTransformer(GuardedInvocationTransformer)} + * @param syncOnRelink see {@link DynamicLinkerFactory#setSyncOnRelink(boolean)} + * @param unstableRelinkThreshold see {@link DynamicLinkerFactory#setUnstableRelinkThreshold(int)} */ - DynamicLinker(final LinkerServices linkerServices, final GuardedInvocationFilter prelinkFilter, final int runtimeContextArgCount, + DynamicLinker(final LinkerServices linkerServices, final GuardedInvocationTransformer prelinkTransformer, final boolean syncOnRelink, final int unstableRelinkThreshold) { - if(runtimeContextArgCount < 0) { - throw new IllegalArgumentException("runtimeContextArgCount < 0"); - } if(unstableRelinkThreshold < 0) { throw new IllegalArgumentException("unstableRelinkThreshold < 0"); } this.linkerServices = linkerServices; - this.prelinkFilter = prelinkFilter; - this.runtimeContextArgCount = runtimeContextArgCount; + this.prelinkTransformer = prelinkTransformer; this.syncOnRelink = syncOnRelink; this.unstableRelinkThreshold = unstableRelinkThreshold; } @@ -202,12 +214,13 @@ } /** - * 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. + * Returns the object representing the linker services of this class that + * are normally exposed to individual {@link GuardingDynamicLinker + * 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. */ @@ -244,10 +257,7 @@ final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor(); final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0; final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold; - final LinkRequest linkRequest = - runtimeContextArgCount == 0 ? - new LinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments) : - new RuntimeContextLinkRequestImpl(callSiteDescriptor, callSite, relinkCount, callSiteUnstable, arguments, runtimeContextArgCount); + final LinkRequest linkRequest = new SimpleLinkRequest(callSiteDescriptor, callSiteUnstable, arguments); GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest); @@ -256,21 +266,9 @@ 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); - } - } - - // Make sure we filter the invocation before linking it into the call site. This is typically used to match the + // Make sure we transform the invocation before linking it into the call site. This is typically used to match the // return type of the invocation to the call site. - guardedInvocation = prelinkFilter.filter(guardedInvocation, linkRequest, linkerServices); + guardedInvocation = prelinkTransformer.filter(guardedInvocation, linkRequest, linkerServices); Objects.requireNonNull(guardedInvocation); int newRelinkCount = relinkCount; @@ -290,11 +288,12 @@ } /** - * Returns a stack trace element describing the location of the call site - * currently being linked 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. + * Returns a stack trace element describing the location of the + * {@code invokedynamic} call site currently being linked on the current + * thread. The operation is potentially expensive as it needs to generate a + * stack trace to inspect it and is intended for use in diagnostics code. + * For "free-floating" call sites (not associated with an + * {@code invokedynamic} instruction), the result is not well-defined. * * @return a stack trace element describing the location of the call site * currently being linked, or null if it is not invoked while a call diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinkerFactory.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinkerFactory.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/DynamicLinkerFactory.java Thu Oct 22 11:12:39 2015 -0700 @@ -83,43 +83,59 @@ package jdk.internal.dynalink; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; import java.lang.invoke.MutableCallSite; +import java.security.AccessControlContext; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Objects; +import java.util.ServiceConfigurationError; +import java.util.ServiceLoader; import java.util.Set; +import java.util.function.Supplier; import jdk.internal.dynalink.beans.BeansLinker; +import jdk.internal.dynalink.internal.AccessControlContextFactory; +import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.internal.dynalink.linker.GuardedInvocationTransformer; import jdk.internal.dynalink.linker.GuardingDynamicLinker; +import jdk.internal.dynalink.linker.GuardingDynamicLinkerExporter; import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; import jdk.internal.dynalink.linker.LinkRequest; import jdk.internal.dynalink.linker.LinkerServices; import jdk.internal.dynalink.linker.MethodHandleTransformer; import jdk.internal.dynalink.linker.MethodTypeConversionStrategy; -import jdk.internal.dynalink.support.AutoDiscovery; -import jdk.internal.dynalink.support.BottomGuardingDynamicLinker; -import jdk.internal.dynalink.support.ClassLoaderGetterContextProvider; -import jdk.internal.dynalink.support.CompositeGuardingDynamicLinker; -import jdk.internal.dynalink.support.CompositeTypeBasedGuardingDynamicLinker; -import jdk.internal.dynalink.support.DefaultPrelinkFilter; -import jdk.internal.dynalink.support.LinkerServicesImpl; -import jdk.internal.dynalink.support.TypeConverterFactory; -import jdk.internal.dynalink.support.TypeUtilities; +import jdk.internal.dynalink.linker.support.CompositeGuardingDynamicLinker; +import jdk.internal.dynalink.linker.support.CompositeTypeBasedGuardingDynamicLinker; +import jdk.internal.dynalink.linker.support.DefaultInternalObjectFilter; +import jdk.internal.dynalink.linker.support.TypeUtilities; /** - * A factory class for creating {@link DynamicLinker}s. The usual dynamic linker is a linker composed 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} and a {@link DefaultPrelinkFilter}. See {@link DynamicLinker} documentation for tips on - * how to use this class. + * A factory class for creating {@link DynamicLinker} objects. Dynamic linkers + * are the central objects in Dynalink; these are composed of several + * {@link GuardingDynamicLinker} objects and coordinate linking of call sites + * with them. The usual dynamic linker is a linker + * composed of all {@link GuardingDynamicLinker} objects explicitly pre-created + * by the user of the factory and configured with + * {@link #setPrioritizedLinkers(List)}, as well as any + * {@link #setClassLoader(ClassLoader) automatically discovered} ones, and + * finally the ones configured with {@link #setFallbackLinkers(List)}; this last + * category usually includes {@link BeansLinker}. */ public final class DynamicLinkerFactory { + private static final AccessControlContext GET_CLASS_LOADER_CONTEXT = + AccessControlContextFactory.createAccessControlContext("getClassLoader"); + /** - * Default value for {@link #setUnstableRelinkThreshold(int) unstable relink threshold}. + * Default value for {@link #setUnstableRelinkThreshold(int) unstable relink + * threshold}. */ public static final int DEFAULT_UNSTABLE_RELINK_THRESHOLD = 8; @@ -128,18 +144,40 @@ private List prioritizedLinkers; private List fallbackLinkers; - private int runtimeContextArgCount = 0; private boolean syncOnRelink = false; private int unstableRelinkThreshold = DEFAULT_UNSTABLE_RELINK_THRESHOLD; - private GuardedInvocationFilter prelinkFilter; + private GuardedInvocationTransformer prelinkTransformer; private MethodTypeConversionStrategy autoConversionStrategy; private MethodHandleTransformer internalObjectsFilter; + private List autoLoadingErrors = Collections.emptyList(); + /** - * Sets the class loader for automatic discovery of available linkers. If not set explicitly, then the thread - * context class loader at the time of {@link #createLinker()} invocation will be used. + * Creates a new dynamic linker factory with default configuration. Upon + * creation, the factory can be configured using various {@code setXxx()} + * methods and used to create one or more dynamic linkers according to its + * current configuration using {@link #createLinker()}. + */ + public DynamicLinkerFactory() { + } + + /** + * Sets the class loader for automatic discovery of available guarding + * dynamic linkers. {@link GuardingDynamicLinkerExporter} implementations + * available through this class loader will be automatically instantiated + * using the {@link ServiceLoader} mechanism and the linkers they provide + * will be incorporated into {@code DynamicLinker}s that this factory + * creates. This allows for cross-language interoperability where call sites + * belonging to this language runtime can be linked by linkers from these + * automatically discovered runtimes if their native objects are passed to + * this runtime. If class loader is not set explicitly by invoking this + * method, then the thread context class loader of the thread invoking + * {@link #createLinker()} will be used. If this method is invoked + * explicitly with null then {@link ServiceLoader#loadInstalled(Class)} will + * be used to load the linkers. * - * @param classLoader the class loader used for the autodiscovery of available linkers. + * @param classLoader the class loader used for the automatic discovery of + * available linkers. */ public void setClassLoader(final ClassLoader classLoader) { this.classLoader = classLoader; @@ -147,90 +185,84 @@ } /** - * 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. + * Sets the prioritized guarding dynamic linkers. Language runtimes using + * Dynalink will usually have at least one linker for their own language. + * These linkers will be consulted first by the resulting dynamic linker + * when it is linking call sites, before any autodiscovered and fallback + * linkers. If the factory also autodiscovers a linker class matching one + * of the prioritized linkers, the autodiscovered class 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). + * @param prioritizedLinkers the list of prioritized linkers. Can be null. + * @throws NullPointerException if any of the list elements are null. */ public void setPrioritizedLinkers(final List prioritizedLinkers) { - this.prioritizedLinkers = - prioritizedLinkers == null ? null : new ArrayList<>(prioritizedLinkers); + this.prioritizedLinkers = copyListRequireNonNullElements(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. + * Sets the prioritized guarding dynamic linkers. Identical to calling + * {@link #setPrioritizedLinkers(List)} with + * {@code Arrays.asList(prioritizedLinkers)}. * - * @param prioritizedLinkers a list of prioritized linkers. + * @param prioritizedLinkers an array of prioritized linkers. Can be null. + * @throws NullPointerException if any of the array elements are null. */ public void setPrioritizedLinkers(final GuardingDynamicLinker... prioritizedLinkers) { - setPrioritizedLinkers(Arrays.asList(prioritizedLinkers)); + setPrioritizedLinkers(prioritizedLinkers == null ? null : Arrays.asList(prioritizedLinkers)); } /** - * Sets a single prioritized linker. Identical to calling {@link #setPrioritizedLinkers(List)} with a single-element - * list. + * 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. + * @throws NullPointerException if null is passed. */ public void setPrioritizedLinker(final GuardingDynamicLinker prioritizedLinker) { - if(prioritizedLinker == null) { - throw new IllegalArgumentException("prioritizedLinker == null"); - } - this.prioritizedLinkers = Collections.singletonList(prioritizedLinker); + this.prioritizedLinkers = Collections.singletonList(Objects.requireNonNull(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. + * Sets the fallback guarding dynamic linkers. These linkers will be + * consulted last by the resulting dynamic linker when it is linking call + * sites, after any autodiscovered and prioritized linkers. If the factory + * also autodiscovers a linker class matching one of the fallback linkers, + * the autodiscovered class 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. + * @param fallbackLinkers the list of fallback linkers. Can be empty to + * indicate the caller wishes to set no fallback linkers. Note that if this + * method is not invoked explicitly or is passed null, then the factory + * will create an instance of {@link BeansLinker} to serve as the default + * fallback linker. + * @throws NullPointerException if any of the list elements are null. */ public void setFallbackLinkers(final List fallbackLinkers) { - this.fallbackLinkers = fallbackLinkers == null ? null : new ArrayList<>(fallbackLinkers); + this.fallbackLinkers = copyListRequireNonNullElements(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. + * Sets the fallback guarding dynamic linkers. Identical to calling + * {@link #setFallbackLinkers(List)} with + * {@code Arrays.asList(fallbackLinkers)}. * - * @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. + * @param fallbackLinkers an array of fallback linkers. Can be empty to + * indicate the caller wishes to set no fallback linkers. Note that if this + * method is not invoked explicitly or is passed null, then the factory + * will create an instance of {@link BeansLinker} to serve as the default + * fallback linker. + * @throws NullPointerException if any of the array elements are null. */ public void setFallbackLinkers(final GuardingDynamicLinker... fallbackLinkers) { - setFallbackLinkers(Arrays.asList(fallbackLinkers)); + setFallbackLinkers(fallbackLinkers == null ? null : 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(final 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. + * Sets whether the dynamic 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(final boolean syncOnRelink) { @@ -238,10 +270,12 @@ } /** - * 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. + * 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(final int unstableRelinkThreshold) { @@ -252,52 +286,85 @@ } /** - * Set the pre-link filter. This is a {@link GuardedInvocationFilter} that will get the final chance to modify the - * guarded invocation after it has been created by a component linker and before the dynamic linker links it into - * the call site. It is normally used to adapt the return value type of the invocation to the type of the call site. - * When not set explicitly, {@link DefaultPrelinkFilter} will be used. - * @param prelinkFilter the pre-link filter for the dynamic linker. + * Set the pre-link transformer. This is a + * {@link GuardedInvocationTransformer} that will get the final chance to + * modify the guarded invocation after it has been created by a component + * linker and before the dynamic linker links it into the call site. It is + * normally used to adapt the return value type of the invocation to the + * type of the call site. When not set explicitly, a default pre-link + * transformer will be used that simply calls + * {@link GuardedInvocation#asType(LinkerServices, MethodType)}. Customized + * pre-link transformers are rarely needed; they are mostly used as a + * building block for implementing advanced techniques such as code + * deoptimization strategies. + * @param prelinkTransformer the pre-link transformer for the dynamic + * linker. Can be null to have the factory use the default transformer. */ - public void setPrelinkFilter(final GuardedInvocationFilter prelinkFilter) { - this.prelinkFilter = prelinkFilter; + public void setPrelinkTransformer(final GuardedInvocationTransformer prelinkTransformer) { + this.prelinkTransformer = prelinkTransformer; } /** - * Sets an object representing the conversion strategy for automatic type conversions. After - * {@link TypeConverterFactory#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has - * applied all custom conversions to a method handle, it still needs to effect - * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that - * can usually be automatically applied as per - * {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}. - * However, sometimes language runtimes will want to customize even those conversions for their own call - * sites. A typical example is allowing unboxing of null return values, which is by default prohibited by - * ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom - * automatic conversion strategy, that can deal with null values. Note that when the strategy's - * {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} - * is invoked, the custom language conversions will already have been applied to the method handle, so by - * design the difference between the handle's current method type and the desired final type will always - * only be ones that can be subjected to method invocation conversions. The strategy also doesn't need to - * invoke a final {@code MethodHandle.asType()} as the converter factory will do that as the final step. - * @param autoConversionStrategy the strategy for applying method invocation conversions for the linker - * created by this factory. + * Sets an object representing the conversion strategy for automatic type + * conversions. After + * {@link LinkerServices#asType(MethodHandle, MethodType)} has applied all + * custom conversions to a method handle, it still needs to effect + * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method + * invocation conversions} that can usually be automatically applied as per + * {@link MethodHandle#asType(MethodType)}. However, sometimes language + * runtimes will want to customize even those conversions for their own call + * sites. A typical example is allowing unboxing of null return values, + * which is by default prohibited by ordinary + * {@code MethodHandles.asType()}. In this case, a language runtime can + * install its own custom automatic conversion strategy, that can deal with + * null values. Note that when the strategy's + * {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)} + * is invoked, the custom language conversions will already have been + * applied to the method handle, so by design the difference between the + * handle's current method type and the desired final type will always only + * be ones that can be subjected to method invocation conversions. The + * strategy also doesn't need to invoke a final + * {@code MethodHandle.asType()} as that will be done internally as the + * final step. + * @param autoConversionStrategy the strategy for applying method invocation + * conversions for the linker created by this factory. Can be null for no + * custom strategy. */ public void setAutoConversionStrategy(final MethodTypeConversionStrategy autoConversionStrategy) { this.autoConversionStrategy = autoConversionStrategy; } /** - * Sets a method handle transformer that is supposed to act as the implementation of this linker factory's linkers' - * services {@link LinkerServices#filterInternalObjects(java.lang.invoke.MethodHandle)} method. - * @param internalObjectsFilter a method handle transformer filtering out internal objects, or null. + * Sets a method handle transformer that is supposed to act as the + * implementation of + * {@link LinkerServices#filterInternalObjects(MethodHandle)} for linker + * services of dynamic linkers created by this factory. Some language + * runtimes can have internal objects that should not escape their scope. + * They can add a transformer here that will modify the method handle so + * that any parameters that can receive potentially internal language + * runtime objects will have a filter added on them to prevent them from + * escaping, potentially by wrapping them. The transformer can also + * potentially add an unwrapping filter to the return value. + * {@link DefaultInternalObjectFilter} is provided as a convenience class + * for easily creating such filtering transformers. + * @param internalObjectsFilter a method handle transformer filtering out + * internal objects, or null. */ public void setInternalObjectsFilter(final MethodHandleTransformer internalObjectsFilter) { this.internalObjectsFilter = internalObjectsFilter; } /** - * Creates a new dynamic linker consisting of all the prioritized, autodiscovered, and fallback linkers as well as - * the pre-link filter. - * + * Creates a new dynamic linker based on the current configuration. This + * method can be invoked more than once to create multiple dynamic linkers. + * Automatically discovered linkers are newly instantiated on every + * invocation of this method. It is allowed to change the factory's + * configuration between invocations. The method is not thread safe. After + * invocation, callers can invoke {@link #getAutoLoadingErrors()} to + * retrieve a list of {@link ServiceConfigurationError}s that occurred while + * trying to load automatically discovered linkers. These are never thrown + * from the call to this method as it makes every effort to recover from + * them and ignore the failing linkers. * @return the new dynamic Linker */ public DynamicLinker createLinker() { @@ -316,8 +383,8 @@ addClasses(knownLinkerClasses, prioritizedLinkers); addClasses(knownLinkerClasses, fallbackLinkers); - final ClassLoader effectiveClassLoader = classLoaderExplicitlySet ? classLoader : getThreadContextClassLoader(); - final List discovered = AutoDiscovery.loadLinkers(effectiveClassLoader); + final List discovered = discoverAutoLoadLinkers(); + // Now, concatenate ... final List linkers = new ArrayList<>(prioritizedLinkers.size() + discovered.size() @@ -336,7 +403,7 @@ final GuardingDynamicLinker composite; switch(linkers.size()) { case 0: { - composite = BottomGuardingDynamicLinker.INSTANCE; + composite = (r, s) -> null; // linker that can't link anything break; } case 1: { @@ -356,22 +423,84 @@ } } - if(prelinkFilter == null) { - prelinkFilter = new DefaultPrelinkFilter(); + if(prelinkTransformer == null) { + prelinkTransformer = (inv, request, linkerServices) -> inv.asType(linkerServices, request.getCallSiteDescriptor().getMethodType()); } return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters, - autoConversionStrategy), composite, internalObjectsFilter), prelinkFilter, runtimeContextArgCount, + autoConversionStrategy), composite, internalObjectsFilter), prelinkTransformer, syncOnRelink, unstableRelinkThreshold); } + /** + * Returns a list of {@link ServiceConfigurationError}s that were + * encountered while loading automatically discovered linkers during the + * last invocation of {@link #createLinker()}. They can be any non-Dynalink + * specific service configuration issues, as well as some Dynalink-specific + * errors when an exporter that the factory tried to automatically load: + *
    + *
  • did not have the runtime permission named + * {@link GuardingDynamicLinkerExporter#AUTOLOAD_PERMISSION_NAME} in a + * system with a security manager, or
  • + *
  • returned null from {@link GuardingDynamicLinkerExporter#get()}, or
  • + *
  • the list returned from {@link GuardingDynamicLinkerExporter#get()} + * had a null element.
  • + *
+ * @return an immutable list of encountered + * {@link ServiceConfigurationError}s. Can be empty. + */ + public List getAutoLoadingErrors() { + return Collections.unmodifiableList(autoLoadingErrors); + } + + private List discoverAutoLoadLinkers() { + autoLoadingErrors = new LinkedList<>(); + final ClassLoader effectiveClassLoader = classLoaderExplicitlySet ? classLoader : getThreadContextClassLoader(); + final List discovered = new LinkedList<>(); + try { + final ServiceLoader linkerLoader = + AccessController.doPrivileged((PrivilegedAction>)()-> { + if (effectiveClassLoader == null) { + return ServiceLoader.loadInstalled(GuardingDynamicLinkerExporter.class); + } + return ServiceLoader.load(GuardingDynamicLinkerExporter.class, effectiveClassLoader); + }); + + for(final Iterator it = linkerLoader.iterator(); it.hasNext();) { + try { + final GuardingDynamicLinkerExporter autoLoader = it.next(); + try { + discovered.addAll(requireNonNullElements( + Objects.requireNonNull(autoLoader.get(), + ()->(autoLoader.getClass().getName() + " returned null from get()")), + ()->(autoLoader.getClass().getName() + " returned a list with at least one null element"))); + } catch (final ServiceConfigurationError|VirtualMachineError e) { + // Don't wrap a SCE in another SCE. Also, don't ignore + // any VME (e.g. StackOverflowError or OutOfMemoryError). + throw e; + } catch (final Throwable t) { + throw new ServiceConfigurationError(t.getMessage(), t); + } + } catch (final ServiceConfigurationError e) { + // Catch SCE with an individual exporter, carry on with it.hasNext(). + autoLoadingErrors.add(e); + } + } + } catch (final ServiceConfigurationError e) { + // Catch a top-level SCE; one either in ServiceLoader.load(), + // ServiceLoader.iterator(), or Iterator.hasNext(). + autoLoadingErrors.add(e); + } + return discovered; + } + private static ClassLoader getThreadContextClassLoader() { return AccessController.doPrivileged(new PrivilegedAction() { @Override public ClassLoader run() { return Thread.currentThread().getContextClassLoader(); } - }, ClassLoaderGetterContextProvider.GET_CLASS_LOADER_CONTEXT); + }, GET_CLASS_LOADER_CONTEXT); } private static void addClasses(final Set> knownLinkerClasses, @@ -380,4 +509,19 @@ knownLinkerClasses.add(linker.getClass()); } } + + private static List copyListRequireNonNullElements(final List list) { + if (list == null) { + return null; + } + return new ArrayList<>(requireNonNullElements(list, ()->"List has at least one null element")); + } + + private static List requireNonNullElements(final List list, final Supplier msgSupplier) { + for(final T t: list) { + Objects.requireNonNull(t, msgSupplier); + } + return list; + } + } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/GuardedInvocationFilter.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/GuardedInvocationFilter.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,105 +0,0 @@ -/* - * 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.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; -import jdk.internal.dynalink.linker.LinkerServices; - -/** - * Interface for objects that are used to transform one guarded invocation into another one. Typical usage is for - * implementing {@link DynamicLinkerFactory#setPrelinkFilter(GuardedInvocationFilter) pre-link filters}. - */ -public interface GuardedInvocationFilter { - /** - * Given a guarded invocation, return a potentially different guarded invocation. - * @param inv the original guarded invocation. Null is never passed. - * @param linkRequest the link request for which the invocation was generated (usually by some linker). - * @param linkerServices the linker services that can be used during creation of a new invocation. - * @return either the passed guarded invocation or a different one, with the difference usually determined based on - * information in the link request and the differing invocation created with the assistance of the linker services. - * Whether or not {@code null} is an accepted return value is dependent on the user of the filter. - */ - public GuardedInvocation filter(GuardedInvocation inv, LinkRequest linkRequest, LinkerServices linkerServices); -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/LinkerServicesImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/LinkerServicesImpl.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,164 @@ +/* + * 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 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; +import jdk.internal.dynalink.linker.MethodHandleTransformer; + +/** + * Default implementation of the {@link LinkerServices} interface. + */ +final class LinkerServicesImpl implements LinkerServices { + private static final ThreadLocal threadLinkRequest = new ThreadLocal<>(); + + private final TypeConverterFactory typeConverterFactory; + private final GuardingDynamicLinker topLevelLinker; + private final MethodHandleTransformer internalObjectsFilter; + + /** + * 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. + * @param internalObjectsFilter a method handle transformer that is supposed to act as the implementation of this + * services' {@link #filterInternalObjects(java.lang.invoke.MethodHandle)} method. + */ + LinkerServicesImpl(final TypeConverterFactory typeConverterFactory, + final GuardingDynamicLinker topLevelLinker, final MethodHandleTransformer internalObjectsFilter) { + this.typeConverterFactory = typeConverterFactory; + this.topLevelLinker = topLevelLinker; + this.internalObjectsFilter = internalObjectsFilter; + } + + @Override + public boolean canConvert(final Class from, final Class to) { + return typeConverterFactory.canConvert(from, to); + } + + @Override + public MethodHandle asType(final MethodHandle handle, final MethodType fromType) { + return typeConverterFactory.asType(handle, fromType); + } + + @Override + public MethodHandle getTypeConverter(final Class sourceType, final Class targetType) { + return typeConverterFactory.getTypeConverter(sourceType, targetType); + } + + @Override + public Comparison compareConversion(final Class sourceType, final Class targetType1, final Class targetType2) { + return typeConverterFactory.compareConversion(sourceType, targetType1, targetType2); + } + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest) throws Exception { + final LinkRequest prevLinkRequest = threadLinkRequest.get(); + threadLinkRequest.set(linkRequest); + try { + return topLevelLinker.getGuardedInvocation(linkRequest, this); + } finally { + threadLinkRequest.set(prevLinkRequest); + } + } + + @Override + public MethodHandle filterInternalObjects(final MethodHandle target) { + return internalObjectsFilter != null ? internalObjectsFilter.transform(target) : target; + } + + static MethodHandles.Lookup getCurrentLookup() { + final LinkRequest currentRequest = threadLinkRequest.get(); + if (currentRequest != null) { + return currentRequest.getCallSiteDescriptor().getLookup(); + } + return MethodHandles.publicLookup(); + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/MonomorphicCallSite.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/MonomorphicCallSite.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -/* - * 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}. - */ -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(final CallSiteDescriptor descriptor) { - super(descriptor); - } - - @Override - public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relink) { - setTarget(guardedInvocation.compose(relink)); - } - - @Override - public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relink) { - relink(guardedInvocation, relink); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/NamedOperation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/NamedOperation.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2015, 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 2015 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.util.Objects; + +/** + * Operation that associates a name with another operation. Typically used with + * operations that normally take a name or an index to bind them to a fixed + * name. E.g. {@code new NamedOperation(StandardOperation.GET_PROPERTY, "color")} + * will be a named operation for getting the property named "color" on the + * object it is applied to, and + * {@code new NamedOperation(StandardOperation.GET_ELEMENT, 3)} will be a named + * operation for getting the element at index 3 from the collection it is + * applied to. In these cases, the expected signature of the call site for the + * operation will change to no longer include the name parameter. Specifically, + * the documentation for all {@link StandardOperation} members describes how + * they are affected by being incorporated into a named operation. + */ +public class NamedOperation implements Operation { + private final Operation baseOperation; + private final Object name; + + /** + * Creates a new named operation. + * @param baseOperation the base operation that is associated with a name. + * @param name the name associated with the base operation. Note that the + * name is not necessarily a string, but can be an arbitrary object. As the + * name is used for addressing, it can be an {@link Integer} when meant + * to be used as an index into an array or list etc. + * @throws NullPointerException if either {@code baseOperation} or + * {@code name} is null. + * @throws IllegalArgumentException if {@code baseOperation} is itself a + * {@code NamedOperation}. + */ + public NamedOperation(final Operation baseOperation, final Object name) { + if (baseOperation instanceof NamedOperation) { + throw new IllegalArgumentException("baseOperation is a named operation"); + } + this.baseOperation = Objects.requireNonNull(baseOperation, "baseOperation is null"); + this.name = Objects.requireNonNull(name, "name is null"); + } + + /** + * Returns the base operation of this named operation. + * @return the base operation of this named operation. + */ + public Operation getBaseOperation() { + return baseOperation; + } + + /** + * Returns the name of this named operation. + * @return the name of this named operation. + */ + public Object getName() { + return name; + } + + /** + * Compares this named operation to another object. Returns true if the + * other object is also a named operation, and both their base operations + * and name are equal. + */ + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } else if(obj.getClass() != NamedOperation.class) { + return false; + } + final NamedOperation other = (NamedOperation)obj; + return baseOperation.equals(other.baseOperation) && name.equals(other.name); + } + + /** + * Returns the hash code of this named operation. It is defined to be equal + * to {@code baseOperation.hashCode() + 31 * name.hashCode()}. + */ + @Override + public int hashCode() { + return baseOperation.hashCode() + 31 * name.hashCode(); + } + + /** + * Returns the string representation of this named operation. It is defined + * to be equal to {@code baseOperation.toString() + ":" + name.toString()}. + */ + @Override + public String toString() { + return baseOperation.toString() + ":" + name.toString(); + } + + /** + * If the passed operation is a named operation, returns its + * {@link #getBaseOperation()}, otherwise returns the operation as is. + * @param op the operation + * @return the base operation of the passed operation. + */ + public static Operation getBaseOperation(final Operation op) { + return op instanceof NamedOperation ? ((NamedOperation)op).baseOperation : op; + } + + /** + * If the passed operation is a named operation, returns its + * {@link #getName()}, otherwise returns null. Note that a named operation + * object can never have a null name, therefore returning null is indicative + * that the passed operation is not, in fact, a named operation. + * @param op the operation + * @return the name in the passed operation, or null if it is not a named + * operation. + */ + public static Object getName(final Operation op) { + return op instanceof NamedOperation ? ((NamedOperation)op).name : null; + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/Operation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/Operation.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2015, 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 2015 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; + +/** + * An object that describes a dynamic operation. Dynalink defines a set of + * standard operations with the {@link StandardOperation} class, as well as a + * way to attach a fixed name to an operation using {@link NamedOperation} and + * to express a set of alternative operations using {@link CompositeOperation}. + * When presenting examples in this documentation, we will refer to standard + * operations using their name (e.g. {@code GET_PROPERTY}), to composite + * operations by separating their components with the vertical line character + * (e.g. {@code GET_PROPERTY|GET_ELEMENT}), and finally to named operations by + * separating the base operation and the name with the colon character (e.g. + * {@code GET_PROPERTY|GET_ELEMENT:color}). + */ +public interface Operation { +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/RelinkableCallSite.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/RelinkableCallSite.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/RelinkableCallSite.java Thu Oct 22 11:12:39 2015 -0700 @@ -85,23 +85,37 @@ 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; +import jdk.internal.dynalink.support.ChainedCallSite; +import jdk.internal.dynalink.support.SimpleRelinkableCallSite; /** - * 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. + * Interface for call sites managed by a {@link DynamicLinker}. Users of + * Dynalink must use subclasses of {@link CallSite} that also implement this + * interface as their call site implementations. There is a readily usable + * {@link SimpleRelinkableCallSite} subclass that implements monomorphic inline + * caching strategy as well as {@link ChainedCallSite} that implements a + * polymorphic inline caching strategy and retains a chain of previously linked + * method handles. A relinkable call site will be managed by a + * {@link DynamicLinker} object after being associated with it using its + * {@link DynamicLinker#link(RelinkableCallSite)} method. */ 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}. + * Invoked by dynamic linker to initialize 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 using + * {@link CallSite#setTarget(MethodHandle)}. Relink-and-invoke is the + * initial method handle set by + * {@link DynamicLinker#link(RelinkableCallSite)} that will cause the call + * site to be relinked to an appropriate target on its first invocation + * based on its arguments, and that linked target will then be invoked + * (hence the name). This linking protocol effectively delays linking until + * the call site is invoked with actual arguments and thus ensures that + * linkers can make nuanced linking decisions based on those arguments and + * not just on the static method type of the call site. + * @param relinkAndInvoke a relink-and-invoke method handle supplied by + * Dynalink. */ public void initialize(MethodHandle relinkAndInvoke); @@ -113,33 +127,52 @@ 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. + * This method will be called by the dynamic linker every time the call site + * is relinked (but see + * {@link #resetAndRelink(GuardedInvocation, MethodHandle)} for an + * exception). 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. + * @param guardedInvocation the guarded invocation that the call site should + * incorporate into its target method handle. + * @param relinkAndInvoke a relink-and-invoke method handle. This is a + * method handle matching the method type of the call site that is supplied + * by the {@link DynamicLinker} as a callback. It should be used by this + * call site as the ultimate 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 obtain an adequate target {@link GuardedInvocation} for the + * invocation, and subsequently invoke + * {@link #relink(GuardedInvocation, MethodHandle)} or + * {@link #resetAndRelink(GuardedInvocation, MethodHandle)}, and finally + * invoke the target. */ - public void relink(GuardedInvocation guardedInvocation, MethodHandle fallback); + public void relink(GuardedInvocation guardedInvocation, MethodHandle relinkAndInvoke); /** - * 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. + * 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 (that is how it differs from + * {@link #relink(GuardedInvocation, MethodHandle)}). It will be passed a + * {@code GuardedInvocation} that the call site should use to build its new + * target method handle. When this method is called, the call site is + * discouraged from keeping any previous state, 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. + * @param guardedInvocation the guarded invocation that the call site should + * use to build its target method handle. + * @param relinkAndInvoke a relink-and-invoke method handle. This is a + * method handle matching the method type of the call site that is supplied + * by the {@link DynamicLinker} as a callback. It should be used by this + * call site as the ultimate 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 obtain an adequate target {@link GuardedInvocation} for the + * invocation, and subsequently invoke + * {@link #relink(GuardedInvocation, MethodHandle)} or + * {@link #resetAndRelink(GuardedInvocation, MethodHandle)}, and finally + * invoke the target. */ - public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle fallback); + public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle relinkAndInvoke); } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/StandardOperation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/StandardOperation.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2015, 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 2015 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; + +/** + * Defines the standard dynamic operations. Getter and setter operations defined + * in this enumeration can be composed into a {@link CompositeOperation}, and + * {@link NamedOperation} can be used to bind the name parameter of operations + * that take one, in which case it disappears from the type signature. + */ +public enum StandardOperation implements Operation { + /** + * Get the value of a property defined on an object. Call sites with this + * operation should have a signature of + * (receiver, propertyName)→value or + * (receiver)→value when used with {@link NamedOperation}, with + * all parameters and return type being of any type (either primitive or + * reference). + */ + GET_PROPERTY, + /** + * Set the value of a property defined on an object. Call sites with this + * operation should have a signature of + * (receiver, propertyName, value)→void or + * (receiver, value)→void when used with {@link NamedOperation}, + * with all parameters and return type being of any type (either primitive + * or reference). + */ + SET_PROPERTY, + /** + * Get the value of an element of a collection. Call sites with this + * operation should have a signature of + * (receiver, index)→value or + * (receiver)→value when used with {@link NamedOperation}, with + * all parameters and return type being of any type (either primitive or + * reference). + */ + GET_ELEMENT, + /** + * Set the value of an element of a collection. Call sites with this + * operation should have a signature of + * (receiver, index, value)→void or + * (receiver, value)→void when used with {@link NamedOperation}, + * with all parameters and return type being of any type (either primitive + * or reference). + */ + SET_ELEMENT, + /** + * Get the length of an array of size of a collection. Call sites with + * this operation should have a signature of (receiver)→value, + * with all parameters and return type being of any type (either primitive + * or reference). + */ + GET_LENGTH, + /** + * Gets an object representing a method defined on an object. Call sites + * with this operation should have a signature of + * (receiver, methodName)→value, or + * (receiver)→value when used with {@link NamedOperation} + * with all parameters and return type being of any type (either primitive + * or reference). + */ + GET_METHOD, + /** + * Calls a method defined on an object. Call sites with this + * operation should have a signature of + * (receiver, methodName, arguments...)→value or + * (receiver, arguments...)→value when used with {@link NamedOperation}, + * with all parameters and return type being of any type (either primitive + * or reference). + */ + CALL_METHOD, + /** + * Calls a callable object. Call sites with this operation should have a + * signature of (receiver, arguments...)→value, with all + * parameters and return type being of any type (either primitive or + * reference). Typically, if the callable is a method of an object, the + * first argument will act as the "this" value passed to the called method. + * The CALL operation is allowed to be used with a + * {@link NamedOperation} even though it does not take a name. Using it with + * a named operation won't affect its signature; the name is solely meant to + * be used as a diagnostic description for error messages. + */ + CALL, + /** + * Calls a constructor object. Call sites with this operation should have a + * signature of (receiver, arguments...)→value, with all + * parameters and return type being of any type (either primitive or + * reference). The NEW operation is allowed to be used with a + * {@link NamedOperation} even though it does not take a name. Using it with + * a named operation won't affect its signature; the name is solely meant to + * be used as a diagnostic description for error messages. + */ + NEW +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/TypeConverterFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/TypeConverterFactory.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,437 @@ +/* + * 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.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import java.lang.invoke.WrongMethodTypeException; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.LinkedList; +import java.util.List; +import java.util.function.Supplier; +import jdk.internal.dynalink.internal.AccessControlContextFactory; +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; +import jdk.internal.dynalink.linker.MethodTypeConversionStrategy; +import jdk.internal.dynalink.linker.support.TypeUtilities; + +/** + * 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. + */ +final class TypeConverterFactory { + private static final AccessControlContext GET_CLASS_LOADER_CONTEXT = + AccessControlContextFactory.createAccessControlContext("getClassLoader"); + + private final GuardingTypeConverterFactory[] factories; + private final ConversionComparator[] comparators; + private final MethodTypeConversionStrategy autoConversionStrategy; + + private final ClassValue> converterMap = new ClassValue>() { + @Override + protected ClassMap computeValue(final Class sourceType) { + return new ClassMap(getClassLoader(sourceType)) { + @Override + protected MethodHandle computeValue(final Class targetType) { + try { + return createConverter(sourceType, targetType); + } catch (final RuntimeException e) { + throw e; + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + }; + } + }; + + private final ClassValue> converterIdentityMap = new ClassValue>() { + @Override + protected ClassMap computeValue(final Class sourceType) { + return new ClassMap(getClassLoader(sourceType)) { + @Override + protected MethodHandle computeValue(final Class targetType) { + if(!canAutoConvert(sourceType, targetType)) { + final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType); + if(converter != IDENTITY_CONVERSION) { + return converter; + } + } + return IDENTITY_CONVERSION.asType(MethodType.methodType(targetType, sourceType)); + } + }; + } + }; + + private final ClassValue> canConvert = new ClassValue>() { + @Override + protected ClassMap computeValue(final Class sourceType) { + return new ClassMap(getClassLoader(sourceType)) { + @Override + protected Boolean computeValue(final Class targetType) { + try { + return getTypeConverterNull(sourceType, targetType) != null; + } catch (final RuntimeException e) { + throw e; + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + }; + } + }; + + private static ClassLoader getClassLoader(final Class clazz) { + return AccessController.doPrivileged(new PrivilegedAction() { + @Override + public ClassLoader run() { + return clazz.getClassLoader(); + } + }, GET_CLASS_LOADER_CONTEXT); + } + + /** + * Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances. + * + * @param factories the {@link GuardingTypeConverterFactory} instances to compose. + * @param autoConversionStrategy conversion strategy for automatic type conversions. After + * {@link #asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has applied all custom + * conversions to a method handle, it still needs to effect + * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that + * can usually be automatically applied as per + * {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}. + * However, sometimes language runtimes will want to customize even those conversions for their own call + * sites. A typical example is allowing unboxing of null return values, which is by default prohibited by + * ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom + * automatic conversion strategy, that can deal with null values. Note that when the strategy's + * {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} + * is invoked, the custom language conversions will already have been applied to the method handle, so by + * design the difference between the handle's current method type and the desired final type will always + * only be ones that can be subjected to method invocation conversions. Can be null, in which case no + * custom strategy is employed. + */ + TypeConverterFactory(final Iterable factories, + final MethodTypeConversionStrategy autoConversionStrategy) { + final List l = new LinkedList<>(); + final List c = new LinkedList<>(); + for(final 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()]); + this.autoConversionStrategy = autoConversionStrategy; + } + + /** + * 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. For all conversions that are not a JLS method invocation conversion it'll insert + * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters + * provided by {@link GuardingTypeConverterFactory} implementations. For the remaining JLS method invocation + * conversions, it will invoke {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)} first + * if an automatic conversion strategy was specified in the + * {@link #TypeConverterFactory(Iterable, MethodTypeConversionStrategy) constructor}, and finally apply + * {@link MethodHandle#asType(MethodType)} for any remaining conversions. + * + * @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)}, + * {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)}, and + * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with + * {@link GuardingTypeConverterFactory} produced type converters as filters. + */ + MethodHandle asType(final 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); + } + } + } + + // Give change to automatic conversion strategy, if one is present. + final MethodHandle autoConvertedHandle = + autoConversionStrategy != null ? autoConversionStrategy.asType(newHandle, fromType) : newHandle; + + // Do a final asType for any conversions that remain. + return autoConvertedHandle.asType(fromType); + } + + private static MethodHandle applyConverters(final MethodHandle handle, final int pos, final 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. + */ + boolean canConvert(final Class from, final Class to) { + return canAutoConvert(from, to) || canConvert.get(from).get(to); + } + + /** + * 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. + */ + Comparison compareConversion(final Class sourceType, final Class targetType1, final Class targetType2) { + for(final 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 getCacheableTypeConverterNull(final Class sourceType, final Class targetType) { + final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType); + return converter == IDENTITY_CONVERSION ? null : converter; + } + + /*private*/ MethodHandle getTypeConverterNull(final Class sourceType, final Class targetType) { + try { + return getCacheableTypeConverterNull(sourceType, targetType); + } catch(final NotCacheableConverter e) { + return e.converter; + } + } + + /*private*/ MethodHandle getCacheableTypeConverter(final Class sourceType, final Class targetType) { + return converterMap.get(sourceType).get(targetType); + } + + /** + * 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. + */ + MethodHandle getTypeConverter(final Class sourceType, final Class targetType) { + try { + return converterIdentityMap.get(sourceType).get(targetType); + } catch(final NotCacheableConverter e) { + return e.converter; + } + } + + private static class LookupSupplier implements Supplier { + volatile boolean returnedLookup; + volatile boolean closed; + + @Override + public Lookup get() { + if (closed) { + // Something held on to this supplier and tried to invoke it + // after we're done with it. + throw new IllegalStateException(); + } + final Lookup lookup = LinkerServicesImpl.getCurrentLookup(); + returnedLookup = true; + return lookup; + } + } + + /*private*/ MethodHandle createConverter(final Class sourceType, final Class targetType) throws Exception { + final MethodType type = MethodType.methodType(targetType, sourceType); + final MethodHandle identity = IDENTITY_CONVERSION.asType(type); + MethodHandle last = identity; + + final LookupSupplier lookupSupplier = new LookupSupplier(); + try { + for(int i = factories.length; i-- > 0;) { + final GuardedInvocation next = factories[i].convertToType(sourceType, targetType, lookupSupplier); + if(next != null) { + last = next.compose(last); + } + } + } finally { + lookupSupplier.closed = true; + } + + if(last == identity) { + return IDENTITY_CONVERSION; + } + if(!lookupSupplier.returnedLookup) { + return last; + } + // At least one of the consulted converter factories obtained the + // lookup, so we must presume the created converter is sensitive to the + // lookup class and thus we will not cache it. + throw new NotCacheableConverter(last); + } + + /*private*/ static final MethodHandle IDENTITY_CONVERSION = MethodHandles.identity(Object.class); + + @SuppressWarnings("serial") + private static class NotCacheableConverter extends RuntimeException { + final MethodHandle converter; + + NotCacheableConverter(final MethodHandle converter) { + super("", null, false, false); + this.converter = converter; + } + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AbstractJavaLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AbstractJavaLinker.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AbstractJavaLinker.java Thu Oct 22 11:12:39 2015 -0700 @@ -92,21 +92,26 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.CompositeOperation; +import jdk.internal.dynalink.NamedOperation; +import jdk.internal.dynalink.Operation; +import jdk.internal.dynalink.StandardOperation; import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType; +import jdk.internal.dynalink.internal.InternalTypeUtilities; 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; -import jdk.internal.dynalink.support.TypeUtilities; +import jdk.internal.dynalink.linker.support.Guards; +import jdk.internal.dynalink.linker.support.Lookup; +import sun.reflect.CallerSensitive; /** * A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property @@ -284,7 +289,7 @@ * @return the single dynamic method representing the reflective member */ private static SingleDynamicMethod createDynamicMethod(final AccessibleObject m) { - if(CallerSensitiveDetector.isCallerSensitive(m)) { + if (m.isAnnotationPresent(CallerSensitive.class)) { // Method has @CallerSensitive annotation return new CallerSensitiveDynamicMethod(m); } @@ -342,18 +347,27 @@ @Override public GuardedInvocation getGuardedInvocation(final 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); + final CallSiteDescriptor callSiteDescriptor = request.getCallSiteDescriptor(); + + // Handle NamedOperation(CALL_METHOD, name) separately + final Operation operation = callSiteDescriptor.getOperation(); + if (operation instanceof NamedOperation) { + final NamedOperation namedOperation = (NamedOperation)operation; + if (namedOperation.getBaseOperation() == StandardOperation.CALL_METHOD) { + return createGuardedDynamicMethodInvocation(callSiteDescriptor, + linkerServices, namedOperation.getName().toString(), methods); + } } - List operations = CallSiteDescriptorFactory.tokenizeOperators(callSiteDescriptor); + + List operations = Arrays.asList( + CompositeOperation.getOperations( + NamedOperation.getBaseOperation(operation))); + final Object name = NamedOperation.getName(operation); + while(!operations.isEmpty()) { - final GuardedInvocationComponent gic = getGuardedInvocationComponent(callSiteDescriptor, linkerServices, - operations); + final GuardedInvocationComponent gic = + getGuardedInvocationComponent(callSiteDescriptor, + linkerServices, operations, name); if(gic != null) { return gic.getGuardedInvocation(); } @@ -362,23 +376,26 @@ return null; } - protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List operations) throws Exception { + protected GuardedInvocationComponent getGuardedInvocationComponent( + final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, + final List operations, final Object name) + 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)); + final Operation op = operations.get(0); + // Either GET_PROPERTY:name(this) or GET_PROPERTY(this, name) + if(op == StandardOperation.GET_PROPERTY) { + return getPropertyGetter(callSiteDescriptor, linkerServices, pop(operations), name); } - // Either dyn:setProp:name(this, value) or dyn:setProp(this, name, value) - if("setProp".equals(op)) { - return getPropertySetter(callSiteDescriptor, linkerServices, pop(operations)); + // Either SET_PROPERTY:name(this, value) or SET_PROPERTY(this, name, value) + if(op == StandardOperation.SET_PROPERTY) { + return getPropertySetter(callSiteDescriptor, linkerServices, pop(operations), name); } - // Either dyn:getMethod:name(this), or dyn:getMethod(this, name) - if("getMethod".equals(op)) { - return getMethodGetter(callSiteDescriptor, linkerServices, pop(operations)); + // Either GET_METHOD:name(this), or GET_METHOD(this, name) + if(op == StandardOperation.GET_METHOD) { + return getMethodGetter(callSiteDescriptor, linkerServices, pop(operations), name); } return null; } @@ -407,18 +424,6 @@ return Guards.asType(assignableGuard, type); } - private GuardedInvocation getCallPropWithThis(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { - switch(callSiteDescriptor.getNameTokenCount()) { - case 3: { - return createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices, - callSiteDescriptor.getNameToken(CallSiteDescriptor.NAME_OPERAND), methods); - } - default: { - return null; - } - } - } - private GuardedInvocation createGuardedDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices, final String methodName, final Map methodMap){ final MethodHandle inv = getDynamicMethodInvocation(callSiteDescriptor, linkerServices, methodName, methodMap); @@ -481,84 +486,86 @@ MethodHandles.constant(Object.class, null), 0, MethodHandle.class); private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List operations) throws Exception { - switch(callSiteDescriptor.getNameTokenCount()) { - case 2: { - // Must have three arguments: target object, property name, and property value. - assertParameterCount(callSiteDescriptor, 3); + final LinkerServices linkerServices, final List operations, final Object name) throws Exception { + if (name == null) { + return getUnnamedPropertySetter(callSiteDescriptor, linkerServices, operations); + } + return getNamedPropertySetter(callSiteDescriptor, linkerServices, operations, name); + } - // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be - // valid for us to convert return values proactively. Also, since we don't know what setters will be - // invoked, we'll conservatively presume Object return type. The one exception is void return. - final MethodType origType = callSiteDescriptor.getMethodType(); - final MethodType type = origType.returnType() == void.class ? origType : origType.changeReturnType(Object.class); + private GuardedInvocationComponent getUnnamedPropertySetter(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List operations) throws Exception { + // Must have three arguments: target object, property name, and property value. + assertParameterCount(callSiteDescriptor, 3); + + // We want setters that conform to "Object(O, V)". Note, we aren't doing "R(O, V)" as it might not be + // valid for us to convert return values proactively. Also, since we don't know what setters will be + // invoked, we'll conservatively presume Object return type. The one exception is void return. + final MethodType origType = callSiteDescriptor.getMethodType(); + final MethodType type = origType.returnType() == void.class ? origType : origType.changeReturnType(Object.class); - // 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. + // 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, although we don't really use R here (see above about using - // Object return type). - 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, - callSiteDescriptor.changeMethodType(setterType), linkerServices); + // 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, although we don't really use R here (see above about using + // Object return type). + 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, + callSiteDescriptor.changeMethodType(setterType), linkerServices); - // Cast getter to MethodHandle(O, N, V) - final MethodHandle typedGetter = linkerServices.asType(boundGetter, type.changeReturnType( - MethodHandle.class)); + // 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); + // 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, null); - final MethodHandle fallbackFolded; - if(nextComponent == null) { - // Object(MethodHandle)->Object(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 { - // Object(O, N, V)->Object(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); - } + final MethodHandle fallbackFolded; + if(nextComponent == null) { + // Object(MethodHandle)->Object(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 { + // Object(O, N, V)->Object(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); - } - 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, 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; - } + // 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); } + return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); + } + + private GuardedInvocationComponent getNamedPropertySetter(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List operations, final Object name) throws Exception { + // Must have two arguments: target object and property value + assertParameterCount(callSiteDescriptor, 2); + final GuardedInvocation gi = createGuardedDynamicMethodInvocation(callSiteDescriptor, linkerServices, + name.toString(), 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, name); } private static final Lookup privateLookup = new Lookup(MethodHandles.lookup()); @@ -568,91 +575,93 @@ private static final MethodHandle CONSTANT_NULL_DROP_ANNOTATED_METHOD = MethodHandles.dropArguments( MethodHandles.constant(Object.class, null), 0, AnnotatedDynamicMethod.class); private static final MethodHandle GET_ANNOTATED_METHOD = privateLookup.findVirtual(AnnotatedDynamicMethod.class, - "getTarget", MethodType.methodType(MethodHandle.class, MethodHandles.Lookup.class, LinkerServices.class)); + "getTarget", MethodType.methodType(MethodHandle.class, CallSiteDescriptor.class, LinkerServices.class)); private static final MethodHandle GETTER_INVOKER = MethodHandles.invoker(MethodType.methodType(Object.class, Object.class)); private GuardedInvocationComponent getPropertyGetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List ops) throws Exception { - switch(callSiteDescriptor.getNameTokenCount()) { - case 2: { - // Since we can't know what kind of a getter we'll get back on different invocations, we'll just - // conservatively presume Object. Note we can't just coerce to a narrower call site type as the linking - // runtime might not allow coercing at that call site. - final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class); - // Must have exactly two arguments: receiver and name - assertParameterCount(callSiteDescriptor, 2); + final LinkerServices linkerServices, final List ops, final Object name) throws Exception { + if (name == null) { + return getUnnamedPropertyGetter(callSiteDescriptor, linkerServices, ops); + } + + return getNamedPropertyGetter(callSiteDescriptor, linkerServices, ops, name); + } - // 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 - // AnnotatedDynamicMethod; if it is non-null, invoke its "handle" field, otherwise either return null, - // or delegate to next component's invocation. + private GuardedInvocationComponent getUnnamedPropertyGetter(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List ops) throws Exception { + // Since we can't know what kind of a getter we'll get back on different invocations, we'll just + // conservatively presume Object. Note we can't just coerce to a narrower call site type as the linking + // runtime might not allow coercing at that call site. + final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class); + // Must have exactly two arguments: receiver and name + assertParameterCount(callSiteDescriptor, 2); - final MethodHandle typedGetter = linkerServices.asType(getPropertyGetterHandle, type.changeReturnType( - AnnotatedDynamicMethod.class)); - final MethodHandle callSiteBoundMethodGetter = MethodHandles.insertArguments( - GET_ANNOTATED_METHOD, 1, callSiteDescriptor.getLookup(), linkerServices); - final MethodHandle callSiteBoundInvoker = MethodHandles.filterArguments(GETTER_INVOKER, 0, - callSiteBoundMethodGetter); - // Object(AnnotatedDynamicMethod, Object)->Object(AnnotatedDynamicMethod, T0) - final MethodHandle invokeHandleTyped = linkerServices.asType(callSiteBoundInvoker, - MethodType.methodType(type.returnType(), AnnotatedDynamicMethod.class, type.parameterType(0))); - // Since it's in the target of a fold, drop the unnecessary second argument - // Object(AnnotatedDynamicMethod, T0)->Object(AnnotatedDynamicMethod, T0, T1) - final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2, - type.parameterType(1)); - final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, - linkerServices, ops); + // 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 + // AnnotatedDynamicMethod; 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( + AnnotatedDynamicMethod.class)); + final MethodHandle callSiteBoundMethodGetter = MethodHandles.insertArguments( + GET_ANNOTATED_METHOD, 1, callSiteDescriptor, linkerServices); + final MethodHandle callSiteBoundInvoker = MethodHandles.filterArguments(GETTER_INVOKER, 0, + callSiteBoundMethodGetter); + // Object(AnnotatedDynamicMethod, Object)->Object(AnnotatedDynamicMethod, T0) + final MethodHandle invokeHandleTyped = linkerServices.asType(callSiteBoundInvoker, + MethodType.methodType(type.returnType(), AnnotatedDynamicMethod.class, type.parameterType(0))); + // Since it's in the target of a fold, drop the unnecessary second argument + // Object(AnnotatedDynamicMethod, T0)->Object(AnnotatedDynamicMethod, T0, T1) + final MethodHandle invokeHandleFolded = MethodHandles.dropArguments(invokeHandleTyped, 2, + type.parameterType(1)); + final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, + linkerServices, ops, null); - final MethodHandle fallbackFolded; - if(nextComponent == null) { - // Object(AnnotatedDynamicMethod)->Object(AnnotatedDynamicMethod, T0, T1); returns constant null - fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_METHOD, 1, - type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedDynamicMethod.class)); - } else { - // Object(T0, T1)->Object(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to - // drop the extra argument resulting from fold and to change its return type to Object. - final MethodHandle nextInvocation = nextComponent.getGuardedInvocation().getInvocation(); - final MethodType nextType = nextInvocation.type(); - fallbackFolded = MethodHandles.dropArguments(nextInvocation.asType( - nextType.changeReturnType(Object.class)), 0, AnnotatedDynamicMethod.class); - } + final MethodHandle fallbackFolded; + if(nextComponent == null) { + // Object(AnnotatedDynamicMethod)->Object(AnnotatedDynamicMethod, T0, T1); returns constant null + fallbackFolded = MethodHandles.dropArguments(CONSTANT_NULL_DROP_ANNOTATED_METHOD, 1, + type.parameterList()).asType(type.insertParameterTypes(0, AnnotatedDynamicMethod.class)); + } else { + // Object(T0, T1)->Object(AnnotatedDynamicMethod, T0, T1); adapts the next component's invocation to + // drop the extra argument resulting from fold and to change its return type to Object. + final MethodHandle nextInvocation = nextComponent.getGuardedInvocation().getInvocation(); + final MethodType nextType = nextInvocation.type(); + fallbackFolded = MethodHandles.dropArguments(nextInvocation.asType( + nextType.changeReturnType(Object.class)), 0, AnnotatedDynamicMethod.class); + } - // fold(Object(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1)) - final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( - IS_ANNOTATED_METHOD_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter); - if(nextComponent == null) { - return getClassGuardedInvocationComponent(compositeGetter, type); - } - return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); - } - case 3: { - // Must have exactly one argument: receiver - assertParameterCount(callSiteDescriptor, 1); - // Fixed name - final AnnotatedDynamicMethod 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.getInvocation(callSiteDescriptor, linkerServices); - // 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; - // TODO: we aren't using the type that declares the most generic getter here! - return new GuardedInvocationComponent(getter, getGuard(validationType, - callSiteDescriptor.getMethodType()), clazz, validationType); - } - default: { - // Can't do anything with more than 3 name components - return null; - } + // fold(Object(AnnotatedDynamicMethod, T0, T1), AnnotatedDynamicMethod(T0, T1)) + final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( + IS_ANNOTATED_METHOD_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter); + if(nextComponent == null) { + return getClassGuardedInvocationComponent(compositeGetter, type); } + return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); + } + + private GuardedInvocationComponent getNamedPropertyGetter(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List ops, final Object name) throws Exception { + // Must have exactly one argument: receiver + assertParameterCount(callSiteDescriptor, 1); + // Fixed name + final AnnotatedDynamicMethod annGetter = propertyGetters.get(name.toString()); + if(annGetter == null) { + // We have no such property, always delegate to the next component operation + return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops, name); + } + final MethodHandle getter = annGetter.getInvocation(callSiteDescriptor, linkerServices); + // 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; + // TODO: we aren't using the type that declares the most generic getter here! + return new GuardedInvocationComponent(getter, getGuard(validationType, + callSiteDescriptor.getMethodType()), clazz, validationType); } private MethodHandle getGuard(final ValidationType validationType, final MethodType methodType) { @@ -680,64 +689,67 @@ private static final MethodHandle OBJECT_IDENTITY = MethodHandles.identity(Object.class); private GuardedInvocationComponent getMethodGetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List ops) throws Exception { + final LinkerServices linkerServices, final List ops, final Object name) throws Exception { // The created method handle will always return a DynamicMethod (or null), but since we don't want that type to // be visible outside of this linker, declare it to return Object. final MethodType type = callSiteDescriptor.getMethodType().changeReturnType(Object.class); - 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 || !TypeUtilities.areAssignable(DynamicMethod.class, - nextComponent.getGuardedInvocation().getInvocation().type().returnType())) { - // No next component operation, or it can never produce a dynamic method; just return a component - // for this operation. - return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type); - } + if (name == null) { + return getUnnamedMethodGetter(callSiteDescriptor, linkerServices, ops, type); + } + + return getNamedMethodGetter(callSiteDescriptor, linkerServices, ops, name, type); + } - // 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. + private GuardedInvocationComponent getUnnamedMethodGetter(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List ops, final MethodType type) throws Exception { + // Must have exactly two arguments: receiver and name + assertParameterCount(callSiteDescriptor, 2); + final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, + linkerServices, ops, null); + if(nextComponent == null || !InternalTypeUtilities.areAssignable(DynamicMethod.class, + nextComponent.getGuardedInvocation().getInvocation().type().returnType())) { + // No next component operation, or it can never produce a dynamic method; just return a component + // for this operation. + return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type); + } + + // 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); - // 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( - OBJECT_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0, Object.class)); - final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation(); - // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly modulo the - // return type. - assert nextComponentInvocation.type().changeReturnType(type.returnType()).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, - Object.class); - // Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get) - final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( - IS_DYNAMIC_METHOD, returnMethodHandle, nextCombinedInvocation), typedGetter); + final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type); + // 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( + OBJECT_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0, Object.class)); + final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation(); + // The assumption is that getGuardedInvocationComponent() already asType()'d it correctly modulo the + // return type. + assert nextComponentInvocation.type().changeReturnType(type.returnType()).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, + Object.class); + // Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get) + final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest( + IS_DYNAMIC_METHOD, 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(Object.class, method), 0, type.parameterType(0)), type), type); - } - default: { - // Can't do anything with more than 3 name components - return null; - } + return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); + } + + private GuardedInvocationComponent getNamedMethodGetter(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List ops, final Object name, final MethodType type) + throws Exception { + // Must have exactly one argument: receiver + assertParameterCount(callSiteDescriptor, 1); + final DynamicMethod method = getDynamicMethod(name.toString()); + if(method == null) { + // We have no such method, always delegate to the next component + return getGuardedInvocationComponent(callSiteDescriptor, linkerServices, ops, name); } + // 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(Object.class, method), 0, type.parameterType(0)), type), type); } static class MethodPair { @@ -757,7 +769,7 @@ static MethodPair matchReturnTypes(final MethodHandle m1, final MethodHandle m2) { final MethodType type1 = m1.type(); final MethodType type2 = m2.type(); - final Class commonRetType = TypeUtilities.getCommonLosslessConversionType(type1.returnType(), + final Class commonRetType = InternalTypeUtilities.getCommonLosslessConversionType(type1.returnType(), type2.returnType()); return new MethodPair( m1.asType(type1.changeReturnType(commonRetType)), @@ -766,7 +778,7 @@ private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) { if(descriptor.getMethodType().parameterCount() != paramCount) { - throw new BootstrapMethodError(descriptor.getName() + " must have exactly " + paramCount + " parameters."); + throw new BootstrapMethodError(descriptor.getOperation() + " must have exactly " + paramCount + " parameters."); } } @@ -805,7 +817,7 @@ @SuppressWarnings("unused") // This method is marked to return Object instead of DynamicMethod as it's used as a linking component and we don't // want to make the DynamicMethod type observable externally (e.g. as the return type of a MethodHandle returned for - // "dyn:getMethod" linking). + // GET_METHOD linking). private Object getDynamicMethod(final Object name) { return getDynamicMethod(String.valueOf(name), methods); } @@ -871,8 +883,8 @@ } @SuppressWarnings("unused") - MethodHandle getTarget(final MethodHandles.Lookup lookup, final LinkerServices linkerServices) { - final MethodHandle inv = linkerServices.filterInternalObjects(method.getTarget(lookup)); + MethodHandle getTarget(final CallSiteDescriptor desc, final LinkerServices linkerServices) { + final MethodHandle inv = linkerServices.filterInternalObjects(method.getTarget(desc)); assert inv != null; return inv; } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java Thu Oct 22 11:12:39 2015 -0700 @@ -86,7 +86,7 @@ import java.lang.invoke.MethodType; import java.util.LinkedList; import java.util.List; -import jdk.internal.dynalink.support.TypeUtilities; +import jdk.internal.dynalink.linker.support.TypeUtilities; /** * Represents overloaded methods applicable to a specific call site signature. diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanLinker.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanLinker.java Thu Oct 22 11:12:39 2015 -0700 @@ -91,13 +91,15 @@ import java.util.List; import java.util.Map; import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.Operation; +import jdk.internal.dynalink.StandardOperation; 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; +import jdk.internal.dynalink.linker.support.Guards; +import jdk.internal.dynalink.linker.support.Lookup; +import jdk.internal.dynalink.linker.support.TypeUtilities; /** * A class that provides linking capabilities for a single POJO class. Normally not used directly, but managed by @@ -109,7 +111,7 @@ 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? + // REVISIT: is it maybe a code smell that StandardOperation.GET_LENGTH is not needed? setPropertyGetter("length", GET_ARRAY_LENGTH, ValidationType.IS_ARRAY); } else if(List.class.isAssignableFrom(clazz)) { setPropertyGetter("length", GET_COLLECTION_LENGTH, ValidationType.INSTANCE_OF); @@ -128,27 +130,23 @@ @Override protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List operations) throws Exception { + final LinkerServices linkerServices, final List operations, final Object name) throws Exception { final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(callSiteDescriptor, - linkerServices, operations); + linkerServices, operations, name); 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)); + final Operation op = operations.get(0); + if(op == StandardOperation.GET_ELEMENT) { + return getElementGetter(callSiteDescriptor, linkerServices, pop(operations), name); } - if("setElem".equals(op)) { - return getElementSetter(callSiteDescriptor, linkerServices, pop(operations)); + if(op == StandardOperation.SET_ELEMENT) { + return getElementSetter(callSiteDescriptor, linkerServices, pop(operations), name); } - // dyn:getLength(this) (works on Java arrays, collections, and maps) - if("getLength".equals(op)) { + if(op == StandardOperation.GET_LENGTH) { return getLengthGetter(callSiteDescriptor); } return null; @@ -168,11 +166,11 @@ }; private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List operations) throws Exception { + final LinkerServices linkerServices, final List operations, final Object name) throws Exception { final MethodType callSiteType = callSiteDescriptor.getMethodType(); final Class declaredType = callSiteType.parameterType(0); final GuardedInvocationComponent nextComponent = getGuardedInvocationComponent(callSiteDescriptor, - linkerServices, operations); + linkerServices, operations, name); // 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 @@ -206,22 +204,20 @@ 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(collectionType != CollectionType.MAP && fixedKey != null) { - typedFixedKey = convertKeyToInteger(fixedKey, linkerServices); - if(typedFixedKey == null) { + final Object typedName; + if(collectionType != CollectionType.MAP && name != null) { + typedName = convertKeyToInteger(name, linkerServices); + if(typedName == null) { // key is not numeric, it can never succeed return nextComponent; } } else { - typedFixedKey = fixedKey; + typedName = name; } final GuardedInvocation gi = gic.getGuardedInvocation(); - final Binder binder = new Binder(linkerServices, callSiteType, typedFixedKey); + final Binder binder = new Binder(linkerServices, callSiteType, typedName); final MethodHandle invocation = gi.getInvocation(); if(nextComponent == null) { @@ -263,40 +259,50 @@ validatorClass, validationType); } - private static String getFixedKey(final CallSiteDescriptor callSiteDescriptor) { - return callSiteDescriptor.getNameTokenCount() == 2 ? null : callSiteDescriptor.getNameToken( - CallSiteDescriptor.NAME_OPERAND); - } + private static Integer convertKeyToInteger(final Object fixedKey, final LinkerServices linkerServices) throws Exception { + if (fixedKey instanceof Integer) { + return (Integer)fixedKey; + } - private static Object convertKeyToInteger(final String fixedKey, final LinkerServices linkerServices) throws Exception { - try { - if(linkerServices.canConvert(String.class, Number.class)) { + final Number n; + if (fixedKey instanceof Number) { + n = (Number)fixedKey; + } else { + final Class keyClass = fixedKey.getClass(); + if(linkerServices.canConvert(keyClass, Number.class)) { + final Object val; 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 intIndex; + val = linkerServices.getTypeConverter(keyClass, Number.class).invoke(fixedKey); } catch(Exception|Error e) { throw e; } catch(final Throwable t) { throw new RuntimeException(t); } + if(!(val instanceof Number)) { + return null; // not a number + } + n = (Number)val; + } else if (fixedKey instanceof String){ + try { + return Integer.valueOf((String)fixedKey); + } catch(final NumberFormatException e) { + // key is not a number + return null; + } + } else { + return null; } - return Integer.valueOf(fixedKey); - } catch(final NumberFormatException e) { - // key is not a number - return null; + } + + if(n instanceof Integer) { + return (Integer)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 intIndex; } private static MethodHandle convertArgToInt(final MethodHandle mh, final LinkerServices ls, final CallSiteDescriptor desc) { @@ -389,7 +395,7 @@ MethodType.methodType(Object.class, Object.class, Object.class)); private GuardedInvocationComponent getElementSetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List operations) throws Exception { + final LinkerServices linkerServices, final List operations, final Object name) throws Exception { final MethodType callSiteType = callSiteDescriptor.getMethodType(); final Class declaredType = callSiteType.parameterType(0); @@ -431,27 +437,25 @@ // as maps will always succeed in setting the element and will never need to fall back to the next component // operation. final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getGuardedInvocationComponent( - callSiteDescriptor, linkerServices, operations); + callSiteDescriptor, linkerServices, operations, name); 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(collectionType != CollectionType.MAP && fixedKey != null) { - typedFixedKey = convertKeyToInteger(fixedKey, linkerServices); - if(typedFixedKey == null) { + final Object typedName; + if(collectionType != CollectionType.MAP && name != null) { + typedName = convertKeyToInteger(name, linkerServices); + if(typedName == null) { // key is not numeric, it can never succeed return nextComponent; } } else { - typedFixedKey = fixedKey; + typedName = name; } final GuardedInvocation gi = gic.getGuardedInvocation(); - final Binder binder = new Binder(linkerServices, callSiteType, typedFixedKey); + final Binder binder = new Binder(linkerServices, callSiteType, typedName); final MethodHandle invocation = gi.getInvocation(); if(nextComponent == null) { @@ -510,7 +514,7 @@ private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) { if(descriptor.getMethodType().parameterCount() != paramCount) { - throw new BootstrapMethodError(descriptor.getName() + " must have exactly " + paramCount + " parameters."); + throw new BootstrapMethodError(descriptor.getOperation() + " must have exactly " + paramCount + " parameters."); } } } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeansLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeansLinker.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeansLinker.java Thu Oct 22 11:12:39 2015 -0700 @@ -83,11 +83,11 @@ package jdk.internal.dynalink.beans; -import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; import java.util.Collection; import java.util.Collections; -import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.DynamicLinkerFactory; +import jdk.internal.dynalink.StandardOperation; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.GuardingDynamicLinker; import jdk.internal.dynalink.linker.LinkRequest; @@ -95,36 +95,61 @@ 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: + * A linker for ordinary Java objects. 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 linker recognized. 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 public methods for invocation through {@code dyn:callMethod} operation;
  • - *
  • expose all public methods 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 all public methods of form {@code setXxx()}, {@code getXxx()}, + * and {@code isXxx()} as property setters and getters for + * {@link StandardOperation#SET_PROPERTY} and {@link StandardOperation#GET_PROPERTY} + * operations;
  • + *
  • expose all public methods for invocation through + * {@link StandardOperation#CALL_METHOD} operation;
  • + *
  • expose all public methods for retrieval for + * {@link StandardOperation#GET_METHOD} operation; the methods thus retrieved + * can then be invoked using {@link StandardOperation#CALL}.
  • + *
  • expose all public fields as properties, unless there are getters or + * setters for the properties of the same name;
  • + *
  • expose {@link StandardOperation#GET_LENGTH}, + * {@link StandardOperation#GET_ELEMENT} and {@link StandardOperation#SET_ELEMENT} + * on native Java arrays, as well as {@link java.util.List} and + * {@link java.util.Map} objects; ({@link StandardOperation#GET_LENGTH} 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}.
  • + *
  • expose {@link StandardOperation#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.

+ *

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 NamedMethod(GET_METHOD, "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). Overloaded + * resolution for constructors is not automatic as there is no logical place to + * attach that functionality to but if a language wishes to provide this + * functionality, it can use {@link #getConstructorMethod(Class, String)} as a + * useful building block for it.

+ *

Variable argument invocation is handled for both methods + * and constructors.

+ *

Caller sensitive methods can be linked as long as they + * are otherwise public and link requests have call site descriptors carrying + * full-strength {@link Lookup} objects and not weakened lookups or the public + * lookup.

+ *

The class also exposes various static methods for discovery of available + * property and method names on classes and class instances, as well as access + * to per-class linkers using the {@link #getLinkerForClass(Class)} + * method.

*/ public class BeansLinker implements GuardingDynamicLinker { private static final ClassValue linkers = new ClassValue() { @@ -140,15 +165,16 @@ }; /** - * Creates a new POJO linker. + * Creates a new beans 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. + * 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 */ @@ -157,9 +183,12 @@ } /** - * Returns true if the object is a Dynalink Java dynamic method. + * Returns true if the object is a Java dynamic method (e.g., one + * obtained through a {@code GET_METHOD} operation on a Java object or + * {@link StaticClass} or through + * {@link #getConstructorMethod(Class, String)}. * - * @param obj the object we want to test for being a dynamic method + * @param obj the object we want to test for being a Java dynamic method. * @return true if it is a dynamic method, false otherwise. */ public static boolean isDynamicMethod(final Object obj) { @@ -167,9 +196,10 @@ } /** - * Returns true if the object is a Dynalink Java constructor. + * Returns true if the object is a Java constructor (obtained through + * {@link #getConstructorMethod(Class, String)}}. * - * @param obj the object we want to test for being a constructor + * @param obj the object we want to test for being a Java constructor. * @return true if it is a constructor, false otherwise. */ public static boolean isDynamicConstructor(final Object obj) { @@ -177,10 +207,22 @@ } /** - * Return the dynamic method of constructor of the given class and the given signature. + * Return the dynamic method of constructor of the given class and the given + * signature. This method is useful for exposing a functionality for + * selecting an overloaded constructor based on an explicit signature, as + * this functionality is not otherwise exposed by Dynalink as + * {@link StaticClass} objects act as overloaded constructors without + * explicit signature selection. Example usage would be: + * {@code getConstructorMethod(java.awt.Color.class, "int, int, int")}. * @param clazz the class - * @param signature full signature of the constructor - * @return DynamicMethod for the constructor + * @param signature full signature of the constructor. Note how you can use + * names of primitive types, array names with normal Java notation (e.g. + * {@code "int[]"}), and normally you can even use unqualified class names + * (e.g. {@code "String, List"} instead of + * {@code "java.lang.String, java.util.List"} as long as they don't cause + * ambiguity in the specific parameter position. + * @return dynamic method for the constructor or null if no constructor with + * the specified signature exists. */ public static Object getConstructorMethod(final Class clazz, final String signature) { return StaticClassLinker.getConstructorMethod(clazz, signature); @@ -255,13 +297,6 @@ @Override public GuardedInvocation getGuardedInvocation(final 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 diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDetector.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDetector.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,148 +0,0 @@ -/* - * 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.annotation.Annotation; -import java.lang.reflect.AccessibleObject; -import sun.reflect.CallerSensitive; - -/** - * Utility class that determines if a method or constructor is caller sensitive. It actually encapsulates two different - * strategies for determining caller sensitivity; a more robust one that works if Dynalink runs as code with access - * to {@code sun.reflect} package, and an unprivileged one that is used when Dynalink doesn't have access to that - * package. Note that even the unprivileged strategy is ordinarily robust, but it relies on the {@code toString} method - * of the annotation. If an attacker were to use a different annotation to spoof the string representation of the - * {@code CallerSensitive} annotation, they could designate their own methods as caller sensitive. This however does not - * escalate privileges, only causes Dynalink to never cache method handles for such methods, so all it would do would - * decrease the performance in linking such methods. In the opposite case when an attacker could trick Dynalink into not - * recognizing genuine {@code CallerSensitive} annotations, Dynalink would treat caller sensitive methods as ordinary - * methods, and would cache them bound to a zero-privilege delegate as the caller (just what Dynalink did before it - * could handle caller-sensitive methods). That would practically render caller-sensitive methods exposed through - * Dynalink unusable, but again, can not lead to any privilege escalations. Therefore, even the less robust unprivileged - * strategy is safe; the worst thing a successful attack against it can achieve is slight reduction in Dynalink-exposed - * functionality or performance. - */ -public class CallerSensitiveDetector { - - private static final DetectionStrategy DETECTION_STRATEGY = getDetectionStrategy(); - - static boolean isCallerSensitive(final AccessibleObject ao) { - return DETECTION_STRATEGY.isCallerSensitive(ao); - } - - private static DetectionStrategy getDetectionStrategy() { - try { - return new PrivilegedDetectionStrategy(); - } catch(final Throwable t) { - return new UnprivilegedDetectionStrategy(); - } - } - - private abstract static class DetectionStrategy { - abstract boolean isCallerSensitive(AccessibleObject ao); - } - - private static class PrivilegedDetectionStrategy extends DetectionStrategy { - private static final Class CALLER_SENSITIVE_ANNOTATION_CLASS = CallerSensitive.class; - - @Override - boolean isCallerSensitive(final AccessibleObject ao) { - return ao.getAnnotation(CALLER_SENSITIVE_ANNOTATION_CLASS) != null; - } - } - - private static class UnprivilegedDetectionStrategy extends DetectionStrategy { - private static final String CALLER_SENSITIVE_ANNOTATION_STRING = "@sun.reflect.CallerSensitive()"; - - @Override - boolean isCallerSensitive(final AccessibleObject o) { - for(final Annotation a: o.getAnnotations()) { - if(String.valueOf(a).equals(CALLER_SENSITIVE_ANNOTATION_STRING)) { - return true; - } - } - return false; - } - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Thu Oct 22 11:12:39 2015 -0700 @@ -91,15 +91,24 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import jdk.internal.dynalink.support.Lookup; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.internal.AccessControlContextFactory; +import jdk.internal.dynalink.linker.support.Lookup; /** * A dynamic method bound to exactly one Java method or constructor that is caller sensitive. Since the target method is * caller sensitive, it doesn't cache a method handle but rather uses the passed lookup object in - * {@link #getTarget(java.lang.invoke.MethodHandles.Lookup)} to unreflect a method handle from the reflective member on + * {@link #getTarget(CallSiteDescriptor)} to unreflect a method handle from the reflective member on * every request. */ class CallerSensitiveDynamicMethod extends SingleDynamicMethod { + private static final AccessControlContext GET_LOOKUP_CONTEXT = + AccessControlContextFactory.createAccessControlContext( + CallSiteDescriptor.GET_LOOKUP_PERMISSION_NAME); + // Typed as "AccessibleObject" as it can be either a method or a constructor. // If we were Java8-only, we could use java.lang.reflect.Executable private final AccessibleObject target; @@ -143,7 +152,11 @@ } @Override - MethodHandle getTarget(final MethodHandles.Lookup lookup) { + MethodHandle getTarget(final CallSiteDescriptor desc) { + final MethodHandles.Lookup lookup = AccessController.doPrivileged( + (PrivilegedAction)()->desc.getLookup(), + GET_LOOKUP_CONTEXT); + if(target instanceof Method) { final MethodHandle mh = Lookup.unreflect(lookup, (Method)target); if(Modifier.isStatic(((Member)target).getModifiers())) { diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CheckRestrictedPackage.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CheckRestrictedPackage.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/CheckRestrictedPackage.java Thu Oct 22 11:12:39 2015 -0700 @@ -86,15 +86,15 @@ import java.lang.reflect.Modifier; import java.security.AccessControlContext; import java.security.AccessController; -import java.security.Permissions; import java.security.PrivilegedAction; -import java.security.ProtectionDomain; +import jdk.internal.dynalink.internal.AccessControlContextFactory; /** * A utility class to check whether a given class is in a package with restricted access e.g. "sun.*" etc. */ class CheckRestrictedPackage { - private static final AccessControlContext NO_PERMISSIONS_CONTEXT = createNoPermissionsContext(); + private static final AccessControlContext NO_PERMISSIONS_CONTEXT = + AccessControlContextFactory.createAccessControlContext(); /** * Returns true if the class is either not public, or it resides in a package with restricted access. @@ -131,8 +131,4 @@ } return false; } - - private static AccessControlContext createNoPermissionsContext() { - return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, new Permissions()) }); - } } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassLinker.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassLinker.java Thu Oct 22 11:12:39 2015 -0700 @@ -87,7 +87,7 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType; -import jdk.internal.dynalink.support.Lookup; +import jdk.internal.dynalink.linker.support.Lookup; /** * A linker for java.lang.Class objects. Provides a synthetic property "static" that allows access to static fields and diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassString.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassString.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/ClassString.java Thu Oct 22 11:12:39 2015 -0700 @@ -85,11 +85,15 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.LinkedList; import java.util.List; +import jdk.internal.dynalink.internal.AccessControlContextFactory; +import jdk.internal.dynalink.internal.InternalTypeUtilities; import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.support.Guards; -import jdk.internal.dynalink.support.TypeUtilities; +import jdk.internal.dynalink.linker.support.TypeUtilities; /** * Represents a sequence of {@link Class} objects, useful for representing method signatures. Provides value @@ -97,6 +101,9 @@ * JLS. */ final class ClassString { + private static final AccessControlContext GET_CLASS_LOADER_CONTEXT = + AccessControlContextFactory.createAccessControlContext("getClassLoader"); + /** * An anonymous inner class used solely to represent the "type" of null values for method applicability checking. */ @@ -143,12 +150,17 @@ } boolean isVisibleFrom(final ClassLoader classLoader) { - for(int i = 0; i < classes.length; ++i) { - if(!Guards.canReferenceDirectly(classLoader, classes[i].getClassLoader())) { - return false; + return AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Boolean run() { + for(final Class clazz: classes) { + if(!InternalTypeUtilities.canReferenceDirectly(classLoader, clazz.getClassLoader())) { + return false; + } + } + return true; } - } - return true; + }, GET_CLASS_LOADER_CONTEXT); } List getMaximallySpecifics(final List methods, final LinkerServices linkerServices, final boolean varArg) { diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/DynamicMethodLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/DynamicMethodLinker.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/DynamicMethodLinker.java Thu Oct 22 11:12:39 2015 -0700 @@ -86,16 +86,19 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.NamedOperation; +import jdk.internal.dynalink.Operation; +import jdk.internal.dynalink.StandardOperation; 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.internal.dynalink.support.Guards; +import jdk.internal.dynalink.linker.support.Guards; /** - * Simple linker that implements the "dyn:call" operation for {@link DynamicMethod} objects - the objects returned by - * "dyn:getMethod" from {@link AbstractJavaLinker}. + * Simple linker that implements the {@link StandardOperation#CALL} operation + * for {@link DynamicMethod} objects - the objects returned by + * {@link StandardOperation#GET_METHOD} through {@link AbstractJavaLinker}. */ class DynamicMethodLinker implements TypeBasedGuardingDynamicLinker { @Override @@ -109,19 +112,16 @@ 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); final DynamicMethod dynMethod = (DynamicMethod)receiver; final boolean constructor = dynMethod.isConstructor(); final MethodHandle invocation; - if (operator == "call" && !constructor) { - invocation = dynMethod.getInvocation( - CallSiteDescriptorFactory.dropParameterTypes(desc, 0, 1), linkerServices); - } else if (operator == "new" && constructor) { + final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor(); + final Operation op = NamedOperation.getBaseOperation(desc.getOperation()); + if (op == StandardOperation.CALL && !constructor) { + invocation = dynMethod.getInvocation(desc.changeMethodType( + desc.getMethodType().dropParameterTypes(0, 1)), linkerServices); + } else if (op == StandardOperation.NEW && constructor) { final MethodHandle ctorInvocation = dynMethod.getInvocation(desc, linkerServices); if(ctorInvocation == null) { return null; diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/FacetIntrospector.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/FacetIntrospector.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/FacetIntrospector.java Thu Oct 22 11:12:39 2015 -0700 @@ -92,7 +92,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Map; -import jdk.internal.dynalink.support.Lookup; +import jdk.internal.dynalink.linker.support.Lookup; /** * Base for classes that expose class field and method information to an {@link AbstractJavaLinker}. There are diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/MaximallySpecific.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/MaximallySpecific.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/MaximallySpecific.java Thu Oct 22 11:12:39 2015 -0700 @@ -90,7 +90,7 @@ import java.util.List; import jdk.internal.dynalink.linker.ConversionComparator.Comparison; import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.support.TypeUtilities; +import jdk.internal.dynalink.linker.support.TypeUtilities; /** * Utility class that encapsulates the algorithm for choosing the maximally specific methods. diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Thu Oct 22 11:12:39 2015 -0700 @@ -84,18 +84,24 @@ package jdk.internal.dynalink.beans; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.text.Collator; import java.util.ArrayList; import java.util.Collections; +import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Map; +import java.util.Set; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.beans.ApplicableOverloadedMethods.ApplicabilityTest; +import jdk.internal.dynalink.internal.AccessControlContextFactory; +import jdk.internal.dynalink.internal.InternalTypeUtilities; import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.support.TypeUtilities; /** * Represents a group of {@link SingleDynamicMethod} objects that represents all overloads of a particular name (or all @@ -216,14 +222,25 @@ // methods here to their handles, as the OverloadedMethod instance is specific to a call site, so it // has an already determined Lookup. final List methodHandles = new ArrayList<>(invokables.size()); - final MethodHandles.Lookup lookup = callSiteDescriptor.getLookup(); for(final SingleDynamicMethod method: invokables) { - methodHandles.add(method.getTarget(lookup)); + methodHandles.add(method.getTarget(callSiteDescriptor)); } - return new OverloadedMethod(methodHandles, this, callSiteType, linkerServices).getInvoker(); + return new OverloadedMethod(methodHandles, this, getCallSiteClassLoader(callSiteDescriptor), callSiteType, linkerServices).getInvoker(); } } + } + private static final AccessControlContext GET_CALL_SITE_CLASS_LOADER_CONTEXT = + AccessControlContextFactory.createAccessControlContext( + "getClassLoader", CallSiteDescriptor.GET_LOOKUP_PERMISSION_NAME); + + private static ClassLoader getCallSiteClassLoader(final CallSiteDescriptor callSiteDescriptor) { + return AccessController.doPrivileged(new PrivilegedAction() { + @Override + public ClassLoader run() { + return callSiteDescriptor.getLookup().lookupClass().getClassLoader(); + } + }, GET_CALL_SITE_CLASS_LOADER_CONTEXT); } @Override @@ -324,7 +341,7 @@ private static boolean isApplicableDynamically(final LinkerServices linkerServices, final Class callSiteType, final Class methodType) { - return TypeUtilities.isPotentiallyConvertible(callSiteType, methodType) + return isPotentiallyConvertible(callSiteType, methodType) || linkerServices.canConvert(callSiteType, methodType); } @@ -345,4 +362,72 @@ private boolean constructorFlagConsistent(final SingleDynamicMethod method) { return methods.isEmpty()? true : (methods.getFirst().isConstructor() == method.isConstructor()); } + + /** + * 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. + */ + private static boolean isPotentiallyConvertible(final Class callSiteType, final Class methodType) { + // Widening or narrowing reference conversion + if(InternalTypeUtilities.areAssignable(callSiteType, 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; + } + + 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(final Map, Class> map, final Class clazz) { + if(clazz == null) { + return; + } + map.put(clazz, clazz); + addClassHierarchy(map, clazz.getSuperclass()); + for(final 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(final Class clazz) { + return PRIMITIVE_WRAPPER_TYPES.contains(clazz); + } } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedMethod.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedMethod.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/OverloadedMethod.java Thu Oct 22 11:12:39 2015 -0700 @@ -91,9 +91,9 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import jdk.internal.dynalink.internal.InternalTypeUtilities; import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.support.Lookup; -import jdk.internal.dynalink.support.TypeUtilities; +import jdk.internal.dynalink.linker.support.Lookup; /** * Represents a subset of overloaded methods for a certain method name on a certain class. It can be either a fixarg or @@ -104,15 +104,20 @@ class OverloadedMethod { private final Map argTypesToMethods = new ConcurrentHashMap<>(); private final OverloadedDynamicMethod parent; + private final ClassLoader callSiteClassLoader; private final MethodType callSiteType; private final MethodHandle invoker; private final LinkerServices linkerServices; private final ArrayList fixArgMethods; private final ArrayList varArgMethods; - OverloadedMethod(final List methodHandles, final OverloadedDynamicMethod parent, final MethodType callSiteType, + OverloadedMethod(final List methodHandles, + final OverloadedDynamicMethod parent, + final ClassLoader callSiteClassLoader, + final MethodType callSiteType, final LinkerServices linkerServices) { this.parent = parent; + this.callSiteClassLoader = callSiteClassLoader; final Class commonRetType = getCommonReturnType(methodHandles); this.callSiteType = callSiteType.changeReturnType(commonRetType); this.linkerServices = linkerServices; @@ -177,9 +182,9 @@ break; } } - // Avoid keeping references to unrelated classes; this ruins the performance a bit, but avoids class loader - // memory leaks. - if(classString.isVisibleFrom(parent.getClassLoader())) { + // Avoid keeping references to unrelated classes; this ruins the + // performance a bit, but avoids class loader memory leaks. + if(classString.isVisibleFrom(callSiteClassLoader)) { argTypesToMethods.put(classString, method); } } @@ -268,7 +273,7 @@ final Iterator it = methodHandles.iterator(); Class retType = it.next().type().returnType(); while(it.hasNext()) { - retType = TypeUtilities.getCommonLosslessConversionType(retType, it.next().type().returnType()); + retType = InternalTypeUtilities.getCommonLosslessConversionType(retType, it.next().type().returnType()); } return retType; } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Thu Oct 22 11:12:39 2015 -0700 @@ -84,13 +84,13 @@ package jdk.internal.dynalink.beans; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; +import jdk.internal.dynalink.CallSiteDescriptor; /** * A dynamic method bound to exactly one Java method or constructor that is not caller sensitive. Since its target is * not caller sensitive, this class pre-caches its method handle and always returns it from the call to - * {@link #getTarget(Lookup)}. Can be used in general to represents dynamic methods bound to a single method handle, + * {@link #getTarget(CallSiteDescriptor)}. Can be used in general to represents dynamic methods bound to a single method handle, * even if that handle is not mapped to a Java method, i.e. as a wrapper around field getters/setters, array element * getters/setters, etc. */ @@ -140,7 +140,7 @@ } @Override - MethodHandle getTarget(final Lookup lookup) { + MethodHandle getTarget(final CallSiteDescriptor desc) { return target; } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/SingleDynamicMethod.java Thu Oct 22 11:12:39 2015 -0700 @@ -90,8 +90,8 @@ import java.util.StringTokenizer; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.support.Guards; -import jdk.internal.dynalink.support.Lookup; +import jdk.internal.dynalink.linker.support.Guards; +import jdk.internal.dynalink.linker.support.Lookup; /** * Base class for dynamic methods that dispatch to a single target Java method or constructor. Handles adaptation of the @@ -119,15 +119,17 @@ abstract MethodType getMethodType(); /** - * Given a specified lookup, returns a method handle to this method's target. - * @param lookup the lookup to use. + * Given a specified call site descriptor, returns a method handle to this method's target. The target + * should only depend on the descriptor's lookup, and it should only retrieve it (as a privileged + * operation) when it is absolutely needed. + * @param desc the call site descriptor to use. * @return the handle to this method's target method. */ - abstract MethodHandle getTarget(MethodHandles.Lookup lookup); + abstract MethodHandle getTarget(CallSiteDescriptor desc); @Override MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { - return getInvocation(getTarget(callSiteDescriptor.getLookup()), callSiteDescriptor.getMethodType(), + return getInvocation(getTarget(callSiteDescriptor), callSiteDescriptor.getMethodType(), linkerServices); } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClass.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClass.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClass.java Thu Oct 22 11:12:39 2015 -0700 @@ -85,16 +85,48 @@ import java.io.Serializable; import java.util.Objects; +import jdk.internal.dynalink.StandardOperation; /** - * 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. + * Object that allows access to the static members of a class (its static + * methods, properties, and fields), as well as construction of instances using + * {@link StandardOperation#NEW} operation. In Dynalink, {@link Class} objects + * are not treated specially and act as ordinary Java objects; you can use e.g. + * {@code NamedOperation(GET_PROPERTY, "superclass")} as a property getter to + * invoke {@code clazz.getSuperclass()}. On the other hand, you can not use + * {@code Class} objects to access static members of a class, nor to create new + * instances of the class using {@code NEW}. This is consistent with how + * {@code Class} objects behave in Java: in Java, you write e.g. + * {@code new BitSet()} instead of {@code new BitSet.class()}. Similarly, you + * write {@code System.out} and not {@code System.class.out}. It is this aspect + * of using a class name as the constructor and a namespace for static members + * that {@code StaticClass} embodies. + *

+ * 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 members. The {@code "class"} synthetic property is additionally + * recognized and returns the Java {@link Class} object, just as in Java + * {@code System.class} evaluates to the {@code Class} object for the + * {@code} System class. Conversely, {@link Class} objects exposed through + * {@link BeansLinker} expose the {@code "static"} synthetic property which + * returns their {@code StaticClass} object (there is no equivalent to this in + * Java). + *

+ * In summary, instances of this class act as namespaces for static members and + * as constructors for classes, much the same way as specifying a class name in + * Java language does, except that in Java this is just a syntactic element, + * while in Dynalink they are expressed as actual objects. + *

{@code StaticClass} objects representing Java array types will act as + * constructors taking a single int argument and create an array of the + * specified size. + *

+ * If the class has several constructors, {@link StandardOperation#NEW} on + * {@code StaticClass} will try to select the most specific applicable + * constructor. You might want to expose a mechanism in your language for + * selecting a constructor with an explicit signature through + * {@link BeansLinker#getConstructorMethod(Class, String)}. */ -public class StaticClass implements Serializable { +public final class StaticClass implements Serializable { private static final ClassValue staticClasses = new ClassValue() { @Override protected StaticClass computeValue(final Class type) { @@ -129,7 +161,7 @@ @Override public String toString() { - return "JavaClassStatics[" + clazz.getName() + "]"; + return "StaticClass[" + clazz.getName() + "]"; } private Object readResolve() { diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClassLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClassLinker.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClassLinker.java Thu Oct 22 11:12:39 2015 -0700 @@ -90,12 +90,14 @@ import java.util.Arrays; import java.util.Collection; import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.NamedOperation; +import jdk.internal.dynalink.StandardOperation; import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType; 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.Lookup; +import jdk.internal.dynalink.linker.support.Lookup; /** * Provides a linker for the {@link StaticClass} objects. @@ -150,8 +152,7 @@ return gi; } final CallSiteDescriptor desc = request.getCallSiteDescriptor(); - final String op = desc.getNameToken(CallSiteDescriptor.OPERATOR); - if("new" == op && constructor != null) { + if(NamedOperation.getBaseOperation(desc.getOperation()) == StandardOperation.NEW && constructor != null) { final MethodHandle ctorInvocation = constructor.getInvocation(desc, linkerServices); if(ctorInvocation != null) { return new GuardedInvocation(ctorInvocation, getClassGuard(desc.getMethodType())); diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/package-info.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015, 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. +*/ + +/** + * Contains the linker for ordinary Java objects. + * @since 1.9 + */ +@jdk.Exported +package jdk.internal.dynalink.beans; diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/package.html --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/package.html Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ - - - - -

- Contains the linker for POJOs. -

- diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/internal/AccessControlContextFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/internal/AccessControlContextFactory.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.dynalink.internal; + +import java.security.AccessControlContext; +import java.security.Permission; +import java.security.Permissions; +import java.security.ProtectionDomain; +import java.util.stream.Stream; + +/** + * Utility class for creating permission-restricting {@link AccessControlContext}s. + */ +public final class AccessControlContextFactory { + private AccessControlContextFactory () { + } + + /** + * Creates an access control context with no permissions. + * @return an access control context with no permissions. + */ + public static AccessControlContext createAccessControlContext() { + return createAccessControlContext(new Permission[0]); + } + + /** + * Creates an access control context limited to only the specified permissions. + * @param permissions the permissions for the newly created access control context. + * @return a new access control context limited to only the specified permissions. + */ + public static AccessControlContext createAccessControlContext(final Permission... permissions) { + final Permissions perms = new Permissions(); + for(final Permission permission: permissions) { + perms.add(permission); + } + return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) }); + } + + /** + * Creates an access control context limited to only the {@link RuntimePermission}s + * of the given names. + * @param runtimePermissionNames the names of runtime permissions for the + * newly created access control context. + * @return a new access control context limited to only the runtime + * permissions with the specified names. + */ + public static AccessControlContext createAccessControlContext(final String... runtimePermissionNames) { + return createAccessControlContext(makeRuntimePermissions(runtimePermissionNames)); + } + + private static Permission[] makeRuntimePermissions(final String... runtimePermissionNames) { + return Stream.of(runtimePermissionNames).map(RuntimePermission::new).toArray(Permission[]::new); + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/internal/InternalTypeUtilities.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/internal/InternalTypeUtilities.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.dynalink.internal; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import jdk.internal.dynalink.linker.support.TypeUtilities; + +/** + * Various static utility methods for testing type relationships; internal to Dynalink. + */ +public class InternalTypeUtilities { + private InternalTypeUtilities() { + } + + /** + * Returns true if either of the types is assignable from the other. + * @param c1 one type + * @param c2 another type + * @return true if either c1 is assignable from c2 or c2 is assignable from c1. + */ + public static boolean areAssignable(final Class c1, final Class c2) { + return c1.isAssignableFrom(c2) || c2.isAssignableFrom(c1); + } + + /** + * 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. Generally, it is only safe + * to reference classes from the same or ancestor class loader. {@code null} + * indicates the system class loader; classes from it can always be + * directly referenced, and it can only directly reference classes from + * itself. This method can be used by language runtimes to ensure they are + * using weak references in their linkages when they need to link to methods + * in unrelated class loaders. + * + * @param referrerLoader the referrer class loader. + * @param referredLoader the referred class loader + * @return true if it is safe to strongly reference the class from referred + * in referred. + * @throws SecurityException if the caller does not have the + * {@code RuntimePermission("getClassLoader")} permission and the method + * needs to traverse the parent class loader chain. + */ + public static boolean canReferenceDirectly(final 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; + } + + /** + * Given two types represented by c1 and c2, returns a type that is their + * most specific common supertype for purposes of lossless conversions. + * + * @param c1 one type + * @param c2 another type + * @return their most common superclass or superinterface for purposes of + * lossless conversions. 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 getCommonLosslessConversionType(final Class c1, final Class c2) { + if(c1 == c2) { + return c1; + } else if (c1 == void.class || c2 == void.class) { + return Object.class; + } else if(TypeUtilities.isConvertibleWithoutLoss(c2, c1)) { + return c1; + } else if(TypeUtilities.isConvertibleWithoutLoss(c1, c2)) { + return c2; + } else if(c1.isPrimitive() && c2.isPrimitive()) { + if((c1 == byte.class && c2 == char.class) || (c1 == char.class && c2 == byte.class)) { + // byte + char = int + return int.class; + } else if((c1 == short.class && c2 == char.class) || (c1 == char.class && c2 == short.class)) { + // short + char = int + return int.class; + } else if((c1 == int.class && c2 == float.class) || (c1 == float.class && c2 == int.class)) { + // int + float = double + return double.class; + } + } + // For all other cases. This will handle long + (float|double) = Number case as well as boolean + anything = Object case too. + return getMostSpecificCommonTypeUnequalNonprimitives(c1, c2); + } + + private static Class getMostSpecificCommonTypeUnequalNonprimitives(final Class c1, final Class c2) { + final Class npc1 = c1.isPrimitive() ? TypeUtilities.getWrapperType(c1) : c1; + final Class npc2 = c2.isPrimitive() ? TypeUtilities.getWrapperType(c2) : c2; + final Set> a1 = getAssignables(npc1, npc2); + final Set> a2 = getAssignables(npc2, npc1); + 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. + final List> max = new ArrayList<>(); + outer: for(final Class clazz: a1) { + for(final Iterator> maxiter = max.iterator(); maxiter.hasNext();) { + final Class maxClazz = maxiter.next(); + if(TypeUtilities.isSubtype(maxClazz, clazz)) { + // It can't be maximal, if there's already a more specific + // maximal than it. + continue outer; + } + if(TypeUtilities.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(final Class c1, final Class c2) { + final Set> s = new HashSet<>(); + collectAssignables(c1, c2, s); + return s; + } + + private static void collectAssignables(final Class c1, final Class c2, final Set> s) { + if(c1.isAssignableFrom(c2)) { + s.add(c1); + } + final Class sc = c1.getSuperclass(); + if(sc != null) { + collectAssignables(sc, c2, s); + } + final Class[] itf = c1.getInterfaces(); + for(int i = 0; i < itf.length; ++i) { + collectAssignables(itf[i], c2, s); + } + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/ConversionComparator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/ConversionComparator.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/ConversionComparator.java Thu Oct 22 11:12:39 2015 -0700 @@ -85,11 +85,14 @@ /** - * 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. + * 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. */ public interface ConversionComparator { /** @@ -105,12 +108,13 @@ } /** - * Determines which of the two target types is the preferred conversion target from a source type. + * 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. + * @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 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocation.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocation.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocation.java Thu Oct 22 11:12:39 2015 -0700 @@ -83,24 +83,32 @@ package jdk.internal.dynalink.linker; -import static jdk.nashorn.internal.lookup.Lookup.MH; - 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 java.util.Objects; +import java.util.function.Supplier; import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.support.Guards; +import jdk.internal.dynalink.linker.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. + * Represents a conditionally valid method handle. Usually produced as a return + * value of + * {@link GuardingDynamicLinker#getGuardedInvocation(LinkRequest, LinkerServices)} + * and + * {@link GuardingTypeConverterFactory#convertToType(Class, Class, Supplier)}. + * It is an immutable tuple of an invocation method handle, a guard method + * handle that defines the applicability of the invocation handle, zero or more + * switch points that can be used for external invalidation of the invocation + * handle, and an exception type that if thrown during an invocation of the + * method handle also invalidates it. The invocation handle is suitable for + * invocation if the guard handle returns true for its arguments, and as long + * as any of the switch points are not invalidated, and as long as it does not + * throw an exception of the designated type. The guard, the switch points, and + * the exception type are all optional (a guarded invocation having none of them + * is unconditionally valid). */ public class GuardedInvocation { private final MethodHandle invocation; @@ -109,9 +117,11 @@ private final SwitchPoint[] switchPoints; /** - * Creates a new guarded invocation. This invocation is unconditional as it has no invalidations. + * Creates a new unconditional guarded invocation. It is unconditional as it + * has no invalidations. * - * @param invocation the method handle representing the invocation. Must not be null. + * @param invocation the method handle representing the invocation. Must not + * be null. * @throws NullPointerException if invocation is null. */ public GuardedInvocation(final MethodHandle invocation) { @@ -119,12 +129,15 @@ } /** - * Creates a new guarded invocation. + * Creates a new guarded invocation, with a guard method handle. * - * @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. + * @param invocation the method handle representing the invocation. Must not + * be null. + * @param guard the method handle representing the guard. Must have be + * compatible with the {@code invocation} handle as per + * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. + * For some useful guards, check out the {@link Guards} class. It can be + * null to represent an unconditional invocation. * @throws NullPointerException if invocation is null. */ public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard) { @@ -132,10 +145,14 @@ } /** - * Creates a new guarded invocation. + * Creates a new guarded invocation that can be invalidated by a switch + * point. * - * @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 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. It can be null. If it is null, this represents + * an unconditional invocation. * @throws NullPointerException if invocation is null. */ public GuardedInvocation(final MethodHandle invocation, final SwitchPoint switchPoint) { @@ -143,13 +160,19 @@ } /** - * Creates a new guarded invocation. + * Creates a new guarded invocation, with both a guard method handle and a + * switch point that can be used to invalidate it. * - * @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. + * @param invocation the method handle representing the invocation. Must + * not be null. + * @param guard the method handle representing the guard. Must have be + * compatible with the {@code invocation} handle as per + * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. + * 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. + * @param switchPoint the optional switch point that can be used to + * invalidate this linkage. * @throws NullPointerException if invocation is null. */ public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint) { @@ -157,15 +180,22 @@ } /** - * Creates a new guarded invocation. + * Creates a new guarded invocation, with a guard method handle, a + * switch point that can be used to invalidate it, and an exception that if + * thrown when invoked also invalidates it. * - * @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. - * @param exception the optional exception type that is expected to be thrown by the invocation and that also - * invalidates the linkage. + * @param invocation the method handle representing the invocation. Must not + * be null. + * @param guard the method handle representing the guard. Must have be + * compatible with the {@code invocation} handle as per + * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. + * For some useful guards, check out the {@link Guards} class. It can be + * null. If it and the switch point and the exception are all null, this + * represents an unconditional invocation. + * @param switchPoint the optional switch point that can be used to + * invalidate this linkage. + * @param exception the optional exception type that is when thrown by the + * invocation also invalidates it. * @throws NullPointerException if invocation is null. */ public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint, final Class exception) { @@ -176,15 +206,22 @@ } /** - * Creates a new guarded invocation + * Creates a new guarded invocation, with a guard method handle, any number + * of switch points that can be used to invalidate it, and an exception that + * if thrown when invoked also invalidates it. * - * @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 switchPoints the optional switch points that can be used to invalidate this linkage. - * @param exception the optional exception type that is expected to be thrown by the invocation and that also - * invalidates the linkage. + * @param invocation the method handle representing the invocation. Must not + * be null. + * @param guard the method handle representing the guard. Must have be + * compatible with the {@code invocation} handle as per + * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. + * For some useful guards, check out the {@link Guards} class. It can be + * null. If it and the exception are both null, and no switch points were + * specified, this represents an unconditional invocation. + * @param switchPoints optional switch points that can be used to + * invalidate this linkage. + * @param exception the optional exception type that is when thrown by the + * invocation also invalidates it. * @throws NullPointerException if invocation is null. */ public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint[] switchPoints, final Class exception) { @@ -213,26 +250,32 @@ } /** - * Returns the switch point that can be used to invalidate the invocation handle. + * Returns the switch points that can be used to invalidate the linkage of + * this invocation handle. * - * @return the switch point that can be used to invalidate the invocation handle. Can be null. + * @return the switch points that can be used to invalidate the linkage of + * this invocation handle. Can be null. */ public SwitchPoint[] getSwitchPoints() { return switchPoints == null ? null : switchPoints.clone(); } /** - * Returns the exception type that if thrown should be used to invalidate the linkage. + * Returns the exception type that if thrown by the invocation should + * invalidate the linkage of this guarded invocation. * - * @return the exception type that if thrown should be used to invalidate the linkage. Can be null. + * @return the exception type that if thrown should be used to invalidate + * the linkage. Can be null. */ public Class getException() { return exception; } /** - * 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. + * Returns true if and only if this guarded invocation has at least one + * invalidated switch point. + * @return true if and only if this guarded invocation has at least one + * invalidated switch point. */ public boolean hasBeenInvalidated() { if (switchPoints == null) { @@ -247,20 +290,6 @@ } /** - * 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(final 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 @@ -272,9 +301,10 @@ } /** - * Add a switchpoint to this guarded invocation - * @param newSwitchPoint new switchpoint, or null for nop - * @return new guarded invocation with the extra switchpoint + * Create a new guarded invocation with an added switch point. + * @param newSwitchPoint new switch point. Can be null in which case this + * method return the current guarded invocation with no changes. + * @return a guarded invocation with the added switch point. */ public GuardedInvocation addSwitchPoint(final SwitchPoint newSwitchPoint) { if (newSwitchPoint == null) { @@ -301,9 +331,11 @@ } /** - * 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. + * 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. */ @@ -312,9 +344,11 @@ } /** - * 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. + * 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. @@ -325,10 +359,13 @@ } /** - * Changes the type of the invocation, as if {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)} was - * applied to its invocation and {@link LinkerServices#asType(MethodHandle, MethodType)} applied to its guard, if it - * has one (with return type changed to boolean, and parameter count potentially truncated for the guard). If the - * invocation doesn't change its type, returns this object. + * Changes the type of the invocation, as if + * {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)} was + * applied to its invocation and + * {@link LinkerServices#asType(MethodHandle, MethodType)} applied to its + * guard, if it has one (with return type changed to boolean, and parameter + * count potentially truncated for the guard). If the invocation doesn't + * change its 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. @@ -339,9 +376,11 @@ } /** - * 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. + * 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. */ @@ -350,7 +389,8 @@ } /** - * Applies argument filters to both the invocation and the guard (if there is one). + * Applies argument filters to both the invocation and the guard (if there + * is one) with {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}. * @param pos the position of the first argument being filtered * @param filters the argument filters * @return a filtered invocation @@ -361,7 +401,8 @@ } /** - * Makes an invocation that drops arguments in both the invocation and the guard (if there is one). + * Makes an invocation that drops arguments in both the invocation and the + * guard (if there is one) with {@link MethodHandles#dropArguments(MethodHandle, int, List)}. * @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 @@ -372,7 +413,8 @@ } /** - * Makes an invocation that drops arguments in both the invocation and the guard (if there is one). + * Makes an invocation that drops arguments in both the invocation and the + * guard (if there is one) with {@link MethodHandles#dropArguments(MethodHandle, int, Class...)}. * @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 @@ -384,8 +426,11 @@ /** - * 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. + * Composes the invocation, guard, switch points, and the exception into a + * composite method handle that knows how to fall back when the guard fails + * or the invocation is invalidated. + * @param fallback the fallback method handle for when a switch point is + * invalidated, a guard returns false, or invalidating exception is thrown. * @return a composite method handle. */ public MethodHandle compose(final MethodHandle fallback) { @@ -393,10 +438,15 @@ } /** - * 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. - * @param catchFallback the fallback method in case the exception handler triggers + * Composes the invocation, guard, switch points, and the exception into a + * composite method handle that knows how to fall back when the guard fails + * or the invocation is invalidated. + * @param switchpointFallback the fallback method handle in case a switch + * point is invalidated. + * @param guardFallback the fallback method handle in case guard returns + * false. + * @param catchFallback the fallback method in case the exception handler + * triggers. * @return a composite method handle. */ public MethodHandle compose(final MethodHandle guardFallback, final MethodHandle switchpointFallback, final MethodHandle catchFallback) { @@ -411,7 +461,7 @@ final MethodHandle catchGuarded = exception == null ? guarded : - MH.catchException( + MethodHandles.catchException( guarded, exception, MethodHandles.dropArguments( @@ -430,10 +480,4 @@ return spGuarded; } - - private static void assertType(final MethodHandle mh, final MethodType type) { - if(!mh.type().equals(type)) { - throw new WrongMethodTypeException("Expected type: " + type + " actual type: " + mh.type()); - } - } } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocationTransformer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocationTransformer.java Thu Oct 22 11:12:39 2015 -0700 @@ -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.linker; + +import jdk.internal.dynalink.DynamicLinkerFactory; + +/** + * Interface for objects that are used to transform one guarded invocation into + * another one. Typical usage is for implementing + * {@link DynamicLinkerFactory#setPrelinkTransformer(GuardedInvocationTransformer) + * pre-link transformers}. + */ +@FunctionalInterface +public interface GuardedInvocationTransformer { + /** + * Given a guarded invocation, return either the same or potentially + * different guarded invocation. + * @param inv the original guarded invocation. + * @param linkRequest the link request for which the invocation was + * generated (usually by some linker). + * @param linkerServices the linker services that can be used during + * creation of a new invocation. + * @return either the passed guarded invocation or a different one, with + * the difference usually determined based on information in the link + * request and the differing invocation created with the assistance of the + * linker services. Whether or not {@code null} is an accepted return value + * is dependent on the user of the filter. + * @throws NullPointerException is allowed to be thrown by implementations + * if any of the passed arguments is null. + */ + public GuardedInvocation filter(GuardedInvocation inv, LinkRequest linkRequest, LinkerServices linkerServices); +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedTypeConversion.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedTypeConversion.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,118 +0,0 @@ -/* - * 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; - -/** - * Guarded type conversion - */ -public class GuardedTypeConversion { - private final GuardedInvocation conversionInvocation; - private final boolean cacheable; - - /** - * Constructor - * @param conversionInvocation guarded invocation for this type conversion - * @param cacheable is this invocation cacheable - */ - public GuardedTypeConversion(final GuardedInvocation conversionInvocation, final boolean cacheable) { - this.conversionInvocation = conversionInvocation; - this.cacheable = cacheable; - } - - /** - * Get the invocation - * @return invocation - */ - public GuardedInvocation getConversionInvocation() { - return conversionInvocation; - } - - /** - * Check if invocation is cacheable - * @return true if cacheable, false otherwise - */ - public boolean isCacheable() { - return cacheable; - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingDynamicLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingDynamicLinker.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingDynamicLinker.java Thu Oct 22 11:12:39 2015 -0700 @@ -83,32 +83,58 @@ package jdk.internal.dynalink.linker; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import java.util.List; +import jdk.internal.dynalink.DynamicLinkerFactory; + /** - * 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. + * 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 + * the linking logic for their own language as one or more + * {@link GuardingDynamicLinker} classes. They will typically set them as + * {@link DynamicLinkerFactory#setPrioritizedLinkers(List) prioritized linkers} + * in the {@code DynamicLinkerFactory} they configure for themselves, and maybe also + * set some as {@link DynamicLinkerFactory#setFallbackLinkers(List) fallback + * linkers} to handle language-specific "property not found" etc. conditions. + *

+ * Consider implementing {@link TypeBasedGuardingDynamicLinker} interface + * instead of this interface for those linkers that are based on the Java class + * of the objects. If you need to implement language-specific type conversions, + * have your {@code GuardingDynamicLinker} also implement the + * {@link GuardingTypeConverterFactory} interface. + *

+ * Languages can export linkers to other language runtimes for + * {@link DynamicLinkerFactory#setClassLoader(ClassLoader) automatic discovery} + * using a {@link GuardingDynamicLinkerExporter}. */ public interface GuardingDynamicLinker { /** - * Creates a guarded invocation appropriate for a particular invocation with the specified arguments at a call site. + * 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 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, as well as a - * {@link Throwable} subclass that describes an expected exception condition that also triggers relinking (often it - * is faster to rely on an infrequent but expected {@link ClassCastException} than on an always evaluated - * {@code instanceof} guard). 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. While the linker must produce an - * invocation with parameter types matching those in the call site descriptor of the link request, it should not try - * to match the return type expected at the call site except when it can do it with only the conversions that lose - * neither precision nor magnitude, see {@link LinkerServices#asTypeLosslessReturn(java.lang.invoke.MethodHandle, - * java.lang.invoke.MethodType)}. + * @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 any + * number of switch points for asynchronous invalidation of the linkage, as + * well as a {@link Throwable} subclass that describes an expected exception + * condition that also triggers relinking (often it is faster to rely on an + * infrequent but expected {@link ClassCastException} than on an always + * evaluated {@code instanceof} guard). While the linker must produce an + * invocation with parameter types matching those in the call site + * descriptor of the link request, it should not try to match the return + * type expected at the call site except when it can do it with only the + * conversions that lose neither precision nor magnitude, see + * {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)} for + * further explanation. * @throws Exception if the operation fails for whatever reason */ public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingDynamicLinkerExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingDynamicLinkerExporter.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.dynalink.linker; + +import java.security.Permission; +import java.util.List; +import java.util.ServiceLoader; +import java.util.function.Supplier; +import jdk.internal.dynalink.DynamicLinkerFactory; + +/** + * A class acting as a supplier of guarding dynamic linkers that can be + * automatically loaded by other language runtimes. Language runtimes wishing + * to export their own linkers should subclass this class and implement the + * {@link #get()} method to return a list of exported linkers and declare the + * subclass in + * {@code /META-INF/services/jdk.internal.dynalink.linker.GuardingDynamicLinkerExporter} + * resource of their distribution (typically, JAR file) so that dynamic linker + * factories can discover them using the {@link ServiceLoader} mechanism. Note + * that instantiating this class is tied to a security check for the + * {@code RuntimePermission("dynalink.exportLinkersAutomatically")} when a + * security manager is present, to ensure that only trusted runtimes can + * automatically export their linkers into other runtimes. + * @see DynamicLinkerFactory#setClassLoader(ClassLoader) + */ +public abstract class GuardingDynamicLinkerExporter implements Supplier> { + /** + * The name of the runtime permission for creating instances of this class. + * Granting this permission to a language runtime allows it to export its + * linkers for automatic loading into other language runtimes. + */ + public static final String AUTOLOAD_PERMISSION_NAME = "dynalink.exportLinkersAutomatically"; + + private static final Permission AUTOLOAD_PERMISSION = new RuntimePermission(AUTOLOAD_PERMISSION_NAME); + + /** + * Creates a new linker exporter. If there is a security manager installed + * checks for the + * {@code RuntimePermission("dynalink.exportLinkersAutomatically")} runtime + * permission. This ensures only language runtimes granted this permission + * will be allowed to export their linkers for automatic loading. + * @throws SecurityException if the necessary runtime permission is not + * granted. + */ + protected GuardingDynamicLinkerExporter() { + final SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(AUTOLOAD_PERMISSION); + } + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingTypeConverterFactory.java Thu Oct 22 11:12:39 2015 -0700 @@ -83,30 +83,65 @@ package jdk.internal.dynalink.linker; -import jdk.internal.dynalink.support.TypeUtilities; +import java.lang.invoke.MethodHandles; +import java.util.function.Supplier; +import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.beans.BeansLinker; +import jdk.internal.dynalink.linker.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. + * Optional interface that can be implemented by {@link GuardingDynamicLinker} + * implementations to provide language-specific 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 for {@link BeansLinker} in + * selecting the correct overload when trying to link to an overloaded Java + * method. */ public interface GuardingTypeConverterFactory { /** - * Returns a guarded type conversion 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. + * Returns a guarded type conversion that receives a value of the specified + * source type and returns a value converted to the specified target type. + * Value types can be either primitives or reference types, including + * interfaces, so you can even provide converters for converting your + * language's objects to Java interfaces and classes by generating adapters + * for them. + *

+ * The type of the invocation is {@code targetType(sourceType)}, while the + * type of the guard is {@code boolean(sourceType)}. You are allowed to + * return unconditional invocations (with no guard) if the source type is + * specific to your runtime and your runtime only. + *

Note that this method 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. + *

Dynalink is at liberty to either cache some of the returned converters + * or to repeatedly request the converter factory to create the same + * conversion. * * @param sourceType source type * @param targetType the target type. - * @return a guarded type conversion that contains a guarded invocation that can take an object (if it passes guard) - * and return 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). + * @param lookupSupplier a supplier for retrieving the lookup of the class + * on whose behalf a type converter is requested. When a converter is + * requested as part of linking an {@code invokedynamic} instruction the + * supplier will return the lookup passed to the bootstrap method, otherwise + * it will return the public lookup. A typical case where the lookup might + * be needed is when the converter creates a Java adapter class on the fly + * (e.g. to convert some object from the dynamic language into a Java + * interface for interoperability). Invoking the {@link Supplier#get()} + * method on the passed supplier will be subject to the same security checks + * as {@link CallSiteDescriptor#getLookup()}. An implementation should avoid + * retrieving the lookup if it is not needed so as to avoid the expense of + * {@code AccessController.doPrivileged} call. + * @return a guarded invocation that can take an object (if it passes guard) + * and return 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 GuardedTypeConversion convertToType(Class sourceType, Class targetType) throws Exception; + public GuardedInvocation convertToType(Class sourceType, Class targetType, Supplier lookupSupplier) throws Exception; } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/LinkRequest.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/LinkRequest.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/LinkRequest.java Thu Oct 22 11:12:39 2015 -0700 @@ -84,11 +84,14 @@ package jdk.internal.dynalink.linker; import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.DynamicLinker; 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}. + * Represents a request to link a particular invocation at a particular call + * site. Instances of these requests will be constructed and passed to all + * {@link GuardingDynamicLinker} objects managed by the {@link DynamicLinker} + * that is trying to link the call site. */ public interface LinkRequest { /** @@ -99,65 +102,35 @@ public CallSiteDescriptor getCallSiteDescriptor(); /** - * Returns the call site token for the call site being linked. This token is an opaque object that is guaranteed to - * have different identity for different call sites, and is also guaranteed to not become weakly reachable before - * the call site does and to become weakly reachable some time after the call site does. This makes it ideal as a - * candidate for a key in a weak hash map in which a linker might want to keep per-call site linking state (usually - * profiling information). - * - * @return the call site token for the call site being linked. - */ - public Object getCallSiteToken(); - - /** - * 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. + * Returns the arguments for the invocation being linked. The returned array + * must be a clone; modifications to it must not 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. + * Returns the first argument for the invocation being linked; this is + * typically the receiver object. This is a shorthand for + * {@code getArguments()[0]} that also avoids the cloning of the arguments + * array. * * @return the receiver object. */ public Object getReceiver(); /** - * Returns the number of times this callsite has been linked/relinked. This can be useful if you want to - * change e.g. exception based relinking to guard based relinking. It's probably not a good idea to keep, - * for example, expensive exception throwing relinkage based on failed type checks/ClassCastException in - * a nested callsite tree where the exception is thrown repeatedly for the common case. There it would be - * much more performant to use exact type guards instead. - * - * @return link count for call site - */ - public int getLinkCount(); - - /** * 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. + * causes a less effective version of an operation to be linked. This is just a hint, though, and linkers are + * allowed 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 @@ -165,5 +138,5 @@ * @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); + public LinkRequest replaceArguments(CallSiteDescriptor callSiteDescriptor, Object... arguments); } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/LinkerServices.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/LinkerServices.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/LinkerServices.java Thu Oct 22 11:12:39 2015 -0700 @@ -89,44 +89,54 @@ import jdk.internal.dynalink.DynamicLinker; import jdk.internal.dynalink.DynamicLinkerFactory; import jdk.internal.dynalink.linker.ConversionComparator.Comparison; -import jdk.internal.dynalink.support.TypeUtilities; +import jdk.internal.dynalink.linker.support.TypeUtilities; /** - * 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. + * Interface for services provided to {@link GuardingDynamicLinker} instances by + * the {@link DynamicLinker} that owns them. */ 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. + * Similar to {@link MethodHandle#asType(MethodType)} except it also hooks + * in method handles produced by all available + * {@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)}, - * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}, and - * {@link MethodHandles#filterReturnValue(MethodHandle, MethodHandle)} with - * {@link GuardingTypeConverterFactory}-produced type converters as filters. + * @return a method handle that is a suitable combination of + * {@link MethodHandle#asType(MethodType)}, + * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}, + * and {@link MethodHandles#filterReturnValue(MethodHandle, MethodHandle)} + * with {@link GuardingTypeConverterFactory}-produced type converters as + * filters. */ public MethodHandle asType(MethodHandle handle, MethodType fromType); /** - * Similar to {@link #asType(MethodHandle, MethodType)} except it only converts the return type of the method handle - * when it can be done using a conversion that loses neither precision nor magnitude, otherwise it leaves it - * unchanged. The idea is that other conversions should not be performed by individual linkers, but instead the - * {@link DynamicLinkerFactory#setPrelinkFilter(jdk.internal.dynalink.GuardedInvocationFilter) pre-link filter of - * the dynamic linker} should implement the strategy of dealing with potentially lossy return type conversions in a - * manner specific to the language runtime. + * Similar to {@link #asType(MethodHandle, MethodType)} except it treats + * return value type conversion specially. It only converts the return type + * of the method handle when it can be done using a conversion that loses + * neither precision nor magnitude, otherwise it leaves it unchanged. These + * are the only return value conversions that should be performed by + * individual language-specific linkers, and + * {@link DynamicLinkerFactory#setPrelinkTransformer(GuardedInvocationTransformer) + * pre-link transformer of the dynamic linker} should implement the strategy + * for dealing with potentially lossy return type conversions in a manner + * specific to the language runtime where the call site is located. * * @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. + * @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 default MethodHandle asTypeLosslessReturn(final MethodHandle handle, final MethodType fromType) { final Class handleReturnType = handle.type().returnType(); @@ -135,11 +145,13 @@ } /** - * 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. + * 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 and should mostly rely on + * {@link #asType(MethodHandle, MethodType)} instead. This method is needed + * when you need to reuse existing type conversion machinery outside the + * context of processing a link request. * @param sourceType the type to convert from * @param targetType the type to convert to * @return a method handle performing the conversion. @@ -147,11 +159,13 @@ 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. + * 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 for all values (especially 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 @@ -160,34 +174,47 @@ 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. + * Creates a guarded invocation delegating back to the {@link DynamicLinker} + * that exposes this linker services object. The dynamic linker will then + * itself delegate the linking to all of its managed + * {@link GuardingDynamicLinker}s including potentially this one if no + * linker responds earlier, so beware of infinite recursion. You'll + * typically craft the link request so that it will be different than the + * one you are currently trying to link. * * @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. + * @return a guarded invocation linked by some of the guarding dynamic + * linkers managed by the top-level dynamic linker. Can be null if no + * available linker is able to link the invocation. You will typically use + * the elements of the returned invocation to compose your own 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. + * 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. + * @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); /** - * Modifies the method handle so that any parameters that can receive potentially internal language runtime objects - * will have a filter added on them to prevent them from escaping, potentially by wrapping them. - * It can also potentially add an unwrapping filter to the return value. + * Modifies the method handle so that any parameters that can receive + * potentially internal language runtime objects will have a filter added on + * them to prevent them from escaping, potentially by wrapping them. It can + * also potentially add an unwrapping filter to the return value. Basically + * transforms the method handle using the transformer configured by + * {@link DynamicLinkerFactory#setInternalObjectsFilter(MethodHandleTransformer)}. * @param target the target method handle - * @return a method handle with parameters and/or return type potentially filtered for wrapping and unwrapping. + * @return a method handle with parameters and/or return type potentially + * filtered for wrapping and unwrapping. */ public MethodHandle filterInternalObjects(final MethodHandle target); } diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/MethodHandleTransformer.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/MethodHandleTransformer.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/MethodHandleTransformer.java Thu Oct 22 11:12:39 2015 -0700 @@ -84,10 +84,15 @@ package jdk.internal.dynalink.linker; import java.lang.invoke.MethodHandle; +import jdk.internal.dynalink.DynamicLinkerFactory; /** * A generic interface describing operations that transform method handles. + * Typical usage is for implementing + * {@link DynamicLinkerFactory#setInternalObjectsFilter(MethodHandleTransformer) + * internal objects filters}. */ +@FunctionalInterface public interface MethodHandleTransformer { /** * Transforms a method handle. diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/MethodTypeConversionStrategy.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/MethodTypeConversionStrategy.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/MethodTypeConversionStrategy.java Thu Oct 22 11:12:39 2015 -0700 @@ -85,10 +85,16 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; +import jdk.internal.dynalink.DynamicLinkerFactory; /** - * Interface for objects representing a strategy for converting a method handle to a new type. + * Interface for objects representing a strategy for converting a method handle + * to a new type. Typical usage is for customizing a language runtime's handling + * of + * {@link DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy) + * method invocation conversions}. */ +@FunctionalInterface public interface MethodTypeConversionStrategy { /** * Converts a method handle to a new type. diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/TypeBasedGuardingDynamicLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/TypeBasedGuardingDynamicLinker.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/TypeBasedGuardingDynamicLinker.java Thu Oct 22 11:12:39 2015 -0700 @@ -83,11 +83,14 @@ package jdk.internal.dynalink.linker; +import jdk.internal.dynalink.linker.support.CompositeTypeBasedGuardingDynamicLinker; + /** * 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 + * argument at linking invocation time. (The first argument is usually the receiver). 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. + * a specific language-native interface or superclass. The linker mechanism can optimize the dispatch for these linkers, + * see {@link CompositeTypeBasedGuardingDynamicLinker}. */ public interface TypeBasedGuardingDynamicLinker extends GuardingDynamicLinker { /** diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/package-info.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015, 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. +*/ + +/** + *

+ * Contains interfaces and classes needed by language runtimes to implement + * their own language-specific object models and type conversions. The main + * entry point is the + * {@link jdk.internal.dynalink.linker.GuardingDynamicLinker} interface. It needs to be + * implemented in order to provide linking for the runtime's own object model. + * A language runtime can have more than one guarding dynamic linker + * implementation. When a runtime is configuring Dynalink for itself, it will + * normally set these guarding linkers as the prioritized linkers in its + * {@link jdk.internal.dynalink.DynamicLinkerFactory} (and maybe some of them as fallback + * linkers, for e.g. handling "method not found" and similar errors in a + * language-specific manner if no other linker managed to handle the operation.) + *

+ * A language runtime that wishes to make at least some of its linkers available + * to other language runtimes for interoperability will need to declare the + * class names of those linkers in + * {@code /META-INF/services/jdk.internal.dynalink.linker.GuardingDynamicLinker} file in + * its distribution (typically, JAR file). + *

+ * Most language runtimes will be able to implement their own linking logic by + * implementing {@link jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker} + * instead of {@link jdk.internal.dynalink.linker.GuardingDynamicLinker}; it allows for + * faster type-based linking dispatch. + *

+ * Language runtimes that allow type conversions other than those provided by + * Java will need to have their guarding dynamic linker (or linkers) also + * implement the {@link jdk.internal.dynalink.linker.GuardingTypeConverterFactory} + * interface to provide the logic for these conversions. + *

+ * @since 1.9 + */ +@jdk.Exported +package jdk.internal.dynalink.linker; diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/package.html --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/package.html Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,87 +0,0 @@ - - - - -

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

- diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/CompositeGuardingDynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/CompositeGuardingDynamicLinker.java Thu Oct 22 11:12:39 2015 -0700 @@ -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.linker.support; + +import java.io.Serializable; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +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 in its + * {@link #getGuardedInvocation(LinkRequest, LinkerServices)}. + */ +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. + * @throws NullPointerException if {@code linkers} or any of its elements + * are null. + */ + public CompositeGuardingDynamicLinker(final Iterable linkers) { + final List l = new LinkedList<>(); + for(final GuardingDynamicLinker linker: linkers) { + l.add(Objects.requireNonNull(linker)); + } + this.linkers = l.toArray(new GuardingDynamicLinker[l.size()]); + } + + /** + * Delegates the call to its component linkers. The first non-null value + * returned from a component linker is returned. If no component linker + * returns a non-null invocation, null is returned. + * @param linkRequest the object describing the request for linking a + * particular invocation + * @param linkerServices linker services + * @return the first non-null return value from a component linker, or null + * if none of the components returned a non-null. + */ + @Override + public GuardedInvocation getGuardedInvocation(final 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; + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,240 @@ +/* + * 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.support; + +import java.io.Serializable; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +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. + */ +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", "rawtypes"}) + ClassToLinker(final TypeBasedGuardingDynamicLinker[] linkers) { + this.linkers = linkers; + singletonLinkers = new List[linkers.length]; + for(int i = 0; i < linkers.length; ++i) { + singletonLinkers[i] = Collections.singletonList(linkers[i]); + } + } + + @SuppressWarnings("fallthrough") + @Override + protected List computeValue(final 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); + } + default: { + list.add(linker); + } + } + } + } + return list; + } + } + + private final ClassValue> classToLinker; + + /** + * Creates a new composite type-based linker. + * + * @param linkers the component linkers + * @throws NullPointerException if {@code linkers} or any of its elements + * are null. + */ + public CompositeTypeBasedGuardingDynamicLinker(final Iterable linkers) { + final List l = new LinkedList<>(); + for(final TypeBasedGuardingDynamicLinker linker: linkers) { + l.add(Objects.requireNonNull(linker)); + } + this.classToLinker = new ClassToLinker(l.toArray(new TypeBasedGuardingDynamicLinker[l.size()])); + } + + /** + * Returns true if at least one of the composite linkers returns true from + * {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)} for the type. + * @param type the type to link + * @return true true if at least one of the composite linkers returns true + * from {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)}, false + * otherwise. + */ + @Override + public boolean canLinkType(final Class type) { + return !classToLinker.get(type).isEmpty(); + } + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) + throws Exception { + final Object obj = linkRequest.getReceiver(); + if(obj == null) { + return null; + } + for(final 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 + * @throws NullPointerException if {@code linkers} or any of its elements + * are null. + */ + public static List optimize(final Iterable linkers) { + final List llinkers = new LinkedList<>(); + final List tblinkers = new LinkedList<>(); + for(final GuardingDynamicLinker linker: linkers) { + Objects.requireNonNull(linker); + if(linker instanceof TypeBasedGuardingDynamicLinker) { + tblinkers.add((TypeBasedGuardingDynamicLinker)linker); + } else { + addTypeBased(llinkers, tblinkers); + llinkers.add(linker); + } + } + addTypeBased(llinkers, tblinkers); + return llinkers; + } + + private static void addTypeBased(final List llinkers, + final 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; + } + } + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/DefaultInternalObjectFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/DefaultInternalObjectFilter.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2015, 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-2015 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.support; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import jdk.internal.dynalink.DynamicLinkerFactory; +import jdk.internal.dynalink.linker.MethodHandleTransformer; + +/** + * Default implementation for a + * {@link DynamicLinkerFactory#setInternalObjectsFilter(MethodHandleTransformer)} + * that delegates to a pair of filtering method handles. It takes a method + * handle of {@code Object(Object)} type for filtering parameter values and + * another one of the same type for filtering return values. It applies them as + * parameter and return value filters on method handles passed to its + * {@link #transform(MethodHandle)} method, on those parameters and return values + * that are declared to have type {@link Object}. Also handles + * {@link MethodHandle#isVarargsCollector() method handles that support variable + * arity calls} with a last {@code Object[]} parameter. You can broadly think of + * the parameter filter as being a wrapping method for exposing internal runtime + * objects wrapped into an adapter with some public interface, and the return + * value filter as being its inverse unwrapping method. + */ +public class DefaultInternalObjectFilter implements MethodHandleTransformer { + private static final MethodHandle FILTER_VARARGS = new Lookup(MethodHandles.lookup()).findStatic( + DefaultInternalObjectFilter.class, "filterVarArgs", MethodType.methodType(Object[].class, MethodHandle.class, Object[].class)); + + private final MethodHandle parameterFilter; + private final MethodHandle returnFilter; + private final MethodHandle varArgFilter; + + /** + * Creates a new filter. + * @param parameterFilter the filter for method parameters. Must be of type + * {@code Object(Object)}, or {@code null}. + * @param returnFilter the filter for return values. Must be of type + * {@code Object(Object)}, or {@code null}. + * @throws IllegalArgumentException if one or both filters are not of the + * expected type. + */ + public DefaultInternalObjectFilter(final MethodHandle parameterFilter, final MethodHandle returnFilter) { + this.parameterFilter = checkHandle(parameterFilter, "parameterFilter"); + this.returnFilter = checkHandle(returnFilter, "returnFilter"); + this.varArgFilter = parameterFilter == null ? null : FILTER_VARARGS.bindTo(parameterFilter); + } + + @Override + public MethodHandle transform(final MethodHandle target) { + assert target != null; + MethodHandle[] filters = null; + final MethodType type = target.type(); + final boolean isVarArg = target.isVarargsCollector(); + final int paramCount = type.parameterCount(); + final MethodHandle paramsFiltered; + // Filter parameters + if (parameterFilter != null) { + int firstFilter = -1; + // Ignore receiver, start from argument 1 + for(int i = 1; i < paramCount; ++i) { + final Class paramType = type.parameterType(i); + final boolean filterVarArg = isVarArg && i == paramCount - 1 && paramType == Object[].class; + if (filterVarArg || paramType == Object.class) { + if (filters == null) { + firstFilter = i; + filters = new MethodHandle[paramCount - firstFilter]; + } + filters[i - firstFilter] = filterVarArg ? varArgFilter : parameterFilter; + } + } + paramsFiltered = filters != null ? MethodHandles.filterArguments(target, firstFilter, filters) : target; + } else { + paramsFiltered = target; + } + // Filter return value if needed + final MethodHandle returnFiltered = returnFilter != null && type.returnType() == Object.class ? MethodHandles.filterReturnValue(paramsFiltered, returnFilter) : paramsFiltered; + // Preserve varargs collector state + return isVarArg && !returnFiltered.isVarargsCollector() ? returnFiltered.asVarargsCollector(type.parameterType(paramCount - 1)) : returnFiltered; + + } + + private static MethodHandle checkHandle(final MethodHandle handle, final String handleKind) { + if (handle != null) { + final MethodType objectObjectType = MethodType.methodType(Object.class, Object.class); + if (!handle.type().equals(objectObjectType)) { + throw new IllegalArgumentException("Method type for " + handleKind + " must be " + objectObjectType); + } + } + return handle; + } + + @SuppressWarnings("unused") + private static Object[] filterVarArgs(final MethodHandle parameterFilter, final Object[] args) throws Throwable { + Object[] newArgs = null; + for(int i = 0; i < args.length; ++i) { + final Object arg = args[i]; + final Object newArg = parameterFilter.invokeExact(arg); + if (arg != newArg) { + if (newArgs == null) { + newArgs = args.clone(); + } + newArgs[i] = newArg; + } + } + return newArgs == null ? args : newArgs; + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/Guards.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/Guards.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,338 @@ +/* + * 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.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.DynamicLinker; +import jdk.internal.dynalink.linker.LinkerServices; + +/** + * Utility methods for creating typical guards for + * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)} + * and for adjusting their method types. + */ +public final 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(final Class clazz, final MethodType type) { + final Class declaredType = type.parameterType(0); + if(clazz == declaredType) { + LOG.log(Level.WARNING, "isOfClassGuardAlwaysTrue", new Object[] { clazz.getName(), 0, type, DynamicLinker.getLinkedCallSiteLocation() }); + return constantTrue(type); + } + if(!declaredType.isAssignableFrom(clazz)) { + LOG.log(Level.WARNING, "isOfClassGuardAlwaysFalse", new Object[] { clazz.getName(), 0, type, DynamicLinker.getLinkedCallSiteLocation() }); + 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(final Class clazz, final 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(final Class clazz, final int pos, final MethodType type) { + final Class declaredType = type.parameterType(pos); + if(clazz.isAssignableFrom(declaredType)) { + LOG.log(Level.WARNING, "isInstanceGuardAlwaysTrue", new Object[] { clazz.getName(), pos, type, DynamicLinker.getLinkedCallSiteLocation() }); + return constantTrue(type); + } + if(!declaredType.isAssignableFrom(clazz)) { + LOG.log(Level.WARNING, "isInstanceGuardAlwaysFalse", new Object[] { clazz.getName(), pos, type, DynamicLinker.getLinkedCallSiteLocation() }); + 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(final int pos, final MethodType type) { + final Class declaredType = type.parameterType(pos); + if(declaredType.isArray()) { + LOG.log(Level.WARNING, "isArrayGuardAlwaysTrue", new Object[] { pos, type, DynamicLinker.getLinkedCallSiteLocation() }); + return constantTrue(type); + } + if(!declaredType.isAssignableFrom(Object[].class)) { + LOG.log(Level.WARNING, "isArrayGuardAlwaysFalse", new Object[] { pos, type, DynamicLinker.getLinkedCallSiteLocation() }); + return constantFalse(type); + } + return asType(IS_ARRAY, pos, type); + } + + private static MethodHandle getClassBoundArgumentTest(final MethodHandle test, final Class clazz, final int pos, final MethodType type) { + // Bind the class to the first argument of the test + return asType(test.bindTo(clazz), pos, type); + } + + /** + * Takes a method handle intended to be used as a guard, and adapts it to + * the requested type, but returning a boolean. Applies + * {@link MethodHandle#asType(MethodType)} to convert types and uses + * {@link MethodHandles#dropArguments(MethodHandle, int, Class...)} to match + * the requested type arity. + * @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(final MethodHandle test, final MethodType type) { + return test.asType(getTestType(test, type)); + } + + /** + * Takes a method handle intended to be used as a guard, and adapts it to + * the requested type, but returning a boolean. Applies + * {@link LinkerServices#asType(MethodHandle, MethodType)} to convert types + * and uses + * {@link MethodHandles#dropArguments(MethodHandle, int, Class...)} to match + * the requested type arity. + * @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(final LinkerServices linkerServices, final MethodHandle test, final MethodType type) { + return linkerServices.asType(test, getTestType(test, type)); + } + + private static MethodType getTestType(final MethodHandle test, final MethodType type) { + return type.dropParameterTypes(test.type().parameterCount(), + type.parameterCount()).changeReturnType(boolean.class); + } + + private static MethodHandle asType(final MethodHandle test, final int pos, final 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_INSTANCE = Lookup.PUBLIC.findVirtual(Class.class, "isInstance", + MethodType.methodType(Boolean.TYPE, Object.class)); + + private static final MethodHandle IS_OF_CLASS; + private static final MethodHandle IS_ARRAY; + private static final MethodHandle IS_IDENTICAL; + private static final MethodHandle IS_NULL; + private static final MethodHandle IS_NOT_NULL; + + static { + final Lookup lookup = new Lookup(MethodHandles.lookup()); + + IS_OF_CLASS = lookup.findOwnStatic("isOfClass", Boolean.TYPE, Class.class, Object.class); + IS_ARRAY = lookup.findOwnStatic("isArray", Boolean.TYPE, Object.class); + IS_IDENTICAL = lookup.findOwnStatic("isIdentical", Boolean.TYPE, Object.class, Object.class); + IS_NULL = lookup.findOwnStatic("isNull", Boolean.TYPE, Object.class); + IS_NOT_NULL = lookup.findOwnStatic("isNotNull", 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(final 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(final 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(final 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(final Object obj) { + return obj == null; + } + + @SuppressWarnings("unused") + private static boolean isNotNull(final Object obj) { + return obj != null; + } + + @SuppressWarnings("unused") + private static boolean isArray(final Object o) { + return o != null && o.getClass().isArray(); + } + + @SuppressWarnings("unused") + private static boolean isOfClass(final Class c, final Object o) { + return o != null && o.getClass() == c; + } + + @SuppressWarnings("unused") + private static boolean isIdentical(final Object o1, final Object o2) { + return o1 == o2; + } + + private static MethodHandle constantTrue(final MethodType type) { + return constantBoolean(Boolean.TRUE, type); + } + + private static MethodHandle constantFalse(final MethodType type) { + return constantBoolean(Boolean.FALSE, type); + } + + private static MethodHandle constantBoolean(final Boolean value, final MethodType type) { + return MethodHandles.permuteArguments(MethodHandles.constant(Boolean.TYPE, value), + type.changeReturnType(Boolean.TYPE)); + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/Lookup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/Lookup.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,401 @@ +/* + * 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.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; + +/** + * A wrapper around {@link java.lang.invoke.MethodHandles.Lookup} that masks + * checked exceptions. It is useful in those cases when you're looking up + * methods within your own codebase (therefore it is an error if they are not + * present). + */ +public final 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(final 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. + * @throws IllegalAccessError if the method is inaccessible. + */ + public MethodHandle unreflect(final Method m) { + return unreflect(lookup, m); + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, + * converting any encountered {@link IllegalAccessException} into an + * {@link IllegalAccessError}. + * + * @param lookup the lookup used to unreflect + * @param m the method to unreflect + * @return the unreflected method handle. + * @throws IllegalAccessError if the method is inaccessible. + */ + public static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) { + try { + return lookup.unreflect(m); + } catch(final 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. + * @throws IllegalAccessError if the getter is inaccessible. + */ + public MethodHandle unreflectGetter(final Field f) { + try { + return lookup.unreflectGetter(f); + } catch(final 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(final Classrefc, final String name, final Class type) { + try { + return lookup.findGetter(refc, name, type); + } catch(final 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(final 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. + * @throws IllegalAccessError if the field is inaccessible. + * @throws NoSuchFieldError if the field does not exist. + */ + public MethodHandle unreflectSetter(final Field f) { + try { + return lookup.unreflectSetter(f); + } catch(final 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. + * @throws IllegalAccessError if the constructor is inaccessible. + */ + public MethodHandle unreflectConstructor(final Constructor c) { + return unreflectConstructor(lookup, c); + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, + * converting any encountered {@link IllegalAccessException} into an + * {@link IllegalAccessError}. + * + * @param lookup the lookup used to unreflect + * @param c the constructor to unreflect + * @return the unreflected constructor handle. + * @throws IllegalAccessError if the constructor is inaccessible. + */ + public static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor c) { + try { + return lookup.unreflectConstructor(c); + } catch(final IllegalAccessException e) { + final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect constructor " + c); + ee.initCause(e); + throw ee; + } + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findSpecial(Class, String, MethodType, Class)} + * on the underlying lookup. Converts any encountered + * {@link IllegalAccessException} into an {@link IllegalAccessError} and + * {@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(final Class declaringClass, final String name, final MethodType type) { + try { + return lookup.findSpecial(declaringClass, name, type, declaringClass); + } catch(final IllegalAccessException e) { + final IllegalAccessError ee = new IllegalAccessError("Failed to access special method " + methodDescription( + declaringClass, name, type)); + ee.initCause(e); + throw ee; + } catch(final 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(final Class declaringClass, final String name, final MethodType type) { + return declaringClass.getName() + "#" + name + type; + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findStatic(Class, String, MethodType)} + * on the underlying lookup. Converts any encountered + * {@link IllegalAccessException} into an {@link IllegalAccessError} and + * {@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(final Class declaringClass, final String name, final MethodType type) { + try { + return lookup.findStatic(declaringClass, name, type); + } catch(final IllegalAccessException e) { + final IllegalAccessError ee = new IllegalAccessError("Failed to access static method " + methodDescription( + declaringClass, name, type)); + ee.initCause(e); + throw ee; + } catch(final NoSuchMethodException e) { + final NoSuchMethodError ee = new NoSuchMethodError("Failed to find static method " + methodDescription( + declaringClass, name, type)); + ee.initCause(e); + throw ee; + } + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findVirtual(Class, String, MethodType)} + * on the underlying lookup. Converts any encountered + * {@link IllegalAccessException} into an {@link IllegalAccessError} and + * {@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(final Class declaringClass, final String name, final MethodType type) { + try { + return lookup.findVirtual(declaringClass, name, type); + } catch(final IllegalAccessException e) { + final IllegalAccessError ee = new IllegalAccessError("Failed to access virtual method " + methodDescription( + declaringClass, name, type)); + ee.initCause(e); + throw ee; + } catch(final 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(final MethodHandles.Lookup lookup, final String name, final Class rtype, final 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 also more convenient 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(final String name, final Class rtype, final 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(final MethodHandles.Lookup lookup, final String name, final Class rtype, final 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(final String name, final Class rtype, final Class... ptypes) { + return findStatic(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes)); + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/SimpleLinkRequest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/SimpleLinkRequest.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,140 @@ +/* + * 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.support; + +import java.util.Objects; +import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.linker.LinkRequest; + +/** + * Default simple implementation of {@link LinkRequest}. + */ +public class SimpleLinkRequest 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. + * Must not be null. + * @param callSiteUnstable true if the call site being linked is considered + * unstable. + * @param arguments the arguments for the invocation. Must not be null. + * @throws NullPointerException if either {@code callSiteDescriptor} or + * {@code arguments} is null. + */ + public SimpleLinkRequest(final CallSiteDescriptor callSiteDescriptor, final boolean callSiteUnstable, final Object... arguments) { + this.callSiteDescriptor = Objects.requireNonNull(callSiteDescriptor); + this.callSiteUnstable = callSiteUnstable; + this.arguments = arguments.clone(); + } + + @Override + public Object[] getArguments() { + return arguments.clone(); + } + + @Override + public Object getReceiver() { + return arguments.length > 0 ? arguments[0] : null; + } + + @Override + public CallSiteDescriptor getCallSiteDescriptor() { + return callSiteDescriptor; + } + + @Override + public boolean isCallSiteUnstable() { + return callSiteUnstable; + } + + @Override + public LinkRequest replaceArguments(final CallSiteDescriptor newCallSiteDescriptor, final Object... newArguments) { + return new SimpleLinkRequest(newCallSiteDescriptor, callSiteUnstable, newArguments); + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/TypeUtilities.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/TypeUtilities.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,349 @@ +/* + * 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.support; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Map; +import jdk.internal.dynalink.DynamicLinkerFactory; +import jdk.internal.dynalink.linker.MethodTypeConversionStrategy; + +/** + * Various static utility methods for working with Java types. + */ +public class TypeUtilities { + static final Class OBJECT_CLASS = Object.class; + + private TypeUtilities() { + } + + 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(Void.TYPE, Void.class); + 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(final Collection> classes) { + final Map> map = new HashMap<>(); + for(final Class clazz: classes) { + map.put(clazz.getName(), clazz); + } + return map; + } + + private static Map invertMap(final Map map) { + final Map inverted = new IdentityHashMap<>(map.size()); + for(final 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 sourceType the type being converted from (call site type for parameter types, method type for return types) + * @param targetType the parameter type being converted to (method type for parameter types, call site type for return types) + * @return true if source type is method invocation convertible to target type. + */ + public static boolean isMethodInvocationConvertible(final Class sourceType, final Class targetType) { + if(targetType.isAssignableFrom(sourceType)) { + return true; + } + if(sourceType.isPrimitive()) { + if(targetType.isPrimitive()) { + return isProperPrimitiveSubtype(sourceType, targetType); + } + return isBoxingAndWideningReferenceConversion(sourceType, targetType); + } + if(targetType.isPrimitive()) { + final Class unboxedCallSiteType = getPrimitiveType(sourceType); + return unboxedCallSiteType != null + && (unboxedCallSiteType == targetType || isProperPrimitiveSubtype(unboxedCallSiteType, targetType)); + } + return false; + } + + private static boolean isBoxingAndWideningReferenceConversion(final Class sourceType, final Class targetType) { + final Class wrapperType = getWrapperType(sourceType); + assert wrapperType != null : sourceType.getName(); + return targetType.isAssignableFrom(wrapperType); + } + + /** + * Determines whether a type can be converted to another without losing any + * precision. As a special case, void is considered convertible only to void + * and {@link Object} (either as {@code null} or as a custom value set in + * {@link DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy)}). + * Somewhat unintuitively, we consider anything to be convertible to void + * even though converting to void causes the ultimate loss of data. On the + * other hand, conversion to void essentially means that the value is of no + * interest and should be discarded, thus there's no expectation of + * preserving any precision. + * + * @param sourceType the source type + * @param targetType the target type + * @return true if lossless conversion is possible + */ + public static boolean isConvertibleWithoutLoss(final Class sourceType, final Class targetType) { + if(targetType.isAssignableFrom(sourceType) || targetType == void.class) { + return true; + } + if(sourceType.isPrimitive()) { + if(sourceType == void.class) { + // Void should be losslessly representable by Object, either as null or as a custom value that + // can be set with DynamicLinkerFactory.setAutoConversionStrategy. + return targetType == Object.class; + } + if(targetType.isPrimitive()) { + return isProperPrimitiveLosslessSubtype(sourceType, targetType); + } + return isBoxingAndWideningReferenceConversion(sourceType, targetType); + } + // Can't convert from any non-primitive type to any primitive type without data loss because of null. + // Also, can't convert non-assignable reference types. + 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(final Class subType, final 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(final Class subType, final 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; + } + + /** + * Similar to {@link #isProperPrimitiveSubtype(Class, Class)}, except it disallows conversions from int and long to + * float, and from long to double, as those can lose precision. It also disallows conversion from and to char and + * anything else (similar to boolean) as char is not meant to be an arithmetic type. + * @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 that can be represented + * by the supertype without no precision loss. + */ + private static boolean isProperPrimitiveLosslessSubtype(final Class subType, final Class superType) { + if(superType == boolean.class || subType == boolean.class) { + return false; + } + if(superType == char.class || subType == char.class) { + return false; + } + if(subType == byte.class) { + return true; + } + if(subType == short.class) { + return superType != byte.class; + } + if(subType == int.class) { + return superType == long.class || superType == double.class; + } + if(subType == float.class) { + return superType == double.class; + } + return false; + } + + /** + * Given a name of a primitive type 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. + */ + public static Class getPrimitiveTypeByName(final 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(final Class wrapperType) { + return 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(final Class primitiveType) { + return WRAPPER_TYPES.get(primitiveType); + } + + /** + * Returns true if the passed type is a wrapper for a primitive type. + * @param type the examined type + * @return true if the passed type is a wrapper for a primitive type. + */ + public static boolean isWrapperType(final Class type) { + return PRIMITIVE_TYPES.containsKey(type); + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/package-info.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, 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 2015 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. +*/ + +/** + *

Contains classes that make it more convenient for language runtimes to + * implement their own language-specific object models and type conversions + * by providing basic implementations of some classes as well as various + * utilities. + *

+ * @since 1.9 + */ +@jdk.Exported +package jdk.internal.dynalink.linker.support; diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/package-info.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2015, 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. +*/ + +/** + *

+ * Dynalink is a library for dynamic linking high-level operations on objects. + * These operations include "read a property", + * "write a property", "invoke a function" and so on. Dynalink is primarily + * useful for implementing programming languages where at least some expressions + * have dynamic types (that is, types that can not be decided statically), and + * the operations on dynamic types are expressed as + * {@link java.lang.invoke.CallSite call sites}. These call sites will be + * linked to appropriate target {@link java.lang.invoke.MethodHandle method handles} + * at run time based on actual types of the values the expressions evaluated to. + * These can change between invocations, necessitating relinking the call site + * multiple times to accommodate new types; Dynalink handles all that and more. + *

+ * Dynalink supports implementation of programming languages with object models + * that differ (even radically) from the JVM's class-based model and have their + * custom type conversions. + *

+ * Dynalink is closely related to, and relies on, the {@link java.lang.invoke} + * package. + *

+ * + * While {@link java.lang.invoke} provides a low level API for dynamic linking + * of {@code invokedynamic} call sites, it does not provide a way to express + * higher level operations on objects, nor methods that implement them. These + * operations are the usual ones in object-oriented environments: property + * access, access of elements of collections, invocation of methods and + * constructors (potentially with multiple dispatch, e.g. link- and run-time + * equivalents of Java overloaded method resolution). These are all functions + * that are normally desired in a language on the JVM. If a language is + * statically typed and its type system matches that of the JVM, it can + * accomplish this with use of the usual invocation, field access, etc. + * instructions (e.g. {@code invokevirtual}, {@code getfield}). However, if the + * language is dynamic (hence, types of some expressions are not known until + * evaluated at run time), or its object model or type system don't match + * closely that of the JVM, then it should use {@code invokedynamic} call sites + * instead and let Dynalink manage them. + *

Example

+ * Dynalink is probably best explained by an example showing its use. Let's + * suppose you have a program in a language where you don't have to declare the + * type of an object and you want to access a property on it: + *
+ * var color = obj.color;
+ * 
+ * If you generated a Java class to represent the above one-line program, its + * bytecode would look something like this: + *
+ * aload 2 // load "obj" on stack
+ * invokedynamic "GET_PROPERTY:color"(Object)Object // invoke property getter on object of unknown type
+ * astore 3 // store the return value into local variable "color"
+ * 
+ * In order to link the {@code invokedynamic} instruction, we need a bootstrap + * method. A minimalist bootstrap method with Dynalink could look like this: + *
+ * import java.lang.invoke.*;
+ * import jdk.internal.dynalink.*;
+ * import jdk.internal.dynalink.support.*;
+ *
+ * class MyLanguageRuntime {
+ *     private static final DynamicLinker dynamicLinker = new DynamicLinkerFactory().createLinker();
+ *
+ *     public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {
+ *         return dynamicLinker.link(
+ *             new SimpleRelinkableCallSite(
+ *                 new CallSiteDescriptor(lookup, parseOperation(name), type)));
+ *     }
+ *
+ *     private static Operation parseOperation(String name) {
+ *         ...
+ *     }
+ * }
+ * 
+ * There are several objects of significance in the above code snippet: + *
    + *
  • {@link jdk.internal.dynalink.DynamicLinker} is the main object in Dynalink, it + * coordinates the linking of call sites to method handles that implement the + * operations named in them. It is configured and created using a + * {@link jdk.internal.dynalink.DynamicLinkerFactory}.
  • + *
  • When the bootstrap method is invoked, it needs to create a + * {@link java.lang.invoke.CallSite} object. In Dynalink, these call sites need + * to additionally implement the {@link jdk.internal.dynalink.RelinkableCallSite} + * interface. "Relinkable" here alludes to the fact that if the call site + * encounters objects of different types at run time, its target will be changed + * to a method handle that can perform the operation on the newly encountered + * type. {@link jdk.internal.dynalink.support.SimpleRelinkableCallSite} and + * {@link jdk.internal.dynalink.support.ChainedCallSite} (not used in the above example) + * are two implementations already provided by the library.
  • + *
  • Dynalink uses {@link jdk.internal.dynalink.CallSiteDescriptor} objects to + * preserve the parameters to the bootstrap method: the lookup and the method type, + * as it will need them whenever it needs to relink a call site.
  • + *
  • Dynalink uses {@link jdk.internal.dynalink.Operation} objects to express + * dynamic operations. It does not prescribe how would you encode the operations + * in your call site, though. That is why in the above example the + * {@code parseOperation} function is left empty, and you would be expected to + * provide the code to parse the string {@code "GET_PROPERTY:color"} + * in the call site's name into a named property getter operation object as + * {@code new NamedOperation(StandardOperation.GET_PROPERTY), "color")}. + *
+ *

What can you already do with the above setup? {@code DynamicLinkerFactory} + * by default creates a {@code DynamicLinker} that can link Java objects with the + * usual Java semantics. If you have these three simple classes: + *

+ * public class A {
+ *     public String color;
+ *     public A(String color) { this.color = color; }
+ * }
+ *
+ * public class B {
+ *     private String color;
+ *     public B(String color) { this.color = color; }
+ *     public String getColor() { return color; }
+ * }
+ *
+ * public class C {
+ *     private int color;
+ *     public C(int color) { this.color = color; }
+ *     public int getColor() { return color; }
+ * }
+ * 
+ * and you somehow create their instances and pass them to your call site in your + * programming language: + *
+ * for each(var obj in [new A("red"), new B("green"), new C(0x0000ff)]) {
+ *     print(obj.color);
+ * }
+ * 
+ * then on first invocation, Dynalink will link the {@code .color} getter + * operation to a field getter for {@code A.color}, on second invocation it will + * relink it to {@code B.getColor()} returning a {@code String}, and finally on + * third invocation it will relink it to {@code C.getColor()} returning an {@code int}. + * The {@code SimpleRelinkableCallSite} we used above only remembers the linkage + * for the last encountered type (it implements what is known as a monomorphic + * inline cache). Another already provided implementation, + * {@link jdk.internal.dynalink.support.ChainedCallSite} will remember linkages for + * several different types (it is a polymorphic inline cache) and is + * probably a better choice in serious applications. + *

Dynalink and bytecode creation

+ * {@code CallSite} objects are usually created as part of bootstrapping + * {@code invokedynamic} instructions in bytecode. Hence, Dynalink is typically + * used as part of language runtimes that compile programs into Java + * {@code .class} bytecode format. Dynalink does not address the aspects of + * either creating bytecode classes or loading them into the JVM. That said, + * Dynalink can also be used without bytecode compilation (e.g. in language + * interpreters) by creating {@code CallSite} objects explicitly and associating + * them with representations of dynamic operations in the interpreted program + * (e.g. a typical representation would be some node objects in a syntax tree). + *

Available operations

+ * Dynalink defines several standard operations in its + * {@link jdk.internal.dynalink.StandardOperation} class. The linker for Java + * objects can link all of these operations, and you are encouraged to at + * minimum support and use these operations in your language too. To associate + * a fixed name with an operation, you can use + * {@link jdk.internal.dynalink.NamedOperation} as in the above example where + * {@code StandardOperation.GET_PROPERTY} was combined with the name + * {@code "color"} in a {@code NamedOperation} to form a property getter for the + * property named "color". + *

Composite operations

+ * Some languages might not have separate namespaces on objects for + * properties, elements, and methods, and a source language construct might + * address two or three of them. Dynalink supports specifying composite + * operations for this purpose using the + * {@link jdk.internal.dynalink.CompositeOperation} class. + *

Language-specific linkers

+ * Languages that define their own object model different than the JVM + * class-based model and/or use their own type conversions will need to create + * their own language-specific linkers. See the {@link jdk.internal.dynalink.linker} + * package and specifically the {@link jdk.internal.dynalink.linker.GuardingDynamicLinker} + * interface to get started. + *

Dynalink and Java objects

+ * The {@code DynamicLinker} objects created by {@code DynamicLinkerFactory} by + * default contain an internal instance of + * {@code BeansLinker}, which is a language-specific linker + * that implements the usual Java semantics for all of the above operations and + * can link any Java object that no other language-specific linker has managed + * to link. This way, all language runtimes have built-in interoperability with + * ordinary Java objects. See {@link jdk.internal.dynalink.beans.BeansLinker} for details + * on how it links the various operations. + *

Cross-language interoperability

+ * A {@code DynamicLinkerFactory} can be configured with a + * {@link jdk.internal.dynalink.DynamicLinkerFactory#setClassLoader(ClassLoader) class + * loader}. It will try to instantiate all + * {@link jdk.internal.dynalink.linker.GuardingDynamicLinkerExporter} classes visible to + * that class loader and compose the linkers they provide into the + * {@code DynamicLinker} it creates. This allows for interoperability between + * languages: if you have two language runtimes A and B deployed in your JVM and + * they export their linkers through the above mechanism, language runtime A + * will have a language-specific linker instance from B and vice versa inside + * their {@code DynamicLinker} objects. This means that if an object from + * language runtime B gets passed to code from language runtime A, the linker + * from B will get a chance to link the call site in A when it encounters the + * object from B. + */ +@jdk.Exported +package jdk.internal.dynalink; diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/package.html --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/package.html Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ - - - - -

- 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 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,185 +0,0 @@ -/* - * 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. - */ -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(final 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(final 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 MethodHandles.Lookup lookup = getLookup(); - int h = lookup.lookupClass().hashCode() + 31 * lookup.lookupModes(); - final int c = getNameTokenCount(); - 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(final 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(final Lookup l1, final Lookup l2) { - if(l1 == l2) { - return true; - } - if(l1.lookupClass() != l2.lookupClass()) { - return false; - } - return l1.lookupModes() == l2.lookupModes(); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java Thu Oct 22 11:12:39 2015 -0700 @@ -83,20 +83,31 @@ package jdk.internal.dynalink.support; +import java.lang.invoke.CallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MutableCallSite; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.RelinkableCallSite; +import jdk.internal.dynalink.linker.GuardedInvocation; /** - * A basic implementation of the {@link RelinkableCallSite} as a {@link MutableCallSite} subclass. + * A basic implementation of the {@link RelinkableCallSite} as a + * {@link MutableCallSite}. It carries a {@link CallSiteDescriptor} passed in + * the constructor and provides the correct implementation of the + * {@link #initialize(MethodHandle)} method. Subclasses must provide + * {@link #relink(GuardedInvocation, MethodHandle)} and + * {@link #resetAndRelink(GuardedInvocation, MethodHandle)} + * methods. */ 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 + * Creates a new abstract relinkable call site. + * @param descriptor the descriptor for this call site that will be returned + * from {@link #getDescriptor()}. The call site's {@link CallSite#type()} + * will be equal to descriptor's {@link CallSiteDescriptor#getMethodType()}. + * @throws NullPointerException if {@code descriptor} is null. */ protected AbstractRelinkableCallSite(final CallSiteDescriptor descriptor) { super(descriptor.getMethodType()); diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AutoDiscovery.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AutoDiscovery.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/* - * 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(final 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(final ServiceLoader loader) { - final List list = new LinkedList<>(); - for(final T linker: loader) { - list.add(linker); - } - return list; - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,114 +0,0 @@ -/* - * 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. - */ -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(final Class type) { - return false; - } - - @Override - public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) { - return null; - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,274 +0,0 @@ -/* - * 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.Reference; -import java.lang.ref.WeakReference; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -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 {@code "dyn:getProp:color"} of type {@code 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. - */ -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(final Lookup lookup, final String name, final MethodType methodType) { - Objects.requireNonNull(name); - Objects.requireNonNull(methodType); - Objects.requireNonNull(lookup); - final String[] tokenizedName = tokenizeName(name); - if(isPublicLookup(lookup)) { - return getCanonicalPublicDescriptor(createPublicCallSiteDescriptor(tokenizedName, methodType)); - } - return new LookupCallSiteDescriptor(tokenizedName, methodType, lookup); - } - - static CallSiteDescriptor getCanonicalPublicDescriptor(final CallSiteDescriptor desc) { - synchronized(publicDescs) { - final Reference ref = publicDescs.get(desc); - if(ref != null) { - final CallSiteDescriptor canonical = ref.get(); - if(canonical != null) { - return canonical; - } - } - publicDescs.put(desc, createReference(desc)); - } - return desc; - } - - /** - * Override this to use a different kind of references for the cache - * @param desc desc - * @return reference - */ - protected static Reference createReference(final CallSiteDescriptor desc) { - return new WeakReference<>(desc); - } - - private static CallSiteDescriptor createPublicCallSiteDescriptor(final String[] tokenizedName, final 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(final 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(final 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(final 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(final CallSiteDescriptor desc, final int start, final 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(final CallSiteDescriptor desc, final int num, final 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(final CallSiteDescriptor desc, final 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(final CallSiteDescriptor desc, final int num, final 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(final CallSiteDescriptor desc, final int num, final List> ptypesToInsert) { - return desc.changeMethodType(desc.getMethodType().insertParameterTypes(num, ptypesToInsert)); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/ChainedCallSite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/ChainedCallSite.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,244 @@ +/* + * 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.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.internal.dynalink.linker.support.Lookup; + +/** + * A relinkable call site that implements a polymorphic inline caching strategy. + * It remembers up to 8 {@link GuardedInvocation}s it was linked with, and on + * each relink request builds a cascading chain of method handles of one + * invocation falling back to the next one. The number of remembered invocations + * can be customized by overriding {@link #getMaxChainLength()} in a subclass. + * When this call site is relinked with a new invocation and the length of the + * chain is already at the maximum, it will throw away the oldest invocation. + * Invocations with invalidated switch points and ones for which their + * invalidating exception triggered are removed eagerly from the chain. The + * invocations are never reordered; the most recently linked method handle is + * always at the start of the chain and the least recently linked at its end. + * The call site can be safely relinked on more than one thread concurrently. + * Race conditions in linking are resolved by throwing away the + * {@link GuardedInvocation} produced on the losing thread without incorporating + * it into the chain, so it can lead to repeated linking for the same arguments. + */ +public class ChainedCallSite extends AbstractRelinkableCallSite { + private static final MethodHandle PRUNE_CATCHES; + private static final MethodHandle PRUNE_SWITCHPOINTS; + static { + final MethodHandle PRUNE = Lookup.findOwnSpecial(MethodHandles.lookup(), "prune", MethodHandle.class, + MethodHandle.class, boolean.class); + PRUNE_CATCHES = MethodHandles.insertArguments(PRUNE, 2, true); + PRUNE_SWITCHPOINTS = MethodHandles.insertArguments(PRUNE, 2, false); + } + + /** + * Contains the invocations currently linked into this call site's target. They are used when we are + * relinking to rebuild the guardWithTest chain. Valid values for this field are: {@code null} if there's + * no linked invocations, or an instance of {@link GuardedInvocation} if there is exactly one previous + * invocation, or an instance of {@code GuardedInvocation[]} if there is more than one previous + * invocation. + */ + private Object invocations; + + /** + * Creates a new chained call site. + * @param descriptor the descriptor for the call site. + */ + public ChainedCallSite(final 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. + * @return the maximum number of method handles in the chain. The return + * value is checked, and if your override returns a value less than 1, a + * {@link RuntimeException} will be thrown. + */ + protected int getMaxChainLength() { + return 8; + } + + @Override + public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { + relinkInternal(guardedInvocation, relinkAndInvoke, false, false); + } + + @Override + public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { + relinkInternal(guardedInvocation, relinkAndInvoke, true, false); + } + + private MethodHandle relinkInternal(final GuardedInvocation invocation, final MethodHandle relink, final boolean reset, final boolean removeCatches) { + final Object currentInvocations = invocations; + final LinkedList newInvocations; + if (currentInvocations == null || reset) { + newInvocations = new LinkedList<>(); + } else if (currentInvocations instanceof GuardedInvocation) { + newInvocations = new LinkedList<>(); + newInvocations.add((GuardedInvocation)currentInvocations); + } else if (currentInvocations instanceof GuardedInvocation[]) { + newInvocations = new LinkedList<>(Arrays.asList(((GuardedInvocation[])currentInvocations))); + } else { + throw new AssertionError(); + } + + // First, prune the chain of invalidated switchpoints, we always do this + // We also remove any catches if the remove catches flag is set + for(final Iterator it = newInvocations.iterator(); it.hasNext();) { + final GuardedInvocation inv = it.next(); + if(inv.hasBeenInvalidated() || (removeCatches && inv.getException() != null)) { + 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() == checkMaxChainLength(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 pruneAndInvokeSwitchPoints = makePruneAndInvokeMethod(relink, PRUNE_SWITCHPOINTS); + final MethodHandle pruneAndInvokeCatches = makePruneAndInvokeMethod(relink, PRUNE_CATCHES); + + // Fold the new chain + MethodHandle target = relink; + for(final GuardedInvocation inv: newInvocations) { + target = inv.compose(target, pruneAndInvokeSwitchPoints, pruneAndInvokeCatches); + } + + switch (newInvocations.size()) { + case 0: + invocations = null; + break; + case 1: + invocations = newInvocations.getFirst(); + break; + default: + invocations = newInvocations.toArray(new GuardedInvocation[newInvocations.size()]); + } + setTarget(target); + return target; + } + + private static int checkMaxChainLength(final int maxChainLength) { + if (maxChainLength > 0) { + return maxChainLength; + } + throw new RuntimeException("getMaxChainLength() returned a non-positive value"); + + } + /** + * Creates a method that rebuilds our call chain, pruning it of any invalidated switchpoints, and then invokes that + * chain. + * @param relinkAndInvoke the ultimate fallback for the chain passed from the dynamic linker. + * @return a method handle for prune-and-invoke + */ + private MethodHandle makePruneAndInvokeMethod(final MethodHandle relinkAndInvoke, final MethodHandle prune) { + // Bind prune to (this, relink) + final MethodHandle boundPrune = MethodHandles.insertArguments(prune, 0, this, relinkAndInvoke); + // 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(final MethodHandle relink, final boolean catches) { + return relinkInternal(null, relink, false, catches); + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/ClassLoaderGetterContextProvider.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/ClassLoaderGetterContextProvider.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +0,0 @@ -/* - * 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.security.AccessControlContext; -import java.security.Permissions; -import java.security.ProtectionDomain; - -/** - * This class exposes a canonical {@link AccessControlContext} with a single {@link RuntimePermission} for - * {@code "getClassLoader"} permission that is used by other parts of the code to narrow their set of permissions when - * they're retrieving class loaders in privileged blocks. - */ -public class ClassLoaderGetterContextProvider { - /** - * Canonical instance of {@link AccessControlContext} with a single {@link RuntimePermission} for - * {@code "getClassLoader"} permission. - */ - public static final AccessControlContext GET_CLASS_LOADER_CONTEXT; - static { - final Permissions perms = new Permissions(); - perms.add(new RuntimePermission("getClassLoader")); - GET_CLASS_LOADER_CONTEXT = new AccessControlContext( - new ProtectionDomain[] { new ProtectionDomain(null, perms) }); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/ClassMap.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/ClassMap.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -/* - * 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.security.AccessController; -import java.security.PrivilegedAction; -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. - * - * @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(final 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 value associated with the class - * - * @param clazz the class - * @return the value associated with the class - */ - public T get(final 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; - - final ClassLoader clazzLoader = AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ClassLoader run() { - return clazz.getClassLoader(); - } - }, ClassLoaderGetterContextProvider.GET_CLASS_LOADER_CONTEXT); - - // If allowed to strongly reference, put it in the fast map - if(Guards.canReferenceDirectly(classLoader, clazzLoader)) { - 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 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -/* - * 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. - */ -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(final Iterable linkers) { - final List l = new LinkedList<>(); - for(final GuardingDynamicLinker linker: linkers) { - l.add(linker); - } - this.linkers = l.toArray(new GuardingDynamicLinker[l.size()]); - } - - @Override - public GuardedInvocation getGuardedInvocation(final 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; - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,223 +0,0 @@ -/* - * 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. - */ -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", "rawtypes"}) - ClassToLinker(final TypeBasedGuardingDynamicLinker[] linkers) { - this.linkers = linkers; - singletonLinkers = new List[linkers.length]; - for(int i = 0; i < linkers.length; ++i) { - singletonLinkers[i] = Collections.singletonList(linkers[i]); - } - } - - @SuppressWarnings("fallthrough") - @Override - protected List computeValue(final 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); - } - default: { - list.add(linker); - } - } - } - } - return list; - } - } - - private final ClassValue> classToLinker; - - /** - * Creates a new composite type-based linker. - * - * @param linkers the component linkers - */ - public CompositeTypeBasedGuardingDynamicLinker(final Iterable linkers) { - final List l = new LinkedList<>(); - for(final TypeBasedGuardingDynamicLinker linker: linkers) { - l.add(linker); - } - this.classToLinker = new ClassToLinker(l.toArray(new TypeBasedGuardingDynamicLinker[l.size()])); - } - - @Override - public boolean canLinkType(final Class type) { - return !classToLinker.get(type).isEmpty(); - } - - @Override - public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) - throws Exception { - final Object obj = linkRequest.getReceiver(); - if(obj == null) { - return null; - } - for(final 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(final Iterable linkers) { - final List llinkers = new LinkedList<>(); - final List tblinkers = new LinkedList<>(); - for(final 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(final List llinkers, - final 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; - } - } - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/* - * 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}. - */ -class DefaultCallSiteDescriptor extends AbstractCallSiteDescriptor { - - private final String[] tokenizedName; - private final MethodType methodType; - - DefaultCallSiteDescriptor(final String[] tokenizedName, final MethodType methodType) { - this.tokenizedName = tokenizedName; - this.methodType = methodType; - } - - @Override - public int getNameTokenCount() { - return tokenizedName.length; - } - - @Override - public String getNameToken(final int i) { - try { - return tokenizedName[i]; - } catch(final ArrayIndexOutOfBoundsException e) { - throw new IllegalArgumentException(e.getMessage()); - } - } - - String[] getTokenizedName() { - return tokenizedName; - } - - @Override - public MethodType getMethodType() { - return methodType; - } - - @Override - public CallSiteDescriptor changeMethodType(final MethodType newMethodType) { - return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new DefaultCallSiteDescriptor(tokenizedName, - newMethodType)); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/DefaultInternalObjectFilter.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/DefaultInternalObjectFilter.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2015, 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-2015 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 jdk.internal.dynalink.DynamicLinkerFactory; -import jdk.internal.dynalink.linker.MethodHandleTransformer; - -/** - * Default implementation for a {@link DynamicLinkerFactory#setInternalObjectsFilter(MethodHandleTransformer)}. - * Given a method handle of {@code Object(Object)} type for filtering parameter and another one of the same type for - * filtering return values, applies them to passed method handles where their parameter types and/or return value types - * are declared to be {@link Object}. - */ -public class DefaultInternalObjectFilter implements MethodHandleTransformer { - private static final MethodHandle FILTER_VARARGS = new Lookup(MethodHandles.lookup()).findStatic( - DefaultInternalObjectFilter.class, "filterVarArgs", MethodType.methodType(Object[].class, MethodHandle.class, Object[].class)); - - private final MethodHandle parameterFilter; - private final MethodHandle returnFilter; - private final MethodHandle varArgFilter; - - /** - * Creates a new filter. - * @param parameterFilter the filter for method parameters. Must be of type {@code Object(Object)}, or null. - * @param returnFilter the filter for return values. Must be of type {@code Object(Object)}, or null. - * @throws IllegalArgumentException if one or both filters are not of the expected type. - */ - public DefaultInternalObjectFilter(final MethodHandle parameterFilter, final MethodHandle returnFilter) { - this.parameterFilter = checkHandle(parameterFilter, "parameterFilter"); - this.returnFilter = checkHandle(returnFilter, "returnFilter"); - this.varArgFilter = parameterFilter == null ? null : FILTER_VARARGS.bindTo(parameterFilter); - } - - @Override - public MethodHandle transform(final MethodHandle target) { - assert target != null; - MethodHandle[] filters = null; - final MethodType type = target.type(); - final boolean isVarArg = target.isVarargsCollector(); - final int paramCount = type.parameterCount(); - final MethodHandle paramsFiltered; - // Filter parameters - if (parameterFilter != null) { - int firstFilter = -1; - // Ignore receiver, start from argument 1 - for(int i = 1; i < paramCount; ++i) { - final Class paramType = type.parameterType(i); - final boolean filterVarArg = isVarArg && i == paramCount - 1 && paramType == Object[].class; - if (filterVarArg || paramType == Object.class) { - if (filters == null) { - firstFilter = i; - filters = new MethodHandle[paramCount - firstFilter]; - } - filters[i - firstFilter] = filterVarArg ? varArgFilter : parameterFilter; - } - } - paramsFiltered = filters != null ? MethodHandles.filterArguments(target, firstFilter, filters) : target; - } else { - paramsFiltered = target; - } - // Filter return value if needed - final MethodHandle returnFiltered = returnFilter != null && type.returnType() == Object.class ? MethodHandles.filterReturnValue(paramsFiltered, returnFilter) : paramsFiltered; - // Preserve varargs collector state - return isVarArg && !returnFiltered.isVarargsCollector() ? returnFiltered.asVarargsCollector(type.parameterType(paramCount - 1)) : returnFiltered; - - } - - private static MethodHandle checkHandle(final MethodHandle handle, final String handleKind) { - if (handle != null) { - final MethodType objectObjectType = MethodType.methodType(Object.class, Object.class); - if (!handle.type().equals(objectObjectType)) { - throw new IllegalArgumentException("Method type for " + handleKind + " must be " + objectObjectType); - } - } - return handle; - } - - @SuppressWarnings("unused") - private static Object[] filterVarArgs(final MethodHandle parameterFilter, final Object[] args) throws Throwable { - Object[] newArgs = null; - for(int i = 0; i < args.length; ++i) { - final Object arg = args[i]; - final Object newArg = parameterFilter.invokeExact(arg); - if (arg != newArg) { - if (newArgs == null) { - newArgs = args.clone(); - } - newArgs[i] = newArg; - } - } - return newArgs == null ? args : newArgs; - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/DefaultPrelinkFilter.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/DefaultPrelinkFilter.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * 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.GuardedInvocationFilter; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; -import jdk.internal.dynalink.linker.LinkerServices; - -/** - * Default filter for guarded invocation pre link filtering - */ -public class DefaultPrelinkFilter implements GuardedInvocationFilter { - @Override - public GuardedInvocation filter(final GuardedInvocation inv, final LinkRequest request, final LinkerServices linkerServices) { - return inv.asType(linkerServices, request.getCallSiteDescriptor().getMethodType()); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/Guards.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/Guards.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,360 +0,0 @@ -/* - * 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.DynamicLinker; -import jdk.internal.dynalink.linker.LinkerServices; - -/** - * Utility methods for creating typical guards. TODO: introduce reasonable caching of created guards. - * - */ -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(final Class clazz, final MethodType type) { - final Class declaredType = type.parameterType(0); - if(clazz == declaredType) { - LOG.log(Level.WARNING, "isOfClassGuardAlwaysTrue", new Object[] { clazz.getName(), 0, type, DynamicLinker.getLinkedCallSiteLocation() }); - return constantTrue(type); - } - if(!declaredType.isAssignableFrom(clazz)) { - LOG.log(Level.WARNING, "isOfClassGuardAlwaysFalse", new Object[] { clazz.getName(), 0, type, DynamicLinker.getLinkedCallSiteLocation() }); - 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(final Class clazz, final 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(final Class clazz, final int pos, final MethodType type) { - final Class declaredType = type.parameterType(pos); - if(clazz.isAssignableFrom(declaredType)) { - LOG.log(Level.WARNING, "isInstanceGuardAlwaysTrue", new Object[] { clazz.getName(), pos, type, DynamicLinker.getLinkedCallSiteLocation() }); - return constantTrue(type); - } - if(!declaredType.isAssignableFrom(clazz)) { - LOG.log(Level.WARNING, "isInstanceGuardAlwaysFalse", new Object[] { clazz.getName(), pos, type, DynamicLinker.getLinkedCallSiteLocation() }); - 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(final int pos, final MethodType type) { - final Class declaredType = type.parameterType(pos); - if(declaredType.isArray()) { - LOG.log(Level.WARNING, "isArrayGuardAlwaysTrue", new Object[] { pos, type, DynamicLinker.getLinkedCallSiteLocation() }); - return constantTrue(type); - } - if(!declaredType.isAssignableFrom(Object[].class)) { - LOG.log(Level.WARNING, "isArrayGuardAlwaysFalse", new Object[] { pos, type, DynamicLinker.getLinkedCallSiteLocation() }); - 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(final 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(final MethodHandle test, final Class clazz, final int pos, final 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(final MethodHandle test, final 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(final LinkerServices linkerServices, final MethodHandle test, final MethodType type) { - return linkerServices.asType(test, getTestType(test, type)); - } - - private static MethodType getTestType(final MethodHandle test, final MethodType type) { - return type.dropParameterTypes(test.type().parameterCount(), - type.parameterCount()).changeReturnType(boolean.class); - } - - private static MethodHandle asType(final MethodHandle test, final int pos, final 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_INSTANCE = Lookup.PUBLIC.findVirtual(Class.class, "isInstance", - MethodType.methodType(Boolean.TYPE, Object.class)); - - private static final MethodHandle IS_OF_CLASS; - private static final MethodHandle IS_ARRAY; - private static final MethodHandle IS_IDENTICAL; - private static final MethodHandle IS_NULL; - private static final MethodHandle IS_NOT_NULL; - - static { - final Lookup lookup = new Lookup(MethodHandles.lookup()); - - IS_OF_CLASS = lookup.findOwnStatic("isOfClass", Boolean.TYPE, Class.class, Object.class); - IS_ARRAY = lookup.findOwnStatic("isArray", Boolean.TYPE, Object.class); - IS_IDENTICAL = lookup.findOwnStatic("isIdentical", Boolean.TYPE, Object.class, Object.class); - IS_NULL = lookup.findOwnStatic("isNull", Boolean.TYPE, Object.class); - IS_NOT_NULL = lookup.findOwnStatic("isNotNull", 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(final 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(final 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(final 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(final Object obj) { - return obj == null; - } - - @SuppressWarnings("unused") - private static boolean isNotNull(final Object obj) { - return obj != null; - } - - @SuppressWarnings("unused") - private static boolean isArray(final Object o) { - return o != null && o.getClass().isArray(); - } - - @SuppressWarnings("unused") - private static boolean isOfClass(final Class c, final Object o) { - return o != null && o.getClass() == c; - } - - @SuppressWarnings("unused") - private static boolean isIdentical(final Object o1, final Object o2) { - return o1 == o2; - } - - private static MethodHandle constantTrue(final MethodType type) { - return constantBoolean(Boolean.TRUE, type); - } - - private static MethodHandle constantFalse(final MethodType type) { - return constantBoolean(Boolean.FALSE, type); - } - - private static MethodHandle constantBoolean(final Boolean value, final MethodType type) { - return MethodHandles.permuteArguments(MethodHandles.constant(Boolean.TYPE, value), - type.changeReturnType(Boolean.TYPE)); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/LinkRequestImpl.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/LinkRequestImpl.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -/* - * 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. - */ -public class LinkRequestImpl implements LinkRequest { - - private final CallSiteDescriptor callSiteDescriptor; - private final Object callSiteToken; - private final Object[] arguments; - private final boolean callSiteUnstable; - private final int linkCount; - - /** - * Creates a new link request. - * - * @param callSiteDescriptor the descriptor for the call site being linked - * @param callSiteToken the opaque token for the call site being linked. - * @param linkCount how many times this callsite has been linked/relinked - * @param callSiteUnstable true if the call site being linked is considered unstable - * @param arguments the arguments for the invocation - */ - public LinkRequestImpl(final CallSiteDescriptor callSiteDescriptor, final Object callSiteToken, final int linkCount, final boolean callSiteUnstable, final Object... arguments) { - this.callSiteDescriptor = callSiteDescriptor; - this.callSiteToken = callSiteToken; - this.linkCount = linkCount; - 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 Object getCallSiteToken() { - return callSiteToken; - } - - @Override - public boolean isCallSiteUnstable() { - return callSiteUnstable; - } - - @Override - public int getLinkCount() { - return linkCount; - } - - @Override - public LinkRequest withoutRuntimeContext() { - return this; - } - - @Override - public LinkRequest replaceArguments(final CallSiteDescriptor newCallSiteDescriptor, final Object[] newArguments) { - return new LinkRequestImpl(newCallSiteDescriptor, callSiteToken, linkCount, callSiteUnstable, newArguments); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/LinkerServicesImpl.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/LinkerServicesImpl.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,171 +0,0 @@ -/* - * 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; -import jdk.internal.dynalink.linker.MethodHandleTransformer; - -/** - * Default implementation of the {@link LinkerServices} interface. - */ -public class LinkerServicesImpl implements LinkerServices { - - private static final RuntimePermission GET_CURRENT_LINK_REQUEST = new RuntimePermission("dynalink.getCurrentLinkRequest"); - private static final ThreadLocal threadLinkRequest = new ThreadLocal<>(); - - private final TypeConverterFactory typeConverterFactory; - private final GuardingDynamicLinker topLevelLinker; - private final MethodHandleTransformer internalObjectsFilter; - - /** - * 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. - * @param internalObjectsFilter a method handle transformer that is supposed to act as the implementation of this - * services' {@link #filterInternalObjects(java.lang.invoke.MethodHandle)} method. - */ - public LinkerServicesImpl(final TypeConverterFactory typeConverterFactory, - final GuardingDynamicLinker topLevelLinker, final MethodHandleTransformer internalObjectsFilter) { - this.typeConverterFactory = typeConverterFactory; - this.topLevelLinker = topLevelLinker; - this.internalObjectsFilter = internalObjectsFilter; - } - - @Override - public boolean canConvert(final Class from, final Class to) { - return typeConverterFactory.canConvert(from, to); - } - - @Override - public MethodHandle asType(final MethodHandle handle, final MethodType fromType) { - return typeConverterFactory.asType(handle, fromType); - } - - @Override - public MethodHandle getTypeConverter(final Class sourceType, final Class targetType) { - return typeConverterFactory.getTypeConverter(sourceType, targetType); - } - - @Override - public Comparison compareConversion(final Class sourceType, final Class targetType1, final Class targetType2) { - return typeConverterFactory.compareConversion(sourceType, targetType1, targetType2); - } - - @Override - public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest) throws Exception { - final LinkRequest prevLinkRequest = threadLinkRequest.get(); - threadLinkRequest.set(linkRequest); - try { - return topLevelLinker.getGuardedInvocation(linkRequest, this); - } finally { - threadLinkRequest.set(prevLinkRequest); - } - } - - @Override - public MethodHandle filterInternalObjects(final MethodHandle target) { - return internalObjectsFilter != null ? internalObjectsFilter.transform(target) : target; - } - - /** - * Returns the currently processed link request, or null if the method is invoked outside of the linking process. - * @return the currently processed link request, or null. - * @throws SecurityException if the calling code doesn't have the {@code "dynalink.getCurrentLinkRequest"} runtime - * permission. - */ - public static LinkRequest getCurrentLinkRequest() { - final SecurityManager sm = System.getSecurityManager(); - if(sm != null) { - sm.checkPermission(GET_CURRENT_LINK_REQUEST); - } - return threadLinkRequest.get(); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/Lookup.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/Lookup.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,372 +0,0 @@ -/* - * 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; - -/** - * 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). - */ -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(final 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(final Method m) { - return unreflect(lookup, m); - } - - /** - * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, converting any encountered - * {@link IllegalAccessException} into an {@link IllegalAccessError}. - * - * @param lookup the lookup used to unreflect - * @param m the method to unreflect - * @return the unreflected method handle. - */ - public static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) { - try { - return lookup.unreflect(m); - } catch(final 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(final Field f) { - try { - return lookup.unreflectGetter(f); - } catch(final 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(final Classrefc, final String name, final Class type) { - try { - return lookup.findGetter(refc, name, type); - } catch(final 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(final 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(final Field f) { - try { - return lookup.unreflectSetter(f); - } catch(final 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(final Constructor c) { - return unreflectConstructor(lookup, c); - } - - /** - * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, converting any - * encountered {@link IllegalAccessException} into an {@link IllegalAccessError}. - * - * @param lookup the lookup used to unreflect - * @param c the constructor to unreflect - * @return the unreflected constructor handle. - */ - public static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor c) { - try { - return lookup.unreflectConstructor(c); - } catch(final IllegalAccessException e) { - final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect constructor " + c); - ee.initCause(e); - throw ee; - } - } - - /** - * Performs a findSpecial 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 findSpecial(final Class declaringClass, final String name, final MethodType type) { - try { - return lookup.findSpecial(declaringClass, name, type, declaringClass); - } catch(final IllegalAccessException e) { - final IllegalAccessError ee = new IllegalAccessError("Failed to access special method " + methodDescription( - declaringClass, name, type)); - ee.initCause(e); - throw ee; - } catch(final 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(final Class declaringClass, final String name, final 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(final Class declaringClass, final String name, final MethodType type) { - try { - return lookup.findStatic(declaringClass, name, type); - } catch(final IllegalAccessException e) { - final IllegalAccessError ee = new IllegalAccessError("Failed to access static method " + methodDescription( - declaringClass, name, type)); - ee.initCause(e); - throw ee; - } catch(final 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(final Class declaringClass, final String name, final MethodType type) { - try { - return lookup.findVirtual(declaringClass, name, type); - } catch(final IllegalAccessException e) { - final IllegalAccessError ee = new IllegalAccessError("Failed to access virtual method " + methodDescription( - declaringClass, name, type)); - ee.initCause(e); - throw ee; - } catch(final 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(final MethodHandles.Lookup lookup, final String name, final Class rtype, final 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(final String name, final Class rtype, final 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(final MethodHandles.Lookup lookup, final String name, final Class rtype, final 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(final String name, final Class rtype, final Class... ptypes) { - return findStatic(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes)); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -/* - * 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. - */ -class LookupCallSiteDescriptor extends DefaultCallSiteDescriptor { - private final 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(final String[] tokenizedName, final MethodType methodType, final Lookup lookup) { - super(tokenizedName, methodType); - this.lookup = lookup; - } - - @Override - public Lookup getLookup() { - return lookup; - } - - @Override - public CallSiteDescriptor changeMethodType(final MethodType newMethodType) { - return new LookupCallSiteDescriptor(getTokenizedName(), newMethodType, lookup); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NameCodec.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NameCodec.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NameCodec.java Thu Oct 22 11:12:39 2015 -0700 @@ -83,24 +83,15 @@ 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. + * "Symbolic Freedom in the VM" article. Normally, you would + * mangle the names in the call sites as you're generating bytecode, and then + * demangle them when you receive them in bootstrap methods. */ -public class NameCodec { +public final 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 }); @@ -175,7 +166,7 @@ * @return the demangled form of the symbolic name. */ public static String decode(final String name) { - if(name.charAt(0) != ESCAPE_CHAR) { + if(name.isEmpty() || name.charAt(0) != ESCAPE_CHAR) { return name; } final int l = name.length(); diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * 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(final String op, final String name, final MethodType methodType) { - super(op, methodType); - this.name = name; - } - - @Override - public int getNameTokenCount() { - return 3; - } - - @Override - public String getNameToken(final 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(final MethodType newMethodType) { - return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new NamedDynCallSiteDescriptor(getOp(), name, - newMethodType)); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -/* - * 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. - */ -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 callSiteToken the opaque token for the call site being linked. - * @param arguments the arguments for the invocation - * @param linkCount number of times callsite has been linked/relinked - * @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(final CallSiteDescriptor callSiteDescriptor, final Object callSiteToken, - final int linkCount, final boolean callSiteUnstable, final Object[] arguments, final int runtimeContextArgCount) { - super(callSiteDescriptor, callSiteToken, linkCount, 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), getCallSiteToken(), getLinkCount(), isCallSiteUnstable(), getTruncatedArguments()); - } - return contextStrippedRequest; - } - - @Override - public LinkRequest replaceArguments(final CallSiteDescriptor callSiteDescriptor, final Object[] arguments) { - return new RuntimeContextLinkRequestImpl(callSiteDescriptor, getCallSiteToken(), getLinkCount(), 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; - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/SimpleRelinkableCallSite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/SimpleRelinkableCallSite.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,115 @@ +/* + * 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 jdk.internal.dynalink.CallSiteDescriptor; +import jdk.internal.dynalink.DynamicLinker; +import jdk.internal.dynalink.linker.GuardedInvocation; + +/** + * A relinkable call site that implements monomorphic inline caching strategy, + * only being linked to a single {@link GuardedInvocation}. If that invocation + * is invalidated, it will throw it away and ask its associated + * {@link DynamicLinker} to relink it. + */ +public class SimpleRelinkableCallSite extends AbstractRelinkableCallSite { + /** + * Creates a new call site with monomorphic inline caching strategy. + * @param descriptor the descriptor for this call site + */ + public SimpleRelinkableCallSite(final CallSiteDescriptor descriptor) { + super(descriptor); + } + + @Override + public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { + setTarget(guardedInvocation.compose(relinkAndInvoke)); + } + + @Override + public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { + relink(guardedInvocation, relinkAndInvoke); + } +} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeConverterFactory.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeConverterFactory.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,408 +0,0 @@ -/* - * 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.security.AccessController; -import java.security.PrivilegedAction; -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.GuardedTypeConversion; -import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; -import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.linker.MethodTypeConversionStrategy; - -/** - * 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. - */ -public class TypeConverterFactory { - - private final GuardingTypeConverterFactory[] factories; - private final ConversionComparator[] comparators; - private final MethodTypeConversionStrategy autoConversionStrategy; - - private final ClassValue> converterMap = new ClassValue>() { - @Override - protected ClassMap computeValue(final Class sourceType) { - return new ClassMap(getClassLoader(sourceType)) { - @Override - protected MethodHandle computeValue(final Class targetType) { - try { - return createConverter(sourceType, targetType); - } catch (final RuntimeException e) { - throw e; - } catch (final Exception e) { - throw new RuntimeException(e); - } - } - }; - } - }; - - private final ClassValue> converterIdentityMap = new ClassValue>() { - @Override - protected ClassMap computeValue(final Class sourceType) { - return new ClassMap(getClassLoader(sourceType)) { - @Override - protected MethodHandle computeValue(final Class targetType) { - if(!canAutoConvert(sourceType, targetType)) { - final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType); - if(converter != IDENTITY_CONVERSION) { - return converter; - } - } - return IDENTITY_CONVERSION.asType(MethodType.methodType(targetType, sourceType)); - } - }; - } - }; - - private final ClassValue> canConvert = new ClassValue>() { - @Override - protected ClassMap computeValue(final Class sourceType) { - return new ClassMap(getClassLoader(sourceType)) { - @Override - protected Boolean computeValue(final Class targetType) { - try { - return getTypeConverterNull(sourceType, targetType) != null; - } catch (final RuntimeException e) { - throw e; - } catch (final Exception e) { - throw new RuntimeException(e); - } - } - }; - } - }; - - private static ClassLoader getClassLoader(final Class clazz) { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ClassLoader run() { - return clazz.getClassLoader(); - } - }, ClassLoaderGetterContextProvider.GET_CLASS_LOADER_CONTEXT); - } - - /** - * Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances. - * - * @param factories the {@link GuardingTypeConverterFactory} instances to compose. - * @param autoConversionStrategy conversion strategy for automatic type conversions. After - * {@link #asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has applied all custom - * conversions to a method handle, it still needs to effect - * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that - * can usually be automatically applied as per - * {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}. - * However, sometimes language runtimes will want to customize even those conversions for their own call - * sites. A typical example is allowing unboxing of null return values, which is by default prohibited by - * ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom - * automatic conversion strategy, that can deal with null values. Note that when the strategy's - * {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} - * is invoked, the custom language conversions will already have been applied to the method handle, so by - * design the difference between the handle's current method type and the desired final type will always - * only be ones that can be subjected to method invocation conversions. Can be null, in which case no - * custom strategy is employed. - */ - public TypeConverterFactory(final Iterable factories, - final MethodTypeConversionStrategy autoConversionStrategy) { - final List l = new LinkedList<>(); - final List c = new LinkedList<>(); - for(final 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()]); - this.autoConversionStrategy = autoConversionStrategy; - } - - /** - * 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. For all conversions that are not a JLS method invocation conversion it'll insert - * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters - * provided by {@link GuardingTypeConverterFactory} implementations. For the remaining JLS method invocation - * conversions, it will invoke {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)} first - * if an automatic conversion strategy was specified in the - * {@link #TypeConverterFactory(Iterable, MethodTypeConversionStrategy) constructor}, and finally apply - * {@link MethodHandle#asType(MethodType)} for any remaining conversions. - * - * @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)}, - * {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)}, and - * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with - * {@link GuardingTypeConverterFactory} produced type converters as filters. - */ - public MethodHandle asType(final 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); - } - } - } - - // Give change to automatic conversion strategy, if one is present. - final MethodHandle autoConvertedHandle = - autoConversionStrategy != null ? autoConversionStrategy.asType(newHandle, fromType) : newHandle; - - // Do a final asType for any conversions that remain. - return autoConvertedHandle.asType(fromType); - } - - private static MethodHandle applyConverters(final MethodHandle handle, final int pos, final 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) || canConvert.get(from).get(to); - } - - /** - * 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(final Class sourceType, final Class targetType1, final Class targetType2) { - for(final 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 getCacheableTypeConverterNull(final Class sourceType, final Class targetType) { - final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType); - return converter == IDENTITY_CONVERSION ? null : converter; - } - - /*private*/ MethodHandle getTypeConverterNull(final Class sourceType, final Class targetType) { - try { - return getCacheableTypeConverterNull(sourceType, targetType); - } catch(final NotCacheableConverter e) { - return e.converter; - } - } - - /*private*/ MethodHandle getCacheableTypeConverter(final Class sourceType, final Class targetType) { - return converterMap.get(sourceType).get(targetType); - } - - /** - * 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(final Class sourceType, final Class targetType) { - try { - return converterIdentityMap.get(sourceType).get(targetType); - } catch(final NotCacheableConverter e) { - return e.converter; - } - } - - /*private*/ MethodHandle createConverter(final Class sourceType, final Class targetType) throws Exception { - final MethodType type = MethodType.methodType(targetType, sourceType); - final MethodHandle identity = IDENTITY_CONVERSION.asType(type); - MethodHandle last = identity; - boolean cacheable = true; - for(int i = factories.length; i-- > 0;) { - final GuardedTypeConversion next = factories[i].convertToType(sourceType, targetType); - if(next != null) { - cacheable = cacheable && next.isCacheable(); - final GuardedInvocation conversionInvocation = next.getConversionInvocation(); - conversionInvocation.assertType(type); - last = conversionInvocation.compose(last); - } - } - if(last == identity) { - return IDENTITY_CONVERSION; - } - if(cacheable) { - return last; - } - throw new NotCacheableConverter(last); - } - - /*private*/ static final MethodHandle IDENTITY_CONVERSION = MethodHandles.identity(Object.class); - - @SuppressWarnings("serial") - private static class NotCacheableConverter extends RuntimeException { - final MethodHandle converter; - - NotCacheableConverter(final MethodHandle converter) { - super("", null, false, false); - this.converter = converter; - } - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeUtilities.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/TypeUtilities.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,530 +0,0 @@ -/* - * 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. - */ -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 supertype for - * purposes of lossless conversions. - * - * @param c1 one type - * @param c2 another type - * @return their most common superclass or superinterface for purposes of lossless conversions. 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 getCommonLosslessConversionType(final Class c1, final Class c2) { - if(c1 == c2) { - return c1; - } else if (c1 == void.class || c2 == void.class) { - return Object.class; - } else if(isConvertibleWithoutLoss(c2, c1)) { - return c1; - } else if(isConvertibleWithoutLoss(c1, c2)) { - return c2; - } else if(c1.isPrimitive() && c2.isPrimitive()) { - if((c1 == byte.class && c2 == char.class) || (c1 == char.class && c2 == byte.class)) { - // byte + char = int - return int.class; - } else if((c1 == short.class && c2 == char.class) || (c1 == char.class && c2 == short.class)) { - // short + char = int - return int.class; - } else if((c1 == int.class && c2 == float.class) || (c1 == float.class && c2 == int.class)) { - // int + float = double - return double.class; - } - } - // For all other cases. This will handle long + (float|double) = Number case as well as boolean + anything = Object case too. - return getMostSpecificCommonTypeUnequalNonprimitives(c1, c2); - } - - private static Class getMostSpecificCommonTypeUnequalNonprimitives(final Class c1, final Class c2) { - final Class npc1 = c1.isPrimitive() ? getWrapperType(c1) : c1; - final Class npc2 = c2.isPrimitive() ? getWrapperType(c2) : c2; - final Set> a1 = getAssignables(npc1, npc2); - final Set> a2 = getAssignables(npc2, npc1); - 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. - final List> max = new ArrayList<>(); - outer: for(final Class clazz: a1) { - for(final Iterator> maxiter = max.iterator(); maxiter.hasNext();) { - final 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(final Class c1, final Class c2) { - final Set> s = new HashSet<>(); - collectAssignables(c1, c2, s); - return s; - } - - private static void collectAssignables(final Class c1, final Class c2, final Set> s) { - if(c1.isAssignableFrom(c2)) { - s.add(c1); - } - final Class sc = c1.getSuperclass(); - if(sc != null) { - collectAssignables(sc, c2, s); - } - final 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(final Collection> classes) { - final Map> map = new HashMap<>(); - for(final Class clazz: classes) { - map.put(clazz.getName(), clazz); - } - return map; - } - - private static Map invertMap(final Map map) { - final Map inverted = new IdentityHashMap<>(map.size()); - for(final 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 sourceType the type being converted from (call site type for parameter types, method type for return types) - * @param targetType the parameter type being converted to (method type for parameter types, call site type for return types) - * @return true if source type is method invocation convertible to target type. - */ - public static boolean isMethodInvocationConvertible(final Class sourceType, final Class targetType) { - if(targetType.isAssignableFrom(sourceType)) { - return true; - } - if(sourceType.isPrimitive()) { - if(targetType.isPrimitive()) { - return isProperPrimitiveSubtype(sourceType, targetType); - } - // Boxing + widening reference conversion - assert WRAPPER_TYPES.get(sourceType) != null : sourceType.getName(); - return targetType.isAssignableFrom(WRAPPER_TYPES.get(sourceType)); - } - if(targetType.isPrimitive()) { - final Class unboxedCallSiteType = PRIMITIVE_TYPES.get(sourceType); - return unboxedCallSiteType != null - && (unboxedCallSiteType == targetType || isProperPrimitiveSubtype(unboxedCallSiteType, targetType)); - } - return false; - } - - /** - * Determines whether a type can be converted to another without losing any precision. As a special case, - * void is considered convertible only to Object and void, while anything can be converted to void. This - * is because a target type of void means we don't care about the value, so the conversion is always - * permissible. - * - * @param sourceType the source type - * @param targetType the target type - * @return true if lossless conversion is possible - */ - public static boolean isConvertibleWithoutLoss(final Class sourceType, final Class targetType) { - if(targetType.isAssignableFrom(sourceType) || targetType == void.class) { - return true; - } - if(sourceType.isPrimitive()) { - if(sourceType == void.class) { - // Void should be losslessly representable by Object, either as null or as a custom value that - // can be set with DynamicLinkerFactory.setAutoConversionStrategy. - return targetType == Object.class; - } - if(targetType.isPrimitive()) { - return isProperPrimitiveLosslessSubtype(sourceType, targetType); - } - // Boxing + widening reference conversion - assert WRAPPER_TYPES.get(sourceType) != null : sourceType.getName(); - return targetType.isAssignableFrom(WRAPPER_TYPES.get(sourceType)); - } - // Can't convert from any non-primitive type to any primitive type without data loss because of null. - // Also, can't convert non-assignable reference types. - 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(final Class callSiteType, final Class methodType) { - // Widening or narrowing reference conversion - if(areAssignable(callSiteType, 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; - } - - /** - * Returns true if either of the types is assignable from the other. - * @param c1 one of the types - * @param c2 another one of the types - * @return true if either c1 is assignable from c2 or c2 is assignable from c1. - */ - public static boolean areAssignable(final Class c1, final Class c2) { - return c1.isAssignableFrom(c2) || c2.isAssignableFrom(c1); - } - - /** - * 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(final Class subType, final 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(final Class subType, final 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; - } - - /** - * Similar to {@link #isProperPrimitiveSubtype(Class, Class)}, except it disallows conversions from int and long to - * float, and from long to double, as those can lose precision. It also disallows conversion from and to char and - * anything else (similar to boolean) as char is not meant to be an arithmetic type. - * @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 that can be represented - * by the supertype without no precision loss. - */ - private static boolean isProperPrimitiveLosslessSubtype(final Class subType, final Class superType) { - if(superType == boolean.class || subType == boolean.class) { - return false; - } - if(superType == char.class || subType == char.class) { - return false; - } - if(subType == byte.class) { - return true; - } - if(subType == short.class) { - return superType != byte.class; - } - if(subType == int.class) { - return superType == long.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(final Map, Class> map, final Class clazz) { - if(clazz == null) { - return; - } - map.put(clazz, clazz); - addClassHierarchy(map, clazz.getSuperclass()); - for(final 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(final 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(final 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(final 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(final Class primitiveType) { - return WRAPPER_TYPES.get(primitiveType); - } - - /** - * Returns true if the passed type is a wrapper for a primitive type. - * @param type the examined type - * @return true if the passed type is a wrapper for a primitive type. - */ - public static boolean isWrapperType(final Class type) { - return PRIMITIVE_TYPES.containsKey(type); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* - * 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(final String op, final MethodType methodType) { - this.op = op; - this.methodType = methodType; - } - - @Override - public int getNameTokenCount() { - return 2; - } - - String getOp() { - return op; - } - - @Override - public String getNameToken(final 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(final MethodType newMethodType) { - return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new UnnamedDynCallSiteDescriptor(op, - newMethodType)); - } -} diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/package-info.java Thu Oct 22 11:12:39 2015 -0700 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015, 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. +*/ + +/** + *

Contains classes that make using Dynalink more convenient by providing + * basic implementations of some classes as well as various utilities. + *

+ * @since 1.9 + */ +@jdk.Exported +package jdk.internal.dynalink.support; diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/package.html --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/package.html Thu Oct 22 08:47:53 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ - - - - -

- 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 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Oct 22 11:12:39 2015 -0700 @@ -683,9 +683,9 @@ // (in)equality operators need the specialized JSType.toNumberFor[Strict]Equals. E.g. in the code snippet // "i < obj.size" (where i is primitive and obj.size is statically an object), ".size" will thus be allowed // to compile as: - // invokedynamic dyn:getProp|getElem|getMethod:size(Object;)D + // invokedynamic GET_PROPERTY:size(Object;)D // instead of the more costly: - // invokedynamic dyn:getProp|getElem|getMethod:size(Object;)Object + // invokedynamic GET_PROPERTY:size(Object;)Object // invokestatic JSType.toNumber(Object)D // Note also that even if this is allowed, we're only using it on operands that are non-optimistic, as // otherwise the logic for determining effective optimistic-ness would turn an optimistic double return @@ -1494,11 +1494,11 @@ void loadStack() { /* * We want to load 'eval' to check if it is indeed global builtin eval. - * If this eval call is inside a 'with' statement, dyn:getMethod|getProp|getElem + * If this eval call is inside a 'with' statement, GET_METHOD_PROPERTY * would be generated if ident is a "isFunction". But, that would result in a * bound function from WithObject. We don't want that as bound function as that * won't be detected as builtin eval. So, we make ident as "not a function" which - * results in "dyn:getProp|getElem|getMethod" being generated and so WithObject + * results in GET_PROPERTY being generated and so WithObject * would return unbounded eval function. * * Example: @@ -1525,7 +1525,7 @@ method._goto(invoke_direct_eval); method.label(is_not_eval); - // load this time but with dyn:getMethod|getProp|getElem + // load this time but with GET_METHOD_PROPERTY loadExpressionAsObject(ident); // Type.OBJECT as foo() makes no sense if foo == 3 // This is some scope 'eval' or global eval replaced by user // but not the built-in ECMAScript 'eval' function call diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java Thu Oct 22 11:12:39 2015 -0700 @@ -107,6 +107,7 @@ import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; import jdk.nashorn.internal.runtime.linker.Bootstrap; +import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.logging.DebugLogger; import jdk.nashorn.internal.runtime.options.Options; @@ -124,6 +125,8 @@ * including bytecode stack contents */ public class MethodEmitter { + private static final String EMPTY_NAME = NameCodec.encode(""); + /** The ASM MethodVisitor we are plugged into */ private final MethodVisitor method; @@ -2148,8 +2151,8 @@ debug("dynamic_new", "argcount=", argCount); final String signature = getDynamicSignature(Type.OBJECT, argCount); method.visitInvokeDynamicInsn( - msg != null && msg.length() < LARGE_STRING_THRESHOLD? "dyn:new:" + NameCodec.encode(msg) : "dyn:new", - signature, LINKERBOOTSTRAP, flags); + msg != null && msg.length() < LARGE_STRING_THRESHOLD? NameCodec.encode(msg) : EMPTY_NAME, + signature, LINKERBOOTSTRAP, flags | NashornCallSiteDescriptor.NEW); pushType(Type.OBJECT); //TODO fix result type return this; } @@ -2182,8 +2185,8 @@ final String signature = getDynamicSignature(returnType, argCount); // +1 because the function itself is the 1st parameter for dynamic calls (what you call - call target) debug(" signature", signature); method.visitInvokeDynamicInsn( - msg != null && msg.length() < LARGE_STRING_THRESHOLD? "dyn:call:" + NameCodec.encode(msg) : "dyn:call", - signature, LINKERBOOTSTRAP, flags); + msg != null && msg.length() < LARGE_STRING_THRESHOLD? NameCodec.encode(msg) : EMPTY_NAME, + signature, LINKERBOOTSTRAP, flags | NashornCallSiteDescriptor.CALL); pushType(returnType); return this; @@ -2220,8 +2223,8 @@ } popType(Type.SCOPE); - method.visitInvokeDynamicInsn(dynGetOperation(isMethod, isIndex) + ':' + NameCodec.encode(name), - Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags); + method.visitInvokeDynamicInsn(NameCodec.encode(name), + Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags | dynGetOperation(isMethod, isIndex)); pushType(type); convert(valueType); //most probably a nop @@ -2253,8 +2256,8 @@ popType(type); popType(Type.SCOPE); - method.visitInvokeDynamicInsn(dynSetOperation(isIndex) + ':' + NameCodec.encode(name), - methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags); + method.visitInvokeDynamicInsn(NameCodec.encode(name), + methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags | dynSetOperation(isIndex)); } /** @@ -2287,7 +2290,7 @@ final String signature = Type.getMethodDescriptor(resultType, Type.OBJECT /*e.g STRING->OBJECT*/, index); - method.visitInvokeDynamicInsn(dynGetOperation(isMethod, true), signature, LINKERBOOTSTRAP, flags); + method.visitInvokeDynamicInsn(EMPTY_NAME, signature, LINKERBOOTSTRAP, flags | dynGetOperation(isMethod, true)); pushType(resultType); if (result.isBoolean()) { @@ -2331,7 +2334,9 @@ final Type receiver = popType(Type.OBJECT); assert receiver.isObject(); - method.visitInvokeDynamicInsn("dyn:setElem|setProp", methodDescriptor(void.class, receiver.getTypeClass(), index.getTypeClass(), value.getTypeClass()), LINKERBOOTSTRAP, flags); + method.visitInvokeDynamicInsn(EMPTY_NAME, + methodDescriptor(void.class, receiver.getTypeClass(), index.getTypeClass(), value.getTypeClass()), + LINKERBOOTSTRAP, flags | NashornCallSiteDescriptor.SET_ELEMENT); } /** @@ -2501,16 +2506,16 @@ } } - private static String dynGetOperation(final boolean isMethod, final boolean isIndex) { + private static int dynGetOperation(final boolean isMethod, final boolean isIndex) { if (isMethod) { - return isIndex ? "dyn:getMethod|getElem|getProp" : "dyn:getMethod|getProp|getElem"; + return isIndex ? NashornCallSiteDescriptor.GET_METHOD_ELEMENT : NashornCallSiteDescriptor.GET_METHOD_PROPERTY; } else { - return isIndex ? "dyn:getElem|getProp|getMethod" : "dyn:getProp|getElem|getMethod"; + return isIndex ? NashornCallSiteDescriptor.GET_ELEMENT : NashornCallSiteDescriptor.GET_PROPERTY; } } - private static String dynSetOperation(final boolean isIndex) { - return isIndex ? "dyn:setElem|setProp" : "dyn:setProp|setElem"; + private static int dynSetOperation(final boolean isIndex) { + return isIndex ? NashornCallSiteDescriptor.SET_ELEMENT : NashornCallSiteDescriptor.SET_PROPERTY; } private Type emitLocalVariableConversion(final LocalVariableConversion conversion, final boolean onlySymbolLiveValue) { diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionCall.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionCall.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionCall.java Thu Oct 22 11:12:39 2015 -0700 @@ -25,14 +25,16 @@ package jdk.nashorn.internal.ir; +import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; + /** * Interface used by AccessNodes, IndexNodes and IdentNodes to signal that when evaluated, their value will be treated * as a function and immediately invoked, e.g. {@code foo()}, {@code foo.bar()} or {@code foo[bar]()}. Used to customize * the priority of composite dynamic operations when emitting {@code INVOKEDYNAMIC} instructions that implement them, * namely prioritize {@code getMethod} over {@code getElem} or {@code getProp}. An access or ident node with isFunction - * set to true will be emitted as {@code dyn:getMethod|getProp|getElem} while one with it set to false will be emitted - * as {@code dyn:getProp|getElem|getMethod}. Similarly, an index node with isFunction set to true will be emitted as - * {@code dyn:getMethod|getElem|getProp} while the one set to false will be emitted as {@code dyn:getElem|getProp|getMethod}. + * set to true will be emitted as {@link NashornCallSiteDescriptor#GET_METHOD_PROPERTY} while one with it set to false will be emitted + * as {@link NashornCallSiteDescriptor#GET_PROPERTY}. Similarly, an index node with isFunction set to true will be emitted as + * {@link NashornCallSiteDescriptor#GET_METHOD_ELEMENT} while the one set to false will be emitted as {@link NashornCallSiteDescriptor#GET_ELEMENT}. */ public interface FunctionCall { /** diff -r 15a50c5e0668 -r 1c5439fcdc26 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java Thu Oct 22 08:47:53 2015 -0700 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/debug/NashornTextifier.java Thu Oct 22 11:12:39 2015 -0700 @@ -39,6 +39,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import jdk.internal.dynalink.support.NameCodec; import jdk.internal.org.objectweb.asm.Attribute; import jdk.internal.org.objectweb.asm.Handle; import jdk.internal.org.objectweb.asm.Label; @@ -48,6 +49,7 @@ import jdk.internal.org.objectweb.asm.util.Printer; import jdk.internal.org.objectweb.asm.util.TraceSignatureVisitor; import jdk.nashorn.internal.runtime.ScriptEnvironment; +import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; /** @@ -55,6 +57,7 @@ * Also supports dot formats if --print-code has arguments */ public final class NashornTextifier extends Printer { + private static final String BOOTSTRAP_CLASS_NAME = Bootstrap.class.getName().replace('.', '/'); private String currentClassName; private Iterator