public static T GetDelegateForInvoke <T>(global::java.lang.invoke.MethodHandle h, ref InvokeCache <T> cache) where T : class { #if FIRST_PASS return(null); #else if (cache.type == h.type() && cache.del != null) { return(cache.del); } T del = h.vmtarget as T; if (del == null) { global::java.lang.invoke.MethodHandle adapter = global::java.lang.invoke.MethodHandles.exactInvoker(h.type()); if (h.isVarargsCollector()) { adapter = adapter.asVarargsCollector(h.type().parameterType(h.type().parameterCount() - 1)); } del = (T)adapter.asType(MethodHandleUtil.GetDelegateMethodType(typeof(T))).vmtarget; if (Interlocked.CompareExchange(ref cache.type, h.type(), null) == null) { cache.del = del; } } return(del); #endif }
internal static void InitializeCallSite(JlInvoke.CallSite site) { Type type = typeof(IKVM.Runtime.IndyCallSite <>).MakeGenericType(MethodHandleUtil.GetDelegateTypeForInvokeExact(site.type())); IKVM.Runtime.IIndyCallSite ics = (IKVM.Runtime.IIndyCallSite)Activator.CreateInstance(type, true); System.Threading.Interlocked.CompareExchange(ref site.ics, ics, null); }
public static T DynamicBinderMemberLookup <T>(int kind, string clazz, string name, string sig, [email protected] callerID) where T : class /* delegate */ { #if FIRST_PASS return(null); #else try { java.lang.invoke.MethodHandle mh = DynamicLoadMethodHandleImpl(kind, clazz, name, sig, callerID); return(GetDelegateForInvokeExact <T>(mh.asType(MethodHandleUtil.GetDelegateMethodType(typeof(T))))); } catch (java.lang.IncompatibleClassChangeError x) { if (x.getCause() is java.lang.NoSuchMethodException) { throw new java.lang.NoSuchMethodError(x.getCause().Message); } if (x.getCause() is java.lang.NoSuchFieldException) { throw new java.lang.NoSuchFieldError(x.getCause().Message); } if (x.getCause() is java.lang.IllegalAccessException) { throw new java.lang.IllegalAccessError(x.getCause().Message); } throw; } #endif }
public static java.lang.invoke.MethodType LoadMethodType <T>() where T : class // Delegate { #if FIRST_PASS return(null); #else return(MethodHandleUtil.GetDelegateMethodType(typeof(T))); #endif }
public static Delegate DynamicCreateDelegate(object obj, Type delegateType, string name, string sig) { #if !WINRT #if FIRST_PASS return(null); #else TypeWrapper tw = TypeWrapper.FromClass(ikvm.runtime.Util.getClassFromObject(obj)); MethodWrapper mw = tw.GetMethodWrapper(name, sig, true); if (mw == null || mw.IsStatic || !mw.IsPublic) { #if NO_REF_EMIT java.lang.invoke.MethodType methodType = MethodHandleUtil.GetDelegateMethodType(delegateType); if (methodType.parameterCount() > MethodHandleUtil.MaxArity) { throw new NotImplementedException(); } java.lang.invoke.MethodHandle exception = java.lang.invoke.MethodHandles.publicLookup() .findConstructor(mw == null || mw.IsStatic ? typeof(java.lang.AbstractMethodError) : typeof(java.lang.IllegalAccessError), java.lang.invoke.MethodType.methodType(typeof(void), typeof(string))) .bindTo(tw.Name + ".Invoke" + sig); return(Delegate.CreateDelegate(delegateType, java.lang.invoke.MethodHandles.dropArguments( java.lang.invoke.MethodHandles.foldArguments(java.lang.invoke.MethodHandles.throwException(methodType.returnType(), exception.type().returnType()), exception), 0, methodType.parameterArray()).vmtarget, "Invoke")); #else MethodInfo invoke = delegateType.GetMethod("Invoke"); ParameterInfo[] parameters = invoke.GetParameters(); Type[] parameterTypes = new Type[parameters.Length + 1]; parameterTypes[0] = typeof(object); for (int i = 0; i < parameters.Length; i++) { parameterTypes[i + 1] = parameters[i].ParameterType; } System.Reflection.Emit.DynamicMethod dm = new System.Reflection.Emit.DynamicMethod("Invoke", invoke.ReturnType, parameterTypes); CodeEmitter ilgen = CodeEmitter.Create(dm); ilgen.Emit(System.Reflection.Emit.OpCodes.Ldstr, tw.Name + ".Invoke" + sig); ClassLoaderWrapper.GetBootstrapClassLoader() .LoadClassByDottedName(mw == null || mw.IsStatic ? "java.lang.AbstractMethodError" : "java.lang.IllegalAccessError") .GetMethodWrapper("<init>", "(Ljava.lang.String;)V", false) .EmitNewobj(ilgen); ilgen.Emit(System.Reflection.Emit.OpCodes.Throw); ilgen.DoEmit(); return(dm.CreateDelegate(delegateType, obj)); #endif } else { mw.ResolveMethod(); return(Delegate.CreateDelegate(delegateType, obj, (MethodInfo)mw.GetMethod())); } #endif #else throw new NotImplementedException(); #endif }
/* * NOTE: These load/store methods use the localsMap to find the correct index! */ private void emitLoadInsn(BasicType type, int index) { // [IKVM] we don't need the localsMap (it is used to correct for long/double taking two slots) if (locals[index] == null) { MethodHandleUtil.LoadPackedArg(ilgen, index, 1, packedArgPos, packedArgType); } else { ilgen.Emit(OpCodes.Ldloc, locals[index]); } }
// TODO consider caching this delegate in MethodWrapper private static Delegate CreateMemberNameDelegate(MethodWrapper mw, java.lang.Class caller, bool doDispatch, MethodType type) { #if FIRST_PASS return(null); #else if (mw.IsDynamicOnly) { return(MethodHandleUtil.DynamicMethodBuilder.CreateDynamicOnly(mw, type)); } // 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(caller); 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); } } TypeWrapper tw = mw.DeclaringType; tw.Finish(); mw.Link(); mw.ResolveMethod(); MethodInfo mi = mw.GetMethod() as MethodInfo; if (mi != null && !mw.HasCallerID && mw.IsStatic && MethodHandleUtil.HasOnlyBasicTypes(mw.GetParameters(), mw.ReturnType) && type.parameterCount() <= MethodHandleUtil.MaxArity) { return(Delegate.CreateDelegate(MethodHandleUtil.CreateMemberWrapperDelegateType(mw.GetParameters(), mw.ReturnType), mi)); } else { // slow path where we emit a DynamicMethod return(MethodHandleUtil.DynamicMethodBuilder.CreateMemberName(mw, type, doDispatch)); } #endif }
public static T GetDelegateForInvokeBasic <T>(java.lang.invoke.MethodHandle h) where T : class { #if FIRST_PASS return(null); #else T del = h.form.vmentry.vmtarget as T; if (del == null) { del = MethodHandleUtil.GetVoidAdapter(h.form.vmentry) as T; } return(del); #endif }
public static T GetDelegateForInvokeExact <T>(global::java.lang.invoke.MethodHandle h) where T : class { #if FIRST_PASS return(null); #else T del = h._invokeExactDelegate as T; if (del == null) { del = MethodHandleUtil.GetDelegateForInvokeExact <T>(h); } return(del); #endif }
internal static Delegate CreateMethodHandleLinkTo(MemberName mn) { MethodType type = mn.getMethodType(); Type delegateType = MethodHandleUtil.GetMemberWrapperDelegateType(type.dropParameterTypes(type.parameterCount() - 1, type.parameterCount())); DynamicMethodBuilder dm = new DynamicMethodBuilder("DirectMethodHandle." + mn.getName() + type, type, null, null, null, null, true); dm.Ldarg(type.parameterCount() - 1); dm.ilgen.EmitCastclass(typeof(JlInvoke.MemberName)); dm.ilgen.Emit(OpCodes.Ldfld, typeof(JlInvoke.MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic)); dm.ilgen.Emit(OpCodes.Castclass, delegateType); for (int i = 0, count = type.parameterCount() - 1; i < count; i++) { dm.Ldarg(i); } dm.CallDelegate(delegateType); dm.Ret(); return(dm.CreateDelegate()); }
public static T GetDelegateForInvoke <T>(global::java.lang.invoke.MethodHandle h, java.lang.invoke.MethodType realType, ref InvokeCache <T> cache) where T : class { #if FIRST_PASS return(null); #else T del; if (cache.Type == h.type() && (del = (h.isVarargsCollector() ? cache.varArg : cache.fixedArg)) != null) { return(del); } del = h.form.vmentry.vmtarget as T; if (del == null) { global::java.lang.invoke.MethodHandle adapter = global::java.lang.invoke.MethodHandles.exactInvoker(h.type()); if (h.isVarargsCollector()) { adapter = adapter.asVarargsCollector(h.type().parameterType(h.type().parameterCount() - 1)); } // if realType is set, the delegate contains erased unloadable types if (realType != null) { adapter = adapter.asType(realType.insertParameterTypes(0, [email protected] <java.lang.invoke.MethodHandle> .Value)).asFixedArity(); } adapter = adapter.asType(MethodHandleUtil.GetDelegateMethodType(typeof(T))); del = GetDelegateForInvokeExact <T>(adapter); if (cache.TrySetType(h.type())) { if (h.isVarargsCollector()) { cache.varArg = del; } else { cache.fixedArg = del; } } } return(del); #endif }
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 }
internal static Delegate CreateMethodHandleInvoke(MemberName mn) { MethodType type = mn.getMethodType().insertParameterTypes(0, mn.getDeclaringClass()); Type targetDelegateType = MethodHandleUtil.GetMemberWrapperDelegateType(type); DynamicMethodBuilder dm = new DynamicMethodBuilder("DirectMethodHandle." + mn.getName() + type, type, typeof(Container <,>).MakeGenericType(typeof(object), typeof(IKVM.Runtime.InvokeCache <>).MakeGenericType(targetDelegateType)), null, null, null, true); dm.Ldarg(0); dm.EmitCheckcast(CoreClasses.java.lang.invoke.MethodHandle.Wrapper); switch (mn.getName()) { case "invokeExact": dm.Call(ByteCodeHelperMethods.GetDelegateForInvokeExact.MakeGenericMethod(targetDelegateType)); break; case "invoke": dm.LoadValueAddress(); dm.Call(ByteCodeHelperMethods.GetDelegateForInvoke.MakeGenericMethod(targetDelegateType)); break; case "invokeBasic": dm.Call(ByteCodeHelperMethods.GetDelegateForInvokeBasic.MakeGenericMethod(targetDelegateType)); break; default: throw new InvalidOperationException(); } dm.Ldarg(0); for (int i = 1, count = type.parameterCount(); i < count; i++) { dm.Ldarg(i); } dm.CallDelegate(targetDelegateType); dm.Ret(); return(dm.CreateDelegate()); }
public static T GetDelegateForInvoke <T>(global::java.lang.invoke.MethodHandle h, ref InvokeCache <T> cache) where T : class { #if FIRST_PASS return(null); #else T del; if (cache.Type == h.type() && (del = (h.isVarargsCollector() ? cache.varArg : cache.fixedArg)) != null) { return(del); } del = h.form.vmentry.vmtarget as T; if (del == null) { global::java.lang.invoke.MethodHandle adapter = global::java.lang.invoke.MethodHandles.exactInvoker(h.type()); if (h.isVarargsCollector()) { adapter = adapter.asVarargsCollector(h.type().parameterType(h.type().parameterCount() - 1)); } adapter = adapter.asType(MethodHandleUtil.GetDelegateMethodType(typeof(T))); del = GetDelegateForInvokeExact <T>(adapter); if (cache.TrySetType(h.type())) { if (h.isVarargsCollector()) { cache.varArg = del; } else { cache.fixedArg = del; } } } return(del); #endif }
// 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 }
internal ConstantMethodHandle(Delegate del) : base(MethodHandleUtil.GetDelegateMethodType(del.GetType())) { this.vmtarget = del; }
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 }
private NativeInvokerBytecodeGenerator(LambdaForm lambdaForm, MethodType invokerType) { if (invokerType != invokerType.basicType()) { throw new BailoutException(Bailout.NotBasicType, invokerType); } this.lambdaForm = lambdaForm; this.invokerType = invokerType; this.delegateType = MethodHandleUtil.GetMemberWrapperDelegateType(invokerType); MethodInfo mi = MethodHandleUtil.GetDelegateInvokeMethod(delegateType); Type[] paramTypes = MethodHandleUtil.GetParameterTypes(typeof(object[]), mi); // HACK the code we generate is not verifiable (known issue: locals aren't typed correctly), so we stick the DynamicMethod into mscorlib (a security critical assembly) this.dm = new DynamicMethod(lambdaForm.debugName, mi.ReturnType, paramTypes, typeof(object).Module, true); this.ilgen = CodeEmitter.Create(this.dm); if (invokerType.parameterCount() > MethodHandleUtil.MaxArity) { this.packedArgType = paramTypes[paramTypes.Length - 1]; this.packedArgPos = paramTypes.Length - 1; } else { this.packedArgPos = Int32.MaxValue; } locals = new CodeEmitterLocal[lambdaForm.names.Length]; for (int i = lambdaForm._arity(); i < lambdaForm.names.Length; i++) { Name name = lambdaForm.names[i]; if (name.index() != i) { throw new BailoutException(Bailout.PreconditionViolated, "name.index() != i"); } switch (name.typeChar()) { case 'L': locals[i] = ilgen.DeclareLocal(Types.Object); break; case 'I': locals[i] = ilgen.DeclareLocal(Types.Int32); break; case 'J': locals[i] = ilgen.DeclareLocal(Types.Int64); break; case 'F': locals[i] = ilgen.DeclareLocal(Types.Single); break; case 'D': locals[i] = ilgen.DeclareLocal(Types.Double); break; case 'V': break; default: throw new BailoutException(Bailout.PreconditionViolated, "Unsupported typeChar(): " + name.typeChar()); } } }