# HG changeset patch # User lana # Date 1449077846 28800 # Node ID 84eaea8d05744d50d6528f56c9c0772ba69f3504 # Parent 5ac6287ec71aafe021cc839d8bc828108d23aaba# Parent cc9f05d3caf0c52b12a28ec6e267431360803775 Merge diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/make/BuildNashorn.gmk --- a/nashorn/make/BuildNashorn.gmk Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/make/BuildNashorn.gmk Wed Dec 02 09:37:26 2015 -0800 @@ -34,7 +34,7 @@ include TextFileProcessing.gmk JDK_CLASSES := $(call PathList, $(strip $(addprefix $(JDK_OUTPUTDIR)/modules/, \ - java.base java.logging java.scripting))) + java.base java.logging java.scripting jdk.dynalink))) NASHORN_JAR := $(IMAGES_OUTPUTDIR)/nashorn.jar diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/make/build.xml --- a/nashorn/make/build.xml Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/make/build.xml Wed Dec 02 09:37:26 2015 -0800 @@ -52,6 +52,14 @@ + + + + @@ -155,7 +163,7 @@ - + @@ -244,6 +252,7 @@ + @@ -263,6 +272,18 @@ + + + + + + + + + + @@ -321,14 +342,20 @@ - + + + + + - + + + @@ -432,6 +459,8 @@ + + @@ -603,7 +632,7 @@ - + @@ -773,6 +802,20 @@ + + + + + + + + + + + + + + diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/make/nbproject/project.xml --- a/nashorn/make/nbproject/project.xml Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/make/nbproject/project.xml Wed Dec 02 09:37:26 2015 -0800 @@ -50,6 +50,10 @@ ../src/jdk.scripting.nashorn/share/classes + + ../src/jdk.scripting.nashorn.shell/share/classes + + java ../test/src @@ -74,8 +78,14 @@ UTF-8 - - ../src/jdk.scripting.nashorn.shell/share/classes + + java + ../src/jdk.dynalink/share/classes + UTF-8 + + + + ../src/jdk.dynalink/share/classes @@ -153,6 +163,10 @@ ../src/jdk.scripting.nashorn.shell/share/classes + + + ../src/jdk.dynalink/share/classes + build.xml @@ -189,6 +203,10 @@ ../src/jdk.scripting.nashorn.shell/share/classes 1.8 + + ../src/jdk.dynalink/share/classes + 1.8 + diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/make/project.properties --- a/nashorn/make/project.properties Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/make/project.properties Wed Dec 02 09:37:26 2015 -0800 @@ -85,6 +85,7 @@ # jars refererred file.reference.testng.jar=${test.lib}${file.separator}testng.jar +file.reference.asmtools.jar=${test.lib}${file.separator}asmtools-60.jar # Set testng verbose level # From TestNG docs: "the verbosity level (0 to 10 where 10 is most detailed) @@ -211,6 +212,12 @@ # file containing test262 tests to be excluded # test262-test-sys-prop.test.js.excludes.file=${test262.dir}/test/config/excludelist.xml +# list of test262 files to be excluded +test262-test-sys-prop.test.js.exclude.list=\ + ${test262.suite.dir}/ch07/7.4/S7.4_A6.js \ + ${test262.suite.dir}/ch07/7.8/7.8.5/S7.8.5_A1.4_T2.js \ + ${test262.suite.dir}/ch15/15.2/15.2.3/15.2.3.6/15.2.3.6-4-170.js + # list of test262 test dirs to be excluded test262-test-sys-prop.test.js.exclude.dir=\ ${test262.suite.dir}/intl402/ \ @@ -269,10 +276,12 @@ ${nashorn.internal.tests.jar}${path.separator}\ ${nashorn.api.tests.jar} +dynalink.module.src.dir=src/jdk.dynalink/share/classes nashorn.module.src.dir=src/jdk.scripting.nashorn/share/classes nashorn.shell.module.src.dir=src/jdk.scripting.nashorn.shell/share/classes -src.dir=${nashorn.module.src.dir}${path.separator}\ +src.dir=${dynalink.module.src.dir}${path.separator}\ + ${nashorn.module.src.dir}${path.separator}\ ${nashorn.shell.module.src.dir}${path.separator}\ ${jdk.jline.src.dir} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/samples/DOMLinkerExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/samples/DOMLinkerExporter.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.List; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.CompositeOperation; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.GuardingDynamicLinkerExporter; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.support.Guards; +import jdk.dynalink.linker.support.Lookup; +import org.w3c.dom.Attr; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.Element; + +/** + * This is a dynalink pluggable linker (see http://openjdk.java.net/jeps/276). + * This linker handles XML DOM Element objects specially. This linker links + * special properties starting with "_" and treats those as child element names + * to access. This kind of child element access makes it easy to write XML DOM + * accessing scripts. See for example ./dom_linker_gutenberg.js. + */ +public final class DOMLinkerExporter extends GuardingDynamicLinkerExporter { + static { + System.out.println("pluggable dynalink DOM linker loaded"); + } + + // return List of child Elements of the given Element matching the given name. + private static List getChildElements(Element elem, String name) { + NodeList nodeList = elem.getChildNodes(); + List childElems = new ArrayList<>(); + int len = nodeList.getLength(); + for (int i = 0; i < len; i++) { + Node node = nodeList.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE && + ((Element)node).getTagName().equals(name)) { + childElems.add((Element)node); + } + } + return childElems; + } + + // method that returns either unique child element matching given name + // or a list of child elements of that name (if there are more than one matches). + public static Object getElementsByName(Object elem, final String name) { + List elems = getChildElements((Element)elem, name); + return elems.size() == 1? elems.get(0) : elems; + } + + // method to extract text context under a given DOM Element + public static Object getElementText(Object elem) { + NodeList nodeList = ((Element)elem).getChildNodes(); + int len = nodeList.getLength(); + StringBuilder text = new StringBuilder(); + for (int i = 0; i < len; i++) { + Node node = nodeList.item(i); + if (node.getNodeType() == Node.TEXT_NODE) { + text.append(node.getNodeValue()); + } + } + return text.toString(); + } + + private static final MethodHandle ELEMENTS_BY_NAME; + private static final MethodHandle ELEMENT_TEXT; + private static final MethodHandle IS_ELEMENT; + static { + ELEMENTS_BY_NAME = Lookup.PUBLIC.findStatic(DOMLinkerExporter.class, + "getElementsByName", + MethodType.methodType(Object.class, Object.class, String.class)); + ELEMENT_TEXT = Lookup.PUBLIC.findStatic(DOMLinkerExporter.class, + "getElementText", + MethodType.methodType(Object.class, Object.class)); + IS_ELEMENT = Guards.isInstance(Element.class, MethodType.methodType(Boolean.TYPE, Object.class)); + } + + @Override + public List get() { + final ArrayList linkers = new ArrayList<>(); + linkers.add(new TypeBasedGuardingDynamicLinker() { + @Override + public boolean canLinkType(final Class type) { + return Element.class.isAssignableFrom(type); + } + + @Override + public GuardedInvocation getGuardedInvocation(LinkRequest request, + LinkerServices linkerServices) throws Exception { + final Object self = request.getReceiver(); + if (! (self instanceof Element)) { + return null; + } + + CallSiteDescriptor desc = request.getCallSiteDescriptor(); + Operation op = desc.getOperation(); + Object name = NamedOperation.getName(op); + boolean getProp = CompositeOperation.contains( + NamedOperation.getBaseOperation(op), + StandardOperation.GET_PROPERTY); + if (getProp && name instanceof String) { + String nameStr = (String)name; + + // Treat names starting with "_" as special names. + // Everything else is linked other dynalink bean linker! + // This avoids collision with Java methods of org.w3c.dom.Element class + // Assumption is that Java APIs won't start with "_" character!! + if (nameStr.equals("_")) { + // short-hand to get text content under a given DOM Element + return new GuardedInvocation(ELEMENT_TEXT, IS_ELEMENT); + } else if (nameStr.startsWith("_")) { + return new GuardedInvocation( + MethodHandles.insertArguments(ELEMENTS_BY_NAME, 1, nameStr.substring(1)), + IS_ELEMENT); + } + + } + + return null; + } + }); + return linkers; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/samples/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/samples/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,2 @@ +DOMLinkerExporter +UnderscoreNameLinkerExporter diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/samples/Main.asm --- a/nashorn/samples/Main.asm Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/samples/Main.asm Wed Dec 02 09:37:26 2015 -0800 @@ -38,66 +38,128 @@ // // See also: https://wiki.openjdk.java.net/display/CodeTools/asmtools // -// NOTE: Uses nashorn internals and so *may* break with later nashorn! +// NOTE: Uses dynalink API defined by JEP-276 (http://openjdk.java.net/jeps/276) super public class Main version 52:0 { +private static final Field linker:"Ljdk/dynalink/DynamicLinker;"; +/* + static { + // create dynalink linker factory + final DynamicLinkerFactory factory = new DynamicLinkerFactory(); + + // create standard linker that can handle Java POJOs + linker = factory.createLinker(); + } +*/ +static Method "":"()V" + stack 2 locals 1 +{ + new class jdk/dynalink/DynamicLinkerFactory; + dup; + invokespecial Method jdk/dynalink/DynamicLinkerFactory."":"()V"; + astore_0; + aload_0; + invokevirtual Method jdk/dynalink/DynamicLinkerFactory.createLinker:"()Ljdk/dynalink/DynamicLinker;"; + putstatic Field linker:"Ljdk/dynalink/DynamicLinker;"; + return; +} + +/* + // Bootstrap method used with invokedynamic methods + + public static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) { + // use dynalink linker to perform the actual linking + return linker.link( + new SimpleRelinkableCallSite( + new CallSiteDescriptor( + MethodHandles.publicLookup(), + new NamedOperation(StandardOperation.GET_PROPERTY, name), type) + ) + ); + } + + */ +public static Method bootstrap:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;" + stack 10 locals 3 +{ + getstatic Field linker:"Ljdk/dynalink/DynamicLinker;"; + new class jdk/dynalink/support/SimpleRelinkableCallSite; + dup; + new class jdk/dynalink/CallSiteDescriptor; + dup; + invokestatic Method java/lang/invoke/MethodHandles.publicLookup:"()Ljava/lang/invoke/MethodHandles$Lookup;"; + new class jdk/dynalink/NamedOperation; + dup; + getstatic Field jdk/dynalink/StandardOperation.GET_PROPERTY:"Ljdk/dynalink/StandardOperation;"; + aload_1; + invokespecial Method jdk/dynalink/NamedOperation."":"(Ljdk/dynalink/Operation;Ljava/lang/Object;)V"; + aload_2; + invokespecial Method jdk/dynalink/CallSiteDescriptor."":"(Ljava/lang/invoke/MethodHandles$Lookup;Ljdk/dynalink/Operation;Ljava/lang/invoke/MethodType;)V"; + invokespecial Method jdk/dynalink/support/SimpleRelinkableCallSite."":"(Ljdk/dynalink/CallSiteDescriptor;)V"; + invokevirtual Method jdk/dynalink/DynamicLinker.link:"(Ljdk/dynalink/RelinkableCallSite;)Ljdk/dynalink/RelinkableCallSite;"; + checkcast class java/lang/invoke/CallSite; + areturn; +} + +// default constructor that does nothing! public Method "":"()V" stack 1 locals 1 { - aload_0; - invokespecial Method java/lang/Object."":"()V"; - return; + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; } public static Method main:"([Ljava/lang/String;)V" stack 2 locals 2 { - // List l = new ArrayList(); - new class java/util/ArrayList; - dup; - invokespecial Method java/util/ArrayList."":"()V"; - astore_1; - aload_1; + // List l = new ArrayList(); + new class java/util/ArrayList; + dup; + invokespecial Method java/util/ArrayList."":"()V"; + astore_1; + aload_1; - // l.add("hello"); - ldc String "hello"; - invokeinterface InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z", 2; - pop; + // l.add("hello"); + ldc String "hello"; + invokeinterface InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z", 2; + pop; - // l.add("world"); - aload_1; - ldc String "world"; - invokeinterface InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z", 2; - pop; + // l.add("world"); + aload_1; + ldc String "world"; + invokeinterface InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z", 2; + pop; - // printLength(l); - aload_1; - invokestatic Method printLength:"(Ljava/lang/Object;)V"; + // printLength(l); + aload_1; + invokestatic Method printLength:"(Ljava/lang/Object;)V"; - // printLength(args); // args is argument of main method - aload_0; - invokestatic Method printLength:"(Ljava/lang/Object;)V"; - return; + // printLength(args); // args is argument of main method + aload_0; + invokestatic Method printLength:"(Ljava/lang/Object;)V"; + return; } private static Method printLength:"(Ljava/lang/Object;)V" stack 2 locals 1 { - getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; - aload_0; - - // Using nashorn embedded dynalink linker with the following invokedynamic - // 'length' property on a bean - arrays, lists supported + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + aload_0; - invokedynamic InvokeDynamic REF_invokeStatic:jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;":"dyn:getProp|getElem|getMethod:length":"(Ljava/lang/Object;)Ljava/lang/Object;" int 0; + // Using bootstrap method in this class with the following invokedynamic + // which uses dynalink linker. Dynalink's bean linker handles Java beans. + // 'length' property on a bean - arrays, lists supported - // print 'length' value - invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/Object;)V"; - return; + invokedynamic InvokeDynamic REF_invokeStatic:Main.bootstrap:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;":"length":"(Ljava/lang/Object;)Ljava/lang/Object;"; + + // print 'length' value + invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/Object;)V"; + return; } } // end Class Main diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/samples/Main.class Binary file nashorn/samples/Main.class has changed diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/samples/UnderscoreNameLinkerExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/samples/UnderscoreNameLinkerExporter.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; +import java.util.regex.Matcher; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.CompositeOperation; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.CompositeOperation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.GuardingDynamicLinkerExporter; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.support.SimpleLinkRequest; + +/** + * This is a dynalink pluggable linker (see http://openjdk.java.net/jeps/276). + * This linker translater underscore_separated method names to CamelCase names + * used in Java APIs. + */ +public final class UnderscoreNameLinkerExporter extends GuardingDynamicLinkerExporter { + static { + System.out.println("pluggable dynalink underscore name linker loaded"); + } + + private static final Pattern UNDERSCORE_NAME = Pattern.compile("_(.)"); + + // translate underscore_separated name as a CamelCase name + private static String translateToCamelCase(String name) { + Matcher m = UNDERSCORE_NAME.matcher(name); + StringBuilder buf = new StringBuilder(); + while (m.find()) { + m.appendReplacement(buf, m.group(1).toUpperCase()); + } + m.appendTail(buf); + return buf.toString(); + } + + // locate the first standard operation from the call descriptor + private static StandardOperation getFirstStandardOperation(final CallSiteDescriptor desc) { + final Operation base = NamedOperation.getBaseOperation(desc.getOperation()); + if (base instanceof StandardOperation) { + return (StandardOperation)base; + } else if (base instanceof CompositeOperation) { + final CompositeOperation cop = (CompositeOperation)base; + for(int i = 0; i < cop.getOperationCount(); ++i) { + final Operation op = cop.getOperation(i); + if (op instanceof StandardOperation) { + return (StandardOperation)op; + } + } + } + return null; + } + + @Override + public List get() { + final ArrayList linkers = new ArrayList<>(); + linkers.add(new GuardingDynamicLinker() { + @Override + public GuardedInvocation getGuardedInvocation(LinkRequest request, + LinkerServices linkerServices) throws Exception { + final Object self = request.getReceiver(); + CallSiteDescriptor desc = request.getCallSiteDescriptor(); + Operation op = desc.getOperation(); + Object name = NamedOperation.getName(op); + // is this a named GET_METHOD? + boolean isGetMethod = getFirstStandardOperation(desc) == StandardOperation.GET_METHOD; + if (isGetMethod && name instanceof String) { + String str = (String)name; + if (str.indexOf('_') == -1) { + return null; + } + + String nameStr = translateToCamelCase(str); + // create a new call descriptor to use translated name + CallSiteDescriptor newDesc = new CallSiteDescriptor( + desc.getLookup(), + new NamedOperation(NamedOperation.getBaseOperation(op), nameStr), + desc.getMethodType()); + // create a new Link request to link the call site with translated name + LinkRequest newRequest = new SimpleLinkRequest(newDesc, + request.isCallSiteUnstable(), request.getArguments()); + // return guarded invocation linking the translated request + return linkerServices.getGuardedInvocation(newRequest); + } + + return null; + } + }); + return linkers; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/samples/dom_linker.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/samples/dom_linker.js Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,48 @@ +#! simple dom linker example + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This script assumes you've built jdk9 or using latest +// jdk9 image and put the 'bin' directory in the PATH + +$EXEC.throwOnError=true + +// compile DOMLinkerExporter +`javac -cp ../dist/nashorn.jar DOMLinkerExporter.java` + +// make a jar file out of pluggable linker +`jar cvf dom_linker.jar DOMLinkerExporter*.class META-INF/` + +// run a sample script that uses pluggable linker +// but make sure classpath points to the pluggable linker jar! + +`jjs -cp dom_linker.jar dom_linker_gutenberg.js` diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/samples/dom_linker_gutenberg.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/samples/dom_linker_gutenberg.js Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,117 @@ +#// Usage: jjs -cp dom_linker.jar -scripting dom_linker_gutenberg.js + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This script depends on DOM Element dynalink linker! +// Without that linker, this script will fail to run! + +// Simple example that demonstrates reading XML Rss feed +// to generate a HTML file from script and show it by browser. +// Uses XML DOM parser along with DOM element pluggable dynalink linker +// for ease of navigation of DOM (child) elements by name. + +// Java classes used +var DocBuilderFac = Java.type("javax.xml.parsers.DocumentBuilderFactory"); +var Node = Java.type("org.w3c.dom.Node"); +var File = Java.type("java.io.File"); +var FileWriter = Java.type("java.io.FileWriter"); +var PrintWriter = Java.type("java.io.PrintWriter"); + +// parse XML from uri and return Document +function parseXML(uri) { + var docBuilder = DocBuilderFac.newInstance().newDocumentBuilder(); + return docBuilder["parse(java.lang.String)"](uri); +} + +// generate HTML using here-doc and string interpolation +function getBooksHtml() { + var doc = parseXML("http://www.gutenberg.org/cache/epub/feeds/today.rss"); + // wrap document root Element as script convenient object + var rss = doc.documentElement; + + var str = < +${rss._channel._title._} + +

${rss._channel._description._}

+

+Published on ${rss._channel._pubDate._} +

+ +HEAD + + var items = rss._channel._item; + for each (var i in items) { + str += < +
${i._title._}
+
${i._description._}
+ + +LIST + } + str += < + + +END + return str; +} + +// write the string to the given file +function writeTo(file, str) { + var w = new PrintWriter(new FileWriter(file)); + try { + w.print(str); + } finally { + w.close(); + } +} + +// generate books HTML +var str = getBooksHtml(); + +// write to file. __DIR__ is directory where +// this script is stored. +var file = new File(__DIR__ + "books.html"); +writeTo(file, str); + +// show it by desktop browser +try { + var Desktop = Java.type("java.awt.Desktop"); + Desktop.desktop.browse(file.toURI()); +} catch (e) { + print(e); +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/samples/underscore.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/samples/underscore.js Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,42 @@ +#// Usage: jjs -cp underscore_linker.jar -scripting underscore.js + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This script depends on underscore name to CamelCase name +// translator dynalink linker! Without that linker, this script +// will fail to run! + +var S = java.util.stream.Stream +S.of(45, 54654,546,435).for_each(print) +print("hello".char_at(2)) +print(4354.45.value_of()) +print(java.lang.System.get_properties()) diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/samples/underscore_linker.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/samples/underscore_linker.js Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,50 @@ +# underscore name translator dynalink linker example + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This script assumes you've built jdk9 or using latest +// jdk9 image and put the 'bin' directory in the PATH + +$EXEC.throwOnError=true + +// compile UnderscoreNameLinkerExporter +`javac -cp ../dist/nashorn.jar UnderscoreNameLinkerExporter.java` + +// make a jar file out of pluggable linker +`jar cvf underscore_linker.jar UnderscoreNameLinkerExporter*.class META-INF/` + +// run a sample script that uses pluggable linker +// but make sure classpath points to the pluggable linker jar! + +`jjs -cp underscore_linker.jar underscore.js` +print($OUT) + diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/CallSiteDescriptor.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,287 @@ +/* + * 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.dynalink; + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import java.util.Objects; + +/** + * 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 class CallSiteDescriptor { + private final MethodHandles.Lookup lookup; + private final Operation operation; + private final MethodType methodType; + + /** + * The name of a runtime permission to invoke the {@link #getLookup()} + * method. + */ + public static final String GET_LOOKUP_PERMISSION_NAME = "dynalink.getLookup"; + + private static final RuntimePermission GET_LOOKUP_PERMISSION = new RuntimePermission(GET_LOOKUP_PERMISSION_NAME); + + /** + * 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 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 operation at the call site. + * @return the operation at the call site. + */ + 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 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 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()}. + */ + 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. 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. + */ + 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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/ClassMap.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/ClassMap.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.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.dynalink.internal.AccessControlContextFactory; +import jdk.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/CompositeOperation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/CompositeOperation.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.dynalink; + +import java.util.Arrays; +import java.util.Objects; + +/** + * Describes an operation that is composed of at least two other operations. The + * component operations are treated as alternatives to each other in order of + * preference. The semantics of the composite operation is "first successful". + * That is, a composite of {@code GET_PROPERTY|GET_ELEMENT:color} should be + * interpreted as get the property named "color" on the object, but if the + * property does not exist, then get the collection element named "color" + * instead. + *

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

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

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

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

+ * Not all compositions make sense. Typically, any combination in any order of + * standard getter operations {@code GET_PROPERTY}, {@code GET_ELEMENT}, and + * {@code GET_METHOD} make sense, as do combinations of {@code SET_PROPERTY} and + * {@code SET_ELEMENT}; other standard operations should not be combined. The + * constructor will allow any combination of operations, though. + */ +public final 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 instanceof CompositeOperation) { + return Arrays.equals(operations, ((CompositeOperation)obj).operations); + } + return false; + } + + /** + * 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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.dynalink; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.MutableCallSite; +import java.util.Objects; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardedInvocationTransformer; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.support.Lookup; +import jdk.dynalink.linker.support.SimpleLinkRequest; +import jdk.dynalink.support.ChainedCallSite; +import jdk.dynalink.support.SimpleRelinkableCallSite; + +/** + * The linker for {@link RelinkableCallSite} objects. A dynamic linker is a main + * objects when using Dynalink, it coordinates linking of call sites with + * linkers of available language runtimes that are represented by + * {@link GuardingDynamicLinker} objects (you only need to deal with these if + * you are yourself implementing a language runtime with its own object model + * and/or type conversions). To use Dynalink, you have to create one or more + * dynamic linkers using a {@link DynamicLinkerFactory}. Subsequently, you need + * to invoke its {@link #link(RelinkableCallSite)} method from + * {@code invokedynamic} bootstrap methods to let it manage all the call sites + * they create. Usual usage would be to create at least one class per language + * runtime to contain one linker instance as: + *

+ *
+ * class MyLanguageRuntime {
+ *     private static final GuardingDynamicLinker myLanguageLinker = new MyLanguageLinker();
+ *     private static final DynamicLinker dynamicLinker = createDynamicLinker();
+ *
+ *     private static DynamicLinker createDynamicLinker() {
+ *         final DynamicLinkerFactory factory = new DynamicLinkerFactory();
+ *         factory.setPrioritizedLinker(myLanguageLinker);
+ *         return factory.createLinker();
+ *     }
+ *
+ *     public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {
+ *         return dynamicLinker.link(
+ *             new SimpleRelinkableCallSite(
+ *                 new CallSiteDescriptor(lookup, parseOperation(name), type)));
+ *     }
+ *
+ *     private static Operation parseOperation(String name) {
+ *         ...
+ *     }
+ * }
+ * 
+ * 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 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 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 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.
  • + * + *
+ */ +public final class DynamicLinker { + private static final String CLASS_NAME = DynamicLinker.class.getName(); + private static final String RELINK_METHOD_NAME = "relink"; + + private static final String INITIAL_LINK_CLASS_NAME = "java.lang.invoke.MethodHandleNatives"; + private static final String INITIAL_LINK_METHOD_NAME = "linkCallSite"; + private static final String INVOKE_PACKAGE_PREFIX = "java.lang.invoke."; + + private final LinkerServices linkerServices; + private final GuardedInvocationTransformer prelinkTransformer; + private final boolean syncOnRelink; + private final int unstableRelinkThreshold; + + /** + * Creates a new dynamic linker. + * + * @param linkerServices the linkerServices used by the linker, created by the factory. + * @param 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 GuardedInvocationTransformer prelinkTransformer, + final boolean syncOnRelink, final int unstableRelinkThreshold) { + if(unstableRelinkThreshold < 0) { + throw new IllegalArgumentException("unstableRelinkThreshold < 0"); + } + this.linkerServices = linkerServices; + this.prelinkTransformer = prelinkTransformer; + this.syncOnRelink = syncOnRelink; + this.unstableRelinkThreshold = unstableRelinkThreshold; + } + + /** + * Links an invokedynamic call site. It will install a method handle into + * the call site that invokes the relinking mechanism of this linker. Next + * time the call site is invoked, it will be linked for the actual arguments + * it was invoked with. + * + * @param the particular subclass of {@link RelinkableCallSite} for + * which to create a link. + * @param callSite the call site to link. + * + * @return the callSite, for easy call chaining. + */ + public T link(final T callSite) { + callSite.initialize(createRelinkAndInvokeMethod(callSite, 0)); + return callSite; + } + + /** + * Returns the object representing the 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. + */ + public LinkerServices getLinkerServices() { + return linkerServices; + } + + private static final MethodHandle RELINK = Lookup.findOwnSpecial(MethodHandles.lookup(), RELINK_METHOD_NAME, + MethodHandle.class, RelinkableCallSite.class, int.class, Object[].class); + + private MethodHandle createRelinkAndInvokeMethod(final RelinkableCallSite callSite, final int relinkCount) { + // Make a bound MH of invoke() for this linker and call site + final MethodHandle boundRelinker = MethodHandles.insertArguments(RELINK, 0, this, callSite, Integer.valueOf( + relinkCount)); + // Make a MH that gathers all arguments to the invocation into an Object[] + final MethodType type = callSite.getDescriptor().getMethodType(); + final MethodHandle collectingRelinker = boundRelinker.asCollector(Object[].class, type.parameterCount()); + return MethodHandles.foldArguments(MethodHandles.exactInvoker(type), collectingRelinker.asType( + type.changeReturnType(MethodHandle.class))); + } + + /** + * Relinks a call site conforming to the invocation arguments. + * + * @param callSite the call site itself + * @param arguments arguments to the invocation + * + * @return return the method handle for the invocation + * + * @throws Exception rethrows any exception thrown by the linkers + */ + @SuppressWarnings("unused") + private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception { + final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor(); + final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0; + final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold; + final LinkRequest linkRequest = new SimpleLinkRequest(callSiteDescriptor, callSiteUnstable, arguments); + + GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest); + + // None found - throw an exception + if(guardedInvocation == null) { + throw new NoSuchDynamicMethodException(callSiteDescriptor.toString()); + } + + // 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 = prelinkTransformer.filter(guardedInvocation, linkRequest, linkerServices); + Objects.requireNonNull(guardedInvocation); + + int newRelinkCount = relinkCount; + // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until + // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink + // has already executed once for the unstable call site; we only want the call site to throw away its current + // linkage once, when it transitions to unstable. + if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) { + callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount)); + } else { + callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount)); + } + if(syncOnRelink) { + MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite }); + } + return guardedInvocation.getInvocation(); + } + + /** + * 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 + * site is being linked. + */ + public static StackTraceElement getLinkedCallSiteLocation() { + final StackTraceElement[] trace = new Throwable().getStackTrace(); + for(int i = 0; i < trace.length - 1; ++i) { + final StackTraceElement frame = trace[i]; + // If we found any of our linking entry points on the stack... + if(isRelinkFrame(frame) || isInitialLinkFrame(frame)) { + // ... then look for the first thing calling it that isn't j.l.invoke + for (int j = i + 1; j < trace.length; ++j) { + final StackTraceElement frame2 = trace[j]; + if (!frame2.getClassName().startsWith(INVOKE_PACKAGE_PREFIX)) { + return frame2; + } + } + } + } + return null; + } + + /** + * Returns {@code true} if the frame represents {@code MethodHandleNatives.linkCallSite()}, + * the frame immediately on top of the call site frame when the call site is + * being linked for the first time. + * + * @param frame the frame + * + * @return {@code true} if this frame represents {@code MethodHandleNatives.linkCallSite()}. + */ + private static boolean isInitialLinkFrame(final StackTraceElement frame) { + return testFrame(frame, INITIAL_LINK_METHOD_NAME, INITIAL_LINK_CLASS_NAME); + } + + /** + * Returns {@code true} if the frame represents {@code DynamicLinker.relink()}, + * the frame immediately on top of the call site frame when the call site is + * being relinked (linked for second and subsequent times). + * + * @param frame the frame + * + * @return {@code true} if this frame represents {@code DynamicLinker.relink()}. + */ + private static boolean isRelinkFrame(final StackTraceElement frame) { + return testFrame(frame, RELINK_METHOD_NAME, CLASS_NAME); + } + + private static boolean testFrame(final StackTraceElement frame, final String methodName, final String className) { + return methodName.equals(frame.getMethodName()) && className.equals(frame.getClassName()); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/DynamicLinkerFactory.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,527 @@ +/* + * 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.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.dynalink.beans.BeansLinker; +import jdk.dynalink.internal.AccessControlContextFactory; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardedInvocationTransformer; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.GuardingDynamicLinkerExporter; +import jdk.dynalink.linker.GuardingTypeConverterFactory; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.MethodHandleTransformer; +import jdk.dynalink.linker.MethodTypeConversionStrategy; +import jdk.dynalink.linker.support.CompositeGuardingDynamicLinker; +import jdk.dynalink.linker.support.CompositeTypeBasedGuardingDynamicLinker; +import jdk.dynalink.linker.support.DefaultInternalObjectFilter; +import jdk.dynalink.linker.support.TypeUtilities; + +/** + * 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}. + */ + private static final int DEFAULT_UNSTABLE_RELINK_THRESHOLD = 8; + + private boolean classLoaderExplicitlySet = false; + private ClassLoader classLoader; + + private List prioritizedLinkers; + private List fallbackLinkers; + private boolean syncOnRelink = false; + private int unstableRelinkThreshold = DEFAULT_UNSTABLE_RELINK_THRESHOLD; + private GuardedInvocationTransformer prelinkTransformer; + private MethodTypeConversionStrategy autoConversionStrategy; + private MethodHandleTransformer internalObjectsFilter; + + private List autoLoadingErrors = Collections.emptyList(); + + /** + * 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 automatic discovery of + * available linkers. + */ + public void setClassLoader(final ClassLoader classLoader) { + this.classLoader = classLoader; + classLoaderExplicitlySet = true; + } + + /** + * 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. Can be null. + * @throws NullPointerException if any of the list elements are null. + */ + public void setPrioritizedLinkers(final List prioritizedLinkers) { + this.prioritizedLinkers = copyListRequireNonNullElements(prioritizedLinkers); + } + + /** + * Sets the prioritized guarding dynamic linkers. Identical to calling + * {@link #setPrioritizedLinkers(List)} with + * {@code Arrays.asList(prioritizedLinkers)}. + * + * @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(prioritizedLinkers == null ? null : Arrays.asList(prioritizedLinkers)); + } + + /** + * Sets a single prioritized linker. Identical to calling + * {@link #setPrioritizedLinkers(List)} with a single-element list. + * + * @param prioritizedLinker the single prioritized linker. Must not be null. + * @throws NullPointerException if null is passed. + */ + public void setPrioritizedLinker(final GuardingDynamicLinker prioritizedLinker) { + this.prioritizedLinkers = Collections.singletonList(Objects.requireNonNull(prioritizedLinker)); + } + + /** + * 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. Note that if this + * method is not invoked explicitly or is passed null, then the factory + * will create an instance of {@link BeansLinker} to serve as the default + * fallback linker. + * @throws NullPointerException if any of the list elements are null. + */ + public void setFallbackLinkers(final List fallbackLinkers) { + this.fallbackLinkers = copyListRequireNonNullElements(fallbackLinkers); + } + + /** + * Sets the fallback guarding dynamic linkers. Identical to calling + * {@link #setFallbackLinkers(List)} with + * {@code Arrays.asList(fallbackLinkers)}. + * + * @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(fallbackLinkers == null ? null : Arrays.asList(fallbackLinkers)); + } + + /** + * 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) { + this.syncOnRelink = syncOnRelink; + } + + /** + * Sets the unstable relink threshold; the number of times a call site is + * relinked after which it will be considered unstable, and subsequent link + * requests for it will indicate this. Defaults to 8 when not set explicitly. + * @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) { + if(unstableRelinkThreshold < 0) { + throw new IllegalArgumentException("unstableRelinkThreshold < 0"); + } + this.unstableRelinkThreshold = unstableRelinkThreshold; + } + + /** + * 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 setPrelinkTransformer(final GuardedInvocationTransformer prelinkTransformer) { + this.prelinkTransformer = prelinkTransformer; + } + + /** + * 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 + * {@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 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() { + // Treat nulls appropriately + if(prioritizedLinkers == null) { + prioritizedLinkers = Collections.emptyList(); + } + if(fallbackLinkers == null) { + fallbackLinkers = Collections.singletonList(new BeansLinker()); + } + + // Gather classes of all precreated (prioritized and fallback) linkers. + // We'll filter out any discovered linkers of the same class. + final Set> knownLinkerClasses = + new HashSet<>(); + addClasses(knownLinkerClasses, prioritizedLinkers); + addClasses(knownLinkerClasses, fallbackLinkers); + + final List discovered = discoverAutoLoadLinkers(); + + // Now, concatenate ... + final List linkers = + new ArrayList<>(prioritizedLinkers.size() + discovered.size() + + fallbackLinkers.size()); + // ... prioritized linkers, ... + linkers.addAll(prioritizedLinkers); + // ... filtered discovered linkers, ... + for(final GuardingDynamicLinker linker: discovered) { + if(!knownLinkerClasses.contains(linker.getClass())) { + linkers.add(linker); + } + } + // ... and finally fallback linkers. + linkers.addAll(fallbackLinkers); + final List optimized = CompositeTypeBasedGuardingDynamicLinker.optimize(linkers); + final GuardingDynamicLinker composite; + switch(linkers.size()) { + case 0: { + composite = (r, s) -> null; // linker that can't link anything + break; + } + case 1: { + composite = optimized.get(0); + break; + } + default: { + composite = new CompositeGuardingDynamicLinker(optimized); + break; + } + } + + final List typeConverters = new LinkedList<>(); + for(final GuardingDynamicLinker linker: linkers) { + if(linker instanceof GuardingTypeConverterFactory) { + typeConverters.add((GuardingTypeConverterFactory)linker); + } + } + + if(prelinkTransformer == null) { + prelinkTransformer = (inv, request, linkerServices) -> inv.asType(linkerServices, request.getCallSiteDescriptor().getMethodType()); + } + + return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters, + 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(); + } + }, GET_CLASS_LOADER_CONTEXT); + } + + private static void addClasses(final Set> knownLinkerClasses, + final List linkers) { + for(final GuardingDynamicLinker linker: linkers) { + 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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/LinkerServicesImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/LinkerServicesImpl.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.dynalink; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import jdk.dynalink.linker.ConversionComparator.Comparison; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/NamedOperation.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,195 @@ +/* + * 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.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 final 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 instanceof NamedOperation) { + final NamedOperation other = (NamedOperation)obj; + return baseOperation.equals(other.baseOperation) && name.equals(other.name); + } + return false; + } + + /** + * 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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/NoSuchDynamicMethodException.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,101 @@ +/* + * 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.dynalink; + +import jdk.dynalink.linker.GuardingDynamicLinker; + +/** + * Thrown at the invocation if the call site can not be linked by any available {@link GuardingDynamicLinker}. + */ +public class NoSuchDynamicMethodException extends RuntimeException { + private static final long serialVersionUID = 1L; + + /** + * Creates a new NoSuchDynamicMethodException + * @param message the message of the exception. + */ + public NoSuchDynamicMethodException(final String message) { + super(message); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/Operation.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/RelinkableCallSite.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,178 @@ +/* + * 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.dynalink; + +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.support.ChainedCallSite; +import jdk.dynalink.support.SimpleRelinkableCallSite; + +/** + * 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 { + /** + * 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); + + /** + * Returns the descriptor for this call site. + * + * @return the descriptor for this call site. + */ + public CallSiteDescriptor getDescriptor(); + + /** + * This method will be called by the dynamic linker every time the call site + * is 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 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 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 (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 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 relinkAndInvoke); +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/StandardOperation.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.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 or 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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/TypeConverterFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/TypeConverterFactory.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.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.dynalink.internal.AccessControlContextFactory; +import jdk.dynalink.linker.ConversionComparator; +import jdk.dynalink.linker.ConversionComparator.Comparison; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingTypeConverterFactory; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.MethodTypeConversionStrategy; +import jdk.dynalink.linker.support.TypeUtilities; + +/** + * A factory for type converters. This class is the main implementation behind the + * {@link LinkerServices#asType(MethodHandle, MethodType)}. It manages the known {@link GuardingTypeConverterFactory} + * instances and creates appropriate converters for method handles. + */ +final class TypeConverterFactory { + private static final AccessControlContext GET_CLASS_LOADER_CONTEXT = + AccessControlContextFactory.createAccessControlContext("getClassLoader"); + + private final GuardingTypeConverterFactory[] factories; + private final ConversionComparator[] comparators; + private final MethodTypeConversionStrategy autoConversionStrategy; + + private final ClassValue> converterMap = new ClassValue>() { + @Override + protected ClassMap computeValue(final Class sourceType) { + return new ClassMap(getClassLoader(sourceType)) { + @Override + protected MethodHandle computeValue(final Class targetType) { + try { + return createConverter(sourceType, targetType); + } catch (final RuntimeException e) { + throw e; + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + }; + } + }; + + private final ClassValue> converterIdentityMap = new ClassValue>() { + @Override + protected ClassMap computeValue(final Class sourceType) { + return new ClassMap(getClassLoader(sourceType)) { + @Override + protected MethodHandle computeValue(final Class targetType) { + if(!canAutoConvert(sourceType, targetType)) { + final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType); + if(converter != IDENTITY_CONVERSION) { + return converter; + } + } + return IDENTITY_CONVERSION.asType(MethodType.methodType(targetType, sourceType)); + } + }; + } + }; + + private final ClassValue> canConvert = new ClassValue>() { + @Override + protected ClassMap computeValue(final Class sourceType) { + return new ClassMap(getClassLoader(sourceType)) { + @Override + protected Boolean computeValue(final Class targetType) { + try { + return getTypeConverterNull(sourceType, targetType) != null; + } catch (final RuntimeException e) { + throw e; + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + }; + } + }; + + private static ClassLoader getClassLoader(final Class clazz) { + return AccessController.doPrivileged(new PrivilegedAction() { + @Override + public ClassLoader run() { + return clazz.getClassLoader(); + } + }, GET_CLASS_LOADER_CONTEXT); + } + + /** + * Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances. + * + * @param factories the {@link GuardingTypeConverterFactory} instances to compose. + * @param autoConversionStrategy conversion strategy for automatic type conversions. After + * {@link #asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has applied all custom + * conversions to a method handle, it still needs to effect + * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that + * can usually be automatically applied as per + * {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}. + * However, sometimes language runtimes will want to customize even those conversions for their own call + * sites. A typical example is allowing unboxing of null return values, which is by default prohibited by + * ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom + * automatic conversion strategy, that can deal with null values. Note that when the strategy's + * {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} + * is invoked, the custom language conversions will already have been applied to the method handle, so by + * design the difference between the handle's current method type and the desired final type will always + * only be ones that can be subjected to method invocation conversions. Can be null, in which case no + * custom strategy is employed. + */ + TypeConverterFactory(final Iterable factories, + final MethodTypeConversionStrategy autoConversionStrategy) { + final List l = new LinkedList<>(); + final List c = new LinkedList<>(); + for(final GuardingTypeConverterFactory factory: factories) { + l.add(factory); + if(factory instanceof ConversionComparator) { + c.add((ConversionComparator)factory); + } + } + this.factories = l.toArray(new GuardingTypeConverterFactory[l.size()]); + this.comparators = c.toArray(new ConversionComparator[c.size()]); + this.autoConversionStrategy = autoConversionStrategy; + } + + /** + * Similar to {@link MethodHandle#asType(MethodType)} except it also hooks in method handles produced by + * {@link GuardingTypeConverterFactory} implementations, providing for language-specific type coercing of + * parameters. For all conversions that are not a JLS method invocation conversion it'll insert + * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters + * provided by {@link GuardingTypeConverterFactory} implementations. For the remaining JLS method invocation + * conversions, it will invoke {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)} first + * if an automatic conversion strategy was specified in the + * {@link #TypeConverterFactory(Iterable, MethodTypeConversionStrategy) constructor}, and finally apply + * {@link MethodHandle#asType(MethodType)} for any remaining conversions. + * + * @param handle target method handle + * @param fromType the types of source arguments + * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)}, + * {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)}, and + * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with + * {@link GuardingTypeConverterFactory} produced type converters as filters. + */ + MethodHandle asType(final MethodHandle handle, final MethodType fromType) { + MethodHandle newHandle = handle; + final MethodType toType = newHandle.type(); + final int l = toType.parameterCount(); + if(l != fromType.parameterCount()) { + throw new WrongMethodTypeException("Parameter counts differ: " + handle.type() + " vs. " + fromType); + } + int pos = 0; + final List converters = new LinkedList<>(); + for(int i = 0; i < l; ++i) { + final Class fromParamType = fromType.parameterType(i); + final Class toParamType = toType.parameterType(i); + if(canAutoConvert(fromParamType, toParamType)) { + newHandle = applyConverters(newHandle, pos, converters); + } else { + final MethodHandle converter = getTypeConverterNull(fromParamType, toParamType); + if(converter != null) { + if(converters.isEmpty()) { + pos = i; + } + converters.add(converter); + } else { + newHandle = applyConverters(newHandle, pos, converters); + } + } + } + newHandle = applyConverters(newHandle, pos, converters); + + // Convert return type + final Class fromRetType = fromType.returnType(); + final Class toRetType = toType.returnType(); + if(fromRetType != Void.TYPE && toRetType != Void.TYPE) { + if(!canAutoConvert(toRetType, fromRetType)) { + final MethodHandle converter = getTypeConverterNull(toRetType, fromRetType); + if(converter != null) { + newHandle = MethodHandles.filterReturnValue(newHandle, converter); + } + } + } + + // Give change to automatic conversion strategy, if one is present. + final MethodHandle autoConvertedHandle = + autoConversionStrategy != null ? autoConversionStrategy.asType(newHandle, fromType) : newHandle; + + // Do a final asType for any conversions that remain. + return autoConvertedHandle.asType(fromType); + } + + private static MethodHandle applyConverters(final MethodHandle handle, final int pos, final List converters) { + if(converters.isEmpty()) { + return handle; + } + final MethodHandle newHandle = + MethodHandles.filterArguments(handle, pos, converters.toArray(new MethodHandle[converters.size()])); + converters.clear(); + return newHandle; + } + + /** + * Returns true if there might exist a conversion between the requested types (either an automatic JVM conversion, + * or one provided by any available {@link GuardingTypeConverterFactory}), or false if there definitely does not + * exist a conversion between the requested types. Note that returning true does not guarantee that the conversion + * will succeed at runtime (notably, if the "from" or "to" types are sufficiently generic), but returning false + * guarantees that it would fail. + * + * @param from the source type for the conversion + * @param to the target type for the conversion + * @return true if there can be a conversion, false if there can not. + */ + boolean canConvert(final Class from, final Class to) { + return canAutoConvert(from, to) || canConvert.get(from).get(to); + } + + /** + * Determines which of the two type conversions from a source type to the two target types is preferred. This is + * used for dynamic overloaded method resolution. If the source type is convertible to exactly one target type with + * a method invocation conversion, it is chosen, otherwise available {@link ConversionComparator}s are consulted. + * @param sourceType the source type. + * @param targetType1 one potential target type + * @param targetType2 another potential target type. + * @return one of Comparison constants that establish which - if any - of the target types is preferable for the + * conversion. + */ + Comparison compareConversion(final Class sourceType, final Class targetType1, final Class targetType2) { + for(final ConversionComparator comparator: comparators) { + final Comparison result = comparator.compareConversion(sourceType, targetType1, targetType2); + if(result != Comparison.INDETERMINATE) { + return result; + } + } + if(TypeUtilities.isMethodInvocationConvertible(sourceType, targetType1)) { + if(!TypeUtilities.isMethodInvocationConvertible(sourceType, targetType2)) { + return Comparison.TYPE_1_BETTER; + } + } else if(TypeUtilities.isMethodInvocationConvertible(sourceType, targetType2)) { + return Comparison.TYPE_2_BETTER; + } + return Comparison.INDETERMINATE; + } + + /** + * Determines whether it's safe to perform an automatic conversion between the source and target class. + * + * @param fromType convert from this class + * @param toType convert to this class + * @return true if it's safe to let MethodHandles.convertArguments() to handle this conversion. + */ + /*private*/ static boolean canAutoConvert(final Class fromType, final Class toType) { + return TypeUtilities.isMethodInvocationConvertible(fromType, toType); + } + + /*private*/ MethodHandle getCacheableTypeConverterNull(final Class sourceType, final Class targetType) { + final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType); + return converter == IDENTITY_CONVERSION ? null : converter; + } + + /*private*/ MethodHandle getTypeConverterNull(final Class sourceType, final Class targetType) { + try { + return getCacheableTypeConverterNull(sourceType, targetType); + } catch(final NotCacheableConverter e) { + return e.converter; + } + } + + /*private*/ MethodHandle getCacheableTypeConverter(final Class sourceType, final Class targetType) { + return converterMap.get(sourceType).get(targetType); + } + + /** + * Given a source and target type, returns a method handle that converts between them. Never returns null; in worst + * case it will return an identity conversion (that might fail for some values at runtime). You can use this method + * if you have a piece of your program that is written in Java, and you need to reuse existing type conversion + * machinery in a non-invokedynamic context. + * @param sourceType the type to convert from + * @param targetType the type to convert to + * @return a method handle performing the conversion. + */ + MethodHandle getTypeConverter(final Class sourceType, final Class targetType) { + try { + return converterIdentityMap.get(sourceType).get(targetType); + } catch(final NotCacheableConverter e) { + return e.converter; + } + } + + private static class LookupSupplier implements Supplier { + volatile boolean returnedLookup; + volatile boolean closed; + + @Override + public Lookup get() { + if (closed) { + // Something held on to this supplier and tried to invoke it + // after we're done with it. + throw new IllegalStateException(); + } + final Lookup lookup = LinkerServicesImpl.getCurrentLookup(); + returnedLookup = true; + return lookup; + } + } + + /*private*/ MethodHandle createConverter(final Class sourceType, final Class targetType) throws Exception { + final MethodType type = MethodType.methodType(targetType, sourceType); + final MethodHandle identity = IDENTITY_CONVERSION.asType(type); + MethodHandle last = identity; + + final LookupSupplier lookupSupplier = new LookupSupplier(); + try { + for(int i = factories.length; i-- > 0;) { + final GuardedInvocation next = factories[i].convertToType(sourceType, targetType, lookupSupplier); + if(next != null) { + last = next.compose(last); + } + } + } finally { + lookupSupplier.closed = true; + } + + if(last == identity) { + return IDENTITY_CONVERSION; + } + if(!lookupSupplier.returnedLookup) { + return last; + } + // At least one of the consulted converter factories obtained the + // lookup, so we must presume the created converter is sensitive to the + // lookup class and thus we will not cache it. + throw new NotCacheableConverter(last); + } + + /*private*/ static final MethodHandle IDENTITY_CONVERSION = MethodHandles.identity(Object.class); + + @SuppressWarnings("serial") + private static class NotCacheableConverter extends RuntimeException { + final MethodHandle converter; + + NotCacheableConverter(final MethodHandle converter) { + super("", null, false, false); + this.converter = converter; + } + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AbstractJavaLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,890 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.CompositeOperation; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.beans.GuardedInvocationComponent.ValidationType; +import jdk.dynalink.internal.InternalTypeUtilities; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.support.Guards; +import jdk.dynalink.linker.support.Lookup; +import sun.reflect.CallerSensitive; + +/** + * A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property + * exposure and method calls for both static and instance facets of a class. + */ +abstract class AbstractJavaLinker implements GuardingDynamicLinker { + + final Class clazz; + private final MethodHandle classGuard; + private final MethodHandle assignableGuard; + private final Map propertyGetters = new HashMap<>(); + private final Map propertySetters = new HashMap<>(); + private final Map methods = new HashMap<>(); + + AbstractJavaLinker(final Class clazz, final MethodHandle classGuard) { + this(clazz, classGuard, classGuard); + } + + AbstractJavaLinker(final Class clazz, final MethodHandle classGuard, final MethodHandle assignableGuard) { + this.clazz = clazz; + this.classGuard = classGuard; + this.assignableGuard = assignableGuard; + + final FacetIntrospector introspector = createFacetIntrospector(); + // Add methods and properties + for(final Method method: introspector.getMethods()) { + final String name = method.getName(); + // Add method + addMember(name, method, methods); + // Add the method as a property getter and/or setter + if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) { + // Property getter + setPropertyGetter(method, 3); + } else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 && + method.getReturnType() == boolean.class) { + // Boolean property getter + setPropertyGetter(method, 2); + } else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) { + // Property setter + addMember(decapitalize(name.substring(3)), method, propertySetters); + } + } + + // Add field getter/setters as property getters/setters. + for(final Field field: introspector.getFields()) { + final String name = field.getName(); + // Only add a property getter when one is not defined already as a getXxx()/isXxx() method. + if(!propertyGetters.containsKey(name)) { + setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS); + } + if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) { + addMember(name, new SimpleDynamicMethod(introspector.unreflectSetter(field), clazz, name), + propertySetters); + } + } + + // Add inner classes, but only those for which we don't hide a property with it + for(final Map.Entry innerClassSpec: introspector.getInnerClassGetters().entrySet()) { + final String name = innerClassSpec.getKey(); + if(!propertyGetters.containsKey(name)) { + setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS); + } + } + } + + private static String decapitalize(final String str) { + assert str != null; + if(str.isEmpty()) { + return str; + } + + final char c0 = str.charAt(0); + if(Character.isLowerCase(c0)) { + return str; + } + + // If it has two consecutive upper-case characters, i.e. "URL", don't decapitalize + if(str.length() > 1 && Character.isUpperCase(str.charAt(1))) { + return str; + } + + final char c[] = str.toCharArray(); + c[0] = Character.toLowerCase(c0); + return new String(c); + } + + abstract FacetIntrospector createFacetIntrospector(); + + Set getReadablePropertyNames() { + return getUnmodifiableKeys(propertyGetters); + } + + Set getWritablePropertyNames() { + return getUnmodifiableKeys(propertySetters); + } + + Set getMethodNames() { + return getUnmodifiableKeys(methods); + } + + private static Set getUnmodifiableKeys(final Map m) { + return Collections.unmodifiableSet(m.keySet()); + } + + /** + * Sets the specified dynamic method to be the property getter for the specified property. Note that you can only + * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties + * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)} + * instead. + * @param name name of the property + * @param handle the method handle that implements the property getter + * @param validationType the validation type for the property + */ + private void setPropertyGetter(final String name, final SingleDynamicMethod handle, final ValidationType validationType) { + propertyGetters.put(name, new AnnotatedDynamicMethod(handle, validationType)); + } + + /** + * Sets the specified reflective method to be the property getter for the specified property. + * @param getter the getter method + * @param prefixLen the getter prefix in the method name; should be 3 for getter names starting with "get" and 2 for + * names starting with "is". + */ + private void setPropertyGetter(final Method getter, final int prefixLen) { + setPropertyGetter(decapitalize(getter.getName().substring(prefixLen)), createDynamicMethod( + getMostGenericGetter(getter)), ValidationType.INSTANCE_OF); + } + + /** + * Sets the specified method handle to be the property getter for the specified property. Note that you can only + * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties + * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)} + * instead. + * @param name name of the property + * @param handle the method handle that implements the property getter + * @param validationType the validation type for the property + */ + void setPropertyGetter(final String name, final MethodHandle handle, final ValidationType validationType) { + setPropertyGetter(name, new SimpleDynamicMethod(handle, clazz, name), validationType); + } + + private void addMember(final String name, final AccessibleObject ao, final Map methodMap) { + addMember(name, createDynamicMethod(ao), methodMap); + } + + private void addMember(final String name, final SingleDynamicMethod method, final Map methodMap) { + final DynamicMethod existingMethod = methodMap.get(name); + final DynamicMethod newMethod = mergeMethods(method, existingMethod, clazz, name); + if(newMethod != existingMethod) { + methodMap.put(name, newMethod); + } + } + + /** + * Given one or more reflective methods or constructors, creates a dynamic method that represents them all. The + * methods should represent all overloads of the same name (or all constructors of the class). + * @param members the reflective members + * @param clazz the class declaring the reflective members + * @param name the common name of the reflective members. + * @return a dynamic method representing all the specified reflective members. + */ + static DynamicMethod createDynamicMethod(final Iterable members, final Class clazz, final String name) { + DynamicMethod dynMethod = null; + for(final AccessibleObject method: members) { + dynMethod = mergeMethods(createDynamicMethod(method), dynMethod, clazz, name); + } + return dynMethod; + } + + /** + * Given a reflective method or a constructor, creates a dynamic method that represents it. This method will + * distinguish between caller sensitive and ordinary methods/constructors, and create appropriate caller sensitive + * dynamic method when needed. + * @param m the reflective member + * @return the single dynamic method representing the reflective member + */ + private static SingleDynamicMethod createDynamicMethod(final AccessibleObject m) { + if (m.isAnnotationPresent(CallerSensitive.class)) { + // Method has @CallerSensitive annotation + return new CallerSensitiveDynamicMethod(m); + } + // Method has no @CallerSensitive annotation + final MethodHandle mh; + try { + mh = unreflectSafely(m); + } catch (final IllegalAccessError e) { + // java.lang.invoke can in some case conservatively treat as caller sensitive methods that aren't + // marked with the annotation. In this case, we'll fall back to treating it as caller sensitive. + return new CallerSensitiveDynamicMethod(m); + } + // Proceed with non-caller sensitive + final Member member = (Member)m; + return new SimpleDynamicMethod(mh, member.getDeclaringClass(), member.getName(), m instanceof Constructor); + } + + /** + * Unreflects a method handle from a Method or a Constructor using safe (zero-privilege) unreflection. Should be + * only used for methods and constructors that are not caller sensitive. If a caller sensitive method were + * unreflected through this mechanism, it would not be a security issue, but would be bound to the zero-privilege + * unreflector as its caller, and thus completely useless. + * @param m the method or constructor + * @return the method handle + */ + private static MethodHandle unreflectSafely(final AccessibleObject m) { + if(m instanceof Method) { + final Method reflMethod = (Method)m; + final MethodHandle handle = Lookup.PUBLIC.unreflect(reflMethod); + if(Modifier.isStatic(reflMethod.getModifiers())) { + return StaticClassIntrospector.editStaticMethodHandle(handle); + } + return handle; + } + return StaticClassIntrospector.editConstructorMethodHandle(Lookup.PUBLIC.unreflectConstructor((Constructor)m)); + } + + private static DynamicMethod mergeMethods(final SingleDynamicMethod method, final DynamicMethod existing, final Class clazz, final String name) { + if(existing == null) { + return method; + } else if(existing.contains(method)) { + return existing; + } else if(existing instanceof SingleDynamicMethod) { + final OverloadedDynamicMethod odm = new OverloadedDynamicMethod(clazz, name); + odm.addMethod(((SingleDynamicMethod)existing)); + odm.addMethod(method); + return odm; + } else if(existing instanceof OverloadedDynamicMethod) { + ((OverloadedDynamicMethod)existing).addMethod(method); + return existing; + } + throw new AssertionError(); + } + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) + throws Exception { + 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 = Arrays.asList( + CompositeOperation.getOperations( + NamedOperation.getBaseOperation(operation))); + final Object name = NamedOperation.getName(operation); + + while(!operations.isEmpty()) { + final GuardedInvocationComponent gic = + getGuardedInvocationComponent(callSiteDescriptor, + linkerServices, operations, name); + if(gic != null) { + return gic.getGuardedInvocation(); + } + operations = pop(operations); + } + return null; + } + + protected GuardedInvocationComponent getGuardedInvocationComponent( + final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, + final List operations, final Object name) + throws Exception { + if(operations.isEmpty()) { + return null; + } + 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 SET_PROPERTY:name(this, value) or SET_PROPERTY(this, name, value) + if(op == StandardOperation.SET_PROPERTY) { + return getPropertySetter(callSiteDescriptor, linkerServices, pop(operations), name); + } + // Either GET_METHOD:name(this), or GET_METHOD(this, name) + if(op == StandardOperation.GET_METHOD) { + return getMethodGetter(callSiteDescriptor, linkerServices, pop(operations), name); + } + return null; + } + + static final List pop(final List l) { + return l.subList(1, l.size()); + } + + MethodHandle getClassGuard(final CallSiteDescriptor desc) { + return getClassGuard(desc.getMethodType()); + } + + MethodHandle getClassGuard(final MethodType type) { + return Guards.asType(classGuard, type); + } + + GuardedInvocationComponent getClassGuardedInvocationComponent(final MethodHandle invocation, final MethodType type) { + return new GuardedInvocationComponent(invocation, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); + } + + abstract SingleDynamicMethod getConstructorMethod(final String signature); + + private MethodHandle getAssignableGuard(final MethodType type) { + return Guards.asType(assignableGuard, type); + } + + private GuardedInvocation createGuardedDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final String methodName, final Map methodMap){ + final MethodHandle inv = getDynamicMethodInvocation(callSiteDescriptor, linkerServices, methodName, methodMap); + return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteDescriptor.getMethodType())); + } + + private MethodHandle getDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final String methodName, final Map methodMap) { + final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap); + return dynaMethod != null ? dynaMethod.getInvocation(callSiteDescriptor, linkerServices) : null; + } + + private DynamicMethod getDynamicMethod(final String methodName, final Map methodMap) { + final DynamicMethod dynaMethod = methodMap.get(methodName); + return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap); + } + + private SingleDynamicMethod getExplicitSignatureDynamicMethod(final String fullName, + final Map methodsMap) { + // What's below is meant to support the "name(type, type, ...)" syntax that programmers can use in a method name + // to manually pin down an exact overloaded variant. This is not usually required, as the overloaded method + // resolution works correctly in almost every situation. However, in presence of many language-specific + // conversions with a radically dynamic language, most overloaded methods will end up being constantly selected + // at invocation time, so a programmer knowledgeable of the situation might choose to pin down an exact overload + // for performance reasons. + + // Is the method name lexically of the form "name(types)"? + final int lastChar = fullName.length() - 1; + if(fullName.charAt(lastChar) != ')') { + return null; + } + final int openBrace = fullName.indexOf('('); + if(openBrace == -1) { + return null; + } + + final String name = fullName.substring(0, openBrace); + final String signature = fullName.substring(openBrace + 1, lastChar); + + // Find an existing method for the "name" part + final DynamicMethod simpleNamedMethod = methodsMap.get(name); + if(simpleNamedMethod == null) { + // explicit signature constructor access + // Java.type("java.awt.Color")["(int,int,int)"] + // will get Color(int,int,int) constructor of Color class. + if (name.isEmpty()) { + return getConstructorMethod(signature); + } + + return null; + } + + // Try to get a narrowed dynamic method for the explicit parameter types. + return simpleNamedMethod.getMethodForExactParamTypes(signature); + } + + private static final MethodHandle IS_METHOD_HANDLE_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType( + boolean.class, MethodHandle.class)); + private static final MethodHandle CONSTANT_NULL_DROP_METHOD_HANDLE = MethodHandles.dropArguments( + MethodHandles.constant(Object.class, null), 0, MethodHandle.class); + + private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor, + 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); + } + + 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. + + // 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)); + + // 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); + } + + // 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()); + + private static final MethodHandle IS_ANNOTATED_METHOD_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType( + boolean.class, AnnotatedDynamicMethod.class)); + 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, 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, final Object name) throws Exception { + if (name == null) { + return getUnnamedPropertyGetter(callSiteDescriptor, linkerServices, ops); + } + + return getNamedPropertyGetter(callSiteDescriptor, linkerServices, ops, name); + } + + 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); + + // 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); + } + + // 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) { + switch(validationType) { + case EXACT_CLASS: { + return getClassGuard(methodType); + } + case INSTANCE_OF: { + return getAssignableGuard(methodType); + } + case IS_ARRAY: { + return Guards.isArray(0, methodType); + } + case NONE: { + return null; + } + default: { + throw new AssertionError(); + } + } + } + + private static final MethodHandle IS_DYNAMIC_METHOD = Guards.isInstance(DynamicMethod.class, + MethodType.methodType(boolean.class, Object.class)); + private static final MethodHandle OBJECT_IDENTITY = MethodHandles.identity(Object.class); + + private GuardedInvocationComponent getMethodGetter(final CallSiteDescriptor callSiteDescriptor, + 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); + if (name == null) { + return getUnnamedMethodGetter(callSiteDescriptor, linkerServices, ops, type); + } + + return getNamedMethodGetter(callSiteDescriptor, linkerServices, ops, name, type); + } + + 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); + + 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 { + final MethodHandle method1; + final MethodHandle method2; + + MethodPair(final MethodHandle method1, final MethodHandle method2) { + this.method1 = method1; + this.method2 = method2; + } + + MethodHandle guardWithTest(final MethodHandle test) { + return MethodHandles.guardWithTest(test, method1, method2); + } + } + + static MethodPair matchReturnTypes(final MethodHandle m1, final MethodHandle m2) { + final MethodType type1 = m1.type(); + final MethodType type2 = m2.type(); + final Class commonRetType = InternalTypeUtilities.getCommonLosslessConversionType(type1.returnType(), + type2.returnType()); + return new MethodPair( + m1.asType(type1.changeReturnType(commonRetType)), + m2.asType(type2.changeReturnType(commonRetType))); + } + + private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) { + if(descriptor.getMethodType().parameterCount() != paramCount) { + throw new BootstrapMethodError(descriptor.getOperation() + " must have exactly " + paramCount + " parameters."); + } + } + + private static MethodHandle GET_PROPERTY_GETTER_HANDLE = MethodHandles.dropArguments(privateLookup.findOwnSpecial( + "getPropertyGetterHandle", Object.class, Object.class), 1, Object.class); + private final MethodHandle getPropertyGetterHandle = GET_PROPERTY_GETTER_HANDLE.bindTo(this); + + /** + * @param id the property ID + * @return the method handle for retrieving the property, or null if the property does not exist + */ + @SuppressWarnings("unused") + private Object getPropertyGetterHandle(final Object id) { + return propertyGetters.get(id); + } + + // Type is MethodHandle(BeanLinker, MethodType, LinkerServices, Object, String, Object), of which the two "Object" + // args are dropped; this makes handles with first three args conform to "Object, String, Object" though, which is + // a typical property setter with variable name signature (target, name, value). + private static final MethodHandle GET_PROPERTY_SETTER_HANDLE = MethodHandles.dropArguments(MethodHandles.dropArguments( + privateLookup.findOwnSpecial("getPropertySetterHandle", MethodHandle.class, CallSiteDescriptor.class, + LinkerServices.class, Object.class), 3, Object.class), 5, Object.class); + // Type is MethodHandle(MethodType, LinkerServices, Object, String, Object) + private final MethodHandle getPropertySetterHandle = GET_PROPERTY_SETTER_HANDLE.bindTo(this); + + @SuppressWarnings("unused") + private MethodHandle getPropertySetterHandle(final CallSiteDescriptor setterDescriptor, final LinkerServices linkerServices, + final Object id) { + return getDynamicMethodInvocation(setterDescriptor, linkerServices, String.valueOf(id), propertySetters); + } + + private static MethodHandle GET_DYNAMIC_METHOD = MethodHandles.dropArguments(privateLookup.findOwnSpecial( + "getDynamicMethod", Object.class, Object.class), 1, Object.class); + private final MethodHandle getDynamicMethod = GET_DYNAMIC_METHOD.bindTo(this); + + @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 + // GET_METHOD linking). + private Object getDynamicMethod(final Object name) { + return getDynamicMethod(String.valueOf(name), methods); + } + + /** + * Returns a dynamic method of the specified name. + * + * @param name name of the method + * @return the dynamic method (either {@link SimpleDynamicMethod} or {@link OverloadedDynamicMethod}, or null if the + * method with the specified name does not exist. + */ + DynamicMethod getDynamicMethod(final String name) { + return getDynamicMethod(name, methods); + } + + /** + * Find the most generic superclass that declares this getter. Since getters have zero args (aside from the + * receiver), they can't be overloaded, so we're free to link with an instanceof guard for the most generic one, + * creating more stable call sites. + * @param getter the getter + * @return getter with same name, declared on the most generic superclass/interface of the declaring class + */ + private static Method getMostGenericGetter(final Method getter) { + return getMostGenericGetter(getter.getName(), getter.getReturnType(), getter.getDeclaringClass()); + } + + private static Method getMostGenericGetter(final String name, final Class returnType, final Class declaringClass) { + if(declaringClass == null) { + return null; + } + // Prefer interfaces + for(final Class itf: declaringClass.getInterfaces()) { + final Method itfGetter = getMostGenericGetter(name, returnType, itf); + if(itfGetter != null) { + return itfGetter; + } + } + final Method superGetter = getMostGenericGetter(name, returnType, declaringClass.getSuperclass()); + if(superGetter != null) { + return superGetter; + } + if(!CheckRestrictedPackage.isRestrictedClass(declaringClass)) { + try { + return declaringClass.getMethod(name); + } catch(final NoSuchMethodException e) { + // Intentionally ignored, meant to fall through + } + } + return null; + } + + private static final class AnnotatedDynamicMethod { + private final SingleDynamicMethod method; + /*private*/ final ValidationType validationType; + + AnnotatedDynamicMethod(final SingleDynamicMethod method, final ValidationType validationType) { + this.method = method; + this.validationType = validationType; + } + + MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { + return method.getInvocation(callSiteDescriptor, linkerServices); + } + + @SuppressWarnings("unused") + MethodHandle getTarget(final CallSiteDescriptor desc, final LinkerServices linkerServices) { + final MethodHandle inv = linkerServices.filterInternalObjects(method.getTarget(desc)); + assert inv != null; + return inv; + } + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AccessibleMembersLookup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/AccessibleMembersLookup.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,263 @@ +/* + * 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.dynalink.beans; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +/** + * Utility class for discovering accessible methods and inner classes. Normally, a public member declared on a class is + * accessible (that is, it can be invoked from anywhere). However, this is not the case if the class itself is not + * public, or belongs to a restricted-access package. In that case, it is required to lookup a member in a publicly + * accessible superclass or implemented interface of the class, and use it instead of the member discovered on the + * class. + */ +class AccessibleMembersLookup { + private final Map methods; + private final Set> innerClasses; + private final boolean instance; + + /** + * Creates a mapping for all accessible methods and inner classes on a class. + * + * @param clazz the inspected class + * @param instance true to inspect instance methods, false to inspect static methods. + */ + AccessibleMembersLookup(final Class clazz, final boolean instance) { + this.methods = new HashMap<>(); + this.innerClasses = new LinkedHashSet<>(); + this.instance = instance; + lookupAccessibleMembers(clazz); + } + + /** + * Returns an accessible method equivalent of a method. + * + * @param m the method whose accessible equivalent is requested. + * @return the accessible equivalent for the method (can be the same as the passed in method), or null if there is + * no accessible method equivalent. + */ + Method getAccessibleMethod(final Method m) { + return m == null ? null : methods.get(new MethodSignature(m)); + } + + Collection getMethods() { + return methods.values(); + } + + Class[] getInnerClasses() { + return innerClasses.toArray(new Class[innerClasses.size()]); + } + + /** + * A helper class that represents a method signature - name and argument types. + */ + static final class MethodSignature { + private final String name; + private final Class[] args; + + /** + * Creates a new method signature from arbitrary data. + * + * @param name the name of the method this signature represents. + * @param args the argument types of the method. + */ + MethodSignature(final String name, final Class[] args) { + this.name = name; + this.args = args; + } + + /** + * Creates a signature for the given method. + * + * @param method the method for which a signature is created. + */ + MethodSignature(final Method method) { + this(method.getName(), method.getParameterTypes()); + } + + /** + * Compares this object to another object + * + * @param o the other object + * @return true if the other object is also a method signature with the same name, same number of arguments, and + * same types of arguments. + */ + @Override + public boolean equals(final Object o) { + if(o instanceof MethodSignature) { + final MethodSignature ms = (MethodSignature)o; + return ms.name.equals(name) && Arrays.equals(args, ms.args); + } + return false; + } + + /** + * Returns a hash code, consistent with the overridden {@link #equals(Object)}. + */ + @Override + public int hashCode() { + return name.hashCode() ^ Arrays.hashCode(args); + } + + @Override + public String toString() { + final StringBuilder b = new StringBuilder(); + b.append("[MethodSignature ").append(name).append('('); + if(args.length > 0) { + b.append(args[0].getCanonicalName()); + for(int i = 1; i < args.length; ++i) { + b.append(", ").append(args[i].getCanonicalName()); + } + } + return b.append(")]").toString(); + } + } + + private void lookupAccessibleMembers(final Class clazz) { + boolean searchSuperTypes; + + if(!CheckRestrictedPackage.isRestrictedClass(clazz)) { + searchSuperTypes = false; + for(final Method method: clazz.getMethods()) { + final boolean isStatic = Modifier.isStatic(method.getModifiers()); + if(instance != isStatic) { + final MethodSignature sig = new MethodSignature(method); + if(!methods.containsKey(sig)) { + final Class declaringClass = method.getDeclaringClass(); + if(declaringClass != clazz && CheckRestrictedPackage.isRestrictedClass(declaringClass)) { + //Sometimes, the declaring class of a method (Method.getDeclaringClass()) + //retrieved through Class.getMethods() for a public class will be a + //non-public superclass. For such a method, we need to find a method with + //the same name and signature in a public superclass or implemented + //interface. + //This typically doesn't happen with classes emitted by a reasonably modern + //javac, as it'll create synthetic delegator methods in all public + //immediate subclasses of the non-public class. We have, however, observed + //this in the wild with class files compiled with older javac that doesn't + //generate the said synthetic delegators. + searchSuperTypes = true; + } else { + // don't allow inherited static + if (!isStatic || clazz == declaringClass) { + methods.put(sig, method); + } + } + } + } + } + for(final Class innerClass: clazz.getClasses()) { + // Add both static and non-static classes, regardless of instance flag. StaticClassLinker will just + // expose non-static classes with explicit constructor outer class argument. + // NOTE: getting inner class objects through getClasses() does not resolve them, so if those classes + // were not yet loaded, they'll only get loaded in a non-resolved state; no static initializers for + // them will trigger just by doing this. + innerClasses.add(innerClass); + } + } else { + searchSuperTypes = true; + } + + // don't need to search super types for static methods + if(instance && searchSuperTypes) { + // If we reach here, the class is either not public, or it is in a restricted package. Alternatively, it is + // public, but some of its methods claim that their declaring class is non-public. We'll try superclasses + // and implemented interfaces then looking for public ones. + final Class[] interfaces = clazz.getInterfaces(); + for(int i = 0; i < interfaces.length; i++) { + lookupAccessibleMembers(interfaces[i]); + } + final Class superclass = clazz.getSuperclass(); + if(superclass != null) { + lookupAccessibleMembers(superclass); + } + } + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ApplicableOverloadedMethods.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ApplicableOverloadedMethods.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,217 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodType; +import java.util.LinkedList; +import java.util.List; +import jdk.dynalink.linker.support.TypeUtilities; + +/** + * Represents overloaded methods applicable to a specific call site signature. + */ +class ApplicableOverloadedMethods { + private final List methods; + private final boolean varArgs; + + /** + * Creates a new ApplicableOverloadedMethods instance + * + * @param methods a list of all overloaded methods with the same name for a class. + * @param callSiteType the type of the call site + * @param test applicability test. One of {@link #APPLICABLE_BY_SUBTYPING}, + * {@link #APPLICABLE_BY_METHOD_INVOCATION_CONVERSION}, or {@link #APPLICABLE_BY_VARIABLE_ARITY}. + */ + ApplicableOverloadedMethods(final List methods, final MethodType callSiteType, + final ApplicabilityTest test) { + this.methods = new LinkedList<>(); + for(final SingleDynamicMethod m: methods) { + if(test.isApplicable(callSiteType, m)) { + this.methods.add(m); + } + } + varArgs = test == APPLICABLE_BY_VARIABLE_ARITY; + } + + /** + * Retrieves all the methods this object holds. + * + * @return list of all methods. + */ + List getMethods() { + return methods; + } + + /** + * Returns a list of all methods in this objects that are maximally specific. + * + * @return a list of maximally specific methods. + */ + List findMaximallySpecificMethods() { + return MaximallySpecific.getMaximallySpecificMethods(methods, varArgs); + } + + abstract static class ApplicabilityTest { + abstract boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method); + } + + /** + * Implements the applicability-by-subtyping test from JLS 15.12.2.2. + */ + static final ApplicabilityTest APPLICABLE_BY_SUBTYPING = new ApplicabilityTest() { + @Override + boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) { + final MethodType methodType = method.getMethodType(); + final int methodArity = methodType.parameterCount(); + if(methodArity != callSiteType.parameterCount()) { + return false; + } + // 0th arg is receiver; it doesn't matter for overload + // resolution. + for(int i = 1; i < methodArity; ++i) { + if(!TypeUtilities.isSubtype(callSiteType.parameterType(i), methodType.parameterType(i))) { + return false; + } + } + return true; + } + }; + + /** + * Implements the applicability-by-method-invocation-conversion test from JLS 15.12.2.3. + */ + static final ApplicabilityTest APPLICABLE_BY_METHOD_INVOCATION_CONVERSION = new ApplicabilityTest() { + @Override + boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) { + final MethodType methodType = method.getMethodType(); + final int methodArity = methodType.parameterCount(); + if(methodArity != callSiteType.parameterCount()) { + return false; + } + // 0th arg is receiver; it doesn't matter for overload + // resolution. + for(int i = 1; i < methodArity; ++i) { + if(!TypeUtilities.isMethodInvocationConvertible(callSiteType.parameterType(i), + methodType.parameterType(i))) { + return false; + } + } + return true; + } + }; + + /** + * Implements the applicability-by-variable-arity test from JLS 15.12.2.4. + */ + static final ApplicabilityTest APPLICABLE_BY_VARIABLE_ARITY = new ApplicabilityTest() { + @Override + boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) { + if(!method.isVarArgs()) { + return false; + } + final MethodType methodType = method.getMethodType(); + final int methodArity = methodType.parameterCount(); + final int fixArity = methodArity - 1; + final int callSiteArity = callSiteType.parameterCount(); + if(fixArity > callSiteArity) { + return false; + } + // 0th arg is receiver; it doesn't matter for overload + // resolution. + for(int i = 1; i < fixArity; ++i) { + if(!TypeUtilities.isMethodInvocationConvertible(callSiteType.parameterType(i), + methodType.parameterType(i))) { + return false; + } + } + final Class varArgType = methodType.parameterType(fixArity).getComponentType(); + for(int i = fixArity; i < callSiteArity; ++i) { + if(!TypeUtilities.isMethodInvocationConvertible(callSiteType.parameterType(i), varArgType)) { + return false; + } + } + return true; + } + }; +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanIntrospector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanIntrospector.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2009-2013 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package jdk.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.util.Collections; +import java.util.Map; + +class BeanIntrospector extends FacetIntrospector { + BeanIntrospector(final Class clazz) { + super(clazz, true); + } + + @Override + Map getInnerClassGetters() { + return Collections.emptyMap(); // NOTE: non-static inner classes are also on StaticClassIntrospector. + } + + @Override + MethodHandle editMethodHandle(final MethodHandle mh) { + return mh; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,525 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.beans.GuardedInvocationComponent.ValidationType; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.dynalink.linker.support.Guards; +import jdk.dynalink.linker.support.Lookup; +import jdk.dynalink.linker.support.TypeUtilities; + +/** + * A class that provides linking capabilities for a single POJO class. Normally not used directly, but managed by + * {@link BeansLinker}. + */ +class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicLinker { + BeanLinker(final Class clazz) { + super(clazz, Guards.getClassGuard(clazz), Guards.getInstanceOfGuard(clazz)); + if(clazz.isArray()) { + // Some languages won't have a notion of manipulating collections. Exposing "length" on arrays as an + // explicit property is beneficial for them. + // REVISIT: is it maybe a code smell that 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); + } + } + + @Override + public boolean canLinkType(final Class type) { + return type == clazz; + } + + @Override + FacetIntrospector createFacetIntrospector() { + return new BeanIntrospector(clazz); + } + + @Override + protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List operations, final Object name) throws Exception { + final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(callSiteDescriptor, + linkerServices, operations, name); + if(superGic != null) { + return superGic; + } + if(operations.isEmpty()) { + return null; + } + final Operation op = operations.get(0); + if(op == StandardOperation.GET_ELEMENT) { + return getElementGetter(callSiteDescriptor, linkerServices, pop(operations), name); + } + if(op == StandardOperation.SET_ELEMENT) { + return getElementSetter(callSiteDescriptor, linkerServices, pop(operations), name); + } + if(op == StandardOperation.GET_LENGTH) { + return getLengthGetter(callSiteDescriptor); + } + return null; + } + + @Override + SingleDynamicMethod getConstructorMethod(final String signature) { + return null; + } + + private static final MethodHandle GET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "get", + MethodType.methodType(Object.class, int.class)); + + private static final MethodHandle GET_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "get", + MethodType.methodType(Object.class, Object.class)); + + private static final MethodHandle LIST_GUARD = Guards.getInstanceOfGuard(List.class); + private static final MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class); + + private enum CollectionType { + ARRAY, LIST, MAP + }; + + private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor, + 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, 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 + // dealing with an array, or a list or map, but hey... + // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers + // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices. + final GuardedInvocationComponent gic; + final CollectionType collectionType; + if(declaredType.isArray()) { + gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType), linkerServices); + collectionType = CollectionType.ARRAY; + } else if(List.class.isAssignableFrom(declaredType)) { + gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, linkerServices); + collectionType = CollectionType.LIST; + } else if(Map.class.isAssignableFrom(declaredType)) { + gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, linkerServices); + collectionType = CollectionType.MAP; + } else if(clazz.isArray()) { + gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(MethodHandles.arrayElementGetter(clazz)), callSiteType); + collectionType = CollectionType.ARRAY; + } else if(List.class.isAssignableFrom(clazz)) { + gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF, + linkerServices); + collectionType = CollectionType.LIST; + } else if(Map.class.isAssignableFrom(clazz)) { + gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class, ValidationType.INSTANCE_OF, + linkerServices); + collectionType = CollectionType.MAP; + } else { + // Can't retrieve elements for objects that are neither arrays, nor list, nor maps. + return nextComponent; + } + + // Convert the key to a number if we're working with a list or array + 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 { + typedName = name; + } + + final GuardedInvocation gi = gic.getGuardedInvocation(); + final Binder binder = new Binder(linkerServices, callSiteType, typedName); + final MethodHandle invocation = gi.getInvocation(); + + if(nextComponent == null) { + return gic.replaceInvocation(binder.bind(invocation)); + } + + final MethodHandle checkGuard; + switch(collectionType) { + case LIST: + checkGuard = convertArgToInt(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor); + break; + case MAP: + // TODO: A more complex solution could be devised for maps, one where we do a get() first, and fold it + // into a GWT that tests if it returned null, and if it did, do another GWT with containsKey() + // that returns constant null (on true), or falls back to next component (on false) + checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP); + break; + case ARRAY: + checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor); + break; + default: + throw new AssertionError(); + } + final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation), + nextComponent.getGuardedInvocation().getInvocation()); + return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(), + gic.getValidatorClass(), gic.getValidationType()); + } + + private static GuardedInvocationComponent createInternalFilteredGuardedInvocationComponent( + final MethodHandle invocation, final LinkerServices linkerServices) { + return new GuardedInvocationComponent(linkerServices.filterInternalObjects(invocation)); + } + + private static GuardedInvocationComponent createInternalFilteredGuardedInvocationComponent( + final MethodHandle invocation, final MethodHandle guard, final Class validatorClass, + final ValidationType validationType, final LinkerServices linkerServices) { + return new GuardedInvocationComponent(linkerServices.filterInternalObjects(invocation), guard, + validatorClass, validationType); + } + + private static Integer convertKeyToInteger(final Object fixedKey, final LinkerServices linkerServices) throws Exception { + if (fixedKey instanceof Integer) { + return (Integer)fixedKey; + } + + 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 { + 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; + } + } + + 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) { + final Class sourceType = desc.getMethodType().parameterType(1); + if(TypeUtilities.isMethodInvocationConvertible(sourceType, Number.class)) { + return mh; + } else if(ls.canConvert(sourceType, Number.class)) { + final MethodHandle converter = ls.getTypeConverter(sourceType, Number.class); + return MethodHandles.filterArguments(mh, 1, converter.asType(converter.type().changeReturnType( + mh.type().parameterType(1)))); + } + return mh; + } + + /** + * Contains methods to adapt an item getter/setter method handle to the requested type, optionally binding it to a + * fixed key first. + */ + private static class Binder { + private final LinkerServices linkerServices; + private final MethodType methodType; + private final Object fixedKey; + + Binder(final LinkerServices linkerServices, final MethodType methodType, final Object fixedKey) { + this.linkerServices = linkerServices; + this.methodType = fixedKey == null ? methodType : methodType.insertParameterTypes(1, fixedKey.getClass()); + this.fixedKey = fixedKey; + } + + /*private*/ MethodHandle bind(final MethodHandle handle) { + return bindToFixedKey(linkerServices.asTypeLosslessReturn(handle, methodType)); + } + + /*private*/ MethodHandle bindTest(final MethodHandle handle) { + return bindToFixedKey(Guards.asType(handle, methodType)); + } + + private MethodHandle bindToFixedKey(final MethodHandle handle) { + return fixedKey == null ? handle : MethodHandles.insertArguments(handle, 1, fixedKey); + } + } + + private static final MethodHandle RANGE_CHECK_ARRAY = findRangeCheck(Object.class); + private static final MethodHandle RANGE_CHECK_LIST = findRangeCheck(List.class); + private static final MethodHandle CONTAINS_MAP = Lookup.PUBLIC.findVirtual(Map.class, "containsKey", + MethodType.methodType(boolean.class, Object.class)); + + private static MethodHandle findRangeCheck(final Class collectionType) { + return Lookup.findOwnStatic(MethodHandles.lookup(), "rangeCheck", boolean.class, collectionType, Object.class); + } + + @SuppressWarnings("unused") + private static boolean rangeCheck(final Object array, final Object index) { + if(!(index instanceof Number)) { + return false; + } + final Number n = (Number)index; + final int intIndex = n.intValue(); + final double doubleValue = n.doubleValue(); + if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinite trigger IOOBE + return false; + } + if(0 <= intIndex && intIndex < Array.getLength(array)) { + return true; + } + throw new ArrayIndexOutOfBoundsException("Array index out of range: " + n); + } + + @SuppressWarnings("unused") + private static boolean rangeCheck(final List list, final Object index) { + if(!(index instanceof Number)) { + return false; + } + final Number n = (Number)index; + final int intIndex = n.intValue(); + final double doubleValue = n.doubleValue(); + if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinite trigger IOOBE + return false; + } + if(0 <= intIndex && intIndex < list.size()) { + return true; + } + throw new IndexOutOfBoundsException("Index: " + n + ", Size: " + list.size()); + } + + private static final MethodHandle SET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "set", + MethodType.methodType(Object.class, int.class, Object.class)); + + private static final MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put", + MethodType.methodType(Object.class, Object.class, Object.class)); + + private GuardedInvocationComponent getElementSetter(final CallSiteDescriptor callSiteDescriptor, + final LinkerServices linkerServices, final List operations, final Object name) throws Exception { + final MethodType callSiteType = callSiteDescriptor.getMethodType(); + final Class declaredType = callSiteType.parameterType(0); + + final GuardedInvocationComponent gic; + // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing + // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're + // dealing with an array, or a list or map, but hey... + // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers + // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices. + final CollectionType collectionType; + if(declaredType.isArray()) { + gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementSetter(declaredType), linkerServices); + collectionType = CollectionType.ARRAY; + } else if(List.class.isAssignableFrom(declaredType)) { + gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, linkerServices); + collectionType = CollectionType.LIST; + } else if(Map.class.isAssignableFrom(declaredType)) { + gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, linkerServices); + collectionType = CollectionType.MAP; + } else if(clazz.isArray()) { + gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects( + MethodHandles.arrayElementSetter(clazz)), callSiteType); + collectionType = CollectionType.ARRAY; + } else if(List.class.isAssignableFrom(clazz)) { + gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF, + linkerServices); + collectionType = CollectionType.LIST; + } else if(Map.class.isAssignableFrom(clazz)) { + gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), + Map.class, ValidationType.INSTANCE_OF, linkerServices); + collectionType = CollectionType.MAP; + } else { + // Can't set elements for objects that are neither arrays, nor list, nor maps. + gic = null; + collectionType = null; + } + + // In contrast to, say, getElementGetter, we only compute the nextComponent if the target object is not a map, + // as maps will always succeed in setting the element and will never need to fall back to the next component + // operation. + final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getGuardedInvocationComponent( + callSiteDescriptor, linkerServices, operations, name); + if(gic == null) { + return nextComponent; + } + + // Convert the key to a number if we're working with a list or array + 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 { + typedName = name; + } + + final GuardedInvocation gi = gic.getGuardedInvocation(); + final Binder binder = new Binder(linkerServices, callSiteType, typedName); + final MethodHandle invocation = gi.getInvocation(); + + if(nextComponent == null) { + return gic.replaceInvocation(binder.bind(invocation)); + } + + assert collectionType == CollectionType.LIST || collectionType == CollectionType.ARRAY; + final MethodHandle checkGuard = convertArgToInt(collectionType == CollectionType.LIST ? RANGE_CHECK_LIST : + RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor); + final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation), + nextComponent.getGuardedInvocation().getInvocation()); + return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(), + gic.getValidatorClass(), gic.getValidationType()); + } + + private static final MethodHandle GET_ARRAY_LENGTH = Lookup.PUBLIC.findStatic(Array.class, "getLength", + MethodType.methodType(int.class, Object.class)); + + private static final MethodHandle GET_COLLECTION_LENGTH = Lookup.PUBLIC.findVirtual(Collection.class, "size", + MethodType.methodType(int.class)); + + private static final MethodHandle GET_MAP_LENGTH = Lookup.PUBLIC.findVirtual(Map.class, "size", + MethodType.methodType(int.class)); + + private static final MethodHandle COLLECTION_GUARD = Guards.getInstanceOfGuard(Collection.class); + + private GuardedInvocationComponent getLengthGetter(final CallSiteDescriptor callSiteDescriptor) { + assertParameterCount(callSiteDescriptor, 1); + final MethodType callSiteType = callSiteDescriptor.getMethodType(); + final Class declaredType = callSiteType.parameterType(0); + // If declared type of receiver at the call site is already an array, collection, or map, bind without guard. + // Thing is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance + // they're dealing with an array, collection, or map, but hey... + if(declaredType.isArray()) { + return new GuardedInvocationComponent(GET_ARRAY_LENGTH.asType(callSiteType)); + } else if(Collection.class.isAssignableFrom(declaredType)) { + return new GuardedInvocationComponent(GET_COLLECTION_LENGTH.asType(callSiteType)); + } else if(Map.class.isAssignableFrom(declaredType)) { + return new GuardedInvocationComponent(GET_MAP_LENGTH.asType(callSiteType)); + } + + // Otherwise, create a binding based on the actual type of the argument with an appropriate guard. + if(clazz.isArray()) { + return new GuardedInvocationComponent(GET_ARRAY_LENGTH.asType(callSiteType), Guards.isArray(0, + callSiteType), ValidationType.IS_ARRAY); + } if(Collection.class.isAssignableFrom(clazz)) { + return new GuardedInvocationComponent(GET_COLLECTION_LENGTH.asType(callSiteType), Guards.asType( + COLLECTION_GUARD, callSiteType), Collection.class, ValidationType.INSTANCE_OF); + } if(Map.class.isAssignableFrom(clazz)) { + return new GuardedInvocationComponent(GET_MAP_LENGTH.asType(callSiteType), Guards.asType(MAP_GUARD, + callSiteType), Map.class, ValidationType.INSTANCE_OF); + } + // Can't retrieve length for objects that are neither arrays, nor collections, nor maps. + return null; + } + + private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) { + if(descriptor.getMethodType().parameterCount() != paramCount) { + throw new BootstrapMethodError(descriptor.getOperation() + " must have exactly " + paramCount + " parameters."); + } + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeansLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,307 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandles.Lookup; +import java.util.Collections; +import java.util.Set; +import jdk.dynalink.DynamicLinkerFactory; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; + +/** + * 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 + * {@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 {@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 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() { + @Override + protected TypeBasedGuardingDynamicLinker computeValue(final Class clazz) { + // If ClassValue.put() were public, we could just pre-populate with these known mappings... + return + clazz == Class.class ? new ClassLinker() : + clazz == StaticClass.class ? new StaticClassLinker() : + DynamicMethod.class.isAssignableFrom(clazz) ? new DynamicMethodLinker() : + new BeanLinker(clazz); + } + }; + + /** + * Creates a new 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. + * @param clazz the class + * @return a bean linker for that class + */ + public static TypeBasedGuardingDynamicLinker getLinkerForClass(final Class clazz) { + return linkers.get(clazz); + } + + /** + * 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 Java dynamic method. + * @return true if it is a dynamic method, false otherwise. + */ + public static boolean isDynamicMethod(final Object obj) { + return obj instanceof DynamicMethod; + } + + /** + * 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 Java constructor. + * @return true if it is a constructor, false otherwise. + */ + public static boolean isDynamicConstructor(final Object obj) { + return obj instanceof DynamicMethod && ((DynamicMethod)obj).isConstructor(); + } + + /** + * 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. 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); + } + + /** + * Returns a set of names of all readable instance properties of a class. + * @param clazz the class + * @return a set of names of all readable instance properties of a class. + */ + public static Set getReadableInstancePropertyNames(final Class clazz) { + final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); + if(linker instanceof BeanLinker) { + return ((BeanLinker)linker).getReadablePropertyNames(); + } + return Collections.emptySet(); + } + + /** + * Returns a set of names of all writable instance properties of a class. + * @param clazz the class + * @return a set of names of all writable instance properties of a class. + */ + public static Set getWritableInstancePropertyNames(final Class clazz) { + final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); + if(linker instanceof BeanLinker) { + return ((BeanLinker)linker).getWritablePropertyNames(); + } + return Collections.emptySet(); + } + + /** + * Returns a set of names of all instance methods of a class. + * @param clazz the class + * @return a set of names of all instance methods of a class. + */ + public static Set getInstanceMethodNames(final Class clazz) { + final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); + if(linker instanceof BeanLinker) { + return ((BeanLinker)linker).getMethodNames(); + } + return Collections.emptySet(); + } + + /** + * Returns a set of names of all readable static properties of a class. + * @param clazz the class + * @return a set of names of all readable static properties of a class. + */ + public static Set getReadableStaticPropertyNames(final Class clazz) { + return StaticClassLinker.getReadableStaticPropertyNames(clazz); + } + + /** + * Returns a set of names of all writable static properties of a class. + * @param clazz the class + * @return a set of names of all writable static properties of a class. + */ + public static Set getWritableStaticPropertyNames(final Class clazz) { + return StaticClassLinker.getWritableStaticPropertyNames(clazz); + } + + /** + * Returns a set of names of all static methods of a class. + * @param clazz the class + * @return a set of names of all static methods of a class. + */ + public static Set getStaticMethodNames(final Class clazz) { + return StaticClassLinker.getStaticMethodNames(clazz); + } + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) + throws Exception { + final Object receiver = request.getReceiver(); + if(receiver == null) { + // Can't operate on null + return null; + } + return getLinkerForClass(receiver.getClass()).getGuardedInvocation(request, linkerServices); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CallerSensitiveDynamicMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CallerSensitiveDynamicMethod.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2009-2013 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package jdk.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.internal.AccessControlContextFactory; +import jdk.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(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; + private final MethodType type; + + CallerSensitiveDynamicMethod(final AccessibleObject target) { + super(getName(target)); + this.target = target; + this.type = getMethodType(target); + } + + private static String getName(final AccessibleObject target) { + final Member m = (Member)target; + final boolean constructor = m instanceof Constructor; + return getMethodNameWithSignature(getMethodType(target), constructor ? m.getName() : + getClassAndMethodName(m.getDeclaringClass(), m.getName()), !constructor); + } + + @Override + MethodType getMethodType() { + return type; + } + + private static MethodType getMethodType(final AccessibleObject ao) { + final boolean isMethod = ao instanceof Method; + final Class rtype = isMethod ? ((Method)ao).getReturnType() : ((Constructor)ao).getDeclaringClass(); + final Class[] ptypes = isMethod ? ((Method)ao).getParameterTypes() : ((Constructor)ao).getParameterTypes(); + final MethodType type = MethodType.methodType(rtype, ptypes); + final Member m = (Member)ao; + return type.insertParameterTypes(0, + isMethod ? + Modifier.isStatic(m.getModifiers()) ? + Object.class : + m.getDeclaringClass() : + StaticClass.class); + } + + @Override + boolean isVarArgs() { + return target instanceof Method ? ((Method)target).isVarArgs() : ((Constructor)target).isVarArgs(); + } + + @Override + 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())) { + return StaticClassIntrospector.editStaticMethodHandle(mh); + } + return mh; + } + return StaticClassIntrospector.editConstructorMethodHandle(Lookup.unreflectConstructor(lookup, + (Constructor)target)); + } + + @Override + boolean isConstructor() { + return target instanceof Constructor; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CheckRestrictedPackage.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/CheckRestrictedPackage.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2009-2013 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package jdk.dynalink.beans; + +import java.lang.reflect.Modifier; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import jdk.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 = + AccessControlContextFactory.createAccessControlContext(); + + /** + * Returns true if the class is either not public, or it resides in a package with restricted access. + * @param clazz the class to test + * @return true if the class is either not public, or it resides in a package with restricted access. + */ + static boolean isRestrictedClass(final Class clazz) { + if(!Modifier.isPublic(clazz.getModifiers())) { + // Non-public classes are always restricted + return true; + } + final SecurityManager sm = System.getSecurityManager(); + if(sm == null) { + // No further restrictions if we don't have a security manager + return false; + } + final String name = clazz.getName(); + final int i = name.lastIndexOf('.'); + if (i == -1) { + // Classes in default package are never restricted + return false; + } + // Do a package access check from within an access control context with no permissions + try { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + sm.checkPackageAccess(name.substring(0, i)); + return null; + } + }, NO_PERMISSIONS_CONTEXT); + } catch(final SecurityException e) { + return true; + } + return false; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ClassLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ClassLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,108 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import jdk.dynalink.beans.GuardedInvocationComponent.ValidationType; +import jdk.dynalink.linker.support.Lookup; + +/** + * A linker for java.lang.Class objects. Provides a synthetic property "static" that allows access to static fields and + * methods on the class (respecting property getter/setter conventions). Note that Class objects are not recognized by + * the Dynalink as constructors for the instances of the class, {@link StaticClass} is used for this purpose. + */ +class ClassLinker extends BeanLinker { + + ClassLinker() { + super(Class.class); + // Map "classObject.static" to StaticClass.forClass(classObject). Can use EXACT_CLASS since class Class is final. + setPropertyGetter("static", FOR_CLASS, ValidationType.EXACT_CLASS); + } + + private static final MethodHandle FOR_CLASS = new Lookup(MethodHandles.lookup()).findStatic(StaticClass.class, + "forClass", MethodType.methodType(StaticClass.class, Class.class)); + +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ClassString.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/ClassString.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,225 @@ +/* + * 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.dynalink.beans; + +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.dynalink.internal.AccessControlContextFactory; +import jdk.dynalink.internal.InternalTypeUtilities; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.support.TypeUtilities; + +/** + * Represents a sequence of {@link Class} objects, useful for representing method signatures. Provides value + * semantics for using them as map keys, as well as specificity calculations and applicability checks as per + * 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. + */ + static final Class NULL_CLASS = (new Object() { /* Intentionally empty */ }).getClass(); + + private final Class[] classes; + private int hashCode; + + ClassString(final Class[] classes) { + this.classes = classes; + } + + ClassString(final MethodType type) { + this(type.parameterArray()); + } + + @Override + public boolean equals(final Object other) { + if(!(other instanceof ClassString)) { + return false; + } + final Class[] otherClasses = ((ClassString)other).classes; + if(otherClasses.length != classes.length) { + return false; + } + for(int i = 0; i < otherClasses.length; ++i) { + if(otherClasses[i] != classes[i]) { + return false; + } + } + return true; + } + + @Override + public int hashCode() { + if(hashCode == 0) { + int h = 0; + for(int i = 0; i < classes.length; ++i) { + h ^= classes[i].hashCode(); + } + hashCode = h; + } + return hashCode; + } + + boolean isVisibleFrom(final ClassLoader classLoader) { + return AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Boolean run() { + for(final Class clazz: classes) { + if(!InternalTypeUtilities.canReferenceDirectly(classLoader, clazz.getClassLoader())) { + return false; + } + } + return true; + } + }, GET_CLASS_LOADER_CONTEXT); + } + + List getMaximallySpecifics(final List methods, final LinkerServices linkerServices, final boolean varArg) { + return MaximallySpecific.getMaximallySpecificMethodHandles(getApplicables(methods, linkerServices, varArg), + varArg, classes, linkerServices); + } + + /** + * Returns all methods that are applicable to actual parameter classes represented by this ClassString object. + */ + LinkedList getApplicables(final List methods, final LinkerServices linkerServices, final boolean varArg) { + final LinkedList list = new LinkedList<>(); + for(final MethodHandle member: methods) { + if(isApplicable(member, linkerServices, varArg)) { + list.add(member); + } + } + return list; + } + + /** + * Returns true if the supplied method is applicable to actual parameter classes represented by this ClassString + * object. + * + */ + private boolean isApplicable(final MethodHandle method, final LinkerServices linkerServices, final boolean varArg) { + final Class[] formalTypes = method.type().parameterArray(); + final int cl = classes.length; + final int fl = formalTypes.length - (varArg ? 1 : 0); + if(varArg) { + if(cl < fl) { + return false; + } + } else { + if(cl != fl) { + return false; + } + } + // Starting from 1 as we ignore the receiver type + for(int i = 1; i < fl; ++i) { + if(!canConvert(linkerServices, classes[i], formalTypes[i])) { + return false; + } + } + if(varArg) { + final Class varArgType = formalTypes[fl].getComponentType(); + for(int i = fl; i < cl; ++i) { + if(!canConvert(linkerServices, classes[i], varArgType)) { + return false; + } + } + } + return true; + } + + private static boolean canConvert(final LinkerServices ls, final Class from, final Class to) { + if(from == NULL_CLASS) { + return !to.isPrimitive(); + } + return ls == null ? TypeUtilities.isMethodInvocationConvertible(from, to) : ls.canConvert(from, to); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/DynamicMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/DynamicMethod.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,157 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.LinkerServices; + +/** + * Represents a single dynamic method. A "dynamic" method can be bound to a single Java method, or can be bound to all + * overloaded methods of the same name on a class. Getting an invocation of a dynamic method bound to multiple + * overloaded methods will perform overload resolution (actually, it will perform partial overloaded resolution at link + * time, but if that fails to identify exactly one target method, it will generate a method handle that will perform the + * rest of the overload resolution at invocation time for actual argument types). + */ +abstract class DynamicMethod { + private final String name; + + DynamicMethod(final String name) { + this.name = name; + } + + String getName() { + return name; + } + + /** + * Creates an invocation for the dynamic method. If the method is overloaded, it will perform overloaded method + * resolution based on the specified method type. The resulting resolution can either identify a single method to be + * invoked among the overloads, or it can identify multiple ones. In the latter case, the returned method handle + * will perform further overload resolution among these candidates at every invocation. If the method to be invoked + * is a variable arguments (vararg) method, it will pack the extra arguments in an array before the invocation of + * the underlying method if it is not already done. + * + * @param callSiteDescriptor the descriptor of the call site + * @param linkerServices linker services. Used for language-specific type conversions. + * @return an invocation suitable for calling the method from the specified call site. + */ + abstract MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices); + + /** + * Returns a single dynamic method representing a single underlying Java method (possibly selected among several + * overloads) with formal parameter types exactly matching the passed signature. + * @param paramTypes the comma-separated list of requested parameter type names. The names will match both + * qualified and unqualified type names. + * @return a single dynamic method representing a single underlying Java method, or null if none of the Java methods + * behind this dynamic method exactly match the requested parameter types. + */ + abstract SingleDynamicMethod getMethodForExactParamTypes(String paramTypes); + + /** + * True if this dynamic method already contains a method with an identical signature as the passed in method. + * @param method the method to check + * @return true if it already contains an equivalent method. + */ + abstract boolean contains(SingleDynamicMethod method); + + static String getClassAndMethodName(final Class clazz, final String name) { + final String clazzName = clazz.getCanonicalName(); + return (clazzName == null ? clazz.getName() : clazzName) + "." + name; + } + + @Override + public String toString() { + return "[" + getClass().getName() + " " + getName() + "]"; + } + + /** + * True if this method happens to be a constructor method. + * + * @return true if this represents a constructor. + */ + boolean isConstructor() { + return false; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/DynamicMethodLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/DynamicMethodLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2009-2013 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package jdk.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.dynalink.linker.support.Guards; + +/** + * 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 + public boolean canLinkType(final Class type) { + return DynamicMethod.class.isAssignableFrom(type); + } + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) { + final Object receiver = linkRequest.getReceiver(); + if(!(receiver instanceof DynamicMethod)) { + return null; + } + final DynamicMethod dynMethod = (DynamicMethod)receiver; + final boolean constructor = dynMethod.isConstructor(); + final MethodHandle invocation; + + 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; + } + + // Insert null for StaticClass parameter + invocation = MethodHandles.insertArguments(ctorInvocation, 0, (Object)null); + } else { + return null; + } + + if (invocation != null) { + return new GuardedInvocation(MethodHandles.dropArguments(invocation, 0, + desc.getMethodType().parameterType(0)), Guards.getIdentityGuard(receiver)); + } + + return null; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/FacetIntrospector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/FacetIntrospector.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,184 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import jdk.dynalink.linker.support.Lookup; + +/** + * Base for classes that expose class field and method information to an {@link AbstractJavaLinker}. There are + * subclasses for instance (bean) and static facet of a class. + */ +abstract class FacetIntrospector { + private final Class clazz; + private final boolean instance; + private final boolean isRestricted; + + protected final AccessibleMembersLookup membersLookup; + + FacetIntrospector(final Class clazz, final boolean instance) { + this.clazz = clazz; + this.instance = instance; + isRestricted = CheckRestrictedPackage.isRestrictedClass(clazz); + membersLookup = new AccessibleMembersLookup(clazz, instance); + } + + /** + * Returns getters for inner classes. + * @return getters for inner classes. + */ + abstract Map getInnerClassGetters(); + + /** + * Returns the fields for the class facet. + * @return the fields for the class facet. + */ + Collection getFields() { + if(isRestricted) { + // NOTE: we can't do anything here. Unlike with methods in AccessibleMethodsLookup, we can't just return + // the fields from a public superclass, because this class might define same-named fields which will shadow + // the superclass fields, and we have no way to know if they do, since we're denied invocation of + // getFields(). Therefore, the only correct course of action is to not expose any public fields from a class + // defined in a restricted package. + return Collections.emptySet(); + } + + final Field[] fields = clazz.getFields(); + final Collection cfields = new ArrayList<>(fields.length); + for(final Field field: fields) { + final boolean isStatic = Modifier.isStatic(field.getModifiers()); + if(isStatic && clazz != field.getDeclaringClass()) { + // ignore inherited static fields + continue; + } + + if(instance != isStatic && isAccessible(field)) { + cfields.add(field); + } + } + return cfields; + } + + boolean isAccessible(final Member m) { + final Class declaring = m.getDeclaringClass(); + // (declaring == clazz) is just an optimization - we're calling this only from code that operates on a + // non-restricted class, so if the declaring class is identical to the class being inspected, then forego + // a potentially expensive restricted-package check. + return declaring == clazz || !CheckRestrictedPackage.isRestrictedClass(declaring); + } + + /** + * Returns all the methods in the facet. + * @return all the methods in the facet. + */ + Collection getMethods() { + return membersLookup.getMethods(); + } + + + MethodHandle unreflectGetter(final Field field) { + return editMethodHandle(Lookup.PUBLIC.unreflectGetter(field)); + } + + MethodHandle unreflectSetter(final Field field) { + return editMethodHandle(Lookup.PUBLIC.unreflectSetter(field)); + } + + /** + * Returns an edited method handle. A facet might need to edit an unreflected method handle before it is usable with + * the facet. By default, returns the passed method handle unchanged. The class' static facet will introduce a + * dropArguments. + * @param mh the method handle to edit. + * @return the edited method handle. + */ + abstract MethodHandle editMethodHandle(MethodHandle mh); +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/GuardedInvocationComponent.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/GuardedInvocationComponent.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,250 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import jdk.dynalink.linker.GuardedInvocation; + +/** + * Represents one component for a GuardedInvocation of a potentially composite operation of an + * {@link AbstractJavaLinker}. In addition to holding a guarded invocation, it holds semantic information about its + * guard. All guards produced in the AbstractJavaLinker are either "Class.isInstance()" or "getClass() == clazz" + * expressions. This allows choosing the most restrictive guard as the guard for the composition of two components. + */ +class GuardedInvocationComponent { + enum ValidationType { + NONE, // No guard; the operation can be linked unconditionally (quite rare); least strict. + INSTANCE_OF, // "validatorClass.isInstance(obj)" guard + EXACT_CLASS, // "obj.getClass() == validatorClass" guard; most strict. + IS_ARRAY, // "obj.getClass().isArray()" + } + + private final GuardedInvocation guardedInvocation; + private final Validator validator; + + GuardedInvocationComponent(final MethodHandle invocation) { + this(invocation, null, ValidationType.NONE); + } + + GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final ValidationType validationType) { + this(invocation, guard, null, validationType); + } + + GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final Class validatorClass, + final ValidationType validationType) { + this(invocation, guard, new Validator(validatorClass, validationType)); + } + + GuardedInvocationComponent(final GuardedInvocation guardedInvocation, final Class validatorClass, + final ValidationType validationType) { + this(guardedInvocation, new Validator(validatorClass, validationType)); + } + + GuardedInvocationComponent replaceInvocation(final MethodHandle newInvocation) { + return replaceInvocation(newInvocation, guardedInvocation.getGuard()); + } + + GuardedInvocationComponent replaceInvocation(final MethodHandle newInvocation, final MethodHandle newGuard) { + return new GuardedInvocationComponent(guardedInvocation.replaceMethods(newInvocation, + newGuard), validator); + } + + private GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final Validator validator) { + this(new GuardedInvocation(invocation, guard), validator); + } + + private GuardedInvocationComponent(final GuardedInvocation guardedInvocation, final Validator validator) { + this.guardedInvocation = guardedInvocation; + this.validator = validator; + } + + GuardedInvocation getGuardedInvocation() { + return guardedInvocation; + } + + Class getValidatorClass() { + return validator.validatorClass; + } + + ValidationType getValidationType() { + return validator.validationType; + } + + GuardedInvocationComponent compose(final MethodHandle compositeInvocation, final MethodHandle otherGuard, + final Class otherValidatorClass, final ValidationType otherValidationType) { + final Validator compositeValidator = validator.compose(new Validator(otherValidatorClass, otherValidationType)); + final MethodHandle compositeGuard = compositeValidator == validator ? guardedInvocation.getGuard() : otherGuard; + return new GuardedInvocationComponent(compositeInvocation, compositeGuard, compositeValidator); + } + + private static class Validator { + /*private*/ final Class validatorClass; + /*private*/ final ValidationType validationType; + + Validator(final Class validatorClass, final ValidationType validationType) { + this.validatorClass = validatorClass; + this.validationType = validationType; + } + + Validator compose(final Validator other) { + if(other.validationType == ValidationType.NONE) { + return this; + } + switch(validationType) { + case NONE: + return other; + case INSTANCE_OF: + switch(other.validationType) { + case INSTANCE_OF: + if(isAssignableFrom(other)) { + return other; + } else if(other.isAssignableFrom(this)) { + return this; + } + break; + case EXACT_CLASS: + if(isAssignableFrom(other)) { + return other; + } + break; + case IS_ARRAY: + if(validatorClass.isArray()) { + return this; + } + break; + default: + throw new AssertionError(); + } + break; + case EXACT_CLASS: + switch(other.validationType) { + case INSTANCE_OF: + if(other.isAssignableFrom(this)) { + return this; + } + break; + case EXACT_CLASS: + if(validatorClass == other.validatorClass) { + return this; + } + break; + case IS_ARRAY: + if(validatorClass.isArray()) { + return this; + } + break; + default: + throw new AssertionError(); + } + break; + case IS_ARRAY: + switch(other.validationType) { + case INSTANCE_OF: + case EXACT_CLASS: + if(other.validatorClass.isArray()) { + return other; + } + break; + case IS_ARRAY: + return this; + default: + throw new AssertionError(); + } + break; + default: + throw new AssertionError(); + } + throw new AssertionError("Incompatible composition " + this + " vs " + other); + } + + private boolean isAssignableFrom(final Validator other) { + return validatorClass.isAssignableFrom(other.validatorClass); + } + + @Override + public String toString() { + return "Validator[" + validationType + (validatorClass == null ? "" : (" " + validatorClass.getName())) + "]"; + } + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MaximallySpecific.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/MaximallySpecific.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,260 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import jdk.dynalink.linker.ConversionComparator.Comparison; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.support.TypeUtilities; + +/** + * Utility class that encapsulates the algorithm for choosing the maximally specific methods. + */ +class MaximallySpecific { + /** + * Given a list of methods, returns a list of maximally specific methods. + * + * @param methods the list of methods + * @param varArgs whether to assume the methods are varargs + * @return the list of maximally specific methods. + */ + static List getMaximallySpecificMethods(final List methods, final boolean varArgs) { + return getMaximallySpecificSingleDynamicMethods(methods, varArgs, null, null); + } + + private abstract static class MethodTypeGetter { + abstract MethodType getMethodType(T t); + } + + private static final MethodTypeGetter METHOD_HANDLE_TYPE_GETTER = + new MethodTypeGetter() { + @Override + MethodType getMethodType(final MethodHandle t) { + return t.type(); + } + }; + + private static final MethodTypeGetter DYNAMIC_METHOD_TYPE_GETTER = + new MethodTypeGetter() { + @Override + MethodType getMethodType(final SingleDynamicMethod t) { + return t.getMethodType(); + } + }; + + /** + * Given a list of methods handles, returns a list of maximally specific methods, applying language-runtime + * specific conversion preferences. + * + * @param methods the list of method handles + * @param varArgs whether to assume the method handles are varargs + * @param argTypes concrete argument types for the invocation + * @return the list of maximally specific method handles. + */ + static List getMaximallySpecificMethodHandles(final List methods, final boolean varArgs, + final Class[] argTypes, final LinkerServices ls) { + return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, METHOD_HANDLE_TYPE_GETTER); + } + + /** + * Given a list of methods, returns a list of maximally specific methods, applying language-runtime specific + * conversion preferences. + * + * @param methods the list of methods + * @param varArgs whether to assume the methods are varargs + * @param argTypes concrete argument types for the invocation + * @return the list of maximally specific methods. + */ + static List getMaximallySpecificSingleDynamicMethods(final List methods, + final boolean varArgs, final Class[] argTypes, final LinkerServices ls) { + return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, DYNAMIC_METHOD_TYPE_GETTER); + } + + /** + * Given a list of methods, returns a list of maximally specific methods, applying language-runtime specific + * conversion preferences. + * + * @param methods the list of methods + * @param varArgs whether to assume the methods are varargs + * @param argTypes concrete argument types for the invocation + * @return the list of maximally specific methods. + */ + private static List getMaximallySpecificMethods(final List methods, final boolean varArgs, + final Class[] argTypes, final LinkerServices ls, final MethodTypeGetter methodTypeGetter) { + if(methods.size() < 2) { + return methods; + } + final LinkedList maximals = new LinkedList<>(); + for(final T m: methods) { + final MethodType methodType = methodTypeGetter.getMethodType(m); + boolean lessSpecific = false; + for(final Iterator maximal = maximals.iterator(); maximal.hasNext();) { + final T max = maximal.next(); + switch(isMoreSpecific(methodType, methodTypeGetter.getMethodType(max), varArgs, argTypes, ls)) { + case TYPE_1_BETTER: { + maximal.remove(); + break; + } + case TYPE_2_BETTER: { + lessSpecific = true; + break; + } + case INDETERMINATE: { + // do nothing + break; + } + default: { + throw new AssertionError(); + } + } + } + if(!lessSpecific) { + maximals.addLast(m); + } + } + return maximals; + } + + private static Comparison isMoreSpecific(final MethodType t1, final MethodType t2, final boolean varArgs, final Class[] argTypes, + final LinkerServices ls) { + final int pc1 = t1.parameterCount(); + final int pc2 = t2.parameterCount(); + assert varArgs || (pc1 == pc2) && (argTypes == null || argTypes.length == pc1); + assert (argTypes == null) == (ls == null); + final int maxPc = Math.max(Math.max(pc1, pc2), argTypes == null ? 0 : argTypes.length); + boolean t1MoreSpecific = false; + boolean t2MoreSpecific = false; + // NOTE: Starting from 1 as overloaded method resolution doesn't depend on 0th element, which is the type of + // 'this'. We're only dealing with instance methods here, not static methods. Actually, static methods will have + // a fake 'this' of type StaticClass. + for(int i = 1; i < maxPc; ++i) { + final Class c1 = getParameterClass(t1, pc1, i, varArgs); + final Class c2 = getParameterClass(t2, pc2, i, varArgs); + if(c1 != c2) { + final Comparison cmp = compare(c1, c2, argTypes, i, ls); + if(cmp == Comparison.TYPE_1_BETTER && !t1MoreSpecific) { + t1MoreSpecific = true; + if(t2MoreSpecific) { + return Comparison.INDETERMINATE; + } + } + if(cmp == Comparison.TYPE_2_BETTER && !t2MoreSpecific) { + t2MoreSpecific = true; + if(t1MoreSpecific) { + return Comparison.INDETERMINATE; + } + } + } + } + if(t1MoreSpecific) { + return Comparison.TYPE_1_BETTER; + } else if(t2MoreSpecific) { + return Comparison.TYPE_2_BETTER; + } + return Comparison.INDETERMINATE; + } + + private static Comparison compare(final Class c1, final Class c2, final Class[] argTypes, final int i, final LinkerServices cmp) { + if(cmp != null) { + final Comparison c = cmp.compareConversion(argTypes[i], c1, c2); + if(c != Comparison.INDETERMINATE) { + return c; + } + } + if(TypeUtilities.isSubtype(c1, c2)) { + return Comparison.TYPE_1_BETTER; + } if(TypeUtilities.isSubtype(c2, c1)) { + return Comparison.TYPE_2_BETTER; + } + return Comparison.INDETERMINATE; + } + + private static Class getParameterClass(final MethodType t, final int l, final int i, final boolean varArgs) { + return varArgs && i >= l - 1 ? t.parameterType(l - 1).getComponentType() : t.parameterType(i); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedDynamicMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedDynamicMethod.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,433 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +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.dynalink.CallSiteDescriptor; +import jdk.dynalink.beans.ApplicableOverloadedMethods.ApplicabilityTest; +import jdk.dynalink.internal.AccessControlContextFactory; +import jdk.dynalink.internal.InternalTypeUtilities; +import jdk.dynalink.linker.LinkerServices; + +/** + * Represents a group of {@link SingleDynamicMethod} objects that represents all overloads of a particular name (or all + * constructors) for a particular class. Correctly handles overload resolution, variable arity methods, and caller + * sensitive methods within the overloads. + */ +class OverloadedDynamicMethod extends DynamicMethod { + /** + * Holds a list of all methods. + */ + private final LinkedList methods; + private final ClassLoader classLoader; + + /** + * Creates a new overloaded dynamic method. + * + * @param clazz the class this method belongs to + * @param name the name of the method + */ + OverloadedDynamicMethod(final Class clazz, final String name) { + this(new LinkedList(), clazz.getClassLoader(), getClassAndMethodName(clazz, name)); + } + + private OverloadedDynamicMethod(final LinkedList methods, final ClassLoader classLoader, final String name) { + super(name); + this.methods = methods; + this.classLoader = classLoader; + } + + @Override + SingleDynamicMethod getMethodForExactParamTypes(final String paramTypes) { + final LinkedList matchingMethods = new LinkedList<>(); + for(final SingleDynamicMethod method: methods) { + final SingleDynamicMethod matchingMethod = method.getMethodForExactParamTypes(paramTypes); + if(matchingMethod != null) { + matchingMethods.add(matchingMethod); + } + } + switch(matchingMethods.size()) { + case 0: { + return null; + } + case 1: { + return matchingMethods.getFirst(); + } + default: { + throw new BootstrapMethodError("Can't choose among " + matchingMethods + " for argument types " + + paramTypes + " for method " + getName()); + } + } + } + + @Override + public MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { + final MethodType callSiteType = callSiteDescriptor.getMethodType(); + // First, find all methods applicable to the call site by subtyping (JLS 15.12.2.2) + final ApplicableOverloadedMethods subtypingApplicables = getApplicables(callSiteType, + ApplicableOverloadedMethods.APPLICABLE_BY_SUBTYPING); + // Next, find all methods applicable by method invocation conversion to the call site (JLS 15.12.2.3). + final ApplicableOverloadedMethods methodInvocationApplicables = getApplicables(callSiteType, + ApplicableOverloadedMethods.APPLICABLE_BY_METHOD_INVOCATION_CONVERSION); + // Finally, find all methods applicable by variable arity invocation. (JLS 15.12.2.4). + final ApplicableOverloadedMethods variableArityApplicables = getApplicables(callSiteType, + ApplicableOverloadedMethods.APPLICABLE_BY_VARIABLE_ARITY); + + // Find the methods that are maximally specific based on the call site signature + List maximallySpecifics = subtypingApplicables.findMaximallySpecificMethods(); + if(maximallySpecifics.isEmpty()) { + maximallySpecifics = methodInvocationApplicables.findMaximallySpecificMethods(); + if(maximallySpecifics.isEmpty()) { + maximallySpecifics = variableArityApplicables.findMaximallySpecificMethods(); + } + } + + // Now, get a list of the rest of the methods; those that are *not* applicable to the call site signature based + // on JLS rules. As paradoxical as that might sound, we have to consider these for dynamic invocation, as they + // might match more concrete types passed in invocations. That's why we provisionally call them "invokables". + // This is typical for very generic signatures at call sites. Typical example: call site specifies + // (Object, Object), and we have a method whose parameter types are (String, int). None of the JLS applicability + // rules will trigger, but we must consider the method, as it can be the right match for a concrete invocation. + @SuppressWarnings({ "unchecked", "rawtypes" }) + final List invokables = (List)methods.clone(); + invokables.removeAll(subtypingApplicables.getMethods()); + invokables.removeAll(methodInvocationApplicables.getMethods()); + invokables.removeAll(variableArityApplicables.getMethods()); + for(final Iterator it = invokables.iterator(); it.hasNext();) { + final SingleDynamicMethod m = it.next(); + if(!isApplicableDynamically(linkerServices, callSiteType, m)) { + it.remove(); + } + } + + // If no additional methods can apply at invocation time, and there's more than one maximally specific method + // based on call site signature, that is a link-time ambiguity. In a static scenario, javac would report an + // ambiguity error. + if(invokables.isEmpty() && maximallySpecifics.size() > 1) { + throw new BootstrapMethodError("Can't choose among " + maximallySpecifics + " for argument types " + + callSiteType); + } + + // Merge them all. + invokables.addAll(maximallySpecifics); + switch(invokables.size()) { + case 0: { + // No overloads can ever match the call site type + return null; + } + case 1: { + // Very lucky, we ended up with a single candidate method handle based on the call site signature; we + // can link it very simply by delegating to the SingleDynamicMethod. + return invokables.iterator().next().getInvocation(callSiteDescriptor, linkerServices); + } + default: { + // We have more than one candidate. We have no choice but to link to a method that resolves overloads on + // every invocation (alternatively, we could opportunistically link the one method that resolves for the + // current arguments, but we'd need to install a fairly complex guard for that and when it'd fail, we'd + // go back all the way to candidate selection. Note that we're resolving any potential caller sensitive + // 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()); + for(final SingleDynamicMethod method: invokables) { + methodHandles.add(method.getTarget(callSiteDescriptor)); + } + 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 + public boolean contains(final SingleDynamicMethod m) { + for(final SingleDynamicMethod method: methods) { + if(method.contains(m)) { + return true; + } + } + return false; + } + + @Override + public boolean isConstructor() { + assert !methods.isEmpty(); + return methods.getFirst().isConstructor(); + } + + @Override + public String toString() { + // First gather the names and sort them. This makes it consistent and easier to read. + final List names = new ArrayList<>(methods.size()); + int len = 0; + for (final SingleDynamicMethod m: methods) { + final String name = m.getName(); + len += name.length(); + names.add(name); + } + // Case insensitive sorting, so e.g. "Object" doesn't come before "boolean". + final Collator collator = Collator.getInstance(); + collator.setStrength(Collator.SECONDARY); + Collections.sort(names, collator); + + final String className = getClass().getName(); + // Class name length + length of signatures + 2 chars/per signature for indentation and newline + + // 3 for brackets and initial newline + final int totalLength = className.length() + len + 2 * names.size() + 3; + final StringBuilder b = new StringBuilder(totalLength); + b.append('[').append(className).append('\n'); + for(final String name: names) { + b.append(' ').append(name).append('\n'); + } + b.append(']'); + assert b.length() == totalLength; + return b.toString(); + }; + + ClassLoader getClassLoader() { + return classLoader; + } + + private static boolean isApplicableDynamically(final LinkerServices linkerServices, final MethodType callSiteType, + final SingleDynamicMethod m) { + final MethodType methodType = m.getMethodType(); + final boolean varArgs = m.isVarArgs(); + final int fixedArgLen = methodType.parameterCount() - (varArgs ? 1 : 0); + final int callSiteArgLen = callSiteType.parameterCount(); + + // Arity checks + if(varArgs) { + if(callSiteArgLen < fixedArgLen) { + return false; + } + } else if(callSiteArgLen != fixedArgLen) { + return false; + } + + // Fixed arguments type checks, starting from 1, as receiver type doesn't participate + for(int i = 1; i < fixedArgLen; ++i) { + if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), methodType.parameterType(i))) { + return false; + } + } + if(!varArgs) { + // Not vararg; both arity and types matched. + return true; + } + + final Class varArgArrayType = methodType.parameterType(fixedArgLen); + final Class varArgType = varArgArrayType.getComponentType(); + + if(fixedArgLen == callSiteArgLen - 1) { + // Exactly one vararg; check both array type matching and array component type matching. + final Class callSiteArgType = callSiteType.parameterType(fixedArgLen); + return isApplicableDynamically(linkerServices, callSiteArgType, varArgArrayType) + || isApplicableDynamically(linkerServices, callSiteArgType, varArgType); + } + + // Either zero, or more than one vararg; check if all actual vararg types match the vararg array component type. + for(int i = fixedArgLen; i < callSiteArgLen; ++i) { + if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), varArgType)) { + return false; + } + } + + return true; + } + + private static boolean isApplicableDynamically(final LinkerServices linkerServices, final Class callSiteType, + final Class methodType) { + return isPotentiallyConvertible(callSiteType, methodType) + || linkerServices.canConvert(callSiteType, methodType); + } + + private ApplicableOverloadedMethods getApplicables(final MethodType callSiteType, final ApplicabilityTest test) { + return new ApplicableOverloadedMethods(methods, callSiteType, test); + } + + /** + * Add a method to this overloaded method's set. + * + * @param method a method to add + */ + public void addMethod(final SingleDynamicMethod method) { + assert constructorFlagConsistent(method); + methods.add(method); + } + + 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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/OverloadedMethod.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,280 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import jdk.dynalink.internal.InternalTypeUtilities; +import jdk.dynalink.linker.LinkerServices; +import jdk.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 + * a vararg subset depending on the subclass. The method is for a fixed number of arguments though (as it is generated + * for a concrete call site). As such, all methods in the subset can be invoked with the specified number of arguments + * (exactly matching for fixargs, or having less than or equal fixed arguments, for varargs). + */ +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 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; + + fixArgMethods = new ArrayList<>(methodHandles.size()); + varArgMethods = new ArrayList<>(methodHandles.size()); + final int argNum = callSiteType.parameterCount(); + for(final MethodHandle mh: methodHandles) { + if(mh.isVarargsCollector()) { + final MethodHandle asFixed = mh.asFixedArity(); + if(argNum == asFixed.type().parameterCount()) { + fixArgMethods.add(asFixed); + } + varArgMethods.add(mh); + } else { + fixArgMethods.add(mh); + } + } + fixArgMethods.trimToSize(); + varArgMethods.trimToSize(); + + final MethodHandle bound = SELECT_METHOD.bindTo(this); + final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType( + callSiteType.changeReturnType(MethodHandle.class)); + invoker = linkerServices.asTypeLosslessReturn(MethodHandles.foldArguments( + MethodHandles.exactInvoker(this.callSiteType), collecting), callSiteType); + } + + MethodHandle getInvoker() { + return invoker; + } + + private static final MethodHandle SELECT_METHOD = Lookup.findOwnSpecial(MethodHandles.lookup(), "selectMethod", + MethodHandle.class, Object[].class); + + @SuppressWarnings("unused") + private MethodHandle selectMethod(final Object[] args) throws NoSuchMethodException { + final Class[] argTypes = new Class[args.length]; + for(int i = 0; i < argTypes.length; ++i) { + final Object arg = args[i]; + argTypes[i] = arg == null ? ClassString.NULL_CLASS : arg.getClass(); + } + final ClassString classString = new ClassString(argTypes); + MethodHandle method = argTypesToMethods.get(classString); + if(method == null) { + List methods = classString.getMaximallySpecifics(fixArgMethods, linkerServices, false); + if(methods.isEmpty()) { + methods = classString.getMaximallySpecifics(varArgMethods, linkerServices, true); + } + switch(methods.size()) { + case 0: { + method = getNoSuchMethodThrower(argTypes); + break; + } + case 1: { + method = SingleDynamicMethod.getInvocation(methods.get(0), callSiteType, linkerServices); + break; + } + default: { + // This is unfortunate - invocation time ambiguity. We can still save the day if + method = getAmbiguousMethodThrower(argTypes, methods); + break; + } + } + // Avoid keeping references to unrelated classes; this ruins the + // performance a bit, but avoids class loader memory leaks. + if(classString.isVisibleFrom(callSiteClassLoader)) { + argTypesToMethods.put(classString, method); + } + } + return method; + } + + private MethodHandle getNoSuchMethodThrower(final Class[] argTypes) { + return adaptThrower(MethodHandles.insertArguments(THROW_NO_SUCH_METHOD, 0, this, argTypes)); + } + + private static final MethodHandle THROW_NO_SUCH_METHOD = Lookup.findOwnSpecial(MethodHandles.lookup(), + "throwNoSuchMethod", void.class, Class[].class); + + @SuppressWarnings("unused") + private void throwNoSuchMethod(final Class[] argTypes) throws NoSuchMethodException { + if(varArgMethods.isEmpty()) { + throw new NoSuchMethodException("None of the fixed arity signatures " + getSignatureList(fixArgMethods) + + " of method " + parent.getName() + " match the argument types " + argTypesString(argTypes)); + } + throw new NoSuchMethodException("None of the fixed arity signatures " + getSignatureList(fixArgMethods) + + " or the variable arity signatures " + getSignatureList(varArgMethods) + " of the method " + + parent.getName() + " match the argument types " + argTypesString(argTypes)); + } + + private MethodHandle getAmbiguousMethodThrower(final Class[] argTypes, final List methods) { + return adaptThrower(MethodHandles.insertArguments(THROW_AMBIGUOUS_METHOD, 0, this, argTypes, methods)); + } + + private MethodHandle adaptThrower(final MethodHandle rawThrower) { + return MethodHandles.dropArguments(rawThrower, 0, callSiteType.parameterList()).asType(callSiteType); + } + + private static final MethodHandle THROW_AMBIGUOUS_METHOD = Lookup.findOwnSpecial(MethodHandles.lookup(), + "throwAmbiguousMethod", void.class, Class[].class, List.class); + + @SuppressWarnings("unused") + private void throwAmbiguousMethod(final Class[] argTypes, final List methods) throws NoSuchMethodException { + final String arity = methods.get(0).isVarargsCollector() ? "variable" : "fixed"; + throw new NoSuchMethodException("Can't unambiguously select between " + arity + " arity signatures " + + getSignatureList(methods) + " of the method " + parent.getName() + " for argument types " + + argTypesString(argTypes)); + } + + private static String argTypesString(final Class[] classes) { + final StringBuilder b = new StringBuilder().append('['); + appendTypes(b, classes, false); + return b.append(']').toString(); + } + + private static String getSignatureList(final List methods) { + final StringBuilder b = new StringBuilder().append('['); + final Iterator it = methods.iterator(); + if(it.hasNext()) { + appendSig(b, it.next()); + while(it.hasNext()) { + appendSig(b.append(", "), it.next()); + } + } + return b.append(']').toString(); + } + + private static void appendSig(final StringBuilder b, final MethodHandle m) { + b.append('('); + appendTypes(b, m.type().parameterArray(), m.isVarargsCollector()); + b.append(')'); + } + + private static void appendTypes(final StringBuilder b, final Class[] classes, final boolean varArg) { + final int l = classes.length; + if(!varArg) { + if(l > 1) { + b.append(classes[1].getCanonicalName()); + for(int i = 2; i < l; ++i) { + b.append(", ").append(classes[i].getCanonicalName()); + } + } + } else { + for(int i = 1; i < l - 1; ++i) { + b.append(classes[i].getCanonicalName()).append(", "); + } + b.append(classes[l - 1].getComponentType().getCanonicalName()).append("..."); + } + } + + private static Class getCommonReturnType(final List methodHandles) { + final Iterator it = methodHandles.iterator(); + Class retType = it.next().type().returnType(); + while(it.hasNext()) { + retType = InternalTypeUtilities.getCommonLosslessConversionType(retType, it.next().type().returnType()); + } + return retType; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/SimpleDynamicMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/SimpleDynamicMethod.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,151 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import jdk.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(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. + */ +class SimpleDynamicMethod extends SingleDynamicMethod { + private final MethodHandle target; + private final boolean constructor; + + /** + * Creates a new simple dynamic method, with a name constructed from the class name, method name, and handle + * signature. + * + * @param target the target method handle + * @param clazz the class declaring the method + * @param name the simple name of the method + */ + SimpleDynamicMethod(final MethodHandle target, final Class clazz, final String name) { + this(target, clazz, name, false); + } + + /** + * Creates a new simple dynamic method, with a name constructed from the class name, method name, and handle + * signature. + * + * @param target the target method handle + * @param clazz the class declaring the method + * @param name the simple name of the method + * @param constructor does this represent a constructor? + */ + SimpleDynamicMethod(final MethodHandle target, final Class clazz, final String name, final boolean constructor) { + super(getName(target, clazz, name, constructor)); + this.target = target; + this.constructor = constructor; + } + + private static String getName(final MethodHandle target, final Class clazz, final String name, final boolean constructor) { + return getMethodNameWithSignature(target.type(), constructor ? name : getClassAndMethodName(clazz, name), !constructor); + } + + @Override + boolean isVarArgs() { + return target.isVarargsCollector(); + } + + @Override + MethodType getMethodType() { + return target.type(); + } + + @Override + MethodHandle getTarget(final CallSiteDescriptor desc) { + return target; + } + + @Override + boolean isConstructor() { + return constructor; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/SingleDynamicMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/SingleDynamicMethod.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,312 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Array; +import java.util.StringTokenizer; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.support.Guards; +import jdk.dynalink.linker.support.Lookup; + +/** + * Base class for dynamic methods that dispatch to a single target Java method or constructor. Handles adaptation of the + * target method to a call site type (including mapping variable arity methods to a call site signature with different + * arity). + */ +abstract class SingleDynamicMethod extends DynamicMethod { + + private static final MethodHandle CAN_CONVERT_TO = Lookup.findOwnStatic(MethodHandles.lookup(), "canConvertTo", boolean.class, LinkerServices.class, Class.class, Object.class); + + SingleDynamicMethod(final String name) { + super(name); + } + + /** + * Returns true if this method is variable arity. + * @return true if this method is variable arity. + */ + abstract boolean isVarArgs(); + + /** + * Returns this method's native type. + * @return this method's native type. + */ + abstract MethodType getMethodType(); + + /** + * 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(CallSiteDescriptor desc); + + @Override + MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { + return getInvocation(getTarget(callSiteDescriptor), callSiteDescriptor.getMethodType(), + linkerServices); + } + + @Override + SingleDynamicMethod getMethodForExactParamTypes(final String paramTypes) { + return typeMatchesDescription(paramTypes, getMethodType()) ? this : null; + } + + @Override + boolean contains(final SingleDynamicMethod method) { + return getMethodType().parameterList().equals(method.getMethodType().parameterList()); + } + + static String getMethodNameWithSignature(final MethodType type, final String methodName, final boolean withReturnType) { + final String typeStr = type.toString(); + final int retTypeIndex = typeStr.lastIndexOf(')') + 1; + int secondParamIndex = typeStr.indexOf(',') + 1; + if(secondParamIndex == 0) { + secondParamIndex = retTypeIndex - 1; + } + final StringBuilder b = new StringBuilder(); + if (withReturnType) { + b.append(typeStr, retTypeIndex, typeStr.length()).append(' '); + } + return b.append(methodName).append('(').append(typeStr, secondParamIndex, retTypeIndex).toString(); + } + + /** + * Given a method handle and a call site type, adapts the method handle to the call site type. Performs type + * conversions as needed using the specified linker services, and in case that the method handle is a vararg + * collector, matches it to the arity of the call site. The type of the return value is only changed if it can be + * converted using a conversion that loses neither precision nor magnitude, see + * {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)}. + * @param target the method handle to adapt + * @param callSiteType the type of the call site + * @param linkerServices the linker services used for type conversions + * @return the adapted method handle. + */ + static MethodHandle getInvocation(final MethodHandle target, final MethodType callSiteType, final LinkerServices linkerServices) { + final MethodHandle filteredTarget = linkerServices.filterInternalObjects(target); + final MethodType methodType = filteredTarget.type(); + final int paramsLen = methodType.parameterCount(); + final boolean varArgs = target.isVarargsCollector(); + final MethodHandle fixTarget = varArgs ? filteredTarget.asFixedArity() : filteredTarget; + final int fixParamsLen = varArgs ? paramsLen - 1 : paramsLen; + final int argsLen = callSiteType.parameterCount(); + if(argsLen < fixParamsLen) { + // Less actual arguments than number of fixed declared arguments; can't invoke. + return null; + } + // Method handle has the same number of fixed arguments as the call site type + if(argsLen == fixParamsLen) { + // Method handle that matches the number of actual arguments as the number of fixed arguments + final MethodHandle matchedMethod; + if(varArgs) { + // If vararg, add a zero-length array of the expected type as the last argument to signify no variable + // arguments. + matchedMethod = MethodHandles.insertArguments(fixTarget, fixParamsLen, Array.newInstance( + methodType.parameterType(fixParamsLen).getComponentType(), 0)); + } else { + // Otherwise, just use the method + matchedMethod = fixTarget; + } + return createConvertingInvocation(matchedMethod, linkerServices, callSiteType); + } + + // What's below only works for varargs + if(!varArgs) { + return null; + } + + final Class varArgType = methodType.parameterType(fixParamsLen); + // Handle a somewhat sinister corner case: caller passes exactly one argument in the vararg position, and we + // must handle both a prepacked vararg array as well as a genuine 1-long vararg sequence. + if(argsLen == paramsLen) { + final Class callSiteLastArgType = callSiteType.parameterType(fixParamsLen); + if(varArgType.isAssignableFrom(callSiteLastArgType)) { + // Call site signature guarantees we'll always be passed a single compatible array; just link directly + // to the method, introducing necessary conversions. Also, preserve it being a variable arity method. + return createConvertingInvocation(filteredTarget, linkerServices, callSiteType).asVarargsCollector( + callSiteLastArgType); + } + + // This method handle takes the single argument and packs it into a newly allocated single-element array. It + // will be used when the incoming argument can't be converted to the vararg array type (the "vararg packer" + // method). + final MethodHandle varArgCollectingInvocation = createConvertingInvocation(collectArguments(fixTarget, + argsLen), linkerServices, callSiteType); + + // Is call site type assignable from an array type (e.g. Object:int[], or Object[]:String[]) + final boolean isAssignableFromArray = callSiteLastArgType.isAssignableFrom(varArgType); + // Do we have a custom conversion that can potentially convert the call site type to an array? + final boolean isCustomConvertible = linkerServices.canConvert(callSiteLastArgType, varArgType); + if(!isAssignableFromArray && !isCustomConvertible) { + // Call site signature guarantees the argument can definitely not be converted to an array (i.e. it is + // primitive), and no conversion can help with it either. Link immediately to a vararg-packing method + // handle. + return varArgCollectingInvocation; + } + + // This method handle employs language-specific conversions to convert the last argument into an array of + // vararg type. + final MethodHandle arrayConvertingInvocation = createConvertingInvocation(MethodHandles.filterArguments( + fixTarget, fixParamsLen, linkerServices.getTypeConverter(callSiteLastArgType, varArgType)), + linkerServices, callSiteType); + + // This method handle determines whether the value can be converted to the array of vararg type using a + // language-specific conversion. + final MethodHandle canConvertArgToArray = MethodHandles.insertArguments(CAN_CONVERT_TO, 0, linkerServices, + varArgType); + + // This one adjusts the previous one for the location of the argument and the call site type. + final MethodHandle canConvertLastArgToArray = MethodHandles.dropArguments(canConvertArgToArray, 0, + MethodType.genericMethodType(fixParamsLen).parameterList()).asType(callSiteType.changeReturnType(boolean.class)); + + // This one takes the previous ones and combines them into a method handle that converts the argument into + // a vararg array when it can, otherwise falls back to the vararg packer. + final MethodHandle convertToArrayWhenPossible = MethodHandles.guardWithTest(canConvertLastArgToArray, + arrayConvertingInvocation, varArgCollectingInvocation); + + if(isAssignableFromArray) { + return MethodHandles.guardWithTest( + // Is incoming parameter already a compatible array? + Guards.isInstance(varArgType, fixParamsLen, callSiteType), + // Yes: just pass it to the method + createConvertingInvocation(fixTarget, linkerServices, callSiteType), + // No: either go through a custom conversion, or if it is not possible, go directly to the + // vararg packer. + isCustomConvertible ? convertToArrayWhenPossible : varArgCollectingInvocation); + } + + // Just do the custom conversion with fallback to the vararg packer logic. + assert isCustomConvertible; + return convertToArrayWhenPossible; + } + + // Remaining case: more than one vararg. + return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType); + } + + @SuppressWarnings("unused") + private static boolean canConvertTo(final LinkerServices linkerServices, final Class to, final Object obj) { + return obj == null ? false : linkerServices.canConvert(obj.getClass(), to); + } + + /** + * Creates a method handle out of the original target that will collect the varargs for the exact component type of + * the varArg array. Note that this will nicely trigger language-specific type converters for exactly those varargs + * for which it is necessary when later passed to linkerServices.convertArguments(). + * + * @param target the original method handle + * @param parameterCount the total number of arguments in the new method handle + * @return a collecting method handle + */ + static MethodHandle collectArguments(final MethodHandle target, final int parameterCount) { + final MethodType methodType = target.type(); + final int fixParamsLen = methodType.parameterCount() - 1; + final Class arrayType = methodType.parameterType(fixParamsLen); + return target.asCollector(arrayType, parameterCount - fixParamsLen); + } + + private static MethodHandle createConvertingInvocation(final MethodHandle sizedMethod, + final LinkerServices linkerServices, final MethodType callSiteType) { + return linkerServices.asTypeLosslessReturn(sizedMethod, callSiteType); + } + + private static boolean typeMatchesDescription(final String paramTypes, final MethodType type) { + final StringTokenizer tok = new StringTokenizer(paramTypes, ", "); + for(int i = 1; i < type.parameterCount(); ++i) { // i = 1 as we ignore the receiver + if(!(tok.hasMoreTokens() && typeNameMatches(tok.nextToken(), type.parameterType(i)))) { + return false; + } + } + return !tok.hasMoreTokens(); + } + + private static boolean typeNameMatches(final String typeName, final Class type) { + return typeName.equals(typeName.indexOf('.') == -1 ? type.getSimpleName() : type.getCanonicalName()); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClass.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,179 @@ +/* + * 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.dynalink.beans; + +import java.io.Serializable; +import java.util.Objects; +import jdk.dynalink.StandardOperation; + +/** + * 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 final class StaticClass implements Serializable { + private static final ClassValue staticClasses = new ClassValue() { + @Override + protected StaticClass computeValue(final Class type) { + return new StaticClass(type); + } + }; + + private static final long serialVersionUID = 1L; + + /** + * The runtime {@code Class} object whose static members this + * {@code StaticClass} represents. + */ + private final Class clazz; + + /*private*/ StaticClass(final Class clazz) { + this.clazz = Objects.requireNonNull(clazz); + } + + /** + * Retrieves the {@link StaticClass} instance for the specified class. + * @param clazz the class for which the static facet is requested. + * @return the {@link StaticClass} instance representing the specified class. + */ + public static StaticClass forClass(final Class clazz) { + return staticClasses.get(clazz); + } + + /** + * Returns the represented Java class. + * @return the represented Java class. + */ + public Class getRepresentedClass() { + return clazz; + } + + @Override + public String toString() { + return "StaticClass[" + clazz.getName() + "]"; + } + + /** + * Returns {@link #forClass(Class)} for the underlying {@code clazz} field + * ensuring that deserialization doesn't create non-canonical instances. + * @return {@link #forClass(Class)} for the underlying {@code clazz} field. + */ + private Object readResolve() { + return forClass(clazz); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassIntrospector.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassIntrospector.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,129 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.HashMap; +import java.util.Map; + +class StaticClassIntrospector extends FacetIntrospector { + StaticClassIntrospector(final Class clazz) { + super(clazz, false); + } + + @Override + Map getInnerClassGetters() { + final Map map = new HashMap<>(); + for(final Class innerClass: membersLookup.getInnerClasses()) { + map.put(innerClass.getSimpleName(), editMethodHandle(MethodHandles.constant(StaticClass.class, + StaticClass.forClass(innerClass)))); + } + return map; + } + + @Override + MethodHandle editMethodHandle(final MethodHandle mh) { + return editStaticMethodHandle(mh); + } + + static MethodHandle editStaticMethodHandle(final MethodHandle mh) { + return dropReceiver(mh, Object.class); + } + + static MethodHandle editConstructorMethodHandle(final MethodHandle cmh) { + return dropReceiver(cmh, StaticClass.class); + } + + private static MethodHandle dropReceiver(final MethodHandle mh, final Class receiverClass) { + MethodHandle newHandle = MethodHandles.dropArguments(mh, 0, receiverClass); + // NOTE: this is a workaround for the fact that dropArguments doesn't preserve vararg collector state. + if(mh.isVarargsCollector() && !newHandle.isVarargsCollector()) { + final MethodType type = mh.type(); + newHandle = newHandle.asVarargsCollector(type.parameterType(type.parameterCount() - 1)); + } + return newHandle; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/StaticClassLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,216 @@ +/* + * 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.dynalink.beans; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.Set; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.beans.GuardedInvocationComponent.ValidationType; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.dynalink.linker.support.Lookup; + +/** + * Provides a linker for the {@link StaticClass} objects. + */ +class StaticClassLinker implements TypeBasedGuardingDynamicLinker { + private static final ClassValue linkers = new ClassValue() { + @Override + protected SingleClassStaticsLinker computeValue(final Class clazz) { + return new SingleClassStaticsLinker(clazz); + } + }; + + private static class SingleClassStaticsLinker extends AbstractJavaLinker { + private final DynamicMethod constructor; + + SingleClassStaticsLinker(final Class clazz) { + super(clazz, IS_CLASS.bindTo(clazz)); + // Map "staticClassObject.class" to StaticClass.getRepresentedClass(). Some adventurous soul could subclass + // StaticClass, so we use INSTANCE_OF validation instead of EXACT_CLASS. + setPropertyGetter("class", GET_CLASS, ValidationType.INSTANCE_OF); + constructor = createConstructorMethod(clazz); + } + + /** + * Creates a dynamic method containing all overloads of a class' public constructor + * @param clazz the target class + * @return a dynamic method containing all overloads of a class' public constructor. If the class has no public + * constructors, returns null. + */ + private static DynamicMethod createConstructorMethod(final Class clazz) { + if(clazz.isArray()) { + final MethodHandle boundArrayCtor = ARRAY_CTOR.bindTo(clazz.getComponentType()); + return new SimpleDynamicMethod(StaticClassIntrospector.editConstructorMethodHandle( + boundArrayCtor.asType(boundArrayCtor.type().changeReturnType(clazz))), clazz, ""); + } + if(CheckRestrictedPackage.isRestrictedClass(clazz)) { + return null; + } + return createDynamicMethod(Arrays.asList(clazz.getConstructors()), clazz, ""); + } + + @Override + FacetIntrospector createFacetIntrospector() { + return new StaticClassIntrospector(clazz); + } + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) + throws Exception { + final GuardedInvocation gi = super.getGuardedInvocation(request, linkerServices); + if(gi != null) { + return gi; + } + final CallSiteDescriptor desc = request.getCallSiteDescriptor(); + 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())); + } + } + return null; + } + + @Override + SingleDynamicMethod getConstructorMethod(final String signature) { + return constructor != null? constructor.getMethodForExactParamTypes(signature) : null; + } + } + + static Object getConstructorMethod(final Class clazz, final String signature) { + return linkers.get(clazz).getConstructorMethod(signature); + } + + static Set getReadableStaticPropertyNames(final Class clazz) { + return linkers.get(clazz).getReadablePropertyNames(); + } + + static Set getWritableStaticPropertyNames(final Class clazz) { + return linkers.get(clazz).getWritablePropertyNames(); + } + + static Set getStaticMethodNames(final Class clazz) { + return linkers.get(clazz).getMethodNames(); + } + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception { + final Object receiver = request.getReceiver(); + if(receiver instanceof StaticClass) { + return linkers.get(((StaticClass)receiver).getRepresentedClass()).getGuardedInvocation(request, + linkerServices); + } + return null; + } + + @Override + public boolean canLinkType(final Class type) { + return type == StaticClass.class; + } + + /*private*/ static final MethodHandle GET_CLASS; + /*private*/ static final MethodHandle IS_CLASS; + /*private*/ static final MethodHandle ARRAY_CTOR = Lookup.PUBLIC.findStatic(Array.class, "newInstance", + MethodType.methodType(Object.class, Class.class, int.class)); + + static { + final Lookup lookup = new Lookup(MethodHandles.lookup()); + GET_CLASS = lookup.findVirtual(StaticClass.class, "getRepresentedClass", MethodType.methodType(Class.class)); + IS_CLASS = lookup.findOwnStatic("isClass", Boolean.TYPE, Class.class, Object.class); + } + + @SuppressWarnings("unused") + private static boolean isClass(final Class clazz, final Object obj) { + return obj instanceof StaticClass && ((StaticClass)obj).getRepresentedClass() == clazz; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/messages.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/messages.properties Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,25 @@ +# Copyright 2009-2013 Attila Szegedi +# +# Licensed under either the Apache License, Version 2.0 (the "Apache +# License") or the BSD License (the "BSD License"), with licensee +# being free to choose either of the two at their discretion. +# +# You may not use this file except in compliance with either the Apache +# License or the BSD License. +# +# A copy of the BSD License is available in the root directory of the +# source distribution of the project under the file name +# "Dynalink-License-BSD.txt". +# +# A copy of the Apache License is available in the root directory of the +# source distribution of the project under the file name +# "Dynalink-License-Apache-2.0.txt". Alternatively, you may obtain a +# copy of the Apache License at +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See your chosen License for the specific language governing permissions +# and limitations under that License. + +couldNotDiscoverAccessibleMethods=Could not discover accessible methods of class {0}, trying its superclasses and interfaces. diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/beans/package-info.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.dynalink.beans; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/internal/AccessControlContextFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/internal/AccessControlContextFactory.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/internal/InternalTypeUtilities.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/internal/InternalTypeUtilities.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.dynalink.internal; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; +import jdk.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/ConversionComparator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/ConversionComparator.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,120 @@ +/* + * 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.dynalink.linker; + + +/** + * Optional interface to be implemented by {@link GuardingTypeConverterFactory} + * implementers. Language-specific conversions can cause increased overloaded + * method resolution ambiguity, as many methods can become applicable because of + * additional conversions. The static way of selecting the "most specific" + * method will fail more often, because there will be multiple maximally + * specific method with unrelated signatures. In these cases, language runtimes + * can be asked to resolve the ambiguity by expressing preferences for one + * conversion over the other. + */ +public interface ConversionComparator { + /** + * Enumeration of possible outcomes of comparing one conversion to another. + */ + enum Comparison { + /** The conversions cannot be compared. **/ + INDETERMINATE, + /** The first conversion is better than the second one. **/ + TYPE_1_BETTER, + /** The second conversion is better than the first one. **/ + TYPE_2_BETTER, + } + + /** + * Determines which of the two target types is the preferred conversion + * target from a source type. + * @param sourceType the source type. + * @param targetType1 one potential target type + * @param targetType2 another potential target type. + * @return one of Comparison constants that establish which - if any - of + * the target types is preferred for the conversion. + */ + public Comparison compareConversion(Class sourceType, Class targetType1, Class targetType2); +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocation.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,483 @@ +/* + * 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.dynalink.linker; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.invoke.SwitchPoint; +import java.util.List; +import java.util.Objects; +import java.util.function.Supplier; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.support.Guards; + +/** + * 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; + private final MethodHandle guard; + private final Class exception; + private final SwitchPoint[] switchPoints; + + /** + * 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. + * @throws NullPointerException if invocation is null. + */ + public GuardedInvocation(final MethodHandle invocation) { + this(invocation, null, (SwitchPoint)null, null); + } + + /** + * 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 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) { + this(invocation, guard, (SwitchPoint)null, null); + } + + /** + * 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. 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) { + this(invocation, null, switchPoint, null); + } + + /** + * 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 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) { + this(invocation, guard, switchPoint, null); + } + + /** + * 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 be + * compatible with the {@code invocation} handle as per + * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. + * For some useful guards, check out the {@link Guards} class. It can be + * null. If it and the switch point and the exception are all null, this + * represents an unconditional invocation. + * @param switchPoint the optional switch point that can be used to + * invalidate this linkage. + * @param exception the optional exception type that is when thrown by the + * invocation also invalidates it. + * @throws NullPointerException if invocation is null. + */ + public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint, final Class exception) { + this.invocation = Objects.requireNonNull(invocation); + this.guard = guard; + this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint }; + this.exception = exception; + } + + /** + * 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 be + * compatible with the {@code invocation} handle as per + * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. + * For some useful guards, check out the {@link Guards} class. It can be + * null. If it and the exception are both null, and no switch points were + * specified, this represents an unconditional invocation. + * @param switchPoints optional switch points that can be used to + * invalidate this linkage. + * @param exception the optional exception type that is when thrown by the + * invocation also invalidates it. + * @throws NullPointerException if invocation is null. + */ + public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint[] switchPoints, final Class exception) { + this.invocation = Objects.requireNonNull(invocation); + this.guard = guard; + this.switchPoints = switchPoints == null ? null : switchPoints.clone(); + this.exception = exception; + } + + /** + * Returns the invocation method handle. + * + * @return the invocation method handle. It will never be null. + */ + public MethodHandle getInvocation() { + return invocation; + } + + /** + * Returns the guard method handle. + * + * @return the guard method handle. Can be null. + */ + public MethodHandle getGuard() { + return guard; + } + + /** + * Returns the switch points that can be used to invalidate the linkage of + * this invocation handle. + * + * @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 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. + */ + public Class getException() { + return exception; + } + + /** + * 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) { + return false; + } + for (final SwitchPoint sp : switchPoints) { + if (sp.hasBeenInvalidated()) { + return true; + } + } + return false; + } + + /** + * Creates a new guarded invocation with different methods, preserving the switch point. + * + * @param newInvocation the new invocation + * @param newGuard the new guard + * @return a new guarded invocation with the replaced methods and the same switch point as this invocation. + */ + public GuardedInvocation replaceMethods(final MethodHandle newInvocation, final MethodHandle newGuard) { + return new GuardedInvocation(newInvocation, newGuard, switchPoints, exception); + } + + /** + * 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) { + return this; + } + + final SwitchPoint[] newSwitchPoints; + if (switchPoints != null) { + newSwitchPoints = new SwitchPoint[switchPoints.length + 1]; + System.arraycopy(switchPoints, 0, newSwitchPoints, 0, switchPoints.length); + newSwitchPoints[switchPoints.length] = newSwitchPoint; + } else { + newSwitchPoints = new SwitchPoint[] { newSwitchPoint }; + } + + return new GuardedInvocation(invocation, guard, newSwitchPoints, exception); + } + + private GuardedInvocation replaceMethodsOrThis(final MethodHandle newInvocation, final MethodHandle newGuard) { + if (newInvocation == invocation && newGuard == guard) { + return this; + } + return replaceMethods(newInvocation, newGuard); + } + + /** + * Changes the type of the invocation, as if + * {@link MethodHandle#asType(MethodType)} was applied to its invocation + * and its guard, if it has one (with return type changed to boolean, and + * parameter count potentially truncated for the guard). If the invocation + * already is of the required type, returns this object. + * @param newType the new type of the invocation. + * @return a guarded invocation with the new type applied to it. + */ + public GuardedInvocation asType(final MethodType newType) { + return replaceMethodsOrThis(invocation.asType(newType), guard == null ? null : Guards.asType(guard, newType)); + } + + /** + * Changes the type of the invocation, as if + * {@link LinkerServices#asType(MethodHandle, MethodType)} was applied to + * its invocation and its guard, if it has one (with return type changed to + * boolean, and parameter count potentially truncated for the guard). If the + * invocation already is of the required type, returns this object. + * @param linkerServices the linker services to use for the conversion + * @param newType the new type of the invocation. + * @return a guarded invocation with the new type applied to it. + */ + public GuardedInvocation asType(final LinkerServices linkerServices, final MethodType newType) { + return replaceMethodsOrThis(linkerServices.asType(invocation, newType), guard == null ? null : + Guards.asType(linkerServices, guard, newType)); + } + + /** + * Changes the type of the invocation, as if + * {@link 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. + */ + public GuardedInvocation asTypeSafeReturn(final LinkerServices linkerServices, final MethodType newType) { + return replaceMethodsOrThis(linkerServices.asTypeLosslessReturn(invocation, newType), guard == null ? null : + Guards.asType(linkerServices, guard, newType)); + } + + /** + * Changes the type of the invocation, as if + * {@link MethodHandle#asType(MethodType)} was applied to its invocation + * and its guard, if it has one (with return type changed to boolean for + * guard). If the invocation already is of the required type, returns this + * object. + * @param desc a call descriptor whose method type is adapted. + * @return a guarded invocation with the new type applied to it. + */ + public GuardedInvocation asType(final CallSiteDescriptor desc) { + return asType(desc.getMethodType()); + } + + /** + * 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 + */ + public GuardedInvocation filterArguments(final int pos, final MethodHandle... filters) { + return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters), guard == null ? null : + MethodHandles.filterArguments(guard, pos, filters)); + } + + /** + * Makes an invocation that drops arguments in both the invocation and the + * guard (if there is one) 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 + */ + public GuardedInvocation dropArguments(final int pos, final List> valueTypes) { + return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null : + MethodHandles.dropArguments(guard, pos, valueTypes)); + } + + /** + * Makes an invocation that drops arguments in both the invocation and the + * guard (if there is one) 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 + */ + public GuardedInvocation dropArguments(final int pos, final Class... valueTypes) { + return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null : + MethodHandles.dropArguments(guard, pos, valueTypes)); + } + + + /** + * 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) { + return compose(fallback, fallback, fallback); + } + + /** + * 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) { + final MethodHandle guarded = + guard == null ? + invocation : + MethodHandles.guardWithTest( + guard, + invocation, + guardFallback); + + final MethodHandle catchGuarded = + exception == null ? + guarded : + MethodHandles.catchException( + guarded, + exception, + MethodHandles.dropArguments( + catchFallback, + 0, + exception)); + + if (switchPoints == null) { + return catchGuarded; + } + + MethodHandle spGuarded = catchGuarded; + for (final SwitchPoint sp : switchPoints) { + spGuarded = sp.guardWithTest(spGuarded, switchpointFallback); + } + + return spGuarded; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocationTransformer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardedInvocationTransformer.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.dynalink.linker; + +import jdk.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.dynalink.linker; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import java.util.List; +import jdk.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 + * 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. + * + * @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 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) + throws Exception; +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinkerExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingDynamicLinkerExporter.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.dynalink.linker; + +import java.security.Permission; +import java.util.List; +import java.util.ServiceLoader; +import java.util.function.Supplier; +import jdk.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.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/GuardingTypeConverterFactory.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,147 @@ +/* + * 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.dynalink.linker; + +import java.lang.invoke.MethodHandles; +import java.util.function.Supplier; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.beans.BeansLinker; +import jdk.dynalink.linker.support.TypeUtilities; + +/** + * 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 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. + * @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 GuardedInvocation convertToType(Class sourceType, Class targetType, Supplier lookupSupplier) throws Exception; +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkRequest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkRequest.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.dynalink.linker; + +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.DynamicLinker; +import jdk.dynalink.DynamicLinkerFactory; + +/** + * 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 { + /** + * Returns the call site descriptor for the call site being linked. + * + * @return the call site descriptor for the call site being linked. + */ + public CallSiteDescriptor getCallSiteDescriptor(); + + /** + * Returns the arguments for the invocation being linked. The returned array + * 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 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 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, though, and linkers are + * allowed to ignore this property. + * @return true if the call site is considered unstable. + */ + public boolean isCallSiteUnstable(); + + /** + * Returns a request identical to this one with call site descriptor and arguments replaced with the ones specified. + * + * @param callSiteDescriptor the new call site descriptor + * @param arguments the new arguments + * @return a new request identical to this one, except with the call site descriptor and arguments replaced with the + * specified ones. + */ + public LinkRequest replaceArguments(CallSiteDescriptor callSiteDescriptor, Object... arguments); +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkerServices.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/LinkerServices.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,220 @@ +/* + * 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.dynalink.linker; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import jdk.dynalink.DynamicLinker; +import jdk.dynalink.DynamicLinkerFactory; +import jdk.dynalink.linker.ConversionComparator.Comparison; +import jdk.dynalink.linker.support.TypeUtilities; + +/** + * 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 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. + */ + public MethodHandle asType(MethodHandle handle, MethodType fromType); + + /** + * 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. + */ + public default MethodHandle asTypeLosslessReturn(final MethodHandle handle, final MethodType fromType) { + final Class handleReturnType = handle.type().returnType(); + return asType(handle, TypeUtilities.isConvertibleWithoutLoss(handleReturnType, fromType.returnType()) ? + fromType : fromType.changeReturnType(handleReturnType)); + } + + /** + * 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. + */ + 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 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 + * @return true if there can be a conversion, false if there can not. + */ + public boolean canConvert(Class from, Class to); + + /** + * 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 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. + * @param sourceType the source type. + * @param targetType1 one potential target type + * @param targetType2 another potential target type. + * @return one of Comparison constants that establish which – if any + * – of the target types is preferable for the conversion. + */ + public Comparison compareConversion(Class sourceType, Class targetType1, Class targetType2); + + /** + * 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. + */ + public MethodHandle filterInternalObjects(final MethodHandle target); +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodHandleTransformer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodHandleTransformer.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,103 @@ +/* + * 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.dynalink.linker; + +import java.lang.invoke.MethodHandle; +import jdk.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. + * @param target the method handle being transformed. + * @return transformed method handle. + */ + public MethodHandle transform(final MethodHandle target); +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodTypeConversionStrategy.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/MethodTypeConversionStrategy.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2014 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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.dynalink.linker; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; +import jdk.dynalink.DynamicLinkerFactory; + +/** + * 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. + * @param target target method handle + * @param newType new type + * @return target converted to the new type. + */ + public MethodHandle asType(final MethodHandle target, final MethodType newType); +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/TypeBasedGuardingDynamicLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2009-2013 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package jdk.dynalink.linker; + +import jdk.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). 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, + * see {@link CompositeTypeBasedGuardingDynamicLinker}. + */ +public interface TypeBasedGuardingDynamicLinker extends GuardingDynamicLinker { + /** + * Returns true if the linker can link an invocation where the first argument (receiver) is of the specified type. + * + * @param type the type to link + * @return true if the linker can link calls for the receiver type, or false otherwise. + */ + public boolean canLinkType(Class type); +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/package-info.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.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.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.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.dynalink.linker.TypeBasedGuardingDynamicLinker} + * instead of {@link jdk.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.dynalink.linker.GuardingTypeConverterFactory} + * interface to provide the logic for these conversions. + *

+ * @since 1.9 + */ +@jdk.Exported +package jdk.dynalink.linker; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeGuardingDynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeGuardingDynamicLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,139 @@ +/* + * 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.dynalink.linker.support; + +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.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 { + + private final GuardingDynamicLinker[] linkers; + + /** + * Creates a new composite linker. + * + * @param linkers a list of component linkers. + * @throws NullPointerException if {@code linkers} or any of its elements + * are null. + */ + public CompositeGuardingDynamicLinker(final Iterable linkers) { + final List l = new LinkedList<>(); + for(final GuardingDynamicLinker linker: linkers) { + l.add(Objects.requireNonNull(linker)); + } + this.linkers = l.toArray(new GuardingDynamicLinker[l.size()]); + } + + /** + * Delegates the call to its component linkers. The first non-null value + * returned from a component linker is returned. If no component linker + * returns a non-null invocation, null is returned. + * @param linkRequest the object describing the request for linking a + * particular invocation + * @param linkerServices linker services + * @return the first non-null return value from a component linker, or null + * if none of the components returned a non-null. + */ + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) + throws Exception { + for(final GuardingDynamicLinker linker: linkers) { + final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices); + if(invocation != null) { + return invocation; + } + } + return null; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,237 @@ +/* + * 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.dynalink.linker.support; + +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.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 { + // Using a separate static class instance so there's no strong reference from the class value back to the composite + // linker. + private static class ClassToLinker extends ClassValue> { + private static final List NO_LINKER = Collections.emptyList(); + private final TypeBasedGuardingDynamicLinker[] linkers; + private final List[] singletonLinkers; + + @SuppressWarnings({"unchecked", "rawtypes"}) + ClassToLinker(final TypeBasedGuardingDynamicLinker[] linkers) { + this.linkers = linkers; + singletonLinkers = new List[linkers.length]; + for(int i = 0; i < linkers.length; ++i) { + singletonLinkers[i] = Collections.singletonList(linkers[i]); + } + } + + @SuppressWarnings("fallthrough") + @Override + protected List computeValue(final Class clazz) { + List list = NO_LINKER; + for(int i = 0; i < linkers.length; ++i) { + final TypeBasedGuardingDynamicLinker linker = linkers[i]; + if(linker.canLinkType(clazz)) { + switch(list.size()) { + case 0: { + list = singletonLinkers[i]; + break; + } + case 1: { + list = new LinkedList<>(list); + } + default: { + list.add(linker); + } + } + } + } + return list; + } + } + + private final ClassValue> classToLinker; + + /** + * Creates a new composite type-based linker. + * + * @param linkers the component linkers + * @throws NullPointerException if {@code linkers} or any of its elements + * are null. + */ + public CompositeTypeBasedGuardingDynamicLinker(final Iterable linkers) { + final List l = new LinkedList<>(); + for(final TypeBasedGuardingDynamicLinker linker: linkers) { + l.add(Objects.requireNonNull(linker)); + } + this.classToLinker = new ClassToLinker(l.toArray(new TypeBasedGuardingDynamicLinker[l.size()])); + } + + /** + * Returns true if at least one of the composite linkers returns true from + * {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)} for the type. + * @param type the type to link + * @return true true if at least one of the composite linkers returns true + * from {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)}, false + * otherwise. + */ + @Override + public boolean canLinkType(final Class type) { + return !classToLinker.get(type).isEmpty(); + } + + @Override + public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) + throws Exception { + final Object obj = linkRequest.getReceiver(); + if(obj == null) { + return null; + } + for(final TypeBasedGuardingDynamicLinker linker: classToLinker.get(obj.getClass())) { + final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices); + if(invocation != null) { + return invocation; + } + } + return null; + } + + /** + * Optimizes a list of type-based linkers. If a group of adjacent linkers in + * the list all implement {@link TypeBasedGuardingDynamicLinker}, they will + * be replaced with a single instance of + * {@link CompositeTypeBasedGuardingDynamicLinker} that contains them. + * + * @param linkers the list of linkers to optimize + * @return the optimized list + * @throws NullPointerException if {@code linkers} or any of its elements + * are null. + */ + public static List optimize(final Iterable linkers) { + final List llinkers = new LinkedList<>(); + final List tblinkers = new LinkedList<>(); + for(final GuardingDynamicLinker linker: linkers) { + Objects.requireNonNull(linker); + if(linker instanceof TypeBasedGuardingDynamicLinker) { + tblinkers.add((TypeBasedGuardingDynamicLinker)linker); + } else { + addTypeBased(llinkers, tblinkers); + llinkers.add(linker); + } + } + addTypeBased(llinkers, tblinkers); + return llinkers; + } + + private static void addTypeBased(final List llinkers, + final List tblinkers) { + switch(tblinkers.size()) { + case 0: { + break; + } + case 1: { + llinkers.addAll(tblinkers); + tblinkers.clear(); + break; + } + default: { + llinkers.add(new CompositeTypeBasedGuardingDynamicLinker(tblinkers)); + tblinkers.clear(); + break; + } + } + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/DefaultInternalObjectFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/DefaultInternalObjectFilter.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.dynalink.linker.support; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import jdk.dynalink.DynamicLinkerFactory; +import jdk.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Guards.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Guards.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.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.dynalink.DynamicLinker; +import jdk.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.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/Lookup.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.dynalink.linker.support; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * A wrapper around {@link java.lang.invoke.MethodHandles.Lookup} that masks + * checked exceptions. It is useful in those cases when you're looking up + * methods within your own codebase (therefore it is an error if they are not + * present). + */ +public final class Lookup { + private final MethodHandles.Lookup lookup; + + /** + * Creates a new instance, bound to an instance of + * {@link java.lang.invoke.MethodHandles.Lookup}. + * + * @param lookup the {@link java.lang.invoke.MethodHandles.Lookup} it delegates to. + */ + public Lookup(final MethodHandles.Lookup lookup) { + this.lookup = lookup; + } + + /** + * A canonical Lookup object that wraps {@link MethodHandles#publicLookup()}. + */ + public static final Lookup PUBLIC = new Lookup(MethodHandles.publicLookup()); + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, + * converting any encountered {@link IllegalAccessException} into an + * {@link IllegalAccessError}. + * + * @param m the method to unreflect + * @return the unreflected method handle. + * @throws IllegalAccessError if the method is inaccessible. + */ + public MethodHandle unreflect(final Method m) { + return unreflect(lookup, m); + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, + * converting any encountered {@link IllegalAccessException} into an + * {@link IllegalAccessError}. + * + * @param lookup the lookup used to unreflect + * @param m the method to unreflect + * @return the unreflected method handle. + * @throws IllegalAccessError if the method is inaccessible. + */ + public static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) { + try { + return lookup.unreflect(m); + } catch(final IllegalAccessException e) { + final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect method " + m); + ee.initCause(e); + throw ee; + } + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter(Field)}, + * converting any encountered {@link IllegalAccessException} into an {@link IllegalAccessError}. + * + * @param f the field for which a getter is unreflected + * @return the unreflected field getter handle. + * @throws IllegalAccessError if the getter is inaccessible. + */ + public MethodHandle unreflectGetter(final Field f) { + try { + return lookup.unreflectGetter(f); + } catch(final IllegalAccessException e) { + final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect getter for field " + f); + ee.initCause(e); + throw ee; + } + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findGetter(Class, String, Class)}, + * converting any encountered {@link IllegalAccessException} into an + * {@link IllegalAccessError} and {@link NoSuchFieldException} into a + * {@link NoSuchFieldError}. + * + * @param refc the class declaring the field + * @param name the name of the field + * @param type the type of the field + * @return the unreflected field getter handle. + * @throws IllegalAccessError if the field is inaccessible. + * @throws NoSuchFieldError if the field does not exist. + */ + public MethodHandle findGetter(final Classrefc, final String name, final Class type) { + try { + return lookup.findGetter(refc, name, type); + } catch(final IllegalAccessException e) { + final IllegalAccessError ee = new IllegalAccessError("Failed to access getter for field " + refc.getName() + + "." + name + " of type " + type.getName()); + ee.initCause(e); + throw ee; + } catch(final NoSuchFieldException e) { + final NoSuchFieldError ee = new NoSuchFieldError("Failed to find getter for field " + refc.getName() + + "." + name + " of type " + type.getName()); + ee.initCause(e); + throw ee; + } + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectSetter(Field)}, + * converting any encountered {@link IllegalAccessException} into an + * {@link IllegalAccessError}. + * + * @param f the field for which a setter is unreflected + * @return the unreflected field setter handle. + * @throws IllegalAccessError if the field is inaccessible. + * @throws NoSuchFieldError if the field does not exist. + */ + public MethodHandle unreflectSetter(final Field f) { + try { + return lookup.unreflectSetter(f); + } catch(final IllegalAccessException e) { + final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect setter for field " + f); + ee.initCause(e); + throw ee; + } + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, + * converting any encountered {@link IllegalAccessException} into an + * {@link IllegalAccessError}. + * + * @param c the constructor to unreflect + * @return the unreflected constructor handle. + * @throws IllegalAccessError if the constructor is inaccessible. + */ + public MethodHandle unreflectConstructor(final Constructor c) { + return unreflectConstructor(lookup, c); + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, + * converting any encountered {@link IllegalAccessException} into an + * {@link IllegalAccessError}. + * + * @param lookup the lookup used to unreflect + * @param c the constructor to unreflect + * @return the unreflected constructor handle. + * @throws IllegalAccessError if the constructor is inaccessible. + */ + public static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor c) { + try { + return lookup.unreflectConstructor(c); + } catch(final IllegalAccessException e) { + final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect constructor " + c); + ee.initCause(e); + throw ee; + } + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findSpecial(Class, String, MethodType, Class)} + * on the underlying lookup. Converts any encountered + * {@link IllegalAccessException} into an {@link IllegalAccessError} and + * {@link NoSuchMethodException} into a {@link NoSuchMethodError}. + * + * @param declaringClass class declaring the method + * @param name the name of the method + * @param type the type of the method + * @return a method handle for the method + * @throws IllegalAccessError if the method is inaccessible. + * @throws NoSuchMethodError if the method does not exist. + */ + public MethodHandle findSpecial(final Class declaringClass, final String name, final MethodType type) { + try { + return lookup.findSpecial(declaringClass, name, type, declaringClass); + } catch(final IllegalAccessException e) { + final IllegalAccessError ee = new IllegalAccessError("Failed to access special method " + methodDescription( + declaringClass, name, type)); + ee.initCause(e); + throw ee; + } catch(final NoSuchMethodException e) { + final NoSuchMethodError ee = new NoSuchMethodError("Failed to find special method " + methodDescription( + declaringClass, name, type)); + ee.initCause(e); + throw ee; + } + } + + private static String methodDescription(final Class declaringClass, final String name, final MethodType type) { + return declaringClass.getName() + "#" + name + type; + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findStatic(Class, String, MethodType)} + * on the underlying lookup. Converts any encountered + * {@link IllegalAccessException} into an {@link IllegalAccessError} and + * {@link NoSuchMethodException} into a {@link NoSuchMethodError}. + * + * @param declaringClass class declaring the method + * @param name the name of the method + * @param type the type of the method + * @return a method handle for the method + * @throws IllegalAccessError if the method is inaccessible. + * @throws NoSuchMethodError if the method does not exist. + */ + public MethodHandle findStatic(final Class declaringClass, final String name, final MethodType type) { + try { + return lookup.findStatic(declaringClass, name, type); + } catch(final IllegalAccessException e) { + final IllegalAccessError ee = new IllegalAccessError("Failed to access static method " + methodDescription( + declaringClass, name, type)); + ee.initCause(e); + throw ee; + } catch(final NoSuchMethodException e) { + final NoSuchMethodError ee = new NoSuchMethodError("Failed to find static method " + methodDescription( + declaringClass, name, type)); + ee.initCause(e); + throw ee; + } + } + + /** + * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findVirtual(Class, String, MethodType)} + * on the underlying lookup. Converts any encountered + * {@link IllegalAccessException} into an {@link IllegalAccessError} and + * {@link NoSuchMethodException} into a {@link NoSuchMethodError}. + * + * @param declaringClass class declaring the method + * @param name the name of the method + * @param type the type of the method + * @return a method handle for the method + * @throws IllegalAccessError if the method is inaccessible. + * @throws NoSuchMethodError if the method does not exist. + */ + public MethodHandle findVirtual(final Class declaringClass, final String name, final MethodType type) { + try { + return lookup.findVirtual(declaringClass, name, type); + } catch(final IllegalAccessException e) { + final IllegalAccessError ee = new IllegalAccessError("Failed to access virtual method " + methodDescription( + declaringClass, name, type)); + ee.initCause(e); + throw ee; + } catch(final NoSuchMethodException e) { + final NoSuchMethodError ee = new NoSuchMethodError("Failed to find virtual method " + methodDescription( + declaringClass, name, type)); + ee.initCause(e); + throw ee; + } + } + + /** + * Given a lookup, finds using {@link #findSpecial(Class, String, MethodType)} + * a method on that lookup's class. Useful in classes' code for convenient + * linking to their own privates. + * @param lookup the lookup for the class + * @param name the name of the method + * @param rtype the return type of the method + * @param ptypes the parameter types of the method + * @return the method handle for the method + */ + public static MethodHandle findOwnSpecial(final MethodHandles.Lookup lookup, final String name, final Class rtype, final Class... ptypes) { + return new Lookup(lookup).findOwnSpecial(name, rtype, ptypes); + } + + + /** + * Finds using {@link #findSpecial(Class, String, MethodType)} a method on + * that lookup's class. Useful in classes' code for convenient linking to + * their own privates. It's also more convenient than {@code findSpecial} + * in that you can just list the parameter types, and don't have to specify + * lookup class. + * @param name the name of the method + * @param rtype the return type of the method + * @param ptypes the parameter types of the method + * @return the method handle for the method + */ + public MethodHandle findOwnSpecial(final String name, final Class rtype, final Class... ptypes) { + return findSpecial(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes)); + } + + /** + * Given a lookup, finds using {@link #findStatic(Class, String, MethodType)} + * a method on that lookup's class. Useful in classes' code for convenient + * linking to their own privates. It's easier to use than {@code findStatic} + * in that you can just list the parameter types, and don't have to specify + * lookup class. + * @param lookup the lookup for the class + * @param name the name of the method + * @param rtype the return type of the method + * @param ptypes the parameter types of the method + * @return the method handle for the method + */ + public static MethodHandle findOwnStatic(final MethodHandles.Lookup lookup, final String name, final Class rtype, final Class... ptypes) { + return new Lookup(lookup).findOwnStatic(name, rtype, ptypes); + } + + /** + * Finds using {@link #findStatic(Class, String, MethodType)} a method on + * that lookup's class. Useful in classes' code for convenient linking to + * their own privates. It's easier to use than {@code findStatic} + * in that you can just list the parameter types, and don't have to specify + * lookup class. + * @param name the name of the method + * @param rtype the return type of the method + * @param ptypes the parameter types of the method + * @return the method handle for the method + */ + public MethodHandle findOwnStatic(final String name, final Class rtype, final Class... ptypes) { + return findStatic(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes)); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/SimpleLinkRequest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/SimpleLinkRequest.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.dynalink.linker.support; + +import java.util.Objects; +import jdk.dynalink.CallSiteDescriptor; +import jdk.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/TypeUtilities.java Wed Dec 02 09:37:26 2015 -0800 @@ -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.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.dynalink.DynamicLinkerFactory; +import jdk.dynalink.linker.MethodTypeConversionStrategy; + +/** + * Various static utility methods for working with Java types. + */ +public final class TypeUtilities { + static final Class OBJECT_CLASS = Object.class; + + private TypeUtilities() { + } + + private static final Map, Class> WRAPPER_TYPES = createWrapperTypes(); + private static final Map, Class> PRIMITIVE_TYPES = invertMap(WRAPPER_TYPES); + private static final Map> PRIMITIVE_TYPES_BY_NAME = createClassNameMapping(WRAPPER_TYPES.keySet()); + + private static Map, Class> createWrapperTypes() { + final Map, Class> wrapperTypes = new IdentityHashMap<>(8); + wrapperTypes.put(Void.TYPE, Void.class); + wrapperTypes.put(Boolean.TYPE, Boolean.class); + wrapperTypes.put(Byte.TYPE, Byte.class); + wrapperTypes.put(Character.TYPE, Character.class); + wrapperTypes.put(Short.TYPE, Short.class); + wrapperTypes.put(Integer.TYPE, Integer.class); + wrapperTypes.put(Long.TYPE, Long.class); + wrapperTypes.put(Float.TYPE, Float.class); + wrapperTypes.put(Double.TYPE, Double.class); + return Collections.unmodifiableMap(wrapperTypes); + } + + private static Map> createClassNameMapping(final Collection> classes) { + final Map> map = new HashMap<>(); + for(final Class clazz: classes) { + map.put(clazz.getName(), clazz); + } + return map; + } + + private static Map invertMap(final Map map) { + final Map inverted = new IdentityHashMap<>(map.size()); + for(final Map.Entry entry: map.entrySet()) { + inverted.put(entry.getValue(), entry.getKey()); + } + return Collections.unmodifiableMap(inverted); + } + + /** + * Determines whether one type can be converted to another type using a method invocation conversion, as per JLS 5.3 + * "Method Invocation Conversion". This is basically all conversions allowed by subtyping (see + * {@link #isSubtype(Class, Class)}) as well as boxing conversion (JLS 5.1.7) optionally followed by widening + * reference conversion and unboxing conversion (JLS 5.1.8) optionally followed by widening primitive conversion. + * + * @param sourceType the type being converted from (call site type for parameter types, method type for return types) + * @param targetType the parameter type being converted to (method type for parameter types, call site type for return types) + * @return true if source type is method invocation convertible to target type. + */ + public static boolean isMethodInvocationConvertible(final Class sourceType, final Class targetType) { + if(targetType.isAssignableFrom(sourceType)) { + return true; + } + if(sourceType.isPrimitive()) { + if(targetType.isPrimitive()) { + return isProperPrimitiveSubtype(sourceType, targetType); + } + return isBoxingAndWideningReferenceConversion(sourceType, targetType); + } + if(targetType.isPrimitive()) { + final Class unboxedCallSiteType = getPrimitiveType(sourceType); + return unboxedCallSiteType != null + && (unboxedCallSiteType == targetType || isProperPrimitiveSubtype(unboxedCallSiteType, targetType)); + } + return false; + } + + private static boolean isBoxingAndWideningReferenceConversion(final Class sourceType, final Class targetType) { + final Class wrapperType = getWrapperType(sourceType); + assert wrapperType != null : sourceType.getName(); + return targetType.isAssignableFrom(wrapperType); + } + + /** + * Determines whether a type can be converted to another without losing any + * precision. As a special case, void is considered convertible only to void + * and {@link Object} (either as {@code null} or as a custom value set in + * {@link DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy)}). + * Somewhat unintuitively, we consider anything to be convertible to void + * even though converting to void causes the ultimate loss of data. On the + * other hand, conversion to void essentially means that the value is of no + * interest and should be discarded, thus there's no expectation of + * preserving any precision. + * + * @param sourceType the source type + * @param targetType the target type + * @return true if lossless conversion is possible + */ + public static boolean isConvertibleWithoutLoss(final Class sourceType, final Class targetType) { + if(targetType.isAssignableFrom(sourceType) || targetType == void.class) { + return true; + } + if(sourceType.isPrimitive()) { + if(sourceType == void.class) { + // Void should be losslessly representable by Object, either as null or as a custom value that + // can be set with DynamicLinkerFactory.setAutoConversionStrategy. + return targetType == Object.class; + } + if(targetType.isPrimitive()) { + return isProperPrimitiveLosslessSubtype(sourceType, targetType); + } + return isBoxingAndWideningReferenceConversion(sourceType, targetType); + } + // Can't convert from any non-primitive type to any primitive type without data loss because of null. + // Also, can't convert non-assignable reference types. + return false; + } + + /** + * Determines whether one type is a subtype of another type, as per JLS + * 4.10 "Subtyping". Note: this is not strict or proper subtype, therefore + * true is also returned for identical types; to be completely precise, it + * allows identity conversion (JLS 5.1.1), widening primitive conversion + * (JLS 5.1.2) and widening reference conversion (JLS 5.1.5). + * + * @param subType the supposed subtype + * @param superType the supposed supertype of the subtype + * @return true if subType can be converted by identity conversion, widening primitive conversion, or widening + * reference conversion to superType. + */ + public static boolean isSubtype(final Class subType, final Class superType) { + // Covers both JLS 4.10.2 "Subtyping among Class and Interface Types" + // and JLS 4.10.3 "Subtyping among Array Types", as well as primitive + // type identity. + if(superType.isAssignableFrom(subType)) { + return true; + } + // JLS 4.10.1 "Subtyping among Primitive Types". Note we don't test for + // identity, as identical types were taken care of in the + // isAssignableFrom test. As per 4.10.1, the supertype relation is as + // follows: + // double > float + // float > long + // long > int + // int > short + // int > char + // short > byte + if(superType.isPrimitive() && subType.isPrimitive()) { + return isProperPrimitiveSubtype(subType, superType); + } + return false; + } + + /** + * Returns true if a supposed primitive subtype is a proper subtype ( meaning, subtype and not identical) of the + * supposed primitive supertype + * + * @param subType the supposed subtype + * @param superType the supposed supertype + * @return true if subType is a proper (not identical to) primitive subtype of the superType + */ + private static boolean isProperPrimitiveSubtype(final Class subType, final Class superType) { + if(superType == boolean.class || subType == boolean.class) { + return false; + } + if(subType == byte.class) { + return superType != char.class; + } + if(subType == char.class) { + return superType != short.class && superType != byte.class; + } + if(subType == short.class) { + return superType != char.class && superType != byte.class; + } + if(subType == int.class) { + return superType == long.class || superType == float.class || superType == double.class; + } + if(subType == long.class) { + return superType == float.class || superType == double.class; + } + if(subType == float.class) { + return superType == double.class; + } + return false; + } + + /** + * Similar to {@link #isProperPrimitiveSubtype(Class, Class)}, except it disallows conversions from int and long to + * float, and from long to double, as those can lose precision. It also disallows conversion from and to char and + * anything else (similar to boolean) as char is not meant to be an arithmetic type. + * @param subType the supposed subtype + * @param superType the supposed supertype + * @return true if subType is a proper (not identical to) primitive subtype of the superType that can be represented + * by the supertype without no precision loss. + */ + private static boolean isProperPrimitiveLosslessSubtype(final Class subType, final Class superType) { + if(superType == boolean.class || subType == boolean.class) { + return false; + } + if(superType == char.class || subType == char.class) { + return false; + } + if(subType == byte.class) { + return true; + } + if(subType == short.class) { + return superType != byte.class; + } + if(subType == int.class) { + return superType == long.class || superType == double.class; + } + if(subType == float.class) { + return superType == double.class; + } + return false; + } + + /** + * Given a name of a primitive type returns the class representing it. I.e. + * when invoked with "int", returns {@link Integer#TYPE}. + * @param name the name of the primitive type + * @return the class representing the primitive type, or null if the name + * does not correspond to a primitive type. + */ + public static Class getPrimitiveTypeByName(final String name) { + return PRIMITIVE_TYPES_BY_NAME.get(name); + } + + /** + * When passed a class representing a wrapper for a primitive type, returns + * the class representing the corresponding primitive type. I.e. calling it + * with {@code Integer.class} will return {@code Integer.TYPE}. If passed a + * class that is not a wrapper for primitive type, returns null. + * @param wrapperType the class object representing a wrapper for a + * primitive type. + * @return the class object representing the primitive type, or null if the + * passed class is not a primitive wrapper. + */ + public static Class getPrimitiveType(final Class wrapperType) { + return PRIMITIVE_TYPES.get(wrapperType); + } + + /** + * When passed a class representing a primitive type, returns the class representing the corresponding + * wrapper type. I.e. calling it with {@code int.class} will return {@code Integer.class}. If passed a class + * that is not a primitive type, returns null. + * @param primitiveType the class object representing a primitive type + * @return the class object representing the wrapper type, or null if the passed class is not a primitive. + */ + public static Class getWrapperType(final Class primitiveType) { + return WRAPPER_TYPES.get(primitiveType); + } + + /** + * Returns true if the passed type is a wrapper for a primitive type. + * @param type the examined type + * @return true if the passed type is a wrapper for a primitive type. + */ + public static boolean isWrapperType(final Class type) { + return PRIMITIVE_TYPES.containsKey(type); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/linker/support/package-info.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2015 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + *

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

+ * @since 1.9 + */ +@jdk.Exported +package jdk.dynalink.linker.support; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/package-info.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2009-2013 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + *

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

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

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

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

Example

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

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

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

Dynalink and bytecode creation

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

Available operations

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

Composite operations

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

Language-specific linkers

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

Dynalink and Java objects

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

Cross-language interoperability

+ * A {@code DynamicLinkerFactory} can be configured with a + * {@link jdk.dynalink.DynamicLinkerFactory#setClassLoader(ClassLoader) class + * loader}. It will try to instantiate all + * {@link jdk.dynalink.linker.GuardingDynamicLinkerExporter} classes visible to + * that class loader and compose the linkers they provide into the + * {@code DynamicLinker} it creates. This allows for interoperability between + * languages: if you have two language runtimes A and B deployed in your JVM and + * they export their linkers through the above mechanism, language runtime A + * will have a language-specific linker instance from B and vice versa inside + * their {@code DynamicLinker} objects. This means that if an object from + * language runtime B gets passed to code from language runtime A, the linker + * from B will get a chance to link the call site in A when it encounters the + * object from B. + */ +@jdk.Exported +package jdk.dynalink; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/support/AbstractRelinkableCallSite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/support/AbstractRelinkableCallSite.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,126 @@ +/* + * 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.dynalink.support; + +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MutableCallSite; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.RelinkableCallSite; +import jdk.dynalink.linker.GuardedInvocation; + +/** + * A basic implementation of the {@link RelinkableCallSite} as a + * {@link MutableCallSite}. It carries a {@link CallSiteDescriptor} passed in + * the constructor and provides the correct implementation of the + * {@link #initialize(MethodHandle)} method. Subclasses must provide + * {@link #relink(GuardedInvocation, MethodHandle)} and + * {@link #resetAndRelink(GuardedInvocation, MethodHandle)} + * methods. + */ +public abstract class AbstractRelinkableCallSite extends MutableCallSite implements RelinkableCallSite { + private final CallSiteDescriptor descriptor; + + /** + * Creates a new abstract relinkable call site. + * @param descriptor the descriptor for this call site that will be returned + * from {@link #getDescriptor()}. The call site's {@link CallSite#type()} + * will be equal to descriptor's {@link CallSiteDescriptor#getMethodType()}. + * @throws NullPointerException if {@code descriptor} is null. + */ + protected AbstractRelinkableCallSite(final CallSiteDescriptor descriptor) { + super(descriptor.getMethodType()); + this.descriptor = descriptor; + } + + @Override + public CallSiteDescriptor getDescriptor() { + return descriptor; + } + + @Override + public void initialize(final MethodHandle relinkAndInvoke) { + setTarget(relinkAndInvoke); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/support/ChainedCallSite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/support/ChainedCallSite.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2009-2013 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package jdk.dynalink.support; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.support.Lookup; + +/** + * A relinkable call site that implements a polymorphic inline caching strategy. + * It remembers up to 8 {@link GuardedInvocation}s it was linked with, and on + * each relink request builds a cascading chain of method handles of one + * invocation falling back to the next one. The number of remembered invocations + * can be customized by overriding {@link #getMaxChainLength()} in a subclass. + * When this call site is relinked with a new invocation and the length of the + * chain is already at the maximum, it will throw away the oldest invocation. + * Invocations with invalidated switch points and ones for which their + * invalidating exception triggered are removed eagerly from the chain. The + * invocations are never reordered; the most recently linked method handle is + * always at the start of the chain and the least recently linked at its end. + * The call site can be safely relinked on more than one thread concurrently. + * Race conditions in linking are resolved by throwing away the + * {@link GuardedInvocation} produced on the losing thread without incorporating + * it into the chain, so it can lead to repeated linking for the same arguments. + */ +public class ChainedCallSite extends AbstractRelinkableCallSite { + private static final MethodHandle PRUNE_CATCHES; + private static final MethodHandle PRUNE_SWITCHPOINTS; + static { + final MethodHandle PRUNE = Lookup.findOwnSpecial(MethodHandles.lookup(), "prune", MethodHandle.class, + MethodHandle.class, boolean.class); + PRUNE_CATCHES = MethodHandles.insertArguments(PRUNE, 2, true); + PRUNE_SWITCHPOINTS = MethodHandles.insertArguments(PRUNE, 2, false); + } + + /** + * Contains the invocations currently linked into this call site's target. They are used when we are + * relinking to rebuild the guardWithTest chain. Valid values for this field are: {@code null} if there's + * no linked invocations, or an instance of {@link GuardedInvocation} if there is exactly one previous + * invocation, or an instance of {@code GuardedInvocation[]} if there is more than one previous + * invocation. + */ + private Object invocations; + + /** + * Creates a new chained call site. + * @param descriptor the descriptor for the call site. + */ + public ChainedCallSite(final CallSiteDescriptor descriptor) { + super(descriptor); + } + + /** + * The maximum number of method handles in the chain. Defaults to 8. You can + * override it in a subclass if you need to change the value. + * @return the maximum number of method handles in the chain. The return + * value is checked, and if your override returns a value less than 1, a + * {@link RuntimeException} will be thrown. + */ + protected int getMaxChainLength() { + return 8; + } + + @Override + public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { + relinkInternal(guardedInvocation, relinkAndInvoke, false, false); + } + + @Override + public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { + relinkInternal(guardedInvocation, relinkAndInvoke, true, false); + } + + private MethodHandle relinkInternal(final GuardedInvocation invocation, final MethodHandle relink, final boolean reset, final boolean removeCatches) { + final Object currentInvocations = invocations; + final LinkedList newInvocations; + if (currentInvocations == null || reset) { + newInvocations = new LinkedList<>(); + } else if (currentInvocations instanceof GuardedInvocation) { + newInvocations = new LinkedList<>(); + newInvocations.add((GuardedInvocation)currentInvocations); + } else if (currentInvocations instanceof GuardedInvocation[]) { + newInvocations = new LinkedList<>(Arrays.asList(((GuardedInvocation[])currentInvocations))); + } else { + throw new AssertionError(); + } + + // First, prune the chain of invalidated switchpoints, we always do this + // We also remove any catches if the remove catches flag is set + for(final Iterator it = newInvocations.iterator(); it.hasNext();) { + final GuardedInvocation inv = it.next(); + if(inv.hasBeenInvalidated() || (removeCatches && inv.getException() != null)) { + it.remove(); + } + } + + // prune() is allowed to invoke this method with invocation == null meaning we're just pruning the chain and not + // adding any new invocations to it. + if(invocation != null) { + // Remove oldest entry if we're at max length + if(newInvocations.size() == checkMaxChainLength(getMaxChainLength())) { + newInvocations.removeFirst(); + } + newInvocations.addLast(invocation); + } + + // prune-and-invoke is used as the fallback for invalidated switchpoints. If a switchpoint gets invalidated, we + // rebuild the chain and get rid of all invalidated switchpoints instead of letting them linger. + final MethodHandle pruneAndInvokeSwitchPoints = makePruneAndInvokeMethod(relink, PRUNE_SWITCHPOINTS); + final MethodHandle pruneAndInvokeCatches = makePruneAndInvokeMethod(relink, PRUNE_CATCHES); + + // Fold the new chain + MethodHandle target = relink; + for(final GuardedInvocation inv: newInvocations) { + target = inv.compose(target, pruneAndInvokeSwitchPoints, pruneAndInvokeCatches); + } + + switch (newInvocations.size()) { + case 0: + invocations = null; + break; + case 1: + invocations = newInvocations.getFirst(); + break; + default: + invocations = newInvocations.toArray(new GuardedInvocation[newInvocations.size()]); + } + setTarget(target); + return target; + } + + private static int checkMaxChainLength(final int maxChainLength) { + if (maxChainLength > 0) { + return maxChainLength; + } + throw new RuntimeException("getMaxChainLength() returned a non-positive value"); + + } + /** + * Creates a method that rebuilds our call chain, pruning it of any invalidated switchpoints, and then invokes that + * chain. + * @param relinkAndInvoke the ultimate fallback for the chain passed from the dynamic linker. + * @return a method handle for prune-and-invoke + */ + private MethodHandle makePruneAndInvokeMethod(final MethodHandle relinkAndInvoke, final MethodHandle prune) { + // Bind prune to (this, relink) + final MethodHandle boundPrune = MethodHandles.insertArguments(prune, 0, this, relinkAndInvoke); + // Make it ignore all incoming arguments + final MethodHandle ignoreArgsPrune = MethodHandles.dropArguments(boundPrune, 0, type().parameterList()); + // Invoke prune, then invoke the call site target with original arguments + return MethodHandles.foldArguments(MethodHandles.exactInvoker(type()), ignoreArgsPrune); + } + + @SuppressWarnings("unused") + private MethodHandle prune(final MethodHandle relink, final boolean catches) { + return relinkInternal(null, relink, false, catches); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/support/SimpleRelinkableCallSite.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2009-2013 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package jdk.dynalink.support; + +import java.lang.invoke.MethodHandle; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.DynamicLinker; +import jdk.dynalink.linker.GuardedInvocation; + +/** + * A relinkable call site that implements monomorphic inline caching strategy, + * only being linked to a single {@link GuardedInvocation}. If that invocation + * is invalidated, it will throw it away and ask its associated + * {@link DynamicLinker} to relink it. + */ +public class SimpleRelinkableCallSite extends AbstractRelinkableCallSite { + /** + * Creates a new call site with monomorphic inline caching strategy. + * @param descriptor the descriptor for this call site + */ + public SimpleRelinkableCallSite(final CallSiteDescriptor descriptor) { + super(descriptor); + } + + @Override + public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { + setTarget(guardedInvocation.compose(relinkAndInvoke)); + } + + @Override + public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { + relink(guardedInvocation, relinkAndInvoke); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/support/messages.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/support/messages.properties Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,86 @@ +# Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +# This file is available under and governed by the GNU General Public +# License version 2 only, as published by the Free Software Foundation. +# However, the following notice accompanied the original version of this +# file, and Oracle licenses the original version of this file under the BSD +# license: +# +# Copyright 2009-2013 Attila Szegedi +# +# Licensed under both the Apache License, Version 2.0 (the "Apache License") +# and the BSD License (the "BSD License"), with licensee being free to +# choose either of the two at their discretion. +# +# You may not use this file except in compliance with either the Apache +# License or the BSD License. +# +# If you choose to use this file in compliance with the Apache License, the +# following notice applies to you: +# +# You may obtain a copy of the Apache License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. See the License for the specific language governing +# permissions and limitations under the License. +# +# If you choose to use this file in compliance with the BSD License, the +# following notice applies to you: +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the copyright holder nor the names of +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +isInstanceGuardAlwaysTrue=isInstance guard for {0} in position {1} in method type {2} at {3} will always return true +isInstanceGuardAlwaysFalse=isInstance guard for {0} in position {1} in method type {2} at {3} will always return false + +isOfClassGuardAlwaysTrue=isOfClass guard for {0} in position {1} in method type {2} at {3} will always return true +isOfClassGuardAlwaysFalse=isOfClass guard for {0} in position {1} in method type {2} at {3} will always return false + +isArrayGuardAlwaysTrue=isArray guard in position {0} in method type {1} at {2} will always return true +isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} at {2} will always return false diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/support/package-info.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/src/jdk.dynalink/share/classes/jdk/dynalink/support/package-info.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file, and Oracle licenses the original version of this file under the BSD + * license: + */ +/* + Copyright 2009-2013 Attila Szegedi + + Licensed under both the Apache License, Version 2.0 (the "Apache License") + and the BSD License (the "BSD License"), with licensee being free to + choose either of the two at their discretion. + + You may not use this file except in compliance with either the Apache + License or the BSD License. + + If you choose to use this file in compliance with the Apache License, the + following notice applies to you: + + You may obtain a copy of the Apache License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + + If you choose to use this file in compliance with the BSD License, the + following notice applies to you: + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/** + *

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

+ * @since 1.9 + */ +@jdk.Exported +package jdk.dynalink.support; diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,287 +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.MethodHandles; -import java.lang.invoke.MethodHandles.Lookup; -import java.lang.invoke.MethodType; -import java.util.Objects; - -/** - * 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 class CallSiteDescriptor { - private final MethodHandles.Lookup lookup; - private final Operation operation; - private final MethodType methodType; - - /** - * The name of a runtime permission to invoke the {@link #getLookup()} - * method. - */ - public static final String GET_LOOKUP_PERMISSION_NAME = "dynalink.getLookup"; - - private static final RuntimePermission GET_LOOKUP_PERMISSION = new RuntimePermission(GET_LOOKUP_PERMISSION_NAME); - - /** - * 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 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 operation at the call site. - * @return the operation at the call site. - */ - 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 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 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()}. - */ - 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. 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. - */ - 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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ClassMap.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/ClassMap.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,183 +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.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CompositeOperation.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/CompositeOperation.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,297 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2015 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package jdk.internal.dynalink; - -import java.util.Arrays; -import java.util.Objects; - -/** - * Describes an operation that is composed of at least two other operations. The - * component operations are treated as alternatives to each other in order of - * preference. The semantics of the composite operation is "first successful". - * That is, a composite of {@code GET_PROPERTY|GET_ELEMENT:color} should be - * interpreted as get the property named "color" on the object, but if the - * property does not exist, then get the collection element named "color" - * instead. - *

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

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

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

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

- * Not all compositions make sense. Typically, any combination in any order of - * standard getter operations {@code GET_PROPERTY}, {@code GET_ELEMENT}, and - * {@code GET_METHOD} make sense, as do combinations of {@code SET_PROPERTY} and - * {@code SET_ELEMENT}; other standard operations should not be combined. The - * constructor will allow any combination of operations, though. - */ -public final 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 instanceof CompositeOperation) { - return Arrays.equals(operations, ((CompositeOperation)obj).operations); - } - return false; - } - - /** - * 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 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,349 +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.lang.invoke.MethodType; -import java.lang.invoke.MutableCallSite; -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.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. A dynamic linker is a main - * objects when using Dynalink, it coordinates linking of call sites with - * linkers of available language runtimes that are represented by - * {@link GuardingDynamicLinker} objects (you only need to deal with these if - * you are yourself implementing a language runtime with its own object model - * and/or type conversions). To use Dynalink, you have to create one or more - * dynamic linkers using a {@link DynamicLinkerFactory}. Subsequently, you need - * to invoke its {@link #link(RelinkableCallSite)} method from - * {@code invokedynamic} bootstrap methods to let it manage all the call sites - * they create. Usual usage would be to create at least one class per language - * runtime to contain one linker instance as: - *

- *
- * class MyLanguageRuntime {
- *     private static final GuardingDynamicLinker myLanguageLinker = new MyLanguageLinker();
- *     private static final DynamicLinker dynamicLinker = createDynamicLinker();
- *
- *     private static DynamicLinker createDynamicLinker() {
- *         final DynamicLinkerFactory factory = new DynamicLinkerFactory();
- *         factory.setPrioritizedLinker(myLanguageLinker);
- *         return factory.createLinker();
- *     }
- *
- *     public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) {
- *         return dynamicLinker.link(
- *             new SimpleRelinkableCallSite(
- *                 new CallSiteDescriptor(lookup, parseOperation(name), type)));
- *     }
- *
- *     private static Operation parseOperation(String name) {
- *         ...
- *     }
- * }
- * 
- * 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 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 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 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.
  • - * - *
- */ -public final class DynamicLinker { - private static final String CLASS_NAME = DynamicLinker.class.getName(); - private static final String RELINK_METHOD_NAME = "relink"; - - private static final String INITIAL_LINK_CLASS_NAME = "java.lang.invoke.MethodHandleNatives"; - private static final String INITIAL_LINK_METHOD_NAME = "linkCallSite"; - private static final String INVOKE_PACKAGE_PREFIX = "java.lang.invoke."; - - private final LinkerServices linkerServices; - private final GuardedInvocationTransformer prelinkTransformer; - private final boolean syncOnRelink; - private final int unstableRelinkThreshold; - - /** - * Creates a new dynamic linker. - * - * @param linkerServices the linkerServices used by the linker, created by the factory. - * @param 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 GuardedInvocationTransformer prelinkTransformer, - final boolean syncOnRelink, final int unstableRelinkThreshold) { - if(unstableRelinkThreshold < 0) { - throw new IllegalArgumentException("unstableRelinkThreshold < 0"); - } - this.linkerServices = linkerServices; - this.prelinkTransformer = prelinkTransformer; - this.syncOnRelink = syncOnRelink; - this.unstableRelinkThreshold = unstableRelinkThreshold; - } - - /** - * Links an invokedynamic call site. It will install a method handle into - * the call site that invokes the relinking mechanism of this linker. Next - * time the call site is invoked, it will be linked for the actual arguments - * it was invoked with. - * - * @param the particular subclass of {@link RelinkableCallSite} for - * which to create a link. - * @param callSite the call site to link. - * - * @return the callSite, for easy call chaining. - */ - public T link(final T callSite) { - callSite.initialize(createRelinkAndInvokeMethod(callSite, 0)); - return callSite; - } - - /** - * Returns the object representing the 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. - */ - public LinkerServices getLinkerServices() { - return linkerServices; - } - - private static final MethodHandle RELINK = Lookup.findOwnSpecial(MethodHandles.lookup(), RELINK_METHOD_NAME, - MethodHandle.class, RelinkableCallSite.class, int.class, Object[].class); - - private MethodHandle createRelinkAndInvokeMethod(final RelinkableCallSite callSite, final int relinkCount) { - // Make a bound MH of invoke() for this linker and call site - final MethodHandle boundRelinker = MethodHandles.insertArguments(RELINK, 0, this, callSite, Integer.valueOf( - relinkCount)); - // Make a MH that gathers all arguments to the invocation into an Object[] - final MethodType type = callSite.getDescriptor().getMethodType(); - final MethodHandle collectingRelinker = boundRelinker.asCollector(Object[].class, type.parameterCount()); - return MethodHandles.foldArguments(MethodHandles.exactInvoker(type), collectingRelinker.asType( - type.changeReturnType(MethodHandle.class))); - } - - /** - * Relinks a call site conforming to the invocation arguments. - * - * @param callSite the call site itself - * @param arguments arguments to the invocation - * - * @return return the method handle for the invocation - * - * @throws Exception rethrows any exception thrown by the linkers - */ - @SuppressWarnings("unused") - private MethodHandle relink(final RelinkableCallSite callSite, final int relinkCount, final Object... arguments) throws Exception { - final CallSiteDescriptor callSiteDescriptor = callSite.getDescriptor(); - final boolean unstableDetectionEnabled = unstableRelinkThreshold > 0; - final boolean callSiteUnstable = unstableDetectionEnabled && relinkCount >= unstableRelinkThreshold; - final LinkRequest linkRequest = new SimpleLinkRequest(callSiteDescriptor, callSiteUnstable, arguments); - - GuardedInvocation guardedInvocation = linkerServices.getGuardedInvocation(linkRequest); - - // None found - throw an exception - if(guardedInvocation == null) { - throw new NoSuchDynamicMethodException(callSiteDescriptor.toString()); - } - - // 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 = prelinkTransformer.filter(guardedInvocation, linkRequest, linkerServices); - Objects.requireNonNull(guardedInvocation); - - int newRelinkCount = relinkCount; - // Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until - // threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink - // has already executed once for the unstable call site; we only want the call site to throw away its current - // linkage once, when it transitions to unstable. - if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) { - callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount)); - } else { - callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount)); - } - if(syncOnRelink) { - MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite }); - } - return guardedInvocation.getInvocation(); - } - - /** - * 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 - * site is being linked. - */ - public static StackTraceElement getLinkedCallSiteLocation() { - final StackTraceElement[] trace = new Throwable().getStackTrace(); - for(int i = 0; i < trace.length - 1; ++i) { - final StackTraceElement frame = trace[i]; - // If we found any of our linking entry points on the stack... - if(isRelinkFrame(frame) || isInitialLinkFrame(frame)) { - // ... then look for the first thing calling it that isn't j.l.invoke - for (int j = i + 1; j < trace.length; ++j) { - final StackTraceElement frame2 = trace[j]; - if (!frame2.getClassName().startsWith(INVOKE_PACKAGE_PREFIX)) { - return frame2; - } - } - } - } - return null; - } - - /** - * Returns {@code true} if the frame represents {@code MethodHandleNatives.linkCallSite()}, - * the frame immediately on top of the call site frame when the call site is - * being linked for the first time. - * - * @param frame the frame - * - * @return {@code true} if this frame represents {@code MethodHandleNatives.linkCallSite()}. - */ - private static boolean isInitialLinkFrame(final StackTraceElement frame) { - return testFrame(frame, INITIAL_LINK_METHOD_NAME, INITIAL_LINK_CLASS_NAME); - } - - /** - * Returns {@code true} if the frame represents {@code DynamicLinker.relink()}, - * the frame immediately on top of the call site frame when the call site is - * being relinked (linked for second and subsequent times). - * - * @param frame the frame - * - * @return {@code true} if this frame represents {@code DynamicLinker.relink()}. - */ - private static boolean isRelinkFrame(final StackTraceElement frame) { - return testFrame(frame, RELINK_METHOD_NAME, CLASS_NAME); - } - - private static boolean testFrame(final StackTraceElement frame, final String methodName, final String className) { - return methodName.equals(frame.getMethodName()) && className.equals(frame.getClassName()); - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,527 +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.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.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} 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}. - */ - private static final int DEFAULT_UNSTABLE_RELINK_THRESHOLD = 8; - - private boolean classLoaderExplicitlySet = false; - private ClassLoader classLoader; - - private List prioritizedLinkers; - private List fallbackLinkers; - private boolean syncOnRelink = false; - private int unstableRelinkThreshold = DEFAULT_UNSTABLE_RELINK_THRESHOLD; - private GuardedInvocationTransformer prelinkTransformer; - private MethodTypeConversionStrategy autoConversionStrategy; - private MethodHandleTransformer internalObjectsFilter; - - private List autoLoadingErrors = Collections.emptyList(); - - /** - * 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 automatic discovery of - * available linkers. - */ - public void setClassLoader(final ClassLoader classLoader) { - this.classLoader = classLoader; - classLoaderExplicitlySet = true; - } - - /** - * 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. Can be null. - * @throws NullPointerException if any of the list elements are null. - */ - public void setPrioritizedLinkers(final List prioritizedLinkers) { - this.prioritizedLinkers = copyListRequireNonNullElements(prioritizedLinkers); - } - - /** - * Sets the prioritized guarding dynamic linkers. Identical to calling - * {@link #setPrioritizedLinkers(List)} with - * {@code Arrays.asList(prioritizedLinkers)}. - * - * @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(prioritizedLinkers == null ? null : Arrays.asList(prioritizedLinkers)); - } - - /** - * Sets a single prioritized linker. Identical to calling - * {@link #setPrioritizedLinkers(List)} with a single-element list. - * - * @param prioritizedLinker the single prioritized linker. Must not be null. - * @throws NullPointerException if null is passed. - */ - public void setPrioritizedLinker(final GuardingDynamicLinker prioritizedLinker) { - this.prioritizedLinkers = Collections.singletonList(Objects.requireNonNull(prioritizedLinker)); - } - - /** - * 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. Note that if this - * method is not invoked explicitly or is passed null, then the factory - * will create an instance of {@link BeansLinker} to serve as the default - * fallback linker. - * @throws NullPointerException if any of the list elements are null. - */ - public void setFallbackLinkers(final List fallbackLinkers) { - this.fallbackLinkers = copyListRequireNonNullElements(fallbackLinkers); - } - - /** - * Sets the fallback guarding dynamic linkers. Identical to calling - * {@link #setFallbackLinkers(List)} with - * {@code Arrays.asList(fallbackLinkers)}. - * - * @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(fallbackLinkers == null ? null : Arrays.asList(fallbackLinkers)); - } - - /** - * 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) { - this.syncOnRelink = syncOnRelink; - } - - /** - * Sets the unstable relink threshold; the number of times a call site is - * relinked after which it will be considered unstable, and subsequent link - * requests for it will indicate this. Defaults to 8 when not set explicitly. - * @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) { - if(unstableRelinkThreshold < 0) { - throw new IllegalArgumentException("unstableRelinkThreshold < 0"); - } - this.unstableRelinkThreshold = unstableRelinkThreshold; - } - - /** - * 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 setPrelinkTransformer(final GuardedInvocationTransformer prelinkTransformer) { - this.prelinkTransformer = prelinkTransformer; - } - - /** - * 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 - * {@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 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() { - // Treat nulls appropriately - if(prioritizedLinkers == null) { - prioritizedLinkers = Collections.emptyList(); - } - if(fallbackLinkers == null) { - fallbackLinkers = Collections.singletonList(new BeansLinker()); - } - - // Gather classes of all precreated (prioritized and fallback) linkers. - // We'll filter out any discovered linkers of the same class. - final Set> knownLinkerClasses = - new HashSet<>(); - addClasses(knownLinkerClasses, prioritizedLinkers); - addClasses(knownLinkerClasses, fallbackLinkers); - - final List discovered = discoverAutoLoadLinkers(); - - // Now, concatenate ... - final List linkers = - new ArrayList<>(prioritizedLinkers.size() + discovered.size() - + fallbackLinkers.size()); - // ... prioritized linkers, ... - linkers.addAll(prioritizedLinkers); - // ... filtered discovered linkers, ... - for(final GuardingDynamicLinker linker: discovered) { - if(!knownLinkerClasses.contains(linker.getClass())) { - linkers.add(linker); - } - } - // ... and finally fallback linkers. - linkers.addAll(fallbackLinkers); - final List optimized = CompositeTypeBasedGuardingDynamicLinker.optimize(linkers); - final GuardingDynamicLinker composite; - switch(linkers.size()) { - case 0: { - composite = (r, s) -> null; // linker that can't link anything - break; - } - case 1: { - composite = optimized.get(0); - break; - } - default: { - composite = new CompositeGuardingDynamicLinker(optimized); - break; - } - } - - final List typeConverters = new LinkedList<>(); - for(final GuardingDynamicLinker linker: linkers) { - if(linker instanceof GuardingTypeConverterFactory) { - typeConverters.add((GuardingTypeConverterFactory)linker); - } - } - - if(prelinkTransformer == null) { - prelinkTransformer = (inv, request, linkerServices) -> inv.asType(linkerServices, request.getCallSiteDescriptor().getMethodType()); - } - - return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters, - 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(); - } - }, GET_CLASS_LOADER_CONTEXT); - } - - private static void addClasses(final Set> knownLinkerClasses, - final List linkers) { - for(final GuardingDynamicLinker linker: linkers) { - 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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/LinkerServicesImpl.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/LinkerServicesImpl.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,164 +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.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/NamedOperation.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/NamedOperation.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 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 final 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 instanceof NamedOperation) { - final NamedOperation other = (NamedOperation)obj; - return baseOperation.equals(other.baseOperation) && name.equals(other.name); - } - return false; - } - - /** - * 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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/NoSuchDynamicMethodException.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/NoSuchDynamicMethodException.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +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.GuardingDynamicLinker; - -/** - * Thrown at the invocation if the call site can not be linked by any available {@link GuardingDynamicLinker}. - */ -public class NoSuchDynamicMethodException extends RuntimeException { - private static final long serialVersionUID = 1L; - - /** - * Creates a new NoSuchDynamicMethodException - * @param message the message of the exception. - */ - public NoSuchDynamicMethodException(final String message) { - super(message); - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/Operation.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/Operation.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 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 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,178 +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.MethodHandle; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.support.ChainedCallSite; -import jdk.internal.dynalink.support.SimpleRelinkableCallSite; - -/** - * 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 { - /** - * 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); - - /** - * Returns the descriptor for this call site. - * - * @return the descriptor for this call site. - */ - public CallSiteDescriptor getDescriptor(); - - /** - * This method will be called by the dynamic linker every time the call site - * is 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 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 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 (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 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 relinkAndInvoke); -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/StandardOperation.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/StandardOperation.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/TypeConverterFactory.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/TypeConverterFactory.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,437 +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.lang.invoke.MethodHandles.Lookup; -import java.lang.invoke.MethodType; -import java.lang.invoke.WrongMethodTypeException; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.LinkedList; -import java.util.List; -import java.util.function.Supplier; -import jdk.internal.dynalink.internal.AccessControlContextFactory; -import jdk.internal.dynalink.linker.ConversionComparator; -import jdk.internal.dynalink.linker.ConversionComparator.Comparison; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; -import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.linker.MethodTypeConversionStrategy; -import jdk.internal.dynalink.linker.support.TypeUtilities; - -/** - * A factory for type converters. This class is the main implementation behind the - * {@link LinkerServices#asType(MethodHandle, MethodType)}. It manages the known {@link GuardingTypeConverterFactory} - * instances and creates appropriate converters for method handles. - */ -final class TypeConverterFactory { - private static final AccessControlContext GET_CLASS_LOADER_CONTEXT = - AccessControlContextFactory.createAccessControlContext("getClassLoader"); - - private final GuardingTypeConverterFactory[] factories; - private final ConversionComparator[] comparators; - private final MethodTypeConversionStrategy autoConversionStrategy; - - private final ClassValue> converterMap = new ClassValue>() { - @Override - protected ClassMap computeValue(final Class sourceType) { - return new ClassMap(getClassLoader(sourceType)) { - @Override - protected MethodHandle computeValue(final Class targetType) { - try { - return createConverter(sourceType, targetType); - } catch (final RuntimeException e) { - throw e; - } catch (final Exception e) { - throw new RuntimeException(e); - } - } - }; - } - }; - - private final ClassValue> converterIdentityMap = new ClassValue>() { - @Override - protected ClassMap computeValue(final Class sourceType) { - return new ClassMap(getClassLoader(sourceType)) { - @Override - protected MethodHandle computeValue(final Class targetType) { - if(!canAutoConvert(sourceType, targetType)) { - final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType); - if(converter != IDENTITY_CONVERSION) { - return converter; - } - } - return IDENTITY_CONVERSION.asType(MethodType.methodType(targetType, sourceType)); - } - }; - } - }; - - private final ClassValue> canConvert = new ClassValue>() { - @Override - protected ClassMap computeValue(final Class sourceType) { - return new ClassMap(getClassLoader(sourceType)) { - @Override - protected Boolean computeValue(final Class targetType) { - try { - return getTypeConverterNull(sourceType, targetType) != null; - } catch (final RuntimeException e) { - throw e; - } catch (final Exception e) { - throw new RuntimeException(e); - } - } - }; - } - }; - - private static ClassLoader getClassLoader(final Class clazz) { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public ClassLoader run() { - return clazz.getClassLoader(); - } - }, GET_CLASS_LOADER_CONTEXT); - } - - /** - * Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances. - * - * @param factories the {@link GuardingTypeConverterFactory} instances to compose. - * @param autoConversionStrategy conversion strategy for automatic type conversions. After - * {@link #asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has applied all custom - * conversions to a method handle, it still needs to effect - * {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that - * can usually be automatically applied as per - * {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}. - * However, sometimes language runtimes will want to customize even those conversions for their own call - * sites. A typical example is allowing unboxing of null return values, which is by default prohibited by - * ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom - * automatic conversion strategy, that can deal with null values. Note that when the strategy's - * {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} - * is invoked, the custom language conversions will already have been applied to the method handle, so by - * design the difference between the handle's current method type and the desired final type will always - * only be ones that can be subjected to method invocation conversions. Can be null, in which case no - * custom strategy is employed. - */ - TypeConverterFactory(final Iterable factories, - final MethodTypeConversionStrategy autoConversionStrategy) { - final List l = new LinkedList<>(); - final List c = new LinkedList<>(); - for(final GuardingTypeConverterFactory factory: factories) { - l.add(factory); - if(factory instanceof ConversionComparator) { - c.add((ConversionComparator)factory); - } - } - this.factories = l.toArray(new GuardingTypeConverterFactory[l.size()]); - this.comparators = c.toArray(new ConversionComparator[c.size()]); - this.autoConversionStrategy = autoConversionStrategy; - } - - /** - * Similar to {@link MethodHandle#asType(MethodType)} except it also hooks in method handles produced by - * {@link GuardingTypeConverterFactory} implementations, providing for language-specific type coercing of - * parameters. For all conversions that are not a JLS method invocation conversion it'll insert - * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters - * provided by {@link GuardingTypeConverterFactory} implementations. For the remaining JLS method invocation - * conversions, it will invoke {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)} first - * if an automatic conversion strategy was specified in the - * {@link #TypeConverterFactory(Iterable, MethodTypeConversionStrategy) constructor}, and finally apply - * {@link MethodHandle#asType(MethodType)} for any remaining conversions. - * - * @param handle target method handle - * @param fromType the types of source arguments - * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)}, - * {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)}, and - * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with - * {@link GuardingTypeConverterFactory} produced type converters as filters. - */ - MethodHandle asType(final MethodHandle handle, final MethodType fromType) { - MethodHandle newHandle = handle; - final MethodType toType = newHandle.type(); - final int l = toType.parameterCount(); - if(l != fromType.parameterCount()) { - throw new WrongMethodTypeException("Parameter counts differ: " + handle.type() + " vs. " + fromType); - } - int pos = 0; - final List converters = new LinkedList<>(); - for(int i = 0; i < l; ++i) { - final Class fromParamType = fromType.parameterType(i); - final Class toParamType = toType.parameterType(i); - if(canAutoConvert(fromParamType, toParamType)) { - newHandle = applyConverters(newHandle, pos, converters); - } else { - final MethodHandle converter = getTypeConverterNull(fromParamType, toParamType); - if(converter != null) { - if(converters.isEmpty()) { - pos = i; - } - converters.add(converter); - } else { - newHandle = applyConverters(newHandle, pos, converters); - } - } - } - newHandle = applyConverters(newHandle, pos, converters); - - // Convert return type - final Class fromRetType = fromType.returnType(); - final Class toRetType = toType.returnType(); - if(fromRetType != Void.TYPE && toRetType != Void.TYPE) { - if(!canAutoConvert(toRetType, fromRetType)) { - final MethodHandle converter = getTypeConverterNull(toRetType, fromRetType); - if(converter != null) { - newHandle = MethodHandles.filterReturnValue(newHandle, converter); - } - } - } - - // Give change to automatic conversion strategy, if one is present. - final MethodHandle autoConvertedHandle = - autoConversionStrategy != null ? autoConversionStrategy.asType(newHandle, fromType) : newHandle; - - // Do a final asType for any conversions that remain. - return autoConvertedHandle.asType(fromType); - } - - private static MethodHandle applyConverters(final MethodHandle handle, final int pos, final List converters) { - if(converters.isEmpty()) { - return handle; - } - final MethodHandle newHandle = - MethodHandles.filterArguments(handle, pos, converters.toArray(new MethodHandle[converters.size()])); - converters.clear(); - return newHandle; - } - - /** - * Returns true if there might exist a conversion between the requested types (either an automatic JVM conversion, - * or one provided by any available {@link GuardingTypeConverterFactory}), or false if there definitely does not - * exist a conversion between the requested types. Note that returning true does not guarantee that the conversion - * will succeed at runtime (notably, if the "from" or "to" types are sufficiently generic), but returning false - * guarantees that it would fail. - * - * @param from the source type for the conversion - * @param to the target type for the conversion - * @return true if there can be a conversion, false if there can not. - */ - boolean canConvert(final Class from, final Class to) { - return canAutoConvert(from, to) || canConvert.get(from).get(to); - } - - /** - * Determines which of the two type conversions from a source type to the two target types is preferred. This is - * used for dynamic overloaded method resolution. If the source type is convertible to exactly one target type with - * a method invocation conversion, it is chosen, otherwise available {@link ConversionComparator}s are consulted. - * @param sourceType the source type. - * @param targetType1 one potential target type - * @param targetType2 another potential target type. - * @return one of Comparison constants that establish which - if any - of the target types is preferable for the - * conversion. - */ - Comparison compareConversion(final Class sourceType, final Class targetType1, final Class targetType2) { - for(final ConversionComparator comparator: comparators) { - final Comparison result = comparator.compareConversion(sourceType, targetType1, targetType2); - if(result != Comparison.INDETERMINATE) { - return result; - } - } - if(TypeUtilities.isMethodInvocationConvertible(sourceType, targetType1)) { - if(!TypeUtilities.isMethodInvocationConvertible(sourceType, targetType2)) { - return Comparison.TYPE_1_BETTER; - } - } else if(TypeUtilities.isMethodInvocationConvertible(sourceType, targetType2)) { - return Comparison.TYPE_2_BETTER; - } - return Comparison.INDETERMINATE; - } - - /** - * Determines whether it's safe to perform an automatic conversion between the source and target class. - * - * @param fromType convert from this class - * @param toType convert to this class - * @return true if it's safe to let MethodHandles.convertArguments() to handle this conversion. - */ - /*private*/ static boolean canAutoConvert(final Class fromType, final Class toType) { - return TypeUtilities.isMethodInvocationConvertible(fromType, toType); - } - - /*private*/ MethodHandle getCacheableTypeConverterNull(final Class sourceType, final Class targetType) { - final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType); - return converter == IDENTITY_CONVERSION ? null : converter; - } - - /*private*/ MethodHandle getTypeConverterNull(final Class sourceType, final Class targetType) { - try { - return getCacheableTypeConverterNull(sourceType, targetType); - } catch(final NotCacheableConverter e) { - return e.converter; - } - } - - /*private*/ MethodHandle getCacheableTypeConverter(final Class sourceType, final Class targetType) { - return converterMap.get(sourceType).get(targetType); - } - - /** - * Given a source and target type, returns a method handle that converts between them. Never returns null; in worst - * case it will return an identity conversion (that might fail for some values at runtime). You can use this method - * if you have a piece of your program that is written in Java, and you need to reuse existing type conversion - * machinery in a non-invokedynamic context. - * @param sourceType the type to convert from - * @param targetType the type to convert to - * @return a method handle performing the conversion. - */ - MethodHandle getTypeConverter(final Class sourceType, final Class targetType) { - try { - return converterIdentityMap.get(sourceType).get(targetType); - } catch(final NotCacheableConverter e) { - return e.converter; - } - } - - private static class LookupSupplier implements Supplier { - volatile boolean returnedLookup; - volatile boolean closed; - - @Override - public Lookup get() { - if (closed) { - // Something held on to this supplier and tried to invoke it - // after we're done with it. - throw new IllegalStateException(); - } - final Lookup lookup = LinkerServicesImpl.getCurrentLookup(); - returnedLookup = true; - return lookup; - } - } - - /*private*/ MethodHandle createConverter(final Class sourceType, final Class targetType) throws Exception { - final MethodType type = MethodType.methodType(targetType, sourceType); - final MethodHandle identity = IDENTITY_CONVERSION.asType(type); - MethodHandle last = identity; - - final LookupSupplier lookupSupplier = new LookupSupplier(); - try { - for(int i = factories.length; i-- > 0;) { - final GuardedInvocation next = factories[i].convertToType(sourceType, targetType, lookupSupplier); - if(next != null) { - last = next.compose(last); - } - } - } finally { - lookupSupplier.closed = true; - } - - if(last == identity) { - return IDENTITY_CONVERSION; - } - if(!lookupSupplier.returnedLookup) { - return last; - } - // At least one of the consulted converter factories obtained the - // lookup, so we must presume the created converter is sensitive to the - // lookup class and thus we will not cache it. - throw new NotCacheableConverter(last); - } - - /*private*/ static final MethodHandle IDENTITY_CONVERSION = MethodHandles.identity(Object.class); - - @SuppressWarnings("serial") - private static class NotCacheableConverter extends RuntimeException { - final MethodHandle converter; - - NotCacheableConverter(final MethodHandle converter) { - super("", null, false, false); - this.converter = converter; - } - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,890 +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.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -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.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 - * exposure and method calls for both static and instance facets of a class. - */ -abstract class AbstractJavaLinker implements GuardingDynamicLinker { - - final Class clazz; - private final MethodHandle classGuard; - private final MethodHandle assignableGuard; - private final Map propertyGetters = new HashMap<>(); - private final Map propertySetters = new HashMap<>(); - private final Map methods = new HashMap<>(); - - AbstractJavaLinker(final Class clazz, final MethodHandle classGuard) { - this(clazz, classGuard, classGuard); - } - - AbstractJavaLinker(final Class clazz, final MethodHandle classGuard, final MethodHandle assignableGuard) { - this.clazz = clazz; - this.classGuard = classGuard; - this.assignableGuard = assignableGuard; - - final FacetIntrospector introspector = createFacetIntrospector(); - // Add methods and properties - for(final Method method: introspector.getMethods()) { - final String name = method.getName(); - // Add method - addMember(name, method, methods); - // Add the method as a property getter and/or setter - if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) { - // Property getter - setPropertyGetter(method, 3); - } else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 && - method.getReturnType() == boolean.class) { - // Boolean property getter - setPropertyGetter(method, 2); - } else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) { - // Property setter - addMember(decapitalize(name.substring(3)), method, propertySetters); - } - } - - // Add field getter/setters as property getters/setters. - for(final Field field: introspector.getFields()) { - final String name = field.getName(); - // Only add a property getter when one is not defined already as a getXxx()/isXxx() method. - if(!propertyGetters.containsKey(name)) { - setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS); - } - if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) { - addMember(name, new SimpleDynamicMethod(introspector.unreflectSetter(field), clazz, name), - propertySetters); - } - } - - // Add inner classes, but only those for which we don't hide a property with it - for(final Map.Entry innerClassSpec: introspector.getInnerClassGetters().entrySet()) { - final String name = innerClassSpec.getKey(); - if(!propertyGetters.containsKey(name)) { - setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS); - } - } - } - - private static String decapitalize(final String str) { - assert str != null; - if(str.isEmpty()) { - return str; - } - - final char c0 = str.charAt(0); - if(Character.isLowerCase(c0)) { - return str; - } - - // If it has two consecutive upper-case characters, i.e. "URL", don't decapitalize - if(str.length() > 1 && Character.isUpperCase(str.charAt(1))) { - return str; - } - - final char c[] = str.toCharArray(); - c[0] = Character.toLowerCase(c0); - return new String(c); - } - - abstract FacetIntrospector createFacetIntrospector(); - - Set getReadablePropertyNames() { - return getUnmodifiableKeys(propertyGetters); - } - - Set getWritablePropertyNames() { - return getUnmodifiableKeys(propertySetters); - } - - Set getMethodNames() { - return getUnmodifiableKeys(methods); - } - - private static Set getUnmodifiableKeys(final Map m) { - return Collections.unmodifiableSet(m.keySet()); - } - - /** - * Sets the specified dynamic method to be the property getter for the specified property. Note that you can only - * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties - * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)} - * instead. - * @param name name of the property - * @param handle the method handle that implements the property getter - * @param validationType the validation type for the property - */ - private void setPropertyGetter(final String name, final SingleDynamicMethod handle, final ValidationType validationType) { - propertyGetters.put(name, new AnnotatedDynamicMethod(handle, validationType)); - } - - /** - * Sets the specified reflective method to be the property getter for the specified property. - * @param getter the getter method - * @param prefixLen the getter prefix in the method name; should be 3 for getter names starting with "get" and 2 for - * names starting with "is". - */ - private void setPropertyGetter(final Method getter, final int prefixLen) { - setPropertyGetter(decapitalize(getter.getName().substring(prefixLen)), createDynamicMethod( - getMostGenericGetter(getter)), ValidationType.INSTANCE_OF); - } - - /** - * Sets the specified method handle to be the property getter for the specified property. Note that you can only - * use this when you're certain that the method handle does not belong to a caller-sensitive method. For properties - * that are caller-sensitive, you must use {@link #setPropertyGetter(String, SingleDynamicMethod, ValidationType)} - * instead. - * @param name name of the property - * @param handle the method handle that implements the property getter - * @param validationType the validation type for the property - */ - void setPropertyGetter(final String name, final MethodHandle handle, final ValidationType validationType) { - setPropertyGetter(name, new SimpleDynamicMethod(handle, clazz, name), validationType); - } - - private void addMember(final String name, final AccessibleObject ao, final Map methodMap) { - addMember(name, createDynamicMethod(ao), methodMap); - } - - private void addMember(final String name, final SingleDynamicMethod method, final Map methodMap) { - final DynamicMethod existingMethod = methodMap.get(name); - final DynamicMethod newMethod = mergeMethods(method, existingMethod, clazz, name); - if(newMethod != existingMethod) { - methodMap.put(name, newMethod); - } - } - - /** - * Given one or more reflective methods or constructors, creates a dynamic method that represents them all. The - * methods should represent all overloads of the same name (or all constructors of the class). - * @param members the reflective members - * @param clazz the class declaring the reflective members - * @param name the common name of the reflective members. - * @return a dynamic method representing all the specified reflective members. - */ - static DynamicMethod createDynamicMethod(final Iterable members, final Class clazz, final String name) { - DynamicMethod dynMethod = null; - for(final AccessibleObject method: members) { - dynMethod = mergeMethods(createDynamicMethod(method), dynMethod, clazz, name); - } - return dynMethod; - } - - /** - * Given a reflective method or a constructor, creates a dynamic method that represents it. This method will - * distinguish between caller sensitive and ordinary methods/constructors, and create appropriate caller sensitive - * dynamic method when needed. - * @param m the reflective member - * @return the single dynamic method representing the reflective member - */ - private static SingleDynamicMethod createDynamicMethod(final AccessibleObject m) { - if (m.isAnnotationPresent(CallerSensitive.class)) { - // Method has @CallerSensitive annotation - return new CallerSensitiveDynamicMethod(m); - } - // Method has no @CallerSensitive annotation - final MethodHandle mh; - try { - mh = unreflectSafely(m); - } catch (final IllegalAccessError e) { - // java.lang.invoke can in some case conservatively treat as caller sensitive methods that aren't - // marked with the annotation. In this case, we'll fall back to treating it as caller sensitive. - return new CallerSensitiveDynamicMethod(m); - } - // Proceed with non-caller sensitive - final Member member = (Member)m; - return new SimpleDynamicMethod(mh, member.getDeclaringClass(), member.getName(), m instanceof Constructor); - } - - /** - * Unreflects a method handle from a Method or a Constructor using safe (zero-privilege) unreflection. Should be - * only used for methods and constructors that are not caller sensitive. If a caller sensitive method were - * unreflected through this mechanism, it would not be a security issue, but would be bound to the zero-privilege - * unreflector as its caller, and thus completely useless. - * @param m the method or constructor - * @return the method handle - */ - private static MethodHandle unreflectSafely(final AccessibleObject m) { - if(m instanceof Method) { - final Method reflMethod = (Method)m; - final MethodHandle handle = Lookup.PUBLIC.unreflect(reflMethod); - if(Modifier.isStatic(reflMethod.getModifiers())) { - return StaticClassIntrospector.editStaticMethodHandle(handle); - } - return handle; - } - return StaticClassIntrospector.editConstructorMethodHandle(Lookup.PUBLIC.unreflectConstructor((Constructor)m)); - } - - private static DynamicMethod mergeMethods(final SingleDynamicMethod method, final DynamicMethod existing, final Class clazz, final String name) { - if(existing == null) { - return method; - } else if(existing.contains(method)) { - return existing; - } else if(existing instanceof SingleDynamicMethod) { - final OverloadedDynamicMethod odm = new OverloadedDynamicMethod(clazz, name); - odm.addMethod(((SingleDynamicMethod)existing)); - odm.addMethod(method); - return odm; - } else if(existing instanceof OverloadedDynamicMethod) { - ((OverloadedDynamicMethod)existing).addMethod(method); - return existing; - } - throw new AssertionError(); - } - - @Override - public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) - throws Exception { - 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 = Arrays.asList( - CompositeOperation.getOperations( - NamedOperation.getBaseOperation(operation))); - final Object name = NamedOperation.getName(operation); - - while(!operations.isEmpty()) { - final GuardedInvocationComponent gic = - getGuardedInvocationComponent(callSiteDescriptor, - linkerServices, operations, name); - if(gic != null) { - return gic.getGuardedInvocation(); - } - operations = pop(operations); - } - return null; - } - - protected GuardedInvocationComponent getGuardedInvocationComponent( - final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, - final List operations, final Object name) - throws Exception { - if(operations.isEmpty()) { - return null; - } - 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 SET_PROPERTY:name(this, value) or SET_PROPERTY(this, name, value) - if(op == StandardOperation.SET_PROPERTY) { - return getPropertySetter(callSiteDescriptor, linkerServices, pop(operations), name); - } - // Either GET_METHOD:name(this), or GET_METHOD(this, name) - if(op == StandardOperation.GET_METHOD) { - return getMethodGetter(callSiteDescriptor, linkerServices, pop(operations), name); - } - return null; - } - - static final List pop(final List l) { - return l.subList(1, l.size()); - } - - MethodHandle getClassGuard(final CallSiteDescriptor desc) { - return getClassGuard(desc.getMethodType()); - } - - MethodHandle getClassGuard(final MethodType type) { - return Guards.asType(classGuard, type); - } - - GuardedInvocationComponent getClassGuardedInvocationComponent(final MethodHandle invocation, final MethodType type) { - return new GuardedInvocationComponent(invocation, getClassGuard(type), clazz, ValidationType.EXACT_CLASS); - } - - abstract SingleDynamicMethod getConstructorMethod(final String signature); - - private MethodHandle getAssignableGuard(final MethodType type) { - return Guards.asType(assignableGuard, type); - } - - private GuardedInvocation createGuardedDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final String methodName, final Map methodMap){ - final MethodHandle inv = getDynamicMethodInvocation(callSiteDescriptor, linkerServices, methodName, methodMap); - return inv == null ? null : new GuardedInvocation(inv, getClassGuard(callSiteDescriptor.getMethodType())); - } - - private MethodHandle getDynamicMethodInvocation(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final String methodName, final Map methodMap) { - final DynamicMethod dynaMethod = getDynamicMethod(methodName, methodMap); - return dynaMethod != null ? dynaMethod.getInvocation(callSiteDescriptor, linkerServices) : null; - } - - private DynamicMethod getDynamicMethod(final String methodName, final Map methodMap) { - final DynamicMethod dynaMethod = methodMap.get(methodName); - return dynaMethod != null ? dynaMethod : getExplicitSignatureDynamicMethod(methodName, methodMap); - } - - private SingleDynamicMethod getExplicitSignatureDynamicMethod(final String fullName, - final Map methodsMap) { - // What's below is meant to support the "name(type, type, ...)" syntax that programmers can use in a method name - // to manually pin down an exact overloaded variant. This is not usually required, as the overloaded method - // resolution works correctly in almost every situation. However, in presence of many language-specific - // conversions with a radically dynamic language, most overloaded methods will end up being constantly selected - // at invocation time, so a programmer knowledgeable of the situation might choose to pin down an exact overload - // for performance reasons. - - // Is the method name lexically of the form "name(types)"? - final int lastChar = fullName.length() - 1; - if(fullName.charAt(lastChar) != ')') { - return null; - } - final int openBrace = fullName.indexOf('('); - if(openBrace == -1) { - return null; - } - - final String name = fullName.substring(0, openBrace); - final String signature = fullName.substring(openBrace + 1, lastChar); - - // Find an existing method for the "name" part - final DynamicMethod simpleNamedMethod = methodsMap.get(name); - if(simpleNamedMethod == null) { - // explicit signature constructor access - // Java.type("java.awt.Color")["(int,int,int)"] - // will get Color(int,int,int) constructor of Color class. - if (name.isEmpty()) { - return getConstructorMethod(signature); - } - - return null; - } - - // Try to get a narrowed dynamic method for the explicit parameter types. - return simpleNamedMethod.getMethodForExactParamTypes(signature); - } - - private static final MethodHandle IS_METHOD_HANDLE_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType( - boolean.class, MethodHandle.class)); - private static final MethodHandle CONSTANT_NULL_DROP_METHOD_HANDLE = MethodHandles.dropArguments( - MethodHandles.constant(Object.class, null), 0, MethodHandle.class); - - private GuardedInvocationComponent getPropertySetter(final CallSiteDescriptor callSiteDescriptor, - 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); - } - - 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. - - // 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)); - - // 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); - } - - // 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()); - - private static final MethodHandle IS_ANNOTATED_METHOD_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType( - boolean.class, AnnotatedDynamicMethod.class)); - 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, 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, final Object name) throws Exception { - if (name == null) { - return getUnnamedPropertyGetter(callSiteDescriptor, linkerServices, ops); - } - - return getNamedPropertyGetter(callSiteDescriptor, linkerServices, ops, name); - } - - 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); - - // 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); - } - - // 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) { - switch(validationType) { - case EXACT_CLASS: { - return getClassGuard(methodType); - } - case INSTANCE_OF: { - return getAssignableGuard(methodType); - } - case IS_ARRAY: { - return Guards.isArray(0, methodType); - } - case NONE: { - return null; - } - default: { - throw new AssertionError(); - } - } - } - - private static final MethodHandle IS_DYNAMIC_METHOD = Guards.isInstance(DynamicMethod.class, - MethodType.methodType(boolean.class, Object.class)); - private static final MethodHandle OBJECT_IDENTITY = MethodHandles.identity(Object.class); - - private GuardedInvocationComponent getMethodGetter(final CallSiteDescriptor callSiteDescriptor, - 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); - if (name == null) { - return getUnnamedMethodGetter(callSiteDescriptor, linkerServices, ops, type); - } - - return getNamedMethodGetter(callSiteDescriptor, linkerServices, ops, name, type); - } - - 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); - - 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 { - final MethodHandle method1; - final MethodHandle method2; - - MethodPair(final MethodHandle method1, final MethodHandle method2) { - this.method1 = method1; - this.method2 = method2; - } - - MethodHandle guardWithTest(final MethodHandle test) { - return MethodHandles.guardWithTest(test, method1, method2); - } - } - - static MethodPair matchReturnTypes(final MethodHandle m1, final MethodHandle m2) { - final MethodType type1 = m1.type(); - final MethodType type2 = m2.type(); - final Class commonRetType = InternalTypeUtilities.getCommonLosslessConversionType(type1.returnType(), - type2.returnType()); - return new MethodPair( - m1.asType(type1.changeReturnType(commonRetType)), - m2.asType(type2.changeReturnType(commonRetType))); - } - - private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) { - if(descriptor.getMethodType().parameterCount() != paramCount) { - throw new BootstrapMethodError(descriptor.getOperation() + " must have exactly " + paramCount + " parameters."); - } - } - - private static MethodHandle GET_PROPERTY_GETTER_HANDLE = MethodHandles.dropArguments(privateLookup.findOwnSpecial( - "getPropertyGetterHandle", Object.class, Object.class), 1, Object.class); - private final MethodHandle getPropertyGetterHandle = GET_PROPERTY_GETTER_HANDLE.bindTo(this); - - /** - * @param id the property ID - * @return the method handle for retrieving the property, or null if the property does not exist - */ - @SuppressWarnings("unused") - private Object getPropertyGetterHandle(final Object id) { - return propertyGetters.get(id); - } - - // Type is MethodHandle(BeanLinker, MethodType, LinkerServices, Object, String, Object), of which the two "Object" - // args are dropped; this makes handles with first three args conform to "Object, String, Object" though, which is - // a typical property setter with variable name signature (target, name, value). - private static final MethodHandle GET_PROPERTY_SETTER_HANDLE = MethodHandles.dropArguments(MethodHandles.dropArguments( - privateLookup.findOwnSpecial("getPropertySetterHandle", MethodHandle.class, CallSiteDescriptor.class, - LinkerServices.class, Object.class), 3, Object.class), 5, Object.class); - // Type is MethodHandle(MethodType, LinkerServices, Object, String, Object) - private final MethodHandle getPropertySetterHandle = GET_PROPERTY_SETTER_HANDLE.bindTo(this); - - @SuppressWarnings("unused") - private MethodHandle getPropertySetterHandle(final CallSiteDescriptor setterDescriptor, final LinkerServices linkerServices, - final Object id) { - return getDynamicMethodInvocation(setterDescriptor, linkerServices, String.valueOf(id), propertySetters); - } - - private static MethodHandle GET_DYNAMIC_METHOD = MethodHandles.dropArguments(privateLookup.findOwnSpecial( - "getDynamicMethod", Object.class, Object.class), 1, Object.class); - private final MethodHandle getDynamicMethod = GET_DYNAMIC_METHOD.bindTo(this); - - @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 - // GET_METHOD linking). - private Object getDynamicMethod(final Object name) { - return getDynamicMethod(String.valueOf(name), methods); - } - - /** - * Returns a dynamic method of the specified name. - * - * @param name name of the method - * @return the dynamic method (either {@link SimpleDynamicMethod} or {@link OverloadedDynamicMethod}, or null if the - * method with the specified name does not exist. - */ - DynamicMethod getDynamicMethod(final String name) { - return getDynamicMethod(name, methods); - } - - /** - * Find the most generic superclass that declares this getter. Since getters have zero args (aside from the - * receiver), they can't be overloaded, so we're free to link with an instanceof guard for the most generic one, - * creating more stable call sites. - * @param getter the getter - * @return getter with same name, declared on the most generic superclass/interface of the declaring class - */ - private static Method getMostGenericGetter(final Method getter) { - return getMostGenericGetter(getter.getName(), getter.getReturnType(), getter.getDeclaringClass()); - } - - private static Method getMostGenericGetter(final String name, final Class returnType, final Class declaringClass) { - if(declaringClass == null) { - return null; - } - // Prefer interfaces - for(final Class itf: declaringClass.getInterfaces()) { - final Method itfGetter = getMostGenericGetter(name, returnType, itf); - if(itfGetter != null) { - return itfGetter; - } - } - final Method superGetter = getMostGenericGetter(name, returnType, declaringClass.getSuperclass()); - if(superGetter != null) { - return superGetter; - } - if(!CheckRestrictedPackage.isRestrictedClass(declaringClass)) { - try { - return declaringClass.getMethod(name); - } catch(final NoSuchMethodException e) { - // Intentionally ignored, meant to fall through - } - } - return null; - } - - private static final class AnnotatedDynamicMethod { - private final SingleDynamicMethod method; - /*private*/ final ValidationType validationType; - - AnnotatedDynamicMethod(final SingleDynamicMethod method, final ValidationType validationType) { - this.method = method; - this.validationType = validationType; - } - - MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { - return method.getInvocation(callSiteDescriptor, linkerServices); - } - - @SuppressWarnings("unused") - MethodHandle getTarget(final CallSiteDescriptor desc, final LinkerServices linkerServices) { - final MethodHandle inv = linkerServices.filterInternalObjects(method.getTarget(desc)); - assert inv != null; - return inv; - } - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AccessibleMembersLookup.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/AccessibleMembersLookup.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,263 +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.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Set; - -/** - * Utility class for discovering accessible methods and inner classes. Normally, a public member declared on a class is - * accessible (that is, it can be invoked from anywhere). However, this is not the case if the class itself is not - * public, or belongs to a restricted-access package. In that case, it is required to lookup a member in a publicly - * accessible superclass or implemented interface of the class, and use it instead of the member discovered on the - * class. - */ -class AccessibleMembersLookup { - private final Map methods; - private final Set> innerClasses; - private final boolean instance; - - /** - * Creates a mapping for all accessible methods and inner classes on a class. - * - * @param clazz the inspected class - * @param instance true to inspect instance methods, false to inspect static methods. - */ - AccessibleMembersLookup(final Class clazz, final boolean instance) { - this.methods = new HashMap<>(); - this.innerClasses = new LinkedHashSet<>(); - this.instance = instance; - lookupAccessibleMembers(clazz); - } - - /** - * Returns an accessible method equivalent of a method. - * - * @param m the method whose accessible equivalent is requested. - * @return the accessible equivalent for the method (can be the same as the passed in method), or null if there is - * no accessible method equivalent. - */ - Method getAccessibleMethod(final Method m) { - return m == null ? null : methods.get(new MethodSignature(m)); - } - - Collection getMethods() { - return methods.values(); - } - - Class[] getInnerClasses() { - return innerClasses.toArray(new Class[innerClasses.size()]); - } - - /** - * A helper class that represents a method signature - name and argument types. - */ - static final class MethodSignature { - private final String name; - private final Class[] args; - - /** - * Creates a new method signature from arbitrary data. - * - * @param name the name of the method this signature represents. - * @param args the argument types of the method. - */ - MethodSignature(final String name, final Class[] args) { - this.name = name; - this.args = args; - } - - /** - * Creates a signature for the given method. - * - * @param method the method for which a signature is created. - */ - MethodSignature(final Method method) { - this(method.getName(), method.getParameterTypes()); - } - - /** - * Compares this object to another object - * - * @param o the other object - * @return true if the other object is also a method signature with the same name, same number of arguments, and - * same types of arguments. - */ - @Override - public boolean equals(final Object o) { - if(o instanceof MethodSignature) { - final MethodSignature ms = (MethodSignature)o; - return ms.name.equals(name) && Arrays.equals(args, ms.args); - } - return false; - } - - /** - * Returns a hash code, consistent with the overridden {@link #equals(Object)}. - */ - @Override - public int hashCode() { - return name.hashCode() ^ Arrays.hashCode(args); - } - - @Override - public String toString() { - final StringBuilder b = new StringBuilder(); - b.append("[MethodSignature ").append(name).append('('); - if(args.length > 0) { - b.append(args[0].getCanonicalName()); - for(int i = 1; i < args.length; ++i) { - b.append(", ").append(args[i].getCanonicalName()); - } - } - return b.append(")]").toString(); - } - } - - private void lookupAccessibleMembers(final Class clazz) { - boolean searchSuperTypes; - - if(!CheckRestrictedPackage.isRestrictedClass(clazz)) { - searchSuperTypes = false; - for(final Method method: clazz.getMethods()) { - final boolean isStatic = Modifier.isStatic(method.getModifiers()); - if(instance != isStatic) { - final MethodSignature sig = new MethodSignature(method); - if(!methods.containsKey(sig)) { - final Class declaringClass = method.getDeclaringClass(); - if(declaringClass != clazz && CheckRestrictedPackage.isRestrictedClass(declaringClass)) { - //Sometimes, the declaring class of a method (Method.getDeclaringClass()) - //retrieved through Class.getMethods() for a public class will be a - //non-public superclass. For such a method, we need to find a method with - //the same name and signature in a public superclass or implemented - //interface. - //This typically doesn't happen with classes emitted by a reasonably modern - //javac, as it'll create synthetic delegator methods in all public - //immediate subclasses of the non-public class. We have, however, observed - //this in the wild with class files compiled with older javac that doesn't - //generate the said synthetic delegators. - searchSuperTypes = true; - } else { - // don't allow inherited static - if (!isStatic || clazz == declaringClass) { - methods.put(sig, method); - } - } - } - } - } - for(final Class innerClass: clazz.getClasses()) { - // Add both static and non-static classes, regardless of instance flag. StaticClassLinker will just - // expose non-static classes with explicit constructor outer class argument. - // NOTE: getting inner class objects through getClasses() does not resolve them, so if those classes - // were not yet loaded, they'll only get loaded in a non-resolved state; no static initializers for - // them will trigger just by doing this. - innerClasses.add(innerClass); - } - } else { - searchSuperTypes = true; - } - - // don't need to search super types for static methods - if(instance && searchSuperTypes) { - // If we reach here, the class is either not public, or it is in a restricted package. Alternatively, it is - // public, but some of its methods claim that their declaring class is non-public. We'll try superclasses - // and implemented interfaces then looking for public ones. - final Class[] interfaces = clazz.getInterfaces(); - for(int i = 0; i < interfaces.length; i++) { - lookupAccessibleMembers(interfaces[i]); - } - final Class superclass = clazz.getSuperclass(); - if(superclass != null) { - lookupAccessibleMembers(superclass); - } - } - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,217 +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.invoke.MethodType; -import java.util.LinkedList; -import java.util.List; -import jdk.internal.dynalink.linker.support.TypeUtilities; - -/** - * Represents overloaded methods applicable to a specific call site signature. - */ -class ApplicableOverloadedMethods { - private final List methods; - private final boolean varArgs; - - /** - * Creates a new ApplicableOverloadedMethods instance - * - * @param methods a list of all overloaded methods with the same name for a class. - * @param callSiteType the type of the call site - * @param test applicability test. One of {@link #APPLICABLE_BY_SUBTYPING}, - * {@link #APPLICABLE_BY_METHOD_INVOCATION_CONVERSION}, or {@link #APPLICABLE_BY_VARIABLE_ARITY}. - */ - ApplicableOverloadedMethods(final List methods, final MethodType callSiteType, - final ApplicabilityTest test) { - this.methods = new LinkedList<>(); - for(final SingleDynamicMethod m: methods) { - if(test.isApplicable(callSiteType, m)) { - this.methods.add(m); - } - } - varArgs = test == APPLICABLE_BY_VARIABLE_ARITY; - } - - /** - * Retrieves all the methods this object holds. - * - * @return list of all methods. - */ - List getMethods() { - return methods; - } - - /** - * Returns a list of all methods in this objects that are maximally specific. - * - * @return a list of maximally specific methods. - */ - List findMaximallySpecificMethods() { - return MaximallySpecific.getMaximallySpecificMethods(methods, varArgs); - } - - abstract static class ApplicabilityTest { - abstract boolean isApplicable(MethodType callSiteType, SingleDynamicMethod method); - } - - /** - * Implements the applicability-by-subtyping test from JLS 15.12.2.2. - */ - static final ApplicabilityTest APPLICABLE_BY_SUBTYPING = new ApplicabilityTest() { - @Override - boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) { - final MethodType methodType = method.getMethodType(); - final int methodArity = methodType.parameterCount(); - if(methodArity != callSiteType.parameterCount()) { - return false; - } - // 0th arg is receiver; it doesn't matter for overload - // resolution. - for(int i = 1; i < methodArity; ++i) { - if(!TypeUtilities.isSubtype(callSiteType.parameterType(i), methodType.parameterType(i))) { - return false; - } - } - return true; - } - }; - - /** - * Implements the applicability-by-method-invocation-conversion test from JLS 15.12.2.3. - */ - static final ApplicabilityTest APPLICABLE_BY_METHOD_INVOCATION_CONVERSION = new ApplicabilityTest() { - @Override - boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) { - final MethodType methodType = method.getMethodType(); - final int methodArity = methodType.parameterCount(); - if(methodArity != callSiteType.parameterCount()) { - return false; - } - // 0th arg is receiver; it doesn't matter for overload - // resolution. - for(int i = 1; i < methodArity; ++i) { - if(!TypeUtilities.isMethodInvocationConvertible(callSiteType.parameterType(i), - methodType.parameterType(i))) { - return false; - } - } - return true; - } - }; - - /** - * Implements the applicability-by-variable-arity test from JLS 15.12.2.4. - */ - static final ApplicabilityTest APPLICABLE_BY_VARIABLE_ARITY = new ApplicabilityTest() { - @Override - boolean isApplicable(final MethodType callSiteType, final SingleDynamicMethod method) { - if(!method.isVarArgs()) { - return false; - } - final MethodType methodType = method.getMethodType(); - final int methodArity = methodType.parameterCount(); - final int fixArity = methodArity - 1; - final int callSiteArity = callSiteType.parameterCount(); - if(fixArity > callSiteArity) { - return false; - } - // 0th arg is receiver; it doesn't matter for overload - // resolution. - for(int i = 1; i < fixArity; ++i) { - if(!TypeUtilities.isMethodInvocationConvertible(callSiteType.parameterType(i), - methodType.parameterType(i))) { - return false; - } - } - final Class varArgType = methodType.parameterType(fixArity).getComponentType(); - for(int i = fixArity; i < callSiteArity; ++i) { - if(!TypeUtilities.isMethodInvocationConvertible(callSiteType.parameterType(i), varArgType)) { - return false; - } - } - return true; - } - }; -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanIntrospector.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/BeanIntrospector.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,104 +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.invoke.MethodHandle; -import java.util.Collections; -import java.util.Map; - -class BeanIntrospector extends FacetIntrospector { - BeanIntrospector(final Class clazz) { - super(clazz, true); - } - - @Override - Map getInnerClassGetters() { - return Collections.emptyMap(); // NOTE: non-static inner classes are also on StaticClassIntrospector. - } - - @Override - MethodHandle editMethodHandle(final MethodHandle mh) { - return mh; - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,525 +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.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.reflect.Array; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.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.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 - * {@link BeansLinker}. - */ -class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicLinker { - BeanLinker(final Class clazz) { - super(clazz, Guards.getClassGuard(clazz), Guards.getInstanceOfGuard(clazz)); - if(clazz.isArray()) { - // Some languages won't have a notion of manipulating collections. Exposing "length" on arrays as an - // explicit property is beneficial for them. - // REVISIT: is it maybe a code smell that 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); - } - } - - @Override - public boolean canLinkType(final Class type) { - return type == clazz; - } - - @Override - FacetIntrospector createFacetIntrospector() { - return new BeanIntrospector(clazz); - } - - @Override - protected GuardedInvocationComponent getGuardedInvocationComponent(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List operations, final Object name) throws Exception { - final GuardedInvocationComponent superGic = super.getGuardedInvocationComponent(callSiteDescriptor, - linkerServices, operations, name); - if(superGic != null) { - return superGic; - } - if(operations.isEmpty()) { - return null; - } - final Operation op = operations.get(0); - if(op == StandardOperation.GET_ELEMENT) { - return getElementGetter(callSiteDescriptor, linkerServices, pop(operations), name); - } - if(op == StandardOperation.SET_ELEMENT) { - return getElementSetter(callSiteDescriptor, linkerServices, pop(operations), name); - } - if(op == StandardOperation.GET_LENGTH) { - return getLengthGetter(callSiteDescriptor); - } - return null; - } - - @Override - SingleDynamicMethod getConstructorMethod(final String signature) { - return null; - } - - private static final MethodHandle GET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "get", - MethodType.methodType(Object.class, int.class)); - - private static final MethodHandle GET_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "get", - MethodType.methodType(Object.class, Object.class)); - - private static final MethodHandle LIST_GUARD = Guards.getInstanceOfGuard(List.class); - private static final MethodHandle MAP_GUARD = Guards.getInstanceOfGuard(Map.class); - - private enum CollectionType { - ARRAY, LIST, MAP - }; - - private GuardedInvocationComponent getElementGetter(final CallSiteDescriptor callSiteDescriptor, - 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, 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 - // dealing with an array, or a list or map, but hey... - // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers - // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices. - final GuardedInvocationComponent gic; - final CollectionType collectionType; - if(declaredType.isArray()) { - gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType), linkerServices); - collectionType = CollectionType.ARRAY; - } else if(List.class.isAssignableFrom(declaredType)) { - gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, linkerServices); - collectionType = CollectionType.LIST; - } else if(Map.class.isAssignableFrom(declaredType)) { - gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, linkerServices); - collectionType = CollectionType.MAP; - } else if(clazz.isArray()) { - gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(MethodHandles.arrayElementGetter(clazz)), callSiteType); - collectionType = CollectionType.ARRAY; - } else if(List.class.isAssignableFrom(clazz)) { - gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF, - linkerServices); - collectionType = CollectionType.LIST; - } else if(Map.class.isAssignableFrom(clazz)) { - gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class, ValidationType.INSTANCE_OF, - linkerServices); - collectionType = CollectionType.MAP; - } else { - // Can't retrieve elements for objects that are neither arrays, nor list, nor maps. - return nextComponent; - } - - // Convert the key to a number if we're working with a list or array - 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 { - typedName = name; - } - - final GuardedInvocation gi = gic.getGuardedInvocation(); - final Binder binder = new Binder(linkerServices, callSiteType, typedName); - final MethodHandle invocation = gi.getInvocation(); - - if(nextComponent == null) { - return gic.replaceInvocation(binder.bind(invocation)); - } - - final MethodHandle checkGuard; - switch(collectionType) { - case LIST: - checkGuard = convertArgToInt(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor); - break; - case MAP: - // TODO: A more complex solution could be devised for maps, one where we do a get() first, and fold it - // into a GWT that tests if it returned null, and if it did, do another GWT with containsKey() - // that returns constant null (on true), or falls back to next component (on false) - checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP); - break; - case ARRAY: - checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor); - break; - default: - throw new AssertionError(); - } - final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation), - nextComponent.getGuardedInvocation().getInvocation()); - return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(), - gic.getValidatorClass(), gic.getValidationType()); - } - - private static GuardedInvocationComponent createInternalFilteredGuardedInvocationComponent( - final MethodHandle invocation, final LinkerServices linkerServices) { - return new GuardedInvocationComponent(linkerServices.filterInternalObjects(invocation)); - } - - private static GuardedInvocationComponent createInternalFilteredGuardedInvocationComponent( - final MethodHandle invocation, final MethodHandle guard, final Class validatorClass, - final ValidationType validationType, final LinkerServices linkerServices) { - return new GuardedInvocationComponent(linkerServices.filterInternalObjects(invocation), guard, - validatorClass, validationType); - } - - private static Integer convertKeyToInteger(final Object fixedKey, final LinkerServices linkerServices) throws Exception { - if (fixedKey instanceof Integer) { - return (Integer)fixedKey; - } - - 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 { - 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; - } - } - - 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) { - final Class sourceType = desc.getMethodType().parameterType(1); - if(TypeUtilities.isMethodInvocationConvertible(sourceType, Number.class)) { - return mh; - } else if(ls.canConvert(sourceType, Number.class)) { - final MethodHandle converter = ls.getTypeConverter(sourceType, Number.class); - return MethodHandles.filterArguments(mh, 1, converter.asType(converter.type().changeReturnType( - mh.type().parameterType(1)))); - } - return mh; - } - - /** - * Contains methods to adapt an item getter/setter method handle to the requested type, optionally binding it to a - * fixed key first. - */ - private static class Binder { - private final LinkerServices linkerServices; - private final MethodType methodType; - private final Object fixedKey; - - Binder(final LinkerServices linkerServices, final MethodType methodType, final Object fixedKey) { - this.linkerServices = linkerServices; - this.methodType = fixedKey == null ? methodType : methodType.insertParameterTypes(1, fixedKey.getClass()); - this.fixedKey = fixedKey; - } - - /*private*/ MethodHandle bind(final MethodHandle handle) { - return bindToFixedKey(linkerServices.asTypeLosslessReturn(handle, methodType)); - } - - /*private*/ MethodHandle bindTest(final MethodHandle handle) { - return bindToFixedKey(Guards.asType(handle, methodType)); - } - - private MethodHandle bindToFixedKey(final MethodHandle handle) { - return fixedKey == null ? handle : MethodHandles.insertArguments(handle, 1, fixedKey); - } - } - - private static final MethodHandle RANGE_CHECK_ARRAY = findRangeCheck(Object.class); - private static final MethodHandle RANGE_CHECK_LIST = findRangeCheck(List.class); - private static final MethodHandle CONTAINS_MAP = Lookup.PUBLIC.findVirtual(Map.class, "containsKey", - MethodType.methodType(boolean.class, Object.class)); - - private static MethodHandle findRangeCheck(final Class collectionType) { - return Lookup.findOwnStatic(MethodHandles.lookup(), "rangeCheck", boolean.class, collectionType, Object.class); - } - - @SuppressWarnings("unused") - private static boolean rangeCheck(final Object array, final Object index) { - if(!(index instanceof Number)) { - return false; - } - final Number n = (Number)index; - final int intIndex = n.intValue(); - final double doubleValue = n.doubleValue(); - if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinite trigger IOOBE - return false; - } - if(0 <= intIndex && intIndex < Array.getLength(array)) { - return true; - } - throw new ArrayIndexOutOfBoundsException("Array index out of range: " + n); - } - - @SuppressWarnings("unused") - private static boolean rangeCheck(final List list, final Object index) { - if(!(index instanceof Number)) { - return false; - } - final Number n = (Number)index; - final int intIndex = n.intValue(); - final double doubleValue = n.doubleValue(); - if(intIndex != doubleValue && !Double.isInfinite(doubleValue)) { // let infinite trigger IOOBE - return false; - } - if(0 <= intIndex && intIndex < list.size()) { - return true; - } - throw new IndexOutOfBoundsException("Index: " + n + ", Size: " + list.size()); - } - - private static final MethodHandle SET_LIST_ELEMENT = Lookup.PUBLIC.findVirtual(List.class, "set", - MethodType.methodType(Object.class, int.class, Object.class)); - - private static final MethodHandle PUT_MAP_ELEMENT = Lookup.PUBLIC.findVirtual(Map.class, "put", - MethodType.methodType(Object.class, Object.class, Object.class)); - - private GuardedInvocationComponent getElementSetter(final CallSiteDescriptor callSiteDescriptor, - final LinkerServices linkerServices, final List operations, final Object name) throws Exception { - final MethodType callSiteType = callSiteDescriptor.getMethodType(); - final Class declaredType = callSiteType.parameterType(0); - - final GuardedInvocationComponent gic; - // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing - // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're - // dealing with an array, or a list or map, but hey... - // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers - // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices. - final CollectionType collectionType; - if(declaredType.isArray()) { - gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementSetter(declaredType), linkerServices); - collectionType = CollectionType.ARRAY; - } else if(List.class.isAssignableFrom(declaredType)) { - gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, linkerServices); - collectionType = CollectionType.LIST; - } else if(Map.class.isAssignableFrom(declaredType)) { - gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, linkerServices); - collectionType = CollectionType.MAP; - } else if(clazz.isArray()) { - gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects( - MethodHandles.arrayElementSetter(clazz)), callSiteType); - collectionType = CollectionType.ARRAY; - } else if(List.class.isAssignableFrom(clazz)) { - gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF, - linkerServices); - collectionType = CollectionType.LIST; - } else if(Map.class.isAssignableFrom(clazz)) { - gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), - Map.class, ValidationType.INSTANCE_OF, linkerServices); - collectionType = CollectionType.MAP; - } else { - // Can't set elements for objects that are neither arrays, nor list, nor maps. - gic = null; - collectionType = null; - } - - // In contrast to, say, getElementGetter, we only compute the nextComponent if the target object is not a map, - // as maps will always succeed in setting the element and will never need to fall back to the next component - // operation. - final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getGuardedInvocationComponent( - callSiteDescriptor, linkerServices, operations, name); - if(gic == null) { - return nextComponent; - } - - // Convert the key to a number if we're working with a list or array - 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 { - typedName = name; - } - - final GuardedInvocation gi = gic.getGuardedInvocation(); - final Binder binder = new Binder(linkerServices, callSiteType, typedName); - final MethodHandle invocation = gi.getInvocation(); - - if(nextComponent == null) { - return gic.replaceInvocation(binder.bind(invocation)); - } - - assert collectionType == CollectionType.LIST || collectionType == CollectionType.ARRAY; - final MethodHandle checkGuard = convertArgToInt(collectionType == CollectionType.LIST ? RANGE_CHECK_LIST : - RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor); - final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation), - nextComponent.getGuardedInvocation().getInvocation()); - return nextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(), - gic.getValidatorClass(), gic.getValidationType()); - } - - private static final MethodHandle GET_ARRAY_LENGTH = Lookup.PUBLIC.findStatic(Array.class, "getLength", - MethodType.methodType(int.class, Object.class)); - - private static final MethodHandle GET_COLLECTION_LENGTH = Lookup.PUBLIC.findVirtual(Collection.class, "size", - MethodType.methodType(int.class)); - - private static final MethodHandle GET_MAP_LENGTH = Lookup.PUBLIC.findVirtual(Map.class, "size", - MethodType.methodType(int.class)); - - private static final MethodHandle COLLECTION_GUARD = Guards.getInstanceOfGuard(Collection.class); - - private GuardedInvocationComponent getLengthGetter(final CallSiteDescriptor callSiteDescriptor) { - assertParameterCount(callSiteDescriptor, 1); - final MethodType callSiteType = callSiteDescriptor.getMethodType(); - final Class declaredType = callSiteType.parameterType(0); - // If declared type of receiver at the call site is already an array, collection, or map, bind without guard. - // Thing is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance - // they're dealing with an array, collection, or map, but hey... - if(declaredType.isArray()) { - return new GuardedInvocationComponent(GET_ARRAY_LENGTH.asType(callSiteType)); - } else if(Collection.class.isAssignableFrom(declaredType)) { - return new GuardedInvocationComponent(GET_COLLECTION_LENGTH.asType(callSiteType)); - } else if(Map.class.isAssignableFrom(declaredType)) { - return new GuardedInvocationComponent(GET_MAP_LENGTH.asType(callSiteType)); - } - - // Otherwise, create a binding based on the actual type of the argument with an appropriate guard. - if(clazz.isArray()) { - return new GuardedInvocationComponent(GET_ARRAY_LENGTH.asType(callSiteType), Guards.isArray(0, - callSiteType), ValidationType.IS_ARRAY); - } if(Collection.class.isAssignableFrom(clazz)) { - return new GuardedInvocationComponent(GET_COLLECTION_LENGTH.asType(callSiteType), Guards.asType( - COLLECTION_GUARD, callSiteType), Collection.class, ValidationType.INSTANCE_OF); - } if(Map.class.isAssignableFrom(clazz)) { - return new GuardedInvocationComponent(GET_MAP_LENGTH.asType(callSiteType), Guards.asType(MAP_GUARD, - callSiteType), Map.class, ValidationType.INSTANCE_OF); - } - // Can't retrieve length for objects that are neither arrays, nor collections, nor maps. - return null; - } - - private static void assertParameterCount(final CallSiteDescriptor descriptor, final int paramCount) { - if(descriptor.getMethodType().parameterCount() != paramCount) { - throw new BootstrapMethodError(descriptor.getOperation() + " must have exactly " + paramCount + " parameters."); - } - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,307 +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.invoke.MethodHandles.Lookup; -import java.util.Collections; -import java.util.Set; -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; -import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; - -/** - * 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 - * {@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 {@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 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() { - @Override - protected TypeBasedGuardingDynamicLinker computeValue(final Class clazz) { - // If ClassValue.put() were public, we could just pre-populate with these known mappings... - return - clazz == Class.class ? new ClassLinker() : - clazz == StaticClass.class ? new StaticClassLinker() : - DynamicMethod.class.isAssignableFrom(clazz) ? new DynamicMethodLinker() : - new BeanLinker(clazz); - } - }; - - /** - * Creates a new 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. - * @param clazz the class - * @return a bean linker for that class - */ - public static TypeBasedGuardingDynamicLinker getLinkerForClass(final Class clazz) { - return linkers.get(clazz); - } - - /** - * 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 Java dynamic method. - * @return true if it is a dynamic method, false otherwise. - */ - public static boolean isDynamicMethod(final Object obj) { - return obj instanceof DynamicMethod; - } - - /** - * 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 Java constructor. - * @return true if it is a constructor, false otherwise. - */ - public static boolean isDynamicConstructor(final Object obj) { - return obj instanceof DynamicMethod && ((DynamicMethod)obj).isConstructor(); - } - - /** - * 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. 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); - } - - /** - * Returns a set of names of all readable instance properties of a class. - * @param clazz the class - * @return a set of names of all readable instance properties of a class. - */ - public static Set getReadableInstancePropertyNames(final Class clazz) { - final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); - if(linker instanceof BeanLinker) { - return ((BeanLinker)linker).getReadablePropertyNames(); - } - return Collections.emptySet(); - } - - /** - * Returns a set of names of all writable instance properties of a class. - * @param clazz the class - * @return a set of names of all writable instance properties of a class. - */ - public static Set getWritableInstancePropertyNames(final Class clazz) { - final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); - if(linker instanceof BeanLinker) { - return ((BeanLinker)linker).getWritablePropertyNames(); - } - return Collections.emptySet(); - } - - /** - * Returns a set of names of all instance methods of a class. - * @param clazz the class - * @return a set of names of all instance methods of a class. - */ - public static Set getInstanceMethodNames(final Class clazz) { - final TypeBasedGuardingDynamicLinker linker = getLinkerForClass(clazz); - if(linker instanceof BeanLinker) { - return ((BeanLinker)linker).getMethodNames(); - } - return Collections.emptySet(); - } - - /** - * Returns a set of names of all readable static properties of a class. - * @param clazz the class - * @return a set of names of all readable static properties of a class. - */ - public static Set getReadableStaticPropertyNames(final Class clazz) { - return StaticClassLinker.getReadableStaticPropertyNames(clazz); - } - - /** - * Returns a set of names of all writable static properties of a class. - * @param clazz the class - * @return a set of names of all writable static properties of a class. - */ - public static Set getWritableStaticPropertyNames(final Class clazz) { - return StaticClassLinker.getWritableStaticPropertyNames(clazz); - } - - /** - * Returns a set of names of all static methods of a class. - * @param clazz the class - * @return a set of names of all static methods of a class. - */ - public static Set getStaticMethodNames(final Class clazz) { - return StaticClassLinker.getStaticMethodNames(clazz); - } - - @Override - public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) - throws Exception { - final Object receiver = request.getReceiver(); - if(receiver == null) { - // Can't operate on null - return null; - } - return getLinkerForClass(receiver.getClass()).getGuardedInvocation(request, linkerServices); - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,175 +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.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Constructor; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -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(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; - private final MethodType type; - - CallerSensitiveDynamicMethod(final AccessibleObject target) { - super(getName(target)); - this.target = target; - this.type = getMethodType(target); - } - - private static String getName(final AccessibleObject target) { - final Member m = (Member)target; - final boolean constructor = m instanceof Constructor; - return getMethodNameWithSignature(getMethodType(target), constructor ? m.getName() : - getClassAndMethodName(m.getDeclaringClass(), m.getName()), !constructor); - } - - @Override - MethodType getMethodType() { - return type; - } - - private static MethodType getMethodType(final AccessibleObject ao) { - final boolean isMethod = ao instanceof Method; - final Class rtype = isMethod ? ((Method)ao).getReturnType() : ((Constructor)ao).getDeclaringClass(); - final Class[] ptypes = isMethod ? ((Method)ao).getParameterTypes() : ((Constructor)ao).getParameterTypes(); - final MethodType type = MethodType.methodType(rtype, ptypes); - final Member m = (Member)ao; - return type.insertParameterTypes(0, - isMethod ? - Modifier.isStatic(m.getModifiers()) ? - Object.class : - m.getDeclaringClass() : - StaticClass.class); - } - - @Override - boolean isVarArgs() { - return target instanceof Method ? ((Method)target).isVarArgs() : ((Constructor)target).isVarArgs(); - } - - @Override - 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())) { - return StaticClassIntrospector.editStaticMethodHandle(mh); - } - return mh; - } - return StaticClassIntrospector.editConstructorMethodHandle(Lookup.unreflectConstructor(lookup, - (Constructor)target)); - } - - @Override - boolean isConstructor() { - return target instanceof Constructor; - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +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.reflect.Modifier; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.security.PrivilegedAction; -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 = - AccessControlContextFactory.createAccessControlContext(); - - /** - * Returns true if the class is either not public, or it resides in a package with restricted access. - * @param clazz the class to test - * @return true if the class is either not public, or it resides in a package with restricted access. - */ - static boolean isRestrictedClass(final Class clazz) { - if(!Modifier.isPublic(clazz.getModifiers())) { - // Non-public classes are always restricted - return true; - } - final SecurityManager sm = System.getSecurityManager(); - if(sm == null) { - // No further restrictions if we don't have a security manager - return false; - } - final String name = clazz.getName(); - final int i = name.lastIndexOf('.'); - if (i == -1) { - // Classes in default package are never restricted - return false; - } - // Do a package access check from within an access control context with no permissions - try { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - sm.checkPackageAccess(name.substring(0, i)); - return null; - } - }, NO_PERMISSIONS_CONTEXT); - } catch(final SecurityException e) { - return true; - } - return false; - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +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.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType; -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 - * methods on the class (respecting property getter/setter conventions). Note that Class objects are not recognized by - * the Dynalink as constructors for the instances of the class, {@link StaticClass} is used for this purpose. - */ -class ClassLinker extends BeanLinker { - - ClassLinker() { - super(Class.class); - // Map "classObject.static" to StaticClass.forClass(classObject). Can use EXACT_CLASS since class Class is final. - setPropertyGetter("static", FOR_CLASS, ValidationType.EXACT_CLASS); - } - - private static final MethodHandle FOR_CLASS = new Lookup(MethodHandles.lookup()).findStatic(StaticClass.class, - "forClass", MethodType.methodType(StaticClass.class, Class.class)); - -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,225 +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.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.linker.support.TypeUtilities; - -/** - * Represents a sequence of {@link Class} objects, useful for representing method signatures. Provides value - * semantics for using them as map keys, as well as specificity calculations and applicability checks as per - * 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. - */ - static final Class NULL_CLASS = (new Object() { /* Intentionally empty */ }).getClass(); - - private final Class[] classes; - private int hashCode; - - ClassString(final Class[] classes) { - this.classes = classes; - } - - ClassString(final MethodType type) { - this(type.parameterArray()); - } - - @Override - public boolean equals(final Object other) { - if(!(other instanceof ClassString)) { - return false; - } - final Class[] otherClasses = ((ClassString)other).classes; - if(otherClasses.length != classes.length) { - return false; - } - for(int i = 0; i < otherClasses.length; ++i) { - if(otherClasses[i] != classes[i]) { - return false; - } - } - return true; - } - - @Override - public int hashCode() { - if(hashCode == 0) { - int h = 0; - for(int i = 0; i < classes.length; ++i) { - h ^= classes[i].hashCode(); - } - hashCode = h; - } - return hashCode; - } - - boolean isVisibleFrom(final ClassLoader classLoader) { - return AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Boolean run() { - for(final Class clazz: classes) { - if(!InternalTypeUtilities.canReferenceDirectly(classLoader, clazz.getClassLoader())) { - return false; - } - } - return true; - } - }, GET_CLASS_LOADER_CONTEXT); - } - - List getMaximallySpecifics(final List methods, final LinkerServices linkerServices, final boolean varArg) { - return MaximallySpecific.getMaximallySpecificMethodHandles(getApplicables(methods, linkerServices, varArg), - varArg, classes, linkerServices); - } - - /** - * Returns all methods that are applicable to actual parameter classes represented by this ClassString object. - */ - LinkedList getApplicables(final List methods, final LinkerServices linkerServices, final boolean varArg) { - final LinkedList list = new LinkedList<>(); - for(final MethodHandle member: methods) { - if(isApplicable(member, linkerServices, varArg)) { - list.add(member); - } - } - return list; - } - - /** - * Returns true if the supplied method is applicable to actual parameter classes represented by this ClassString - * object. - * - */ - private boolean isApplicable(final MethodHandle method, final LinkerServices linkerServices, final boolean varArg) { - final Class[] formalTypes = method.type().parameterArray(); - final int cl = classes.length; - final int fl = formalTypes.length - (varArg ? 1 : 0); - if(varArg) { - if(cl < fl) { - return false; - } - } else { - if(cl != fl) { - return false; - } - } - // Starting from 1 as we ignore the receiver type - for(int i = 1; i < fl; ++i) { - if(!canConvert(linkerServices, classes[i], formalTypes[i])) { - return false; - } - } - if(varArg) { - final Class varArgType = formalTypes[fl].getComponentType(); - for(int i = fl; i < cl; ++i) { - if(!canConvert(linkerServices, classes[i], varArgType)) { - return false; - } - } - } - return true; - } - - private static boolean canConvert(final LinkerServices ls, final Class from, final Class to) { - if(from == NULL_CLASS) { - return !to.isPrimitive(); - } - return ls == null ? TypeUtilities.isMethodInvocationConvertible(from, to) : ls.canConvert(from, to); - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/DynamicMethod.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/DynamicMethod.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-2013 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package jdk.internal.dynalink.beans; - -import java.lang.invoke.MethodHandle; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.LinkerServices; - -/** - * Represents a single dynamic method. A "dynamic" method can be bound to a single Java method, or can be bound to all - * overloaded methods of the same name on a class. Getting an invocation of a dynamic method bound to multiple - * overloaded methods will perform overload resolution (actually, it will perform partial overloaded resolution at link - * time, but if that fails to identify exactly one target method, it will generate a method handle that will perform the - * rest of the overload resolution at invocation time for actual argument types). - */ -abstract class DynamicMethod { - private final String name; - - DynamicMethod(final String name) { - this.name = name; - } - - String getName() { - return name; - } - - /** - * Creates an invocation for the dynamic method. If the method is overloaded, it will perform overloaded method - * resolution based on the specified method type. The resulting resolution can either identify a single method to be - * invoked among the overloads, or it can identify multiple ones. In the latter case, the returned method handle - * will perform further overload resolution among these candidates at every invocation. If the method to be invoked - * is a variable arguments (vararg) method, it will pack the extra arguments in an array before the invocation of - * the underlying method if it is not already done. - * - * @param callSiteDescriptor the descriptor of the call site - * @param linkerServices linker services. Used for language-specific type conversions. - * @return an invocation suitable for calling the method from the specified call site. - */ - abstract MethodHandle getInvocation(CallSiteDescriptor callSiteDescriptor, LinkerServices linkerServices); - - /** - * Returns a single dynamic method representing a single underlying Java method (possibly selected among several - * overloads) with formal parameter types exactly matching the passed signature. - * @param paramTypes the comma-separated list of requested parameter type names. The names will match both - * qualified and unqualified type names. - * @return a single dynamic method representing a single underlying Java method, or null if none of the Java methods - * behind this dynamic method exactly match the requested parameter types. - */ - abstract SingleDynamicMethod getMethodForExactParamTypes(String paramTypes); - - /** - * True if this dynamic method already contains a method with an identical signature as the passed in method. - * @param method the method to check - * @return true if it already contains an equivalent method. - */ - abstract boolean contains(SingleDynamicMethod method); - - static String getClassAndMethodName(final Class clazz, final String name) { - final String clazzName = clazz.getCanonicalName(); - return (clazzName == null ? clazz.getName() : clazzName) + "." + name; - } - - @Override - public String toString() { - return "[" + getClass().getName() + " " + getName() + "]"; - } - - /** - * True if this method happens to be a constructor method. - * - * @return true if this represents a constructor. - */ - boolean isConstructor() { - return false; - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +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.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.linker.support.Guards; - -/** - * 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 - public boolean canLinkType(final Class type) { - return DynamicMethod.class.isAssignableFrom(type); - } - - @Override - public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) { - final Object receiver = linkRequest.getReceiver(); - if(!(receiver instanceof DynamicMethod)) { - return null; - } - final DynamicMethod dynMethod = (DynamicMethod)receiver; - final boolean constructor = dynMethod.isConstructor(); - final MethodHandle invocation; - - 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; - } - - // Insert null for StaticClass parameter - invocation = MethodHandles.insertArguments(ctorInvocation, 0, (Object)null); - } else { - return null; - } - - if (invocation != null) { - return new GuardedInvocation(MethodHandles.dropArguments(invocation, 0, - desc.getMethodType().parameterType(0)), Guards.getIdentityGuard(receiver)); - } - - return null; - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,184 +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.invoke.MethodHandle; -import java.lang.reflect.Field; -import java.lang.reflect.Member; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import jdk.internal.dynalink.linker.support.Lookup; - -/** - * Base for classes that expose class field and method information to an {@link AbstractJavaLinker}. There are - * subclasses for instance (bean) and static facet of a class. - */ -abstract class FacetIntrospector { - private final Class clazz; - private final boolean instance; - private final boolean isRestricted; - - protected final AccessibleMembersLookup membersLookup; - - FacetIntrospector(final Class clazz, final boolean instance) { - this.clazz = clazz; - this.instance = instance; - isRestricted = CheckRestrictedPackage.isRestrictedClass(clazz); - membersLookup = new AccessibleMembersLookup(clazz, instance); - } - - /** - * Returns getters for inner classes. - * @return getters for inner classes. - */ - abstract Map getInnerClassGetters(); - - /** - * Returns the fields for the class facet. - * @return the fields for the class facet. - */ - Collection getFields() { - if(isRestricted) { - // NOTE: we can't do anything here. Unlike with methods in AccessibleMethodsLookup, we can't just return - // the fields from a public superclass, because this class might define same-named fields which will shadow - // the superclass fields, and we have no way to know if they do, since we're denied invocation of - // getFields(). Therefore, the only correct course of action is to not expose any public fields from a class - // defined in a restricted package. - return Collections.emptySet(); - } - - final Field[] fields = clazz.getFields(); - final Collection cfields = new ArrayList<>(fields.length); - for(final Field field: fields) { - final boolean isStatic = Modifier.isStatic(field.getModifiers()); - if(isStatic && clazz != field.getDeclaringClass()) { - // ignore inherited static fields - continue; - } - - if(instance != isStatic && isAccessible(field)) { - cfields.add(field); - } - } - return cfields; - } - - boolean isAccessible(final Member m) { - final Class declaring = m.getDeclaringClass(); - // (declaring == clazz) is just an optimization - we're calling this only from code that operates on a - // non-restricted class, so if the declaring class is identical to the class being inspected, then forego - // a potentially expensive restricted-package check. - return declaring == clazz || !CheckRestrictedPackage.isRestrictedClass(declaring); - } - - /** - * Returns all the methods in the facet. - * @return all the methods in the facet. - */ - Collection getMethods() { - return membersLookup.getMethods(); - } - - - MethodHandle unreflectGetter(final Field field) { - return editMethodHandle(Lookup.PUBLIC.unreflectGetter(field)); - } - - MethodHandle unreflectSetter(final Field field) { - return editMethodHandle(Lookup.PUBLIC.unreflectSetter(field)); - } - - /** - * Returns an edited method handle. A facet might need to edit an unreflected method handle before it is usable with - * the facet. By default, returns the passed method handle unchanged. The class' static facet will introduce a - * dropArguments. - * @param mh the method handle to edit. - * @return the edited method handle. - */ - abstract MethodHandle editMethodHandle(MethodHandle mh); -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/GuardedInvocationComponent.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/GuardedInvocationComponent.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,250 +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.invoke.MethodHandle; -import jdk.internal.dynalink.linker.GuardedInvocation; - -/** - * Represents one component for a GuardedInvocation of a potentially composite operation of an - * {@link AbstractJavaLinker}. In addition to holding a guarded invocation, it holds semantic information about its - * guard. All guards produced in the AbstractJavaLinker are either "Class.isInstance()" or "getClass() == clazz" - * expressions. This allows choosing the most restrictive guard as the guard for the composition of two components. - */ -class GuardedInvocationComponent { - enum ValidationType { - NONE, // No guard; the operation can be linked unconditionally (quite rare); least strict. - INSTANCE_OF, // "validatorClass.isInstance(obj)" guard - EXACT_CLASS, // "obj.getClass() == validatorClass" guard; most strict. - IS_ARRAY, // "obj.getClass().isArray()" - } - - private final GuardedInvocation guardedInvocation; - private final Validator validator; - - GuardedInvocationComponent(final MethodHandle invocation) { - this(invocation, null, ValidationType.NONE); - } - - GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final ValidationType validationType) { - this(invocation, guard, null, validationType); - } - - GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final Class validatorClass, - final ValidationType validationType) { - this(invocation, guard, new Validator(validatorClass, validationType)); - } - - GuardedInvocationComponent(final GuardedInvocation guardedInvocation, final Class validatorClass, - final ValidationType validationType) { - this(guardedInvocation, new Validator(validatorClass, validationType)); - } - - GuardedInvocationComponent replaceInvocation(final MethodHandle newInvocation) { - return replaceInvocation(newInvocation, guardedInvocation.getGuard()); - } - - GuardedInvocationComponent replaceInvocation(final MethodHandle newInvocation, final MethodHandle newGuard) { - return new GuardedInvocationComponent(guardedInvocation.replaceMethods(newInvocation, - newGuard), validator); - } - - private GuardedInvocationComponent(final MethodHandle invocation, final MethodHandle guard, final Validator validator) { - this(new GuardedInvocation(invocation, guard), validator); - } - - private GuardedInvocationComponent(final GuardedInvocation guardedInvocation, final Validator validator) { - this.guardedInvocation = guardedInvocation; - this.validator = validator; - } - - GuardedInvocation getGuardedInvocation() { - return guardedInvocation; - } - - Class getValidatorClass() { - return validator.validatorClass; - } - - ValidationType getValidationType() { - return validator.validationType; - } - - GuardedInvocationComponent compose(final MethodHandle compositeInvocation, final MethodHandle otherGuard, - final Class otherValidatorClass, final ValidationType otherValidationType) { - final Validator compositeValidator = validator.compose(new Validator(otherValidatorClass, otherValidationType)); - final MethodHandle compositeGuard = compositeValidator == validator ? guardedInvocation.getGuard() : otherGuard; - return new GuardedInvocationComponent(compositeInvocation, compositeGuard, compositeValidator); - } - - private static class Validator { - /*private*/ final Class validatorClass; - /*private*/ final ValidationType validationType; - - Validator(final Class validatorClass, final ValidationType validationType) { - this.validatorClass = validatorClass; - this.validationType = validationType; - } - - Validator compose(final Validator other) { - if(other.validationType == ValidationType.NONE) { - return this; - } - switch(validationType) { - case NONE: - return other; - case INSTANCE_OF: - switch(other.validationType) { - case INSTANCE_OF: - if(isAssignableFrom(other)) { - return other; - } else if(other.isAssignableFrom(this)) { - return this; - } - break; - case EXACT_CLASS: - if(isAssignableFrom(other)) { - return other; - } - break; - case IS_ARRAY: - if(validatorClass.isArray()) { - return this; - } - break; - default: - throw new AssertionError(); - } - break; - case EXACT_CLASS: - switch(other.validationType) { - case INSTANCE_OF: - if(other.isAssignableFrom(this)) { - return this; - } - break; - case EXACT_CLASS: - if(validatorClass == other.validatorClass) { - return this; - } - break; - case IS_ARRAY: - if(validatorClass.isArray()) { - return this; - } - break; - default: - throw new AssertionError(); - } - break; - case IS_ARRAY: - switch(other.validationType) { - case INSTANCE_OF: - case EXACT_CLASS: - if(other.validatorClass.isArray()) { - return other; - } - break; - case IS_ARRAY: - return this; - default: - throw new AssertionError(); - } - break; - default: - throw new AssertionError(); - } - throw new AssertionError("Incompatible composition " + this + " vs " + other); - } - - private boolean isAssignableFrom(final Validator other) { - return validatorClass.isAssignableFrom(other.validatorClass); - } - - @Override - public String toString() { - return "Validator[" + validationType + (validatorClass == null ? "" : (" " + validatorClass.getName())) + "]"; - } - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,260 +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.invoke.MethodHandle; -import java.lang.invoke.MethodType; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import jdk.internal.dynalink.linker.ConversionComparator.Comparison; -import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.linker.support.TypeUtilities; - -/** - * Utility class that encapsulates the algorithm for choosing the maximally specific methods. - */ -class MaximallySpecific { - /** - * Given a list of methods, returns a list of maximally specific methods. - * - * @param methods the list of methods - * @param varArgs whether to assume the methods are varargs - * @return the list of maximally specific methods. - */ - static List getMaximallySpecificMethods(final List methods, final boolean varArgs) { - return getMaximallySpecificSingleDynamicMethods(methods, varArgs, null, null); - } - - private abstract static class MethodTypeGetter { - abstract MethodType getMethodType(T t); - } - - private static final MethodTypeGetter METHOD_HANDLE_TYPE_GETTER = - new MethodTypeGetter() { - @Override - MethodType getMethodType(final MethodHandle t) { - return t.type(); - } - }; - - private static final MethodTypeGetter DYNAMIC_METHOD_TYPE_GETTER = - new MethodTypeGetter() { - @Override - MethodType getMethodType(final SingleDynamicMethod t) { - return t.getMethodType(); - } - }; - - /** - * Given a list of methods handles, returns a list of maximally specific methods, applying language-runtime - * specific conversion preferences. - * - * @param methods the list of method handles - * @param varArgs whether to assume the method handles are varargs - * @param argTypes concrete argument types for the invocation - * @return the list of maximally specific method handles. - */ - static List getMaximallySpecificMethodHandles(final List methods, final boolean varArgs, - final Class[] argTypes, final LinkerServices ls) { - return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, METHOD_HANDLE_TYPE_GETTER); - } - - /** - * Given a list of methods, returns a list of maximally specific methods, applying language-runtime specific - * conversion preferences. - * - * @param methods the list of methods - * @param varArgs whether to assume the methods are varargs - * @param argTypes concrete argument types for the invocation - * @return the list of maximally specific methods. - */ - static List getMaximallySpecificSingleDynamicMethods(final List methods, - final boolean varArgs, final Class[] argTypes, final LinkerServices ls) { - return getMaximallySpecificMethods(methods, varArgs, argTypes, ls, DYNAMIC_METHOD_TYPE_GETTER); - } - - /** - * Given a list of methods, returns a list of maximally specific methods, applying language-runtime specific - * conversion preferences. - * - * @param methods the list of methods - * @param varArgs whether to assume the methods are varargs - * @param argTypes concrete argument types for the invocation - * @return the list of maximally specific methods. - */ - private static List getMaximallySpecificMethods(final List methods, final boolean varArgs, - final Class[] argTypes, final LinkerServices ls, final MethodTypeGetter methodTypeGetter) { - if(methods.size() < 2) { - return methods; - } - final LinkedList maximals = new LinkedList<>(); - for(final T m: methods) { - final MethodType methodType = methodTypeGetter.getMethodType(m); - boolean lessSpecific = false; - for(final Iterator maximal = maximals.iterator(); maximal.hasNext();) { - final T max = maximal.next(); - switch(isMoreSpecific(methodType, methodTypeGetter.getMethodType(max), varArgs, argTypes, ls)) { - case TYPE_1_BETTER: { - maximal.remove(); - break; - } - case TYPE_2_BETTER: { - lessSpecific = true; - break; - } - case INDETERMINATE: { - // do nothing - break; - } - default: { - throw new AssertionError(); - } - } - } - if(!lessSpecific) { - maximals.addLast(m); - } - } - return maximals; - } - - private static Comparison isMoreSpecific(final MethodType t1, final MethodType t2, final boolean varArgs, final Class[] argTypes, - final LinkerServices ls) { - final int pc1 = t1.parameterCount(); - final int pc2 = t2.parameterCount(); - assert varArgs || (pc1 == pc2) && (argTypes == null || argTypes.length == pc1); - assert (argTypes == null) == (ls == null); - final int maxPc = Math.max(Math.max(pc1, pc2), argTypes == null ? 0 : argTypes.length); - boolean t1MoreSpecific = false; - boolean t2MoreSpecific = false; - // NOTE: Starting from 1 as overloaded method resolution doesn't depend on 0th element, which is the type of - // 'this'. We're only dealing with instance methods here, not static methods. Actually, static methods will have - // a fake 'this' of type StaticClass. - for(int i = 1; i < maxPc; ++i) { - final Class c1 = getParameterClass(t1, pc1, i, varArgs); - final Class c2 = getParameterClass(t2, pc2, i, varArgs); - if(c1 != c2) { - final Comparison cmp = compare(c1, c2, argTypes, i, ls); - if(cmp == Comparison.TYPE_1_BETTER && !t1MoreSpecific) { - t1MoreSpecific = true; - if(t2MoreSpecific) { - return Comparison.INDETERMINATE; - } - } - if(cmp == Comparison.TYPE_2_BETTER && !t2MoreSpecific) { - t2MoreSpecific = true; - if(t1MoreSpecific) { - return Comparison.INDETERMINATE; - } - } - } - } - if(t1MoreSpecific) { - return Comparison.TYPE_1_BETTER; - } else if(t2MoreSpecific) { - return Comparison.TYPE_2_BETTER; - } - return Comparison.INDETERMINATE; - } - - private static Comparison compare(final Class c1, final Class c2, final Class[] argTypes, final int i, final LinkerServices cmp) { - if(cmp != null) { - final Comparison c = cmp.compareConversion(argTypes[i], c1, c2); - if(c != Comparison.INDETERMINATE) { - return c; - } - } - if(TypeUtilities.isSubtype(c1, c2)) { - return Comparison.TYPE_1_BETTER; - } if(TypeUtilities.isSubtype(c2, c1)) { - return Comparison.TYPE_2_BETTER; - } - return Comparison.INDETERMINATE; - } - - private static Class getParameterClass(final MethodType t, final int l, final int i, final boolean varArgs) { - return varArgs && i >= l - 1 ? t.parameterType(l - 1).getComponentType() : t.parameterType(i); - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,433 +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.invoke.MethodHandle; -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; - -/** - * Represents a group of {@link SingleDynamicMethod} objects that represents all overloads of a particular name (or all - * constructors) for a particular class. Correctly handles overload resolution, variable arity methods, and caller - * sensitive methods within the overloads. - */ -class OverloadedDynamicMethod extends DynamicMethod { - /** - * Holds a list of all methods. - */ - private final LinkedList methods; - private final ClassLoader classLoader; - - /** - * Creates a new overloaded dynamic method. - * - * @param clazz the class this method belongs to - * @param name the name of the method - */ - OverloadedDynamicMethod(final Class clazz, final String name) { - this(new LinkedList(), clazz.getClassLoader(), getClassAndMethodName(clazz, name)); - } - - private OverloadedDynamicMethod(final LinkedList methods, final ClassLoader classLoader, final String name) { - super(name); - this.methods = methods; - this.classLoader = classLoader; - } - - @Override - SingleDynamicMethod getMethodForExactParamTypes(final String paramTypes) { - final LinkedList matchingMethods = new LinkedList<>(); - for(final SingleDynamicMethod method: methods) { - final SingleDynamicMethod matchingMethod = method.getMethodForExactParamTypes(paramTypes); - if(matchingMethod != null) { - matchingMethods.add(matchingMethod); - } - } - switch(matchingMethods.size()) { - case 0: { - return null; - } - case 1: { - return matchingMethods.getFirst(); - } - default: { - throw new BootstrapMethodError("Can't choose among " + matchingMethods + " for argument types " - + paramTypes + " for method " + getName()); - } - } - } - - @Override - public MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { - final MethodType callSiteType = callSiteDescriptor.getMethodType(); - // First, find all methods applicable to the call site by subtyping (JLS 15.12.2.2) - final ApplicableOverloadedMethods subtypingApplicables = getApplicables(callSiteType, - ApplicableOverloadedMethods.APPLICABLE_BY_SUBTYPING); - // Next, find all methods applicable by method invocation conversion to the call site (JLS 15.12.2.3). - final ApplicableOverloadedMethods methodInvocationApplicables = getApplicables(callSiteType, - ApplicableOverloadedMethods.APPLICABLE_BY_METHOD_INVOCATION_CONVERSION); - // Finally, find all methods applicable by variable arity invocation. (JLS 15.12.2.4). - final ApplicableOverloadedMethods variableArityApplicables = getApplicables(callSiteType, - ApplicableOverloadedMethods.APPLICABLE_BY_VARIABLE_ARITY); - - // Find the methods that are maximally specific based on the call site signature - List maximallySpecifics = subtypingApplicables.findMaximallySpecificMethods(); - if(maximallySpecifics.isEmpty()) { - maximallySpecifics = methodInvocationApplicables.findMaximallySpecificMethods(); - if(maximallySpecifics.isEmpty()) { - maximallySpecifics = variableArityApplicables.findMaximallySpecificMethods(); - } - } - - // Now, get a list of the rest of the methods; those that are *not* applicable to the call site signature based - // on JLS rules. As paradoxical as that might sound, we have to consider these for dynamic invocation, as they - // might match more concrete types passed in invocations. That's why we provisionally call them "invokables". - // This is typical for very generic signatures at call sites. Typical example: call site specifies - // (Object, Object), and we have a method whose parameter types are (String, int). None of the JLS applicability - // rules will trigger, but we must consider the method, as it can be the right match for a concrete invocation. - @SuppressWarnings({ "unchecked", "rawtypes" }) - final List invokables = (List)methods.clone(); - invokables.removeAll(subtypingApplicables.getMethods()); - invokables.removeAll(methodInvocationApplicables.getMethods()); - invokables.removeAll(variableArityApplicables.getMethods()); - for(final Iterator it = invokables.iterator(); it.hasNext();) { - final SingleDynamicMethod m = it.next(); - if(!isApplicableDynamically(linkerServices, callSiteType, m)) { - it.remove(); - } - } - - // If no additional methods can apply at invocation time, and there's more than one maximally specific method - // based on call site signature, that is a link-time ambiguity. In a static scenario, javac would report an - // ambiguity error. - if(invokables.isEmpty() && maximallySpecifics.size() > 1) { - throw new BootstrapMethodError("Can't choose among " + maximallySpecifics + " for argument types " - + callSiteType); - } - - // Merge them all. - invokables.addAll(maximallySpecifics); - switch(invokables.size()) { - case 0: { - // No overloads can ever match the call site type - return null; - } - case 1: { - // Very lucky, we ended up with a single candidate method handle based on the call site signature; we - // can link it very simply by delegating to the SingleDynamicMethod. - return invokables.iterator().next().getInvocation(callSiteDescriptor, linkerServices); - } - default: { - // We have more than one candidate. We have no choice but to link to a method that resolves overloads on - // every invocation (alternatively, we could opportunistically link the one method that resolves for the - // current arguments, but we'd need to install a fairly complex guard for that and when it'd fail, we'd - // go back all the way to candidate selection. Note that we're resolving any potential caller sensitive - // 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()); - for(final SingleDynamicMethod method: invokables) { - methodHandles.add(method.getTarget(callSiteDescriptor)); - } - 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 - public boolean contains(final SingleDynamicMethod m) { - for(final SingleDynamicMethod method: methods) { - if(method.contains(m)) { - return true; - } - } - return false; - } - - @Override - public boolean isConstructor() { - assert !methods.isEmpty(); - return methods.getFirst().isConstructor(); - } - - @Override - public String toString() { - // First gather the names and sort them. This makes it consistent and easier to read. - final List names = new ArrayList<>(methods.size()); - int len = 0; - for (final SingleDynamicMethod m: methods) { - final String name = m.getName(); - len += name.length(); - names.add(name); - } - // Case insensitive sorting, so e.g. "Object" doesn't come before "boolean". - final Collator collator = Collator.getInstance(); - collator.setStrength(Collator.SECONDARY); - Collections.sort(names, collator); - - final String className = getClass().getName(); - // Class name length + length of signatures + 2 chars/per signature for indentation and newline + - // 3 for brackets and initial newline - final int totalLength = className.length() + len + 2 * names.size() + 3; - final StringBuilder b = new StringBuilder(totalLength); - b.append('[').append(className).append('\n'); - for(final String name: names) { - b.append(' ').append(name).append('\n'); - } - b.append(']'); - assert b.length() == totalLength; - return b.toString(); - }; - - ClassLoader getClassLoader() { - return classLoader; - } - - private static boolean isApplicableDynamically(final LinkerServices linkerServices, final MethodType callSiteType, - final SingleDynamicMethod m) { - final MethodType methodType = m.getMethodType(); - final boolean varArgs = m.isVarArgs(); - final int fixedArgLen = methodType.parameterCount() - (varArgs ? 1 : 0); - final int callSiteArgLen = callSiteType.parameterCount(); - - // Arity checks - if(varArgs) { - if(callSiteArgLen < fixedArgLen) { - return false; - } - } else if(callSiteArgLen != fixedArgLen) { - return false; - } - - // Fixed arguments type checks, starting from 1, as receiver type doesn't participate - for(int i = 1; i < fixedArgLen; ++i) { - if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), methodType.parameterType(i))) { - return false; - } - } - if(!varArgs) { - // Not vararg; both arity and types matched. - return true; - } - - final Class varArgArrayType = methodType.parameterType(fixedArgLen); - final Class varArgType = varArgArrayType.getComponentType(); - - if(fixedArgLen == callSiteArgLen - 1) { - // Exactly one vararg; check both array type matching and array component type matching. - final Class callSiteArgType = callSiteType.parameterType(fixedArgLen); - return isApplicableDynamically(linkerServices, callSiteArgType, varArgArrayType) - || isApplicableDynamically(linkerServices, callSiteArgType, varArgType); - } - - // Either zero, or more than one vararg; check if all actual vararg types match the vararg array component type. - for(int i = fixedArgLen; i < callSiteArgLen; ++i) { - if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), varArgType)) { - return false; - } - } - - return true; - } - - private static boolean isApplicableDynamically(final LinkerServices linkerServices, final Class callSiteType, - final Class methodType) { - return isPotentiallyConvertible(callSiteType, methodType) - || linkerServices.canConvert(callSiteType, methodType); - } - - private ApplicableOverloadedMethods getApplicables(final MethodType callSiteType, final ApplicabilityTest test) { - return new ApplicableOverloadedMethods(methods, callSiteType, test); - } - - /** - * Add a method to this overloaded method's set. - * - * @param method a method to add - */ - public void addMethod(final SingleDynamicMethod method) { - assert constructorFlagConsistent(method); - methods.add(method); - } - - 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 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,280 +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.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import jdk.internal.dynalink.internal.InternalTypeUtilities; -import jdk.internal.dynalink.linker.LinkerServices; -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 - * a vararg subset depending on the subclass. The method is for a fixed number of arguments though (as it is generated - * for a concrete call site). As such, all methods in the subset can be invoked with the specified number of arguments - * (exactly matching for fixargs, or having less than or equal fixed arguments, for varargs). - */ -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 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; - - fixArgMethods = new ArrayList<>(methodHandles.size()); - varArgMethods = new ArrayList<>(methodHandles.size()); - final int argNum = callSiteType.parameterCount(); - for(final MethodHandle mh: methodHandles) { - if(mh.isVarargsCollector()) { - final MethodHandle asFixed = mh.asFixedArity(); - if(argNum == asFixed.type().parameterCount()) { - fixArgMethods.add(asFixed); - } - varArgMethods.add(mh); - } else { - fixArgMethods.add(mh); - } - } - fixArgMethods.trimToSize(); - varArgMethods.trimToSize(); - - final MethodHandle bound = SELECT_METHOD.bindTo(this); - final MethodHandle collecting = SingleDynamicMethod.collectArguments(bound, argNum).asType( - callSiteType.changeReturnType(MethodHandle.class)); - invoker = linkerServices.asTypeLosslessReturn(MethodHandles.foldArguments( - MethodHandles.exactInvoker(this.callSiteType), collecting), callSiteType); - } - - MethodHandle getInvoker() { - return invoker; - } - - private static final MethodHandle SELECT_METHOD = Lookup.findOwnSpecial(MethodHandles.lookup(), "selectMethod", - MethodHandle.class, Object[].class); - - @SuppressWarnings("unused") - private MethodHandle selectMethod(final Object[] args) throws NoSuchMethodException { - final Class[] argTypes = new Class[args.length]; - for(int i = 0; i < argTypes.length; ++i) { - final Object arg = args[i]; - argTypes[i] = arg == null ? ClassString.NULL_CLASS : arg.getClass(); - } - final ClassString classString = new ClassString(argTypes); - MethodHandle method = argTypesToMethods.get(classString); - if(method == null) { - List methods = classString.getMaximallySpecifics(fixArgMethods, linkerServices, false); - if(methods.isEmpty()) { - methods = classString.getMaximallySpecifics(varArgMethods, linkerServices, true); - } - switch(methods.size()) { - case 0: { - method = getNoSuchMethodThrower(argTypes); - break; - } - case 1: { - method = SingleDynamicMethod.getInvocation(methods.get(0), callSiteType, linkerServices); - break; - } - default: { - // This is unfortunate - invocation time ambiguity. We can still save the day if - method = getAmbiguousMethodThrower(argTypes, methods); - break; - } - } - // Avoid keeping references to unrelated classes; this ruins the - // performance a bit, but avoids class loader memory leaks. - if(classString.isVisibleFrom(callSiteClassLoader)) { - argTypesToMethods.put(classString, method); - } - } - return method; - } - - private MethodHandle getNoSuchMethodThrower(final Class[] argTypes) { - return adaptThrower(MethodHandles.insertArguments(THROW_NO_SUCH_METHOD, 0, this, argTypes)); - } - - private static final MethodHandle THROW_NO_SUCH_METHOD = Lookup.findOwnSpecial(MethodHandles.lookup(), - "throwNoSuchMethod", void.class, Class[].class); - - @SuppressWarnings("unused") - private void throwNoSuchMethod(final Class[] argTypes) throws NoSuchMethodException { - if(varArgMethods.isEmpty()) { - throw new NoSuchMethodException("None of the fixed arity signatures " + getSignatureList(fixArgMethods) + - " of method " + parent.getName() + " match the argument types " + argTypesString(argTypes)); - } - throw new NoSuchMethodException("None of the fixed arity signatures " + getSignatureList(fixArgMethods) + - " or the variable arity signatures " + getSignatureList(varArgMethods) + " of the method " + - parent.getName() + " match the argument types " + argTypesString(argTypes)); - } - - private MethodHandle getAmbiguousMethodThrower(final Class[] argTypes, final List methods) { - return adaptThrower(MethodHandles.insertArguments(THROW_AMBIGUOUS_METHOD, 0, this, argTypes, methods)); - } - - private MethodHandle adaptThrower(final MethodHandle rawThrower) { - return MethodHandles.dropArguments(rawThrower, 0, callSiteType.parameterList()).asType(callSiteType); - } - - private static final MethodHandle THROW_AMBIGUOUS_METHOD = Lookup.findOwnSpecial(MethodHandles.lookup(), - "throwAmbiguousMethod", void.class, Class[].class, List.class); - - @SuppressWarnings("unused") - private void throwAmbiguousMethod(final Class[] argTypes, final List methods) throws NoSuchMethodException { - final String arity = methods.get(0).isVarargsCollector() ? "variable" : "fixed"; - throw new NoSuchMethodException("Can't unambiguously select between " + arity + " arity signatures " + - getSignatureList(methods) + " of the method " + parent.getName() + " for argument types " + - argTypesString(argTypes)); - } - - private static String argTypesString(final Class[] classes) { - final StringBuilder b = new StringBuilder().append('['); - appendTypes(b, classes, false); - return b.append(']').toString(); - } - - private static String getSignatureList(final List methods) { - final StringBuilder b = new StringBuilder().append('['); - final Iterator it = methods.iterator(); - if(it.hasNext()) { - appendSig(b, it.next()); - while(it.hasNext()) { - appendSig(b.append(", "), it.next()); - } - } - return b.append(']').toString(); - } - - private static void appendSig(final StringBuilder b, final MethodHandle m) { - b.append('('); - appendTypes(b, m.type().parameterArray(), m.isVarargsCollector()); - b.append(')'); - } - - private static void appendTypes(final StringBuilder b, final Class[] classes, final boolean varArg) { - final int l = classes.length; - if(!varArg) { - if(l > 1) { - b.append(classes[1].getCanonicalName()); - for(int i = 2; i < l; ++i) { - b.append(", ").append(classes[i].getCanonicalName()); - } - } - } else { - for(int i = 1; i < l - 1; ++i) { - b.append(classes[i].getCanonicalName()).append(", "); - } - b.append(classes[l - 1].getComponentType().getCanonicalName()).append("..."); - } - } - - private static Class getCommonReturnType(final List methodHandles) { - final Iterator it = methodHandles.iterator(); - Class retType = it.next().type().returnType(); - while(it.hasNext()) { - retType = InternalTypeUtilities.getCommonLosslessConversionType(retType, it.next().type().returnType()); - } - return retType; - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +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.invoke.MethodHandle; -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(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. - */ -class SimpleDynamicMethod extends SingleDynamicMethod { - private final MethodHandle target; - private final boolean constructor; - - /** - * Creates a new simple dynamic method, with a name constructed from the class name, method name, and handle - * signature. - * - * @param target the target method handle - * @param clazz the class declaring the method - * @param name the simple name of the method - */ - SimpleDynamicMethod(final MethodHandle target, final Class clazz, final String name) { - this(target, clazz, name, false); - } - - /** - * Creates a new simple dynamic method, with a name constructed from the class name, method name, and handle - * signature. - * - * @param target the target method handle - * @param clazz the class declaring the method - * @param name the simple name of the method - * @param constructor does this represent a constructor? - */ - SimpleDynamicMethod(final MethodHandle target, final Class clazz, final String name, final boolean constructor) { - super(getName(target, clazz, name, constructor)); - this.target = target; - this.constructor = constructor; - } - - private static String getName(final MethodHandle target, final Class clazz, final String name, final boolean constructor) { - return getMethodNameWithSignature(target.type(), constructor ? name : getClassAndMethodName(clazz, name), !constructor); - } - - @Override - boolean isVarArgs() { - return target.isVarargsCollector(); - } - - @Override - MethodType getMethodType() { - return target.type(); - } - - @Override - MethodHandle getTarget(final CallSiteDescriptor desc) { - return target; - } - - @Override - boolean isConstructor() { - return constructor; - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,312 +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.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.reflect.Array; -import java.util.StringTokenizer; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.LinkerServices; -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 - * target method to a call site type (including mapping variable arity methods to a call site signature with different - * arity). - */ -abstract class SingleDynamicMethod extends DynamicMethod { - - private static final MethodHandle CAN_CONVERT_TO = Lookup.findOwnStatic(MethodHandles.lookup(), "canConvertTo", boolean.class, LinkerServices.class, Class.class, Object.class); - - SingleDynamicMethod(final String name) { - super(name); - } - - /** - * Returns true if this method is variable arity. - * @return true if this method is variable arity. - */ - abstract boolean isVarArgs(); - - /** - * Returns this method's native type. - * @return this method's native type. - */ - abstract MethodType getMethodType(); - - /** - * 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(CallSiteDescriptor desc); - - @Override - MethodHandle getInvocation(final CallSiteDescriptor callSiteDescriptor, final LinkerServices linkerServices) { - return getInvocation(getTarget(callSiteDescriptor), callSiteDescriptor.getMethodType(), - linkerServices); - } - - @Override - SingleDynamicMethod getMethodForExactParamTypes(final String paramTypes) { - return typeMatchesDescription(paramTypes, getMethodType()) ? this : null; - } - - @Override - boolean contains(final SingleDynamicMethod method) { - return getMethodType().parameterList().equals(method.getMethodType().parameterList()); - } - - static String getMethodNameWithSignature(final MethodType type, final String methodName, final boolean withReturnType) { - final String typeStr = type.toString(); - final int retTypeIndex = typeStr.lastIndexOf(')') + 1; - int secondParamIndex = typeStr.indexOf(',') + 1; - if(secondParamIndex == 0) { - secondParamIndex = retTypeIndex - 1; - } - final StringBuilder b = new StringBuilder(); - if (withReturnType) { - b.append(typeStr, retTypeIndex, typeStr.length()).append(' '); - } - return b.append(methodName).append('(').append(typeStr, secondParamIndex, retTypeIndex).toString(); - } - - /** - * Given a method handle and a call site type, adapts the method handle to the call site type. Performs type - * conversions as needed using the specified linker services, and in case that the method handle is a vararg - * collector, matches it to the arity of the call site. The type of the return value is only changed if it can be - * converted using a conversion that loses neither precision nor magnitude, see - * {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)}. - * @param target the method handle to adapt - * @param callSiteType the type of the call site - * @param linkerServices the linker services used for type conversions - * @return the adapted method handle. - */ - static MethodHandle getInvocation(final MethodHandle target, final MethodType callSiteType, final LinkerServices linkerServices) { - final MethodHandle filteredTarget = linkerServices.filterInternalObjects(target); - final MethodType methodType = filteredTarget.type(); - final int paramsLen = methodType.parameterCount(); - final boolean varArgs = target.isVarargsCollector(); - final MethodHandle fixTarget = varArgs ? filteredTarget.asFixedArity() : filteredTarget; - final int fixParamsLen = varArgs ? paramsLen - 1 : paramsLen; - final int argsLen = callSiteType.parameterCount(); - if(argsLen < fixParamsLen) { - // Less actual arguments than number of fixed declared arguments; can't invoke. - return null; - } - // Method handle has the same number of fixed arguments as the call site type - if(argsLen == fixParamsLen) { - // Method handle that matches the number of actual arguments as the number of fixed arguments - final MethodHandle matchedMethod; - if(varArgs) { - // If vararg, add a zero-length array of the expected type as the last argument to signify no variable - // arguments. - matchedMethod = MethodHandles.insertArguments(fixTarget, fixParamsLen, Array.newInstance( - methodType.parameterType(fixParamsLen).getComponentType(), 0)); - } else { - // Otherwise, just use the method - matchedMethod = fixTarget; - } - return createConvertingInvocation(matchedMethod, linkerServices, callSiteType); - } - - // What's below only works for varargs - if(!varArgs) { - return null; - } - - final Class varArgType = methodType.parameterType(fixParamsLen); - // Handle a somewhat sinister corner case: caller passes exactly one argument in the vararg position, and we - // must handle both a prepacked vararg array as well as a genuine 1-long vararg sequence. - if(argsLen == paramsLen) { - final Class callSiteLastArgType = callSiteType.parameterType(fixParamsLen); - if(varArgType.isAssignableFrom(callSiteLastArgType)) { - // Call site signature guarantees we'll always be passed a single compatible array; just link directly - // to the method, introducing necessary conversions. Also, preserve it being a variable arity method. - return createConvertingInvocation(filteredTarget, linkerServices, callSiteType).asVarargsCollector( - callSiteLastArgType); - } - - // This method handle takes the single argument and packs it into a newly allocated single-element array. It - // will be used when the incoming argument can't be converted to the vararg array type (the "vararg packer" - // method). - final MethodHandle varArgCollectingInvocation = createConvertingInvocation(collectArguments(fixTarget, - argsLen), linkerServices, callSiteType); - - // Is call site type assignable from an array type (e.g. Object:int[], or Object[]:String[]) - final boolean isAssignableFromArray = callSiteLastArgType.isAssignableFrom(varArgType); - // Do we have a custom conversion that can potentially convert the call site type to an array? - final boolean isCustomConvertible = linkerServices.canConvert(callSiteLastArgType, varArgType); - if(!isAssignableFromArray && !isCustomConvertible) { - // Call site signature guarantees the argument can definitely not be converted to an array (i.e. it is - // primitive), and no conversion can help with it either. Link immediately to a vararg-packing method - // handle. - return varArgCollectingInvocation; - } - - // This method handle employs language-specific conversions to convert the last argument into an array of - // vararg type. - final MethodHandle arrayConvertingInvocation = createConvertingInvocation(MethodHandles.filterArguments( - fixTarget, fixParamsLen, linkerServices.getTypeConverter(callSiteLastArgType, varArgType)), - linkerServices, callSiteType); - - // This method handle determines whether the value can be converted to the array of vararg type using a - // language-specific conversion. - final MethodHandle canConvertArgToArray = MethodHandles.insertArguments(CAN_CONVERT_TO, 0, linkerServices, - varArgType); - - // This one adjusts the previous one for the location of the argument and the call site type. - final MethodHandle canConvertLastArgToArray = MethodHandles.dropArguments(canConvertArgToArray, 0, - MethodType.genericMethodType(fixParamsLen).parameterList()).asType(callSiteType.changeReturnType(boolean.class)); - - // This one takes the previous ones and combines them into a method handle that converts the argument into - // a vararg array when it can, otherwise falls back to the vararg packer. - final MethodHandle convertToArrayWhenPossible = MethodHandles.guardWithTest(canConvertLastArgToArray, - arrayConvertingInvocation, varArgCollectingInvocation); - - if(isAssignableFromArray) { - return MethodHandles.guardWithTest( - // Is incoming parameter already a compatible array? - Guards.isInstance(varArgType, fixParamsLen, callSiteType), - // Yes: just pass it to the method - createConvertingInvocation(fixTarget, linkerServices, callSiteType), - // No: either go through a custom conversion, or if it is not possible, go directly to the - // vararg packer. - isCustomConvertible ? convertToArrayWhenPossible : varArgCollectingInvocation); - } - - // Just do the custom conversion with fallback to the vararg packer logic. - assert isCustomConvertible; - return convertToArrayWhenPossible; - } - - // Remaining case: more than one vararg. - return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType); - } - - @SuppressWarnings("unused") - private static boolean canConvertTo(final LinkerServices linkerServices, final Class to, final Object obj) { - return obj == null ? false : linkerServices.canConvert(obj.getClass(), to); - } - - /** - * Creates a method handle out of the original target that will collect the varargs for the exact component type of - * the varArg array. Note that this will nicely trigger language-specific type converters for exactly those varargs - * for which it is necessary when later passed to linkerServices.convertArguments(). - * - * @param target the original method handle - * @param parameterCount the total number of arguments in the new method handle - * @return a collecting method handle - */ - static MethodHandle collectArguments(final MethodHandle target, final int parameterCount) { - final MethodType methodType = target.type(); - final int fixParamsLen = methodType.parameterCount() - 1; - final Class arrayType = methodType.parameterType(fixParamsLen); - return target.asCollector(arrayType, parameterCount - fixParamsLen); - } - - private static MethodHandle createConvertingInvocation(final MethodHandle sizedMethod, - final LinkerServices linkerServices, final MethodType callSiteType) { - return linkerServices.asTypeLosslessReturn(sizedMethod, callSiteType); - } - - private static boolean typeMatchesDescription(final String paramTypes, final MethodType type) { - final StringTokenizer tok = new StringTokenizer(paramTypes, ", "); - for(int i = 1; i < type.parameterCount(); ++i) { // i = 1 as we ignore the receiver - if(!(tok.hasMoreTokens() && typeNameMatches(tok.nextToken(), type.parameterType(i)))) { - return false; - } - } - return !tok.hasMoreTokens(); - } - - private static boolean typeNameMatches(final String typeName, final Class type) { - return typeName.equals(typeName.indexOf('.') == -1 ? type.getSimpleName() : type.getCanonicalName()); - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,179 +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.io.Serializable; -import java.util.Objects; -import jdk.internal.dynalink.StandardOperation; - -/** - * 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 final class StaticClass implements Serializable { - private static final ClassValue staticClasses = new ClassValue() { - @Override - protected StaticClass computeValue(final Class type) { - return new StaticClass(type); - } - }; - - private static final long serialVersionUID = 1L; - - /** - * The runtime {@code Class} object whose static members this - * {@code StaticClass} represents. - */ - private final Class clazz; - - /*private*/ StaticClass(final Class clazz) { - this.clazz = Objects.requireNonNull(clazz); - } - - /** - * Retrieves the {@link StaticClass} instance for the specified class. - * @param clazz the class for which the static facet is requested. - * @return the {@link StaticClass} instance representing the specified class. - */ - public static StaticClass forClass(final Class clazz) { - return staticClasses.get(clazz); - } - - /** - * Returns the represented Java class. - * @return the represented Java class. - */ - public Class getRepresentedClass() { - return clazz; - } - - @Override - public String toString() { - return "StaticClass[" + clazz.getName() + "]"; - } - - /** - * Returns {@link #forClass(Class)} for the underlying {@code clazz} field - * ensuring that deserialization doesn't create non-canonical instances. - * @return {@link #forClass(Class)} for the underlying {@code clazz} field. - */ - private Object readResolve() { - return forClass(clazz); - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClassIntrospector.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/StaticClassIntrospector.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-2013 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package jdk.internal.dynalink.beans; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.util.HashMap; -import java.util.Map; - -class StaticClassIntrospector extends FacetIntrospector { - StaticClassIntrospector(final Class clazz) { - super(clazz, false); - } - - @Override - Map getInnerClassGetters() { - final Map map = new HashMap<>(); - for(final Class innerClass: membersLookup.getInnerClasses()) { - map.put(innerClass.getSimpleName(), editMethodHandle(MethodHandles.constant(StaticClass.class, - StaticClass.forClass(innerClass)))); - } - return map; - } - - @Override - MethodHandle editMethodHandle(final MethodHandle mh) { - return editStaticMethodHandle(mh); - } - - static MethodHandle editStaticMethodHandle(final MethodHandle mh) { - return dropReceiver(mh, Object.class); - } - - static MethodHandle editConstructorMethodHandle(final MethodHandle cmh) { - return dropReceiver(cmh, StaticClass.class); - } - - private static MethodHandle dropReceiver(final MethodHandle mh, final Class receiverClass) { - MethodHandle newHandle = MethodHandles.dropArguments(mh, 0, receiverClass); - // NOTE: this is a workaround for the fact that dropArguments doesn't preserve vararg collector state. - if(mh.isVarargsCollector() && !newHandle.isVarargsCollector()) { - final MethodType type = mh.type(); - newHandle = newHandle.asVarargsCollector(type.parameterType(type.parameterCount() - 1)); - } - return newHandle; - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,216 +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.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.reflect.Array; -import java.util.Arrays; -import java.util.Set; -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.linker.support.Lookup; - -/** - * Provides a linker for the {@link StaticClass} objects. - */ -class StaticClassLinker implements TypeBasedGuardingDynamicLinker { - private static final ClassValue linkers = new ClassValue() { - @Override - protected SingleClassStaticsLinker computeValue(final Class clazz) { - return new SingleClassStaticsLinker(clazz); - } - }; - - private static class SingleClassStaticsLinker extends AbstractJavaLinker { - private final DynamicMethod constructor; - - SingleClassStaticsLinker(final Class clazz) { - super(clazz, IS_CLASS.bindTo(clazz)); - // Map "staticClassObject.class" to StaticClass.getRepresentedClass(). Some adventurous soul could subclass - // StaticClass, so we use INSTANCE_OF validation instead of EXACT_CLASS. - setPropertyGetter("class", GET_CLASS, ValidationType.INSTANCE_OF); - constructor = createConstructorMethod(clazz); - } - - /** - * Creates a dynamic method containing all overloads of a class' public constructor - * @param clazz the target class - * @return a dynamic method containing all overloads of a class' public constructor. If the class has no public - * constructors, returns null. - */ - private static DynamicMethod createConstructorMethod(final Class clazz) { - if(clazz.isArray()) { - final MethodHandle boundArrayCtor = ARRAY_CTOR.bindTo(clazz.getComponentType()); - return new SimpleDynamicMethod(StaticClassIntrospector.editConstructorMethodHandle( - boundArrayCtor.asType(boundArrayCtor.type().changeReturnType(clazz))), clazz, ""); - } - if(CheckRestrictedPackage.isRestrictedClass(clazz)) { - return null; - } - return createDynamicMethod(Arrays.asList(clazz.getConstructors()), clazz, ""); - } - - @Override - FacetIntrospector createFacetIntrospector() { - return new StaticClassIntrospector(clazz); - } - - @Override - public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) - throws Exception { - final GuardedInvocation gi = super.getGuardedInvocation(request, linkerServices); - if(gi != null) { - return gi; - } - final CallSiteDescriptor desc = request.getCallSiteDescriptor(); - 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())); - } - } - return null; - } - - @Override - SingleDynamicMethod getConstructorMethod(final String signature) { - return constructor != null? constructor.getMethodForExactParamTypes(signature) : null; - } - } - - static Object getConstructorMethod(final Class clazz, final String signature) { - return linkers.get(clazz).getConstructorMethod(signature); - } - - static Set getReadableStaticPropertyNames(final Class clazz) { - return linkers.get(clazz).getReadablePropertyNames(); - } - - static Set getWritableStaticPropertyNames(final Class clazz) { - return linkers.get(clazz).getWritablePropertyNames(); - } - - static Set getStaticMethodNames(final Class clazz) { - return linkers.get(clazz).getMethodNames(); - } - - @Override - public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception { - final Object receiver = request.getReceiver(); - if(receiver instanceof StaticClass) { - return linkers.get(((StaticClass)receiver).getRepresentedClass()).getGuardedInvocation(request, - linkerServices); - } - return null; - } - - @Override - public boolean canLinkType(final Class type) { - return type == StaticClass.class; - } - - /*private*/ static final MethodHandle GET_CLASS; - /*private*/ static final MethodHandle IS_CLASS; - /*private*/ static final MethodHandle ARRAY_CTOR = Lookup.PUBLIC.findStatic(Array.class, "newInstance", - MethodType.methodType(Object.class, Class.class, int.class)); - - static { - final Lookup lookup = new Lookup(MethodHandles.lookup()); - GET_CLASS = lookup.findVirtual(StaticClass.class, "getRepresentedClass", MethodType.methodType(Class.class)); - IS_CLASS = lookup.findOwnStatic("isClass", Boolean.TYPE, Class.class, Object.class); - } - - @SuppressWarnings("unused") - private static boolean isClass(final Class clazz, final Object obj) { - return obj instanceof StaticClass && ((StaticClass)obj).getRepresentedClass() == clazz; - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/messages.properties --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/messages.properties Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -# Copyright 2009-2013 Attila Szegedi -# -# Licensed under either the Apache License, Version 2.0 (the "Apache -# License") or the BSD License (the "BSD License"), with licensee -# being free to choose either of the two at their discretion. -# -# You may not use this file except in compliance with either the Apache -# License or the BSD License. -# -# A copy of the BSD License is available in the root directory of the -# source distribution of the project under the file name -# "Dynalink-License-BSD.txt". -# -# A copy of the Apache License is available in the root directory of the -# source distribution of the project under the file name -# "Dynalink-License-Apache-2.0.txt". Alternatively, you may obtain a -# copy of the Apache License at -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See your chosen License for the specific language governing permissions -# and limitations under that License. - -couldNotDiscoverAccessibleMethods=Could not discover accessible methods of class {0}, trying its superclasses and interfaces. \ No newline at end of file diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/package-info.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/beans/package-info.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/internal/AccessControlContextFactory.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/internal/AccessControlContextFactory.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/internal/InternalTypeUtilities.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/internal/InternalTypeUtilities.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -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 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +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; - - -/** - * 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 { - /** - * Enumeration of possible outcomes of comparing one conversion to another. - */ - enum Comparison { - /** The conversions cannot be compared. **/ - INDETERMINATE, - /** The first conversion is better than the second one. **/ - TYPE_1_BETTER, - /** The second conversion is better than the first one. **/ - TYPE_2_BETTER, - } - - /** - * Determines which of the two target types is the preferred conversion - * target from a source type. - * @param sourceType the source type. - * @param targetType1 one potential target type - * @param targetType2 another potential target type. - * @return one of Comparison constants that establish which - if any - of - * the target types is preferred for the conversion. - */ - public Comparison compareConversion(Class sourceType, Class targetType1, Class targetType2); -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,483 +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; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.invoke.SwitchPoint; -import java.util.List; -import java.util.Objects; -import java.util.function.Supplier; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.support.Guards; - -/** - * 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; - private final MethodHandle guard; - private final Class exception; - private final SwitchPoint[] switchPoints; - - /** - * 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. - * @throws NullPointerException if invocation is null. - */ - public GuardedInvocation(final MethodHandle invocation) { - this(invocation, null, (SwitchPoint)null, null); - } - - /** - * 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 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) { - this(invocation, guard, (SwitchPoint)null, null); - } - - /** - * 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. 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) { - this(invocation, null, switchPoint, null); - } - - /** - * 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 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) { - this(invocation, guard, switchPoint, null); - } - - /** - * 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 be - * compatible with the {@code invocation} handle as per - * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. - * For some useful guards, check out the {@link Guards} class. It can be - * null. If it and the switch point and the exception are all null, this - * represents an unconditional invocation. - * @param switchPoint the optional switch point that can be used to - * invalidate this linkage. - * @param exception the optional exception type that is when thrown by the - * invocation also invalidates it. - * @throws NullPointerException if invocation is null. - */ - public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint switchPoint, final Class exception) { - this.invocation = Objects.requireNonNull(invocation); - this.guard = guard; - this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint }; - this.exception = exception; - } - - /** - * 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 be - * compatible with the {@code invocation} handle as per - * {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}. - * For some useful guards, check out the {@link Guards} class. It can be - * null. If it and the exception are both null, and no switch points were - * specified, this represents an unconditional invocation. - * @param switchPoints optional switch points that can be used to - * invalidate this linkage. - * @param exception the optional exception type that is when thrown by the - * invocation also invalidates it. - * @throws NullPointerException if invocation is null. - */ - public GuardedInvocation(final MethodHandle invocation, final MethodHandle guard, final SwitchPoint[] switchPoints, final Class exception) { - this.invocation = Objects.requireNonNull(invocation); - this.guard = guard; - this.switchPoints = switchPoints == null ? null : switchPoints.clone(); - this.exception = exception; - } - - /** - * Returns the invocation method handle. - * - * @return the invocation method handle. It will never be null. - */ - public MethodHandle getInvocation() { - return invocation; - } - - /** - * Returns the guard method handle. - * - * @return the guard method handle. Can be null. - */ - public MethodHandle getGuard() { - return guard; - } - - /** - * Returns the switch points that can be used to invalidate the linkage of - * this invocation handle. - * - * @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 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. - */ - public Class getException() { - return exception; - } - - /** - * 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) { - return false; - } - for (final SwitchPoint sp : switchPoints) { - if (sp.hasBeenInvalidated()) { - return true; - } - } - return false; - } - - /** - * Creates a new guarded invocation with different methods, preserving the switch point. - * - * @param newInvocation the new invocation - * @param newGuard the new guard - * @return a new guarded invocation with the replaced methods and the same switch point as this invocation. - */ - public GuardedInvocation replaceMethods(final MethodHandle newInvocation, final MethodHandle newGuard) { - return new GuardedInvocation(newInvocation, newGuard, switchPoints, exception); - } - - /** - * 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) { - return this; - } - - final SwitchPoint[] newSwitchPoints; - if (switchPoints != null) { - newSwitchPoints = new SwitchPoint[switchPoints.length + 1]; - System.arraycopy(switchPoints, 0, newSwitchPoints, 0, switchPoints.length); - newSwitchPoints[switchPoints.length] = newSwitchPoint; - } else { - newSwitchPoints = new SwitchPoint[] { newSwitchPoint }; - } - - return new GuardedInvocation(invocation, guard, newSwitchPoints, exception); - } - - private GuardedInvocation replaceMethodsOrThis(final MethodHandle newInvocation, final MethodHandle newGuard) { - if (newInvocation == invocation && newGuard == guard) { - return this; - } - return replaceMethods(newInvocation, newGuard); - } - - /** - * Changes the type of the invocation, as if - * {@link MethodHandle#asType(MethodType)} was applied to its invocation - * and its guard, if it has one (with return type changed to boolean, and - * parameter count potentially truncated for the guard). If the invocation - * already is of the required type, returns this object. - * @param newType the new type of the invocation. - * @return a guarded invocation with the new type applied to it. - */ - public GuardedInvocation asType(final MethodType newType) { - return replaceMethodsOrThis(invocation.asType(newType), guard == null ? null : Guards.asType(guard, newType)); - } - - /** - * Changes the type of the invocation, as if - * {@link LinkerServices#asType(MethodHandle, MethodType)} was applied to - * its invocation and its guard, if it has one (with return type changed to - * boolean, and parameter count potentially truncated for the guard). If the - * invocation already is of the required type, returns this object. - * @param linkerServices the linker services to use for the conversion - * @param newType the new type of the invocation. - * @return a guarded invocation with the new type applied to it. - */ - public GuardedInvocation asType(final LinkerServices linkerServices, final MethodType newType) { - return replaceMethodsOrThis(linkerServices.asType(invocation, newType), guard == null ? null : - Guards.asType(linkerServices, guard, newType)); - } - - /** - * Changes the type of the invocation, as if - * {@link 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. - */ - public GuardedInvocation asTypeSafeReturn(final LinkerServices linkerServices, final MethodType newType) { - return replaceMethodsOrThis(linkerServices.asTypeLosslessReturn(invocation, newType), guard == null ? null : - Guards.asType(linkerServices, guard, newType)); - } - - /** - * Changes the type of the invocation, as if - * {@link MethodHandle#asType(MethodType)} was applied to its invocation - * and its guard, if it has one (with return type changed to boolean for - * guard). If the invocation already is of the required type, returns this - * object. - * @param desc a call descriptor whose method type is adapted. - * @return a guarded invocation with the new type applied to it. - */ - public GuardedInvocation asType(final CallSiteDescriptor desc) { - return asType(desc.getMethodType()); - } - - /** - * 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 - */ - public GuardedInvocation filterArguments(final int pos, final MethodHandle... filters) { - return replaceMethods(MethodHandles.filterArguments(invocation, pos, filters), guard == null ? null : - MethodHandles.filterArguments(guard, pos, filters)); - } - - /** - * Makes an invocation that drops arguments in both the invocation and the - * guard (if there is one) 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 - */ - public GuardedInvocation dropArguments(final int pos, final List> valueTypes) { - return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null : - MethodHandles.dropArguments(guard, pos, valueTypes)); - } - - /** - * Makes an invocation that drops arguments in both the invocation and the - * guard (if there is one) 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 - */ - public GuardedInvocation dropArguments(final int pos, final Class... valueTypes) { - return replaceMethods(MethodHandles.dropArguments(invocation, pos, valueTypes), guard == null ? null : - MethodHandles.dropArguments(guard, pos, valueTypes)); - } - - - /** - * 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) { - return compose(fallback, fallback, fallback); - } - - /** - * 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) { - final MethodHandle guarded = - guard == null ? - invocation : - MethodHandles.guardWithTest( - guard, - invocation, - guardFallback); - - final MethodHandle catchGuarded = - exception == null ? - guarded : - MethodHandles.catchException( - guarded, - exception, - MethodHandles.dropArguments( - catchFallback, - 0, - exception)); - - if (switchPoints == null) { - return catchGuarded; - } - - MethodHandle spGuarded = catchGuarded; - for (final SwitchPoint sp : switchPoints) { - spGuarded = sp.guardWithTest(spGuarded, switchpointFallback); - } - - return spGuarded; - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocationTransformer.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardedInvocationTransformer.java Wed Jul 05 21:04:26 2017 +0200 +++ /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.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 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-2013 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package jdk.internal.dynalink.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 - * 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. - * - * @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 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) - throws Exception; -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingDynamicLinkerExporter.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/GuardingDynamicLinkerExporter.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -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 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +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; - -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-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 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. - * @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 GuardedInvocation convertToType(Class sourceType, Class targetType, Supplier lookupSupplier) throws Exception; -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-2013 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package jdk.internal.dynalink.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 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 { - /** - * Returns the call site descriptor for the call site being linked. - * - * @return the call site descriptor for the call site being linked. - */ - public CallSiteDescriptor getCallSiteDescriptor(); - - /** - * Returns the arguments for the invocation being linked. The returned array - * 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 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 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, though, and linkers are - * allowed to ignore this property. - * @return true if the call site is considered unstable. - */ - public boolean isCallSiteUnstable(); - - /** - * Returns a request identical to this one with call site descriptor and arguments replaced with the ones specified. - * - * @param callSiteDescriptor the new call site descriptor - * @param arguments the new arguments - * @return a new request identical to this one, except with the call site descriptor and arguments replaced with the - * specified ones. - */ - public LinkRequest replaceArguments(CallSiteDescriptor callSiteDescriptor, Object... arguments); -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,220 +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; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import jdk.internal.dynalink.DynamicLinker; -import jdk.internal.dynalink.DynamicLinkerFactory; -import jdk.internal.dynalink.linker.ConversionComparator.Comparison; -import jdk.internal.dynalink.linker.support.TypeUtilities; - -/** - * 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 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. - */ - public MethodHandle asType(MethodHandle handle, MethodType fromType); - - /** - * 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. - */ - public default MethodHandle asTypeLosslessReturn(final MethodHandle handle, final MethodType fromType) { - final Class handleReturnType = handle.type().returnType(); - return asType(handle, TypeUtilities.isConvertibleWithoutLoss(handleReturnType, fromType.returnType()) ? - fromType : fromType.changeReturnType(handleReturnType)); - } - - /** - * 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. - */ - 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 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 - * @return true if there can be a conversion, false if there can not. - */ - public boolean canConvert(Class from, Class to); - - /** - * 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 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. - * @param sourceType the source type. - * @param targetType1 one potential target type - * @param targetType2 another potential target type. - * @return one of Comparison constants that establish which – if any - * – of the target types is preferable for the conversion. - */ - public Comparison compareConversion(Class sourceType, Class targetType1, Class targetType2); - - /** - * 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. - */ - public MethodHandle filterInternalObjects(final MethodHandle target); -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-2015 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package jdk.internal.dynalink.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. - * @param target the method handle being transformed. - * @return transformed method handle. - */ - public MethodHandle transform(final MethodHandle target); -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2014 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package jdk.internal.dynalink.linker; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; -import jdk.internal.dynalink.DynamicLinkerFactory; - -/** - * 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. - * @param target target method handle - * @param newType new type - * @return target converted to the new type. - */ - public MethodHandle asType(final MethodHandle target, final MethodType newType); -} diff -r 5ac6287ec71a -r 84eaea8d0574 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 Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,103 +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; - -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). 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, - * see {@link CompositeTypeBasedGuardingDynamicLinker}. - */ -public interface TypeBasedGuardingDynamicLinker extends GuardingDynamicLinker { - /** - * Returns true if the linker can link an invocation where the first argument (receiver) is of the specified type. - * - * @param type the type to link - * @return true if the linker can link calls for the receiver type, or false otherwise. - */ - public boolean canLinkType(Class type); -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/package-info.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/package-info.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-2013 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - *

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

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

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

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

- * @since 1.9 - */ -@jdk.Exported -package jdk.internal.dynalink.linker; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/CompositeGuardingDynamicLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/CompositeGuardingDynamicLinker.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +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.support; - -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 { - - private final GuardingDynamicLinker[] linkers; - - /** - * Creates a new composite linker. - * - * @param linkers a list of component linkers. - * @throws NullPointerException if {@code linkers} or any of its elements - * are null. - */ - public CompositeGuardingDynamicLinker(final Iterable linkers) { - final List l = new LinkedList<>(); - for(final GuardingDynamicLinker linker: linkers) { - l.add(Objects.requireNonNull(linker)); - } - this.linkers = l.toArray(new GuardingDynamicLinker[l.size()]); - } - - /** - * Delegates the call to its component linkers. The first non-null value - * returned from a component linker is returned. If no component linker - * returns a non-null invocation, null is returned. - * @param linkRequest the object describing the request for linking a - * particular invocation - * @param linkerServices linker services - * @return the first non-null return value from a component linker, or null - * if none of the components returned a non-null. - */ - @Override - public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) - throws Exception { - for(final GuardingDynamicLinker linker: linkers) { - final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices); - if(invocation != null) { - return invocation; - } - } - return null; - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/CompositeTypeBasedGuardingDynamicLinker.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,237 +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.support; - -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 { - // Using a separate static class instance so there's no strong reference from the class value back to the composite - // linker. - private static class ClassToLinker extends ClassValue> { - private static final List NO_LINKER = Collections.emptyList(); - private final TypeBasedGuardingDynamicLinker[] linkers; - private final List[] singletonLinkers; - - @SuppressWarnings({"unchecked", "rawtypes"}) - ClassToLinker(final TypeBasedGuardingDynamicLinker[] linkers) { - this.linkers = linkers; - singletonLinkers = new List[linkers.length]; - for(int i = 0; i < linkers.length; ++i) { - singletonLinkers[i] = Collections.singletonList(linkers[i]); - } - } - - @SuppressWarnings("fallthrough") - @Override - protected List computeValue(final Class clazz) { - List list = NO_LINKER; - for(int i = 0; i < linkers.length; ++i) { - final TypeBasedGuardingDynamicLinker linker = linkers[i]; - if(linker.canLinkType(clazz)) { - switch(list.size()) { - case 0: { - list = singletonLinkers[i]; - break; - } - case 1: { - list = new LinkedList<>(list); - } - default: { - list.add(linker); - } - } - } - } - return list; - } - } - - private final ClassValue> classToLinker; - - /** - * Creates a new composite type-based linker. - * - * @param linkers the component linkers - * @throws NullPointerException if {@code linkers} or any of its elements - * are null. - */ - public CompositeTypeBasedGuardingDynamicLinker(final Iterable linkers) { - final List l = new LinkedList<>(); - for(final TypeBasedGuardingDynamicLinker linker: linkers) { - l.add(Objects.requireNonNull(linker)); - } - this.classToLinker = new ClassToLinker(l.toArray(new TypeBasedGuardingDynamicLinker[l.size()])); - } - - /** - * Returns true if at least one of the composite linkers returns true from - * {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)} for the type. - * @param type the type to link - * @return true true if at least one of the composite linkers returns true - * from {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)}, false - * otherwise. - */ - @Override - public boolean canLinkType(final Class type) { - return !classToLinker.get(type).isEmpty(); - } - - @Override - public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) - throws Exception { - final Object obj = linkRequest.getReceiver(); - if(obj == null) { - return null; - } - for(final TypeBasedGuardingDynamicLinker linker: classToLinker.get(obj.getClass())) { - final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices); - if(invocation != null) { - return invocation; - } - } - return null; - } - - /** - * Optimizes a list of type-based linkers. If a group of adjacent linkers in - * the list all implement {@link TypeBasedGuardingDynamicLinker}, they will - * be replaced with a single instance of - * {@link CompositeTypeBasedGuardingDynamicLinker} that contains them. - * - * @param linkers the list of linkers to optimize - * @return the optimized list - * @throws NullPointerException if {@code linkers} or any of its elements - * are null. - */ - public static List optimize(final Iterable linkers) { - final List llinkers = new LinkedList<>(); - final List tblinkers = new LinkedList<>(); - for(final GuardingDynamicLinker linker: linkers) { - Objects.requireNonNull(linker); - if(linker instanceof TypeBasedGuardingDynamicLinker) { - tblinkers.add((TypeBasedGuardingDynamicLinker)linker); - } else { - addTypeBased(llinkers, tblinkers); - llinkers.add(linker); - } - } - addTypeBased(llinkers, tblinkers); - return llinkers; - } - - private static void addTypeBased(final List llinkers, - final List tblinkers) { - switch(tblinkers.size()) { - case 0: { - break; - } - case 1: { - llinkers.addAll(tblinkers); - tblinkers.clear(); - break; - } - default: { - llinkers.add(new CompositeTypeBasedGuardingDynamicLinker(tblinkers)); - tblinkers.clear(); - break; - } - } - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/DefaultInternalObjectFilter.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/DefaultInternalObjectFilter.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,189 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-2015 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package jdk.internal.dynalink.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/Guards.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/Guards.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,338 +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.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/Lookup.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/Lookup.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,401 +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.support; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; - -/** - * A wrapper around {@link java.lang.invoke.MethodHandles.Lookup} that masks - * checked exceptions. It is useful in those cases when you're looking up - * methods within your own codebase (therefore it is an error if they are not - * present). - */ -public final class Lookup { - private final MethodHandles.Lookup lookup; - - /** - * Creates a new instance, bound to an instance of - * {@link java.lang.invoke.MethodHandles.Lookup}. - * - * @param lookup the {@link java.lang.invoke.MethodHandles.Lookup} it delegates to. - */ - public Lookup(final MethodHandles.Lookup lookup) { - this.lookup = lookup; - } - - /** - * A canonical Lookup object that wraps {@link MethodHandles#publicLookup()}. - */ - public static final Lookup PUBLIC = new Lookup(MethodHandles.publicLookup()); - - /** - * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, - * converting any encountered {@link IllegalAccessException} into an - * {@link IllegalAccessError}. - * - * @param m the method to unreflect - * @return the unreflected method handle. - * @throws IllegalAccessError if the method is inaccessible. - */ - public MethodHandle unreflect(final Method m) { - return unreflect(lookup, m); - } - - /** - * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}, - * converting any encountered {@link IllegalAccessException} into an - * {@link IllegalAccessError}. - * - * @param lookup the lookup used to unreflect - * @param m the method to unreflect - * @return the unreflected method handle. - * @throws IllegalAccessError if the method is inaccessible. - */ - public static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) { - try { - return lookup.unreflect(m); - } catch(final IllegalAccessException e) { - final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect method " + m); - ee.initCause(e); - throw ee; - } - } - - /** - * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectGetter(Field)}, - * converting any encountered {@link IllegalAccessException} into an {@link IllegalAccessError}. - * - * @param f the field for which a getter is unreflected - * @return the unreflected field getter handle. - * @throws IllegalAccessError if the getter is inaccessible. - */ - public MethodHandle unreflectGetter(final Field f) { - try { - return lookup.unreflectGetter(f); - } catch(final IllegalAccessException e) { - final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect getter for field " + f); - ee.initCause(e); - throw ee; - } - } - - /** - * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findGetter(Class, String, Class)}, - * converting any encountered {@link IllegalAccessException} into an - * {@link IllegalAccessError} and {@link NoSuchFieldException} into a - * {@link NoSuchFieldError}. - * - * @param refc the class declaring the field - * @param name the name of the field - * @param type the type of the field - * @return the unreflected field getter handle. - * @throws IllegalAccessError if the field is inaccessible. - * @throws NoSuchFieldError if the field does not exist. - */ - public MethodHandle findGetter(final Classrefc, final String name, final Class type) { - try { - return lookup.findGetter(refc, name, type); - } catch(final IllegalAccessException e) { - final IllegalAccessError ee = new IllegalAccessError("Failed to access getter for field " + refc.getName() + - "." + name + " of type " + type.getName()); - ee.initCause(e); - throw ee; - } catch(final NoSuchFieldException e) { - final NoSuchFieldError ee = new NoSuchFieldError("Failed to find getter for field " + refc.getName() + - "." + name + " of type " + type.getName()); - ee.initCause(e); - throw ee; - } - } - - /** - * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectSetter(Field)}, - * converting any encountered {@link IllegalAccessException} into an - * {@link IllegalAccessError}. - * - * @param f the field for which a setter is unreflected - * @return the unreflected field setter handle. - * @throws IllegalAccessError if the field is inaccessible. - * @throws NoSuchFieldError if the field does not exist. - */ - public MethodHandle unreflectSetter(final Field f) { - try { - return lookup.unreflectSetter(f); - } catch(final IllegalAccessException e) { - final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect setter for field " + f); - ee.initCause(e); - throw ee; - } - } - - /** - * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, - * converting any encountered {@link IllegalAccessException} into an - * {@link IllegalAccessError}. - * - * @param c the constructor to unreflect - * @return the unreflected constructor handle. - * @throws IllegalAccessError if the constructor is inaccessible. - */ - public MethodHandle unreflectConstructor(final Constructor c) { - return unreflectConstructor(lookup, c); - } - - /** - * Performs a {@link java.lang.invoke.MethodHandles.Lookup#unreflectConstructor(Constructor)}, - * converting any encountered {@link IllegalAccessException} into an - * {@link IllegalAccessError}. - * - * @param lookup the lookup used to unreflect - * @param c the constructor to unreflect - * @return the unreflected constructor handle. - * @throws IllegalAccessError if the constructor is inaccessible. - */ - public static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor c) { - try { - return lookup.unreflectConstructor(c); - } catch(final IllegalAccessException e) { - final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect constructor " + c); - ee.initCause(e); - throw ee; - } - } - - /** - * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findSpecial(Class, String, MethodType, Class)} - * on the underlying lookup. Converts any encountered - * {@link IllegalAccessException} into an {@link IllegalAccessError} and - * {@link NoSuchMethodException} into a {@link NoSuchMethodError}. - * - * @param declaringClass class declaring the method - * @param name the name of the method - * @param type the type of the method - * @return a method handle for the method - * @throws IllegalAccessError if the method is inaccessible. - * @throws NoSuchMethodError if the method does not exist. - */ - public MethodHandle findSpecial(final Class declaringClass, final String name, final MethodType type) { - try { - return lookup.findSpecial(declaringClass, name, type, declaringClass); - } catch(final IllegalAccessException e) { - final IllegalAccessError ee = new IllegalAccessError("Failed to access special method " + methodDescription( - declaringClass, name, type)); - ee.initCause(e); - throw ee; - } catch(final NoSuchMethodException e) { - final NoSuchMethodError ee = new NoSuchMethodError("Failed to find special method " + methodDescription( - declaringClass, name, type)); - ee.initCause(e); - throw ee; - } - } - - private static String methodDescription(final Class declaringClass, final String name, final MethodType type) { - return declaringClass.getName() + "#" + name + type; - } - - /** - * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findStatic(Class, String, MethodType)} - * on the underlying lookup. Converts any encountered - * {@link IllegalAccessException} into an {@link IllegalAccessError} and - * {@link NoSuchMethodException} into a {@link NoSuchMethodError}. - * - * @param declaringClass class declaring the method - * @param name the name of the method - * @param type the type of the method - * @return a method handle for the method - * @throws IllegalAccessError if the method is inaccessible. - * @throws NoSuchMethodError if the method does not exist. - */ - public MethodHandle findStatic(final Class declaringClass, final String name, final MethodType type) { - try { - return lookup.findStatic(declaringClass, name, type); - } catch(final IllegalAccessException e) { - final IllegalAccessError ee = new IllegalAccessError("Failed to access static method " + methodDescription( - declaringClass, name, type)); - ee.initCause(e); - throw ee; - } catch(final NoSuchMethodException e) { - final NoSuchMethodError ee = new NoSuchMethodError("Failed to find static method " + methodDescription( - declaringClass, name, type)); - ee.initCause(e); - throw ee; - } - } - - /** - * Performs a {@link java.lang.invoke.MethodHandles.Lookup#findVirtual(Class, String, MethodType)} - * on the underlying lookup. Converts any encountered - * {@link IllegalAccessException} into an {@link IllegalAccessError} and - * {@link NoSuchMethodException} into a {@link NoSuchMethodError}. - * - * @param declaringClass class declaring the method - * @param name the name of the method - * @param type the type of the method - * @return a method handle for the method - * @throws IllegalAccessError if the method is inaccessible. - * @throws NoSuchMethodError if the method does not exist. - */ - public MethodHandle findVirtual(final Class declaringClass, final String name, final MethodType type) { - try { - return lookup.findVirtual(declaringClass, name, type); - } catch(final IllegalAccessException e) { - final IllegalAccessError ee = new IllegalAccessError("Failed to access virtual method " + methodDescription( - declaringClass, name, type)); - ee.initCause(e); - throw ee; - } catch(final NoSuchMethodException e) { - final NoSuchMethodError ee = new NoSuchMethodError("Failed to find virtual method " + methodDescription( - declaringClass, name, type)); - ee.initCause(e); - throw ee; - } - } - - /** - * Given a lookup, finds using {@link #findSpecial(Class, String, MethodType)} - * a method on that lookup's class. Useful in classes' code for convenient - * linking to their own privates. - * @param lookup the lookup for the class - * @param name the name of the method - * @param rtype the return type of the method - * @param ptypes the parameter types of the method - * @return the method handle for the method - */ - public static MethodHandle findOwnSpecial(final MethodHandles.Lookup lookup, final String name, final Class rtype, final Class... ptypes) { - return new Lookup(lookup).findOwnSpecial(name, rtype, ptypes); - } - - - /** - * Finds using {@link #findSpecial(Class, String, MethodType)} a method on - * that lookup's class. Useful in classes' code for convenient linking to - * their own privates. It's also more convenient than {@code findSpecial} - * in that you can just list the parameter types, and don't have to specify - * lookup class. - * @param name the name of the method - * @param rtype the return type of the method - * @param ptypes the parameter types of the method - * @return the method handle for the method - */ - public MethodHandle findOwnSpecial(final String name, final Class rtype, final Class... ptypes) { - return findSpecial(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes)); - } - - /** - * Given a lookup, finds using {@link #findStatic(Class, String, MethodType)} - * a method on that lookup's class. Useful in classes' code for convenient - * linking to their own privates. It's easier to use than {@code findStatic} - * in that you can just list the parameter types, and don't have to specify - * lookup class. - * @param lookup the lookup for the class - * @param name the name of the method - * @param rtype the return type of the method - * @param ptypes the parameter types of the method - * @return the method handle for the method - */ - public static MethodHandle findOwnStatic(final MethodHandles.Lookup lookup, final String name, final Class rtype, final Class... ptypes) { - return new Lookup(lookup).findOwnStatic(name, rtype, ptypes); - } - - /** - * Finds using {@link #findStatic(Class, String, MethodType)} a method on - * that lookup's class. Useful in classes' code for convenient linking to - * their own privates. It's easier to use than {@code findStatic} - * in that you can just list the parameter types, and don't have to specify - * lookup class. - * @param name the name of the method - * @param rtype the return type of the method - * @param ptypes the parameter types of the method - * @return the method handle for the method - */ - public MethodHandle findOwnStatic(final String name, final Class rtype, final Class... ptypes) { - return findStatic(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes)); - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/SimpleLinkRequest.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/SimpleLinkRequest.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +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.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 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/TypeUtilities.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/TypeUtilities.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,349 +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.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 final class TypeUtilities { - static final Class OBJECT_CLASS = Object.class; - - private TypeUtilities() { - } - - private static final Map, Class> WRAPPER_TYPES = createWrapperTypes(); - private static final Map, Class> PRIMITIVE_TYPES = invertMap(WRAPPER_TYPES); - private static final Map> PRIMITIVE_TYPES_BY_NAME = createClassNameMapping(WRAPPER_TYPES.keySet()); - - private static Map, Class> createWrapperTypes() { - final Map, Class> wrapperTypes = new IdentityHashMap<>(8); - wrapperTypes.put(Void.TYPE, Void.class); - wrapperTypes.put(Boolean.TYPE, Boolean.class); - wrapperTypes.put(Byte.TYPE, Byte.class); - wrapperTypes.put(Character.TYPE, Character.class); - wrapperTypes.put(Short.TYPE, Short.class); - wrapperTypes.put(Integer.TYPE, Integer.class); - wrapperTypes.put(Long.TYPE, Long.class); - wrapperTypes.put(Float.TYPE, Float.class); - wrapperTypes.put(Double.TYPE, Double.class); - return Collections.unmodifiableMap(wrapperTypes); - } - - private static Map> createClassNameMapping(final Collection> classes) { - final Map> map = new HashMap<>(); - for(final Class clazz: classes) { - map.put(clazz.getName(), clazz); - } - return map; - } - - private static Map invertMap(final Map map) { - final Map inverted = new IdentityHashMap<>(map.size()); - for(final Map.Entry entry: map.entrySet()) { - inverted.put(entry.getValue(), entry.getKey()); - } - return Collections.unmodifiableMap(inverted); - } - - /** - * Determines whether one type can be converted to another type using a method invocation conversion, as per JLS 5.3 - * "Method Invocation Conversion". This is basically all conversions allowed by subtyping (see - * {@link #isSubtype(Class, Class)}) as well as boxing conversion (JLS 5.1.7) optionally followed by widening - * reference conversion and unboxing conversion (JLS 5.1.8) optionally followed by widening primitive conversion. - * - * @param sourceType the type being converted from (call site type for parameter types, method type for return types) - * @param targetType the parameter type being converted to (method type for parameter types, call site type for return types) - * @return true if source type is method invocation convertible to target type. - */ - public static boolean isMethodInvocationConvertible(final Class sourceType, final Class targetType) { - if(targetType.isAssignableFrom(sourceType)) { - return true; - } - if(sourceType.isPrimitive()) { - if(targetType.isPrimitive()) { - return isProperPrimitiveSubtype(sourceType, targetType); - } - return isBoxingAndWideningReferenceConversion(sourceType, targetType); - } - if(targetType.isPrimitive()) { - final Class unboxedCallSiteType = getPrimitiveType(sourceType); - return unboxedCallSiteType != null - && (unboxedCallSiteType == targetType || isProperPrimitiveSubtype(unboxedCallSiteType, targetType)); - } - return false; - } - - private static boolean isBoxingAndWideningReferenceConversion(final Class sourceType, final Class targetType) { - final Class wrapperType = getWrapperType(sourceType); - assert wrapperType != null : sourceType.getName(); - return targetType.isAssignableFrom(wrapperType); - } - - /** - * Determines whether a type can be converted to another without losing any - * precision. As a special case, void is considered convertible only to void - * and {@link Object} (either as {@code null} or as a custom value set in - * {@link DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy)}). - * Somewhat unintuitively, we consider anything to be convertible to void - * even though converting to void causes the ultimate loss of data. On the - * other hand, conversion to void essentially means that the value is of no - * interest and should be discarded, thus there's no expectation of - * preserving any precision. - * - * @param sourceType the source type - * @param targetType the target type - * @return true if lossless conversion is possible - */ - public static boolean isConvertibleWithoutLoss(final Class sourceType, final Class targetType) { - if(targetType.isAssignableFrom(sourceType) || targetType == void.class) { - return true; - } - if(sourceType.isPrimitive()) { - if(sourceType == void.class) { - // Void should be losslessly representable by Object, either as null or as a custom value that - // can be set with DynamicLinkerFactory.setAutoConversionStrategy. - return targetType == Object.class; - } - if(targetType.isPrimitive()) { - return isProperPrimitiveLosslessSubtype(sourceType, targetType); - } - return isBoxingAndWideningReferenceConversion(sourceType, targetType); - } - // Can't convert from any non-primitive type to any primitive type without data loss because of null. - // Also, can't convert non-assignable reference types. - return false; - } - - /** - * Determines whether one type is a subtype of another type, as per JLS - * 4.10 "Subtyping". Note: this is not strict or proper subtype, therefore - * true is also returned for identical types; to be completely precise, it - * allows identity conversion (JLS 5.1.1), widening primitive conversion - * (JLS 5.1.2) and widening reference conversion (JLS 5.1.5). - * - * @param subType the supposed subtype - * @param superType the supposed supertype of the subtype - * @return true if subType can be converted by identity conversion, widening primitive conversion, or widening - * reference conversion to superType. - */ - public static boolean isSubtype(final Class subType, final Class superType) { - // Covers both JLS 4.10.2 "Subtyping among Class and Interface Types" - // and JLS 4.10.3 "Subtyping among Array Types", as well as primitive - // type identity. - if(superType.isAssignableFrom(subType)) { - return true; - } - // JLS 4.10.1 "Subtyping among Primitive Types". Note we don't test for - // identity, as identical types were taken care of in the - // isAssignableFrom test. As per 4.10.1, the supertype relation is as - // follows: - // double > float - // float > long - // long > int - // int > short - // int > char - // short > byte - if(superType.isPrimitive() && subType.isPrimitive()) { - return isProperPrimitiveSubtype(subType, superType); - } - return false; - } - - /** - * Returns true if a supposed primitive subtype is a proper subtype ( meaning, subtype and not identical) of the - * supposed primitive supertype - * - * @param subType the supposed subtype - * @param superType the supposed supertype - * @return true if subType is a proper (not identical to) primitive subtype of the superType - */ - private static boolean isProperPrimitiveSubtype(final Class subType, final Class superType) { - if(superType == boolean.class || subType == boolean.class) { - return false; - } - if(subType == byte.class) { - return superType != char.class; - } - if(subType == char.class) { - return superType != short.class && superType != byte.class; - } - if(subType == short.class) { - return superType != char.class && superType != byte.class; - } - if(subType == int.class) { - return superType == long.class || superType == float.class || superType == double.class; - } - if(subType == long.class) { - return superType == float.class || superType == double.class; - } - if(subType == float.class) { - return superType == double.class; - } - return false; - } - - /** - * Similar to {@link #isProperPrimitiveSubtype(Class, Class)}, except it disallows conversions from int and long to - * float, and from long to double, as those can lose precision. It also disallows conversion from and to char and - * anything else (similar to boolean) as char is not meant to be an arithmetic type. - * @param subType the supposed subtype - * @param superType the supposed supertype - * @return true if subType is a proper (not identical to) primitive subtype of the superType that can be represented - * by the supertype without no precision loss. - */ - private static boolean isProperPrimitiveLosslessSubtype(final Class subType, final Class superType) { - if(superType == boolean.class || subType == boolean.class) { - return false; - } - if(superType == char.class || subType == char.class) { - return false; - } - if(subType == byte.class) { - return true; - } - if(subType == short.class) { - return superType != byte.class; - } - if(subType == int.class) { - return superType == long.class || superType == double.class; - } - if(subType == float.class) { - return superType == double.class; - } - return false; - } - - /** - * Given a name of a primitive type returns the class representing it. I.e. - * when invoked with "int", returns {@link Integer#TYPE}. - * @param name the name of the primitive type - * @return the class representing the primitive type, or null if the name - * does not correspond to a primitive type. - */ - public static Class getPrimitiveTypeByName(final String name) { - return PRIMITIVE_TYPES_BY_NAME.get(name); - } - - /** - * When passed a class representing a wrapper for a primitive type, returns - * the class representing the corresponding primitive type. I.e. calling it - * with {@code Integer.class} will return {@code Integer.TYPE}. If passed a - * class that is not a wrapper for primitive type, returns null. - * @param wrapperType the class object representing a wrapper for a - * primitive type. - * @return the class object representing the primitive type, or null if the - * passed class is not a primitive wrapper. - */ - public static Class getPrimitiveType(final Class wrapperType) { - return PRIMITIVE_TYPES.get(wrapperType); - } - - /** - * When passed a class representing a primitive type, returns the class representing the corresponding - * wrapper type. I.e. calling it with {@code int.class} will return {@code Integer.class}. If passed a class - * that is not a primitive type, returns null. - * @param primitiveType the class object representing a primitive type - * @return the class object representing the wrapper type, or null if the passed class is not a primitive. - */ - public static Class getWrapperType(final Class primitiveType) { - return WRAPPER_TYPES.get(primitiveType); - } - - /** - * Returns true if the passed type is a wrapper for a primitive type. - * @param type the examined type - * @return true if the passed type is a wrapper for a primitive type. - */ - public static boolean isWrapperType(final Class type) { - return PRIMITIVE_TYPES.containsKey(type); - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/package-info.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/linker/support/package-info.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2015 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - *

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

- * @since 1.9 - */ -@jdk.Exported -package jdk.internal.dynalink.linker.support; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/package-info.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/package-info.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,277 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-2013 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - *

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

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

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

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

Example

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

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

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

Dynalink and bytecode creation

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

Available operations

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

Composite operations

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

Language-specific linkers

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

Dynalink and Java objects

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

Cross-language interoperability

- * A {@code DynamicLinkerFactory} can be configured with a - * {@link jdk.internal.dynalink.DynamicLinkerFactory#setClassLoader(ClassLoader) class - * loader}. It will try to instantiate all - * {@link jdk.internal.dynalink.linker.GuardingDynamicLinkerExporter} classes visible to - * that class loader and compose the linkers they provide into the - * {@code DynamicLinker} it creates. This allows for interoperability between - * languages: if you have two language runtimes A and B deployed in your JVM and - * they export their linkers through the above mechanism, language runtime A - * will have a language-specific linker instance from B and vice versa inside - * their {@code DynamicLinker} objects. This means that if an object from - * language runtime B gets passed to code from language runtime A, the linker - * from B will get a chance to link the call site in A when it encounters the - * object from B. - */ -@jdk.Exported -package jdk.internal.dynalink; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-2013 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package jdk.internal.dynalink.support; - -import java.lang.invoke.CallSite; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MutableCallSite; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.RelinkableCallSite; -import jdk.internal.dynalink.linker.GuardedInvocation; - -/** - * A basic implementation of the {@link RelinkableCallSite} as a - * {@link MutableCallSite}. It carries a {@link CallSiteDescriptor} passed in - * the constructor and provides the correct implementation of the - * {@link #initialize(MethodHandle)} method. Subclasses must provide - * {@link #relink(GuardedInvocation, MethodHandle)} and - * {@link #resetAndRelink(GuardedInvocation, MethodHandle)} - * methods. - */ -public abstract class AbstractRelinkableCallSite extends MutableCallSite implements RelinkableCallSite { - private final CallSiteDescriptor descriptor; - - /** - * Creates a new abstract relinkable call site. - * @param descriptor the descriptor for this call site that will be returned - * from {@link #getDescriptor()}. The call site's {@link CallSite#type()} - * will be equal to descriptor's {@link CallSiteDescriptor#getMethodType()}. - * @throws NullPointerException if {@code descriptor} is null. - */ - protected AbstractRelinkableCallSite(final CallSiteDescriptor descriptor) { - super(descriptor.getMethodType()); - this.descriptor = descriptor; - } - - @Override - public CallSiteDescriptor getDescriptor() { - return descriptor; - } - - @Override - public void initialize(final MethodHandle relinkAndInvoke) { - setTarget(relinkAndInvoke); - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/ChainedCallSite.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/ChainedCallSite.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,244 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-2013 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package jdk.internal.dynalink.support; - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.util.Arrays; -import java.util.Iterator; -import java.util.LinkedList; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.support.Lookup; - -/** - * A relinkable call site that implements a polymorphic inline caching strategy. - * It remembers up to 8 {@link GuardedInvocation}s it was linked with, and on - * each relink request builds a cascading chain of method handles of one - * invocation falling back to the next one. The number of remembered invocations - * can be customized by overriding {@link #getMaxChainLength()} in a subclass. - * When this call site is relinked with a new invocation and the length of the - * chain is already at the maximum, it will throw away the oldest invocation. - * Invocations with invalidated switch points and ones for which their - * invalidating exception triggered are removed eagerly from the chain. The - * invocations are never reordered; the most recently linked method handle is - * always at the start of the chain and the least recently linked at its end. - * The call site can be safely relinked on more than one thread concurrently. - * Race conditions in linking are resolved by throwing away the - * {@link GuardedInvocation} produced on the losing thread without incorporating - * it into the chain, so it can lead to repeated linking for the same arguments. - */ -public class ChainedCallSite extends AbstractRelinkableCallSite { - private static final MethodHandle PRUNE_CATCHES; - private static final MethodHandle PRUNE_SWITCHPOINTS; - static { - final MethodHandle PRUNE = Lookup.findOwnSpecial(MethodHandles.lookup(), "prune", MethodHandle.class, - MethodHandle.class, boolean.class); - PRUNE_CATCHES = MethodHandles.insertArguments(PRUNE, 2, true); - PRUNE_SWITCHPOINTS = MethodHandles.insertArguments(PRUNE, 2, false); - } - - /** - * Contains the invocations currently linked into this call site's target. They are used when we are - * relinking to rebuild the guardWithTest chain. Valid values for this field are: {@code null} if there's - * no linked invocations, or an instance of {@link GuardedInvocation} if there is exactly one previous - * invocation, or an instance of {@code GuardedInvocation[]} if there is more than one previous - * invocation. - */ - private Object invocations; - - /** - * Creates a new chained call site. - * @param descriptor the descriptor for the call site. - */ - public ChainedCallSite(final CallSiteDescriptor descriptor) { - super(descriptor); - } - - /** - * The maximum number of method handles in the chain. Defaults to 8. You can - * override it in a subclass if you need to change the value. - * @return the maximum number of method handles in the chain. The return - * value is checked, and if your override returns a value less than 1, a - * {@link RuntimeException} will be thrown. - */ - protected int getMaxChainLength() { - return 8; - } - - @Override - public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { - relinkInternal(guardedInvocation, relinkAndInvoke, false, false); - } - - @Override - public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { - relinkInternal(guardedInvocation, relinkAndInvoke, true, false); - } - - private MethodHandle relinkInternal(final GuardedInvocation invocation, final MethodHandle relink, final boolean reset, final boolean removeCatches) { - final Object currentInvocations = invocations; - final LinkedList newInvocations; - if (currentInvocations == null || reset) { - newInvocations = new LinkedList<>(); - } else if (currentInvocations instanceof GuardedInvocation) { - newInvocations = new LinkedList<>(); - newInvocations.add((GuardedInvocation)currentInvocations); - } else if (currentInvocations instanceof GuardedInvocation[]) { - newInvocations = new LinkedList<>(Arrays.asList(((GuardedInvocation[])currentInvocations))); - } else { - throw new AssertionError(); - } - - // First, prune the chain of invalidated switchpoints, we always do this - // We also remove any catches if the remove catches flag is set - for(final Iterator it = newInvocations.iterator(); it.hasNext();) { - final GuardedInvocation inv = it.next(); - if(inv.hasBeenInvalidated() || (removeCatches && inv.getException() != null)) { - it.remove(); - } - } - - // prune() is allowed to invoke this method with invocation == null meaning we're just pruning the chain and not - // adding any new invocations to it. - if(invocation != null) { - // Remove oldest entry if we're at max length - if(newInvocations.size() == checkMaxChainLength(getMaxChainLength())) { - newInvocations.removeFirst(); - } - newInvocations.addLast(invocation); - } - - // prune-and-invoke is used as the fallback for invalidated switchpoints. If a switchpoint gets invalidated, we - // rebuild the chain and get rid of all invalidated switchpoints instead of letting them linger. - final MethodHandle pruneAndInvokeSwitchPoints = makePruneAndInvokeMethod(relink, PRUNE_SWITCHPOINTS); - final MethodHandle pruneAndInvokeCatches = makePruneAndInvokeMethod(relink, PRUNE_CATCHES); - - // Fold the new chain - MethodHandle target = relink; - for(final GuardedInvocation inv: newInvocations) { - target = inv.compose(target, pruneAndInvokeSwitchPoints, pruneAndInvokeCatches); - } - - switch (newInvocations.size()) { - case 0: - invocations = null; - break; - case 1: - invocations = newInvocations.getFirst(); - break; - default: - invocations = newInvocations.toArray(new GuardedInvocation[newInvocations.size()]); - } - setTarget(target); - return target; - } - - private static int checkMaxChainLength(final int maxChainLength) { - if (maxChainLength > 0) { - return maxChainLength; - } - throw new RuntimeException("getMaxChainLength() returned a non-positive value"); - - } - /** - * Creates a method that rebuilds our call chain, pruning it of any invalidated switchpoints, and then invokes that - * chain. - * @param relinkAndInvoke the ultimate fallback for the chain passed from the dynamic linker. - * @return a method handle for prune-and-invoke - */ - private MethodHandle makePruneAndInvokeMethod(final MethodHandle relinkAndInvoke, final MethodHandle prune) { - // Bind prune to (this, relink) - final MethodHandle boundPrune = MethodHandles.insertArguments(prune, 0, this, relinkAndInvoke); - // Make it ignore all incoming arguments - final MethodHandle ignoreArgsPrune = MethodHandles.dropArguments(boundPrune, 0, type().parameterList()); - // Invoke prune, then invoke the call site target with original arguments - return MethodHandles.foldArguments(MethodHandles.exactInvoker(type()), ignoreArgsPrune); - } - - @SuppressWarnings("unused") - private MethodHandle prune(final MethodHandle relink, final boolean catches) { - return relinkInternal(null, relink, false, catches); - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/SimpleRelinkableCallSite.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/SimpleRelinkableCallSite.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-2013 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -package jdk.internal.dynalink.support; - -import java.lang.invoke.MethodHandle; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.DynamicLinker; -import jdk.internal.dynalink.linker.GuardedInvocation; - -/** - * A relinkable call site that implements monomorphic inline caching strategy, - * only being linked to a single {@link GuardedInvocation}. If that invocation - * is invalidated, it will throw it away and ask its associated - * {@link DynamicLinker} to relink it. - */ -public class SimpleRelinkableCallSite extends AbstractRelinkableCallSite { - /** - * Creates a new call site with monomorphic inline caching strategy. - * @param descriptor the descriptor for this call site - */ - public SimpleRelinkableCallSite(final CallSiteDescriptor descriptor) { - super(descriptor); - } - - @Override - public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { - setTarget(guardedInvocation.compose(relinkAndInvoke)); - } - - @Override - public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { - relink(guardedInvocation, relinkAndInvoke); - } -} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/messages.properties --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/messages.properties Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +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. - -isInstanceGuardAlwaysTrue=isInstance guard for {0} in position {1} in method type {2} at {3} will always return true -isInstanceGuardAlwaysFalse=isInstance guard for {0} in position {1} in method type {2} at {3} will always return false - -isOfClassGuardAlwaysTrue=isOfClass guard for {0} in position {1} in method type {2} at {3} will always return true -isOfClassGuardAlwaysFalse=isOfClass guard for {0} in position {1} in method type {2} at {3} will always return false - -isArrayGuardAlwaysTrue=isArray guard in position {0} in method type {1} at {2} will always return true -isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} at {2} will always return false diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/package-info.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/internal/dynalink/support/package-info.java Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This file is available under and governed by the GNU General Public - * License version 2 only, as published by the Free Software Foundation. - * However, the following notice accompanied the original version of this - * file, and Oracle licenses the original version of this file under the BSD - * license: - */ -/* - Copyright 2009-2013 Attila Szegedi - - Licensed under both the Apache License, Version 2.0 (the "Apache License") - and the BSD License (the "BSD License"), with licensee being free to - choose either of the two at their discretion. - - You may not use this file except in compliance with either the Apache - License or the BSD License. - - If you choose to use this file in compliance with the Apache License, the - following notice applies to you: - - You may obtain a copy of the Apache License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied. See the License for the specific language governing - permissions and limitations under the License. - - If you choose to use this file in compliance with the BSD License, the - following notice applies to you: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the copyright holder nor the names of - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -/** - *

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

- * @since 1.9 - */ -@jdk.Exported -package jdk.internal.dynalink.support; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java Wed Dec 02 09:37:26 2015 -0800 @@ -26,8 +26,8 @@ package jdk.nashorn.api.scripting; import java.lang.invoke.MethodHandle; -import jdk.internal.dynalink.beans.StaticClass; -import jdk.internal.dynalink.linker.LinkerServices; +import jdk.dynalink.beans.StaticClass; +import jdk.dynalink.linker.LinkerServices; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FoldConstants.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FoldConstants.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/FoldConstants.java Wed Dec 02 09:37:26 2015 -0800 @@ -234,6 +234,8 @@ case ADD: if (rhsInteger) { literalNode = LiteralNode.newInstance(token, finish, rhs.getInt32()); + } else if (rhsType.isLong()) { + literalNode = LiteralNode.newInstance(token, finish, rhs.getLong()); } else { literalNode = LiteralNode.newInstance(token, finish, rhs.getNumber()); } @@ -241,6 +243,8 @@ case SUB: if (rhsInteger && rhs.getInt32() != 0) { // @see test/script/basic/minuszero.js literalNode = LiteralNode.newInstance(token, finish, -rhs.getInt32()); + } else if (rhsType.isLong() && rhs.getLong() != 0L) { + literalNode = LiteralNode.newInstance(token, finish, -rhs.getLong()); } else { literalNode = LiteralNode.newInstance(token, finish, -rhs.getNumber()); } diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayBufferView.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayBufferView.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayBufferView.java Wed Dec 02 09:37:26 2015 -0800 @@ -30,9 +30,9 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; import java.nio.ByteBuffer; import java.nio.ByteOrder; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Getter; import jdk.nashorn.internal.objects.annotations.ScriptClass; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java Wed Dec 02 09:37:26 2015 -0800 @@ -47,10 +47,10 @@ import java.util.concurrent.ConcurrentHashMap; import javax.script.ScriptContext; import javax.script.ScriptEngine; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.StandardOperation; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.api.scripting.ClassFilter; import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.lookup.Lookup; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeArray.java Wed Dec 02 09:37:26 2015 -0800 @@ -42,9 +42,9 @@ import java.util.Iterator; import java.util.List; import java.util.concurrent.Callable; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeBoolean.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeBoolean.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeBoolean.java Wed Dec 02 09:37:26 2015 -0800 @@ -31,8 +31,8 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFunction.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFunction.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFunction.java Wed Dec 02 09:37:26 2015 -0800 @@ -33,7 +33,7 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.List; -import jdk.internal.dynalink.linker.support.Lookup; +import jdk.dynalink.linker.support.Lookup; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJSAdapter.java Wed Dec 02 09:37:26 2015 -0800 @@ -36,10 +36,10 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.StandardOperation; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.lookup.Lookup; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.ScriptClass; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java Wed Dec 02 09:37:26 2015 -0800 @@ -37,9 +37,9 @@ import java.util.List; import java.util.Map; import java.util.Queue; -import jdk.internal.dynalink.beans.BeansLinker; -import jdk.internal.dynalink.beans.StaticClass; -import jdk.internal.dynalink.linker.support.TypeUtilities; +import jdk.dynalink.beans.BeansLinker; +import jdk.dynalink.beans.StaticClass; +import jdk.dynalink.linker.support.TypeUtilities; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.objects.annotations.Attribute; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJavaImporter.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJavaImporter.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJavaImporter.java Wed Dec 02 09:37:26 2015 -0800 @@ -28,10 +28,10 @@ import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.beans.StaticClass; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.beans.StaticClass; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeNumber.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeNumber.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeNumber.java Wed Dec 02 09:37:26 2015 -0800 @@ -36,8 +36,8 @@ import java.math.RoundingMode; import java.text.NumberFormat; import java.util.Locale; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeObject.java Wed Dec 02 09:37:26 2015 -0800 @@ -39,16 +39,16 @@ import java.util.List; import java.util.Set; import java.util.concurrent.Callable; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.NamedOperation; -import jdk.internal.dynalink.Operation; -import jdk.internal.dynalink.StandardOperation; -import jdk.internal.dynalink.beans.BeansLinker; -import jdk.internal.dynalink.beans.StaticClass; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.GuardingDynamicLinker; -import jdk.internal.dynalink.linker.LinkRequest; -import jdk.internal.dynalink.linker.support.SimpleLinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.beans.BeansLinker; +import jdk.dynalink.beans.StaticClass; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.support.SimpleLinkRequest; import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.lookup.Lookup; import jdk.nashorn.internal.objects.annotations.Attribute; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeString.java Wed Dec 02 09:37:26 2015 -0800 @@ -41,10 +41,10 @@ import java.util.List; import java.util.Locale; import java.util.Set; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.StandardOperation; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.lookup.MethodHandleFactory.LookupException; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/annotations/SpecializedFunction.java Wed Dec 02 09:37:26 2015 -0800 @@ -30,8 +30,8 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.invoke.MethodHandle; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java Wed Dec 02 09:37:26 2015 -0800 @@ -3068,7 +3068,7 @@ if (k < stream.last() && start < parserState.position && parserState.position <= Token.descPosition(stream.get(stream.last()))) { // RBRACE is already in the token stream, so fast forward to it for (; k < stream.last(); k++) { - long nextToken = stream.get(k + 1); + final long nextToken = stream.get(k + 1); if (Token.descPosition(nextToken) == parserState.position && Token.descType(nextToken) == RBRACE) { token = stream.get(k); type = Token.descType(token); @@ -3484,7 +3484,7 @@ Expression concat = literal; TokenType lastLiteralType; do { - Expression expression = expression(); + final Expression expression = expression(); if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) { throw error(AbstractParser.message("unterminated.template.expression"), token); } @@ -3515,7 +3515,7 @@ if (hasSubstitutions) { TokenType lastLiteralType; do { - Expression expression = expression(); + final Expression expression = expression(); if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) { throw error(AbstractParser.message("unterminated.template.expression"), token); } diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CompiledFunction.java Wed Dec 02 09:37:26 2015 -0800 @@ -43,7 +43,7 @@ import java.util.TreeMap; import java.util.function.Supplier; import java.util.logging.Level; -import jdk.internal.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardedInvocation; import jdk.nashorn.internal.codegen.Compiler; import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; import jdk.nashorn.internal.codegen.TypeMap; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java Wed Dec 02 09:37:26 2015 -0800 @@ -71,7 +71,7 @@ import java.util.function.Supplier; import java.util.logging.Level; import javax.script.ScriptEngine; -import jdk.internal.dynalink.DynamicLinker; +import jdk.dynalink.DynamicLinker; import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/FindProperty.java Wed Dec 02 09:37:26 2015 -0800 @@ -29,7 +29,7 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; import java.lang.invoke.MethodHandle; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.objects.Global; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalConstants.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalConstants.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalConstants.java Wed Dec 02 09:37:26 2015 -0800 @@ -40,10 +40,10 @@ import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import java.util.logging.Level; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.DynamicLinker; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.DynamicLinker; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.lookup.Lookup; import jdk.nashorn.internal.lookup.MethodHandleFactory; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/JSType.java Wed Dec 02 09:37:26 2015 -0800 @@ -35,7 +35,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import jdk.internal.dynalink.beans.StaticClass; +import jdk.dynalink.beans.StaticClass; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.codegen.types.Type; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NativeJavaPackage.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NativeJavaPackage.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/NativeJavaPackage.java Wed Dec 02 09:37:26 2015 -0800 @@ -31,12 +31,12 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.beans.BeansLinker; -import jdk.internal.dynalink.beans.StaticClass; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; -import jdk.internal.dynalink.linker.support.Guards; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.beans.BeansLinker; +import jdk.dynalink.beans.StaticClass; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.support.Guards; import jdk.nashorn.internal.lookup.MethodHandleFactory; import jdk.nashorn.internal.lookup.MethodHandleFunctionality; import jdk.nashorn.internal.objects.annotations.Attribute; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java Wed Dec 02 09:37:26 2015 -0800 @@ -32,9 +32,9 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.support.TypeUtilities; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.support.TypeUtilities; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptFunction.java Wed Dec 02 09:37:26 2015 -0800 @@ -44,10 +44,10 @@ import java.util.HashSet; import java.util.List; import java.util.concurrent.atomic.LongAdder; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; -import jdk.internal.dynalink.linker.support.Guards; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.support.Guards; import jdk.nashorn.internal.codegen.ApplySpecialization; import jdk.nashorn.internal.codegen.Compiler; import jdk.nashorn.internal.codegen.CompilerConstants.Call; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java Wed Dec 02 09:37:26 2015 -0800 @@ -66,11 +66,11 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.LongAdder; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.NamedOperation; -import jdk.internal.dynalink.StandardOperation; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.codegen.ObjectClassGenerator; import jdk.nashorn.internal.codegen.types.Type; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptRuntime.java Wed Dec 02 09:37:26 2015 -0800 @@ -45,8 +45,7 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; - -import jdk.internal.dynalink.beans.StaticClass; +import jdk.dynalink.beans.StaticClass; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.codegen.ApplySpecialization; @@ -756,7 +755,9 @@ /** ECMA 11.9.3 The Abstract Equality Comparison Algorithm */ private static boolean equals(final Object x, final Object y) { - if (x == y) { + // We want to keep this method small so we skip reference equality check for numbers + // as NaN should return false when compared to itself (JDK-8043608). + if (x == y && !(x instanceof Number)) { return true; } if (x instanceof ScriptObject && y instanceof ScriptObject) { diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/SetMethodCreator.java Wed Dec 02 09:37:26 2015 -0800 @@ -31,15 +31,15 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.SwitchPoint; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; import jdk.nashorn.internal.runtime.linker.NashornGuards; /** * Instances of this class are quite ephemeral; they only exist for the duration of an invocation of - * {@link ScriptObject#findSetMethod(CallSiteDescriptor, jdk.internal.dynalink.linker.LinkRequest)} and + * {@link ScriptObject#findSetMethod(CallSiteDescriptor, jdk.dynalink.linker.LinkRequest)} and * serve as the actual encapsulation of the algorithm for creating an appropriate property setter method. */ final class SetMethodCreator { diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Undefined.java Wed Dec 02 09:37:26 2015 -0800 @@ -30,11 +30,11 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.NamedOperation; -import jdk.internal.dynalink.StandardOperation; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.support.Guards; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.support.Guards; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; /** diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java Wed Dec 02 09:37:26 2015 -0800 @@ -32,12 +32,12 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.SwitchPoint; -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.dynalink.CallSiteDescriptor; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.api.scripting.AbstractJSObject; import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ArrayData.java Wed Dec 02 09:37:26 2015 -0800 @@ -34,9 +34,9 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.codegen.CompilerConstants; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.objects.Global; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java Wed Dec 02 09:37:26 2015 -0800 @@ -33,9 +33,9 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.SwitchPoint; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.lookup.Lookup; import jdk.nashorn.internal.runtime.ScriptObject; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java Wed Dec 02 09:37:26 2015 -0800 @@ -241,7 +241,7 @@ @Override public int getInt(final int index) { - return (int)array[index]; + return JSType.toInt32(array[index]); } @Override diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java Wed Dec 02 09:37:26 2015 -0800 @@ -32,7 +32,8 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.Arrays; -import jdk.internal.dynalink.linker.support.TypeUtilities; +import jdk.dynalink.linker.support.TypeUtilities; +import jdk.nashorn.internal.runtime.JSType; /** * Implementation of {@link ArrayData} as soon as a double has been @@ -226,7 +227,7 @@ @Override public int getInt(final int index) { - return (int)array[index]; + return JSType.toInt32(array[index]); } @Override diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java Wed Dec 02 09:37:26 2015 -0800 @@ -28,9 +28,9 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; import java.lang.invoke.MethodHandle; import java.nio.Buffer; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.internal.lookup.Lookup; /** diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/Bootstrap.java Wed Dec 02 09:37:26 2015 -0800 @@ -34,17 +34,17 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.DynamicLinker; -import jdk.internal.dynalink.DynamicLinkerFactory; -import jdk.internal.dynalink.beans.BeansLinker; -import jdk.internal.dynalink.beans.StaticClass; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.GuardedInvocationTransformer; -import jdk.internal.dynalink.linker.LinkRequest; -import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.linker.MethodTypeConversionStrategy; -import jdk.internal.dynalink.linker.support.TypeUtilities; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.DynamicLinker; +import jdk.dynalink.DynamicLinkerFactory; +import jdk.dynalink.beans.BeansLinker; +import jdk.dynalink.beans.StaticClass; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardedInvocationTransformer; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.MethodTypeConversionStrategy; +import jdk.dynalink.linker.support.TypeUtilities; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.lookup.MethodHandleFactory; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BoundCallableLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -29,15 +29,15 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.Arrays; -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.linker.support.Guards; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.dynalink.linker.support.Guards; /** * Links {@link BoundCallable} objects. Passes through to linker services for linking a callable (for either diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -34,12 +34,12 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; -import jdk.internal.dynalink.CallSiteDescriptor; -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.dynalink.CallSiteDescriptor; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; import jdk.nashorn.internal.lookup.MethodHandleFactory; import jdk.nashorn.internal.lookup.MethodHandleFunctionality; import jdk.nashorn.internal.runtime.JSType; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -31,12 +31,12 @@ import java.lang.invoke.MethodHandles; import java.util.Map; import javax.script.Bindings; -import jdk.internal.dynalink.CallSiteDescriptor; -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.dynalink.CallSiteDescriptor; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.lookup.MethodHandleFactory; import jdk.nashorn.internal.lookup.MethodHandleFunctionality; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java Wed Dec 02 09:37:26 2015 -0800 @@ -34,7 +34,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import jdk.internal.dynalink.beans.StaticClass; +import jdk.dynalink.beans.StaticClass; import jdk.nashorn.internal.codegen.DumpBytecode; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.JSType; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java Wed Dec 02 09:37:26 2015 -0800 @@ -46,10 +46,10 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.StandardOperation; -import jdk.internal.dynalink.beans.StaticClass; -import jdk.internal.dynalink.linker.support.SimpleLinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.beans.StaticClass; +import jdk.dynalink.linker.support.SimpleLinkRequest; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ECMAException; import jdk.nashorn.internal.runtime.ScriptFunction; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java Wed Dec 02 09:37:26 2015 -0800 @@ -34,7 +34,7 @@ import java.lang.invoke.MethodHandles; import java.util.HashMap; import java.util.Map; -import jdk.internal.dynalink.linker.support.TypeUtilities; +import jdk.dynalink.linker.support.TypeUtilities; import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptObject; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -31,16 +31,16 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.NamedOperation; -import jdk.internal.dynalink.Operation; -import jdk.internal.dynalink.StandardOperation; -import jdk.internal.dynalink.beans.BeansLinker; -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.linker.support.Lookup; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.beans.BeansLinker; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.dynalink.linker.support.Lookup; import jdk.nashorn.internal.runtime.ScriptRuntime; /** diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java Wed Dec 02 09:37:26 2015 -0800 @@ -44,9 +44,9 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.LongAdder; -import jdk.internal.dynalink.DynamicLinker; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.support.ChainedCallSite; +import jdk.dynalink.DynamicLinker; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.support.ChainedCallSite; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.Debug; import jdk.nashorn.internal.runtime.ScriptObject; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -32,18 +32,18 @@ import java.lang.invoke.MethodType; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.NamedOperation; -import jdk.internal.dynalink.StandardOperation; -import jdk.internal.dynalink.beans.BeansLinker; -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; -import jdk.internal.dynalink.linker.support.DefaultInternalObjectFilter; -import jdk.internal.dynalink.linker.support.Lookup; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.beans.BeansLinker; +import jdk.dynalink.linker.ConversionComparator.Comparison; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.MethodHandleTransformer; +import jdk.dynalink.linker.support.DefaultInternalObjectFilter; +import jdk.dynalink.linker.support.Lookup; import jdk.nashorn.api.scripting.ScriptUtils; import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.Context; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -36,16 +36,16 @@ import java.util.HashMap; import java.util.Map; import java.util.function.Supplier; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.NamedOperation; -import jdk.internal.dynalink.Operation; -import jdk.internal.dynalink.beans.BeansLinker; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.GuardingDynamicLinker; -import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; -import jdk.internal.dynalink.linker.LinkRequest; -import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.linker.support.Guards; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.beans.BeansLinker; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.GuardingTypeConverterFactory; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.support.Guards; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptRuntime; @@ -86,9 +86,9 @@ MH.dropArguments(EMPTY_PROP_SETTER, 0, Object.class); private static GuardedInvocation linkBean(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { - final NashornCallSiteDescriptor desc = (NashornCallSiteDescriptor)linkRequest.getCallSiteDescriptor(); + final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor(); final Object self = linkRequest.getReceiver(); - switch (desc.getFirstOperation()) { + switch (NashornCallSiteDescriptor.getFirstStandardOperation(desc)) { case NEW: if(BeansLinker.isDynamicConstructor(self)) { throw typeError("no.constructor.matches.args", ScriptRuntime.safeToString(self)); @@ -96,7 +96,7 @@ if(BeansLinker.isDynamicMethod(self)) { throw typeError("method.not.constructor", ScriptRuntime.safeToString(self)); } - throw typeError("not.a.function", desc.getFunctionErrorMessage(self)); + throw typeError("not.a.function", NashornCallSiteDescriptor.getFunctionErrorMessage(desc, self)); case CALL: if(BeansLinker.isDynamicConstructor(self)) { throw typeError("constructor.requires.new", ScriptRuntime.safeToString(self)); @@ -104,7 +104,7 @@ if(BeansLinker.isDynamicMethod(self)) { throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self)); } - throw typeError("not.a.function", desc.getFunctionErrorMessage(self)); + throw typeError("not.a.function", NashornCallSiteDescriptor.getFunctionErrorMessage(desc, self)); case CALL_METHOD: throw typeError("no.such.function", getArgument(linkRequest), ScriptRuntime.safeToString(self)); case GET_METHOD: @@ -115,7 +115,7 @@ if(NashornCallSiteDescriptor.isOptimistic(desc)) { throw new UnwarrantedOptimismException(UNDEFINED, NashornCallSiteDescriptor.getProgramPoint(desc), Type.OBJECT); } - if (desc.getOperand() != null) { + if (NashornCallSiteDescriptor.getOperand(desc) != null) { return getInvocation(EMPTY_PROP_GETTER, self, linkerServices, desc); } return getInvocation(EMPTY_ELEM_GETTER, self, linkerServices, desc); @@ -125,7 +125,7 @@ if (strict) { throw typeError("cant.set.property", getArgument(linkRequest), ScriptRuntime.safeToString(self)); } - if (desc.getOperand() != null) { + if (NashornCallSiteDescriptor.getOperand(desc) != null) { return getInvocation(EMPTY_PROP_SETTER, self, linkerServices, desc); } return getInvocation(EMPTY_ELEM_SETTER, self, linkerServices, desc); @@ -168,8 +168,8 @@ } private static GuardedInvocation linkNull(final LinkRequest linkRequest) { - final NashornCallSiteDescriptor desc = (NashornCallSiteDescriptor)linkRequest.getCallSiteDescriptor(); - switch (desc.getFirstOperation()) { + final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor(); + switch (NashornCallSiteDescriptor.getFirstStandardOperation(desc)) { case NEW: case CALL: throw typeError("not.a.function", "null"); diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java Wed Dec 02 09:37:26 2015 -0800 @@ -39,11 +39,11 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.stream.Stream; -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.dynalink.CallSiteDescriptor; +import jdk.dynalink.CompositeOperation; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; import jdk.nashorn.internal.ir.debug.NashornTextifier; import jdk.nashorn.internal.runtime.AccessControlContextFactory; import jdk.nashorn.internal.runtime.ScriptRuntime; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornGuards.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornGuards.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornGuards.java Wed Dec 02 09:37:26 2015 -0800 @@ -30,8 +30,8 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.ref.WeakReference; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.LinkRequest; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.LinkRequest; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.Property; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -41,15 +41,15 @@ import java.util.Queue; import java.util.function.Supplier; import javax.script.Bindings; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.linker.ConversionComparator; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; -import jdk.internal.dynalink.linker.LinkRequest; -import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; -import jdk.internal.dynalink.linker.support.Guards; -import jdk.internal.dynalink.linker.support.Lookup; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.ConversionComparator; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingTypeConverterFactory; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.dynalink.linker.support.Guards; +import jdk.dynalink.linker.support.Lookup; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.api.scripting.ScriptUtils; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -30,13 +30,13 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.function.Supplier; -import jdk.internal.dynalink.linker.ConversionComparator; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.GuardingTypeConverterFactory; -import jdk.internal.dynalink.linker.LinkRequest; -import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; -import jdk.internal.dynalink.linker.support.TypeUtilities; +import jdk.dynalink.linker.ConversionComparator; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingTypeConverterFactory; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.dynalink.linker.support.TypeUtilities; import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.ConsString; import jdk.nashorn.internal.runtime.JSType; @@ -64,9 +64,7 @@ public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception { final Object self = request.getReceiver(); - final NashornCallSiteDescriptor desc = (NashornCallSiteDescriptor) request.getCallSiteDescriptor(); - - return Bootstrap.asTypeSafeReturn(Global.primitiveLookup(request, self), linkerServices, desc); + return Bootstrap.asTypeSafeReturn(Global.primitiveLookup(request, self), linkerServices, request.getCallSiteDescriptor()); } /** @@ -95,7 +93,7 @@ * @param sourceType the source type to convert from * @param targetType1 one candidate target type * @param targetType2 another candidate target type - * @return one of {@link jdk.internal.dynalink.linker.ConversionComparator.Comparison} values signifying which + * @return one of {@link jdk.dynalink.linker.ConversionComparator.Comparison} values signifying which * target type should be favored for conversion. */ @Override diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -26,17 +26,17 @@ package jdk.nashorn.internal.runtime.linker; import java.lang.reflect.Modifier; -import jdk.internal.dynalink.CallSiteDescriptor; -import jdk.internal.dynalink.NamedOperation; -import jdk.internal.dynalink.StandardOperation; -import jdk.internal.dynalink.beans.BeansLinker; -import jdk.internal.dynalink.beans.StaticClass; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.GuardingDynamicLinker; -import jdk.internal.dynalink.linker.LinkRequest; -import jdk.internal.dynalink.linker.LinkerServices; -import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; -import jdk.internal.dynalink.linker.support.Guards; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.beans.BeansLinker; +import jdk.dynalink.beans.StaticClass; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; +import jdk.dynalink.linker.support.Guards; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ECMAErrors; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java Wed Dec 02 09:37:26 2015 -0800 @@ -32,9 +32,10 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.SwitchPoint; -import jdk.internal.dynalink.linker.GuardedInvocation; -import jdk.internal.dynalink.linker.LinkRequest; -import jdk.internal.dynalink.linker.support.Guards; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.support.Guards; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.FindProperty; import jdk.nashorn.internal.runtime.GlobalConstants; @@ -95,14 +96,11 @@ public static GuardedInvocation lookupPrimitive(final LinkRequest request, final MethodHandle guard, final ScriptObject wrappedReceiver, final MethodHandle wrapFilter, final MethodHandle protoFilter) { - // lookupPrimitive is only ever invoked from NashornPrimitiveLinker, - // which is a linker private to Nashorn, therefore the call site - // descriptor class will always be NashornCallSiteDescriptor. - final NashornCallSiteDescriptor desc = (NashornCallSiteDescriptor)request.getCallSiteDescriptor(); - final String name = desc.getOperand(); + final CallSiteDescriptor desc = request.getCallSiteDescriptor(); + final String name = NashornCallSiteDescriptor.getOperand(desc); final FindProperty find = name != null ? wrappedReceiver.findProperty(name, true) : null; - switch (desc.getFirstOperation()) { + switch (NashornCallSiteDescriptor.getFirstStandardOperation(desc)) { case GET_PROPERTY: case GET_ELEMENT: case GET_METHOD: diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java Wed Dec 02 09:37:26 2015 -0800 @@ -29,12 +29,12 @@ import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; -import jdk.internal.dynalink.CallSiteDescriptor; -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.dynalink.CallSiteDescriptor; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.linker.TypeBasedGuardingDynamicLinker; import jdk.nashorn.api.scripting.ClassFilter; import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.Context; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/tools/Shell.java Wed Dec 02 09:37:26 2015 -0800 @@ -36,10 +36,12 @@ import java.io.OutputStream; import java.io.PrintStream; import java.io.PrintWriter; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.ResourceBundle; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; + import jdk.nashorn.api.scripting.NashornException; import jdk.nashorn.internal.codegen.Compiler; import jdk.nashorn.internal.codegen.Compiler.CompilationPhases; @@ -201,7 +203,9 @@ // parse options if (args != null) { try { - options.process(args); + // FIXME: preprocessArgs does not yet work fine + final String[] prepArgs = args; // preprocessArgs(args); + options.process(prepArgs); } catch (final IllegalArgumentException e) { werr.println(bundle.getString("shell.usage")); options.displayHelp(e); @@ -232,6 +236,74 @@ } /** + * Preprocess the command line arguments passed in by the shell. This checks, for each of the arguments, whether it + * can be a file name, and if so, whether the file exists. If the file exists and begins with a shebang line, and + * the arguments on that line are a prefix of {@code args} with the file removed, it is assumed that a script file + * being executed via shebang was found, and it is moved to the appropriate position in the argument list. The first + * such match is used. + *

+ * This method canonicalizes the command line arguments to the form {@code -- }, + * where the last of the {@code scripts} is the one being run in shebang fashion. + *

+ * @implNote Example:

    + *
  • Shebang line in {@code script.js}: {@code #!/path/to/jjs --language=es6 other.js -- arg1}
  • + *
  • Command line: {@code ./script.js arg2}
  • + *
  • {@code args} array passed to Nashorn: {@code --language=es6,other.js,--,arg1,./script.js,arg2}
  • + *
  • Required canonicalized arguments array: {@code --language=es6,other.js,./script.js,--,arg1,arg2}
  • + *
+ * + * @param args the command line arguments as passed into Nashorn. + * @return a properly ordered argument list + */ + private static String[] preprocessArgs(final String[] args) { + final List largs = new ArrayList<>(); + Collections.addAll(largs, args); + final List pa = new ArrayList<>(); + String scriptFile = null; + boolean found = false; + for (int i = 0; i < args.length; ++i) { + final String a = args[i]; + final Path p = Paths.get(a); + if (!found && (!a.startsWith("-") || a.length() == 1) && Files.exists(p)) { + String l = ""; + try (final BufferedReader r = Files.newBufferedReader(p)) { + l = r.readLine(); + } catch (IOException ioe) { + // ignore + } + if (l.startsWith("#!")) { + List shebangArgs = Arrays.asList(l.split(" ")); + shebangArgs = shebangArgs.subList(1, shebangArgs.size()); // remove #! part + final int ssize = shebangArgs.size(); + final List filteredArgs = largs.stream().filter(x -> !x.equals(a)).collect(Collectors.toList()); + if (filteredArgs.size() >= ssize && shebangArgs.equals(filteredArgs.subList(0, ssize))) { + scriptFile = a; + found = true; + continue; + } + } + } + pa.add(a); + } + if (scriptFile != null) { + // Insert the found script file name either before a -- argument, or at the end of the options list, before + // any other arguments, with an extra --. + int argidx = pa.indexOf("--"); + if (argidx == -1) { + for (String s : pa) { + ++argidx; + if (s.charAt(0) != '-') { + pa.add(argidx, "--"); + break; + } + } + } + pa.add(argidx, scriptFile); + } + return pa.stream().toArray(String[]::new); + } + + /** * Compiles the given script files in the command line * This is called only when using the --compile-only flag * diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/basic/JDK-8010946-2.js.EXPECTED --- a/nashorn/test/script/basic/JDK-8010946-2.js.EXPECTED Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/test/script/basic/JDK-8010946-2.js.EXPECTED Wed Dec 02 09:37:26 2015 -0800 @@ -1,2 +1,2 @@ -[jdk.internal.dynalink.beans.CallerSensitiveDynamicMethod Object java.security.AccessController.doPrivileged(PrivilegedAction)] -[jdk.internal.dynalink.beans.SimpleDynamicMethod String java.lang.String.valueOf(char)] +[jdk.dynalink.beans.CallerSensitiveDynamicMethod Object java.security.AccessController.doPrivileged(PrivilegedAction)] +[jdk.dynalink.beans.SimpleDynamicMethod String java.lang.String.valueOf(char)] diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/basic/JDK-8026125.js --- a/nashorn/test/script/basic/JDK-8026125.js Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/test/script/basic/JDK-8026125.js Wed Dec 02 09:37:26 2015 -0800 @@ -22,7 +22,7 @@ */ /** - * JDK-8026125: Array.prototype.slice.call(Java.type("java.util.HashMap")) throws ClassCastException: jdk.internal.dynalink.beans.StaticClass cannot be cast to jdk.nashorn.internal.runtime.ScriptObject + * JDK-8026125: Array.prototype.slice.call(Java.type("java.util.HashMap")) throws ClassCastException: jdk.dynalink.beans.StaticClass cannot be cast to jdk.nashorn.internal.runtime.ScriptObject * * @test * @run diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/basic/JDK-8043232.js.EXPECTED --- a/nashorn/test/script/basic/JDK-8043232.js.EXPECTED Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/test/script/basic/JDK-8043232.js.EXPECTED Wed Dec 02 09:37:26 2015 -0800 @@ -1,16 +1,16 @@ bcd -[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] +[jdk.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] red TypeError: No such Java class: java.lang.NonExistent TypeError: No such Java constructor: Object(String) TypeError: Java constructor signature invalid: Object()xxxxx TypeError: Java constructor signature invalid: Object( TypeError: Java constructor signature invalid: Object) -TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod +TypeError: Java method [jdk.dynalink.beans.OverloadedDynamicMethod String java.lang.System.getProperty(String,String) String java.lang.System.getProperty(String) ] cannot be used as a constructor. -TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod +TypeError: Java method [jdk.dynalink.beans.OverloadedDynamicMethod void java.io.PrintStream.println() void java.io.PrintStream.println(boolean) void java.io.PrintStream.println(char) @@ -22,7 +22,7 @@ void java.io.PrintStream.println(Object) void java.io.PrintStream.println(String) ] cannot be used as a constructor. -TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new". +TypeError: Constructor [jdk.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new". TypeError: No such Java constructor: Runnable() TypeError: No such Java constructor: Runnable(int) java.lang.InstantiationException: java.io.InputStream diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/basic/JDK-8049242.js.EXPECTED --- a/nashorn/test/script/basic/JDK-8049242.js.EXPECTED Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/test/script/basic/JDK-8049242.js.EXPECTED Wed Dec 02 09:37:26 2015 -0800 @@ -1,10 +1,10 @@ abc -[jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] +[jdk.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] ava TypeError: null is not a function TypeError: null is not a function TypeError: null is not a function -TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new". +TypeError: Constructor [jdk.dynalink.beans.SimpleDynamicMethod java.lang.String(char[],int,int)] requires "new". TypeError: null is not a function TypeError: null is not a function java.lang.InstantiationException: java.io.InputStream diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/basic/JDK-8059934.js --- a/nashorn/test/script/basic/JDK-8059934.js Wed Jul 05 21:04:26 2017 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * JDK-8059934: Random failures when script size exceeds token limits - * - * @test - * @run - */ - -// Make sure that we can successfully evaluate a 100 MB string. -// We don't go beyond that as we'd likely hit heap size limits. -var src = "var x = 'ok';"; -for (var i = 0; i < 1000000; i++) { - src += " "; -} -src += "x;"; - -Assert.assertEquals(100000015, src.length); -Assert.assertEquals("ok", eval(src)); - diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/basic/JDK-8079470.js.EXPECTED --- a/nashorn/test/script/basic/JDK-8079470.js.EXPECTED Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/test/script/basic/JDK-8079470.js.EXPECTED Wed Dec 02 09:37:26 2015 -0800 @@ -1,2 +1,2 @@ -TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures. -TypeError: Can not create new object with constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures. +TypeError: Can not create new object with constructor [jdk.dynalink.beans.SimpleDynamicMethod java.io.File(String,String)] with the passed arguments; they do not match any of its method signatures. +TypeError: Can not create new object with constructor [jdk.dynalink.beans.SimpleDynamicMethod java.awt.Color(int,int,int)] with the passed arguments; they do not match any of its method signatures. diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/basic/JDK-8134939.js --- a/nashorn/test/script/basic/JDK-8134939.js Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/test/script/basic/JDK-8134939.js Wed Dec 02 09:37:26 2015 -0800 @@ -31,13 +31,13 @@ var overloadedSetter = new (Java.type("jdk.nashorn.test.models.OverloadedSetter")); Assert.assertEquals(String(overloadedSetter.foo), - "[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" + + "[jdk.dynalink.beans.OverloadedDynamicMethod\n" + " String jdk.nashorn.test.models.OverloadedSetter.foo(String)\n" + " void jdk.nashorn.test.models.OverloadedSetter.foo(int)\n" + "]"); Assert.assertEquals(String(overloadedSetter.setColor), - "[jdk.internal.dynalink.beans.OverloadedDynamicMethod\n" + + "[jdk.dynalink.beans.OverloadedDynamicMethod\n" + " void jdk.nashorn.test.models.OverloadedSetter.setColor(int)\n" + " void jdk.nashorn.test.models.OverloadedSetter.setColor(String)\n" + "]"); diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/basic/JDK-8141407.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8141407.js Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,62 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8141407: Wrong evaluation of a != a when a = NaN + * + * @test + * @run + */ + +function expectNotEqualToSelf(a) { + Assert.assertFalse(a == a); + Assert.assertFalse(a === a); + Assert.assertTrue(a != a); + Assert.assertTrue(a !== a); +} + +// In previous versions of Nashorn this failed only on the second assignment, +// because only then the property slot was widened to object. +var a = NaN; +expectNotEqualToSelf(a); +a = {}; +a = NaN; +expectNotEqualToSelf(a); + +// We do have to do value-based rather than reference-based comparison for +// java.lang.Double since that class is used to represent primitive numbers +// in JavaScript. +var b = new java.lang.Double(NaN); +expectNotEqualToSelf(b); +b = {}; +b = new java.lang.Double(NaN); +expectNotEqualToSelf(b); + +// Although float is not used internally by Nashorn, java.lang.Float +// is handled like a primitive number in most of Nashorn, so for consistency +// we treat it like java.lang.Double. +var c = new java.lang.Float(NaN); +expectNotEqualToSelf(c); +c = {}; +c = new java.lang.Float(NaN); +expectNotEqualToSelf(c); diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/basic/JDK-8143304.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8143304.js Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,41 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8143304: Random failures when script size exceeds token limits + * + * @test + * @run + */ + +// Make sure that we can successfully evaluate a 100 MB string. +// We don't go beyond that as we'd likely hit heap size limits. +var src = "var x = 'ok';"; +for (var i = 0; i < 1000000; i++) { + src += " "; +} +src += "x;"; + +Assert.assertEquals(100000015, src.length); +Assert.assertEquals("ok", eval(src)); + diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/basic/JDK-8144131.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/script/basic/JDK-8144131.js Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,50 @@ +/* + * 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8144131: ArrayData.getInt implementations do not convert to int32 + * + * @test + * @run + */ + +var doubleArray = [97912312397.234, -182374983434.56]; +var doubleArrayResults = [-871935411, -1986357002]; +var longArray = [0x7fffffff8c102ebc, -0x7fffffffe9dfec18]; +var longArrayResults = [-1945096192, 371201024]; + +// Make sure arrays use double and long array data +Assert.assertEquals(doubleArray[0].getClass(), java.lang.Double.class); +Assert.assertEquals(longArray[0].getClass(), java.lang.Long.class); + +function testBinaryOp(array, index, expected) { + Assert.assertEquals(array[index] & 0xffffffff, expected); +} + +for (var i = 0; i < doubleArray.length; i++) { + testBinaryOp(doubleArray, i, doubleArrayResults[i]); +} +for (var i = 0; i < longArray.length; i++) { + testBinaryOp(longArray, i, longArrayResults[i]); +} + diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/basic/minuszero.js --- a/nashorn/test/script/basic/minuszero.js Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/test/script/basic/minuszero.js Wed Dec 02 09:37:26 2015 -0800 @@ -39,3 +39,7 @@ print(obj.length === -0); print(1/obj.length); +var mzl = -(0x7fffffffffffffff - 0x7fffffffffffffff); +print(mzl); +print(mzl === -0); +print(1/mzl); \ No newline at end of file diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/basic/minuszero.js.EXPECTED --- a/nashorn/test/script/basic/minuszero.js.EXPECTED Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/test/script/basic/minuszero.js.EXPECTED Wed Dec 02 09:37:26 2015 -0800 @@ -4,3 +4,6 @@ 0 true -Infinity +0 +true +-Infinity diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/sandbox/nashorninternals.js --- a/nashorn/test/script/sandbox/nashorninternals.js Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/test/script/sandbox/nashorninternals.js Wed Dec 02 09:37:26 2015 -0800 @@ -63,7 +63,3 @@ checkClass("jdk.nashorn.internal.runtime.regexp.RegExp"); checkClass("jdk.nashorn.internal.scripts.JO"); checkClass("jdk.nashorn.tools.Shell"); -checkClass("jdk.internal.dynalink.CallSiteDescriptor"); -checkClass("jdk.internal.dynalink.beans.StaticClass"); -checkClass("jdk.internal.dynalink.linker.LinkRequest"); -checkClass("jdk.internal.dynalink.support.AbstractRelinkableCallSite"); diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/script/trusted/classfilter.js.EXPECTED --- a/nashorn/test/script/trusted/classfilter.js.EXPECTED Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/test/script/trusted/classfilter.js.EXPECTED Wed Dec 02 09:37:26 2015 -0800 @@ -4,7 +4,7 @@ typeof java.util.Map evalutes to function typeof java.util.HashMap evalutes to function var m = new java.util.HashMap(); m.put('foo', 42); m evalutes to {foo=42} -java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod +java.lang.System.out.println evalutes to [jdk.dynalink.beans.OverloadedDynamicMethod void java.io.PrintStream.println() void java.io.PrintStream.println(boolean) void java.io.PrintStream.println(char) @@ -16,7 +16,7 @@ void java.io.PrintStream.println(Object) void java.io.PrintStream.println(String) ] -java.lang.System.exit evalutes to [jdk.internal.dynalink.beans.SimpleDynamicMethod void java.lang.System.exit(int)] +java.lang.System.exit evalutes to [jdk.dynalink.beans.SimpleDynamicMethod void java.lang.System.exit(int)] new javax.script.SimpleBindings throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.SimpleBindings Java.type('javax.script.ScriptContext') throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.ScriptContext java.lang.Class.forName('javax.script.ScriptContext') throws javax.script.ScriptException: TypeError: Java reflection not supported when class filter is present in at line number 1 diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/META-INF/services/jdk.dynalink.linker.GuardingDynamicLinkerExporter Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,2 @@ +jdk.dynalink.test.UntrustedGuardingDynamicLinkerExporter +jdk.dynalink.test.TrustedGuardingDynamicLinkerExporter diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/jdk/dynalink/beans/test/BeanLinkerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/jdk/dynalink/beans/test/BeanLinkerTest.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,410 @@ +/* + * 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.dynalink.beans.test; + +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.DynamicLinker; +import jdk.dynalink.DynamicLinkerFactory; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.NoSuchDynamicMethodException; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.beans.BeansLinker; +import jdk.dynalink.beans.StaticClass; +import jdk.dynalink.support.SimpleRelinkableCallSite; +import org.testng.Assert; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class BeanLinkerTest { + + private DynamicLinker linker; + private static final MethodHandles.Lookup MY_LOOKUP = MethodHandles.lookup(); + + @SuppressWarnings("unused") + @DataProvider + private static Object[][] flags() { + return new Object[][]{ + {Boolean.FALSE}, + {Boolean.TRUE} + }; + } + + // helpers to create callsite objects + private CallSite createCallSite(final boolean publicLookup, final Operation op, final MethodType mt) { + return linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( + publicLookup ? MethodHandles.publicLookup() : MY_LOOKUP, op, mt))); + } + + private CallSite createCallSite(final boolean publicLookup, final Operation op, final Object name, final MethodType mt) { + return createCallSite(publicLookup, new NamedOperation(op, name), mt); + } + + @BeforeTest + public void initLinker() { + final DynamicLinkerFactory factory = new DynamicLinkerFactory(); + this.linker = factory.createLinker(); + } + + @AfterTest + public void afterTest() { + this.linker = null; + } + + @Test(dataProvider = "flags") + public void getPropertyTest(final boolean publicLookup) throws Throwable { + final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_PROPERTY, mt); + Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class); + Assert.assertEquals(cs.getTarget().invoke(new Date(), "class"), Date.class); + } + + @Test(dataProvider = "flags") + public void getPropertyNegativeTest(final boolean publicLookup) throws Throwable { + final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_PROPERTY, mt); + Assert.assertNull(cs.getTarget().invoke(new Object(), "DOES_NOT_EXIST")); + } + + @Test(dataProvider = "flags") + public void getPropertyTest2(final boolean publicLookup) throws Throwable { + final MethodType mt = MethodType.methodType(Object.class, Object.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_PROPERTY, "class", mt); + Assert.assertEquals(cs.getTarget().invoke(new Object()), Object.class); + Assert.assertEquals(cs.getTarget().invoke(new Date()), Date.class); + } + + @Test(dataProvider = "flags") + public void getPropertyNegativeTest2(final boolean publicLookup) throws Throwable { + final MethodType mt = MethodType.methodType(Object.class, Object.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_PROPERTY, "DOES_NOT_EXIST", mt); + + try { + cs.getTarget().invoke(new Object()); + throw new RuntimeException("Expected NoSuchDynamicMethodException"); + } catch (Throwable th) { + Assert.assertTrue(th instanceof NoSuchDynamicMethodException); + } + } + + @Test(dataProvider = "flags") + public void getLengthPropertyTest(final boolean publicLookup) throws Throwable { + final MethodType mt = MethodType.methodType(int.class, Object.class, String.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_PROPERTY, mt); + + Assert.assertEquals((int) cs.getTarget().invoke(new int[10], "length"), 10); + Assert.assertEquals((int) cs.getTarget().invoke(new String[33], "length"), 33); + } + + @Test(dataProvider = "flags") + public void getlengthTest(final boolean publicLookup) throws Throwable { + final MethodType mt = MethodType.methodType(int.class, Object.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_LENGTH, mt); + + final int[] arr = {23, 42}; + Assert.assertEquals((int) cs.getTarget().invoke((Object) arr), 2); + Assert.assertEquals((int) cs.getTarget().invoke(Collections.EMPTY_LIST), 0); + + final List list = new ArrayList<>(); + list.add("hello"); + list.add("world"); + list.add("dynalink"); + Assert.assertEquals((int) cs.getTarget().invoke(list), 3); + list.add("nashorn"); + Assert.assertEquals((int) cs.getTarget().invoke(list), 4); + list.clear(); + Assert.assertEquals((int) cs.getTarget().invoke(list), 0); + } + + @Test(dataProvider = "flags") + public void getElementTest(final boolean publicLookup) throws Throwable { + final MethodType mt = MethodType.methodType(int.class, Object.class, int.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_ELEMENT, mt); + + final int[] arr = {23, 42}; + Assert.assertEquals((int) cs.getTarget().invoke(arr, 0), 23); + Assert.assertEquals((int) cs.getTarget().invoke(arr, 1), 42); + try { + int x = (int) cs.getTarget().invoke(arr, -1); + throw new RuntimeException("expected ArrayIndexOutOfBoundsException"); + } catch (ArrayIndexOutOfBoundsException ex) { + } + + try { + int x = (int) cs.getTarget().invoke(arr, arr.length); + throw new RuntimeException("expected ArrayIndexOutOfBoundsException"); + } catch (ArrayIndexOutOfBoundsException ex) { + } + + final List list = new ArrayList<>(); + list.add(23); + list.add(430); + list.add(-4354); + Assert.assertEquals((int) cs.getTarget().invoke(list, 0), (int) list.get(0)); + Assert.assertEquals((int) cs.getTarget().invoke(list, 1), (int) list.get(1)); + Assert.assertEquals((int) cs.getTarget().invoke(list, 2), (int) list.get(2)); + try { + int x = (int) cs.getTarget().invoke(list, -1); + throw new RuntimeException("expected IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + } + + try { + int x = (int) cs.getTarget().invoke(list, list.size()); + throw new RuntimeException("expected IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + } + } + + @Test(dataProvider = "flags") + public void setElementTest(final boolean publicLookup) throws Throwable { + final MethodType mt = MethodType.methodType(void.class, Object.class, int.class, int.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.SET_ELEMENT, mt); + + final int[] arr = {23, 42}; + cs.getTarget().invoke(arr, 0, 0); + Assert.assertEquals(arr[0], 0); + cs.getTarget().invoke(arr, 1, -5); + Assert.assertEquals(arr[1], -5); + + try { + cs.getTarget().invoke(arr, -1, 12); + throw new RuntimeException("expected ArrayIndexOutOfBoundsException"); + } catch (ArrayIndexOutOfBoundsException ex) { + } + + try { + cs.getTarget().invoke(arr, arr.length, 20); + throw new RuntimeException("expected ArrayIndexOutOfBoundsException"); + } catch (ArrayIndexOutOfBoundsException ex) { + } + + final List list = new ArrayList<>(); + list.add(23); + list.add(430); + list.add(-4354); + + cs.getTarget().invoke(list, 0, -list.get(0)); + Assert.assertEquals((int) list.get(0), -23); + cs.getTarget().invoke(list, 1, -430); + cs.getTarget().invoke(list, 2, 4354); + try { + cs.getTarget().invoke(list, -1, 343); + throw new RuntimeException("expected IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + } + + try { + cs.getTarget().invoke(list, list.size(), 43543); + throw new RuntimeException("expected IndexOutOfBoundsException"); + } catch (IndexOutOfBoundsException ex) { + } + } + + @Test(dataProvider = "flags") + public void newObjectTest(final boolean publicLookup) { + final MethodType mt = MethodType.methodType(Object.class, Object.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.NEW, mt); + + Object obj = null; + try { + obj = cs.getTarget().invoke(StaticClass.forClass(Date.class)); + } catch (Throwable th) { + throw new RuntimeException(th); + } + + Assert.assertTrue(obj instanceof Date); + } + + @Test(dataProvider = "flags") + public void staticPropertyTest(final boolean publicLookup) { + final MethodType mt = MethodType.methodType(Object.class, Class.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_PROPERTY, "static", mt); + + Object obj = null; + try { + obj = cs.getTarget().invoke(Object.class); + } catch (Throwable th) { + throw new RuntimeException(th); + } + + Assert.assertTrue(obj instanceof StaticClass); + Assert.assertEquals(((StaticClass) obj).getRepresentedClass(), Object.class); + + try { + obj = cs.getTarget().invoke(Date.class); + } catch (Throwable th) { + throw new RuntimeException(th); + } + + Assert.assertTrue(obj instanceof StaticClass); + Assert.assertEquals(((StaticClass) obj).getRepresentedClass(), Date.class); + + try { + obj = cs.getTarget().invoke(Object[].class); + } catch (Throwable th) { + throw new RuntimeException(th); + } + + Assert.assertTrue(obj instanceof StaticClass); + Assert.assertEquals(((StaticClass) obj).getRepresentedClass(), Object[].class); + } + + @Test(dataProvider = "flags") + public void instanceMethodCallTest(final boolean publicLookup) { + final MethodType mt = MethodType.methodType(Object.class, Object.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_METHOD, "getClass", mt); + final MethodType mt2 = MethodType.methodType(Class.class, Object.class, Object.class); + final CallSite cs2 = createCallSite(publicLookup, StandardOperation.CALL, mt2); + + Object method = null; + try { + method = cs.getTarget().invoke(new Date()); + } catch (Throwable th) { + throw new RuntimeException(th); + } + + Assert.assertNotNull(method); + Assert.assertTrue(BeansLinker.isDynamicMethod(method)); + Class clz = null; + try { + clz = (Class) cs2.getTarget().invoke(method, new Date()); + } catch (Throwable th) { + throw new RuntimeException(th); + } + + Assert.assertEquals(clz, Date.class); + } + + @Test(dataProvider = "flags") + public void instanceMethodCallTest2(final boolean publicLookup) { + final MethodType mt = MethodType.methodType(Class.class, Object.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.CALL_METHOD, "getClass", mt); + Class clz = null; + try { + clz = (Class) cs.getTarget().invoke(new Date()); + } catch (Throwable th) { + throw new RuntimeException(th); + } + + Assert.assertEquals(clz, Date.class); + } + + @Test(dataProvider = "flags") + public void staticMethodCallTest(final boolean publicLookup) { + final MethodType mt = MethodType.methodType(Object.class, StaticClass.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.GET_METHOD, "getProperty", mt); + final MethodType mt2 = MethodType.methodType(String.class, Object.class, Object.class, String.class); + final CallSite cs2 = createCallSite(publicLookup, StandardOperation.CALL, mt2); + + Object method = null; + try { + method = cs.getTarget().invoke(StaticClass.forClass(System.class)); + } catch (Throwable th) { + throw new RuntimeException(th); + } + + Assert.assertNotNull(method); + Assert.assertTrue(BeansLinker.isDynamicMethod(method)); + + String str = null; + try { + str = (String) cs2.getTarget().invoke(method, null, "os.name"); + } catch (Throwable th) { + throw new RuntimeException(th); + } + Assert.assertEquals(str, System.getProperty("os.name")); + } + + @Test(dataProvider = "flags") + public void staticMethodCallTest2(final boolean publicLookup) { + final MethodType mt = MethodType.methodType(String.class, Object.class, String.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.CALL_METHOD, "getProperty", mt); + + String str = null; + try { + str = (String) cs.getTarget().invoke(StaticClass.forClass(System.class), "os.name"); + } catch (Throwable th) { + throw new RuntimeException(th); + } + Assert.assertEquals(str, System.getProperty("os.name")); + } + + // try calling System.getenv and expect security exception + @Test(dataProvider = "flags") + public void systemGetenvTest(final boolean publicLookup) { + final MethodType mt = MethodType.methodType(Object.class, Object.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.CALL_METHOD, "getenv", mt); + + try { + cs.getTarget().invoke(StaticClass.forClass(System.class)); + throw new RuntimeException("should not reach here in any case!"); + } catch (Throwable th) { + Assert.assertTrue(th instanceof SecurityException); + } + } + + // try getting a specific sensitive System property and expect security exception + @Test(dataProvider = "flags") + public void systemGetPropertyTest(final boolean publicLookup) { + final MethodType mt = MethodType.methodType(String.class, Object.class, String.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.CALL_METHOD, "getProperty", mt); + + try { + cs.getTarget().invoke(StaticClass.forClass(System.class), "java.home"); + throw new RuntimeException("should not reach here in any case!"); + } catch (Throwable th) { + Assert.assertTrue(th instanceof SecurityException); + } + } + + // check a @CallerSensitive API and expect appropriate access check exception + @Test(dataProvider = "flags") + public void systemLoadLibraryTest(final boolean publicLookup) { + final MethodType mt = MethodType.methodType(void.class, Object.class, String.class); + final CallSite cs = createCallSite(publicLookup, StandardOperation.CALL_METHOD, "loadLibrary", mt); + + try { + cs.getTarget().invoke(StaticClass.forClass(System.class), "foo"); + throw new RuntimeException("should not reach here in any case!"); + } catch (Throwable th) { + if (publicLookup) { + Assert.assertTrue(th instanceof IllegalAccessError); + } else { + Assert.assertTrue(th instanceof AccessControlException); + } + } + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/jdk/dynalink/beans/test/BeansLinkerTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/jdk/dynalink/beans/test/BeansLinkerTest.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,289 @@ +/* + * 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.dynalink.beans.test; + +import static jdk.dynalink.StandardOperation.CALL; +import static jdk.dynalink.StandardOperation.GET_ELEMENT; +import static jdk.dynalink.StandardOperation.GET_METHOD; +import static jdk.dynalink.StandardOperation.GET_PROPERTY; +import static jdk.dynalink.StandardOperation.SET_ELEMENT; +import static jdk.dynalink.StandardOperation.SET_PROPERTY; + +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.regex.Pattern; +import java.util.stream.Stream; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.CompositeOperation; +import jdk.dynalink.DynamicLinkerFactory; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.support.SimpleRelinkableCallSite; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class BeansLinkerTest { + public static class Bean1 { + public final int answer = 42; + + public String getName() { + return "bean1"; + } + + public String someMethod(final String x) { + return x + "-foo"; + } + } + + @Test + public static void testPublicFieldPropertyUnnamedGetter() { + testGetterPermutations(GET_PROPERTY, (op) -> Assert.assertEquals(42, call(op, new Bean1(), "answer"))); + } + + @Test + public static void testPublicFieldPropertyNamedGetter() { + testGetterPermutations(GET_PROPERTY, (op) -> Assert.assertEquals(42, call(named("answer", op), new Bean1()))); + } + + @Test + public static void testGetterPropertyUnnamedGetter() { + testGetterPermutations(GET_PROPERTY, (op) -> Assert.assertEquals("bean1", call(op, new Bean1(), "name"))); + } + + @Test + public static void testGetterPropertyNamedGetter() { + testGetterPermutations(GET_PROPERTY, (op) -> Assert.assertEquals("bean1", call(named("name", op), new Bean1()))); + } + + @Test + public static void testMethodUnnamedGetter() { + testGetterPermutations(GET_METHOD, (op) -> Assert.assertEquals("bar-foo", call(call(op, new Bean1(), "someMethod"), new Bean1(), "bar"))); + } + + @Test + public static void testMethodNamedGetter() { + testGetterPermutations(GET_METHOD, (op) -> Assert.assertEquals("bar-foo", call(call(named("someMethod", op), new Bean1()), new Bean1(), "bar"))); + } + + private static final Map MAP1 = new HashMap<>(); + static { + MAP1.put("foo", "bar"); + } + + @Test + public static void testElementUnnamedGetter() { + testGetterPermutations(GET_ELEMENT, (op) -> Assert.assertEquals("bar", call(op, MAP1, "foo"))); + } + + @Test + public static void testElementNamedGetter() { + testGetterPermutations(GET_ELEMENT, (op) -> Assert.assertEquals("bar", call(named("foo", op), MAP1))); + } + + public static class Bean2 { + public int answer; + private String name; + + public void setName(final String name) { + this.name = name; + } + } + + @Test + public static void testUnnamedFieldSetter() { + testSetterPermutations(SET_PROPERTY, (op) -> { + final Bean2 bean2 = new Bean2(); + call(op, bean2, "answer", 12); + Assert.assertEquals(bean2.answer, 12); + }); + } + + @Test + public static void testNamedFieldSetter() { + testSetterPermutations(SET_PROPERTY, (op) -> { + final Bean2 bean2 = new Bean2(); + call(named("answer", op), bean2, 14); + Assert.assertEquals(bean2.answer, 14); + }); + } + + @Test + public static void testUnnamedPropertySetter() { + testSetterPermutations(SET_PROPERTY, (op) -> { + final Bean2 bean2 = new Bean2(); + call(op, bean2, "name", "boo"); + Assert.assertEquals(bean2.name, "boo"); + }); + } + + @Test + public static void testNamedPropertySetter() { + testSetterPermutations(SET_PROPERTY, (op) -> { + final Bean2 bean2 = new Bean2(); + call(named("name", op), bean2, "blah"); + Assert.assertEquals(bean2.name, "blah"); + }); + } + + private static final Pattern GET_ELEMENT_THEN_PROPERTY_PATTERN = Pattern.compile(".*GET_ELEMENT.*GET_PROPERTY.*"); + + @Test + public static void testUnnamedElementAndPropertyGetter() { + final Map map = new HashMap<>(); + map.put("empty", true); + testGetterPermutations(GET_ELEMENT_THEN_PROPERTY_PATTERN, 4, (op) -> Assert.assertEquals(true, call(op, map, "empty"))); + } + + @Test + public static void testNamedElementAndPropertyGetter() { + final Map map = new HashMap<>(); + map.put("empty", true); + testGetterPermutations(GET_ELEMENT_THEN_PROPERTY_PATTERN, 4, (op) -> Assert.assertEquals(true, call(named("empty", op), map))); + } + + private static final Pattern GET_PROPERTY_THEN_ELEMENT_PATTERN = Pattern.compile(".*GET_PROPERTY.*GET_ELEMENT.*"); + + @Test + public static void testUnnamedPropertyAndElementGetter() { + final Map map = new HashMap<>(); + map.put("empty", true); + testGetterPermutations(GET_PROPERTY_THEN_ELEMENT_PATTERN, 4, (op) -> Assert.assertEquals(false, call(op, map, "empty"))); + } + + @Test + public static void testNamedPropertyAndElementGetter() { + final Map map = new HashMap<>(); + map.put("empty", true); + testGetterPermutations(GET_PROPERTY_THEN_ELEMENT_PATTERN, 4, (op) -> Assert.assertEquals(false, call(named("empty", op), map))); + } + + public static class MapWithProperty extends HashMap { + private String name; + + public void setName(final String name) { + this.name = name; + } + } + + @Test + public static void testUnnamedPropertyAndElementSetter() { + final MapWithProperty map = new MapWithProperty(); + map.put("name", "element"); + + call(ops(SET_PROPERTY, SET_ELEMENT), map, "name", "property"); + Assert.assertEquals("property", map.name); + Assert.assertEquals("element", map.get("name")); + + call(ops(SET_ELEMENT, SET_PROPERTY), map, "name", "element2"); + Assert.assertEquals("property", map.name); + Assert.assertEquals("element2", map.get("name")); + } + + private static Operation[] GETTER_PERMUTATIONS = new Operation[] { + GET_PROPERTY, + GET_METHOD, + GET_ELEMENT, + ops(GET_PROPERTY, GET_ELEMENT), + ops(GET_PROPERTY, GET_METHOD), + ops(GET_ELEMENT, GET_PROPERTY), + ops(GET_ELEMENT, GET_METHOD), + ops(GET_METHOD, GET_PROPERTY), + ops(GET_METHOD, GET_ELEMENT), + ops(GET_PROPERTY, GET_ELEMENT, GET_METHOD), + ops(GET_PROPERTY, GET_METHOD, GET_ELEMENT), + ops(GET_ELEMENT, GET_PROPERTY, GET_METHOD), + ops(GET_ELEMENT, GET_METHOD, GET_PROPERTY), + ops(GET_METHOD, GET_PROPERTY, GET_ELEMENT), + ops(GET_METHOD, GET_ELEMENT, GET_PROPERTY), + }; + + private static Operation[] SETTER_PERMUTATIONS = new Operation[] { + SET_PROPERTY, + SET_ELEMENT, + ops(SET_PROPERTY, SET_ELEMENT), + ops(SET_ELEMENT, SET_PROPERTY) + }; + + private static void testPermutations(final Operation[] ops, final StandardOperation requiredOp, final int expectedCount, final Consumer test) { + testPermutationsWithFilter(ops, (op)->CompositeOperation.contains(op, requiredOp), expectedCount, test); + } + + private static void testPermutations(final Operation[] ops, final Pattern regex, final int expectedCount, final Consumer test) { + testPermutationsWithFilter(ops, (op)->regex.matcher(op.toString()).matches(), expectedCount, test); + } + + private static void testPermutationsWithFilter(final Operation[] ops, final Predicate filter, final int expectedCount, final Consumer test) { + final int[] counter = new int[1]; + Stream.of(ops).filter(filter).forEach((op)-> { counter[0]++; test.accept(op); }); + Assert.assertEquals(counter[0], expectedCount); + } + + private static void testGetterPermutations(final StandardOperation requiredOp, final Consumer test) { + testPermutations(GETTER_PERMUTATIONS, requiredOp, 11, test); + } + + private static void testGetterPermutations(final Pattern regex, final int expectedCount, final Consumer test) { + testPermutations(GETTER_PERMUTATIONS, regex, expectedCount, test); + } + + private static void testSetterPermutations(final StandardOperation requiredOp, final Consumer test) { + testPermutations(SETTER_PERMUTATIONS, requiredOp, 3, test); + } + + private static Object call(final Operation op, final Object... args) { + try { + return new DynamicLinkerFactory().createLinker().link( + new SimpleRelinkableCallSite(new CallSiteDescriptor( + MethodHandles.publicLookup(), op, t(args.length)))) + .dynamicInvoker().invokeWithArguments(args); + } catch (final Error|RuntimeException e) { + throw e; + } catch (final Throwable t) { + throw new RuntimeException(t); + } + } + + private static Object call(final Object... args) { + return call(CALL, args); + } + + private static Operation named(final Object name, final Operation... ops) { + return new NamedOperation(ops(ops), name); + } + + private static Operation ops(final Operation... ops) { + return ops.length == 1 ? ops[0] : new CompositeOperation(ops); + } + + private static MethodType t(final int argCount) { + return MethodType.methodType(Object.class, Collections.nCopies(argCount, Object.class)); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/jdk/dynalink/beans/test/CallerSensitiveTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/jdk/dynalink/beans/test/CallerSensitiveTest.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please 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.dynalink.beans.test; + +import jdk.dynalink.beans.BeansLinker; +import jdk.nashorn.test.models.ClassLoaderAware; +import org.testng.annotations.Test; + +@SuppressWarnings("javadoc") +public class CallerSensitiveTest { + @Test + public void testCallerSensitive() { + BeansLinker.getLinkerForClass(ClassLoaderAware.class); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/jdk/dynalink/linker/support/test/LookupTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/jdk/dynalink/linker/support/test/LookupTest.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,273 @@ +/* + * 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.dynalink.linker.support.test; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import jdk.dynalink.linker.support.Lookup; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +// Tests for jdk.dynalink.linker.support.Lookup class. + +public class LookupTest { + private static final MethodHandles.Lookup MY_LOOKUP = MethodHandles.lookup(); + + private static MethodHandles.Lookup getLookup(final boolean publicLookup) { + return publicLookup? MethodHandles.publicLookup() : MY_LOOKUP; + } + + // test constructors, methods used for lookup + @SuppressWarnings("unused") + public LookupTest() {} + + @SuppressWarnings("unused") + private LookupTest(final int unused) {} + + @SuppressWarnings("unused") + private void privateFunc() {} + + @SuppressWarnings("unused") + protected void protectedFunc() {} + + @SuppressWarnings("unused") + private static void privateStaticFunc() {} + + @SuppressWarnings("unused") + private int myIntField = 0; + + @SuppressWarnings("unused") + @DataProvider + private static Object[][] flags() { + return new Object[][]{ + {Boolean.FALSE}, + {Boolean.TRUE} + }; + } + + @Test(dataProvider = "flags") + public void unreflectTest(final boolean publicLookup) throws NoSuchMethodException { + MethodHandle mh = Lookup.unreflect(getLookup(publicLookup), LookupTest.class.getMethod("unreflectTest", Boolean.TYPE)); + Assert.assertNotNull(mh); + } + + @Test + public void unreflectTest2() throws NoSuchMethodException { + MethodHandle mh = Lookup.PUBLIC.unreflect(LookupTest.class.getMethod("unreflectTest", Boolean.TYPE)); + Assert.assertNotNull(mh); + } + + @Test(dataProvider = "flags") + public void unreflectNegativeTest(final boolean publicLookup) throws NoSuchMethodException { + try { + MethodHandle mh = Lookup.unreflect(getLookup(publicLookup), + LookupTest.class.getDeclaredMethod("privateFunc")); + if (publicLookup) { + throw new RuntimeException("should have thrown Error"); + } + Assert.assertNotNull(mh); + } catch (Error err) { + Assert.assertTrue(publicLookup); + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test + public void unreflectNegativeTest2() throws NoSuchMethodException { + try { + Lookup.PUBLIC.unreflect(LookupTest.class.getDeclaredMethod("privateFunc")); + throw new RuntimeException("should have thrown Error"); + } catch (Error err) { + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test(dataProvider = "flags") + public void unreflectConstructorTest(final boolean publicLookup) throws NoSuchMethodException { + MethodHandle mh = Lookup.unreflectConstructor(getLookup(publicLookup), LookupTest.class.getConstructor()); + Assert.assertNotNull(mh); + } + + @Test + public void unreflectConstructorTest2() throws NoSuchMethodException { + MethodHandle mh = Lookup.PUBLIC.unreflectConstructor(LookupTest.class.getConstructor()); + Assert.assertNotNull(mh); + } + + @Test(dataProvider = "flags") + public void unreflectConstructorNegativeTest(final boolean publicLookup) throws NoSuchMethodException { + try { + MethodHandle mh = Lookup.unreflectConstructor(getLookup(publicLookup), + LookupTest.class.getDeclaredConstructor(Integer.TYPE)); + if (publicLookup) { + throw new RuntimeException("should have thrown Error"); + } + Assert.assertNotNull(mh); + } catch (Error err) { + Assert.assertTrue(publicLookup); + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test + public void unreflectConstructorNegativeTest2() throws NoSuchMethodException { + try { + Lookup.PUBLIC.unreflectConstructor( + LookupTest.class.getDeclaredConstructor(Integer.TYPE)); + throw new RuntimeException("should have thrown Error"); + } catch (Error err) { + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test(dataProvider = "flags") + public void findOwnStaticTest(final boolean publicLookup) { + try { + MethodHandle mh = Lookup.findOwnStatic(getLookup(publicLookup), "getLookup", + MethodHandles.Lookup.class, Boolean.TYPE); + if (publicLookup) { + throw new RuntimeException("should have thrown Error"); + } + Assert.assertNotNull(mh); + } catch (Error err) { + Assert.assertTrue(publicLookup); + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test + public void findOwnStaticTest2() { + try { + Lookup.PUBLIC.findStatic(LookupTest.class, "getLookup", + MethodType.methodType(MethodHandles.Lookup.class, Boolean.TYPE)); + throw new RuntimeException("should have thrown Error"); + } catch (Error err) { + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test(dataProvider = "flags") + public void findOwnSepcialTest(final boolean publicLookup) { + try { + MethodHandle mh = Lookup.findOwnSpecial(getLookup(publicLookup), "privateFunc", Void.TYPE); + if (publicLookup) { + throw new RuntimeException("should have thrown Error"); + } + Assert.assertNotNull(mh); + } catch (Error err) { + Assert.assertTrue(publicLookup); + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test + public void findOwnSepcialTest2() { + try { + Lookup.PUBLIC.findOwnSpecial("privateFunc", Void.TYPE); + throw new RuntimeException("should have thrown Error"); + } catch (Error err) { + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test(dataProvider = "flags") + public void findGetterTest(final boolean publicLookup) { + try { + MethodHandle mh = new Lookup(getLookup(publicLookup)).findGetter(LookupTest.class, "myIntField", Integer.TYPE); + if (publicLookup) { + throw new RuntimeException("should have thrown Error"); + } + Assert.assertNotNull(mh); + } catch (Error err) { + Assert.assertTrue(publicLookup); + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test + public void findGetterTest2() { + try { + Lookup.PUBLIC.findGetter(LookupTest.class, "myIntField", Integer.TYPE); + throw new RuntimeException("should have thrown Error"); + } catch (Error err) { + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test(dataProvider = "flags") + public void findVirtualTest(final boolean publicLookup) { + try { + MethodHandle mh = new Lookup(getLookup(publicLookup)).findVirtual(LookupTest.class, "protectedFunc", + MethodType.methodType(Void.TYPE)); + if (publicLookup) { + throw new RuntimeException("should have thrown Error"); + } + Assert.assertNotNull(mh); + } catch (Error err) { + Assert.assertTrue(publicLookup); + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test + public void findVirtualTest2() { + try { + Lookup.PUBLIC.findVirtual(LookupTest.class, "protectedFunc", + MethodType.methodType(Void.TYPE)); + throw new RuntimeException("should have thrown Error"); + } catch (Error err) { + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test(dataProvider = "flags") + public void findStaticTest(final boolean publicLookup) { + try { + MethodHandle mh = new Lookup(getLookup(publicLookup)).findStatic(LookupTest.class, "privateStaticFunc", + MethodType.methodType(Void.TYPE)); + if (publicLookup) { + throw new RuntimeException("should have thrown Error"); + } + Assert.assertNotNull(mh); + } catch (Error err) { + Assert.assertTrue(publicLookup); + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } + + @Test + public void findStaticTest2() { + try { + Lookup.PUBLIC.findStatic(LookupTest.class, "privateStaticFunc", + MethodType.methodType(Void.TYPE)); + throw new RuntimeException("should have thrown Error"); + } catch (Error err) { + Assert.assertTrue(err instanceof NoSuchMethodError || err instanceof IllegalAccessError); + } + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/jdk/dynalink/support/test/CallSiteTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/jdk/dynalink/support/test/CallSiteTest.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,113 @@ +/* + * 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.dynalink.support.test; + +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.DynamicLinker; +import jdk.dynalink.DynamicLinkerFactory; +import jdk.dynalink.NamedOperation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardedInvocation; +import jdk.dynalink.support.SimpleRelinkableCallSite; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class CallSiteTest { + @Test + public void testInitialize() { + final DynamicLinkerFactory factory = new DynamicLinkerFactory(); + final DynamicLinker linker = factory.createLinker(); + final MethodType mt = MethodType.methodType(Object.class, Object.class); + final boolean[] initializeCalled = { Boolean.FALSE }; + linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( + MethodHandles.publicLookup(), new NamedOperation(StandardOperation.GET_PROPERTY, "DO_NOT_CARE"), mt)) { + @Override + public void initialize(final MethodHandle relinkAndInvoke) { + initializeCalled[0] = Boolean.TRUE; + super.initialize(relinkAndInvoke); + } + }); + + Assert.assertTrue(initializeCalled[0]); + } + + @Test + public void testRelink() { + final DynamicLinkerFactory factory = new DynamicLinkerFactory(); + final DynamicLinker linker = factory.createLinker(); + final MethodType mt = MethodType.methodType(Object.class, Object.class); + final boolean[] relinkCalled = { Boolean.FALSE }; + final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( + MethodHandles.publicLookup(), new NamedOperation(StandardOperation.GET_PROPERTY, "class"), mt)) { + @Override + public void relink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { + relinkCalled[0] = Boolean.TRUE; + super.relink(guardedInvocation, relinkAndInvoke); + } + }); + + Assert.assertFalse(relinkCalled[0]); + try { + cs.getTarget().invoke(new Object()); + } catch (final Throwable th) {} + + Assert.assertTrue(relinkCalled[0]); + } + + @Test + public void testResetAndRelink() { + final DynamicLinkerFactory factory = new DynamicLinkerFactory(); + factory.setUnstableRelinkThreshold(1); + final DynamicLinker linker = factory.createLinker(); + final MethodType mt = MethodType.methodType(Object.class, Object.class); + final boolean[] resetAndRelinkCalled = { Boolean.FALSE }; + final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( + MethodHandles.publicLookup(), new NamedOperation(StandardOperation.GET_PROPERTY, "length"), mt)) { + @Override + public void resetAndRelink(final GuardedInvocation guardedInvocation, final MethodHandle relinkAndInvoke) { + resetAndRelinkCalled[0] = Boolean.TRUE; + super.resetAndRelink(guardedInvocation, relinkAndInvoke); + } + }); + + Assert.assertFalse(resetAndRelinkCalled[0]); + try { + cs.getTarget().invoke(new Object[] {}); + } catch (final Throwable th) {} + + Assert.assertFalse(resetAndRelinkCalled[0]); + try { + cs.getTarget().invoke(new ArrayList()); + } catch (final Throwable th) {} + + Assert.assertTrue(resetAndRelinkCalled[0]); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/jdk/dynalink/test/DynamicLinkerFactoryTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/jdk/dynalink/test/DynamicLinkerFactoryTest.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,257 @@ +/* + * 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.dynalink.test; + +import java.lang.invoke.CallSite; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.util.List; +import java.util.ServiceConfigurationError; +import jdk.dynalink.CallSiteDescriptor; +import jdk.dynalink.DynamicLinker; +import jdk.dynalink.DynamicLinkerFactory; +import jdk.dynalink.NoSuchDynamicMethodException; +import jdk.dynalink.Operation; +import jdk.dynalink.StandardOperation; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; +import jdk.dynalink.support.SimpleRelinkableCallSite; +import jdk.dynalink.linker.GuardedInvocation; +import org.testng.Assert; +import org.testng.annotations.Test; + +@SuppressWarnings("javadoc") +public class DynamicLinkerFactoryTest { + + private static DynamicLinkerFactory newDynamicLinkerFactory(final boolean resetClassLoader) { + final DynamicLinkerFactory factory = new DynamicLinkerFactory(); + if (resetClassLoader) { + factory.setClassLoader(null); + } + return factory; + } + + @Test + public void callSiteCreationTest() { + final DynamicLinkerFactory factory = newDynamicLinkerFactory(true); + final DynamicLinker linker = factory.createLinker(); + final StandardOperation[] operations = StandardOperation.values(); + final MethodType mt = MethodType.methodType(Object.class, Object.class); + for (final Operation op : operations) { + final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( + MethodHandles.publicLookup(), op, mt))); + Assert.assertNotNull(cs); + Assert.assertEquals(cs.type(), mt); + Assert.assertNotNull(cs.getTarget()); + } + } + + @Test + public void fallbackLinkerTest() { + final DynamicLinkerFactory factory = newDynamicLinkerFactory(true); + final Operation myOperation = new Operation() { + }; + final boolean[] reachedFallback = { false }; + factory.setFallbackLinkers((GuardingDynamicLinker) (LinkRequest linkRequest, LinkerServices linkerServices) -> { + Assert.assertEquals(linkRequest.getCallSiteDescriptor().getOperation(), myOperation); + reachedFallback[0] = true; + return null; + }); + + final DynamicLinker linker = factory.createLinker(); + final MethodType mt = MethodType.methodType(Object.class); + final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( + MethodHandles.publicLookup(), myOperation, mt))); + + // linking the call site initially does not invoke the linkers! + Assert.assertFalse(reachedFallback[0]); + try { + cs.getTarget().invoke(); + } catch (NoSuchDynamicMethodException nsdm) { + // we do expect NoSuchDynamicMethod! + // because our dummy fallback linker returns null! + } catch (Throwable th) { + throw new RuntimeException("should not reach here with: " + th); + } + + // check that the control reached fallback linker! + Assert.assertTrue(reachedFallback[0]); + } + + @Test + public void priorityLinkerTest() { + final DynamicLinkerFactory factory = newDynamicLinkerFactory(true); + final Operation myOperation = new Operation() { + }; + final boolean[] reachedProrityLinker = { false }; + factory.setPrioritizedLinker((GuardingDynamicLinker) (LinkRequest linkRequest, LinkerServices linkerServices) -> { + Assert.assertEquals(linkRequest.getCallSiteDescriptor().getOperation(), myOperation); + reachedProrityLinker[0] = true; + return null; + }); + + final DynamicLinker linker = factory.createLinker(); + final MethodType mt = MethodType.methodType(Object.class); + final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( + MethodHandles.publicLookup(), myOperation, mt))); + + // linking the call site initially does not invoke the linkers! + Assert.assertFalse(reachedProrityLinker[0]); + try { + cs.getTarget().invoke(); + } catch (NoSuchDynamicMethodException nsdm) { + // we do expect NoSuchDynamicMethod! + // because our dummy priority linker returns null! + } catch (Throwable th) { + throw new RuntimeException("should not reach here with: " + th); + } + + // check that the control reached fallback linker! + Assert.assertTrue(reachedProrityLinker[0]); + } + + @Test + public void priorityAndFallbackLinkerTest() { + final DynamicLinkerFactory factory = newDynamicLinkerFactory(true); + final Operation myOperation = new Operation() { + }; + final int[] linkerReachCounter = { 0 }; + factory.setPrioritizedLinker((GuardingDynamicLinker) (LinkRequest linkRequest, LinkerServices linkerServices) -> { + Assert.assertEquals(linkRequest.getCallSiteDescriptor().getOperation(), myOperation); + linkerReachCounter[0]++; + return null; + }); + factory.setFallbackLinkers((GuardingDynamicLinker) (LinkRequest linkRequest, LinkerServices linkerServices) -> { + Assert.assertEquals(linkRequest.getCallSiteDescriptor().getOperation(), myOperation); + Assert.assertEquals(linkerReachCounter[0], 1); + linkerReachCounter[0]++; + return null; + }); + + final DynamicLinker linker = factory.createLinker(); + final MethodType mt = MethodType.methodType(Object.class); + final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( + MethodHandles.publicLookup(), myOperation, mt))); + + // linking the call site initially does not invoke the linkers! + Assert.assertEquals(linkerReachCounter[0], 0); + + try { + cs.getTarget().invoke(); + } catch (NoSuchDynamicMethodException nsdm) { + // we do expect NoSuchDynamicMethod! + } catch (Throwable th) { + throw new RuntimeException("should not reach here with: " + th); + } + + Assert.assertEquals(linkerReachCounter[0], 2); + } + + @Test + public void prelinkTransformerTest() throws Throwable { + final DynamicLinkerFactory factory = newDynamicLinkerFactory(true); + final boolean[] reachedPrelinkTransformer = { false }; + + factory.setPrelinkTransformer((GuardedInvocation inv, LinkRequest linkRequest, LinkerServices linkerServices) -> { + reachedPrelinkTransformer[0] = true; + // just identity transformer! + return inv; + }); + + final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class); + final DynamicLinker linker = factory.createLinker(); + final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( + MethodHandles.publicLookup(), StandardOperation.GET_PROPERTY, mt))); + Assert.assertFalse(reachedPrelinkTransformer[0]); + Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class); + Assert.assertTrue(reachedPrelinkTransformer[0]); + } + + @Test + public void internalObjectsFilterTest() throws Throwable { + final DynamicLinkerFactory factory = newDynamicLinkerFactory(true); + final boolean[] reachedInternalObjectsFilter = { false }; + + factory.setInternalObjectsFilter((MethodHandle mh) -> { + reachedInternalObjectsFilter[0] = true; + return mh; + }); + + final MethodType mt = MethodType.methodType(Object.class, Object.class, String.class); + final DynamicLinker linker = factory.createLinker(); + final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( + MethodHandles.publicLookup(), StandardOperation.GET_PROPERTY, mt))); + Assert.assertFalse(reachedInternalObjectsFilter[0]); + Assert.assertEquals(cs.getTarget().invoke(new Object(), "class"), Object.class); + Assert.assertTrue(reachedInternalObjectsFilter[0]); + } + + private static void checkOneAutoLoadingError(final DynamicLinkerFactory factory) { + // expect one error as we have one untrusted linker exporter in META-INF/services + final List autoLoadingErrors = factory.getAutoLoadingErrors(); + // single error ... + Assert.assertFalse(autoLoadingErrors.isEmpty()); + final Throwable cause = autoLoadingErrors.get(0).getCause(); + // .. due to permission check.. + Assert.assertTrue(cause.toString().contains("dynalink.exportLinkersAutomatically")); + } + + @Test + public void autoLoadedLinkerNegativeTest() { + // enable auto loaded linkers + final DynamicLinkerFactory factory = newDynamicLinkerFactory(false); + factory.createLinker(); + checkOneAutoLoadingError(factory); + } + + @Test + public void autoLoadedLinkerTest() { + final DynamicLinkerFactory factory = newDynamicLinkerFactory(false); + final DynamicLinker linker = factory.createLinker(); + + // we should still get one error due to untrusted dynamic linker exporter! + checkOneAutoLoadingError(factory); + + final MethodType mt = MethodType.methodType(Object.class, Object.class); + // create a callsite with TestLinkerOperation + final CallSite cs = linker.link(new SimpleRelinkableCallSite(new CallSiteDescriptor( + MethodHandles.publicLookup(), new TestLinkerOperation(), mt))); + boolean reachedAutoLinker = false; + + + try { + cs.getTarget().invoke(new Object()); + } catch (ReachedAutoLoadedDynamicLinkerException e) { + // TrustedGuardingDynamicLinkerExporter threw exception on TestLinkerOperation as expected! + reachedAutoLinker = true; + } catch (Throwable th) { + throw new RuntimeException(th); + } + + Assert.assertTrue(reachedAutoLinker); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/jdk/dynalink/test/ReachedAutoLoadedDynamicLinkerException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/jdk/dynalink/test/ReachedAutoLoadedDynamicLinkerException.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,33 @@ +/* + * 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.dynalink.test; + +/** + * Exception used to signal to the test method that the control has reached auto loaded + * dynamic linker. + */ +public final class ReachedAutoLoadedDynamicLinkerException extends RuntimeException { +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/jdk/dynalink/test/TestLinkerOperation.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/jdk/dynalink/test/TestLinkerOperation.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,31 @@ +/* + * 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.dynalink.test; + +import jdk.dynalink.Operation; + +public final class TestLinkerOperation implements Operation { +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/jdk/dynalink/test/TrustedGuardingDynamicLinkerExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/jdk/dynalink/test/TrustedGuardingDynamicLinkerExporter.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,56 @@ +/* + * 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.dynalink.test; + +import java.util.ArrayList; +import java.util.List; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.GuardingDynamicLinkerExporter; +import jdk.dynalink.linker.LinkRequest; +import jdk.dynalink.linker.LinkerServices; + +/** + * A trusted linker exporter (build file gives appropriate permission to the jar containing this class!). + */ +public final class TrustedGuardingDynamicLinkerExporter extends GuardingDynamicLinkerExporter { + + @Override + public List get() { + final ArrayList linkers = new ArrayList<>(); + linkers.add((GuardingDynamicLinker) (LinkRequest linkRequest, LinkerServices linkerServices) -> { + // handle only the TestLinkerOperation instances + if (linkRequest.getCallSiteDescriptor().getOperation() instanceof TestLinkerOperation) { + System.out.println("inside " + this.getClass().getName()); + // throw exception to signal to the test method that the control has reached here! + throw new ReachedAutoLoadedDynamicLinkerException(); + } else { + // any other operation! + return null; + } + }); + return linkers; + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/jdk/dynalink/test/UntrustedGuardingDynamicLinkerExporter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nashorn/test/src/jdk/dynalink/test/UntrustedGuardingDynamicLinkerExporter.java Wed Dec 02 09:37:26 2015 -0800 @@ -0,0 +1,39 @@ +/* + * 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.dynalink.test; + +import java.util.List; +import jdk.dynalink.linker.GuardingDynamicLinker; +import jdk.dynalink.linker.GuardingDynamicLinkerExporter; + +/** + * Untrusted dummy guarding dynamic linker exporter - used in negative auto linker test + */ +public class UntrustedGuardingDynamicLinkerExporter extends GuardingDynamicLinkerExporter { + @Override + public List get() { + throw new UnsupportedOperationException("Not supported yet."); + } +} diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/jdk/internal/dynalink/beans/test/CallerSensitiveTest.java --- a/nashorn/test/src/jdk/internal/dynalink/beans/test/CallerSensitiveTest.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/test/src/jdk/internal/dynalink/beans/test/CallerSensitiveTest.java Wed Dec 02 09:37:26 2015 -0800 @@ -25,7 +25,7 @@ package jdk.internal.dynalink.beans.test; -import jdk.internal.dynalink.beans.BeansLinker; +import jdk.dynalink.beans.BeansLinker; import jdk.nashorn.test.models.ClassLoaderAware; import org.testng.annotations.Test; diff -r 5ac6287ec71a -r 84eaea8d0574 nashorn/test/src/jdk/nashorn/test/models/InternalRunnableSuperclass.java --- a/nashorn/test/src/jdk/nashorn/test/models/InternalRunnableSuperclass.java Wed Jul 05 21:04:26 2017 +0200 +++ b/nashorn/test/src/jdk/nashorn/test/models/InternalRunnableSuperclass.java Wed Dec 02 09:37:26 2015 -0800 @@ -25,7 +25,7 @@ package jdk.nashorn.test.models; -import jdk.internal.dynalink.beans.StaticClass; +import jdk.dynalink.beans.StaticClass; import jdk.nashorn.internal.test.models.InternalRunnable; /**