// // 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); } }
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); }
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); }
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); }
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); } }