static JavaMethodHandle GetLambdaMetafactory() { if (_LambdaMetafactory == null) { var lookupArg = new JavaFieldRef("", new JavaType(0, 0, "java.lang.invoke.MethodHandles$Lookup")); var stringArg = new JavaFieldRef("", JavaType.StringType); var methodTypeArg = new JavaFieldRef("", new JavaType(0, 0, "java.lang.invoke.MethodType")); var methodHandleArg = new JavaFieldRef("", new JavaType(0, 0, "java.lang.invoke.MethodHandle")); var parameters = new List <JavaFieldRef>(); parameters.Add(lookupArg); parameters.Add(stringArg); parameters.Add(methodTypeArg); parameters.Add(methodTypeArg); parameters.Add(methodHandleArg); parameters.Add(methodTypeArg); var factory = new JavaMethodHandle(); factory.Kind = JavaMethodHandle.HandleKind.InvokeStatic; factory.Class = new JavaType(0, 0, "java.lang.invoke.LambdaMetafactory"); factory.Method = new JavaMethodRef("metafactory", new JavaType(0, 0, "java.lang.invoke.CallSite"), parameters); _LambdaMetafactory = factory; } return(_LambdaMetafactory); }
public int FindOrCreateItem(JavaMethodHandle mh, object[] args) { if (methods == null) { methods = new Item[1]; methods[0] = new Item { mh = mh, args = args }; return(0); } int n = methods.Length; if (mh == methods[0].mh) { // we expect that new entry will always point to the same method, // the lambda metafactory, and we scan old entries to see if we // have a duplicate. if the new entry is for a different method, // we skip the scan and always add a new entry. for (int i = 0; i < n; i++) { if (CompareBootstrapArgs(methods[i].args, args)) { return(i); } } } var newMethods = new Item[n + 1]; Array.Copy(methods, 0, newMethods, 0, n); newMethods[n] = new Item { mh = mh, args = args }; methods = newMethods; return(n);
// // create a CallSite that returns an object that implements the // functional interface 'declType', containing a single method with the // signature 'declMethod'. this interface method is a proxy that calls // the method 'implMethod' from class 'implClass'. // // 'captureParameters' may optionally specify any number of parameters, // which would be on the stack when 'invokedynamic' is executed. these // parameters are captured by the callsite, and injected as the first // several parameters of 'implMethod' when the proxy is called. the // parameter list for 'implMethod' should not include these parameters; // they are inserted by this method. // // callKind should be InvokeStatic, InvokeVirtual, or InvokeInterface, // and specifies the type of 'implMethod'. if not InvokeStatic, it is // as if the first parameter in 'captureParameters' is 'declType'. // public JavaCallSite(JavaType declType, JavaMethodRef declMethod, JavaType implClass, JavaMethodRef implMethod, List <JavaFieldRef> captureParameters, JavaMethodHandle.HandleKind callKind) { BootstrapMethod = GetLambdaMetafactory(); BootstrapMethodIndex = 0xFFFF; var invokedMethod = new JavaMethodRef(); invokedMethod.Name = declMethod.Name; invokedMethod.ReturnType = declType; invokedMethod.Parameters = new List <JavaFieldRef>(); if (callKind != JavaMethodHandle.HandleKind.InvokeStatic) { invokedMethod.Parameters.Add(new JavaFieldRef("", implClass)); } InvokedMethod = invokedMethod; var methodHandle = new JavaMethodHandle(); methodHandle.Class = implClass; methodHandle.Method = implMethod; methodHandle.Kind = callKind; methodHandle.IsInterfaceMethod = (callKind == JavaMethodHandle.HandleKind.InvokeInterface); JavaMethodType castMethod = new JavaMethodType(declMethod.ReturnType, null); castMethod.Parameters = new List <JavaFieldRef>(); for (int i = 0; i < implMethod.Parameters.Count; i++) { JavaType castParameterType = declMethod.Parameters[i].Type; if (castParameterType.Equals(JavaType.ObjectType)) { var implParameterType = implMethod.Parameters[i].Type; castParameterType = implParameterType.Wrapper ?? implParameterType; } castMethod.Parameters.Add(new JavaFieldRef("", castParameterType)); } BootstrapArgs = new object[3]; // arg#0 (aka 'samMethodType') specifies the signature, minus the name, // of the method in the functional interface. note that the name was // already inserted into 'InvokedMethod', above BootstrapArgs[0] = new JavaMethodType(declMethod.ReturnType, declMethod.Parameters); // arg#1 (aka 'implMethod') specifies the name and signature of the // method that provides the actual implementation for the interface BootstrapArgs[1] = methodHandle; // arg#2 (aka 'instantiatedMethodType') specifies optional conversions // on the parameters passed to the 'invokeinterface' instructions. // in particular, boxing of primitives to standard wrapper types, or // casting generic java.lang.Object to a more restricted type. BootstrapArgs[2] = new JavaMethodType(castMethod.ReturnType, castMethod.Parameters); if (captureParameters != null) { invokedMethod.Parameters.AddRange(captureParameters); var newParameters = new List <JavaFieldRef>(captureParameters); newParameters.AddRange(implMethod.Parameters); methodHandle.Method = new JavaMethodRef( implMethod.Name, implMethod.ReturnType, newParameters); } }
public ushort ConstMethodHandle(JavaMethodHandle vMethodHandle) { return((ushort)constants.Put(vMethodHandle.ToConstant(this), Where)); }