2
Copyright (C) 2011 Jeroen Frijters
4
This software is provided 'as-is', without any express or implied
5
warranty. In no event will the authors be held liable for any damages
6
arising from the use of this software.
8
Permission is granted to anyone to use this software for any purpose,
9
including commercial applications, and to alter it and redistribute it
10
freely, subject to the following restrictions:
12
1. The origin of this software must not be misrepresented; you must not
13
claim that you wrote the original software. If you use this software
14
in a product, an acknowledgment in the product documentation would be
15
appreciated but is not required.
16
2. Altered source versions must be plainly marked as such, and must not be
17
misrepresented as being the original software.
18
3. This notice may not be removed or altered from any source distribution.
26
using System.Reflection;
27
using System.Reflection.Emit;
29
using java.lang.invoke;
30
using jlClass = java.lang.Class;
32
static class Java_java_lang_invoke_BoundMethodHandle
34
public static object createDelegate(MethodType newType, MethodHandle mh, int argnum, object argument)
39
Delegate del = (Delegate)mh.vmtarget;
42
// we don't have to check for instance methods on a Value Type, because DirectMethodHandle can't use a direct delegate for that anyway
43
&& (!del.Method.IsStatic || !del.Method.GetParameters()[0].ParameterType.IsValueType)
44
&& !ReflectUtil.IsDynamicMethod(del.Method))
46
return Delegate.CreateDelegate(MethodHandleUtil.CreateDelegateType(newType), argument, del.Method);
50
// slow path where we're generating a DynamicMethod
51
if (mh.type().parameterType(argnum).isPrimitive())
53
argument = JVM.Unbox(argument);
55
MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder("BoundMethodHandle", newType, mh, argument);
56
for (int i = 0, count = mh.type().parameterCount(), pos = 0; i < count; i++)
69
return dm.CreateDelegate();
75
static class Java_java_lang_invoke_CallSite
77
public static object createIndyCallSite(object target)
79
return Activator.CreateInstance(typeof(IKVM.Runtime.IndyCallSite<>).MakeGenericType(target.GetType()), true);
83
static class Java_java_lang_invoke_DirectMethodHandle
85
// TODO what is lookupClass for?
86
public static object createDelegate(MethodType type, MemberName m, bool doDispatch, jlClass lookupClass)
91
int index = m.getVMIndex();
92
if (index == Int32.MaxValue)
94
bool invokeExact = m.getName() == "invokeExact";
95
Type targetDelegateType = MethodHandleUtil.CreateDelegateType(invokeExact ? type.dropParameterTypes(0, 1) : type);
96
MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder("DirectMethodHandle." + m.getName(), type, typeof(IKVM.Runtime.InvokeCache<>).MakeGenericType(targetDelegateType));
100
dm.Call(ByteCodeHelperMethods.GetDelegateForInvokeExact.MakeGenericMethod(targetDelegateType));
104
dm.LoadValueAddress();
105
dm.Call(ByteCodeHelperMethods.GetDelegateForInvoke.MakeGenericMethod(targetDelegateType));
108
for (int i = 1, count = type.parameterCount(); i < count; i++)
112
dm.CallDelegate(targetDelegateType);
114
return dm.CreateDelegate();
118
TypeWrapper tw = (TypeWrapper)typeof(MemberName).GetField("vmtarget", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(m);
120
MethodWrapper mw = tw.GetMethods()[index];
122
MethodInfo mi = mw.GetMethod() as MethodInfo;
126
&& !tw.IsNonPrimitiveValueType
127
&& type.parameterCount() <= MethodHandleUtil.MaxArity
128
// FXBUG we should be able to use a normal (unbound) delegate for virtual methods
129
// (when doDispatch is set), but the x64 CLR crashes when doing a virtual method dispatch on
131
&& (!mi.IsVirtual || (doDispatch && IntPtr.Size == 4))
132
&& (doDispatch || !mi.IsVirtual))
134
return Delegate.CreateDelegate(MethodHandleUtil.CreateDelegateType(tw, mw), mi);
138
// slow path where we emit a DynamicMethod
139
MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder(mw.DeclaringType.TypeAsBaseType, "DirectMethodHandle:" + mw.Name, type);
140
for (int i = 0, count = type.parameterCount(); i < count; i++)
142
if (i == 0 && !mw.IsStatic && (tw.IsGhost || tw.IsNonPrimitiveValueType))
144
dm.LoadFirstArgAddress();
151
if (doDispatch && !mw.IsStatic)
160
return dm.CreateDelegate();
167
static class Java_java_lang_invoke_MethodHandle
169
private static IKVM.Runtime.InvokeCache<IKVM.Runtime.MH<MethodHandle, object[], object>> cache;
171
public static object invokeExact(MethodHandle mh, object[] args)
176
return IKVM.Runtime.ByteCodeHelper.GetDelegateForInvokeExact<IKVM.Runtime.MH<object[], object>>(mh)(args);
180
public static object invoke(MethodHandle mh, object[] args)
185
MethodType type = mh.type();
186
if (mh.isVarargsCollector())
188
java.lang.Class varargType = type.parameterType(type.parameterCount() - 1);
189
if (type.parameterCount() == args.Length)
191
if (!varargType.isInstance(args[args.Length - 1]))
193
Array arr = (Array)java.lang.reflect.Array.newInstance(varargType.getComponentType(), 1);
194
arr.SetValue(args[args.Length - 1], 0);
195
args[args.Length - 1] = arr;
198
else if (type.parameterCount() - 1 > args.Length)
200
throw new WrongMethodTypeException();
204
object[] newArgs = new object[type.parameterCount()];
205
Array.Copy(args, newArgs, newArgs.Length - 1);
206
Array varargs = (Array)java.lang.reflect.Array.newInstance(varargType.getComponentType(), args.Length - (newArgs.Length - 1));
207
Array.Copy(args, newArgs.Length - 1, varargs, 0, varargs.Length);
208
newArgs[newArgs.Length - 1] = varargs;
212
if (mh.type().parameterCount() != args.Length)
214
throw new WrongMethodTypeException();
216
mh = mh.asSpreader(typeof(object[]), args.Length);
217
return IKVM.Runtime.ByteCodeHelper.GetDelegateForInvoke<IKVM.Runtime.MH<MethodHandle, object[], object>>(mh, ref cache)(mh, args);
222
static partial class MethodHandleUtil
224
internal static Type CreateDelegateType(MethodType type)
229
TypeWrapper[] args = new TypeWrapper[type.parameterCount()];
230
for (int i = 0; i < args.Length; i++)
232
args[i] = TypeWrapper.FromClass(type.parameterType(i));
235
TypeWrapper ret = TypeWrapper.FromClass(type.returnType());
237
return CreateDelegateType(args, ret);
242
private static Type[] GetParameterTypes(MethodBase mb)
244
ParameterInfo[] pi = mb.GetParameters();
245
Type[] args = new Type[pi.Length];
246
for (int i = 0; i < args.Length; i++)
248
args[i] = pi[i].ParameterType;
253
private static Type[] GetParameterTypes(Type thisType, MethodBase mb)
255
ParameterInfo[] pi = mb.GetParameters();
256
Type[] args = new Type[pi.Length + 1];
258
for (int i = 1; i < args.Length; i++)
260
args[i] = pi[i - 1].ParameterType;
265
internal static MethodType GetDelegateMethodType(Type type)
267
java.lang.Class[] types;
268
MethodInfo mi = GetDelegateInvokeMethod(type);
269
ParameterInfo[] pi = mi.GetParameters();
270
if (pi.Length > 0 && IsPackedArgsContainer(pi[pi.Length - 1].ParameterType))
272
System.Collections.Generic.List<java.lang.Class> list = new System.Collections.Generic.List<java.lang.Class>();
273
for (int i = 0; i < pi.Length - 1; i++)
275
list.Add(ClassLoaderWrapper.GetWrapperFromType(pi[i].ParameterType).ClassObject);
277
Type[] args = pi[pi.Length - 1].ParameterType.GetGenericArguments();
278
while (IsPackedArgsContainer(args[args.Length - 1]))
280
for (int i = 0; i < args.Length - 1; i++)
282
list.Add(ClassLoaderWrapper.GetWrapperFromType(args[i]).ClassObject);
284
args = args[args.Length - 1].GetGenericArguments();
286
for (int i = 0; i < args.Length; i++)
288
list.Add(ClassLoaderWrapper.GetWrapperFromType(args[i]).ClassObject);
290
types = list.ToArray();
294
types = new java.lang.Class[pi.Length];
295
for (int i = 0; i < types.Length; i++)
297
types[i] = ClassLoaderWrapper.GetWrapperFromType(pi[i].ParameterType).ClassObject;
300
return MethodType.methodType(ClassLoaderWrapper.GetWrapperFromType(mi.ReturnType).ClassObject, types);
303
internal sealed class DynamicMethodBuilder
305
private readonly MethodType type;
306
private readonly int firstArg;
307
private readonly Type delegateType;
308
private readonly object target;
309
private readonly object value;
310
private readonly Type container;
311
private readonly DynamicMethod dm;
312
private readonly CodeEmitter ilgen;
313
private readonly Type packedArgType;
314
private readonly int packedArgPos;
316
sealed class Container<T1, T2>
321
public Container(T1 target, T2 value)
323
this.target = target;
328
private DynamicMethodBuilder(string name, MethodType type, Type container, object target, object value, Type owner)
331
this.delegateType = CreateDelegateType(type);
332
this.target = target;
334
this.container = container;
335
MethodInfo mi = GetDelegateInvokeMethod(delegateType);
337
if (container != null)
340
paramTypes = GetParameterTypes(container, mi);
342
else if (target != null)
345
paramTypes = GetParameterTypes(target.GetType(), mi);
349
paramTypes = GetParameterTypes(mi);
351
if (!ReflectUtil.CanOwnDynamicMethod(owner))
353
owner = typeof(DynamicMethodBuilder);
355
this.dm = new DynamicMethod(name, mi.ReturnType, paramTypes, owner, true);
356
this.ilgen = CodeEmitter.Create(dm);
358
if (type.parameterCount() > MaxArity)
360
ParameterInfo[] pi = mi.GetParameters();
361
this.packedArgType = pi[pi.Length - 1].ParameterType;
362
this.packedArgPos = pi.Length - 1 + firstArg;
366
this.packedArgPos = Int32.MaxValue;
370
internal DynamicMethodBuilder(Type owner, string name, MethodType type)
371
: this(name, type, null, null, null, owner)
375
internal DynamicMethodBuilder(string name, MethodType type, MethodHandle target)
376
: this(name, type, null, target.vmtarget, null, null)
378
ilgen.Emit(OpCodes.Ldarg_0);
381
internal DynamicMethodBuilder(string name, MethodType type, MethodHandle target, object value)
382
: this(name, type, typeof(Container<,>).MakeGenericType(target.vmtarget.GetType(), value.GetType()), target.vmtarget, value, null)
384
ilgen.Emit(OpCodes.Ldarg_0);
385
ilgen.Emit(OpCodes.Ldfld, container.GetField("target"));
388
internal DynamicMethodBuilder(string name, MethodType type, Type valueType)
389
: this(name, type, typeof(Container<,>).MakeGenericType(typeof(object), valueType), null, null, null)
393
internal void Call(MethodInfo method)
395
ilgen.Emit(OpCodes.Call, method);
398
internal void Callvirt(MethodInfo method)
400
ilgen.Emit(OpCodes.Callvirt, method);
403
internal void Call(MethodWrapper mw)
408
internal void Callvirt(MethodWrapper mw)
410
mw.EmitCallvirt(ilgen);
413
internal void CallDelegate(Type delegateType)
415
EmitCallDelegateInvokeMethod(ilgen, delegateType);
418
internal void LoadFirstArgAddress()
420
ilgen.EmitLdarga(firstArg);
423
internal void Ldarg(int i)
426
if (i >= packedArgPos)
428
ilgen.EmitLdarga(packedArgPos);
429
int fieldPos = i - packedArgPos;
430
Type type = packedArgType;
431
while (fieldPos >= MaxArity || (fieldPos == MaxArity - 1 && IsPackedArgsContainer(type.GetField("t8").FieldType)))
433
FieldInfo field = type.GetField("t8");
434
type = field.FieldType;
435
ilgen.Emit(OpCodes.Ldflda, field);
436
fieldPos -= MaxArity - 1;
438
ilgen.Emit(OpCodes.Ldfld, type.GetField("t" + (1 + fieldPos)));
446
internal void LoadArrayElement(int index, TypeWrapper tw)
448
ilgen.EmitLdc_I4(index);
449
if (tw.IsNonPrimitiveValueType)
451
ilgen.Emit(OpCodes.Ldelema, tw.TypeAsArrayType);
452
ilgen.Emit(OpCodes.Ldobj, tw.TypeAsArrayType);
454
else if (tw == PrimitiveTypeWrapper.BYTE
455
|| tw == PrimitiveTypeWrapper.BOOLEAN)
457
ilgen.Emit(OpCodes.Ldelem_I1);
459
else if (tw == PrimitiveTypeWrapper.SHORT)
461
ilgen.Emit(OpCodes.Ldelem_I2);
463
else if (tw == PrimitiveTypeWrapper.CHAR)
465
ilgen.Emit(OpCodes.Ldelem_U2);
467
else if (tw == PrimitiveTypeWrapper.INT)
469
ilgen.Emit(OpCodes.Ldelem_I4);
471
else if (tw == PrimitiveTypeWrapper.LONG)
473
ilgen.Emit(OpCodes.Ldelem_I8);
475
else if (tw == PrimitiveTypeWrapper.FLOAT)
477
ilgen.Emit(OpCodes.Ldelem_R4);
479
else if (tw == PrimitiveTypeWrapper.DOUBLE)
481
ilgen.Emit(OpCodes.Ldelem_R8);
485
ilgen.Emit(OpCodes.Ldelem_Ref);
488
tw.EmitConvStackTypeToSignatureType(ilgen, null);
493
internal void Convert(java.lang.Class srcType, java.lang.Class dstType, int level)
495
EmitConvert(ilgen, srcType, dstType, level);
498
internal void CallTarget()
500
EmitCallDelegateInvokeMethod(ilgen, target.GetType());
503
internal void LoadValueAddress()
505
ilgen.Emit(OpCodes.Ldarg_0);
506
ilgen.Emit(OpCodes.Ldflda, container.GetField("value"));
509
internal void LoadValue()
511
ilgen.Emit(OpCodes.Ldarg_0);
512
ilgen.Emit(OpCodes.Ldfld, container.GetField("value"));
515
internal void CallValue()
517
EmitCallDelegateInvokeMethod(ilgen, value.GetType());
522
ilgen.Emit(OpCodes.Ret);
525
internal Delegate CreateDelegate()
528
return ValidateDelegate(firstArg == 0
529
? dm.CreateDelegate(delegateType)
530
: dm.CreateDelegate(delegateType, container == null ? target : Activator.CreateInstance(container, target, value)));
533
internal AdapterMethodHandle CreateAdapter()
535
return new AdapterMethodHandle(type, CreateDelegate());
540
[System.Security.SecuritySafeCritical]
542
private static Delegate ValidateDelegate(Delegate d)
547
System.Runtime.CompilerServices.RuntimeHelpers.PrepareDelegate(d);
551
JVM.CriticalFailure("Delegate failed to JIT", x);
557
private struct BoxUtil
559
private static readonly BoxUtil[] boxers = new BoxUtil[] {
560
BoxUtil.Create<java.lang.Boolean, bool>(java.lang.Boolean.TYPE, "boolean", "Boolean"),
561
BoxUtil.Create<java.lang.Byte, byte>(java.lang.Byte.TYPE, "byte", "Byte"),
562
BoxUtil.Create<java.lang.Character, char>(java.lang.Character.TYPE, "char", "Character"),
563
BoxUtil.Create<java.lang.Short, short>(java.lang.Short.TYPE, "short", "Short"),
564
BoxUtil.Create<java.lang.Integer, int>(java.lang.Integer.TYPE, "int", "Integer"),
565
BoxUtil.Create<java.lang.Long, int>(java.lang.Long.TYPE, "long", "Long"),
566
BoxUtil.Create<java.lang.Float, float>(java.lang.Float.TYPE, "float", "Float"),
567
BoxUtil.Create<java.lang.Double, double>(java.lang.Double.TYPE, "double", "Double"),
569
private readonly jlClass clazz;
570
private readonly jlClass type;
571
private readonly MethodInfo box;
572
private readonly MethodInfo unbox;
573
private readonly MethodInfo unboxObject;
575
private BoxUtil(jlClass clazz, jlClass type, MethodInfo box, MethodInfo unbox, MethodInfo unboxObject)
581
this.unboxObject = unboxObject;
584
private static BoxUtil Create<T, P>(jlClass type, string name, string longName)
586
return new BoxUtil(ikvm.@internal.ClassLiteral<T>.Value, type,
587
typeof(T).GetMethod("valueOf", new Type[] { typeof(P) }),
588
typeof(T).GetMethod(name + "Value", Type.EmptyTypes),
589
typeof(sun.invoke.util.ValueConversions).GetMethod("unbox" + longName, BindingFlags.Static | BindingFlags.NonPublic));
592
internal static void Box(CodeEmitter ilgen, jlClass srcClass, jlClass dstClass, int level)
594
for (int i = 0; i < boxers.Length; i++)
596
if (boxers[i].type == srcClass)
598
ilgen.Emit(OpCodes.Call, boxers[i].box);
599
EmitConvert(ilgen, boxers[i].clazz, dstClass, level);
603
throw new InvalidOperationException();
606
internal static void Unbox(CodeEmitter ilgen, jlClass srcClass, jlClass dstClass, int level)
608
for (int i = 0; i < boxers.Length; i++)
610
if (boxers[i].clazz == srcClass)
613
ilgen.Emit(OpCodes.Call, boxers[i].unbox);
614
EmitConvert(ilgen, boxers[i].type, dstClass, level);
618
for (int i = 0; i < boxers.Length; i++)
620
if (boxers[i].type == dstClass)
623
ilgen.EmitLdc_I4(level > 1 ? 1 : 0);
624
ilgen.Emit(OpCodes.Call, boxers[i].unboxObject);
628
throw new InvalidOperationException();
632
private static void EmitConvert(CodeEmitter ilgen, java.lang.Class srcClass, java.lang.Class dstClass, int level)
634
if (srcClass != dstClass)
636
TypeWrapper src = TypeWrapper.FromClass(srcClass);
637
TypeWrapper dst = TypeWrapper.FromClass(dstClass);
640
if (src.IsNonPrimitiveValueType)
644
if (dst == PrimitiveTypeWrapper.VOID)
646
ilgen.Emit(OpCodes.Pop);
648
else if (src.IsPrimitive)
652
if (src == PrimitiveTypeWrapper.BYTE)
654
ilgen.Emit(OpCodes.Conv_I1);
656
if (dst == PrimitiveTypeWrapper.FLOAT)
658
ilgen.Emit(OpCodes.Conv_R4);
660
else if (dst == PrimitiveTypeWrapper.DOUBLE)
662
ilgen.Emit(OpCodes.Conv_R8);
664
else if (dst == PrimitiveTypeWrapper.LONG)
666
if (src == PrimitiveTypeWrapper.FLOAT)
668
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.f2l);
670
else if (src == PrimitiveTypeWrapper.DOUBLE)
672
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.d2l);
676
ilgen.Emit(OpCodes.Conv_I8);
679
else if (dst == PrimitiveTypeWrapper.BOOLEAN)
681
if (src == PrimitiveTypeWrapper.FLOAT)
683
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.f2i);
685
else if (src == PrimitiveTypeWrapper.DOUBLE)
687
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.d2i);
691
ilgen.Emit(OpCodes.Conv_I4);
693
ilgen.Emit(OpCodes.Ldc_I4_1);
694
ilgen.Emit(OpCodes.And);
696
else if (src == PrimitiveTypeWrapper.LONG)
698
ilgen.Emit(OpCodes.Conv_I4);
700
else if (src == PrimitiveTypeWrapper.FLOAT)
702
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.f2i);
704
else if (src == PrimitiveTypeWrapper.DOUBLE)
706
ilgen.Emit(OpCodes.Call, ByteCodeHelperMethods.d2i);
711
BoxUtil.Box(ilgen, srcClass, dstClass, level);
714
else if (src.IsGhost)
716
src.EmitConvSignatureTypeToStackType(ilgen);
717
EmitConvert(ilgen, ikvm.@internal.ClassLiteral<java.lang.Object>.Value, dstClass, level);
719
else if (srcClass == ikvm.@internal.ClassLiteral<sun.invoke.empty.Empty>.Value)
721
ilgen.Emit(OpCodes.Pop);
722
ilgen.Emit(OpCodes.Ldloc, ilgen.DeclareLocal(dst.TypeAsSignatureType));
724
else if (dst.IsPrimitive)
726
BoxUtil.Unbox(ilgen, srcClass, dstClass, level);
728
else if (dst.IsGhost)
730
dst.EmitConvStackTypeToSignatureType(ilgen, null);
732
else if (dst.IsNonPrimitiveValueType)
734
dst.EmitUnbox(ilgen);
738
dst.EmitCheckcast(null, ilgen);
743
internal static void Dump(MethodHandle mh)
745
Console.WriteLine("----");
746
Dump((Delegate)mh.vmtarget, 0);
749
private static void WriteNest(int nest)
751
for (int i = 0; i < nest; i++)
757
private static void Dump(Delegate d, int nest)
764
Console.Write(d.Method.Name + "(");
766
foreach (ParameterInfo pi in d.Method.GetParameters())
768
Console.WriteLine(sep);
770
Console.Write(" {0}", TypeToString(pi.ParameterType));
773
Console.WriteLine(")");
775
Console.WriteLine(" : {0}", TypeToString(d.Method.ReturnType));
776
if (d.Target is Delegate)
778
Dump((Delegate)d.Target, nest == 0 ? 1 : nest);
780
else if (d.Target != null)
782
FieldInfo field = d.Target.GetType().GetField("value");
783
if (field != null && field.GetValue(d.Target) is Delegate)
786
Console.WriteLine("Collector:");
787
Dump((Delegate)field.GetValue(d.Target), nest + 2);
789
field = d.Target.GetType().GetField("target");
790
if (field != null && field.GetValue(d.Target) != null)
792
Dump((Delegate)field.GetValue(d.Target), nest == 0 ? 1 : nest);
797
private static string TypeToString(Type type)
799
if (type.IsGenericType
800
&& type.Namespace == "IKVM.Runtime"
801
&& (type.Name.StartsWith("MH`") || type.Name.StartsWith("MHV`")))
803
return type.Name.Substring(0, type.Name.IndexOf('`')) + "<" + TypesToString(type.GetGenericArguments()) + ">";
805
else if (type.DeclaringType == typeof(DynamicMethodBuilder))
807
return "C<" + TypesToString(type.GetGenericArguments()) + ">";
809
else if (ReflectUtil.IsVector(type))
811
return TypeToString(type.GetElementType()) + "[]";
813
else if (type == typeof(object))
817
else if (type == typeof(string))
821
else if (type.IsPrimitive)
823
return type.Name.ToLowerInvariant();
827
return type.ToString();
831
private static string TypesToString(Type[] types)
833
System.Text.StringBuilder sb = new System.Text.StringBuilder();
834
foreach (Type type in types)
840
sb.Append(TypeToString(type));
842
return sb.ToString();
847
static class Java_java_lang_invoke_AdapterMethodHandle
849
public static MethodHandle makePairwiseConvert(MethodType newType, MethodHandle target, int level)
854
MethodType oldType = target.type();
855
MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder("AdapterMethodHandle.pairwiseConvert", newType, target);
856
for (int i = 0, count = newType.parameterCount(); i < count; i++)
859
dm.Convert(newType.parameterType(i), oldType.parameterType(i), level);
862
dm.Convert(oldType.returnType(), newType.returnType(), level);
864
return dm.CreateAdapter();
868
public static MethodHandle makeRetype(MethodType newType, MethodHandle target, bool raw)
873
MethodType oldType = target.type();
874
if (oldType == newType)
878
if (!AdapterMethodHandle.canRetype(newType, oldType, raw))
882
// TODO does raw translate into a level?
883
return makePairwiseConvert(newType, target, 0);
887
public static MethodHandle makeSpreadArguments(MethodType newType, MethodHandle target, java.lang.Class spreadArgType, int spreadArgPos, int spreadArgCount)
892
TypeWrapper twComponent = TypeWrapper.FromClass(spreadArgType).ElementTypeWrapper;
893
MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder("AdapterMethodHandle.spreadArguments", newType, target);
894
for (int i = 0, count = newType.parameterCount(); i < count; i++)
896
if (i == spreadArgPos)
898
for (int j = 0; j < spreadArgCount; j++)
901
dm.LoadArrayElement(j, twComponent);
902
dm.Convert(twComponent.ClassObject, target.type().parameterType(i + j), 0);
912
return dm.CreateAdapter();
916
public static MethodHandle makeCollectArguments(MethodHandle target, MethodHandle collector, int collectArgPos, bool retainOriginalArgs)
921
MethodType targetType = target.type();
922
MethodType collectorType = collector.type();
923
bool isfilter = collectorType.returnType() == java.lang.Void.TYPE;
924
MethodType newType = targetType.dropParameterTypes(collectArgPos, collectArgPos + (isfilter ? 0 : 1));
925
if (!retainOriginalArgs)
927
newType = newType.insertParameterTypes(collectArgPos, collectorType.parameterList());
929
MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder("AdapterMethodHandle.collectArguments", newType, target, collector.vmtarget);
930
for (int i = 0, count = newType.parameterCount(); i < count || i == collectArgPos; i++)
932
if (i == collectArgPos)
935
for (int j = 0; j < collectorType.parameterCount(); j++)
943
if (!retainOriginalArgs)
945
i += collectorType.parameterCount();
955
return dm.CreateAdapter();
960
static class Java_java_lang_invoke_MethodHandleImpl
962
public static MethodHandle permuteArguments(MethodHandle target, MethodType newType, MethodType oldType, int[] permutationOrNull)
967
// LAME why does OpenJDK name the parameter permutationOrNull while it is not allowed to be null?
968
if (permutationOrNull.Length != oldType.parameterCount())
970
throw new java.lang.IllegalArgumentException("wrong number of arguments in permutation");
972
MethodHandleUtil.DynamicMethodBuilder dm = new MethodHandleUtil.DynamicMethodBuilder("MethodHandleImpl.permuteArguments", newType, target);
973
for (int i = 0, argCount = newType.parameterCount(); i < permutationOrNull.Length; i++)
975
// make sure to only read each array element once, to avoid having to make a defensive copy of the array
976
int perm = permutationOrNull[i];
977
if (perm < 0 || perm >= argCount)
979
throw new java.lang.IllegalArgumentException("permutation argument out of range");
982
dm.Convert(oldType.parameterType(i), newType.parameterType(perm), 0);
985
dm.Convert(oldType.returnType(), newType.returnType(), 0);
987
return dm.CreateAdapter();
992
static class Java_java_lang_invoke_MethodHandleNatives
994
public static void init(MemberName self, object r)
997
if (r is java.lang.reflect.Method || r is java.lang.reflect.Constructor)
999
MethodWrapper mw = MethodWrapper.FromMethodOrConstructor(r);
1000
int index = Array.IndexOf(mw.DeclaringType.GetMethods(), mw);
1003
// TODO self.setVMIndex(index);
1004
typeof(MemberName).GetField("vmindex", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(self, index);
1005
typeof(MemberName).GetField("vmtarget", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(self, mw.DeclaringType);
1006
int flags = (int)mw.Modifiers;
1007
if (r is java.lang.reflect.Method)
1009
flags |= MemberName.IS_METHOD;
1013
flags |= MemberName.IS_CONSTRUCTOR;
1015
typeof(MemberName).GetField("flags", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(self, flags);
1018
else if (r is java.lang.reflect.Field)
1020
FieldWrapper fw = FieldWrapper.FromField(r);
1021
int index = Array.IndexOf(fw.DeclaringType.GetFields(), fw);
1024
// TODO self.setVMIndex(index);
1025
typeof(MemberName).GetField("vmindex", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(self, index);
1026
typeof(MemberName).GetField("flags", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(self, (int)fw.Modifiers | MemberName.IS_FIELD);
1031
throw new InvalidOperationException();
1036
public static void expand(MemberName self)
1038
throw new NotImplementedException();
1041
public static void resolve(MemberName self, jlClass caller)
1044
if (self.isMethod() || self.isConstructor())
1046
TypeWrapper tw = TypeWrapper.FromClass(self.getDeclaringClass());
1047
if (tw == CoreClasses.java.lang.invoke.MethodHandle.Wrapper
1048
&& (self.getName() == "invoke" || self.getName() == "invokeExact"))
1050
typeof(MemberName).GetField("vmindex", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(self, Int32.MaxValue);
1053
MethodWrapper mw = tw.GetMethodWrapper(self.getName(), self.getSignature().Replace('/', '.'), true);
1056
tw = mw.DeclaringType;
1057
int index = Array.IndexOf(tw.GetMethods(), mw);
1060
// TODO self.setVMIndex(index);
1061
typeof(MemberName).GetField("vmindex", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(self, index);
1062
typeof(MemberName).GetField("vmtarget", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(self, tw);
1063
int flags = (int)mw.Modifiers;
1064
if (self.isMethod())
1066
flags |= MemberName.IS_METHOD;
1070
flags |= MemberName.IS_CONSTRUCTOR;
1072
typeof(MemberName).GetField("flags", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(self, flags);
1076
else if (self.isField())
1078
TypeWrapper tw = TypeWrapper.FromClass(self.getDeclaringClass());
1079
// TODO should we look in base classes?
1080
FieldWrapper fw = tw.GetFieldWrapper(self.getName(), self.getSignature().Replace('/', '.'));
1083
int index = Array.IndexOf(fw.DeclaringType.GetFields(), fw);
1086
// TODO self.setVMIndex(index);
1087
typeof(MemberName).GetField("vmindex", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(self, index);
1088
typeof(MemberName).GetField("flags", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(self, (int)fw.Modifiers | MemberName.IS_FIELD);
1094
throw new InvalidOperationException();
1099
public static int getMembers(jlClass defc, string matchName, string matchSig, int matchFlags, jlClass caller, int skip, object[] results)