/** * Adds the standard exception handler. */ public void addExceptionHandler() { //TODO: if we would know exactly which paths require the exceptions // and which paths not, we can sometimes save this guard if (handle==null || !catchException) return; Class returnType = handle.type().returnType(); if (returnType!=Object.class) { MethodType mtype = MethodType.methodType(returnType, GroovyRuntimeException.class); handle = MethodHandles.catchException(handle, GroovyRuntimeException.class, UNWRAP_EXCEPTION.asType(mtype)); } else { handle = MethodHandles.catchException(handle, GroovyRuntimeException.class, UNWRAP_EXCEPTION); } if (LOG_ENABLED) LOG.info("added GroovyRuntimeException unwrapper"); }
private static MethodHandle cleanStackTraces(MethodHandle mh) { MethodType type = EXCEPTION_HANDLER.type().changeReturnType(mh.type().returnType()); return catchException(mh, Throwable.class, EXCEPTION_HANDLER.asType(type)); } }
/** * Creates a MethodHandle, which will use the meta class path. * This method is called only if no handle has been created before. This * is usually the case if the method selection failed. */ public void setMetaClassCallHandleIfNedded(boolean standardMetaClass) { if (handle!=null) return; useMetaClass = true; if (LOG_ENABLED) LOG.info("set meta class invocation path"); Object receiver = getCorrectedReceiver(); if (receiver instanceof Class) { handle = META_CLASS_INVOKE_STATIC_METHOD.bindTo(mc); if (LOG_ENABLED) LOG.info("use invokeStaticMethod with bound meta class"); } else { handle = MOP_INVOKE_METHOD.bindTo(mc); if (LOG_ENABLED) LOG.info("use invokeMethod with bound meta class"); if (receiver instanceof GroovyObject) { // if the meta class call fails we may still want to fall back to call // GroovyObject#invokeMethod if the receiver is a GroovyObject if (LOG_ENABLED) LOG.info("add MissingMethod handler for GrooObject#invokeMethod fallback path"); handle = MethodHandles.catchException(handle, MissingMethodException.class, GROOVY_OBJECT_INVOKER); } } handle = MethodHandles.insertArguments(handle, 1, name); if (!spread) handle = handle.asCollector(Object[].class, targetType.parameterCount()-1); if (LOG_ENABLED) LOG.info("bind method name and create collector for arguments"); }
@Override public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type fromType = boundVariables.getTypeVariable("F"); Type toType = boundVariables.getTypeVariable("T"); Class<?> returnType = Primitives.wrap(toType.getJavaType()); List<ArgumentProperty> argumentProperties; MethodHandle tryCastHandle; // the resulting method needs to return a boxed type Signature signature = functionRegistry.getCoercion(fromType, toType); ScalarFunctionImplementation implementation = functionRegistry.getScalarFunctionImplementation(signature); argumentProperties = ImmutableList.of(implementation.getArgumentProperty(0)); MethodHandle coercion = implementation.getMethodHandle(); coercion = coercion.asType(methodType(returnType, coercion.type())); MethodHandle exceptionHandler = dropArguments(constant(returnType, null), 0, RuntimeException.class); tryCastHandle = catchException(coercion, RuntimeException.class, exceptionHandler); return new ScalarFunctionImplementation(true, argumentProperties, tryCastHandle, isDeterministic()); } }
public MethodHandle up(MethodHandle target) { return MethodHandles.catchException(target, throwable, function); }
private static MethodHandle makeNullSafeGuarded(MethodHandle root) { MethodHandle catchThenNull = dropArguments(constant(Object.class, null), 0, NullPointerException.class); root = catchException(root, NullPointerException.class, catchThenNull); return root; }
@Override protected boolean matchesSafely(Block block) { MethodHandle call = MethodHandles.insertArguments(CALL_PROTECTED, 0, this, block); MethodHandle catchException = MethodHandles.insertArguments(CATCH_EXCEPTION, 0, this); MethodHandle verification = MethodHandles.catchException(call, expected, catchException); try { return (boolean) verification.invokeWithArguments(); } catch (Throwable e) { return false; } }
public static Object fallback_1(MonomorphicInlineCache inlineCache, Object[] args) throws Throwable { Class<?> argClass = (args[0] == null) ? Object.class : args[0].getClass(); MethodHandle target; try { target = inlineCache.callerLookup.findStatic( OperatorSupport.class, inlineCache.name, methodType(Object.class, argClass)); } catch (Throwable t1) { try { target = inlineCache.callerLookup.findStatic( OperatorSupport.class, inlineCache.name + "_fallback", methodType(Object.class, Object.class)); } catch (Throwable t2) { return reject(args[0], inlineCache.name); } } target = target.asType(methodType(Object.class, Object.class)); target = catchException(target, ClassCastException.class, inlineCache.fallback); inlineCache.setTarget(target); return target.invokeWithArguments(args); }
/** * Composes the invocation, switchpoint, and the guard into a composite method handle that knows how to fall back. * @param switchpointFallback the fallback method handle in case switchpoint is invalidated. * @param guardFallback the fallback method handle in case guard returns false. * @param catchFallback the fallback method in case the exception handler triggers * @return a composite method handle. */ public MethodHandle compose(final MethodHandle guardFallback, final MethodHandle switchpointFallback, final MethodHandle catchFallback) { final MethodHandle guarded = guard == null ? invocation : MethodHandles.guardWithTest(guard, invocation, guardFallback); final MethodHandle catchGuarded = exception == null ? guarded : MethodHandles.catchException(guarded, exception, MethodHandles.dropArguments(catchFallback, 0, exception)); MethodHandle spGuarded = catchGuarded; for (final SwitchPoint sp : switchPoints) { spGuarded = sp.guardWithTest(spGuarded, switchpointFallback); } return spGuarded; }
private static MethodHandle cleanStackTraces(MethodHandle mh) { MethodType type = EXCEPTION_HANDLER.type().changeReturnType(mh.type().returnType()); return catchException(mh, Throwable.class, EXCEPTION_HANDLER.asType(type)); } }
public static Object fallback_2(MonomorphicInlineCache inlineCache, Object[] args) throws Throwable { Class<?> arg1Class = (args[0] == null) ? Object.class : args[0].getClass(); Class<?> arg2Class = (args[1] == null) ? Object.class : args[1].getClass(); MethodHandle target; try { target = inlineCache.callerLookup.findStatic( OperatorSupport.class, inlineCache.name, methodType(Object.class, arg1Class, arg2Class)); } catch (Throwable t1) { try { target = inlineCache.callerLookup.findStatic( OperatorSupport.class, inlineCache.name + "_fallback", methodType(Object.class, Object.class, Object.class)); } catch (Throwable t2) { return reject(args[0], args[1], inlineCache.name); } } target = target.asType(methodType(Object.class, Object.class, Object.class)); if (arg1Class == String.class || arg2Class == String.class) { MethodHandle guard = insertArguments(GUARD_2, 0, arg1Class, arg2Class); target = guardWithTest(guard, target, inlineCache.fallback); } else { target = catchException(target, ClassCastException.class, dropArguments(inlineCache.fallback, 0, ClassCastException.class)); } inlineCache.setTarget(target); return target.invokeWithArguments(args); }
private static MethodHandle catchExceptions(MethodHandle handle, Converter converter) { MethodHandle thrower = MethodHandles.throwException(handle.type().returnType(), ScriptException.class); thrower = MethodHandles.filterArguments(thrower, 0, converter.toScriptException()); return MethodHandles.catchException(handle, Exception.class, thrower); }
@Override public ScalarFunctionImplementation specialize(Map<String, Type> types, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type fromType = types.get("F"); Type toType = types.get("T"); Class<?> returnType = Primitives.wrap(toType.getJavaType()); MethodHandle tryCastHandle; if (fromType.equals(UNKNOWN)) { tryCastHandle = dropArguments(constant(returnType, null), 0, Void.class); } else { // the resulting method needs to return a boxed type Signature signature = functionRegistry.getCoercion(fromType, toType); MethodHandle coercion = functionRegistry.getScalarFunctionImplementation(signature).getMethodHandle(); coercion = coercion.asType(methodType(returnType, coercion.type())); MethodHandle exceptionHandler = dropArguments(constant(returnType, null), 0, RuntimeException.class); tryCastHandle = catchException(coercion, RuntimeException.class, exceptionHandler); } return new ScalarFunctionImplementation(true, ImmutableList.of(true), tryCastHandle, isDeterministic()); } }
private static MethodHandle adaptMethodHandle(String name, MethodType callsiteType, MethodHandle mh) { try { MethodHandle target; if (isSpreadCall(mh, callsiteType)) { target = forSpreadCall(mh, callsiteType); } else { target = mh.asType(callsiteType); } if (target != mh) { MethodHandle invalidArgumentsHandle = invalidCallArgumentsExceptionHandle(name, callsiteType); target = MethodHandles.catchException(target, ClassCastException.class, invalidArgumentsHandle); } return target; } catch (IllegalArgumentException e) { return invalidCallHandle(name, callsiteType); } catch (WrongMethodTypeException e) { return invalidCallArgumentsHandle(name, callsiteType, e); } }
@Override public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type fromType = boundVariables.getTypeVariable("F"); Type toType = boundVariables.getTypeVariable("T"); Class<?> returnType = Primitives.wrap(toType.getJavaType()); List<ArgumentProperty> argumentProperties; MethodHandle tryCastHandle; // the resulting method needs to return a boxed type Signature signature = functionRegistry.getCoercion(fromType, toType); ScalarFunctionImplementation implementation = functionRegistry.getScalarFunctionImplementation(signature); argumentProperties = ImmutableList.of(implementation.getArgumentProperty(0)); MethodHandle coercion = implementation.getMethodHandle(); coercion = coercion.asType(methodType(returnType, coercion.type())); MethodHandle exceptionHandler = dropArguments(constant(returnType, null), 0, RuntimeException.class); tryCastHandle = catchException(coercion, RuntimeException.class, exceptionHandler); return new ScalarFunctionImplementation(true, argumentProperties, tryCastHandle, isDeterministic()); } }
@Override public ScalarFunctionImplementation specialize(BoundVariables boundVariables, int arity, TypeManager typeManager, FunctionRegistry functionRegistry) { Type fromType = boundVariables.getTypeVariable("F"); Type toType = boundVariables.getTypeVariable("T"); Class<?> returnType = Primitives.wrap(toType.getJavaType()); List<ArgumentProperty> argumentProperties; MethodHandle tryCastHandle; // the resulting method needs to return a boxed type Signature signature = functionRegistry.getCoercion(fromType, toType); ScalarFunctionImplementation implementation = functionRegistry.getScalarFunctionImplementation(signature); argumentProperties = ImmutableList.of(implementation.getArgumentProperty(0)); MethodHandle coercion = implementation.getMethodHandle(); coercion = coercion.asType(methodType(returnType, coercion.type())); MethodHandle exceptionHandler = dropArguments(constant(returnType, null), 0, RuntimeException.class); tryCastHandle = catchException(coercion, RuntimeException.class, exceptionHandler); return new ScalarFunctionImplementation(true, argumentProperties, tryCastHandle, isDeterministic()); } }
.invokeStaticQuiet(lookup(), Helpers.class, "rewriteStackTraceAndThrow"); nativeTarget = catchException(nativeTarget, Throwable.class, rewriteHandle.handle());
.invokeStaticQuiet(lookup(), Helpers.class, "rewriteStackTraceAndThrow"); nativeTarget = catchException(nativeTarget, Throwable.class, rewriteHandle.handle());
new int[] {0, 1}); target = catchException(target, JumpException.BreakJump.class, breakHandler);
public MethodHandle up(MethodHandle target) { if (Util.isJava9()) return nativeTryFinally(target, post); MethodHandle exceptionHandler = Binder .from(target.type().insertParameterTypes(0, Throwable.class).changeReturnType(void.class)) .drop(0) .invoke(post); MethodHandle rethrow = Binder .from(target.type().insertParameterTypes(0, Throwable.class)) .fold(exceptionHandler) .drop(1, target.type().parameterCount()) .throwException(); target = MethodHandles.catchException(target, Throwable.class, rethrow); // if target returns a value, we must return it regardless of post MethodHandle realPost = post; if (target.type().returnType() != void.class) { // modify post to ignore return value MethodHandle newPost = Binder .from(target.type().insertParameterTypes(0, target.type().returnType()).changeReturnType(void.class)) .drop(0) .invoke(post); // fold post into an identity chain that only returns the value realPost = Binder .from(target.type().insertParameterTypes(0, target.type().returnType())) .fold(newPost) .drop(1, target.type().parameterCount()) .identity(); } return MethodHandles.foldArguments(realPost, target); }