diff mbox

[pph] Add registry for open PPH images (issue5540067)

Message ID 20120117151540.E6842AE1D7@tobiano.tor.corp.google.com
State New
Headers show

Commit Message

Diego Novillo Jan. 17, 2012, 3:15 p.m. UTC
This patch adds a centralized registry for all open PPH
images.  This has three different uses:

   1- To associate header pathnames (HEADER_NAME field in
      pph_stream) and images.  Used for looking up PPH streams from
      header names (e.g., pph_out_line_table_and_includes).

   2- To associate PPH file names (NAME field in pph_stream) and
      images.  Used for deciding whether a PPH file has been
      opened already (e.g., pph_stream_open).

   3- To look for symbols and types in the pickle cache of opened
      PPH streams (e.g., pph_cache_lookup_in_includes).

We used to have a simple VEC array that we would always traverse
looking for an image.  But this is slow and we sometimes need to
lookup PPH images by the full path name of the original header file or
by the full path name of the PPH file itself.

This patch simply introduces the new registry.  It does not yet uses
it for looking up header files during line table emission.  That comes
in the next patch.

	* pph-core.c (struct pph_name_stream_map): Declare.
	(struct pph_stream_registry_d): Declare.
	(pph_stream_registry): New.
	(pph_read_images): Remove.  Update all users.
	(pph_find_stream_for): Remove.  Update all users.
	(pph_mark_stream_read): Remove.  Update all users.
	(pph_stream_register): New.
	(pph_stream_unregister): New
	(pph_stream_registry_ix_for): New.
	(pph_stream_registered_p): New.
	(pph_stream_registry_add_name): New.
	(pph_stream_registry_lookup): New.
	(pph_stream_open): Call it.
	Call pph_stream_register.
	(pph_stream_close): Call pph_stream_unregister.
	(pph_header_image_hash): New.
	(pph_header_image_eq): New.
	(pph_init): Initialize pph_stream_registry.
	(pph_streamer_finish): Free memory used by pph_stream_registry.
	* pph-in.c (pph_read_file_1): Do not call pph_mark_stream_read.
	Set STREAM->IN_MEMORY_P to true.
	* pph-streamer.h (pph_mark_stream_read): Remove.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/pph@183230 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/ChangeLog.pph                   |   25 ++++
 gcc/cp/pph-core.c                      |  195 ++++++++++++++++++++++++++++----
 gcc/cp/pph-in.c                        |    2 +-
 gcc/cp/pph-streamer.h                  |    1 -
 gcc/testsuite/g++.dg/pph/c1deepincl4.h |    6 +
 gcc/testsuite/g++.dg/pph/c2deepincl.cc |    2 +-
 gcc/testsuite/g++.dg/pph/c2deepincl3.h |    1 +
 7 files changed, 205 insertions(+), 27 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/pph/c1deepincl4.h
diff mbox

Patch

diff --git a/gcc/cp/ChangeLog.pph b/gcc/cp/ChangeLog.pph
index 8ea94b2..7e5b90f 100644
--- a/gcc/cp/ChangeLog.pph
+++ b/gcc/cp/ChangeLog.pph
@@ -1,3 +1,28 @@ 
+2012-01-16   Diego Novillo  <dnovillo@google.com>
+
+	* pph-core.c (struct pph_name_stream_map): Declare.
+	(struct pph_stream_registry_d): Declare.
+	(pph_stream_registry): New.
+	(pph_read_images): Remove.  Update all users.
+	(pph_find_stream_for): Remove.  Update all users.
+	(pph_mark_stream_read): Remove.  Update all users.
+	(pph_stream_register): New.
+	(pph_stream_unregister): New
+	(pph_stream_registry_ix_for): New.
+	(pph_stream_registered_p): New.
+	(pph_stream_registry_add_name): New.
+	(pph_stream_registry_lookup): New.
+	(pph_stream_open): Call it.
+	Call pph_stream_register.
+	(pph_stream_close): Call pph_stream_unregister.
+	(pph_header_image_hash): New.
+	(pph_header_image_eq): New.
+	(pph_init): Initialize pph_stream_registry.
+	(pph_streamer_finish): Free memory used by pph_stream_registry.
+	* pph-in.c (pph_read_file_1): Do not call pph_mark_stream_read.
+	Set STREAM->IN_MEMORY_P to true.
+	* pph-streamer.h (pph_mark_stream_read): Remove.
+
 2012-01-13   Diego Novillo  <dnovillo@google.com>
 
 	* pph-in.c (pph_in_line_table_and_includes): Fix computation of
