@Override public MethodHandle getMethodHandle(String methodName, MethodType type) throws NoSuchMethodException, IllegalAccessException { MethodHandle nothing = constant(Void.class, null).asType(methodType(void.class)); if (type.parameterCount() != 0) { return dropArguments(nothing, 0, type.parameterArray()); } else { return nothing; } } }
/** * Set MOP based constructor invocation path. */ @Override public void setMetaClassCallHandleIfNedded(boolean standardMetaClass) { if (handle!=null) return; useMetaClass = true; if (LOG_ENABLED) LOG.info("set meta class invocation path"); handle = MOP_INVOKE_CONSTRUCTOR.bindTo(mc); handle = handle.asCollector(Object[].class, targetType.parameterCount()-1); handle = MethodHandles.dropArguments(handle, 0, Class.class); if (LOG_ENABLED) LOG.info("create collector for arguments"); } }
private static MethodHandle getMethodHandle(String className, String methodName, MethodType type) { Interceptor interceptor = INTERCEPTORS.findInterceptor(className, methodName); if (interceptor != null) { try { // reload interceptor in sandbox... Class<Interceptor> theClass = (Class<Interceptor>) ReflectionHelpers.loadClass( RobolectricInternals.getClassLoader(), interceptor.getClass().getName()).asSubclass(Interceptor.class); return ReflectionHelpers.newInstance(theClass).getMethodHandle(methodName, type); } catch (NoSuchMethodException | IllegalAccessException e) { throw new RuntimeException(e); } } if (type.parameterCount() != 0) { return dropArguments(NOTHING, 0, type.parameterArray()); } else { return NOTHING; } }
/** * Makes a fallback method for an invalidated method selection */ protected static MethodHandle makeFallBack(MutableCallSite mc, Class<?> sender, String name, int callID, MethodType type, boolean safeNavigation, boolean thisCall, boolean spreadCall) { MethodHandle mh = MethodHandles.insertArguments(SELECT_METHOD, 0, mc, sender, name, callID, safeNavigation, thisCall, spreadCall, /*dummy receiver:*/ 1); mh = mh.asCollector(Object[].class, type.parameterCount()). asType(type); return mh; }
/** * Sets a handle to call {@link GroovyInterceptable#invokeMethod(String, Object)} */ public boolean setInterceptor() { if (!(this.args[0] instanceof GroovyInterceptable)) return false; handle = MethodHandles.insertArguments(INTERCEPTABLE_INVOKER, 1, this.name); handle = handle.asCollector(Object[].class, targetType.parameterCount()-1); handle = handle.asType(targetType); return true; }
/** * Additionally to the normal {@link MethodSelector#setHandleForMetaMethod()} * task we have to also take care of generic getter methods, that depend * one the name. */ @Override public void setHandleForMetaMethod() { if (handle!=null) return; super.setHandleForMetaMethod(); if (handle != null && insertName && handle.type().parameterCount()==2) { handle = MethodHandles.insertArguments(handle, 1, name); } }
private MethodHandle getMethodHandle(Method method) { MethodHandle methodHandle = methodHandle(FUNCTION_IMPLEMENTATION_ERROR, method); if (!isStatic(method.getModifiers())) { // Change type of "this" argument to Object to make sure callers won't have classloader issues methodHandle = methodHandle.asType(methodHandle.type().changeParameterType(0, Object.class)); // Re-arrange the parameters, so that the "this" parameter is after the meta parameters int[] permutedIndices = new int[methodHandle.type().parameterCount()]; permutedIndices[0] = dependencies.size(); MethodType newType = methodHandle.type().changeParameterType(dependencies.size(), methodHandle.type().parameterType(0)); for (int i = 0; i < dependencies.size(); i++) { permutedIndices[i + 1] = i; newType = newType.changeParameterType(i, methodHandle.type().parameterType(i + 1)); } for (int i = dependencies.size() + 1; i < permutedIndices.length; i++) { permutedIndices[i] = i; } methodHandle = permuteArguments(methodHandle, newType, permutedIndices); } return methodHandle; }
/** * 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"); }
/** * @since 2.5.0 */ public static CallSite staticArrayAccess(MethodHandles.Lookup lookup, String name, MethodType type) { if (type.parameterCount()==2) { return new ConstantCallSite(IndyArrayAccess.arrayGet(type)); } else { return new ConstantCallSite(IndyArrayAccess.arraySet(type)); } } }
@Override public MethodHandle findShadowMethodHandle(Class<?> theClass, String name, MethodType type, boolean isStatic) throws IllegalAccessException { String signature = getSignature(theClass, name, type, isStatic); InvocationProfile invocationProfile = new InvocationProfile(signature, isStatic, getClass().getClassLoader()); try { MethodHandle mh = MethodHandles.lookup().findVirtual(getClass(), "invoke", methodType(Object.class, InvocationProfile.class, Object.class, Object[].class)); mh = insertArguments(mh, 0, this, invocationProfile); if (isStatic) { return mh.bindTo(null).asCollector(Object[].class, type.parameterCount()); } else { return mh.asCollector(Object[].class, type.parameterCount() - 1); } } catch (NoSuchMethodException e) { throw new AssertionError(e); } }
if (method.type().parameterCount() > 0 && method.type().parameterType(0) == ConnectorSession.class) { method = method.bindTo(session);
} else { handle = handle.asCollector(Object[].class, targetType.parameterCount()-1);
if (f.type().parameterCount() != 2) { throw new IllegalArgumentException(format("f.parameterCount != 2. f: %s", f.type())); MethodHandle fVTU = MethodHandles.permuteArguments(f, typeVTU, h.type().parameterCount() + 1, 0); int[] reorder = new int[fhTU.type().parameterCount()]; for (int i = 0; i < reorder.length - 1; i++) { reorder[i] = i + 1 + g.type().parameterCount();
if (f.type().parameterCount() != 2) { throw new IllegalArgumentException(format("f.parameterCount != 2. f: %s", f.type())); MethodHandle fVTU = MethodHandles.permuteArguments(f, typeVTU, h.type().parameterCount() + 1, 0); int[] reorder = new int[fhTU.type().parameterCount()]; for (int i = 0; i < reorder.length - 1; i++) { reorder[i] = i + 1 + g.type().parameterCount();
MethodHandle method = function.getMethodHandle(); if (method.type().parameterCount() > 0 && method.type().parameterType(0) == ConnectorSession.class) { method = method.bindTo(session);
@Override protected Object visitArithmeticUnary(ArithmeticUnaryExpression node, Object context) { Object value = process(node.getValue(), context); if (value == null) { return null; } if (value instanceof Expression) { return new ArithmeticUnaryExpression(node.getSign(), toExpression(value, type(node.getValue()))); } switch (node.getSign()) { case PLUS: return value; case MINUS: Signature operatorSignature = metadata.getFunctionRegistry().resolveOperator(OperatorType.NEGATION, types(node.getValue())); MethodHandle handle = metadata.getFunctionRegistry().getScalarFunctionImplementation(operatorSignature).getMethodHandle(); if (handle.type().parameterCount() > 0 && handle.type().parameterType(0) == ConnectorSession.class) { handle = handle.bindTo(session); } try { return handle.invokeWithArguments(value); } catch (Throwable throwable) { throwIfInstanceOf(throwable, RuntimeException.class); throwIfInstanceOf(throwable, Error.class); throw new RuntimeException(throwable.getMessage(), throwable); } } throw new UnsupportedOperationException("Unsupported unary operator: " + node.getSign()); }
/** * Widens the operators. For math operations like a+b we generally * execute them using a conversion to certain types. If a for example * is an int and b a byte, we do the operation using integer math. This * method gives a simplified MethodType that contains the two operators * with this widening according to Groovy rules applied. That means both * parameters in the MethodType will have the same type. */ private static MethodType widenOperators(MethodType mt) { if (mt.parameterCount()==2) { Class leftType = mt.parameterType(0); Class rightType = mt.parameterType(1); if (isIntCategory(leftType) && isIntCategory(rightType)) return IIV; if (isLongCategory(leftType) && isLongCategory(rightType)) return LLV; if (isBigDecCategory(leftType) && isBigDecCategory(rightType)) return GGV; if (isDoubleCategory(leftType) && isDoubleCategory(rightType)) return DDV; return OOV; } else if (mt.parameterCount()==1) { Class leftType = mt.parameterType(0); if (isIntCategory(leftType)) return IV; if (isLongCategory(leftType)) return LV; if (isBigDecCategory(leftType)) return GV; if (isDoubleCategory(leftType)) return DV; } return mt; }
@Override public MethodHandle getMethodHandle(String methodName, MethodType type) throws NoSuchMethodException, IllegalAccessException { MethodHandle nothing = constant(Void.class, null).asType(methodType(void.class)); if (type.parameterCount() != 0) { return dropArguments(nothing, 0, type.parameterArray()); } else { return nothing; } } }
/** * Returns the arity of the function. * * The arity is the number of declared parameter in the function signature. * * @return the number of declared parameter */ public int arity() { return handle.type().parameterCount(); }
public MethodHandle bind(TypeDefinition td) { MethodHandle mh = this.mh; mh = bindDatabases(type.wantedType.parameterCount(), td, mh); return type.adapt(mh); }