2010-03-17 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mcs / ilasm / codegen / GenericTypeInst.cs
index f809df0d1c3af0619fabef1a17eb5c916a4ac2c9..6634f418b6346482c33fd997c18fc649e79edf74 100644 (file)
@@ -15,58 +15,40 @@ using System.Collections;
 
 namespace Mono.ILASM {
 
-        public class GenericTypeInst : ModifiableType, IClassRef {
+        public class GenericTypeInst : BaseGenericTypeRef {
 
-                private IClassRef class_ref;
-                private PEAPI.Type ptype;
+                private BaseClassRef class_ref;
                 private PEAPI.GenericTypeInst p_gen_inst;
                 private bool is_valuetypeinst;
-                private bool is_resolved;
                 private GenericArguments gen_args;
-                private string sig_mod;
                 private bool is_added; /* Added to PEFile (to TypeSpec table) ? */
-                private static Hashtable method_table = new Hashtable ();
+                /* Note: Using static hashtable here as GenericTypeInsts is not cached */
+                private static Hashtable s_method_table = new Hashtable ();
+                private static Hashtable s_field_table = new Hashtable ();
 
-                public GenericTypeInst (IClassRef class_ref, GenericArguments gen_args, bool is_valuetypeinst)
+                public GenericTypeInst (BaseClassRef class_ref, GenericArguments gen_args, bool is_valuetypeinst)
                         : this (class_ref, gen_args, is_valuetypeinst, null, null)
                 {
                 }
 
-                public GenericTypeInst (IClassRef class_ref, GenericArguments gen_args, bool is_valuetypeinst,
+                public GenericTypeInst (BaseClassRef class_ref, GenericArguments gen_args, bool is_valuetypeinst,
                                 string sig_mod, ArrayList conv_list)
+                        : base ("", is_valuetypeinst, conv_list, sig_mod)
                 {
                         if (class_ref is GenericTypeInst)
-                                throw new ArgumentException (String.Format ("Cannot create nested GenericInst, '{0}' '{1}'", class_ref.FullName, gen_args.ToString ()));
+                                throw new InternalErrorException ("Cannot create nested GenericInst, '" +
+                                                        class_ref.FullName + "' '" + gen_args.ToString () + "'");
 
                         this.class_ref = class_ref;
                         this.gen_args = gen_args;
-                        this.is_valuetypeinst = is_valuetypeinst;
-                        this.sig_mod = sig_mod;
                         is_added = false;
-                        if (conv_list != null)
-                                ConversionList = conv_list;
-
-                        is_resolved = false;
-                }
-
-                public PEAPI.Type PeapiType {
-                        get { return ptype; }
                 }
 
-                public string FullName {
+                public override string FullName {
                         get { return class_ref.FullName + gen_args.ToString () + SigMod; }
                 }
 
-                public PEAPI.Class PeapiClass {
-                        get { return (PEAPI.Class) ptype; }
-                }
-
-                public override string SigMod {
-                        get { return sig_mod; }
-                        set { sig_mod = value; }
-                }
-
-                public IClassRef Clone ()
+                public override BaseTypeRef Clone ()
                 {
                         //Clone'd instance shares the class_ref and gen_args,
                         //as its basically used to create modified types (arrays etc)
@@ -74,24 +56,12 @@ namespace Mono.ILASM {
                                         (ArrayList) ConversionList.Clone () );
                 }
 
-                public void MakeValueClass ()
+                public override void MakeValueClass ()
                 {
                         class_ref.MakeValueClass ();
                 }
 
-                public GenericTypeInst GetGenericTypeInst (GenericArguments gen_args)
-                {
-                        throw new Exception (String.Format ("Invalid attempt to create '{0}''{1}'", FullName, gen_args.ToString ()));
-                }
-
-                public PEAPI.Type ResolveInstance (CodeGen code_gen, GenericArguments gen_args)
-                {
-                        throw new Exception (String.Format ("Invalid attempt to create '{0}''{1}'", FullName, gen_args.ToString ()));
-                }
-                
-                /* Only resolves, does not add it to the TypeSpec
-                   table */
-                public void ResolveOnly (CodeGen code_gen)
+                public override void ResolveNoTypeSpec (CodeGen code_gen)
                 {
                         if (is_resolved)
                                 return;
@@ -99,14 +69,14 @@ namespace Mono.ILASM {
                         class_ref.Resolve (code_gen);
                         p_gen_inst = (PEAPI.GenericTypeInst) class_ref.ResolveInstance (code_gen, gen_args);
 
-                        ptype = Modify (code_gen, p_gen_inst);
+                        type = Modify (code_gen, p_gen_inst);
 
                         is_resolved = true;
                 }
 
-                public void Resolve (CodeGen code_gen)
+                public override void Resolve (CodeGen code_gen)
                 {
-                        ResolveOnly (code_gen);
+                        ResolveNoTypeSpec (code_gen);
                         if (is_added)
                                 return;
 
@@ -114,22 +84,44 @@ namespace Mono.ILASM {
                         is_added = true;
                 }
 
-                public IMethodRef GetMethodRef (ITypeRef ret_type, PEAPI.CallConv call_conv,
-                                string meth_name, ITypeRef[] param, int gen_param_count)
+                public override void Resolve (GenericParameters type_gen_params, GenericParameters method_gen_params)
+                {
+                        gen_args.Resolve (type_gen_params, method_gen_params);
+                }
+
+                protected override BaseMethodRef CreateMethodRef (BaseTypeRef ret_type,
+                        PEAPI.CallConv call_conv, string name, BaseTypeRef[] param, int gen_param_count)
                 {
-                        string key = FullName + MethodDef.CreateSignature (ret_type, meth_name, param, gen_param_count);
-                        TypeSpecMethodRef mr = method_table [key] as TypeSpecMethodRef;
+                        throw new InternalErrorException ("Should not be called");
+                }
+
+                public override BaseMethodRef GetMethodRef (BaseTypeRef ret_type, PEAPI.CallConv call_conv,
+                                string meth_name, BaseTypeRef[] param, int gen_param_count)
+                {
+                       /* Note: Using FullName here as we are caching in a static hashtable */
+                        string key = FullName + MethodDef.CreateSignature (ret_type, call_conv, meth_name, param, gen_param_count, true);
+                        TypeSpecMethodRef mr = s_method_table [key] as TypeSpecMethodRef;
                         if (mr == null) {         
-                                mr = new TypeSpecMethodRef (this, ret_type, call_conv, meth_name, param, gen_param_count);
-                                method_table [key] = mr;
+                                mr = new TypeSpecMethodRef (this, call_conv, ret_type, meth_name, param, gen_param_count);
+                                s_method_table [key] = mr;
                         }
 
                         return mr;
                 }
 
-                public IFieldRef GetFieldRef (ITypeRef ret_type, string field_name)
+                protected override IFieldRef CreateFieldRef (BaseTypeRef ret_type, string field_name)
                 {
-                        return new TypeSpecFieldRef (this, ret_type, field_name);
+                       /* Note: Using FullName here as we are caching in a static hashtable */
+                        string key = FullName + ret_type.FullName + field_name;
+
+                        IFieldRef fr = (IFieldRef) s_field_table [key];
+
+                        if (fr == null) {
+                                fr = new TypeSpecFieldRef (this, ret_type, field_name);
+                                s_field_table [key] = fr;
+                        }
+
+                        return fr;
                 }
         }
 }