diff --git a/gcc/cp/pph-core.c b/gcc/cp/pph-core.c
index 1cd202a..57dc53d 100644
--- a/gcc/cp/pph-core.c
+++ b/gcc/cp/pph-core.c
@@ -49,6 +49,46 @@  along with GCC; see the file COPYING3.  If not see
 #include "streamer-hooks.h"
 
 
+/* Mapping between a name string and the registry index for the
+   corresponding PPH image.  */
+struct pph_name_stream_map {
+  const char *name;
+  unsigned ix;
+};
+
+/* Registry of all the PPH images opened during this compilation.
+   This registry is used in three different ways:
+
+    1- To associate header pathnames (HEADER_NAME field in
+       pph_stream) and images.  Used for looking up PPH streams from
+       header names (e.g., pph_out_line_table_and_includes).
+
+    2- To associate PPH file names (NAME field in pph_stream) and
+       images.  Used for deciding whether a PPH file has been
+       opened already (e.g., pph_stream_open).
+
+    3- To look for symbols and types in the pickle cache of opened
+       PPH streams (e.g., pph_cache_lookup_in_includes).
+
+   This registry is needed because images opened during #include
+   processing and opened from pph_in_includes cannot be closed
+   immediately after reading, because the pickle cache contained in
+   them may be referenced from other images.  We delay closing all of
+   them until the end of parsing (when pph_streamer_finish is called).  */
+struct pph_stream_registry_d {
+  /* Map between names and images.  */
+  htab_t name_ix;
+
+  /* Index of all registered PPH images.  */
+  struct pointer_map_t *image_ix;
+
+  /* List of registered PPH images.  */
+  VEC(pph_stream_ptr, heap) *v;
+};
+
+static struct pph_stream_registry_d pph_stream_registry;
+
+
 /*************************************************************** pph logging */
 
 
@@ -815,38 +855,113 @@  pph_loaded (void)
 /*********************************************************** stream handling */
 
 
-/* List of PPH images opened for reading.  Images opened during #include
-   processing and opened from pph_in_includes cannot be closed
-   immediately after reading, because the pickle cache contained in
-   them may be referenced from other images.  We delay closing all of
-   them until the end of parsing (when pph_streamer_finish is called).  */
-static VEC(pph_stream_ptr, heap) *pph_read_images = NULL;
+/* Register STREAM in the table of open streams.  */
 
+static void
+pph_stream_register (pph_stream *stream)
+{
+  void **slot;
+  unsigned vlen;
 
-/* If FILENAME has already been read, return the stream associated with it.  */
+  slot = pointer_map_insert (pph_stream_registry.image_ix, stream);
 
-static pph_stream *
-pph_find_stream_for (const char *filename)
+  /* Disallow multpile registration of the same STREAM.  This is overly
+     strict, but it prevents some unnecessary overhead.  */
+  gcc_assert (*slot == NULL);
+
+  VEC_safe_push (pph_stream_ptr, heap, pph_stream_registry.v, stream);
+  vlen = VEC_length (pph_stream_ptr, pph_stream_registry.v);
+  *slot = (void *)(intptr_t) (vlen - 1);
+}
+
+
+/* Unregister STREAM from the table of open streams.  */
+
+static void
+pph_stream_unregister (pph_stream *stream)
 {
-  pph_stream *include;
-  unsigned i;
+  void **slot;
+  unsigned ix;
+
+  slot = pointer_map_contains (pph_stream_registry.image_ix, stream);
+  gcc_assert (slot);
+  ix = (unsigned)(intptr_t) *slot;
 
-  /* FIXME pph, implement a hash map to avoid this linear search.  */
-  FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, include)
-    if (strcmp (include->name, filename) == 0)
-      return include;
+  /* Mark it unregistered in the image index.  */
+  *slot = (void *)(intptr_t) -1;
 
