diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
index 98ad3d8..428daa5 100644
--- a/gio/gdesktopappinfo.c
+++ b/gio/gdesktopappinfo.c
@@ -1942,14 +1942,27 @@ g_app_info_get_all (void)
 /* Cacheing of mimeinfo.cache and defaults.list files */
 
 typedef struct {
+  gchar *filename;
+  void (*constructor)(GHashTable *table, char *mime_type, char **desktop_file_ids);
+  void (*destructor) (gpointer value);
+  gchar* groups[];
+} MimeInfoCacheDirItemSpec;
+
+typedef struct {
+  time_t timestamp;
+  GHashTable *map[0];
+} MimeInfoCacheDirItem;
+
+typedef GHashTable *MimeInfoCacheDirItemMapPad;
+
+typedef struct {
   char *path;
-  GHashTable *mime_info_cache_map;
-  GHashTable *defaults_list_map;
-  GHashTable *mimeapps_list_added_map;
-  GHashTable *mimeapps_list_removed_map;
-  time_t mime_info_cache_timestamp;
-  time_t defaults_list_timestamp;
-  time_t mimeapps_list_timestamp;
+  MimeInfoCacheDirItem mime_info_cache;
+  MimeInfoCacheDirItemMapPad _mime_info_cache_map_pad[1];
+  MimeInfoCacheDirItem defaults_list;
+  MimeInfoCacheDirItemMapPad _defaults_list_map_pad[1];
+  MimeInfoCacheDirItem mimeapps_list;
+  MimeInfoCacheDirItemMapPad _mimeapps_list_map_pad[2];
 } MimeInfoCacheDir;
 
 typedef struct {
@@ -1962,28 +1975,20 @@ typedef struct {
 static MimeInfoCache *mime_info_cache = NULL;
 G_LOCK_DEFINE_STATIC (mime_info_cache);
 
-static void mime_info_cache_dir_add_desktop_entries (MimeInfoCacheDir  *dir,
-						     const char        *mime_type,
-						     char             **new_desktop_file_ids);
+static void mime_info_cache_dir_add_desktop_entries (GHashTable *map,
+						     char       *mime_type,
+						     char      **new_desktop_file_ids);
 
 static MimeInfoCache * mime_info_cache_new (void);
 
+
 static void
-destroy_info_cache_value (gpointer  key, 
-                          GList    *value, 
-                          gpointer  data)
+destroy_info_cache_value (GList *value)
 {
   g_list_foreach (value, (GFunc)g_free, NULL);
   g_list_free (value);
 }
 
-static void
-destroy_info_cache_map (GHashTable *info_cache_map)
-{
-  g_hash_table_foreach (info_cache_map, (GHFunc)destroy_info_cache_value, NULL);
-  g_hash_table_destroy (info_cache_map);
-}
-
 static gboolean
 mime_info_cache_dir_out_of_date (MimeInfoCacheDir *dir,
 				 const char       *cache_file,
@@ -2024,264 +2029,110 @@ mime_info_cache_blow_global_cache (void)
 			       remove_all, NULL);
 }
 
-static void
-mime_info_cache_dir_init (MimeInfoCacheDir *dir)
-{
-  GError *load_error;
-  GKeyFile *key_file;
-  gchar *filename, **mime_types;
-  int i;
-  struct stat buf;
-  
-  load_error = NULL;
-  mime_types = NULL;
-  
-  if (dir->mime_info_cache_map != NULL &&
-      !mime_info_cache_dir_out_of_date (dir, "mimeinfo.cache",
-					&dir->mime_info_cache_timestamp))
-    return;
-  
-  if (dir->mime_info_cache_map != NULL)
-    destroy_info_cache_map (dir->mime_info_cache_map);
-  
-  dir->mime_info_cache_map = g_hash_table_new_full (g_str_hash, g_str_equal,
-						    (GDestroyNotify) g_free,
-						    NULL);
-  
-  key_file = g_key_file_new ();
-  
-  filename = g_build_filename (dir->path, "mimeinfo.cache", NULL);
-  
-  if (g_stat (filename, &buf) < 0)
-    goto error;
-  
-  if (dir->mime_info_cache_timestamp > 0) 
-    mime_info_cache->should_ping_mime_monitor = TRUE;
-  
-  dir->mime_info_cache_timestamp = buf.st_mtime;
-  
-  g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, &load_error);
-  
-  g_free (filename);
-  filename = NULL;
-  
-  if (load_error != NULL)
-    goto error;
-  
-  mime_types = g_key_file_get_keys (key_file, MIME_CACHE_GROUP,
-				    NULL, &load_error);
-  
-  if (load_error != NULL)
-    goto error;
-  
-  for (i = 0; mime_types[i] != NULL; i++)
-    {
-      gchar **desktop_file_ids;
-      char *unaliased_type;
-      desktop_file_ids = g_key_file_get_string_list (key_file,
-						     MIME_CACHE_GROUP,
-						     mime_types[i],
-						     NULL,
-						     NULL);
-      
-      if (desktop_file_ids == NULL)
-	continue;
-
-      unaliased_type = _g_unix_content_type_unalias (mime_types[i]);
-      mime_info_cache_dir_add_desktop_entries (dir,
-					       unaliased_type,
-					       desktop_file_ids);
-      g_free (unaliased_type);
-    
-      g_strfreev (desktop_file_ids);
-    }
-  
-  g_strfreev (mime_types);
-  g_key_file_free (key_file);
-  
-  return;
- error:
-  g_free (filename);
-  g_key_file_free (key_file);
-  
-  if (mime_types != NULL)
-    g_strfreev (mime_types);
-  
-  if (load_error)
-    g_error_free (load_error);
-}
+typedef void (*MimeInfoCacheDirItemConstructor) (GHashTable* table,
+						 char *mime_type,
+						 char **desktop_file_ids);
+
+typedef void (*MimeInfoCacheDirItemDestructor) (gpointer value);
+
+static const MimeInfoCacheDirItemSpec
+mime_info_cache_dir_item_spec_mime_info_cache =
+  {
+    .filename = "mimeinfo.cache",
+    .constructor = mime_info_cache_dir_add_desktop_entries,
+    .destructor = (MimeInfoCacheDirItemDestructor) destroy_info_cache_value,
+    .groups = {MIME_CACHE_GROUP, NULL}
+  };
+
+static const MimeInfoCacheDirItemSpec
+mime_info_cache_dir_item_spec_defaults_list =
+  {
+    .filename = "defaults.list",
+    .constructor = (MimeInfoCacheDirItemConstructor) g_hash_table_replace,
+    .destructor = (MimeInfoCacheDirItemDestructor) g_strfreev,
+    .groups = {DEFAULT_APPLICATIONS_GROUP, NULL}
+  };
+
+static const MimeInfoCacheDirItemSpec
+mime_info_cache_dir_item_spec_mimeapps_list =
+  {
+    .filename = "mimeapps.list",
+    .constructor = (MimeInfoCacheDirItemConstructor) g_hash_table_replace,
+    .destructor = (MimeInfoCacheDirItemDestructor) g_strfreev,
+    .groups = {ADDED_ASSOCIATIONS_GROUP, REMOVED_ASSOCIATIONS_GROUP, NULL}
+  };
 
 static void
