[corlib] ModuleBuilder pseudo-token lookup needs to use references insteads of logica...
[mono.git] / mcs / class / corlib / System.Reflection.Emit / ModuleBuilder.cs
index c000b1eadc153211c13b0d4227b6a0a8a264054e..2e985180ef549a1f9daac1d89129ded9b73a354b 100644 (file)
@@ -77,6 +77,8 @@ namespace System.Reflection.Emit {
                Hashtable resource_writers;
                ISymbolWriter symbolWriter;
 
+               static bool has_warned_about_symbolWriter;
+
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private static extern void basic_init (ModuleBuilder ab);
 
@@ -107,11 +109,22 @@ namespace System.Reflection.Emit {
 
                        if (emitSymbolInfo) {
                                Assembly asm = Assembly.LoadWithPartialName ("Mono.CompilerServices.SymbolWriter");
-                               if (asm == null)
-                                       throw new TypeLoadException ("The assembly for default symbol writer cannot be loaded");
 
-                               Type t = asm.GetType ("Mono.CompilerServices.SymbolWriter.SymbolWriterImpl", true);
-                               symbolWriter = (ISymbolWriter) Activator.CreateInstance (t, new object[] { this });
+                               Type t = null;
+                               if (asm != null)
+                                       t = asm.GetType ("Mono.CompilerServices.SymbolWriter.SymbolWriterImpl");
+
+                               if (t == null) {
+                                       WarnAboutSymbolWriter ("Failed to load the default Mono.CompilerServices.SymbolWriter assembly");
+                               } else {
+                                       try {
+                                               symbolWriter = (ISymbolWriter) Activator.CreateInstance (t, new object[] { this });
+                                       } catch (System.MissingMethodException) {
+                                               WarnAboutSymbolWriter ("The default Mono.CompilerServices.SymbolWriter is not available on this platform");                                     
+                                               return;
+                                       }
+                               }
+                               
                                string fileName = fqname;
                                if (assemblyb.AssemblyDir != null)
                                        fileName = Path.Combine (assemblyb.AssemblyDir, fileName);
@@ -119,6 +132,15 @@ namespace System.Reflection.Emit {
                        }
                }
 
+               static void WarnAboutSymbolWriter (string message) 
+               {
+                       if (has_warned_about_symbolWriter)
+                               return;
+
+                       has_warned_about_symbolWriter = true;
+                       Console.Error.WriteLine ("WARNING: {0}", message);
+               }
+
                public override string FullyQualifiedName {get { return fqname;}}
 
                public bool IsTransient () {
@@ -687,8 +709,7 @@ namespace System.Reflection.Emit {
                static int typespec_tokengen =  0x1bffffff;
                static int memberref_tokengen =  0x0affffff;
                static int methoddef_tokengen =  0x06ffffff;
-               Dictionary<MemberInfo, int> inst_tokens = new Dictionary<MemberInfo, int> ();
-               Dictionary<MemberInfo, int> inst_tokens_open = new Dictionary<MemberInfo, int> ();
+               Dictionary<MemberInfo, int> inst_tokens, inst_tokens_open;
 
                //
                // Assign a pseudo token to the various TypeBuilderInst objects, so the runtime
@@ -698,16 +719,20 @@ namespace System.Reflection.Emit {
                // still encounter these objects, it will resolve them by calling their
                // RuntimeResolve () methods.
                //
-               int GetPseudoToken (MemberInfo member, bool create_open_instance) {
+               int GetPseudoToken (MemberInfo member, bool create_open_instance)
+               {
                        int token;
-
-                       if (create_open_instance) {
-                               if (inst_tokens_open.TryGetValue (member, out token))
-                                       return token;
-                       } else {
-                               if (inst_tokens.TryGetValue (member, out token))
-                                       return token;
+                       var dict = create_open_instance ? inst_tokens_open : inst_tokens;
+                       if (dict == null) {
+                               dict = new Dictionary<MemberInfo, int> (ReferenceEqualityComparer<MemberInfo>.Instance);
+                               if (create_open_instance)
+                                       inst_tokens_open = dict;
+                               else
+                                       inst_tokens = dict;
+                       } else if (dict.TryGetValue (member, out token)) {
+                               return token;
                        }
+
                        // Count backwards to avoid collisions with the tokens
                        // allocated by the runtime
                        if (member is TypeBuilderInstantiation || member is SymbolType)
@@ -742,10 +767,8 @@ namespace System.Reflection.Emit {
                                token = typespec_tokengen --;
                        } else
                                throw new NotImplementedException ();
-                       if (create_open_instance)
-                               inst_tokens_open [member] = token;
-                       else
-                               inst_tokens [member] = token;
+
+                       dict [member] = token;
                        RegisterToken (member, token);
                        return token;
                }
@@ -871,11 +894,14 @@ namespace System.Reflection.Emit {
                //
                // Fixup the pseudo tokens assigned to the various SRE objects
                //
-               void FixupTokens () {
+               void FixupTokens ()
+               {
                        var token_map = new Dictionary<int, int> ();
                        var member_map = new Dictionary<int, MemberInfo> ();
-                       FixupTokens (token_map, member_map, inst_tokens, false);
-                       FixupTokens (token_map, member_map, inst_tokens_open, true);
+                       if (inst_tokens != null)
+                               FixupTokens (token_map, member_map, inst_tokens, false);
+                       if (inst_tokens_open != null)
+                               FixupTokens (token_map, member_map, inst_tokens_open, true);
 
                        // Replace the tokens in the IL stream
                        if (types != null) {