This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 3/5] remove deleted BFDs from the archive cache


On Fri, Aug 03, 2012 at 08:54:40AM -0600, Tom Tromey wrote:
> I could not find a way to look up the member BFD in its parent cache
> directly, hence the iteration.

You've made closing an archive O(n^2) on number of elements.  That I
dislike enough to NAK the patch.

Here's something I hacked together to go a little further than your
patch and actually close archive member bfds when the archive is
closed.  You'll see I solved the problem of looking up the member BFD
by saving the filepos in arelt_data.  What I haven't done is make this
all work with thin archives, but that shouldn't be too hard.  
Just a matter of adding a field to struct areltdata instead of
reusing "origin", and solving the fact that my_archive isn't set for
thin archives, I think.  Care to run with this?

Index: bfd/archive.c
===================================================================
RCS file: /cvs/src/src/bfd/archive.c,v
retrieving revision 1.87
diff -u -p -r1.87 archive.c
--- bfd/archive.c	13 Jul 2012 14:22:42 -0000	1.87
+++ bfd/archive.c	3 Aug 2012 14:59:07 -0000
@@ -316,7 +316,8 @@ _bfd_look_for_bfd_in_cache (bfd *arch_bf
 static hashval_t
 hash_file_ptr (const void * p)
 {
-  return (hashval_t) (((struct ar_cache *) p)->ptr);
+  struct ar_cache *ent = (struct ar_cache *) p;
+  return (hashval_t) ent->ptr;
 }
 
 /* Returns non-zero if P1 and P2 are equal.  */
@@ -422,8 +423,6 @@ get_extended_arelt_filename (bfd *arch, 
 	}
       *originp = origin;
     }
-  else
-    *originp = 0;
 
   return bfd_ardata (arch)->extended_names + table_index;
 }
@@ -687,6 +686,7 @@ _bfd_get_elt_at_filepos (bfd *archive, f
     {
       n_nfd->origin = n_nfd->proxy_origin;
       n_nfd->filename = filename;
+      new_areldata->origin = filepos;
     }
 
   n_nfd->arelt_data = new_areldata;
@@ -2682,3 +2682,58 @@ coff_write_armap (bfd *arch,
 
   return TRUE;
 }
+
+static int
+archive_close_worker (void **slot, void *inf ATTRIBUTE_UNUSED)
+{
+  struct ar_cache *ent = (struct ar_cache *) *slot;
+
+  bfd_close_all_done (ent->arbfd);
+  return 1;
+}
+
+bfd_boolean
+_bfd_archive_close_and_cleanup (bfd *abfd)
+{
+  if (bfd_check_format (abfd, bfd_archive))
+    {
+      bfd *nbfd;
+      bfd *next;
+      htab_t htab;
+
+      /* Close nested archives (if this bfd is a thin archive).  */
+      for (nbfd = abfd->nested_archives; nbfd; nbfd = next)
+	{
+	  next = nbfd->archive_next;
+	  bfd_close (nbfd);
+	}
+
+      htab = bfd_ardata (abfd)->cache;
+      if (htab)
+	{
+	  htab_traverse_noresize (htab, archive_close_worker, NULL);
+	  htab_delete (htab);
+	  bfd_ardata (abfd)->cache = NULL;
+	}
+    }
+  else if (abfd->my_archive != NULL)
+    {
+      htab_t htab = bfd_ardata (abfd->my_archive)->cache;
+
+      if (htab)
+	{
+	  struct ar_cache ent;
+	  void **slot;
+	  struct areltdata *ared = arch_eltdata (abfd);
+
+	  ent.ptr = ared->origin;
+	  slot = htab_find_slot (htab, &ent, NO_INSERT);
+	  if (slot != NULL)
+	    {
+	      BFD_ASSERT (((struct ar_cache *) *slot)->arbfd == abfd);
+	      htab_clear_slot (htab, slot);
+	    }
+	}
+    }
+  return TRUE;
+}
Index: bfd/libbfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd-in.h,v
retrieving revision 1.99
diff -u -p -r1.99 libbfd-in.h
--- bfd/libbfd-in.h	24 Jul 2012 21:06:58 -0000	1.99
+++ bfd/libbfd-in.h	3 Aug 2012 14:59:10 -0000
@@ -232,7 +232,9 @@ int bfd_generic_stat_arch_elt
 /* Generic routines to use for BFD_JUMP_TABLE_GENERIC.  Use
    BFD_JUMP_TABLE_GENERIC (_bfd_generic).  */
 
-#define _bfd_generic_close_and_cleanup bfd_true
+#define _bfd_generic_close_and_cleanup _bfd_archive_close_and_cleanup
+extern bfd_boolean _bfd_archive_close_and_cleanup
+  (bfd *);
 #define _bfd_generic_bfd_free_cached_info bfd_true
 extern bfd_boolean _bfd_generic_new_section_hook
   (bfd *, asection *);
Index: bfd/opncls.c
===================================================================
RCS file: /cvs/src/src/bfd/opncls.c,v
retrieving revision 1.69
diff -u -p -r1.69 opncls.c
--- bfd/opncls.c	29 May 2012 14:23:33 -0000	1.69
+++ bfd/opncls.c	3 Aug 2012 14:59:11 -0000
@@ -707,8 +707,6 @@ bfd_boolean
 bfd_close (bfd *abfd)
 {
   bfd_boolean ret;
-  bfd *nbfd;
-  bfd *next;
 
   if (bfd_write_p (abfd))
     {
@@ -716,13 +714,6 @@ bfd_close (bfd *abfd)
 	return FALSE;
     }
 
-  /* Close nested archives (if this bfd is a thin archive).  */
-  for (nbfd = abfd->nested_archives; nbfd; nbfd = next)
-    {
-      next = nbfd->archive_next;
-      bfd_close (nbfd);
-    }
-
   if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
     return FALSE;
 

-- 
Alan Modra
Australia Development Lab, IBM


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]