Beispiel #1
0
        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);
Beispiel #3
0
        //
        // 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);
            }
        }
Beispiel #4
0
 public ushort ConstMethodHandle(JavaMethodHandle vMethodHandle)
 {
     return((ushort)constants.Put(vMethodHandle.ToConstant(this), Where));
 }