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  */
  25 
  26 package jdk.nashorn.internal.lookup;
  27 
  28 import java.lang.invoke.MethodHandle;
  29 import java.lang.invoke.MethodHandles;
  30 import java.lang.invoke.MethodType;
  31 import java.lang.invoke.SwitchPoint;
  32 import java.lang.reflect.Method;
  33 import java.util.List;
  34 
  35 /**
  36  * Wrapper for all method handle related functions used in Nashorn. This interface only exists
  37  * so that instrumentation can be added to all method handle operations.
  38  */
  39 
  40 public interface MethodHandleFunctionality {
  41     /**
  42      * Wrapper for {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}
  43      *
  44      * @param target  target method handle
  45      * @param pos     start argument index
  46      * @param filters filters
  47      *
  48      * @return filtered handle
  49      */
  50     public MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters);
  51 
  52     /**
  53      * Wrapper for {@link MethodHandles#filterReturnValue(MethodHandle, MethodHandle)}
  54      *
  55      * @param target  target method handle
  56      * @param filter  filter
  57      *
  58      * @return filtered handle
  59      */
  60     public MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter);
  61 
  62     /**
  63      * Wrapper for {@link MethodHandles#guardWithTest(MethodHandle, MethodHandle, MethodHandle)}
  64      *
  65      * @param test     test method handle
  66      * @param target   target method handle when test is true
  67      * @param fallback fallback method handle when test is false
  68      *
  69      * @return guarded handles
  70      */
  71     public MethodHandle guardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback);
  72 
  73     /**
  74      * Wrapper for {@link MethodHandles#insertArguments(MethodHandle, int, Object...)}
  75      *
  76      * @param target target method handle
  77      * @param pos    start argument index
  78      * @param values values to insert
  79      *
  80      * @return handle with bound arguments
  81      */
  82     public MethodHandle insertArguments(MethodHandle target, int pos, Object... values);
  83 
  84     /**
  85      * Wrapper for {@link MethodHandles#dropArguments(MethodHandle, int, Class...)}
  86      *
  87      * @param target     target method handle
  88      * @param pos        start argument index
  89      * @param valueTypes valueTypes of arguments to drop
  90      *
  91      * @return handle with dropped arguments
  92      */
  93     public MethodHandle dropArguments(MethodHandle target, int pos, Class<?>... valueTypes);
  94 
  95     /**
  96      * Wrapper for {@link MethodHandles#dropArguments(MethodHandle, int, List)}
  97      *
  98      * @param target     target method handle
  99      * @param pos        start argument index
 100      * @param valueTypes valueTypes of arguments to drop
 101      *
 102      * @return handle with dropped arguments
 103      */
 104     public MethodHandle dropArguments(final MethodHandle target, final int pos, final List<Class<?>> valueTypes);
 105 
 106     /**
 107      * Wrapper for {@link MethodHandles#foldArguments(MethodHandle, MethodHandle)}
 108      *
 109      * @param target   target method handle
 110      * @param combiner combiner to apply for fold
 111      *
 112      * @return folded method handle
 113      */
 114     public MethodHandle foldArguments(MethodHandle target, MethodHandle combiner);
 115 
 116     /**
 117      * Wrapper for {@link MethodHandles#explicitCastArguments(MethodHandle, MethodType)}
 118      *
 119      * @param target  target method handle
 120      * @param type    type to cast to
 121      *
 122      * @return modified method handle
 123      */
 124     public MethodHandle explicitCastArguments(MethodHandle target, MethodType type);
 125 
 126     /**
 127      * Wrapper for {@link java.lang.invoke.MethodHandles#arrayElementGetter(Class)}
 128      *
 129      * @param arrayClass class for array
 130      *
 131      * @return array element getter
 132      */
 133     public MethodHandle arrayElementGetter(Class<?> arrayClass);
 134 
 135     /**
 136      * Wrapper for {@link java.lang.invoke.MethodHandles#arrayElementSetter(Class)}
 137      *
 138      * @param arrayClass class for array
 139      *
 140      * @return array element setter
 141      */
 142     public MethodHandle arrayElementSetter(Class<?> arrayClass);
 143 
 144     /**
 145      * Wrapper for {@link java.lang.invoke.MethodHandles#throwException(Class, Class)}
 146      *
 147      * @param returnType ignored, but method signature will use it
 148      * @param exType     exception type that will be thrown
 149      *
 150      * @return exception thrower method handle
 151      */
 152     public MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType);
 153 
 154     /**
 155      * Wrapper for {@link java.lang.invoke.MethodHandles#catchException(MethodHandle, Class, MethodHandle)}
 156      *
 157      * @param target  target method
 158      * @param exType  exception type
 159      * @param handler the method handle to call when exception is thrown
 160      *
 161      * @return exception thrower method handle
 162      */
 163     public MethodHandle catchException(final MethodHandle target, final Class<? extends Throwable> exType, final MethodHandle handler);
 164 
 165     /**
 166      * Wrapper for {@link java.lang.invoke.MethodHandles#constant(Class, Object)}
 167      *
 168      * @param type  type of constant
 169      * @param value constant value
 170      *
 171      * @return method handle that returns said constant
 172      */
 173     public MethodHandle constant(Class<?> type, Object value);
 174 
 175     /**
 176      * Wrapper for {@link java.lang.invoke.MethodHandles#identity(Class)}
 177      *
 178      * @param type  type of value
 179      *
 180      * @return method handle that returns identity argument
 181      */
 182     public MethodHandle identity(Class<?> type);
 183 
 184     /**
 185      * Wrapper for {@link java.lang.invoke.MethodHandle#asType(MethodType)}
 186      *
 187      * @param handle  method handle for type conversion
 188      * @param type    type to convert to
 189      *
 190      * @return method handle with given type conversion applied
 191      */
 192     public MethodHandle asType(MethodHandle handle, MethodType type);
 193 
 194     /**
 195      * Wrapper for {@link java.lang.invoke.MethodHandle#asCollector(Class, int)}
 196      *
 197      * @param handle      handle to convert
 198      * @param arrayType   array type for collector array
 199      * @param arrayLength length of collector array
 200      *
 201      * @return method handle with collector
 202      */
 203     public MethodHandle asCollector(MethodHandle handle, Class<?> arrayType, int arrayLength);
 204 
 205     /**
 206      * Wrapper for {@link java.lang.invoke.MethodHandle#asSpreader(Class, int)}
 207      *
 208      * @param handle      handle to convert
 209      * @param arrayType   array type for spread
 210      * @param arrayLength length of spreader
 211      *
 212      * @return method handle as spreader
 213      */
 214     public MethodHandle asSpreader(MethodHandle handle, Class<?> arrayType, int arrayLength);
 215 
 216     /**
 217      * Wrapper for {@link java.lang.invoke.MethodHandle#bindTo(Object)}
 218      *
 219      * @param handle a handle to which to bind a receiver
 220      * @param x      the receiver
 221      *
 222      * @return the bound handle
 223      */
 224     public MethodHandle bindTo(MethodHandle handle, Object x);
 225 
 226     /**
 227      * Wrapper for {@link java.lang.invoke.MethodHandles.Lookup#findGetter(Class, String, Class)}
 228       *
 229      * @param explicitLookup explicit lookup to be used
 230      * @param clazz          class to look in
 231      * @param name           name of field
 232      * @param type           type of field
 233      *
 234      * @return getter method handle for virtual field
 235      */
 236     public MethodHandle getter(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, Class<?> type);
 237 
 238     /**
 239      * Wrapper for {@link java.lang.invoke.MethodHandles.Lookup#findStaticGetter(Class, String, Class)}
 240       *
 241      * @param explicitLookup explicit lookup to be used
 242      * @param clazz          class to look in
 243      * @param name           name of field
 244      * @param type           type of field
 245      *
 246      * @return getter method handle for static field
 247      */
 248     public MethodHandle staticGetter(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, Class<?> type);
 249 
 250     /**
 251      * Wrapper for {@link java.lang.invoke.MethodHandles.Lookup#findSetter(Class, String, Class)}
 252       *
 253      * @param explicitLookup explicit lookup to be used
 254      * @param clazz          class to look in
 255      * @param name           name of field
 256      * @param type           type of field
 257      *
 258      * @return setter method handle for virtual field
 259      */
 260     public MethodHandle setter(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, Class<?> type);
 261 
 262     /**
 263      * Wrapper for {@link java.lang.invoke.MethodHandles.Lookup#findStaticSetter(Class, String, Class)}
 264       *
 265      * @param explicitLookup explicit lookup to be used
 266      * @param clazz          class to look in
 267      * @param name           name of field
 268      * @param type           type of field
 269      *
 270      * @return setter method handle for static field
 271      */
 272     public MethodHandle staticSetter(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, Class<?> type);
 273 
 274     /**
 275      * Wrapper for {@link java.lang.invoke.MethodHandles.Lookup#unreflect(Method)}
 276      *
 277      * Unreflect a method as a method handle
 278      *
 279      * @param method method to unreflect
 280      * @return unreflected method as method handle
 281      */
 282     public MethodHandle find(Method method);
 283 
 284     /**
 285      * Wrapper for {@link java.lang.invoke.MethodHandles.Lookup#findStatic(Class, String, MethodType)}
 286      *
 287      * @param explicitLookup explicit lookup to be used
 288      * @param clazz          class to look in
 289      * @param name           name of method
 290      * @param type           method type
 291      *
 292      * @return method handle for static method
 293      */
 294     public MethodHandle findStatic(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, MethodType type);
 295 
 296     /**
 297      * Wrapper for {@link java.lang.invoke.MethodHandles.Lookup#findVirtual(Class, String, MethodType)}
 298      *
 299      * @param explicitLookup explicit lookup to be used
 300      * @param clazz          class to look in
 301      * @param name           name of method
 302      * @param type           method type
 303      *
 304      * @return method handle for virtual method
 305      */
 306     public MethodHandle findVirtual(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, MethodType type);
 307 
 308     /**
 309      * Wrapper for {@link java.lang.invoke.MethodHandles.Lookup#findSpecial(Class, String, MethodType, Class)}
 310      *
 311      * @param explicitLookup explicit lookup to be used
 312      * @param clazz          class to look in
 313      * @param name           name of method
 314      * @param type           method type
 315      * @param thisClass      thisClass
 316      *
 317      * @return method handle for virtual method
 318      */
 319     public MethodHandle findSpecial(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, MethodType type, final Class<?> thisClass);
 320 
 321     /**
 322      * Wrapper for SwitchPoint creation. Just like {@code new SwitchPoint()} but potentially
 323      * tracked
 324      *
 325      * @return new switch point
 326      */
 327     public SwitchPoint createSwitchPoint();
 328 
 329     /**
 330      * Wrapper for {@link SwitchPoint#guardWithTest(MethodHandle, MethodHandle)}
 331      *
 332      * @param sp     switch point
 333      * @param before method handle when switchpoint is valid
 334      * @param after  method handle when switchpoint is invalidated
 335      *
 336      * @return guarded method handle
 337      */
 338     public MethodHandle guardWithTest(SwitchPoint sp, MethodHandle before, MethodHandle after);
 339 
 340     /**
 341      * Wrapper for {@link MethodType#methodType(Class, Class...)}
 342      *
 343      * @param returnType  return type for method type
 344      * @param paramTypes  parameter types for method type
 345      *
 346      * @return the method type
 347      */
 348     public MethodType type(Class<?> returnType, Class<?>... paramTypes);
 349 
 350 }
 351