예제 #1
0
        //
        // create the IGenericObject methods
        //

        public static void BuildGetTypeMethod(JavaClass theClass, CilType theType)
        {
            theClass.AddInterface("system.IGenericObject");

            var methodRef = new JavaMethodRef("system-IGenericObject-GetType",
                                              CilType.SystemTypeType);

            var code = CilMain.CreateHelperMethod(theClass, methodRef, 1, 1);

            if (theType.HasGenericParameters)
            {
                // this is a proper generic type with a -generic-type field
                // created by MakeGenericClass, which also invoked us.

                code.NewInstruction(0x19 /* aload */, null, (int)0);
                code.NewInstruction(0xB4 /* getfield */, theType, ConcreteTypeField);
                code.NewInstruction(JavaType.ObjectType.ReturnOpcode, null, null);
            }
            else
            {
                // this is a non-generic type, but has a generic base type
                // which implements the GetType method, so we want to provide
                // an overriding implementation that returns the correct type.
                // we are invoked by TypeBuilder.

                code.StackMap = new JavaStackMap();
                LoadMaybeGeneric(theType, code);
                code.NewInstruction(JavaType.ObjectType.ReturnOpcode, null, null);
            }
        }
예제 #2
0
        internal static JavaClass CreateInnerClass(JavaClass outerClass, string innerName,
                                                   JavaAccessFlags innerFlags = 0,
                                                   bool markGenericEntity     = false)
        {
            if (innerFlags == 0)
            {
                innerFlags = JavaAccessFlags.ACC_PUBLIC
                             | JavaAccessFlags.ACC_FINAL
                             | JavaAccessFlags.ACC_SUPER;
            }
            innerFlags |= JavaAccessFlags.ACC_SYNTHETIC;

            var innerClass = new JavaClass();

            innerClass.Name              = innerName;
            innerClass.Super             = JavaType.ObjectType.ClassName;
            innerClass.PackageNameLength = outerClass.PackageNameLength;
            innerClass.Flags             = innerFlags;
            innerClass.Fields            = new List <JavaField>();
            innerClass.Methods           = new List <JavaMethod>();

            if (markGenericEntity)
            {
                innerClass.AddInterface("system.IGenericEntity");
            }

            outerClass.AddInnerClass(innerClass);
            return(innerClass);
        }
예제 #3
0
        public static List <CilInterface> ImportInterfaces(JavaClass jclass, CilType myType,
                                                           TypeDefinition cilType)
        {
            var myInterfaces = CilInterface.CollectAll(cilType);

            int n = myInterfaces.Count;

            if (n > 0)
            {
                jclass.Interfaces = new List <string>(n);
                for (int i = 0; i < n; i++)
                {
                    if (myInterfaces[i].DirectReference)
                    {
                        var ifcJavaName = myInterfaces[i].InterfaceType.JavaName;
                        if (ifcJavaName != "system.ValueMethod")
                        {
                            jclass.AddInterface(ifcJavaName);
                        }
                    }
                }
            }

            if ((cilType.Attributes & TypeAttributes.Serializable) != 0)
            {
                jclass.AddInterface("java.io.Serializable");
            }

            if ((cilType.Attributes & TypeAttributes.Interface) != 0)
            {
                // super of interface is always java.lang.Object, per JLS 4.1
                jclass.Super = JavaType.ObjectType.ClassName;
            }

            return(myInterfaces);
        }
