Example #1
0
        //
        // create default parameterless constructor.  (it will be called at the
        // top of any method which allocates a value type local.)  and note that
        // if this is a generic value type, this new constructor will be further
        // modified in GenericUtil.MakeGenericClass.FixConstructorsInFrom
        //

        static void CreateDefaultConstructor(JavaClass valueClass, CilType fromType,
                                             int numCastableInterfaces, bool initFields)
        {
            foreach (var oldMethod in valueClass.Methods)
            {
                if (oldMethod.Name == "<init>")
                {
                    return;
                }
            }

            var code = CilMethod.CreateConstructor(valueClass, fromType.GenericParametersCount, true);

            if (fromType.HasGenericParameters)
            {
                code.StackMap = new JavaStackMap();
                var genericMark = CilMain.GenericStack.Mark();
                CilMain.GenericStack.EnterMethod(fromType, code.Method, true);

                // initialize the generic type field
                GenericUtil.InitializeTypeField(fromType, code);

                CilMain.GenericStack.Release(genericMark);
                code.MaxStack = code.StackMap.GetMaxStackSize(CilMain.Where);
            }

            // init the array of generic interfaces
            InterfaceBuilder.InitInterfaceArrayField(
                fromType, numCastableInterfaces, code, 0);

            if (initFields)
            {
                var oldLabel = code.SetLabel(0xFFFF);

                InitializeInstanceFields(valueClass, fromType, null, code);

                code.SetLabel(oldLabel);
            }

            code.NewInstruction(0x19 /* aload */, null, (int)0);
            code.NewInstruction(0xB7 /* invokespecial */, new JavaType(0, 0, valueClass.Super),
                                new JavaMethodRef("<init>", JavaType.VoidType));

            code.MaxStack = code.StackMap.GetMaxStackSize(CilMain.Where);
            if (code.MaxStack < 1)
            {
                code.MaxStack = 1;
            }

            code.NewInstruction(JavaType.VoidType.ReturnOpcode, null, null);
        }
Example #2
0
        void InsertMethodInitCode()
        {
            if (method.IsStatic)
            {
                if ((!method.IsConstructor) && method.DeclType.HasGenericParameters)
                {
                    // in a static method in a generic class, if the class has
                    // a static initializer, then we want to start with a call to
                    // GetType(), to force initialization of the static data class

                    foreach (var m in defMethod.DeclaringType.Methods)
                    {
                        if (m.IsConstructor && m.IsStatic)
                        {
                            GenericUtil.LoadMaybeGeneric(method.DeclType, code);
                            code.NewInstruction(0x57 /* pop */, null, null);
                            code.StackMap.PopStack(CilMain.Where);
                            break;
                        }
                    }
                }
            }
            else if (method.IsConstructor)
            {
                if (method.DeclType.HasGenericParameters)
                {
                    // in a constructor of a generic class, we want to start
                    // with a call to GetType() and store the result in the
                    // $type field
                    GenericUtil.InitializeTypeField(method.DeclType, code);
                }

                // init the array of generic interfaces
                InterfaceBuilder.InitInterfaceArrayField(
                    method.DeclType, numCastableInterfaces, code, 0);

                // in any constructor, we want to allocate boxed instance fields
                ValueUtil.InitializeInstanceFields(newMethod.Class, method.DeclType,
                                                   defMethodBody.Instructions, code);
            }
        }
