# 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:
+ *
+ * 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:
+ *
- *
- * 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:
*
*
- *
You're expected to provide a {@link GuardingDynamicLinker} for your own
- * language. If your runtime doesn't have its own language and/or object model
- * (i.e., it's a generic scripting shell), you don't need to implement a dynamic
- * linker; you would simply not invoke the {@code setPrioritizedLinker} method
- * on the factory, or even better, simply use {@link DefaultBootstrapper}.
+ *
You are expected to provide a {@link GuardingDynamicLinker} for your own
+ * language. If your runtime doesn't have its own object model or type
+ * conversions, you don't need to implement a {@code GuardingDynamicLinker}; you
+ * would simply not invoke the {@code setPrioritizedLinker} method on the factory.
*
*
The performance of the programs can depend on your choice of the class to
- * represent call sites. The above example used {@link MonomorphicCallSite}, but
- * you might want to use {@link ChainedCallSite} instead. You'll need to
- * experiment and decide what fits your language runtime the best. You can
- * subclass either of these or roll your own if you need to.
+ * represent call sites. The above example used
+ * {@link SimpleRelinkableCallSite}, but you might want to use
+ * {@link ChainedCallSite} instead. You'll need to experiment and decide what
+ * fits your runtime the best. You can further subclass either of these or
+ * implement your own.
*
*
You also need to provide {@link CallSiteDescriptor}s to your call sites.
* They are immutable objects that contain all the information about the call
- * site: the class performing the lookups, the name of the method being invoked,
- * and the method signature. The library has a default {@link CallSiteDescriptorFactory}
- * for descriptors that you can use, or you can create your own descriptor
- * classes, especially if you need to add further information (values passed in
- * additional parameters to the bootstrap method) to them.
+ * site: the class performing the lookups, the operation being invoked, and the
+ * method signature. You will have to supply your own scheme to encode and
+ * decode operations in the call site name or static parameters, that is why
+ * in the above example the {@code parseOperation} method is left unimplemented.
*
*
*/
@@ -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 extends GuardingDynamicLinker> prioritizedLinkers;
private List extends GuardingDynamicLinker> 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 extends GuardingDynamicLinker> 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 extends GuardingDynamicLinker> 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 extends GuardingTypeConverterFactory> 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 extends Annotation> 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 extends Throwable> 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 extends Throwable> 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 extends Throwable> 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.
+ *
- 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 extends GuardingDynamicLinker> 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 extends TypeBasedGuardingDynamicLinker> 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 extends GuardingDynamicLinker> 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 Class>refc, 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