-mime_info_cache_dir_init_defaults_list (MimeInfoCacheDir *dir)
+mime_info_cache_dir_build_cache (MimeInfoCacheDir               *dir,
+				 MimeInfoCacheDirItem           *item,
+				 const MimeInfoCacheDirItemSpec *spec)
 {
   GKeyFile *key_file;
   GError *load_error;
   gchar *filename, **mime_types;
   char *unaliased_type;
   char **desktop_file_ids;
-  int i;
   struct stat buf;
+  int hn, i;
 
   load_error = NULL;
-  mime_types = NULL;
 
-  if (dir->defaults_list_map != NULL &&
-      !mime_info_cache_dir_out_of_date (dir, "defaults.list",
-					&dir->defaults_list_timestamp))
+  if (item->map[0] != NULL &&
+      !mime_info_cache_dir_out_of_date (dir, spec->filename,
+					&item->timestamp))
     return;
   
-  if (dir->defaults_list_map != NULL)
-    g_hash_table_destroy (dir->defaults_list_map);
-  dir->defaults_list_map = g_hash_table_new_full (g_str_hash, g_str_equal,
-						  g_free, (GDestroyNotify)g_strfreev);
-  
-
-  key_file = g_key_file_new ();
-  
-  filename = g_build_filename (dir->path, "defaults.list", NULL);
-  if (g_stat (filename, &buf) < 0)
-    goto error;
-
-  if (dir->defaults_list_timestamp > 0) 
-    mime_info_cache->should_ping_mime_monitor = TRUE;
-
-  dir->defaults_list_timestamp = buf.st_mtime;
-
-  g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, &load_error);
-  g_free (filename);
-  filename = NULL;
-
-  if (load_error != NULL)
-    goto error;
-
-  mime_types = g_key_file_get_keys (key_file, DEFAULT_APPLICATIONS_GROUP,
-				    NULL, NULL);
-  if (mime_types != NULL)
+  for (hn = 0; spec->groups[hn] != NULL; hn++)
     {
-      for (i = 0; mime_types[i] != NULL; i++)
-	{
-	  desktop_file_ids = g_key_file_get_string_list (key_file,
-							 DEFAULT_APPLICATIONS_GROUP,
-							 mime_types[i],
-							 NULL,
-							 NULL);
-	  if (desktop_file_ids == NULL)
-	    continue;
-	  
-	  unaliased_type = _g_unix_content_type_unalias (mime_types[i]);
-	  g_hash_table_replace (dir->defaults_list_map,
-				unaliased_type,
-				desktop_file_ids);
-	}
-      
-      g_strfreev (mime_types);
-    }
-
-  g_key_file_free (key_file);
-  return;
-  
- error:
-  g_free (filename);
-  g_key_file_free (key_file);
-  
-  if (mime_types != NULL)
-    g_strfreev (mime_types);
-  
-  if (load_error)
-    g_error_free (load_error);
-}
-
-static void
-mime_info_cache_dir_init_mimeapps_list (MimeInfoCacheDir *dir)
-{
-  GKeyFile *key_file;
-  GError *load_error;
-  gchar *filename, **mime_types;
-  char *unaliased_type;
-  char **desktop_file_ids;
-  int i;
-  struct stat buf;
+      if (item->map[hn] != NULL)
+	g_hash_table_destroy (item->map[hn]);
 
-  load_error = NULL;
-  mime_types = NULL;
-
-  if (dir->mimeapps_list_added_map != NULL &&
-      !mime_info_cache_dir_out_of_date (dir, "mimeapps.list",
-					&dir->mimeapps_list_timestamp))
-    return;
-  
-  if (dir->mimeapps_list_added_map != NULL)
-    g_hash_table_destroy (dir->mimeapps_list_added_map);
-  dir->mimeapps_list_added_map = g_hash_table_new_full (g_str_hash, g_str_equal,
-							g_free, (GDestroyNotify)g_strfreev);
-  
-  if (dir->mimeapps_list_removed_map != NULL)
-    g_hash_table_destroy (dir->mimeapps_list_removed_map);
-  dir->mimeapps_list_removed_map = g_hash_table_new_full (g_str_hash, g_str_equal,
-							  g_free, (GDestroyNotify)g_strfreev);
+      item->map[hn] = g_hash_table_new_full (g_str_hash, g_str_equal,
+					     g_free, spec->destructor);
+    }
 
   key_file = g_key_file_new ();
   