Example #3
0
        public static JavaClass FixClass(JavaClass fromClass, CilType fromType)
        {
            JavaType  interfaceType  = InterfaceType(fromType);
            JavaClass interfaceClass = null;

            var fromMethods = fromClass.Methods;

            for (int i = fromMethods.Count; i-- > 0;)
            {
                var nm = fromMethods[i].Name;
                if (nm == "BeginInvoke" || nm == "EndInvoke")
                {
                    fromClass.Methods.RemoveAt(i);
                }
            }

            foreach (var method in fromMethods)
            {
                if ((method.Flags & JavaAccessFlags.ACC_STATIC) == 0 && method.Code == null)
                {
                    if (method.Name == "<init>")
                    {
                        GenerateConstructor(method, fromType);
                    }
                    else if (method.Name == "Invoke")
                    {
                        if (interfaceClass != null)
                        {
                            break;
                        }

                        interfaceClass = MakeInterface(fromClass, method, interfaceType.ClassName);
                        GenerateInvoke(method, fromType, interfaceType);
                    }

                    /*else if (method.Name == "BeginInvoke")
                     * {
                     *  if (interfaceClass == null)
                     *      break;
                     *
                     *  GenerateBeginInvoke();
                     *  continue;
                     * }
                     * else if (method.Name == "EndInvoke")
                     * {
                     *  GenerateEndInvoke();
                     *  continue;
                     * }*/
                    else
                    {
                        break;
                    }

                    method.Flags &= ~JavaAccessFlags.ACC_ABSTRACT;
                }
            }

            if (interfaceClass == null)
            {
                throw CilMain.Where.Exception("invalid delegate class");
            }

            return(interfaceClass);

            //
            //
            //

            JavaClass MakeInterface(JavaClass fromClass, JavaMethod fromMethod, string newName)
            {
                var newClass = CilMain.CreateInnerClass(fromClass, newName,
                                                        JavaAccessFlags.ACC_PUBLIC
                                                        | JavaAccessFlags.ACC_ABSTRACT
                                                        | JavaAccessFlags.ACC_INTERFACE);

                var newMethod = new JavaMethod(newClass, fromMethod);

                newMethod.Flags = JavaAccessFlags.ACC_PUBLIC
                                  | JavaAccessFlags.ACC_ABSTRACT;
                if (IsPrimitive(newMethod.ReturnType))
                {
                    // primitive return value is translated to java.lang.Object,
                    // because the delegate target may return a generic type that
                    // is specialized for the primitive type in the delegate.
                    // see also GenerateInvoke and LoadFunction
                    newMethod.ReturnType = JavaType.ObjectType;
                }
                newClass.Methods.Add(newMethod);

                return(newClass);
            }

            //
            //
            //

            void GenerateConstructor(JavaMethod method, CilType dlgType)
            {
                var code = method.Code = new JavaCode();

                code.Method       = method;
                code.Instructions = new List <Instruction>();

                if (dlgType.HasGenericParameters)
                {
                    code.StackMap = new JavaStackMap();
                    var genericMark = CilMain.GenericStack.Mark();
                    CilMain.GenericStack.EnterMethod(dlgType, method, true);

                    // initialize the generic type field
                    GenericUtil.InitializeTypeField(dlgType, code);

                    CilMain.GenericStack.Release(genericMark);
                    code.MaxStack = code.StackMap.GetMaxStackSize(CilMain.Where);
                }

                code.NewInstruction(0x19 /* aload_0 */, null, (int)0);
                code.NewInstruction(0x19 /* aload_1 */, null, (int)1);
                code.NewInstruction(0x19 /* aload_2 */, null, (int)2);

                code.NewInstruction(0xB7 /* invokespecial */,
                                    new JavaType(0, 0, method.Class.Super),
                                    new JavaMethodRef("<init>", JavaType.VoidType,
                                                      JavaType.ObjectType, JavaType.ObjectType));

                code.NewInstruction(0xB1 /* return (void) */, null, null);

                if (code.MaxStack < 3)
                {
                    code.MaxStack = 3;
                }
                code.MaxLocals = 3 + dlgType.GenericParametersCount;
            }

            //
            //
            //

            void GenerateInvoke(JavaMethod method, CilType dlgType, JavaType ifcType)
            {
                var delegateType = new JavaType(0, 0, "system.Delegate");

                var code = method.Code = new JavaCode();

                code.Method       = method;
                code.Instructions = new List <Instruction>();
                code.StackMap     = new JavaStackMap();

                code.StackMap.SetLocal(0, dlgType);
                int index = 1;

                for (int i = 0; i < method.Parameters.Count; i++)
                {
                    var paramType = (CilType)method.Parameters[i].Type;
                    code.StackMap.SetLocal(index, paramType);
                    index += paramType.Category;
                }
                code.StackMap.SaveFrame((ushort)0, false, CilMain.Where);

                //
                // step 1, call the target method through the interface reference
                // stored in the 'invokable' field of the system.Delegate class
                //

                code.NewInstruction(0x19 /* aload_0 */, null, (int)0);
                code.NewInstruction(0xB4 /* getfield */, delegateType,
                                    new JavaFieldRef("invokable", JavaType.ObjectType));

                code.NewInstruction(0xC0 /* checkcast */, ifcType, null);
                code.StackMap.PushStack(JavaType.ObjectType);

                // push method parameters 'invokeinterface'

                index = 1;
                for (int i = 0; i < method.Parameters.Count; i++)
                {
                    var paramType = (CilType)method.Parameters[i].Type;
                    code.NewInstruction(paramType.LoadOpcode, null, index);
                    code.StackMap.PushStack(paramType);

                    if (paramType.IsGenericParameter && (!paramType.IsByReference))
                    {
                        // invoke the helper method which identifies our boxed
                        // primitives and re-boxes them as java boxed values.
                        // see also: GenericType::DelegateParameterin baselib.
                        GenericUtil.LoadMaybeGeneric(
                            paramType.GetMethodGenericParameter(), code);
                        code.NewInstruction(0xB8 /* invokestatic */,
                                            SystemDelegateUtilType, DelegateParameterMethod);
                        code.StackMap.PopStack(CilMain.Where);
                    }
                    index += paramType.Category;
                }

                var returnType = (CilType)method.ReturnType;

                if (IsPrimitive(returnType))
                {
                    // primitive return value is translated to java.lang.Object,
                    // because the delegate target may return a generic type that
                    // is specialized for the primitive type in the delegate.
                    // see also GenerateInvoke and LoadFunction
                    var adjustedMethod = new JavaMethodRef(
                        method.Name, JavaType.ObjectType, method.Parameters);
                    code.NewInstruction(0xB9 /* invokeinterface */, ifcType, adjustedMethod);
                }
                else
                {
                    code.NewInstruction(0xB9 /* invokeinterface */, ifcType, method);
                }

                code.StackMap.ClearStack();
                code.StackMap.PushStack(returnType);

                // check if this delegate has a 'following' delegate,
                // attached via system.MulticastDelegate.CombineImpl

                code.NewInstruction(0x19 /* aload_0 */, null, (int)0);
                code.NewInstruction(0xB4 /* getfield */, delegateType,
                                    new JavaFieldRef("following", delegateType));
                code.NewInstruction(0xC7 /* ifnonnull */, null, (ushort)1);

                if (returnType.IsGenericParameter && (!returnType.IsByReference))
                {
                    GenericUtil.LoadMaybeGeneric(
                        returnType.GetMethodGenericParameter(), code);
                    code.NewInstruction(0xB8 /* invokestatic */,
                                        SystemDelegateUtilType, DelegateReturnValueMethod);
                    code.StackMap.PopStack(CilMain.Where);
                }
                else if (IsPrimitive(returnType))
                {
                    // if the delegate returns a primitive type, we need to unbox
                    // the object returned by the method we just called.  it will be
                    // a java boxed primitive (e.g. java.lang.Integer) if the called
                    // method actually returns a primitive, due to the boxing done
                    // by the invokedynamic mechanism.  if the called method returns
                    // a generic type, it will be our boxed type, e.g. system.Int32.
                    //
                    // see also DelegateReturnValueX helper methods in baselib,
                    // and MakeInterface and LoadFunction in this file.
                    var helperMethod = new JavaMethodRef(
                        DelegateReturnValueMethod.Name + returnType.ToDescriptor(),
                        returnType, JavaType.ObjectType);
                    code.NewInstruction(0xB8 /* invokestatic */,
                                        SystemDelegateUtilType, helperMethod);
                }

                code.NewInstruction(returnType.ReturnOpcode, null, index);
                code.StackMap.PopStack(CilMain.Where);

                //
                // step 2
                //
                // if this delegate has a 'following' delegate, then we need to
                // call it, but first get rid of the return value on the stack
                //

                byte popOpcode;

                if (returnType.Equals(JavaType.VoidType))
                {
                    popOpcode = 0x00; // nop
                }
                else // select 0x57 pop, or 0x58 pop2
                {
                    var adjustedReturnType =
                        IsPrimitive(returnType) ? JavaType.ObjectType : returnType;
                    code.StackMap.PushStack(adjustedReturnType);
                    popOpcode = (byte)(0x56 + returnType.Category);
                }
                code.NewInstruction(popOpcode, null, null, (ushort)1);
                code.StackMap.SaveFrame((ushort)1, true, CilMain.Where);

                // now call the Invoke method on the 'following' delegate

                code.NewInstruction(0x19 /* aload_0 */, null, (int)0);
                code.NewInstruction(0xB4 /* getfield */, delegateType,
                                    new JavaFieldRef("following", delegateType));
                code.NewInstruction(0xC0 /* checkcast */, dlgType, null);

                // push all method parameters for 'invokevirtual'

                index = 1;
                for (int i = 0; i < method.Parameters.Count; i++)
                {
                    var paramType = (CilType)method.Parameters[i].Type;
                    code.NewInstruction(paramType.LoadOpcode, null, index);

                    if (paramType.IsGenericParameter && (!paramType.IsByReference))
                    {
                        // invoke the helper method which identifies our boxed
                        // primitives and re-boxes them as java boxed values.
                        // see also: GenericType::DelegateParameterin baselib.
                        GenericUtil.LoadMaybeGeneric(
                            paramType.GetMethodGenericParameter(), code);
                        code.NewInstruction(0xB8 /* invokestatic */,
                                            SystemDelegateUtilType, DelegateParameterMethod);
                    }
                    index += paramType.Category;
                }

                code.NewInstruction(0xB6 /* invokevirtual */, dlgType, method);

                code.NewInstruction(returnType.ReturnOpcode, null, index);
                code.StackMap.ClearStack();

                code.MaxStack  = code.StackMap.GetMaxStackSize(CilMain.Where);
                code.MaxLocals = index;
            }

            //
            //
            //

            /*void GenerateBeginInvoke()
             * {
             * }*/

            //
            //
            //

            /*void GenerateEndInvoke()
             * {
             * }*/
        }