-  return NULL;
+  /* Remove it from the image list.  Note that we do not need to
+     remove the index from the name index.  Any further lookups will
+     simply return NULL.  */
+  VEC_replace (pph_stream_ptr, pph_stream_registry.v, ix, NULL);
 }
 
 
-/* Add STREAM to the list of read images.  */
+/* Return the index into the registry for STREAM.  If STREAM has not been
+   registered yet, return -1.  */
+
+static unsigned
+pph_stream_registry_ix_for (pph_stream *stream)
+{
+  void **slot;
+
+  slot = pointer_map_contains (pph_stream_registry.image_ix, stream);
+  if (slot == NULL)
+    return (unsigned) -1;
+
+  return (unsigned)(intptr_t) *slot;
+}
+
+
+/* Return true if STREAM has been registered.  */
+
+static bool
+pph_stream_registered_p (pph_stream *stream)
+{
+  return pph_stream_registry_ix_for (stream) == -1u;
+}
+
+
+/* Associate string NAME with the registry entry for STREAM.  */
 
 void
-pph_mark_stream_read (pph_stream *stream)
+pph_stream_registry_add_name (pph_stream *stream, const char *name)
+{
+  void **slot;
+  pph_name_stream_map e;
+
+  /* STREAM should have been registered beforehand.  */
+  gcc_assert (pph_stream_registered_p (stream));
+
+  /* Now associate NAME to STREAM.  */
+  e.name = name;
+  e.ix = pph_stream_registry_ix_for (stream);
+  slot = htab_find_slot (pph_stream_registry.name_ix, &e, INSERT);
+  gcc_assert (*slot == NULL);
+  memcpy ((pph_name_stream_map *) *slot, &e, sizeof (e));
+}
+
+
+/* Return the PPH stream associated with NAME.  Return NULL if no such
+   mapping exist.  */
+
+pph_stream *
+pph_stream_registry_lookup (const char *name)
 {
-  stream->in_memory_p = true;
-  VEC_safe_push (pph_stream_ptr, heap, pph_read_images, stream);
+  void **slot;
+  intptr_t slot_ix;
+  pph_name_stream_map e;
+
+  e.name = name;
+  e.ix = -1u;
+  slot = htab_find_slot (pph_stream_registry.name_ix, &e, NO_INSERT);
+  if (slot == NULL)
+    return NULL;
+
+  slot_ix = (intptr_t) *slot;
+  gcc_assert (slot_ix == (intptr_t)(unsigned) slot_ix);
+  e.ix = (unsigned) slot_ix;
+  return VEC_index (pph_stream_ptr, pph_stream_registry.v, e.ix);
 }
 
 
@@ -861,7 +976,7 @@  pph_stream_open (const char *name, const char *mode)
 
   /* If we have already opened a PPH stream named NAME, just return
      its associated stream.  */
-  stream = pph_find_stream_for (name);
+  stream = pph_stream_registry_lookup (name);
   if (stream)
     {
       gcc_assert (stream->in_memory_p);
@@ -883,6 +998,9 @@  pph_stream_open (const char *name, const char *mode)
   else
     pph_init_read (stream);
 
+  /* Register STREAM in the table of all open streams.  */
+  pph_stream_register (stream);
+
   return stream;
 }
 
@@ -932,6 +1050,9 @@  pph_stream_close (pph_stream *stream)
       free (stream->encoder.r.file_data);
     }
 
+  /* Unregister STREAM.  */
+  pph_stream_unregister (stream);
+
   free (stream);
 }
 
@@ -1014,9 +1135,26 @@  pph_streamer_init (void)
 
 /* The initial order of the size of the lexical lookaside table,
    which will accomodate as many as half of its slots in use.  */
-
 static const unsigned int cpp_lt_order = /* 2 to the power of */ 9;
 
+
+/* Hash and comparison functions for pph_stream_registry.  */
+
+static hashval_t
+pph_header_image_hash (const void *p)
+{
+  return htab_hash_string (((const struct pph_name_stream_map *)p)->name);
+}
+
+static int
+pph_header_image_eq (const void *p1, const void *p2)
+{
+  const char *name1 = ((const struct pph_name_stream_map *)p1)->name;
+  const char *name2 = ((const struct pph_name_stream_map *)p2)->name;
+  return (name1 == name2 || strcmp (name1, name2) == 0);
+}
+
+
 /* Initialize PPH support.  */
 
 void
