public static MethodHandle permuteArguments(MethodHandle target, MethodType newType, MethodType oldType, int[] permutationOrNull) { #if FIRST_PASS return(null); #else // LAME why does OpenJDK name the parameter permutationOrNull while it is not allowed to be null? if (permutationOrNull.Length != oldType.parameterCount()) { throw new java.lang.IllegalArgumentException("wrong number of arguments in permutation"); } MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder("MethodHandleImpl.permuteArguments", newType, target); for (int i = 0, argCount = newType.parameterCount(); i < permutationOrNull.Length; i++) { // make sure to only read each array element once, to avoid having to make a defensive copy of the array int perm = permutationOrNull[i]; if (perm < 0 || perm >= argCount) { throw new java.lang.IllegalArgumentException("permutation argument out of range"); } dm.Ldarg(perm); dm.Convert(oldType.parameterType(i), newType.parameterType(perm), 0); } dm.CallTarget(); dm.Convert(oldType.returnType(), newType.returnType(), 0); dm.Ret(); return(dm.CreateAdapter()); #endif }
public static MethodHandle makeSpreadArguments(MethodType newType, MethodHandle target, java.lang.Class spreadArgType, int spreadArgPos, int spreadArgCount) { #if FIRST_PASS return(null); #else TypeWrapper twComponent = TypeWrapper.FromClass(spreadArgType).ElementTypeWrapper; MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder("AdapterMethodHandle.spreadArguments", newType, target); for (int i = 0, count = newType.parameterCount(); i < count; i++) { if (i == spreadArgPos) { for (int j = 0; j < spreadArgCount; j++) { dm.Ldarg(i); dm.LoadArrayElement(j, twComponent); dm.Convert(twComponent.ClassObject, target.type().parameterType(i + j), 0); } } else { dm.Ldarg(i); } } dm.CallTarget(); dm.Ret(); return(dm.CreateAdapter()); #endif }
public static MethodHandle makePairwiseConvert(MethodType newType, MethodHandle target, int level) { #if FIRST_PASS return(null); #else MethodType oldType = target.type(); MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder("AdapterMethodHandle.pairwiseConvert", newType, target); for (int i = 0, count = newType.parameterCount(); i < count; i++) { dm.Ldarg(i); dm.Convert(newType.parameterType(i), oldType.parameterType(i), level); } dm.CallTarget(); dm.Convert(oldType.returnType(), newType.returnType(), level); dm.Ret(); return(dm.CreateAdapter()); #endif }
public static object createDelegate(MethodType type, MemberName m, bool doDispatch, jlClass lookupClass) { #if FIRST_PASS return(null); #else int index = m.getVMIndex(); if (index == Int32.MaxValue) { bool invokeExact = m.getName() == "invokeExact"; Type targetDelegateType = MethodHandleUtil.CreateDelegateType(invokeExact ? type.dropParameterTypes(0, 1) : type); MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder("DirectMethodHandle." + m.getName(), type, typeof(IKVM.Runtime.InvokeCache <>).MakeGenericType(targetDelegateType)); dm.Ldarg(0); if (invokeExact) { dm.Call(ByteCodeHelperMethods.GetDelegateForInvokeExact.MakeGenericMethod(targetDelegateType)); } else { dm.LoadValueAddress(); dm.Call(ByteCodeHelperMethods.GetDelegateForInvoke.MakeGenericMethod(targetDelegateType)); dm.Ldarg(0); } for (int i = 1, count = type.parameterCount(); i < count; i++) { dm.Ldarg(i); } dm.CallDelegate(targetDelegateType); dm.Ret(); return(dm.CreateDelegate()); } else { TypeWrapper tw = (TypeWrapper)typeof(MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(m); tw.Finish(); MethodWrapper mw = tw.GetMethods()[index]; if (mw.IsDynamicOnly) { MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder("CustomInvoke:" + mw.Name, type, (ICustomInvoke)mw); if (mw.IsStatic) { dm.LoadNull(); dm.BoxArgs(0); } else { dm.Ldarg(0); dm.BoxArgs(1); } dm.Callvirt(typeof(ICustomInvoke).GetMethod("Invoke")); dm.Convert(typeof(object), type.returnType(), 0); dm.Ret(); return(dm.CreateDelegate()); } // HACK this code is duplicated in compiler.cs if (mw.IsProtected && (mw.DeclaringType == CoreClasses.java.lang.Object.Wrapper || mw.DeclaringType == CoreClasses.java.lang.Throwable.Wrapper)) { TypeWrapper thisType = TypeWrapper.FromClass(lookupClass); TypeWrapper cli_System_Object = ClassLoaderWrapper.LoadClassCritical("cli.System.Object"); TypeWrapper cli_System_Exception = ClassLoaderWrapper.LoadClassCritical("cli.System.Exception"); // HACK we may need to redirect finalize or clone from java.lang.Object/Throwable // to a more specific base type. if (thisType.IsAssignableTo(cli_System_Object)) { mw = cli_System_Object.GetMethodWrapper(mw.Name, mw.Signature, true); } else if (thisType.IsAssignableTo(cli_System_Exception)) { mw = cli_System_Exception.GetMethodWrapper(mw.Name, mw.Signature, true); } else if (thisType.IsAssignableTo(CoreClasses.java.lang.Throwable.Wrapper)) { mw = CoreClasses.java.lang.Throwable.Wrapper.GetMethodWrapper(mw.Name, mw.Signature, true); } } mw.ResolveMethod(); MethodInfo mi = mw.GetMethod() as MethodInfo; if (mi != null && !tw.IsRemapped && !tw.IsGhost && !tw.IsNonPrimitiveValueType && type.parameterCount() <= MethodHandleUtil.MaxArity // FXBUG we should be able to use a normal (unbound) delegate for virtual methods // (when doDispatch is set), but the x64 CLR crashes when doing a virtual method dispatch on // a null reference && (!mi.IsVirtual || (doDispatch && IntPtr.Size == 4)) && (doDispatch || !mi.IsVirtual)) { return(Delegate.CreateDelegate(MethodHandleUtil.CreateDelegateType(tw, mw), mi)); } else { // slow path where we emit a DynamicMethod MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder(mw.DeclaringType.TypeAsBaseType, "DirectMethodHandle:" + mw.Name, type); for (int i = 0, count = type.parameterCount(); i < count; i++) { if (i == 0 && !mw.IsStatic && (tw.IsGhost || tw.IsNonPrimitiveValueType)) { dm.LoadFirstArgAddress(); } else { dm.Ldarg(i); } } if (doDispatch && !mw.IsStatic) { dm.Callvirt(mw); } else { dm.Call(mw); } dm.Ret(); return(dm.CreateDelegate()); } } #endif }