예제 #4
0
        public static void CreateSuppressibleFinalize(JavaMethod innerMethod, CilType declType,
                                                      JavaClass theClass)
        {
            //
            // if the class defines a finalizer method Finalize() then:
            //
            // - create a flag field that tracks whether finalization is suppressed
            //
            // - implement interface system.GC.FinalizeSuppressible, and its Set()
            // method, which sets the flag field
            //
            // - create a wrapper method that checks the flag field and possibly
            // invokes the original finalizer
            //
            // see also: system.GC in baselib
            //

            var flagField = new JavaField();

            flagField.Name  = "-finalize-suppressed";
            flagField.Type  = CilType.From(JavaType.BooleanType);
            flagField.Class = theClass;
            flagField.Flags = JavaAccessFlags.ACC_PRIVATE | JavaAccessFlags.ACC_VOLATILE;

            if (theClass.Fields == null)
            {
                theClass.Fields = new List <JavaField>();
            }
            theClass.Fields.Add(flagField);

            //
            // implement the interface method
            //

            var ifcMethod = new JavaMethod("system-GC$SuppressibleFinalize-Set",
                                           JavaType.VoidType);

            ifcMethod.Class = theClass;
            ifcMethod.Flags = JavaAccessFlags.ACC_PUBLIC;

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

            code.Method       = ifcMethod;
            code.Instructions = new List <JavaCode.Instruction>();
            code.MaxLocals    = code.MaxStack = 2;

            code.NewInstruction(0x19 /* aload */, null, (int)0);
            code.NewInstruction(0x12 /* ldc */, null, (int)1);
            code.NewInstruction(0xB5 /* putfield */, declType, flagField);
            code.NewInstruction(JavaType.VoidType.ReturnOpcode, null, null);

            theClass.Methods.Add(ifcMethod);
            theClass.AddInterface("system.GC$SuppressibleFinalize");

            //
            // create the wrapper method
            //

            var outerMethod = new JavaMethod(theClass, innerMethod);

            outerMethod.Flags = JavaAccessFlags.ACC_PROTECTED;
            innerMethod.Flags = JavaAccessFlags.ACC_PRIVATE;

            innerMethod.Name += "---inner";

            // prepare to generate instructions

            code              = outerMethod.Code = new JavaCode();
            code.Method       = outerMethod;
            code.Instructions = new List <JavaCode.Instruction>();
            code.StackMap     = new JavaStackMap();
            code.StackMap.SaveFrame((ushort)0, false, CilMain.Where);
            code.MaxLocals = code.MaxStack = 1;

            //
            // check the flag field to determine if suppressed
            //

            code.NewInstruction(0x19 /* aload */, null, (int)0);

            code.NewInstruction(0xB4 /* getfield */, declType, flagField);

            code.NewInstruction(0x9A /* ifne != zero */, null, (ushort)0xFFFE);

            code.NewInstruction(0x19 /* aload */, null, (int)0);

            code.NewInstruction(0xB7 /* invokespecial */, declType, innerMethod);

            code.NewInstruction(JavaType.VoidType.ReturnOpcode, null, null,
                                /* label */ 0xFFFE);

            code.StackMap.SaveFrame((ushort)0xFFFE, true, CilMain.Where);

            theClass.Methods.Add(outerMethod);
        }