-  filename = g_build_filename (dir->path, "mimeapps.list", NULL);
+  filename = g_build_filename (dir->path, spec->filename, NULL);
   if (g_stat (filename, &buf) < 0)
     goto error;
 
-  if (dir->mimeapps_list_timestamp > 0) 
+  if (item->timestamp > 0)
     mime_info_cache->should_ping_mime_monitor = TRUE;
 
-  dir->mimeapps_list_timestamp = buf.st_mtime;
+  item->timestamp = buf.st_mtime;
 
   g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, &load_error);
+
   g_free (filename);
   filename = NULL;
 
   if (load_error != NULL)
     goto error;
 
-  mime_types = g_key_file_get_keys (key_file, ADDED_ASSOCIATIONS_GROUP,
-				    NULL, NULL);
-  if (mime_types != NULL)
-    {
-      for (i = 0; mime_types[i] != NULL; i++)
-	{
-	  desktop_file_ids = g_key_file_get_string_list (key_file,
-							 ADDED_ASSOCIATIONS_GROUP,
-							 mime_types[i],
-							 NULL,
-							 NULL);
-	  if (desktop_file_ids == NULL)
-	    continue;
-	  
-	  unaliased_type = _g_unix_content_type_unalias (mime_types[i]);
-	  g_hash_table_replace (dir->mimeapps_list_added_map,
-				unaliased_type,
-				desktop_file_ids);
-	}
-      
-      g_strfreev (mime_types);
-    }
-
-  mime_types = g_key_file_get_keys (key_file, REMOVED_ASSOCIATIONS_GROUP,
-				    NULL, NULL);
-  if (mime_types != NULL)
+  for (hn = 0; spec->groups[hn] != NULL; hn++)
     {
-      for (i = 0; mime_types[i] != NULL; i++)
+      mime_types = g_key_file_get_keys (key_file, spec->groups[hn],
+					NULL, NULL);
+      if (mime_types != NULL)
 	{
-	  desktop_file_ids = g_key_file_get_string_list (key_file,
-							 REMOVED_ASSOCIATIONS_GROUP,
-							 mime_types[i],
-							 NULL,
-							 NULL);
-	  if (desktop_file_ids == NULL)
-	    continue;
+	  for (i = 0; mime_types[i] != NULL; i++)
+	    {
+	      desktop_file_ids = g_key_file_get_string_list (key_file,
+							     spec->groups[hn],
+							     mime_types[i],
+							     NULL,
+							     NULL);
+	      if (desktop_file_ids == NULL)
+		continue;
 	  
-	  unaliased_type = _g_unix_content_type_unalias (mime_types[i]);
-	  g_hash_table_replace (dir->mimeapps_list_removed_map,
-				unaliased_type,
-				desktop_file_ids);
+	      unaliased_type = _g_unix_content_type_unalias (mime_types[i]);
+	      spec->constructor (item->map[hn],
+				 unaliased_type,
+				 desktop_file_ids);
+	    }
+	  g_strfreev (mime_types);
 	}
-      
-      g_strfreev (mime_types);
     }
 
   g_key_file_free (key_file);
