public static object createDelegate(MethodType newType, MethodHandle mh, int argnum, object argument)
    {
#if FIRST_PASS
        return(null);
#else
        Delegate del = (Delegate)mh.vmtarget;
        if (argnum == 0 &&
            del.Target == null
            // we don't have to check for instance methods on a Value Type, because DirectMethodHandle can't use a direct delegate for that anyway
            && (!del.Method.IsStatic || !del.Method.GetParameters()[0].ParameterType.IsValueType) &&
            !ReflectUtil.IsDynamicMethod(del.Method))
        {
            return(Delegate.CreateDelegate(MethodHandleUtil.CreateDelegateType(newType), argument, del.Method));
        }
        else
        {
            // slow path where we're generating a DynamicMethod
            if (mh.type().parameterType(argnum).isPrimitive())
            {
                argument = JVM.Unbox(argument);
            }
            MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder("BoundMethodHandle", newType, mh, argument);
            for (int i = 0, count = mh.type().parameterCount(), pos = 0; i < count; i++)
            {
                if (i == argnum)
                {
                    dm.LoadValue();
                }
                else
                {
                    dm.Ldarg(pos++);
                }
            }
            dm.CallTarget();
            dm.Ret();
            return(dm.CreateDelegate());
        }
#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
    }
Beispiel #3
0
    // TODO what is lookupClass for?
    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];
            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
    }