예제 #5
0
        public static List <JavaClass> BuildProxyMethods(List <CilInterface> allInterfaces,
                                                         TypeDefinition fromType, CilType intoType,
                                                         JavaClass theClass)
        {
            //
            // process only if the class (or interface) has any methods or super interfaces
            //

            var classMethods = theClass.Methods;

            if (classMethods.Count == 0)
            {
                return(null);
            }

            bool isInterface = intoType.IsInterface;

            if ((!isInterface) && theClass.Interfaces == null)
            {
                return(null);
            }

            var theMethods = CilInterfaceMethod.CollectAll(fromType);

            //
            // if any interfaces are marked [RetainName], make sure that
            // all corresponding methods are also marked [RetainName]
            //

            CheckRetainNameMethods(theMethods, allInterfaces, intoType);

            //
            // if this is an abstract class but forced to an interface via [AddInterface]
            // decoration, then we need to remove all constructors generated for the class
            //

            if (intoType.IsInterface)
            {
                if (!fromType.IsInterface)
                {
                    for (int i = classMethods.Count; i-- > 0;)
                    {
                        if (classMethods[i].Name == "<init>")
                        {
                            classMethods.RemoveAt(i);
                        }
                    }
                }

                if (intoType.HasGenericParameters)
                {
                    // the RuntimeType constructor in baselib uses IGenericEntity
                    // marker interface to identify generic classes.  note that
                    // real generic types implement IGenericObject -> IGenericEntity.

                    theClass.AddInterface("system.IGenericEntity");
                }

                return(null);
            }

            //
            // for each implemented interface, build proxy methods
            //

            List <JavaClass> output = null;

            int ifcNumber = 0;

            foreach (var ifc in allInterfaces)
            {
                if ((!ifc.DirectReference) && ifc.SuperImplements)
                {
                    // we don't have to build proxy for an interface if it is
                    // implemented by a super type and not by our primary type
                    continue;
                }
                if (ifc.GenericTypes == null)
                {
                    foreach (var ifcMethod in ifc.Methods)
                    {
                        // build proxy methods:  interface$method -> method
                        var newMethod = BuildPlainProxy(ifcMethod, intoType, theMethods);
                        if (newMethod != null)
                        {
                            newMethod.Class = theClass;
                            theClass.Methods.Add(newMethod);
                        }
                    }
                }
                else
                {
                    var ifcClass = CreateInnerClass(theClass, intoType, ++ifcNumber);
                    ifcClass.AddInterface(ifc.InterfaceType.JavaName);

                    if (output == null)
                    {
                        output = new List <JavaClass>();
                        CreateInterfaceArrayField(theClass);
                    }
                    output.Add(ifcClass);

                    // if the class implements a generic interface for multiple types,
                    // then we need a method suffix to differentiate between the methods.
                    // see also:  CilMethod::InsertMethodNamePrefix
                    string methodSuffix = "";
                    foreach (var genericType in ifc.GenericTypes)
                    {
                        methodSuffix += "--" + CilMethod.GenericParameterSuffixName(genericType);
                    }

                    foreach (var ifcMethod in ifc.Methods)
                    {
                        // build proxy classes:  proxy sub-class -> this class
                        BuildGenericProxy(ifcMethod, methodSuffix, intoType, theMethods, ifcClass);
                    }
                }
            }

            return(output);

            JavaClass CreateInnerClass(JavaClass parentClass, CilType parentType, int ifcNumber)
            {
                // generic interfaces are implemented as proxy sub-classes which
                // call methods on the parent class object.  we need to define
                // an inner class.  this class has one instance field which is a
                // reference to the parent class.  the constructor takes this
                // reference as a parameter and initializes the instance field.

                var newClass = CilMain.CreateInnerClass(parentClass,
                                                        parentClass.Name + "$$generic" + ifcNumber.ToString());

                var fld = new JavaField();

                fld.Name  = ParentFieldName;
                fld.Type  = parentType;
                fld.Class = newClass;
                fld.Flags = JavaAccessFlags.ACC_PRIVATE;
                newClass.Fields.Add(fld);

                var code = CilMain.CreateHelperMethod(newClass,
                                                      new JavaMethodRef("<init>", JavaType.VoidType, JavaType.ObjectType),
                                                      2, 2);

                code.Method.Flags &= ~JavaAccessFlags.ACC_BRIDGE;   // invalid for constructor

                code.NewInstruction(0x19 /* aload */, null, (int)0);
                code.NewInstruction(0xB7 /* invokespecial */, JavaType.ObjectType,
                                    new JavaMethodRef("<init>", JavaType.VoidType));
                code.NewInstruction(0x19 /* aload */, null, (int)0);
                code.NewInstruction(0x19 /* aload */, null, (int)1);
                code.NewInstruction(0xC0 /* checkcast */, parentType, null);
                code.NewInstruction(0xB5 /* putfield */, new JavaType(0, 0, newClass.Name),
                                    new JavaFieldRef(ParentFieldName, parentType));
                code.NewInstruction(JavaType.VoidType.ReturnOpcode, null, null);

                return(newClass);
            }

            void CreateInterfaceArrayField(JavaClass parentClass)
            {
                // the parent class has a helper array field that is used to track
                // the proxy objects generated for implemented generic interfaces.
                // see also: InitInterfaceArrayField, below.

                var fld = new JavaField();

                fld.Name  = InterfaceArrayField.Name;
                fld.Type  = InterfaceArrayField.Type;
                fld.Class = parentClass;
                fld.Flags = JavaAccessFlags.ACC_PRIVATE;

                if (parentClass.Fields == null)
                {
                    parentClass.Fields = new List <JavaField>(1);
                }
                parentClass.Fields.Add(fld);
            }
        }