@@ -2291,9 +2142,6 @@ mime_info_cache_dir_init_mimeapps_list (MimeInfoCacheDir *dir)
   g_free (filename);
   g_key_file_free (key_file);
   
-  if (mime_types != NULL)
-    g_strfreev (mime_types);
-  
   if (load_error)
     g_error_free (load_error);
 }
@@ -2315,53 +2163,67 @@ mime_info_cache_dir_free (MimeInfoCacheDir *dir)
   if (dir == NULL)
     return;
   
-  if (dir->mime_info_cache_map != NULL)
+  if (dir->mime_info_cache.map[0] != NULL)
     {
-      destroy_info_cache_map (dir->mime_info_cache_map);
-      dir->mime_info_cache_map = NULL;
+      g_hash_table_destroy (dir->mime_info_cache.map[0]);
+      dir->mime_info_cache.map[0] = NULL;
       
   }
   
-  if (dir->defaults_list_map != NULL)
+  if (dir->defaults_list.map[0] != NULL)
     {
-      g_hash_table_destroy (dir->defaults_list_map);
-      dir->defaults_list_map = NULL;
+      g_hash_table_destroy (dir->defaults_list.map[0]);
+      dir->defaults_list.map[0] = NULL;
     }
   
-  if (dir->mimeapps_list_added_map != NULL)
+  if (dir->mimeapps_list.map[0] != NULL)
     {
-      g_hash_table_destroy (dir->mimeapps_list_added_map);
-      dir->mimeapps_list_added_map = NULL;
+      g_hash_table_destroy (dir->mimeapps_list.map[0]);
+      dir->mimeapps_list.map[0] = NULL;
     }
   
-  if (dir->mimeapps_list_removed_map != NULL)
+  if (dir->mimeapps_list.map[1] != NULL)
     {
-      g_hash_table_destroy (dir->mimeapps_list_removed_map);
-      dir->mimeapps_list_removed_map = NULL;
+      g_hash_table_destroy (dir->mimeapps_list.map[1]);
+      dir->mimeapps_list.map[1] = NULL;
     }
   
   g_free (dir);
 }
 
 static void
-mime_info_cache_dir_add_desktop_entries (MimeInfoCacheDir  *dir,
-					 const char        *mime_type,
-					 char             **new_desktop_file_ids)
+mime_info_cache_dir_add_desktop_entries (GHashTable *map,
+					 char       *mime_type,
+					 char      **new_desktop_file_ids)
 {
   GList *desktop_file_ids;
   int i;
   
-  desktop_file_ids = g_hash_table_lookup (dir->mime_info_cache_map,
-					  mime_type);
-  
-  for (i = 0; new_desktop_file_ids[i] != NULL; i++)
+  desktop_file_ids = g_hash_table_lookup (map, mime_type);
+  if (desktop_file_ids)
     {
-      if (!g_list_find_custom (desktop_file_ids, new_desktop_file_ids[i], strcmp))
-	desktop_file_ids = g_list_append (desktop_file_ids,
-					  g_strdup (new_desktop_file_ids[i]));
+      for (i = 0; new_desktop_file_ids[i] != NULL; i++)
+	{
+	  if (g_list_find_custom (desktop_file_ids, new_desktop_file_ids[i],
+				  (GCompareFunc)strcmp))
+	    g_free (new_desktop_file_ids[i]);
+	  else
+	    {
+	      if (g_list_append (desktop_file_ids,
+				 new_desktop_file_ids[i]))
+		{
+		  /* We are appending to a non-empty GList => we can
+		     ignore the return value and skip
+		     g_hash_table_insert(), g_hash_table_steal() (to
+		     not call destructor). */
+		}
+	    }
+	}
+      g_free (mime_type);
+      g_free (new_desktop_file_ids);
     }
-  
-  g_hash_table_insert (dir->mime_info_cache_map, g_strdup (mime_type), desktop_file_ids);
+  else
+    g_hash_table_insert (map, mime_type, desktop_file_ids);
 }
 
 static void