@@ -1045,6 +1183,12 @@  pph_init (void)
                            cpp_lt_create (cpp_lt_order, flag_pph_debug/2));
   gcc_assert (table == NULL);
 
+  /* Set up the PPH registry.  */
+  pph_stream_registry.name_ix = htab_create (10, pph_header_image_hash,
+				              pph_header_image_eq, NULL);
+  pph_stream_registry.image_ix = pointer_map_create ();
+  pph_stream_registry.v = NULL;
+
   pph_streamer_init ();
 
   /* If we are generating a PPH file, initialize the writer.  */
@@ -1073,10 +1217,13 @@  pph_streamer_finish (void)
   pph_reader_finish ();
 
   /* Close any images read during parsing.  */
-  FOR_EACH_VEC_ELT (pph_stream_ptr, pph_read_images, i, image)
+  FOR_EACH_VEC_ELT (pph_stream_ptr, pph_stream_registry.v, i, image)
     pph_stream_close (image);
 
-  VEC_free (pph_stream_ptr, heap, pph_read_images);
+  /* Free all memory used by the stream registry.  */
+  VEC_free (pph_stream_ptr, heap, pph_stream_registry.v);
+  pointer_map_destroy (pph_stream_registry.image_ix);
+  htab_delete (pph_stream_registry.name_ix);
 }
 
 
diff --git a/gcc/cp/pph-in.c b/gcc/cp/pph-in.c
index aba7be0..a67ffa7 100644
--- a/gcc/cp/pph-in.c
+++ b/gcc/cp/pph-in.c
@@ -2892,7 +2892,7 @@  pph_read_file_1 (pph_stream *stream)
 
   /* Mark this file as read.  If other images need to access its contents,
      we will not need to actually read it again.  */
-  pph_mark_stream_read (stream);
+  stream->in_memory_p = true;
 
   if (flag_pph_dump_tree)
     pph_dump_namespace (pph_logfile, global_namespace);
diff --git a/gcc/cp/pph-streamer.h b/gcc/cp/pph-streamer.h
index 0b8af3d..a32d0fe 100644
--- a/gcc/cp/pph-streamer.h
+++ b/gcc/cp/pph-streamer.h
@@ -251,7 +251,6 @@  enum pph_trace_end
 const char *pph_tree_code_text (enum tree_code code);
 void pph_dump_namespace (FILE *, tree ns);
 pph_stream *pph_stream_open (const char *, const char *);
-void pph_mark_stream_read (pph_stream *);
 void pph_stream_close (pph_stream *);
 void pph_add_include (pph_stream *, pph_stream *);
 void pph_trace_marker (enum pph_record_marker marker, enum pph_tag tag);
diff --git a/gcc/testsuite/g++.dg/pph/c1deepincl4.h b/gcc/testsuite/g++.dg/pph/c1deepincl4.h
new file mode 100644
index 0000000..57e15d6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pph/c1deepincl4.h
@@ -0,0 +1,6 @@ 
+#ifndef C1DEEPINCL4_H
+#define C1DEEPINCL4_H
+
+int b4 = 1;
+
+#endif
diff --git a/gcc/testsuite/g++.dg/pph/c2deepincl.cc b/gcc/testsuite/g++.dg/pph/c2deepincl.cc
index bbf9402..9e63887 100644
--- a/gcc/testsuite/g++.dg/pph/c2deepincl.cc
+++ b/gcc/testsuite/g++.dg/pph/c2deepincl.cc
@@ -1,5 +1,5 @@ 
 #include "c2deepincl3.h"
 
 int test() {
-    return a + b + c;
+    return a + b + c * b4;
 }
diff --git a/gcc/testsuite/g++.dg/pph/c2deepincl3.h b/gcc/testsuite/g++.dg/pph/c2deepincl3.h
index d3a1522..3c4f6a4 100644
--- a/gcc/testsuite/g++.dg/pph/c2deepincl3.h
+++ b/gcc/testsuite/g++.dg/pph/c2deepincl3.h
@@ -2,6 +2,7 @@ 
 #define C2DEEPINCL3_H
 
 #include "c1deepincl2.h"
+#include "c1deepincl4.h"
 
 int c = 2;