Example #4
0
        public static JavaClass FixClass(JavaClass fromClass, CilType fromType)
        {
            JavaType  interfaceType  = InterfaceType(fromType);
            JavaClass interfaceClass = null;

            foreach (var method in fromClass.Methods)
            {
                if ((method.Flags & JavaAccessFlags.ACC_STATIC) == 0 && method.Code == null)
                {
                    if (method.Name == "<init>")
                    {
                        GenerateConstructor(method, fromType);
                    }
                    else if (method.Name == "Invoke")
                    {
                        if (interfaceClass != null)
                        {
                            break;
                        }

                        interfaceClass = MakeInterface(fromClass, method, interfaceType.ClassName);
                        GenerateInvoke(method, fromType, interfaceType);
                    }
                    else if (method.Name == "BeginInvoke")
                    {
                        if (interfaceClass == null)
                        {
                            break;
                        }

                        GenerateBeginInvoke();
                        continue;
                    }
                    else if (method.Name == "EndInvoke")
                    {
                        GenerateEndInvoke();
                        continue;
                    }
                    else
                    {
                        break;
                    }

                    method.Flags &= ~JavaAccessFlags.ACC_ABSTRACT;
                }
            }

            if (interfaceClass == null)
            {
                throw CilMain.Where.Exception("invalid delegate class");
            }

            return(interfaceClass);

            //
            //
            //

            JavaClass MakeInterface(JavaClass fromClass, JavaMethod fromMethod, string newName)
            {
                var newClass = CilMain.CreateInnerClass(fromClass, newName,
                                                        JavaAccessFlags.ACC_PUBLIC
                                                        | JavaAccessFlags.ACC_ABSTRACT
                                                        | JavaAccessFlags.ACC_INTERFACE);

                var newMethod = new JavaMethod(newClass, fromMethod);

                newMethod.Flags = JavaAccessFlags.ACC_PUBLIC
                                  | JavaAccessFlags.ACC_ABSTRACT;
                if (IsPrimitive(newMethod.ReturnType))
                {
                    // primitive return value is translated to java.lang.Object,
                    // because the delegate target may return a generic type that
                    // is specialized for the primitive type in the delegate.
                    // see also GenerateInvoke and LoadFunction
                    newMethod.ReturnType = JavaType.ObjectType;
                }
                newClass.Methods.Add(newMethod);

                return(newClass);
            }

            //
            //
            //

            void GenerateConstructor(JavaMethod method, CilType dlgType)
            {
                var code = method.Code = new JavaCode();

                code.Method       = method;
                code.Instructions = new List <Instruction>();

                if (dlgType.HasGenericParameters)
                {
                    code.StackMap = new JavaStackMap();
                    var genericMark = CilMain.GenericStack.Mark();
                    CilMain.GenericStack.EnterMethod(dlgType, method, true);

                    // initialize the generic type field
                    GenericUtil.InitializeTypeField(dlgType, code);

                    CilMain.GenericStack.Release(genericMark);
                    code.MaxStack = code.StackMap.GetMaxStackSize(CilMain.Where);
                }

                code.NewInstruction(0x19 /* aload_0 */, null, (int)0);
                code.NewInstruction(0x19 /* aload_1 */, null, (int)1);
                code.NewInstruction(0x19 /* aload_2 */, null, (int)2);

                code.NewInstruction(0xB7 /* invokespecial */,
                                    new JavaType(0, 0, method.Class.Super),
                                    new JavaMethodRef("<init>", JavaType.VoidType,
                                                      JavaType.ObjectType, JavaType.ObjectType));

                code.NewInstruction(0xB1 /* return (void) */, null, null);

                if (code.MaxStack < 3)
                {
                    code.MaxStack = 3;
                }
                code.MaxLocals = 3 + dlgType.GenericParametersCount;
            }

            //
            //
            //

            void GenerateInvoke(JavaMethod method, CilType dlgType, JavaType ifcType)
            {
                var code = method.Code = new JavaCode();

                code.Method       = method;
                code.Instructions = new List <Instruction>();
                code.StackMap     = new JavaStackMap();

                code.NewInstruction(0x19 /* aload_0 */, null, (int)0);
                code.NewInstruction(0xB4 /* getfield */,
                                    new JavaType(0, 0, "system.Delegate"),
                                    new JavaFieldRef("invokable", JavaType.ObjectType));

                code.NewInstruction(0xC0 /* checkcast */, ifcType, null);
                code.StackMap.PushStack(JavaType.ObjectType);

                int index = 1;

                for (int i = 0; i < method.Parameters.Count; i++)
                {
                    var paramType = (CilType)method.Parameters[i].Type;
                    code.NewInstruction(paramType.LoadOpcode, null, index);
                    code.StackMap.PushStack(paramType);

                    if (paramType.IsGenericParameter && (!paramType.IsByReference))
                    {
                        // invoke the helper method which identifies our boxed
                        // primitives and re-boxes them as java boxed values.
                        // see also: GenericType::DelegateParameterin baselib.
                        GenericUtil.LoadMaybeGeneric(
                            paramType.GetMethodGenericParameter(), code);
                        code.NewInstruction(0xB8 /* invokestatic */,
                                            SystemDelegateUtilType, DelegateParameterMethod);
                        code.StackMap.PopStack(CilMain.Where);
                    }
                    index += paramType.Category;
                }

                var returnType = (CilType)method.ReturnType;

                if (IsPrimitive(returnType))
                {
                    // primitive return value is translated to java.lang.Object,
                    // because the delegate target may return a generic type that
                    // is specialized for the primitive type in the delegate.
                    // see also GenerateInvoke and LoadFunction
                    var adjustedMethod = new JavaMethodRef(
                        method.Name, JavaType.ObjectType, method.Parameters);
                    code.NewInstruction(0xB9 /* invokeinterface */, ifcType, adjustedMethod);
                }
                else
                {
                    code.NewInstruction(0xB9 /* invokeinterface */, ifcType, method);
                }

                code.StackMap.ClearStack();
                code.StackMap.PushStack(returnType);

                if (returnType.IsGenericParameter && (!returnType.IsByReference))
                {
                    GenericUtil.LoadMaybeGeneric(
                        returnType.GetMethodGenericParameter(), code);
                    code.NewInstruction(0xB8 /* invokestatic */,
                                        SystemDelegateUtilType, DelegateReturnValueMethod);
                    code.StackMap.PopStack(CilMain.Where);
                }
                else if (IsPrimitive(returnType))
                {
                    // if the delegate returns a primitive type, we need to unbox
                    // the object returned by the method we just called.  it will be
                    // a java boxed primitive (e.g. java.lang.Integer) if the called
                    // method actually returns a primitive, due to the boxing done
                    // by the invokedynamic mechanism.  if the called method returns
                    // a generic type, it will be our boxed type, e.g. system.Int32.
                    //
                    // see also DelegateReturnValueX helper methods in baselib,
                    // and MakeInterface and LoadFunction in this file.
                    var helperMethod = new JavaMethodRef(
                        DelegateReturnValueMethod.Name + returnType.ToDescriptor(),
                        returnType, JavaType.ObjectType);
                    code.NewInstruction(0xB8 /* invokestatic */,
                                        SystemDelegateUtilType, helperMethod);
                }

                code.NewInstruction(returnType.ReturnOpcode, null, index);
                code.StackMap.PopStack(CilMain.Where);

                code.MaxStack  = code.StackMap.GetMaxStackSize(CilMain.Where);
                code.MaxLocals = index;
            }

            //
            //
            //

            void GenerateBeginInvoke()
            {
            }

            //
            //
            //

            void GenerateEndInvoke()
            {
            }
        }