@@ -2382,10 +2244,12 @@ mime_info_cache_init_dir_lists (void)
       
       if (dir != NULL)
 	{
-	  mime_info_cache_dir_init (dir);
-	  mime_info_cache_dir_init_defaults_list (dir);
-	  mime_info_cache_dir_init_mimeapps_list (dir);
-	  
+	  mime_info_cache_dir_build_cache (dir, &dir->mime_info_cache,
+					   &mime_info_cache_dir_item_spec_mime_info_cache);
+	  mime_info_cache_dir_build_cache (dir, &dir->defaults_list,
+					   &mime_info_cache_dir_item_spec_defaults_list);
+	  mime_info_cache_dir_build_cache (dir, &dir->mimeapps_list,
+					   &mime_info_cache_dir_item_spec_mimeapps_list);
 	  mime_info_cache->dirs = g_list_append (mime_info_cache->dirs, dir);
 	}
     }
@@ -2404,9 +2268,12 @@ mime_info_cache_update_dir_lists (void)
 
       /* No need to do this if we had file monitors... */
       mime_info_cache_blow_global_cache ();
-      mime_info_cache_dir_init (dir);
-      mime_info_cache_dir_init_defaults_list (dir);
-      mime_info_cache_dir_init_mimeapps_list (dir);
+      mime_info_cache_dir_build_cache (dir, &dir->mime_info_cache,
+				       &mime_info_cache_dir_item_spec_mime_info_cache);
+      mime_info_cache_dir_build_cache (dir, &dir->defaults_list,
+				       &mime_info_cache_dir_item_spec_defaults_list);
+      mime_info_cache_dir_build_cache (dir, &dir->mimeapps_list,
+				       &mime_info_cache_dir_item_spec_mimeapps_list);
       
       tmp = tmp->next;
     }
@@ -2575,17 +2442,17 @@ get_all_desktop_entries_for_mime_type (const char *base_mime_type,
 	  dir = dir_list->data;
 
 	  /* First added associations from mimeapps.list */
-	  default_entries = g_hash_table_lookup (dir->mimeapps_list_added_map, mime_type);
+	  default_entries = g_hash_table_lookup (dir->mimeapps_list.map[0], mime_type);
 	  for (j = 0; default_entries != NULL && default_entries[j] != NULL; j++)
 	    desktop_entries = append_desktop_entry (desktop_entries, default_entries[j], removed_entries);
 
 	  /* Then removed associations from mimeapps.list */
-	  removed_associations = g_hash_table_lookup (dir->mimeapps_list_removed_map, mime_type);
+	  removed_associations = g_hash_table_lookup (dir->mimeapps_list.map[1], mime_type);
 	  for (j = 0; removed_associations != NULL && removed_associations[j] != NULL; j++)
 	    removed_entries = append_desktop_entry (removed_entries, removed_associations[j], NULL);
 
 	  /* Then system defaults (or old per-user config) (using removed associations from this dir or earlier) */
-	  default_entries = g_hash_table_lookup (dir->defaults_list_map, mime_type);
+	  default_entries = g_hash_table_lookup (dir->defaults_list.map[0], mime_type);
 	  for (j = 0; default_entries != NULL && default_entries[j] != NULL; j++)
 	    desktop_entries = append_desktop_entry (desktop_entries, default_entries[j], removed_entries);
 	}
@@ -2597,7 +2464,7 @@ get_all_desktop_entries_for_mime_type (const char *base_mime_type,
         {
 	  dir = dir_list->data;
 	
-	  list = g_hash_table_lookup (dir->mime_info_cache_map, mime_type);
+	  list = g_hash_table_lookup (dir->mime_info_cache.map[0], mime_type);
 	  for (tmp = list; tmp != NULL; tmp = tmp->next)
 	    desktop_entries = append_desktop_entry (desktop_entries, tmp->data, removed_entries);
         }
