src/jdk/nashorn/internal/runtime/linker/Bootstrap.java

Thu, 10 Sep 2015 09:59:23 +0530

author
sundar
date
Thu, 10 Sep 2015 09:59:23 +0530
changeset 1526
d731e6ba5037
parent 1521
eed10d5bf2f4
child 1527
340b1462f3e2
permissions
-rw-r--r--

8130888: Typos in nashorn sources
Reviewed-by: hannesw, mhaupt

     1 /*
     2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package jdk.nashorn.internal.runtime.linker;
    28 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
    29 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
    31 import java.lang.invoke.CallSite;
    32 import java.lang.invoke.ConstantCallSite;
    33 import java.lang.invoke.MethodHandle;
    34 import java.lang.invoke.MethodHandles;
    35 import java.lang.invoke.MethodHandles.Lookup;
    36 import java.lang.invoke.MethodType;
    37 import jdk.internal.dynalink.CallSiteDescriptor;
    38 import jdk.internal.dynalink.DynamicLinker;
    39 import jdk.internal.dynalink.DynamicLinkerFactory;
    40 import jdk.internal.dynalink.GuardedInvocationFilter;
    41 import jdk.internal.dynalink.beans.BeansLinker;
    42 import jdk.internal.dynalink.beans.StaticClass;
    43 import jdk.internal.dynalink.linker.GuardedInvocation;
    44 import jdk.internal.dynalink.linker.LinkRequest;
    45 import jdk.internal.dynalink.linker.LinkerServices;
    46 import jdk.internal.dynalink.linker.MethodTypeConversionStrategy;
    47 import jdk.internal.dynalink.support.TypeUtilities;
    48 import jdk.nashorn.api.scripting.JSObject;
    49 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
    50 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
    51 import jdk.nashorn.internal.lookup.MethodHandleFactory;
    52 import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
    53 import jdk.nashorn.internal.objects.ScriptFunctionImpl;
    54 import jdk.nashorn.internal.runtime.ECMAException;
    55 import jdk.nashorn.internal.runtime.JSType;
    56 import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
    57 import jdk.nashorn.internal.runtime.ScriptFunction;
    58 import jdk.nashorn.internal.runtime.ScriptRuntime;
    59 import jdk.nashorn.internal.runtime.options.Options;
    61 /**
    62  * This class houses bootstrap method for invokedynamic instructions generated by compiler.
    63  */
    64 public final class Bootstrap {
    65     /** Reference to the seed boostrap function */
    66     public static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "bootstrap", CallSite.class, Lookup.class, String.class, MethodType.class, int.class);
    68     private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
    70     private static final MethodHandle VOID_TO_OBJECT = MH.constant(Object.class, ScriptRuntime.UNDEFINED);
    72     /**
    73      * The default dynalink relink threshold for megamorphism is 8. In the case
    74      * of object fields only, it is fine. However, with dual fields, in order to get
    75      * performance on benchmarks with a lot of object instantiation and then field
    76      * reassignment, it can take slightly more relinks to become stable with type
    77      * changes swapping out an entire property map and making a map guard fail.
    78      * Since we need to set this value statically it must work with possibly changing
    79      * optimistic types and dual fields settings. A higher value does not seem to have
    80      * any other negative performance implication when running with object-only fields,
    81      * so we choose a higher value here.
    82      *
    83      * See for example octane.gbemu, run with --log=fields:warning to study
    84      * megamorphic behavior
    85      */
    86     private static final int NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD = 16;
    88     // do not create me!!
    89     private Bootstrap() {
    90     }
    92     private static final DynamicLinker dynamicLinker;
    93     static {
    94         final DynamicLinkerFactory factory = new DynamicLinkerFactory();
    95         final NashornBeansLinker nashornBeansLinker = new NashornBeansLinker();
    96         factory.setPrioritizedLinkers(
    97             new NashornLinker(),
    98             new NashornPrimitiveLinker(),
    99             new NashornStaticClassLinker(),
   100             new BoundCallableLinker(),
   101             new JavaSuperAdapterLinker(),
   102             new JSObjectLinker(nashornBeansLinker),
   103             new BrowserJSObjectLinker(nashornBeansLinker),
   104             new ReflectionCheckLinker());
   105         factory.setFallbackLinkers(nashornBeansLinker, new NashornBottomLinker());
   106         factory.setSyncOnRelink(true);
   107         factory.setPrelinkFilter(new GuardedInvocationFilter() {
   108             @Override
   109             public GuardedInvocation filter(final GuardedInvocation inv, final LinkRequest request, final LinkerServices linkerServices) {
   110                 final CallSiteDescriptor desc = request.getCallSiteDescriptor();
   111                 return OptimisticReturnFilters.filterOptimisticReturnValue(inv, desc).asType(linkerServices, desc.getMethodType());
   112             }
   113         });
   114         factory.setAutoConversionStrategy(new MethodTypeConversionStrategy() {
   115             @Override
   116             public MethodHandle asType(final MethodHandle target, final MethodType newType) {
   117                 return unboxReturnType(target, newType);
   118             }
   119         });
   120         factory.setInternalObjectsFilter(NashornBeansLinker.createHiddenObjectFilter());
   121         final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD);
   122         if (relinkThreshold > -1) {
   123             factory.setUnstableRelinkThreshold(relinkThreshold);
   124         }
   126         // Linkers for any additional language runtimes deployed alongside Nashorn will be picked up by the factory.
   127         factory.setClassLoader(Bootstrap.class.getClassLoader());
   129         dynamicLinker = factory.createLinker();
   130     }
   132     /**
   133      * Returns if the given object is a "callable"
   134      * @param obj object to be checked for callability
   135      * @return true if the obj is callable
   136      */
   137     public static boolean isCallable(final Object obj) {
   138         if (obj == ScriptRuntime.UNDEFINED || obj == null) {
   139             return false;
   140         }
   142         return obj instanceof ScriptFunction ||
   143             isJSObjectFunction(obj) ||
   144             BeansLinker.isDynamicMethod(obj) ||
   145             obj instanceof BoundCallable ||
   146             isFunctionalInterfaceObject(obj) ||
   147             obj instanceof StaticClass;
   148     }
   150     /**
   151      * Returns true if the given object is a strict callable
   152      * @param callable the callable object to be checked for strictness
   153      * @return true if the obj is a strict callable, false if it is a non-strict callable.
   154      * @throws ECMAException with {@code TypeError} if the object is not a callable.
   155      */
   156     public static boolean isStrictCallable(final Object callable) {
   157         if (callable instanceof ScriptFunction) {
   158             return ((ScriptFunction)callable).isStrict();
   159         } else if (isJSObjectFunction(callable)) {
   160             return ((JSObject)callable).isStrictFunction();
   161         } else if (callable instanceof BoundCallable) {
   162             return isStrictCallable(((BoundCallable)callable).getCallable());
   163         } else if (BeansLinker.isDynamicMethod(callable) || callable instanceof StaticClass) {
   164             return false;
   165         }
   166         throw notFunction(callable);
   167     }
   169     private static ECMAException notFunction(final Object obj) {
   170         return typeError("not.a.function", ScriptRuntime.safeToString(obj));
   171     }
   173     private static boolean isJSObjectFunction(final Object obj) {
   174         return obj instanceof JSObject && ((JSObject)obj).isFunction();
   175     }
   177     /**
   178      * Returns if the given object is a dynalink Dynamic method
   179      * @param obj object to be checked
   180      * @return true if the obj is a dynamic method
   181      */
   182     public static boolean isDynamicMethod(final Object obj) {
   183         return BeansLinker.isDynamicMethod(obj instanceof BoundCallable ? ((BoundCallable)obj).getCallable() : obj);
   184     }
   186     /**
   187      * Returns if the given object is an instance of an interface annotated with
   188      * java.lang.FunctionalInterface
   189      * @param obj object to be checked
   190      * @return true if the obj is an instance of @FunctionalInterface interface
   191      */
   192     public static boolean isFunctionalInterfaceObject(final Object obj) {
   193         return !JSType.isPrimitive(obj) && (NashornBeansLinker.getFunctionalInterfaceMethodName(obj.getClass()) != null);
   194     }
   196     /**
   197      * Create a call site and link it for Nashorn. This version of the method conforms to the invokedynamic bootstrap
   198      * method expected signature and is referenced from Nashorn generated bytecode as the bootstrap method for all
   199      * invokedynamic instructions.
   200      * @param lookup MethodHandle lookup. Ignored as Nashorn only uses public lookup.
   201      * @param opDesc Dynalink dynamic operation descriptor.
   202      * @param type   Method type.
   203      * @param flags  flags for call type, trace/profile etc.
   204      * @return CallSite with MethodHandle to appropriate method or null if not found.
   205      */
   206     public static CallSite bootstrap(final Lookup lookup, final String opDesc, final MethodType type, final int flags) {
   207         return dynamicLinker.link(LinkerCallSite.newLinkerCallSite(lookup, opDesc, type, flags));
   208     }
   210     /**
   211      * Boostrapper for math calls that may overflow
   212      * @param lookup         lookup
   213      * @param name           name of operation
   214      * @param type           method type
   215      * @param programPoint   program point to bind to callsite
   216      *
   217      * @return callsite for a math intrinsic node
   218      */
   219     public static CallSite mathBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int programPoint) {
   220         final MethodHandle mh;
   221         switch (name) {
   222         case "iadd":
   223             mh = JSType.ADD_EXACT.methodHandle();
   224             break;
   225         case "isub":
   226             mh = JSType.SUB_EXACT.methodHandle();
   227             break;
   228         case "imul":
   229             mh = JSType.MUL_EXACT.methodHandle();
   230             break;
   231         case "idiv":
   232             mh = JSType.DIV_EXACT.methodHandle();
   233             break;
   234         case "irem":
   235             mh = JSType.REM_EXACT.methodHandle();
   236             break;
   237         case "ineg":
   238             mh = JSType.NEGATE_EXACT.methodHandle();
   239             break;
   240         case "ladd":
   241             mh = JSType.ADD_EXACT_LONG.methodHandle();
   242             break;
   243         case "lsub":
   244             mh = JSType.SUB_EXACT_LONG.methodHandle();
   245             break;
   246         case "lmul":
   247             mh = JSType.MUL_EXACT_LONG.methodHandle();
   248             break;
   249         case "ldiv":
   250             mh = JSType.DIV_EXACT_LONG.methodHandle();
   251             break;
   252         case "lrem":
   253             mh = JSType.REM_EXACT_LONG.methodHandle();
   254             break;
   255         case "lneg":
   256             mh = JSType.NEGATE_EXACT_LONG.methodHandle();
   257             break;
   258         default:
   259             throw new AssertionError("unsupported math intrinsic");
   260         }
   261         return new ConstantCallSite(MH.insertArguments(mh, mh.type().parameterCount() - 1, programPoint));
   262     }
   264     /**
   265      * Returns a dynamic invoker for a specified dynamic operation using the public lookup. You can use this method to
   266      * create a method handle that when invoked acts completely as if it were a Nashorn-linked call site. An overview of
   267      * available dynamic operations can be found in the
   268      * <a href="https://github.com/szegedi/dynalink/wiki/User-Guide-0.6">Dynalink User Guide</a>, but we'll show few
   269      * examples here:
   270      * <ul>
   271      *   <li>Get a named property with fixed name:
   272      *     <pre>
   273      * MethodHandle getColor = Boostrap.createDynamicInvoker("dyn:getProp:color", Object.class, Object.class);
   274      * Object obj = ...; // somehow obtain the object
   275      * Object color = getColor.invokeExact(obj);
   276      *     </pre>
   277      *   </li>
   278      *   <li>Get a named property with variable name:
   279      *     <pre>
   280      * MethodHandle getProperty = Boostrap.createDynamicInvoker("dyn:getElem", Object.class, Object.class, String.class);
   281      * Object obj = ...; // somehow obtain the object
   282      * Object color = getProperty.invokeExact(obj, "color");
   283      * Object shape = getProperty.invokeExact(obj, "shape");
   284      * MethodHandle getNumProperty = Boostrap.createDynamicInvoker("dyn:getElem", Object.class, Object.class, int.class);
   285      * Object elem42 = getNumProperty.invokeExact(obj, 42);
   286      *     </pre>
   287      *   </li>
   288      *   <li>Set a named property with fixed name:
   289      *     <pre>
   290      * MethodHandle setColor = Boostrap.createDynamicInvoker("dyn:setProp:color", void.class, Object.class, Object.class);
   291      * Object obj = ...; // somehow obtain the object
   292      * setColor.invokeExact(obj, Color.BLUE);
   293      *     </pre>
   294      *   </li>
   295      *   <li>Set a property with variable name:
   296      *     <pre>
   297      * MethodHandle setProperty = Boostrap.createDynamicInvoker("dyn:setElem", void.class, Object.class, String.class, Object.class);
   298      * Object obj = ...; // somehow obtain the object
   299      * setProperty.invokeExact(obj, "color", Color.BLUE);
   300      * setProperty.invokeExact(obj, "shape", Shape.CIRCLE);
   301      *     </pre>
   302      *   </li>
   303      *   <li>Call a function on an object; two-step variant. This is the actual variant used by Nashorn-generated code:
   304      *     <pre>
   305      * MethodHandle findFooFunction = Boostrap.createDynamicInvoker("dyn:getMethod:foo", Object.class, Object.class);
   306      * Object obj = ...; // somehow obtain the object
   307      * Object foo_fn = findFooFunction.invokeExact(obj);
   308      * MethodHandle callFunctionWithTwoArgs = Boostrap.createDynamicInvoker("dyn:call", Object.class, Object.class, Object.class, Object.class, Object.class);
   309      * // Note: "call" operation takes a function, then a "this" value, then the arguments:
   310      * Object foo_retval = callFunctionWithTwoArgs.invokeExact(foo_fn, obj, arg1, arg2);
   311      *     </pre>
   312      *   </li>
   313      *   <li>Call a function on an object; single-step variant. Although Nashorn doesn't use this variant and never
   314      *   emits any INVOKEDYNAMIC instructions with {@code dyn:getMethod}, it still supports this standard Dynalink
   315      *   operation:
   316      *     <pre>
   317      * MethodHandle callFunctionFooWithTwoArgs = Boostrap.createDynamicInvoker("dyn:callMethod:foo", Object.class, Object.class, Object.class, Object.class);
   318      * Object obj = ...; // somehow obtain the object
   319      * Object foo_retval = callFunctionFooWithTwoArgs.invokeExact(obj, arg1, arg2);
   320      *     </pre>
   321      *   </li>
   322      * </ul>
   323      * Few additional remarks:
   324      * <ul>
   325      * <li>Just as Nashorn works with any Java object, the invokers returned from this method can also be applied to
   326      * arbitrary Java objects in addition to Nashorn JavaScript objects.</li>
   327      * <li>For invoking a named function on an object, you can also use the {@link InvokeByName} convenience class.</li>
   328      * <li>For Nashorn objects {@code getElem}, {@code getProp}, and {@code getMethod} are handled almost identically,
   329      * since JavaScript doesn't distinguish between different kinds of properties on an object. Either can be used with
   330      * fixed property name or a variable property name. The only significant difference is handling of missing
   331      * properties: {@code getMethod} for a missing member will link to a potential invocation of
   332      * {@code __noSuchMethod__} on the object, {@code getProp} for a missing member will link to a potential invocation
   333      * of {@code __noSuchProperty__}, while {@code getElem} for a missing member will link to an empty getter.</li>
   334      * <li>In similar vein, {@code setElem} and {@code setProp} are handled identically on Nashorn objects.</li>
   335      * <li>There's no rule that the variable property identifier has to be a {@code String} for {@code getProp/setProp}
   336      * and {@code int} for {@code getElem/setElem}. You can declare their type to be {@code int}, {@code double},
   337      * {@code Object}, and so on regardless of the kind of the operation.</li>
   338      * <li>You can be as specific in parameter types as you want. E.g. if you know that the receiver of the operation
   339      * will always be {@code ScriptObject}, you can pass {@code ScriptObject.class} as its parameter type. If you happen
   340      * to link to a method that expects different types, (you can use these invokers on POJOs too, after all, and end up
   341      * linking with their methods that have strongly-typed signatures), all necessary conversions allowed by either Java
   342      * or JavaScript will be applied: if invoked methods specify either primitive or wrapped Java numeric types, or
   343      * {@code String} or {@code boolean/Boolean}, then the parameters might be subjected to standard ECMAScript
   344      * {@code ToNumber}, {@code ToString}, and {@code ToBoolean} conversion, respectively. Less obviously, if the
   345      * expected parameter type is a SAM type, and you pass a JavaScript function, a proxy object implementing the SAM
   346      * type and delegating to the function will be passed. Linkage can often be optimized when linkers have more
   347      * specific type information than "everything can be an object".</li>
   348      * <li>You can also be as specific in return types as you want. For return types any necessary type conversion
   349      * available in either Java or JavaScript will be automatically applied, similar to the process described for
   350      * parameters, only in reverse direction:  if you specify any either primitive or wrapped Java numeric type, or
   351      * {@code String} or {@code boolean/Boolean}, then the return values will be subjected to standard ECMAScript
   352      * {@code ToNumber}, {@code ToString}, and {@code ToBoolean} conversion, respectively. Less obviously, if the return
   353      * type is a SAM type, and the return value is a JavaScript function, a proxy object implementing the SAM type and
   354      * delegating to the function will be returned.</li>
   355      * </ul>
   356      * @param opDesc Dynalink dynamic operation descriptor.
   357      * @param rtype the return type for the operation
   358      * @param ptypes the parameter types for the operation
   359      * @return MethodHandle for invoking the operation.
   360      */
   361     public static MethodHandle createDynamicInvoker(final String opDesc, final Class<?> rtype, final Class<?>... ptypes) {
   362         return createDynamicInvoker(opDesc, MethodType.methodType(rtype, ptypes));
   363     }
   365     /**
   366      * Returns a dynamic invoker for a specified dynamic operation using the public lookup. Similar to
   367      * {@link #createDynamicInvoker(String, Class, Class...)} but with an additional parameter to
   368      * set the call site flags of the dynamic invoker.
   369      * @param opDesc Dynalink dynamic operation descriptor.
   370      * @param flags the call site flags for the operation
   371      * @param rtype the return type for the operation
   372      * @param ptypes the parameter types for the operation
   373      * @return MethodHandle for invoking the operation.
   374      */
   375     public static MethodHandle createDynamicInvoker(final String opDesc, final int flags, final Class<?> rtype, final Class<?>... ptypes) {
   376         return bootstrap(MethodHandles.publicLookup(), opDesc, MethodType.methodType(rtype, ptypes), flags).dynamicInvoker();
   377     }
   379     /**
   380      * Returns a dynamic invoker for a specified dynamic operation using the public lookup. Similar to
   381      * {@link #createDynamicInvoker(String, Class, Class...)} but with return and parameter types composed into a
   382      * method type in the signature. See the discussion of that method for details.
   383      * @param opDesc Dynalink dynamic operation descriptor.
   384      * @param type the method type for the operation
   385      * @return MethodHandle for invoking the operation.
   386      */
   387     public static MethodHandle createDynamicInvoker(final String opDesc, final MethodType type) {
   388         return bootstrap(MethodHandles.publicLookup(), opDesc, type, 0).dynamicInvoker();
   389     }
   391     /**
   392      * Binds any object Nashorn can use as a [[Callable]] to a receiver and optionally arguments.
   393      * @param callable the callable to bind
   394      * @param boundThis the bound "this" value.
   395      * @param boundArgs the bound arguments. Can be either null or empty array to signify no arguments are bound.
   396      * @return a bound callable.
   397      * @throws ECMAException with {@code TypeError} if the object is not a callable.
   398      */
   399     public static Object bindCallable(final Object callable, final Object boundThis, final Object[] boundArgs) {
   400         if (callable instanceof ScriptFunctionImpl) {
   401             return ((ScriptFunctionImpl)callable).makeBoundFunction(boundThis, boundArgs);
   402         } else if (callable instanceof BoundCallable) {
   403             return ((BoundCallable)callable).bind(boundArgs);
   404         } else if (isCallable(callable)) {
   405             return new BoundCallable(callable, boundThis, boundArgs);
   406         }
   407         throw notFunction(callable);
   408     }
   410     /**
   411      * Creates a super-adapter for an adapter, that is, an adapter to the adapter that allows invocation of superclass
   412      * methods on it.
   413      * @param adapter the original adapter
   414      * @return a new adapter that can be used to invoke super methods on the original adapter.
   415      */
   416     public static Object createSuperAdapter(final Object adapter) {
   417         return new JavaSuperAdapter(adapter);
   418     }
   420     /**
   421      * If the given class is a reflection-specific class (anything in {@code java.lang.reflect} and
   422      * {@code java.lang.invoke} package, as well a {@link Class} and any subclass of {@link ClassLoader}) and there is
   423      * a security manager in the system, then it checks the {@code nashorn.JavaReflection} {@code RuntimePermission}.
   424      * @param clazz the class being tested
   425      * @param isStatic is access checked for static members (or instance members)
   426      */
   427     public static void checkReflectionAccess(final Class<?> clazz, final boolean isStatic) {
   428         ReflectionCheckLinker.checkReflectionAccess(clazz, isStatic);
   429     }
   431     /**
   432      * Returns the Nashorn's internally used dynamic linker's services object. Note that in code that is processing a
   433      * linking request, you will normally use the {@code LinkerServices} object passed by whatever top-level linker
   434      * invoked the linking (if the call site is in Nashorn-generated code, you'll get this object anyway). You should
   435      * only resort to retrieving a linker services object using this method when you need some linker services (e.g.
   436      * type converter method handles) outside of a code path that is linking a call site.
   437      * @return Nashorn's internal dynamic linker's services object.
   438      */
   439     public static LinkerServices getLinkerServices() {
   440         return dynamicLinker.getLinkerServices();
   441     }
   443     /**
   444      * Takes a guarded invocation, and ensures its method and guard conform to the type of the call descriptor, using
   445      * all type conversions allowed by the linker's services. This method is used by Nashorn's linkers as a last step
   446      * before returning guarded invocations. Most of the code used to produce the guarded invocations does not make an
   447      * effort to coordinate types of the methods, and so a final type adjustment before a guarded invocation is returned
   448      * to the aggregating linker is the responsibility of the linkers themselves.
   449      * @param inv the guarded invocation that needs to be type-converted. Can be null.
   450      * @param linkerServices the linker services object providing the type conversions.
   451      * @param desc the call site descriptor to whose method type the invocation needs to conform.
   452      * @return the type-converted guarded invocation. If input is null, null is returned. If the input invocation
   453      * already conforms to the requested type, it is returned unchanged.
   454      */
   455     static GuardedInvocation asTypeSafeReturn(final GuardedInvocation inv, final LinkerServices linkerServices, final CallSiteDescriptor desc) {
   456         return inv == null ? null : inv.asTypeSafeReturn(linkerServices, desc.getMethodType());
   457     }
   459     /**
   460      * Adapts the return type of the method handle with {@code explicitCastArguments} when it is an unboxing
   461      * conversion. This will ensure that nulls are unwrapped to false or 0.
   462      * @param target the target method handle
   463      * @param newType the desired new type. Note that this method does not adapt the method handle completely to the
   464      * new type, it only adapts the return type; this is allowed as per
   465      * {@link DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy)}, which is what this method
   466      * is used for.
   467      * @return the method handle with adapted return type, if it required an unboxing conversion.
   468      */
   469     private static MethodHandle unboxReturnType(final MethodHandle target, final MethodType newType) {
   470         final MethodType targetType = target.type();
   471         final Class<?> oldReturnType = targetType.returnType();
   472         final Class<?> newReturnType = newType.returnType();
   473         if (TypeUtilities.isWrapperType(oldReturnType)) {
   474             if (newReturnType.isPrimitive()) {
   475                 // The contract of setAutoConversionStrategy is such that the difference between newType and targetType
   476                 // can only be JLS method invocation conversions.
   477                 assert TypeUtilities.isMethodInvocationConvertible(oldReturnType, newReturnType);
   478                 return MethodHandles.explicitCastArguments(target, targetType.changeReturnType(newReturnType));
   479             }
   480         } else if (oldReturnType == void.class && newReturnType == Object.class) {
   481             return MethodHandles.filterReturnValue(target, VOID_TO_OBJECT);
   482         }
   483         return target;
   484     }
   485 }

mercurial