src/jdk/nashorn/internal/lookup/MethodHandleFactory.java

changeset 0
b1a7da25b547
child 952
6d5471a497fb
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java	Wed Apr 27 01:36:41 2016 +0800
     1.3 @@ -0,0 +1,646 @@
     1.4 +/*
     1.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +package jdk.nashorn.internal.lookup;
    1.30 +
    1.31 +import java.io.ByteArrayOutputStream;
    1.32 +import java.io.PrintStream;
    1.33 +import java.lang.invoke.MethodHandle;
    1.34 +import java.lang.invoke.MethodHandles;
    1.35 +import java.lang.invoke.MethodType;
    1.36 +import java.lang.invoke.SwitchPoint;
    1.37 +import java.lang.reflect.Method;
    1.38 +import java.util.ArrayList;
    1.39 +import java.util.Arrays;
    1.40 +import java.util.List;
    1.41 +import java.util.logging.Level;
    1.42 +import jdk.nashorn.internal.runtime.ConsString;
    1.43 +import jdk.nashorn.internal.runtime.Debug;
    1.44 +import jdk.nashorn.internal.runtime.DebugLogger;
    1.45 +import jdk.nashorn.internal.runtime.ScriptObject;
    1.46 +import jdk.nashorn.internal.runtime.options.Options;
    1.47 +
    1.48 +/**
    1.49 + * This class is abstraction for all method handle, switchpoint and method type
    1.50 + * operations. This enables the functionality interface to be subclassed and
    1.51 + * intrumensted, as it has been proven vital to keep the number of method
    1.52 + * handles in the system down.
    1.53 + *
    1.54 + * All operations of the above type should go through this class, and not
    1.55 + * directly into java.lang.invoke
    1.56 + *
    1.57 + */
    1.58 +public final class MethodHandleFactory {
    1.59 +
    1.60 +    private static final MethodHandles.Lookup PUBLIC_LOOKUP = MethodHandles.publicLookup();
    1.61 +    private static final MethodHandles.Lookup LOOKUP        = MethodHandles.lookup();
    1.62 +
    1.63 +    private static final Level TRACE_LEVEL = Level.INFO;
    1.64 +
    1.65 +    private MethodHandleFactory() {
    1.66 +    }
    1.67 +
    1.68 +    /**
    1.69 +     * Runtime exception that collects every reason that a method handle lookup operation can go wrong
    1.70 +     */
    1.71 +    @SuppressWarnings("serial")
    1.72 +    public static class LookupException extends RuntimeException {
    1.73 +        /**
    1.74 +         * Constructor
    1.75 +         * @param e causing exception
    1.76 +         */
    1.77 +        public LookupException(final Exception e) {
    1.78 +            super(e);
    1.79 +        }
    1.80 +    }
    1.81 +
    1.82 +    /**
    1.83 +     * Helper function that takes a class or an object with a toString override
    1.84 +     * and shortens it to notation after last dot. This is used to facilitiate
    1.85 +     * pretty printouts in various debug loggers - internal only
    1.86 +     *
    1.87 +     * @param obj class or object
    1.88 +     *
    1.89 +     * @return pretty version of object as string
    1.90 +     */
    1.91 +    public static String stripName(final Object obj) {
    1.92 +        if (obj == null) {
    1.93 +            return "null";
    1.94 +        }
    1.95 +
    1.96 +        if (obj instanceof Class) {
    1.97 +            return ((Class<?>)obj).getSimpleName();
    1.98 +        }
    1.99 +        return obj.toString();
   1.100 +    }
   1.101 +
   1.102 +    private static final MethodHandleFunctionality STANDARD = new StandardMethodHandleFunctionality();
   1.103 +    private static final MethodHandleFunctionality FUNC;
   1.104 +
   1.105 +    private static final String DEBUG_PROPERTY = "nashorn.methodhandles.debug";
   1.106 +    private static final DebugLogger LOG = new DebugLogger("methodhandles", DEBUG_PROPERTY);
   1.107 +
   1.108 +    static {
   1.109 +        if (LOG.isEnabled() || Options.getBooleanProperty(DEBUG_PROPERTY)) {
   1.110 +            if (Options.getStringProperty(DEBUG_PROPERTY, "").equals("create")) {
   1.111 +                FUNC = new TraceCreateMethodHandleFunctionality();
   1.112 +            } else {
   1.113 +                FUNC = new TraceMethodHandleFunctionality();
   1.114 +            }
   1.115 +        } else {
   1.116 +            FUNC  = STANDARD;
   1.117 +        }
   1.118 +    }
   1.119 +
   1.120 +    private static final boolean PRINT_STACKTRACE = Options.getBooleanProperty("nashorn.methodhandles.debug.stacktrace");
   1.121 +
   1.122 +
   1.123 +    /**
   1.124 +     * Return the method handle functionality used for all method handle operations
   1.125 +     * @return a method handle functionality implementation
   1.126 +     */
   1.127 +    public static MethodHandleFunctionality getFunctionality() {
   1.128 +        return FUNC;
   1.129 +    }
   1.130 +
   1.131 +    private static final MethodHandle TRACE        = STANDARD.findStatic(LOOKUP, MethodHandleFactory.class, "traceArgs",   MethodType.methodType(void.class, DebugLogger.class, String.class, int.class, Object[].class));
   1.132 +    private static final MethodHandle TRACE_RETURN = STANDARD.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturn", MethodType.methodType(Object.class, DebugLogger.class, Object.class));
   1.133 +
   1.134 +    /**
   1.135 +     * Tracer that is applied before a value is returned from the traced function. It will output the return
   1.136 +     * value and its class
   1.137 +     *
   1.138 +     * @param value return value for filter
   1.139 +     * @return return value unmodified
   1.140 +     */
   1.141 +    static Object traceReturn(final DebugLogger logger, final Object value) {
   1.142 +        final String str = "\treturn: " + stripName(value) + " [type=" + (value == null ? "null" : stripName(value.getClass()) + ']');
   1.143 +        logger.log(TRACE_LEVEL, str);
   1.144 +        return value;
   1.145 +    }
   1.146 +
   1.147 +    /**
   1.148 +     * Tracer that is applied before a function is called, printing the arguments
   1.149 +     *
   1.150 +     * @param tag  tag to start the debug printout string
   1.151 +     * @param paramStart param index to start outputting from
   1.152 +     * @param args arguments to the function
   1.153 +     */
   1.154 +    static void traceArgs(final DebugLogger logger, final String tag, final int paramStart, final Object... args) {
   1.155 +        final StringBuilder sb = new StringBuilder();
   1.156 +
   1.157 +        sb.append(tag);
   1.158 +
   1.159 +        for (int i = paramStart; i < args.length; i++) {
   1.160 +            if (i == paramStart) {
   1.161 +                sb.append(" => args: ");
   1.162 +            }
   1.163 +
   1.164 +            sb.append('\'').
   1.165 +                append(stripName(argString(args[i]))).
   1.166 +                append('\'').
   1.167 +                append(' ').
   1.168 +                append('[').
   1.169 +                append("type=").
   1.170 +                append(args[i] == null ? "null" : stripName(args[i].getClass())).
   1.171 +                append(']');
   1.172 +
   1.173 +            if (i + 1 < args.length) {
   1.174 +                sb.append(", ");
   1.175 +            }
   1.176 +        }
   1.177 +
   1.178 +        assert logger != null;
   1.179 +        logger.log(TRACE_LEVEL, sb);
   1.180 +        stacktrace(logger);
   1.181 +    }
   1.182 +
   1.183 +    private static void stacktrace(final DebugLogger logger) {
   1.184 +        if (!PRINT_STACKTRACE) {
   1.185 +            return;
   1.186 +        }
   1.187 +        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
   1.188 +        final PrintStream ps = new PrintStream(baos);
   1.189 +        new Throwable().printStackTrace(ps);
   1.190 +        logger.log(TRACE_LEVEL, baos.toString());
   1.191 +    }
   1.192 +
   1.193 +    private static String argString(final Object arg) {
   1.194 +        if (arg == null) {
   1.195 +            return "null";
   1.196 +        }
   1.197 +
   1.198 +        if (arg.getClass().isArray()) {
   1.199 +            final List<Object> list = new ArrayList<>();
   1.200 +            for (final Object elem : (Object[])arg) {
   1.201 +                list.add('\'' + argString(elem) + '\'');
   1.202 +            }
   1.203 +
   1.204 +            return list.toString();
   1.205 +        }
   1.206 +
   1.207 +        if (arg instanceof ScriptObject) {
   1.208 +            return arg.toString() +
   1.209 +                " (map=" + Debug.id((((ScriptObject)arg).getMap())) +
   1.210 +                ")";
   1.211 +        }
   1.212 +
   1.213 +        return arg.toString();
   1.214 +    }
   1.215 +
   1.216 +    /**
   1.217 +     * Add a debug printout to a method handle, tracing parameters and return values
   1.218 +     *
   1.219 +     * @param logger a specific logger to which to write the output
   1.220 +     * @param mh  method handle to trace
   1.221 +     * @param tag start of trace message
   1.222 +     * @return traced method handle
   1.223 +     */
   1.224 +    public static MethodHandle addDebugPrintout(final DebugLogger logger, final MethodHandle mh, final Object tag) {
   1.225 +        return addDebugPrintout(logger, mh, 0, true, tag);
   1.226 +    }
   1.227 +
   1.228 +
   1.229 +    /**
   1.230 +     * Add a debug printout to a method handle, tracing parameters and return values
   1.231 +     *
   1.232 +     * @param logger a specific logger to which to write the output
   1.233 +     * @param mh  method handle to trace
   1.234 +     * @param paramStart first param to print/trace
   1.235 +     * @param printReturnValue should we print/trace return value if available?
   1.236 +     * @param tag start of trace message
   1.237 +     * @return  traced method handle
   1.238 +     */
   1.239 +    public static MethodHandle addDebugPrintout(final DebugLogger logger, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Object tag) {
   1.240 +        final MethodType type = mh.type();
   1.241 +
   1.242 +        if (logger != null && logger.levelAbove(TRACE_LEVEL)) {
   1.243 +            return mh;
   1.244 +        }
   1.245 +
   1.246 +        assert logger != null;
   1.247 +        assert TRACE != null;
   1.248 +
   1.249 +        MethodHandle trace = MethodHandles.insertArguments(TRACE, 0, logger, tag, paramStart);
   1.250 +
   1.251 +        trace = MethodHandles.foldArguments(
   1.252 +                mh,
   1.253 +                trace.asCollector(
   1.254 +                    Object[].class,
   1.255 +                    type.parameterCount()).
   1.256 +                asType(type.changeReturnType(void.class)));
   1.257 +
   1.258 +        final Class<?> retType = type.returnType();
   1.259 +        if (retType != void.class && printReturnValue) {
   1.260 +            final MethodHandle traceReturn = MethodHandles.insertArguments(TRACE_RETURN, 0, logger);
   1.261 +            trace = MethodHandles.filterReturnValue(trace,
   1.262 +                    traceReturn.asType(
   1.263 +                        traceReturn.type().changeParameterType(0, retType).changeReturnType(retType)));
   1.264 +        }
   1.265 +
   1.266 +        return trace;
   1.267 +    }
   1.268 +
   1.269 +    /**
   1.270 +     * The standard class that marshalls all method handle operations to the java.lang.invoke
   1.271 +     * package. This exists only so that it can be subclassed and method handles created from
   1.272 +     * Nashorn made possible to instrument.
   1.273 +     *
   1.274 +     * All Nashorn classes should use the MethodHandleFactory for their method handle operations
   1.275 +     */
   1.276 +    private static class StandardMethodHandleFunctionality implements MethodHandleFunctionality {
   1.277 +
   1.278 +        @Override
   1.279 +        public MethodHandle filterArguments(final MethodHandle target, final int pos, final MethodHandle... filters) {
   1.280 +            return MethodHandles.filterArguments(target, pos, filters);
   1.281 +        }
   1.282 +
   1.283 +        @Override
   1.284 +        public MethodHandle filterReturnValue(final MethodHandle target, final MethodHandle filter) {
   1.285 +            return MethodHandles.filterReturnValue(target, filter);
   1.286 +        }
   1.287 +
   1.288 +        @Override
   1.289 +        public MethodHandle guardWithTest(final MethodHandle test, final MethodHandle target, final MethodHandle fallback) {
   1.290 +            return MethodHandles.guardWithTest(test, target, fallback);
   1.291 +        }
   1.292 +
   1.293 +        @Override
   1.294 +        public MethodHandle insertArguments(final MethodHandle target, final int pos, final Object... values) {
   1.295 +            return MethodHandles.insertArguments(target, pos, values);
   1.296 +        }
   1.297 +
   1.298 +        @Override
   1.299 +        public MethodHandle dropArguments(final MethodHandle target, final int pos, final Class<?>... valueTypes) {
   1.300 +            return MethodHandles.dropArguments(target, pos, valueTypes);
   1.301 +        }
   1.302 +
   1.303 +        @Override
   1.304 +        public MethodHandle dropArguments(final MethodHandle target, final int pos, final List<Class<?>> valueTypes) {
   1.305 +            return MethodHandles.dropArguments(target, pos, valueTypes);
   1.306 +        }
   1.307 +
   1.308 +        @Override
   1.309 +        public MethodHandle asType(final MethodHandle handle, final MethodType type) {
   1.310 +            return handle.asType(type);
   1.311 +        }
   1.312 +
   1.313 +        @Override
   1.314 +        public MethodHandle bindTo(final MethodHandle handle, final Object x) {
   1.315 +            return handle.bindTo(x);
   1.316 +        }
   1.317 +
   1.318 +        @Override
   1.319 +        public MethodHandle foldArguments(final MethodHandle target, final MethodHandle combiner) {
   1.320 +            return MethodHandles.foldArguments(target, combiner);
   1.321 +        }
   1.322 +
   1.323 +        @Override
   1.324 +        public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) {
   1.325 +            return MethodHandles.explicitCastArguments(target, type);
   1.326 +        }
   1.327 +
   1.328 +        @Override
   1.329 +        public MethodHandle arrayElementGetter(final Class<?> type) {
   1.330 +            return MethodHandles.arrayElementGetter(type);
   1.331 +        }
   1.332 +
   1.333 +        @Override
   1.334 +        public MethodHandle arrayElementSetter(final Class<?> type) {
   1.335 +            return MethodHandles.arrayElementSetter(type);
   1.336 +        }
   1.337 +
   1.338 +        @Override
   1.339 +        public MethodHandle throwException(final Class<?> returnType, final Class<? extends Throwable> exType) {
   1.340 +            return MethodHandles.throwException(returnType, exType);
   1.341 +        }
   1.342 +
   1.343 +        @Override
   1.344 +        public MethodHandle constant(final Class<?> type, final Object value) {
   1.345 +            return MethodHandles.constant(type, value);
   1.346 +        }
   1.347 +
   1.348 +        @Override
   1.349 +        public MethodHandle asCollector(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
   1.350 +            return handle.asCollector(arrayType, arrayLength);
   1.351 +        }
   1.352 +
   1.353 +        @Override
   1.354 +        public MethodHandle asSpreader(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
   1.355 +            return handle.asSpreader(arrayType, arrayLength);
   1.356 +        }
   1.357 +
   1.358 +        @Override
   1.359 +        public MethodHandle getter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
   1.360 +            try {
   1.361 +                return explicitLookup.findGetter(clazz, name, type);
   1.362 +            } catch (final NoSuchFieldException | IllegalAccessException e) {
   1.363 +                throw new LookupException(e);
   1.364 +            }
   1.365 +        }
   1.366 +
   1.367 +        @Override
   1.368 +        public MethodHandle staticGetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
   1.369 +            try {
   1.370 +                return explicitLookup.findStaticGetter(clazz, name, type);
   1.371 +            } catch (final NoSuchFieldException | IllegalAccessException e) {
   1.372 +                throw new LookupException(e);
   1.373 +            }
   1.374 +        }
   1.375 +
   1.376 +
   1.377 +        @Override
   1.378 +        public MethodHandle setter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
   1.379 +            try {
   1.380 +                return explicitLookup.findSetter(clazz, name, type);
   1.381 +            } catch (final NoSuchFieldException | IllegalAccessException e) {
   1.382 +                throw new LookupException(e);
   1.383 +            }
   1.384 +        }
   1.385 +
   1.386 +        @Override
   1.387 +        public MethodHandle staticSetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
   1.388 +            try {
   1.389 +                return explicitLookup.findStaticSetter(clazz, name, type);
   1.390 +            } catch (final NoSuchFieldException | IllegalAccessException e) {
   1.391 +                throw new LookupException(e);
   1.392 +            }
   1.393 +        }
   1.394 +
   1.395 +        @Override
   1.396 +        public MethodHandle find(final Method method) {
   1.397 +            try {
   1.398 +                return PUBLIC_LOOKUP.unreflect(method);
   1.399 +            } catch (final IllegalAccessException e) {
   1.400 +                throw new LookupException(e);
   1.401 +            }
   1.402 +        }
   1.403 +
   1.404 +        @Override
   1.405 +        public MethodHandle findStatic(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
   1.406 +            try {
   1.407 +                return explicitLookup.findStatic(clazz, name, type);
   1.408 +            } catch (final NoSuchMethodException | IllegalAccessException e) {
   1.409 +                throw new LookupException(e);
   1.410 +            }
   1.411 +        }
   1.412 +
   1.413 +        @Override
   1.414 +        public MethodHandle findVirtual(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
   1.415 +            try {
   1.416 +                return explicitLookup.findVirtual(clazz, name, type);
   1.417 +            } catch (final NoSuchMethodException | IllegalAccessException e) {
   1.418 +                throw new LookupException(e);
   1.419 +            }
   1.420 +        }
   1.421 +
   1.422 +        @Override
   1.423 +        public SwitchPoint createSwitchPoint() {
   1.424 +            return new SwitchPoint();
   1.425 +        }
   1.426 +
   1.427 +        @Override
   1.428 +        public MethodHandle guardWithTest(final SwitchPoint sp, final MethodHandle before, final MethodHandle after) {
   1.429 +            return sp.guardWithTest(before, after);
   1.430 +        }
   1.431 +
   1.432 +        @Override
   1.433 +        public MethodType type(final Class<?> returnType, final Class<?>... paramTypes) {
   1.434 +            return MethodType.methodType(returnType, paramTypes);
   1.435 +        }
   1.436 +
   1.437 +    }
   1.438 +
   1.439 +    /**
   1.440 +     * Class used for instrumenting and debugging Nashorn generated method handles
   1.441 +     */
   1.442 +    private static class TraceMethodHandleFunctionality extends StandardMethodHandleFunctionality {
   1.443 +
   1.444 +        protected static String describe(final Object... data) {
   1.445 +            final StringBuilder sb = new StringBuilder();
   1.446 +
   1.447 +            for (int i = 0; i < data.length; i++) {
   1.448 +                final Object d = data[i];
   1.449 +                if (d == null) {
   1.450 +                    sb.append("<null> ");
   1.451 +                } else if (d instanceof String || d instanceof ConsString) {
   1.452 +                    sb.append(d.toString());
   1.453 +                    sb.append(' ');
   1.454 +                } else if (d.getClass().isArray()) {
   1.455 +                    sb.append("[ ");
   1.456 +                    for (final Object da : (Object[])d) {
   1.457 +                        sb.append(describe(new Object[]{ da })).append(' ');
   1.458 +                    }
   1.459 +                    sb.append("] ");
   1.460 +                } else {
   1.461 +                    sb.append(d)
   1.462 +                        .append('{')
   1.463 +                        .append(Integer.toHexString(System.identityHashCode(d)))
   1.464 +                        .append('}');
   1.465 +                }
   1.466 +
   1.467 +                if (i + 1 < data.length) {
   1.468 +                    sb.append(", ");
   1.469 +                }
   1.470 +            }
   1.471 +
   1.472 +            return sb.toString();
   1.473 +        }
   1.474 +
   1.475 +        public MethodHandle debug(final MethodHandle master, final String str, final Object... args) {
   1.476 +            return addDebugPrintout(LOG, master, Integer.MAX_VALUE, false, str + ' ' + describe(args));
   1.477 +        }
   1.478 +
   1.479 +        @Override
   1.480 +        public MethodHandle filterArguments(final MethodHandle target, final int pos, final MethodHandle... filters) {
   1.481 +            final MethodHandle mh = super.filterArguments(target, pos, filters);
   1.482 +            return debug(mh, "filterArguments", target, pos, filters);
   1.483 +        }
   1.484 +
   1.485 +        @Override
   1.486 +        public MethodHandle filterReturnValue(final MethodHandle target, final MethodHandle filter) {
   1.487 +            final MethodHandle mh = super.filterReturnValue(target, filter);
   1.488 +            return debug(mh, "filterReturnValue", target, filter);
   1.489 +        }
   1.490 +
   1.491 +        @Override
   1.492 +        public MethodHandle guardWithTest(final MethodHandle test, final MethodHandle target, final MethodHandle fallback) {
   1.493 +            final MethodHandle mh = super.guardWithTest(test, target, fallback);
   1.494 +            return debug(mh, "guardWithTest", test, target, fallback);
   1.495 +        }
   1.496 +
   1.497 +        @Override
   1.498 +        public MethodHandle insertArguments(final MethodHandle target, final int pos, final Object... values) {
   1.499 +            final MethodHandle mh = super.insertArguments(target, pos, values);
   1.500 +            return debug(mh, "insertArguments", target, pos, values);
   1.501 +        }
   1.502 +
   1.503 +        @Override
   1.504 +        public MethodHandle dropArguments(final MethodHandle target, final int pos, final Class<?>... values) {
   1.505 +            final MethodHandle mh = super.dropArguments(target, pos, values);
   1.506 +            return debug(mh, "dropArguments", target, pos, values);
   1.507 +        }
   1.508 +
   1.509 +        @Override
   1.510 +        public MethodHandle dropArguments(final MethodHandle target, final int pos, final List<Class<?>> values) {
   1.511 +            final MethodHandle mh = super.dropArguments(target, pos, values);
   1.512 +            return debug(mh, "dropArguments", target, pos, values);
   1.513 +        }
   1.514 +
   1.515 +        @Override
   1.516 +        public MethodHandle asType(final MethodHandle handle, final MethodType type) {
   1.517 +            final MethodHandle mh = super.asType(handle, type);
   1.518 +            return debug(mh, "asType", handle, type);
   1.519 +        }
   1.520 +
   1.521 +        @Override
   1.522 +        public MethodHandle bindTo(final MethodHandle handle, final Object x) {
   1.523 +            final MethodHandle mh = super.bindTo(handle, x);
   1.524 +            return debug(mh, "bindTo", handle, x);
   1.525 +        }
   1.526 +
   1.527 +        @Override
   1.528 +        public MethodHandle foldArguments(final MethodHandle target, final MethodHandle combiner) {
   1.529 +            final MethodHandle mh = super.foldArguments(target, combiner);
   1.530 +            return debug(mh, "foldArguments", target, combiner);
   1.531 +        }
   1.532 +
   1.533 +        @Override
   1.534 +        public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) {
   1.535 +            final MethodHandle mh = super.explicitCastArguments(target, type);
   1.536 +            return debug(mh, "explicitCastArguments", target, type);
   1.537 +        }
   1.538 +
   1.539 +        @Override
   1.540 +        public MethodHandle arrayElementGetter(final Class<?> type) {
   1.541 +            final MethodHandle mh = super.arrayElementGetter(type);
   1.542 +            return debug(mh, "arrayElementGetter", type);
   1.543 +        }
   1.544 +
   1.545 +        @Override
   1.546 +        public MethodHandle arrayElementSetter(final Class<?> type) {
   1.547 +            final MethodHandle mh = super.arrayElementSetter(type);
   1.548 +            return debug(mh, "arrayElementSetter", type);
   1.549 +        }
   1.550 +
   1.551 +        @Override
   1.552 +        public MethodHandle throwException(final Class<?> returnType, final Class<? extends Throwable> exType) {
   1.553 +            final MethodHandle mh = super.throwException(returnType, exType);
   1.554 +            return debug(mh, "throwException", returnType, exType);
   1.555 +        }
   1.556 +
   1.557 +        @Override
   1.558 +        public MethodHandle constant(final Class<?> type, final Object value) {
   1.559 +            final MethodHandle mh = super.constant(type, value);
   1.560 +            return debug(mh, "constant", type, value);
   1.561 +        }
   1.562 +
   1.563 +        @Override
   1.564 +        public MethodHandle asCollector(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
   1.565 +            final MethodHandle mh = super.asCollector(handle, arrayType, arrayLength);
   1.566 +            return debug(mh, "asCollector", handle, arrayType, arrayLength);
   1.567 +        }
   1.568 +
   1.569 +        @Override
   1.570 +        public MethodHandle asSpreader(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
   1.571 +            final MethodHandle mh = super.asSpreader(handle, arrayType, arrayLength);
   1.572 +            return debug(mh, "asSpreader", handle, arrayType, arrayLength);
   1.573 +        }
   1.574 +
   1.575 +        @Override
   1.576 +        public MethodHandle getter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
   1.577 +            final MethodHandle mh = super.getter(explicitLookup, clazz, name, type);
   1.578 +            return debug(mh, "getter", explicitLookup, clazz, name, type);
   1.579 +        }
   1.580 +
   1.581 +        @Override
   1.582 +        public MethodHandle staticGetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
   1.583 +            final MethodHandle mh = super.staticGetter(explicitLookup, clazz, name, type);
   1.584 +            return debug(mh, "static getter", explicitLookup, clazz, name, type);
   1.585 +        }
   1.586 +
   1.587 +        @Override
   1.588 +        public MethodHandle setter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
   1.589 +            final MethodHandle mh = super.setter(explicitLookup, clazz, name, type);
   1.590 +            return debug(mh, "setter", explicitLookup, clazz, name, type);
   1.591 +        }
   1.592 +
   1.593 +        @Override
   1.594 +        public MethodHandle staticSetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
   1.595 +            final MethodHandle mh = super.staticSetter(explicitLookup, clazz, name, type);
   1.596 +            return debug(mh, "static setter", explicitLookup, clazz, name, type);
   1.597 +        }
   1.598 +
   1.599 +        @Override
   1.600 +        public MethodHandle find(final Method method) {
   1.601 +            final MethodHandle mh = super.find(method);
   1.602 +            return debug(mh, "find", method);
   1.603 +        }
   1.604 +
   1.605 +        @Override
   1.606 +        public MethodHandle findStatic(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
   1.607 +            final MethodHandle mh = super.findStatic(explicitLookup, clazz, name, type);
   1.608 +            return debug(mh, "findStatic", explicitLookup, clazz, name, type);
   1.609 +        }
   1.610 +
   1.611 +        @Override
   1.612 +        public MethodHandle findVirtual(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
   1.613 +            final MethodHandle mh = super.findVirtual(explicitLookup, clazz, name, type);
   1.614 +            return debug(mh, "findVirtual", explicitLookup, clazz, name, type);
   1.615 +        }
   1.616 +
   1.617 +        @Override
   1.618 +        public SwitchPoint createSwitchPoint() {
   1.619 +            final SwitchPoint sp = super.createSwitchPoint();
   1.620 +            LOG.log(TRACE_LEVEL, "createSwitchPoint ", sp);
   1.621 +            return sp;
   1.622 +        }
   1.623 +
   1.624 +        @Override
   1.625 +        public MethodHandle guardWithTest(final SwitchPoint sp, final MethodHandle before, final MethodHandle after) {
   1.626 +            final MethodHandle mh = super.guardWithTest(sp, before, after);
   1.627 +            return debug(mh, "guardWithTest", sp, before, after);
   1.628 +        }
   1.629 +
   1.630 +        @Override
   1.631 +        public MethodType type(final Class<?> returnType, final Class<?>... paramTypes) {
   1.632 +            final MethodType mt = super.type(returnType, paramTypes);
   1.633 +            LOG.log(TRACE_LEVEL, "methodType ", returnType, " ", Arrays.toString(paramTypes), " ", mt);
   1.634 +            return mt;
   1.635 +        }
   1.636 +    }
   1.637 +
   1.638 +    /**
   1.639 +     * Class used for debugging Nashorn generated method handles
   1.640 +     */
   1.641 +    private static class TraceCreateMethodHandleFunctionality extends TraceMethodHandleFunctionality {
   1.642 +        @Override
   1.643 +        public MethodHandle debug(final MethodHandle master, final String str, final Object... args) {
   1.644 +            LOG.log(TRACE_LEVEL, str, " ", describe(args));
   1.645 +            stacktrace(LOG);
   1.646 +            return master;
   1.647 +        }
   1.648 +    }
   1.649 +}

mercurial