diff options
Diffstat (limited to 'src/jdk/nashorn/internal/lookup')
3 files changed, 219 insertions, 242 deletions
diff --git a/src/jdk/nashorn/internal/lookup/Lookup.java b/src/jdk/nashorn/internal/lookup/Lookup.java index 0dd2741e..57728509 100644 --- a/src/jdk/nashorn/internal/lookup/Lookup.java +++ b/src/jdk/nashorn/internal/lookup/Lookup.java @@ -68,6 +68,12 @@ public final class Lookup { /** Method handle to the most generic of setters, the one that takes an Object */ public static final MethodType SET_OBJECT_TYPE = MH.type(void.class, Object.class, Object.class); + /** Method handle to the primitive getters, the one that returns an long/int/double */ + public static final MethodType GET_PRIMITIVE_TYPE = MH.type(long.class, Object.class); + + /** Method handle to the primitive getters, the one that returns an long/int/double */ + public static final MethodType SET_PRIMITIVE_TYPE = MH.type(void.class, Object.class, long.class); + private Lookup() { } @@ -123,6 +129,53 @@ public final class Lookup { } /** + * This method filters primitive argument types using JavaScript semantics. For example, + * an (int) cast of a double in Java land is not the same thing as invoking toInt32 on it. + * If you are returning values to JavaScript that have to be of a specific type, this is + * the correct return value filter to use, as the explicitCastArguments just uses the + * Java boxing equivalents + * + * @param mh method handle for which to filter argument value + * @param n argument index + * @param from old argument type, the new one is given by the sent method handle + * @return method handle for appropriate argument type conversion + */ + public static MethodHandle filterArgumentType(final MethodHandle mh, final int n, final Class<?> from) { + final Class<?> to = mh.type().parameterType(n); + + if (from == int.class) { + //fallthru + } else if (from == long.class) { + if (to == int.class) { + return MH.filterArguments(mh, n, JSType.TO_INT32_L.methodHandle()); + } + //fallthru + } else if (from == double.class) { + if (to == int.class) { + return MH.filterArguments(mh, n, JSType.TO_INT32_D.methodHandle()); + } else if (to == long.class) { + return MH.filterArguments(mh, n, JSType.TO_UINT32_D.methodHandle()); + } + //fallthru + } else if (!from.isPrimitive()) { + if (to == int.class) { + return MH.filterArguments(mh, n, JSType.TO_INT32.methodHandle()); + } else if (to == long.class) { + return MH.filterArguments(mh, n, JSType.TO_UINT32.methodHandle()); + } else if (to == double.class) { + return MH.filterArguments(mh, n, JSType.TO_NUMBER.methodHandle()); + } else if (!to.isPrimitive()) { + return mh; + } + + assert false : "unsupported Lookup.filterReturnType type " + from + " -> " + to; + } + + //use a standard cast - we don't need to check JavaScript special cases + return MH.explicitCastArguments(mh, mh.type().changeParameterType(n, from)); + } + + /** * This method filters primitive return types using JavaScript semantics. For example, * an (int) cast of a double in Java land is not the same thing as invoking toInt32 on it. * If you are returning values to JavaScript that have to be of a specific type, this is @@ -139,6 +192,9 @@ public final class Lookup { if (retType == int.class) { //fallthru } else if (retType == long.class) { + if (type == int.class) { + return MH.filterReturnValue(mh, JSType.TO_INT32_L.methodHandle()); + } //fallthru } else if (retType == double.class) { if (type == int.class) { diff --git a/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java index 34fe2eb6..8ef13d79 100644 --- a/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java +++ b/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java @@ -37,9 +37,12 @@ import java.util.Arrays; import java.util.List; import java.util.logging.Level; import jdk.nashorn.internal.runtime.ConsString; +import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.Debug; -import jdk.nashorn.internal.runtime.DebugLogger; import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.logging.DebugLogger; +import jdk.nashorn.internal.runtime.logging.Loggable; +import jdk.nashorn.internal.runtime.logging.Logger; import jdk.nashorn.internal.runtime.options.Options; /** @@ -96,27 +99,9 @@ public final class MethodHandleFactory { return obj.toString(); } - private static final MethodHandleFunctionality STANDARD = new StandardMethodHandleFunctionality(); - private static final MethodHandleFunctionality FUNC; - - private static final String DEBUG_PROPERTY = "nashorn.methodhandles.debug"; - private static final DebugLogger LOG = new DebugLogger("methodhandles", DEBUG_PROPERTY); - - static { - if (LOG.isEnabled() || Options.getBooleanProperty(DEBUG_PROPERTY)) { - if (Options.getStringProperty(DEBUG_PROPERTY, "").equals("create")) { - FUNC = new TraceCreateMethodHandleFunctionality(); - } else { - FUNC = new TraceMethodHandleFunctionality(); - } - } else { - FUNC = STANDARD; - } - } - + private static final MethodHandleFunctionality FUNC = new StandardMethodHandleFunctionality(); private static final boolean PRINT_STACKTRACE = Options.getBooleanProperty("nashorn.methodhandles.debug.stacktrace"); - /** * Return the method handle functionality used for all method handle operations * @return a method handle functionality implementation @@ -125,8 +110,11 @@ public final class MethodHandleFactory { return FUNC; } - private static final MethodHandle TRACE = STANDARD.findStatic(LOOKUP, MethodHandleFactory.class, "traceArgs", MethodType.methodType(void.class, DebugLogger.class, String.class, int.class, Object[].class)); - private static final MethodHandle TRACE_RETURN = STANDARD.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturn", MethodType.methodType(Object.class, DebugLogger.class, Object.class)); + private static final MethodHandle TRACE = FUNC.findStatic(LOOKUP, MethodHandleFactory.class, "traceArgs", MethodType.methodType(void.class, DebugLogger.class, String.class, int.class, Object[].class)); + private static final MethodHandle TRACE_RETURN = FUNC.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturn", MethodType.methodType(Object.class, DebugLogger.class, Object.class)); + private static final MethodHandle TRACE_RETURN_VOID = FUNC.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturnVoid", MethodType.methodType(void.class, DebugLogger.class)); + + private static final String VOID_TAG = "[VOID]"; /** * Tracer that is applied before a value is returned from the traced function. It will output the return @@ -136,11 +124,20 @@ public final class MethodHandleFactory { * @return return value unmodified */ static Object traceReturn(final DebugLogger logger, final Object value) { - final String str = "\treturn: " + stripName(value) + " [type=" + (value == null ? "null" : stripName(value.getClass()) + ']'); - logger.log(TRACE_LEVEL, str); + if (logger.isEnabled()) { + final String str = " return" + + (VOID_TAG.equals(value) ? + ";" : + " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']')); + logger.log(TRACE_LEVEL, str); + } return value; } + static void traceReturnVoid(final DebugLogger logger) { + traceReturn(logger, VOID_TAG); + } + /** * Tracer that is applied before a function is called, printing the arguments * @@ -203,7 +200,7 @@ public final class MethodHandleFactory { if (arg instanceof ScriptObject) { return arg.toString() + - " (map=" + Debug.id((((ScriptObject)arg).getMap())) + + " (map=" + Debug.id(((ScriptObject)arg).getMap()) + ")"; } @@ -214,29 +211,32 @@ public final class MethodHandleFactory { * Add a debug printout to a method handle, tracing parameters and return values * * @param logger a specific logger to which to write the output + * @param level level over which to print * @param mh method handle to trace * @param tag start of trace message * @return traced method handle */ - public static MethodHandle addDebugPrintout(final DebugLogger logger, final MethodHandle mh, final Object tag) { - return addDebugPrintout(logger, mh, 0, true, tag); + public static MethodHandle addDebugPrintout(final DebugLogger logger, final Level level, final MethodHandle mh, final Object tag) { + return addDebugPrintout(logger, level, mh, 0, true, tag); } - /** * Add a debug printout to a method handle, tracing parameters and return values * * @param logger a specific logger to which to write the output + * @param level level over which to print * @param mh method handle to trace * @param paramStart first param to print/trace * @param printReturnValue should we print/trace return value if available? * @param tag start of trace message * @return traced method handle */ - public static MethodHandle addDebugPrintout(final DebugLogger logger, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Object tag) { + public static MethodHandle addDebugPrintout(final DebugLogger logger, final Level level, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Object tag) { final MethodType type = mh.type(); - if (logger != null && logger.levelAbove(TRACE_LEVEL)) { + //if there is no logger, or if it's set to log only coarser events + //than the trace level, skip and return + if (logger != null && logger.levelCoarserThan(level)) { return mh; } @@ -253,191 +253,49 @@ public final class MethodHandleFactory { asType(type.changeReturnType(void.class))); final Class<?> retType = type.returnType(); - if (retType != void.class && printReturnValue) { - final MethodHandle traceReturn = MethodHandles.insertArguments(TRACE_RETURN, 0, logger); - trace = MethodHandles.filterReturnValue(trace, - traceReturn.asType( - traceReturn.type().changeParameterType(0, retType).changeReturnType(retType))); + if (printReturnValue) { + if (retType != void.class) { + final MethodHandle traceReturn = MethodHandles.insertArguments(TRACE_RETURN, 0, logger); + trace = MethodHandles.filterReturnValue(trace, + traceReturn.asType( + traceReturn.type().changeParameterType(0, retType).changeReturnType(retType))); + } else { + trace = MethodHandles.filterReturnValue(trace, MethodHandles.insertArguments(TRACE_RETURN_VOID, 0, logger)); + } } return trace; } /** - * The standard class that marshalls all method handle operations to the java.lang.invoke + * Class that marshalls all method handle operations to the java.lang.invoke * package. This exists only so that it can be subclassed and method handles created from * Nashorn made possible to instrument. * * All Nashorn classes should use the MethodHandleFactory for their method handle operations */ - private static class StandardMethodHandleFunctionality implements MethodHandleFunctionality { - - @Override - public MethodHandle filterArguments(final MethodHandle target, final int pos, final MethodHandle... filters) { - return MethodHandles.filterArguments(target, pos, filters); - } - - @Override - public MethodHandle filterReturnValue(final MethodHandle target, final MethodHandle filter) { - return MethodHandles.filterReturnValue(target, filter); - } - - @Override - public MethodHandle guardWithTest(final MethodHandle test, final MethodHandle target, final MethodHandle fallback) { - return MethodHandles.guardWithTest(test, target, fallback); - } - - @Override - public MethodHandle insertArguments(final MethodHandle target, final int pos, final Object... values) { - return MethodHandles.insertArguments(target, pos, values); - } - - @Override - public MethodHandle dropArguments(final MethodHandle target, final int pos, final Class<?>... valueTypes) { - return MethodHandles.dropArguments(target, pos, valueTypes); - } - - @Override - public MethodHandle dropArguments(final MethodHandle target, final int pos, final List<Class<?>> valueTypes) { - return MethodHandles.dropArguments(target, pos, valueTypes); - } - - @Override - public MethodHandle asType(final MethodHandle handle, final MethodType type) { - return handle.asType(type); - } - - @Override - public MethodHandle bindTo(final MethodHandle handle, final Object x) { - return handle.bindTo(x); - } - - @Override - public MethodHandle foldArguments(final MethodHandle target, final MethodHandle combiner) { - return MethodHandles.foldArguments(target, combiner); - } - - @Override - public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) { - return MethodHandles.explicitCastArguments(target, type); - } - - @Override - public MethodHandle arrayElementGetter(final Class<?> type) { - return MethodHandles.arrayElementGetter(type); - } - - @Override - public MethodHandle arrayElementSetter(final Class<?> type) { - return MethodHandles.arrayElementSetter(type); - } - - @Override - public MethodHandle throwException(final Class<?> returnType, final Class<? extends Throwable> exType) { - return MethodHandles.throwException(returnType, exType); - } - - @Override - public MethodHandle constant(final Class<?> type, final Object value) { - return MethodHandles.constant(type, value); - } - - @Override - public MethodHandle asCollector(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) { - return handle.asCollector(arrayType, arrayLength); - } + @Logger(name="methodhandles") + private static class StandardMethodHandleFunctionality implements MethodHandleFunctionality, Loggable { - @Override - public MethodHandle asSpreader(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) { - return handle.asSpreader(arrayType, arrayLength); - } + // for bootstrapping reasons, because a lot of static fields use MH for lookups, we + // need to set the logger when the Global object is finished. This means that we don't + // get instrumentation for public static final MethodHandle SOMETHING = MH... in the builtin + // classes, but that doesn't matter, because this is usually not where we want it + private DebugLogger log = DebugLogger.DISABLED_LOGGER; - @Override - public MethodHandle getter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) { - try { - return explicitLookup.findGetter(clazz, name, type); - } catch (final NoSuchFieldException | IllegalAccessException e) { - throw new LookupException(e); - } + public StandardMethodHandleFunctionality() { } @Override - public MethodHandle staticGetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) { - try { - return explicitLookup.findStaticGetter(clazz, name, type); - } catch (final NoSuchFieldException | IllegalAccessException e) { - throw new LookupException(e); - } + public DebugLogger initLogger(final Context context) { + return this.log = context.getLogger(this.getClass()); } - @Override - public MethodHandle setter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) { - try { - return explicitLookup.findSetter(clazz, name, type); - } catch (final NoSuchFieldException | IllegalAccessException e) { - throw new LookupException(e); - } + public DebugLogger getLogger() { + return log; } - @Override - public MethodHandle staticSetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) { - try { - return explicitLookup.findStaticSetter(clazz, name, type); - } catch (final NoSuchFieldException | IllegalAccessException e) { - throw new LookupException(e); - } - } - - @Override - public MethodHandle find(final Method method) { - try { - return PUBLIC_LOOKUP.unreflect(method); - } catch (final IllegalAccessException e) { - throw new LookupException(e); - } - } - - @Override - public MethodHandle findStatic(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) { - try { - return explicitLookup.findStatic(clazz, name, type); - } catch (final NoSuchMethodException | IllegalAccessException e) { - throw new LookupException(e); - } - } - - @Override - public MethodHandle findVirtual(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) { - try { - return explicitLookup.findVirtual(clazz, name, type); - } catch (final NoSuchMethodException | IllegalAccessException e) { - throw new LookupException(e); - } - } - - @Override - public SwitchPoint createSwitchPoint() { - return new SwitchPoint(); - } - - @Override - public MethodHandle guardWithTest(final SwitchPoint sp, final MethodHandle before, final MethodHandle after) { - return sp.guardWithTest(before, after); - } - - @Override - public MethodType type(final Class<?> returnType, final Class<?>... paramTypes) { - return MethodType.methodType(returnType, paramTypes); - } - - } - - /** - * Class used for instrumenting and debugging Nashorn generated method handles - */ - private static class TraceMethodHandleFunctionality extends StandardMethodHandleFunctionality { - protected static String describe(final Object... data) { final StringBuilder sb = new StringBuilder(); @@ -470,177 +328,215 @@ public final class MethodHandleFactory { } public MethodHandle debug(final MethodHandle master, final String str, final Object... args) { - return addDebugPrintout(LOG, master, Integer.MAX_VALUE, false, str + ' ' + describe(args)); + if (log.isEnabled()) { + if (PRINT_STACKTRACE) { + stacktrace(log); + } + return addDebugPrintout(log, Level.INFO, master, Integer.MAX_VALUE, false, str + ' ' + describe(args)); + } + return master; } @Override public MethodHandle filterArguments(final MethodHandle target, final int pos, final MethodHandle... filters) { - final MethodHandle mh = super.filterArguments(target, pos, filters); + final MethodHandle mh = MethodHandles.filterArguments(target, pos, filters); return debug(mh, "filterArguments", target, pos, filters); } @Override public MethodHandle filterReturnValue(final MethodHandle target, final MethodHandle filter) { - final MethodHandle mh = super.filterReturnValue(target, filter); + final MethodHandle mh = MethodHandles.filterReturnValue(target, filter); return debug(mh, "filterReturnValue", target, filter); } @Override public MethodHandle guardWithTest(final MethodHandle test, final MethodHandle target, final MethodHandle fallback) { - final MethodHandle mh = super.guardWithTest(test, target, fallback); + final MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback); return debug(mh, "guardWithTest", test, target, fallback); } @Override public MethodHandle insertArguments(final MethodHandle target, final int pos, final Object... values) { - final MethodHandle mh = super.insertArguments(target, pos, values); + final MethodHandle mh = MethodHandles.insertArguments(target, pos, values); return debug(mh, "insertArguments", target, pos, values); } @Override public MethodHandle dropArguments(final MethodHandle target, final int pos, final Class<?>... values) { - final MethodHandle mh = super.dropArguments(target, pos, values); + final MethodHandle mh = MethodHandles.dropArguments(target, pos, values); return debug(mh, "dropArguments", target, pos, values); } @Override public MethodHandle dropArguments(final MethodHandle target, final int pos, final List<Class<?>> values) { - final MethodHandle mh = super.dropArguments(target, pos, values); + final MethodHandle mh = MethodHandles.dropArguments(target, pos, values); return debug(mh, "dropArguments", target, pos, values); } @Override public MethodHandle asType(final MethodHandle handle, final MethodType type) { - final MethodHandle mh = super.asType(handle, type); + final MethodHandle mh = handle.asType(type); return debug(mh, "asType", handle, type); } @Override public MethodHandle bindTo(final MethodHandle handle, final Object x) { - final MethodHandle mh = super.bindTo(handle, x); + final MethodHandle mh = handle.bindTo(x); return debug(mh, "bindTo", handle, x); } @Override public MethodHandle foldArguments(final MethodHandle target, final MethodHandle combiner) { - final MethodHandle mh = super.foldArguments(target, combiner); + final MethodHandle mh = MethodHandles.foldArguments(target, combiner); return debug(mh, "foldArguments", target, combiner); } @Override public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) { - final MethodHandle mh = super.explicitCastArguments(target, type); + final MethodHandle mh = MethodHandles.explicitCastArguments(target, type); return debug(mh, "explicitCastArguments", target, type); } @Override public MethodHandle arrayElementGetter(final Class<?> type) { - final MethodHandle mh = super.arrayElementGetter(type); + final MethodHandle mh = MethodHandles.arrayElementGetter(type); return debug(mh, "arrayElementGetter", type); } @Override public MethodHandle arrayElementSetter(final Class<?> type) { - final MethodHandle mh = super.arrayElementSetter(type); + final MethodHandle mh = MethodHandles.arrayElementSetter(type); return debug(mh, "arrayElementSetter", type); } @Override public MethodHandle throwException(final Class<?> returnType, final Class<? extends Throwable> exType) { - final MethodHandle mh = super.throwException(returnType, exType); + final MethodHandle mh = MethodHandles.throwException(returnType, exType); return debug(mh, "throwException", returnType, exType); } @Override + public MethodHandle catchException(final MethodHandle target, final Class<? extends Throwable> exType, final MethodHandle handler) { + final MethodHandle mh = MethodHandles.catchException(target, exType, handler); + return debug(mh, "catchException", exType); + } + + @Override public MethodHandle constant(final Class<?> type, final Object value) { - final MethodHandle mh = super.constant(type, value); + final MethodHandle mh = MethodHandles.constant(type, value); return debug(mh, "constant", type, value); } @Override public MethodHandle asCollector(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) { - final MethodHandle mh = super.asCollector(handle, arrayType, arrayLength); + final MethodHandle mh = handle.asCollector(arrayType, arrayLength); return debug(mh, "asCollector", handle, arrayType, arrayLength); } @Override public MethodHandle asSpreader(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) { - final MethodHandle mh = super.asSpreader(handle, arrayType, arrayLength); + final MethodHandle mh = handle.asSpreader(arrayType, arrayLength); return debug(mh, "asSpreader", handle, arrayType, arrayLength); } @Override public MethodHandle getter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) { - final MethodHandle mh = super.getter(explicitLookup, clazz, name, type); - return debug(mh, "getter", explicitLookup, clazz, name, type); + try { + final MethodHandle mh = explicitLookup.findGetter(clazz, name, type); + return debug(mh, "getter", explicitLookup, clazz, name, type); + } catch (final NoSuchFieldException | IllegalAccessException e) { + throw new LookupException(e); + } } @Override public MethodHandle staticGetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) { - final MethodHandle mh = super.staticGetter(explicitLookup, clazz, name, type); - return debug(mh, "static getter", explicitLookup, clazz, name, type); + try { + final MethodHandle mh = explicitLookup.findStaticGetter(clazz, name, type); + return debug(mh, "static getter", explicitLookup, clazz, name, type); + } catch (final NoSuchFieldException | IllegalAccessException e) { + throw new LookupException(e); + } } @Override public MethodHandle setter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) { - final MethodHandle mh = super.setter(explicitLookup, clazz, name, type); - return debug(mh, "setter", explicitLookup, clazz, name, type); + try { + final MethodHandle mh = explicitLookup.findSetter(clazz, name, type); + return debug(mh, "setter", explicitLookup, clazz, name, type); + } catch (final NoSuchFieldException | IllegalAccessException e) { + throw new LookupException(e); + } } @Override public MethodHandle staticSetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) { - final MethodHandle mh = super.staticSetter(explicitLookup, clazz, name, type); - return debug(mh, "static setter", explicitLookup, clazz, name, type); + try { + final MethodHandle mh = explicitLookup.findStaticSetter(clazz, name, type); + return debug(mh, "static setter", explicitLookup, clazz, name, type); + } catch (final NoSuchFieldException | IllegalAccessException e) { + throw new LookupException(e); + } } @Override public MethodHandle find(final Method method) { - final MethodHandle mh = super.find(method); - return debug(mh, "find", method); + try { + final MethodHandle mh = PUBLIC_LOOKUP.unreflect(method); + return debug(mh, "find", method); + } catch (final IllegalAccessException e) { + throw new LookupException(e); + } } @Override public MethodHandle findStatic(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) { - final MethodHandle mh = super.findStatic(explicitLookup, clazz, name, type); - return debug(mh, "findStatic", explicitLookup, clazz, name, type); + try { + final MethodHandle mh = explicitLookup.findStatic(clazz, name, type); + return debug(mh, "findStatic", explicitLookup, clazz, name, type); + } catch (final NoSuchMethodException | IllegalAccessException e) { + throw new LookupException(e); + } + } + + @Override + public MethodHandle findSpecial(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type, final Class<?> thisClass) { + try { + final MethodHandle mh = explicitLookup.findSpecial(clazz, name, type, thisClass); + return debug(mh, "findSpecial", explicitLookup, clazz, name, type); + } catch (final NoSuchMethodException | IllegalAccessException e) { + throw new LookupException(e); + } } @Override public MethodHandle findVirtual(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) { - final MethodHandle mh = super.findVirtual(explicitLookup, clazz, name, type); - return debug(mh, "findVirtual", explicitLookup, clazz, name, type); + try { + final MethodHandle mh = explicitLookup.findVirtual(clazz, name, type); + return debug(mh, "findVirtual", explicitLookup, clazz, name, type); + } catch (final NoSuchMethodException | IllegalAccessException e) { + throw new LookupException(e); + } } @Override public SwitchPoint createSwitchPoint() { - final SwitchPoint sp = super.createSwitchPoint(); - LOG.log(TRACE_LEVEL, "createSwitchPoint ", sp); + final SwitchPoint sp = new SwitchPoint(); + log.log(TRACE_LEVEL, "createSwitchPoint ", sp); return sp; } @Override public MethodHandle guardWithTest(final SwitchPoint sp, final MethodHandle before, final MethodHandle after) { - final MethodHandle mh = super.guardWithTest(sp, before, after); + final MethodHandle mh = sp.guardWithTest(before, after); return debug(mh, "guardWithTest", sp, before, after); } @Override public MethodType type(final Class<?> returnType, final Class<?>... paramTypes) { - final MethodType mt = super.type(returnType, paramTypes); - LOG.log(TRACE_LEVEL, "methodType ", returnType, " ", Arrays.toString(paramTypes), " ", mt); + final MethodType mt = MethodType.methodType(returnType, paramTypes); + log.log(TRACE_LEVEL, "methodType ", returnType, " ", Arrays.toString(paramTypes), " ", mt); return mt; } } - - /** - * Class used for debugging Nashorn generated method handles - */ - private static class TraceCreateMethodHandleFunctionality extends TraceMethodHandleFunctionality { - @Override - public MethodHandle debug(final MethodHandle master, final String str, final Object... args) { - LOG.log(TRACE_LEVEL, str, " ", describe(args)); - stacktrace(LOG); - return master; - } - } } diff --git a/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java b/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java index c7dd83b2..756c0b7b 100644 --- a/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java +++ b/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java @@ -152,6 +152,17 @@ public interface MethodHandleFunctionality { public MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType); /** + * Wrapper for {@link java.lang.invoke.MethodHandles#catchException(MethodHandle, Class, MethodHandle)} + * + * @param target target method + * @param exType exception type + * @param handler the method handle to call when exception is thrown + * + * @return exception thrower method handle + */ + public MethodHandle catchException(final MethodHandle target, final Class<? extends Throwable> exType, final MethodHandle handler); + + /** * Wrapper for {@link java.lang.invoke.MethodHandles#constant(Class, Object)} * * @param type type of constant @@ -286,6 +297,19 @@ public interface MethodHandleFunctionality { public MethodHandle findVirtual(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, MethodType type); /** + * Wrapper for {@link java.lang.invoke.MethodHandles.Lookup#findSpecial(Class, String, MethodType, Class)} + * + * @param explicitLookup explicit lookup to be used + * @param clazz class to look in + * @param name name of method + * @param type method type + * @param thisClass thisClass + * + * @return method handle for virtual method + */ + public MethodHandle findSpecial(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, MethodType type, final Class<?> thisClass); + + /** * Wrapper for SwitchPoint creation. Just like {@code new SwitchPoint()} but potentially * tracked * @@ -313,5 +337,6 @@ public interface MethodHandleFunctionality { * @return the method type */ public MethodType type(Class<?> returnType, Class<?>... paramTypes); + } |