OSDN Git Service

merge branch profile-stdlib
authorrus <rus@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 Oct 2009 02:17:41 +0000 (02:17 +0000)
committerrus <rus@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 3 Oct 2009 02:17:41 +0000 (02:17 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@152431 138bc75d-0d04-0410-961f-82ee72b054a4

58 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/config.h.in
libstdc++-v3/configure
libstdc++-v3/doc/Makefile.am
libstdc++-v3/doc/Makefile.in
libstdc++-v3/doc/doxygen/user.cfg.in
libstdc++-v3/doc/xml/manual/debug.xml
libstdc++-v3/doc/xml/manual/extensions.xml
libstdc++-v3/doc/xml/manual/profile_mode.xml [new file with mode: 0644]
libstdc++-v3/include/Makefile.am
libstdc++-v3/include/Makefile.in
libstdc++-v3/include/backward/hash_map
libstdc++-v3/include/backward/hash_set
libstdc++-v3/include/bits/c++config
libstdc++-v3/include/profile/base.h [new file with mode: 0644]
libstdc++-v3/include/profile/bitset [new file with mode: 0644]
libstdc++-v3/include/profile/deque [new file with mode: 0644]
libstdc++-v3/include/profile/hashtable.h [new file with mode: 0644]
libstdc++-v3/include/profile/impl/profiler.h [new file with mode: 0644]
libstdc++-v3/include/profile/impl/profiler_container_size.h [new file with mode: 0644]
libstdc++-v3/include/profile/impl/profiler_hash_func.h [new file with mode: 0644]
libstdc++-v3/include/profile/impl/profiler_hashtable_size.h [new file with mode: 0644]
libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h [new file with mode: 0644]
libstdc++-v3/include/profile/impl/profiler_node.h [new file with mode: 0644]
libstdc++-v3/include/profile/impl/profiler_state.h [new file with mode: 0644]
libstdc++-v3/include/profile/impl/profiler_trace.h [new file with mode: 0644]
libstdc++-v3/include/profile/impl/profiler_vector_size.h [new file with mode: 0644]
libstdc++-v3/include/profile/impl/profiler_vector_to_list.h [new file with mode: 0644]
libstdc++-v3/include/profile/list [new file with mode: 0644]
libstdc++-v3/include/profile/map [new file with mode: 0644]
libstdc++-v3/include/profile/map.h [new file with mode: 0644]
libstdc++-v3/include/profile/multimap.h [new file with mode: 0644]
libstdc++-v3/include/profile/multiset.h [new file with mode: 0644]
libstdc++-v3/include/profile/set [new file with mode: 0644]
libstdc++-v3/include/profile/set.h [new file with mode: 0644]
libstdc++-v3/include/profile/unordered_map [new file with mode: 0644]
libstdc++-v3/include/profile/unordered_set [new file with mode: 0644]
libstdc++-v3/include/profile/vector [new file with mode: 0644]
libstdc++-v3/include/std/bitset
libstdc++-v3/include/std/deque
libstdc++-v3/include/std/list
libstdc++-v3/include/std/map
libstdc++-v3/include/std/set
libstdc++-v3/include/std/unordered_map
libstdc++-v3/include/std/unordered_set
libstdc++-v3/include/std/vector
libstdc++-v3/include/tr1_impl/hashtable
libstdc++-v3/testsuite/23_containers/deque/capacity/moveable.cc
libstdc++-v3/testsuite/23_containers/list/capacity/29134.cc
libstdc++-v3/testsuite/23_containers/unordered_map/profile/hash_map.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/unordered_map/profile/unordered.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/vector/profile/vector.cc [new file with mode: 0644]
libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc
libstdc++-v3/testsuite/Makefile.am
libstdc++-v3/testsuite/Makefile.in
libstdc++-v3/testsuite/ext/profile/all.cc [new file with mode: 0644]
libstdc++-v3/testsuite/ext/profile/mh.cc [new file with mode: 0644]
libstdc++-v3/testsuite/ext/profile/mutex_extensions.cc [new file with mode: 0644]

index 860b200..a68aec5 100644 (file)
@@ -1,3 +1,64 @@
+2009-10-02  Silvius Rus  <silvius.rus@gmail.com>
+       * configure: Add check for execinfo.h.
+       * config.h.in: Add undef for HAVE_EXECINFO_H.
+       * include/Makefile.am: Add build support for profile mode.
+       * include/Makefile.in: Same.
+       * include/profile/base.h: New file.
+       * include/profile/bitset: Same.
+       * include/profile/deque: Same.
+       * include/profile/hashtable.h: Same.
+       * include/profile/list: Same.
+       * include/profile/map: Same.
+       * include/profile/map.h: Same.
+       * include/profile/multimap.h: Same.
+       * include/profile/multiset.h: Same.
+       * include/profile/set: Same.
+       * include/profile/set.h: Same.
+       * include/profile/unordered_map: Same.
+       * include/profile/unordered_set: Same.
+       * include/profile/vector: Same.
+       * include/profile/impl/profiler.h: Same.
+       * include/profile/impl/profiler_container_size.h: Same.
+       * include/profile/impl/profiler_hash_func.h: Same.
+       * include/profile/impl/profiler_hashtable_size.h: Same.
+       * include/profile/impl/profiler_map_to_unordered_map.h: Same.
+       * include/profile/impl/profiler_node.h: Same.
+       * include/profile/impl/profiler_state.h: Same.
+       * include/profile/impl/profiler_trace.h: Same.
+       * include/profile/impl/profiler_vector_size.h: Same.
+       * include/profile/impl/profiler_vector_to_list.h: Same.
+       * include/std/vector: Include corresponding profile header guarded by 
+       _GLIBCXX_PROFILE.
+       * include/std/deque: Same.
+       * include/std/list: Same.
+       * include/std/map: Same.
+       * include/std/unordered_map: Same.
+       * include/std/bitset: Same.
+       * include/std/set: Same.
+       * include/std/unordered_set: Same.
+       * include/backward/hash_map: Same.
+       * include/backward/hash_set: Same.
+       * include/tr1_impl/hashtable (_Hashtable): Expose insert_return_type.
+       * include/bits/c++config: Define profile namespace.
+       * testsuite/Makefile.in: Add check-profile.
+       * testsuite/Makefile.am: Same.
+       * testsuite/ext/profile/all.cc: New file.
+       * testsuite/ext/profile/mh.cc: Same.
+       * testsuite/ext/profile/mutex_extensions.cc: Same.
+       * testsuite/23_containers/unordered_map/profile/hash_map.cc: Same.
+       * testsuite/23_containers/unordered_map/profile/unordered.cc: Same.
+       * testsuite/23_containers/vector/profile/vector.cc: Same.
+       * testsuite/23_containers/vector/resize/moveable.cc: Make it pass
+       in profile mode.
+       * testsuite/23_containers/deque/capacity/moveable.cc: Same.
+       * testsuite/23_containers/list/capacity/29134.cc: Same.
+       * doc/Makefile.in: Add reference to profile_mode.xml.
+       * doc/Makefile.am: Same.
+       * doc/xml/manual/profile_mode.xml: New file.
+       * doc/xml/manual/debug.xml: Add link to profile mode section.
+       * doc/xml/manual/extensions.xml: Add profile mode.  Update numbering.
+       * doc/doxygen/user.cfg.in: Add profile mode files.
+
 2009-10-02  Johannes Singler  <singler@ira.uka.de>
 
         * include/parallel/base.h: Take integer types from <tr1/cstdint>.
index 41cf967..506b00e 100644 (file)
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
+/* Define to 1 if you have the <execinfo.h> header file. */
+#undef HAVE_EXECINFO_H
+
 /* Define to 1 if you have the `modf' function. */
 #undef HAVE_MODF
 
index 1eb77d1..0ba287c 100755 (executable)
@@ -7926,7 +7926,7 @@ fi
 
 # On IRIX 5.3, sys/types and inttypes.h are conflicting.
 for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
-                 inttypes.h stdint.h unistd.h
+                 inttypes.h stdint.h unistd.h execinfo.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
index d53ae22..22c549c 100644 (file)
@@ -100,6 +100,7 @@ xml_sources = \
        ${xml_srcdir}/manual/numerics.xml \
        ${xml_srcdir}/manual/parallel_mode.xml \
        ${xml_srcdir}/manual/prerequisites.xml \
+       ${xml_srcdir}/manual/profile_mode.xml \
        ${xml_srcdir}/manual/internals.xml \
        ${xml_srcdir}/manual/shared_ptr.xml \
        ${xml_srcdir}/manual/spine.xml \
index 6eccd89..fd56f3c 100644 (file)
@@ -312,6 +312,7 @@ xml_sources = \
        ${xml_srcdir}/manual/numerics.xml \
        ${xml_srcdir}/manual/parallel_mode.xml \
        ${xml_srcdir}/manual/prerequisites.xml \
+       ${xml_srcdir}/manual/profile_mode.xml \
        ${xml_srcdir}/manual/internals.xml \
        ${xml_srcdir}/manual/shared_ptr.xml \
        ${xml_srcdir}/manual/spine.xml \
index 9c4b6c9..9ffcf1e 100644 (file)
@@ -661,6 +661,25 @@ INPUT                  = @srcdir@/doc/doxygen/doxygroups.cc \
                          include/debug/unordered_map \
                          include/debug/unordered_set \
                          include/debug/vector \
+                         include/profile/bitset \
+                         include/profile/deque \
+                         include/profile/list \
+                         include/profile/map \
+                         include/profile/set \
+                         include/profile/unordered_map \
+                         include/profile/unordered_set \
+                         include/profile/vector \
+                         include/profile/base.h \
+                         include/profile/impl/profiler.h \
+                         include/profile/impl/profiler_container_size.h \
+                         include/profile/impl/profiler_hash_func.h \
+                         include/profile/impl/profiler_hashtable_size.h \
+                         include/profile/impl/profiler_map_to_unordered_map.h \
+                         include/profile/impl/profiler_node.h \
+                         include/profile/impl/profiler_state.h \
+                         include/profile/impl/profiler_trace.h \
+                         include/profile/impl/profiler_vector_size.h \
+                         include/profile/impl/profiler_vector_to_list.h \
                          include/ext/algorithm \
                          include/ext/functional \
                          include/ext/iterator \
@@ -715,6 +734,7 @@ INPUT                  = @srcdir@/doc/doxygen/doxygroups.cc \
                          include/bits/shared_ptr.h \
                          include/debug \
                          include/parallel \
+                         include/profile \
                          include/ext \
                          include/ext/pb_ds \
                          include/ext/pb_ds/detail 
index 273196e..8aa5307 100644 (file)
   </para>
 </sect2>
 
+<sect2 id="debug.profile_mode" xreflabel="debug.profile_mode">
+<title>Profile-based Performance Analysis</title>
+  <para> The <link linkend="manual.ext.profile_mode">Profile-based 
+  Performance Analysis</link> Extension has performance checks for many 
+  algorithms.
+  </para>
+</sect2>
+
 </sect1>
index 82e9100..889fe1d 100644 (file)
@@ -113,7 +113,13 @@ extensions, be aware of two things:
            parse="xml" href="parallel_mode.xml">
 </xi:include>
 
-<!-- Chapter 04 : Allocators -->
+<!-- Chapter 04 : Profile Mode -->
+<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" 
+           parse="xml" href="profile_mode.xml">
+</xi:include>
+
+
+<!-- Chapter 05 : Allocators -->
 <chapter id="manual.ext.allocator" xreflabel="Allocators">
 <?dbhtml filename="ext_allocators.html"?>
   <title>Allocators</title>
@@ -130,7 +136,7 @@ extensions, be aware of two things:
 
 </chapter>
 
-<!-- Chapter 05 : Containers -->
+<!-- Chapter 06 : Containers -->
 <chapter id="manual.ext.containers" xreflabel="Containers">
 <?dbhtml filename="ext_containers.html"?>
   <title>Containers</title>
@@ -266,7 +272,7 @@ extensions, be aware of two things:
   </sect1>  
 </chapter>
 
-<!-- Chapter 06 : Utilities -->
+<!-- Chapter 07 : Utilities -->
 <chapter id="manual.ext.util" xreflabel="Utilities">
 <?dbhtml filename="ext_utilities.html"?>
   <title>Utilities</title>
@@ -336,7 +342,7 @@ get_temporary_buffer(5, (int*)0);
 
 </chapter>
 
-<!-- Chapter 07 : Algorithms -->
+<!-- Chapter 08 : Algorithms -->
 <chapter id="manual.ext.algorithms" xreflabel="Algorithms">
 <?dbhtml filename="ext_algorithms.html"?>
   <title>Algorithms</title>
@@ -374,7 +380,7 @@ get_temporary_buffer(5, (int*)0);
 
 </chapter>
 
-<!-- Chapter 08 : Numerics -->
+<!-- Chapter 09 : Numerics -->
 <chapter id="manual.ext.numerics" xreflabel="Numerics">
 <?dbhtml filename="ext_numerics.html"?>
   <title>Numerics</title>
@@ -399,7 +405,7 @@ get_temporary_buffer(5, (int*)0);
    void iota(_ForwardIter first, _ForwardIter last, _Tp value);</programlisting>
 </chapter>
 
-<!-- Chapter 09 : Iterators -->
+<!-- Chapter 10 : Iterators -->
 <chapter id="manual.ext.iterators" xreflabel="Iterators">
 <?dbhtml filename="ext_iterators.html"?>
   <title>Iterators</title>
@@ -423,7 +429,7 @@ get_temporary_buffer(5, (int*)0);
 
 </chapter>
 
-<!-- Chapter 08 : IO -->
+<!-- Chapter 11 : IO -->
 <chapter id="manual.ext.io" xreflabel="IO">
 <?dbhtml filename="ext_io.html"?>
   <title>Input and Output</title>
@@ -493,7 +499,7 @@ get_temporary_buffer(5, (int*)0);
   </sect1>
 </chapter>
 
-<!-- Chapter 09 : Demangling -->
+<!-- Chapter 12 : Demangling -->
 <chapter id="manual.ext.demangle" xreflabel="Demangling">
 <?dbhtml filename="ext_demangling.html"?>
   <title>Demangling</title>
@@ -579,7 +585,7 @@ int main()
    </para>
 </chapter>
 
-<!-- Chapter 10 : Concurrency -->
+<!-- Chapter 13 : Concurrency -->
 <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" 
            parse="xml" href="concurrency.xml">
 </xi:include>
diff --git a/libstdc++-v3/doc/xml/manual/profile_mode.xml b/libstdc++-v3/doc/xml/manual/profile_mode.xml
new file mode 100644 (file)
index 0000000..5bf8eb1
--- /dev/null
@@ -0,0 +1,1718 @@
+<?xml version='1.0'?>
+<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" 
+ "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" 
+[ ]>
+
+<chapter id="manual.ext.profile_mode" xreflabel="Profile Mode">
+<?dbhtml filename="profile_mode.html"?>
+<chapterinfo>
+  <keywordset>
+    <keyword>
+      C++
+    </keyword>
+    <keyword>
+      library
+    </keyword>
+    <keyword>
+      profile
+    </keyword>
+  </keywordset>
+</chapterinfo>
+
+<title>Profile Mode</title>
+
+
+<sect1 id="manual.ext.profile_mode.intro" xreflabel="Intro">
+  <title>Intro</title>
+  <para>
+  <emphasis>Goal: </emphasis>Give performance improvement advice based on
+  recognition of suboptimal usage patterns of the standard library.
+  </para>
+
+  <para>
+  <emphasis>Method: </emphasis>Wrap the standard library code.  Insert
+  calls to an instrumentation library to record the internal state of
+  various components at interesting entry/exit points to/from the standard
+  library.  Process trace, recognize suboptimal patterns, give advice.
+  For details, see 
+  <ulink url="http://dx.doi.org/10.1109/CGO.2009.36">paper presented at
+   CGO 2009</ulink>.
+  </para>
+  <para>
+  <emphasis>Strengths: </emphasis>
+<itemizedlist>
+  <listitem><para>
+  Unintrusive solution.  The application code does not require any 
+  modification.
+  </para></listitem>
+  <listitem><para> The advice is call context sensitive, thus capable of
+  identifying precisely interesting dynamic performance behavior.
+  </para></listitem>
+  <listitem><para>
+  The overhead model is pay-per-view.  When you turn off a diagnostic class
+  at compile time, its overhead disappears.
+  </para></listitem>
+</itemizedlist>
+  </para>
+  <para>
+  <emphasis>Drawbacks: </emphasis>
+<itemizedlist>
+  <listitem><para>
+  You must recompile the application code with custom options.
+  </para></listitem>
+  <listitem><para>You must run the application on representative input.
+  The advice is input dependent.
+  </para></listitem>
+  <listitem><para>
+  The execution time will increase, in some cases by factors.
+  </para></listitem>
+</itemizedlist>
+  </para>
+
+
+<sect2 id="manual.ext.profile_mode.using" xreflabel="Using">
+  <title>Using the Profile Mode</title>
+
+  <para>
+  This is the anticipated common workflow for program <code>foo.cc</code>:
+<programlisting>
+$ cat foo.cc
+#include &lt;vector&gt;
+int main() {
+  vector&lt;int&gt; v;
+  for (int k = 0; k &lt; 1024; ++k) v.insert(v.begin(), k);
+}
+
+$ g++ -D_GLIBCXX_PROFILE foo.cc
+$ ./a.out
+$ cat libstdcxx-profile.txt
+vector-to-list: improvement = 5: call stack = 0x804842c ...
+    : advice = change std::vector to std::list
+vector-size: improvement = 3: call stack = 0x804842c ...
+    : advice = change initial container size from 0 to 1024
+</programlisting>
+  </para>
+
+  <para>
+  Anatomy of a warning:
+  <itemizedlist>
+  <listitem>
+  <para>
+  Warning id.  This is a short descriptive string for the class
+  that this warning belongs to.  E.g., "vector-to-list".
+  </para>
+  </listitem>
+  <listitem>
+  <para>
+  Estimated improvement.  This is an approximation of the benefit expected
+  from implementing the change suggested by the warning.  It is given on
+  a log10 scale.  Negative values mean that the alternative would actually
+  do worse than the current choice.
+  In the example above, 5 comes from the fact that the overhead of
+  inserting at the beginning of a vector vs. a list is around 1024 * 1024 / 2,
+  which is around 10e5.  The improvement from setting the initial size to
+  1024 is in the range of 10e3, since the overhead of dynamic resizing is
+  linear in this case.
+  </para>
+  </listitem>
+  <listitem>
+  <para>
+  Call stack.  Currently, the addresses are printed without
+  symbol name or code location attribution.
+  Users are expected to postprocess the output using, for instance, addr2line.
+  </para>
+  </listitem>
+  <listitem>
+  <para>
+  The warning message.  For some warnings, this is static text, e.g.,
+  "change vector to list".  For other warnings, such as the one above,
+  the message contains numeric advice, e.g., the suggested initial size
+  of the hashtable.
+  </para>
+  </listitem>
+  </itemizedlist>
+  </para>
+
+  <para>Two files are generated.  <code>libstdcxx-profile.txt</code>
+   contains human readable advice.  <code>libstdcxx-profile.raw</code>
+   contains implementation specific data about each diagnostic.
+   Their format is not documented.  They are sufficient to generate
+   all the advice given in <code>libstdcxx-profile.txt</code>.  The advantage
+   of keeping this raw format is that traces from multiple executions can
+   be aggregated simply by concatenating the raw traces.  We intend to
+   offer an external utility program that can issue advice from a trace.
+  </para>
+
+  <para>Advice is given regardless whether the transformation is valid.
+  For instance, we advise changing a map to an unordered_map even if the
+  application semantics require that data be ordered.
+  We believe such warnings can help users understand the performance
+  behavior of their application better, which can lead to changes
+  at a higher abstraction level.
+  </para>
+
+</sect2>
+
+<sect2 id="manual.ext.profile_mode.tuning" xreflabel="Tuning">
+  <title>Tuning the Profile Mode</title>
+
+  <para>Compile time switches and environment variables (see also file
+   profiler.h).  Unless specified otherwise, they can be set at compile time
+   using -D_&lt;name&gt; or by setting variable &lt;name&gt;
+   in the environment where the program is run, before starting execution.
+  <itemizedlist>
+  <listitem><para>
+   <code>[NO]_GLIBCXX_PROFILE_&lt;diagnostic&gt;</code>:
+   enable/disable specific diagnostics.
+   See section Diagnostics for possible values.
+   (Environment variables not supported.)
+   </para></listitem>
+  <listitem><para>
+   <code>GLIBCXX_PROFILE_TRACE_PATH_ROOT</code>: set an alternative root
+   path for the output files.
+   </para></listitem>
+  <listitem><para>GLIBCXX_PROFILE_MAX_WARN_COUNT: set it to the maximum
+   number of warnings desired.  The default value is 10.</para></listitem>
+  <listitem><para>
+   <code>GLIBCXX_PROFILE_MAX_STACK_DEPTH</code>: if set to 0, 
+   the advice will
+   be collected and reported for the program as a whole, and not for each
+   call context.
+   This could also be used in continuous regression tests, where you
+   just need to know whether there is a regression or not.
+   The default value is 32.
+   </para></listitem>
+  <listitem><para>
+   <code>GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC</code>:
+   set a limit on how much memory to use for the accounting tables for each
+   diagnostic type.  When this limit is reached, new events are ignored
+   until the memory usage decreases under the limit.  Generally, this means
+   that newly created containers will not be instrumented until some
+   live containers are deleted.  The default is 128 MB.
+   </para></listitem>
+  <listitem><para>
+   <code>GLIBCXX_PROFILE_NOTHREADS</code>:
+   Make the library not use threads.  Otherwise, pthread mutexes are used
+   to protect access to internal data structures.  This should be useful
+   only if the program is single threaded and you want to avoid the overhead
+   of aquiring/releasing locks unnecessarily.
+   (Environment variable not supported.)
+   </para></listitem>
+  <listitem><para>
+   <code>HAVE_EXECINFO_H</code>:
+   This name should be defined at library configuration time.
+   If your library was configured without <code>execinfo.h</code>, but
+   you have it in your include path, you can define it explicitly.  Without
+   it, advice is collected for the program as a whole, and not for each
+   call context.
+   (Environment variable not supported.)
+   </para></listitem>
+  </itemizedlist>
+  </para>
+
+</sect2>
+
+</sect1>
+
+
+<sect1 id="manual.ext.profile_mode.design" xreflabel="Design">
+  <title>Design</title>
+
+<para>
+</para>
+<table frame='all'>
+<title>Code Location</title>
+<tgroup cols='2' align='left' colsep='1' rowsep='1'>
+<colspec colname='c1'></colspec>
+<colspec colname='c2'></colspec>
+
+<thead>
+  <row>
+    <entry>Code Location</entry>
+    <entry>Use</entry>
+  </row>
+</thead>
+<tbody>
+  <row>
+    <entry><code>libstdc++-v3/include/std/*</code></entry>
+    <entry>Preprocessor code to redirect to profile extension headers.</entry>
+  </row>
+  <row>
+    <entry><code>libstdc++-v3/include/profile/*</code></entry>
+    <entry>Profile extension public headers (map, vector, ...).</entry>
+  </row>
+  <row>
+    <entry><code>libstdc++-v3/include/profile/impl/*</code></entry>
+    <entry>Profile extension internals.  Implementation files are
+     only included from <code>impl/profiler.h</code>, which is the only
+     file included from the public headers.</entry>
+  </row>
+</tbody>
+</tgroup>
+</table>
+
+<para>
+</para>
+
+<sect2 id="manual.ext.profile_mode.design.wrapper" 
+ xreflabel="Wrapper">
+<title>Wrapper Model</title>
+  <para>
+  In order to get our instrumented library version included instead of the
+  release one,
+  we use the same wrapper model as the debug mode.
+  We subclass entities from the release version.  Wherever
+  <code>_GLIBCXX_PROFILE</code> is defined, the release namespace is
+  <code>std::__norm</code>, whereas the profile namespace is 
+  <code>std::__profile</code>.  Using plain <code>std</code> translates
+  into <code>std::__profile</code>.
+  </para>
+  <para>
+  Whenever possible, we try to wrap at the public interface level, e.g.,
+  in <code>unordered_set</code> rather than in <code>hashtable</code>, 
+  in order not to depend on implementation.
+  </para>
+  <para>
+  Mixing object files built with and without the profile mode must
+  not affect the program execution.  However, there are no guarantees to
+  the accuracy of diagnostics when using even a single object not built with
+  <code>-D_GLIBCXX_PROFILE</code>.
+  Currently, mixing the profile mode with debug and parallel extensions is
+  not allowed.  Mixing them at compile time will result in preprocessor errors.
+  Mixing them at link time is undefined.
+  </para>
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.design.instrumentation" 
+ xreflabel="Instrumentation">
+<title>Instrumentation</title>
+  <para>
+  Instead of instrumenting every public entry and exit point,
+  we chose to add instrumentation on demand, as needed
+  by individual diagnostics.
+  The main reason is that some diagnostics require us to extract bits of 
+  internal state that are particular only to that diagnostic.
+  We plan to formalize this later, after we learn more about the requirements
+  of several diagnostics.
+  </para>
+  <para>
+  All the instrumentation points can be switched on and off using 
+  <code>-D[_NO]_GLIBCXX_PROFILE_&lt;diagnostic&gt;</code> options.
+  With all the instrumentation calls off, there should be negligible
+  overhead over the release version.  This property is needed to support
+  diagnostics based on timing of internal operations.  For such diagnostics,
+  we anticipate turning most of the instrumentation off in order to prevent
+  profiling overhead from polluting time measurements, and thus diagnostics.
+  </para>
+  <para>
+  All the instrumentation on/off compile time switches live in 
+  <code>include/profile/profiler.h</code>.
+  </para>
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.design.rtlib" 
+ xreflabel="Run Time Behavior">
+<title>Run Time Behavior</title>
+  <para>
+  For practical reasons, the instrumentation library processes the trace
+  partially
+  rather than dumping it to disk in raw form.  Each event is processed when
+  it occurs.  It is usually attached a cost and it is aggregated into
+  the database of a specific diagnostic class.  The cost model
+  is based largely on the standard performance guarantees, but in some
+  cases we use knowledge about GCC's standard library implementation.
+  </para>
+  <para>
+  Information is indexed by (1) call stack and (2) instance id or address
+  to be able to understand and summarize precise creation-use-destruction
+  dynamic chains.  Although the analysis is sensitive to dynamic instances,
+  the reports are only sensitive to call context.  Whenever a dynamic instance
+  is destroyed, we accumulate its effect to the corresponding entry for the
+  call stack of its constructor location.
+  </para>
+
+  <para>
+  For details, see 
+   <ulink url="http://dx.doi.org/10.1109/CGO.2009.36">paper presented at
+   CGO 2009</ulink>.
+  </para>
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.design.analysis"
+ xreflabel="Analysis and Diagnostics">
+<title>Analysis and Diagnostics</title>
+  <para>
+  Final analysis takes place offline, and it is based entirely on the
+  generated trace and debugging info in the application binary.
+  See section Diagnostics for a list of analysis types that we plan to support.
+  </para>
+  <para>
+  The input to the analysis is a table indexed by profile type and call stack.
+  The data type for each entry depends on the profile type.
+  </para>
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.design.cost-model"
+ xreflabel="Cost Model">
+<title>Cost Model</title>
+  <para>
+  While it is likely that cost models become complex as we get into 
+  more sophisticated analysis, we will try to follow a simple set of rules
+  at the beginning.
+  </para>
+<itemizedlist>
+  <listitem><para><emphasis>Relative benefit estimation:</emphasis>
+  The idea is to estimate or measure the cost of all operations
+  in the original scenario versus the scenario we advise to switch to.
+  For instance, when advising to change a vector to a list, an occurrence
+  of the <code>insert</code> method will generally count as a benefit.
+  Its magnitude depends on (1) the number of elements that get shifted
+  and (2) whether it triggers a reallocation.
+  </para></listitem>
+  <listitem><para><emphasis>Synthetic measurements:</emphasis>
+  We will measure the relative difference between similar operations on
+  different containers.  We plan to write a battery of small tests that
+  compare the times of the executions of similar methods on different
+  containers.  The idea is to run these tests on the target machine.
+  If this training phase is very quick, we may decide to perform it at
+  library initialization time.  The results can be cached on disk and reused
+  across runs.
+  </para></listitem>
+  <listitem><para><emphasis>Timers:</emphasis>
+  We plan to use timers for operations of larger granularity, such as sort.
+  For instance, we can switch between different sort methods on the fly
+  and report the one that performs best for each call context.
+  </para></listitem>
+  <listitem><para><emphasis>Show stoppers:</emphasis>
+  We may decide that the presence of an operation nullifies the advice.
+  For instance, when considering switching from <code>set</code> to 
+  <code>unordered_set</code>, if we detect use of operator <code>++</code>,
+  we will simply not issue the advice, since this could signal that the use
+  care require a sorted container.</para></listitem>
+</itemizedlist>
+
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.design.reports"
+ xreflabel="Reports">
+<title>Reports</title>
+  <para>
+There are two types of reports.  First, if we recognize a pattern for which
+we have a substitute that is likely to give better performance, we print
+the advice and estimated performance gain.  The advice is usually associated
+to a code position and possibly a call stack.
+  </para>
+  <para>
+Second, we report performance characteristics for which we do not have
+a clear solution for improvement.  For instance, we can point to the user
+the top 10 <code>multimap</code> locations
+which have the worst data locality in actual traversals.
+Although this does not offer a solution,
+it helps the user focus on the key problems and ignore the uninteresting ones.
+  </para>
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.design.testing"
+ xreflabel="Testing">
+<title>Testing</title>
+  <para>
+  First, we want to make sure we preserve the behavior of the release mode.
+  You can just type <code>"make check-profile"</code>, which
+  builds and runs the whole test suite in profile mode.
+  </para>
+  <para>
+  Second, we want to test the correctness of each diagnostic.
+  We created a <code>profile</code> directory in the test suite.
+  Each diagnostic must come with at least two tests, one for false positives
+  and one for false negatives.
+  </para>
+</sect2>
+
+</sect1>
+
+<sect1 id="manual.ext.profile_mode.api"
+ xreflabel="API">
+<title>Extensions for Custom Containers</title>
+
+  <para>
+  Many large projects use their own data structures instead of the ones in the
+  standard library.  If these data structures are similar in functionality
+  to the standard library, they can be instrumented with the same hooks
+  that are used to instrument the standard library.
+  The instrumentation API is exposed in file
+  <code>profiler.h</code> (look for "Instrumentation hooks").
+  </para>
+
+</sect1>
+
+
+<sect1 id="manual.ext.profile_mode.cost_model"
+ xreflabel="Cost Model">
+<title>Empirical Cost Model</title>
+
+  <para>
+  Currently, the cost model uses formulas with predefined relative weights
+  for alternative containers or container implementations.  For instance,
+  iterating through a vector is X times faster than iterating through a list.
+  </para>
+  <para>
+  (Under development.)
+  We are working on customizing this to a particular machine by providing
+  an automated way to compute the actual relative weights for operations
+  on the given machine.
+  </para>
+  <para>
+  (Under development.)
+  We plan to provide a performance parameter database format that can be
+  filled in either by hand or by an automated training mechanism.
+  The analysis module will then use this database instead of the built in.
+  generic parameters.
+  </para>
+
+</sect1>
+
+
+<sect1 id="manual.ext.profile_mode.implementation"
+ xreflabel="Implementation">
+<title>Implementation Issues</title>
+
+
+<sect2 id="manual.ext.profile_mode.implementation.stack"
+ xreflabel="Stack Traces">
+<title>Stack Traces</title>
+  <para>
+  Accurate stack traces are needed during profiling since we group events by
+  call context and dynamic instance.  Without accurate traces, diagnostics
+  may be hard to interpret.  For instance, when giving advice to the user
+  it is imperative to reference application code, not library code.
+  </para>
+  <para>
+  Currently we are using the libc <code>backtrace</code> routine to get
+  stack traces.
+  <code>_GLIBCXX_PROFILE_STACK_DEPTH</code> can be set
+  to 0 if you are willing to give up call context information, or to a small
+  positive value to reduce run time overhead.
+  </para>
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.implementation.symbols"
+ xreflabel="Symbolization">
+<title>Symbolization of Instruction Addresses</title>
+  <para>
+  The profiling and analysis phases use only instruction addresses.
+  An external utility such as addr2line is needed to postprocess the result.
+  We do not plan to add symbolization support in the profile extension.
+  This would require access to symbol tables, debug information tables,
+  external programs or libraries and other system dependent information.
+  </para>
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.implementation.concurrency"
+ xreflabel="Concurrency">
+<title>Concurrency</title>
+  <para>
+  Our current model is simplistic, but precise.
+  We cannot afford to approximate because some of our diagnostics require
+  precise matching of operations to container instance and call context.
+  During profiling, we keep a single information table per diagnostic.
+  There is a single lock per information table.
+  </para>
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.implementation.stdlib-in-proflib"
+ xreflabel="Using the Standard Library in the Runtime Library">
+<title>Using the Standard Library in the Instrumentation Implementation</title>
+  <para>
+  As much as we would like to avoid uses of stdlibc++ within our 
+  instrumentation library, containers such as unordered_map are very 
+  appealing.  We plan to use them as long as they are named properly 
+  to avoid ambiguity.
+  </para>
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.implementation.malloc-hooks"
+ xreflabel="Malloc Hooks">
+<title>Malloc Hooks</title>
+  <para>
+  User applications/libraries can provide malloc hooks.
+  When the implementation of the malloc hooks uses stdlibc++, there can
+  be an infinite cycle between the profile mode instrumentation and the
+  the malloc hook code.
+  </para>
+  <para>
+  We protect against reentrance to the profile mode instrumentation code,
+  which should avoid this problem in most cases.
+  The protection mechanism is thread safe and exception safe.
+  This mechanism does not prevent reentrance to the malloc hook itself,
+  which could still result in deadlock, if, for instance, the malloc hook
+  uses non-recursive locks.
+  XXX: A definitive solution to this problem would be for the profile extension
+  to use a custom allocator internally, and perhaps not to use libstdc++.
+  </para>
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.implementation.construction-destruction"
+ xreflabel="Construction and Destruction of Global Objects">
+<title>Construction and Destruction of Global Objects</title>
+  <para>
+  The profiling library state is initialized at the first call to a profiling
+  method.  This allows us to record the construction of all global objects.
+  However, we cannot do the same at destruction time.  The trace is written
+  by a function registered by <code>atexit</code>, thus invoked by 
+  <code>exit</code>.
+  </para>
+</sect2>
+
+</sect1>
+
+
+<sect1 id="manual.ext.profile_mode.developer"
+ xreflabel="Developer Information">
+<title>Developer Information</title>
+
+<sect2 id="manual.ext.profile_mode.developer.bigpic"
+ xreflabel="Big Picture">
+<title>Big Picture</title>
+
+  <para>The profile mode headers are included with
+   <code>-D_GLIBCXX_PROFILE</code> through preprocessor directives in 
+   <code>include/std/*</code>.
+  </para>
+
+  <para>Instrumented implementations are provided in 
+   <code>include/profile/*</code>.  All instrumentation hooks are macros
+   defined in <code>include/profile/profiler.h</code>.
+  </para>
+
+  <para>All the implementation of the instrumentation hooks is in 
+   <code>include/profile/impl/*</code>.  Although all the code gets included,
+   thus is publicly visible, only a small number of functions are called from
+   outside this directory.  All calls to hook implementations must be
+   done through macros defined in <code>profiler.h</code>.  The macro
+   must ensure (1) that the call is guarded against reentrance and 
+   (2) that the call can be turned off at compile time using a
+   <code>-D_GLIBCXX_PROFILE_...</code> compiler option.
+  </para>
+
+</sect2>
+
+<sect2 id="manual.ext.profile_mode.developer.howto"
+ xreflabel="How To Add A Diagnostic">
+<title>How To Add A Diagnostic</title>
+
+  <para>Let's say the diagnostic name is "magic".
+  </para>
+
+  <para>If you need to instrument a header not already under 
+   <code>include/profile/*</code>, first edit the corresponding header
+   under <code>include/std/</code> and add a preprocessor directive such
+   as the one in <code>include/std/vector</code>:
+<programlisting>
+#ifdef _GLIBCXX_PROFILE
+# include &lt;profile/vector&gt;
+#endif
+</programlisting>
+  </para>
+
+  <para>If the file you need to instrument is not yet under
+   <code>include/profile/</code>, make a copy of the one in
+   <code>include/debug</code>, or the main implementation.
+   You'll need to include the main implementation and inherit the classes
+   you want to instrument.  Then define the methods you want to instrument,
+   define the instrumentation hooks and add calls to them.
+   Look at <code>include/profile/vector</code> for an example.
+  </para>
+
+  <para>Add macros for the instrumentation hooks in
+   <code>include/profile/impl/profiler.h</code>.
+   Hook names must start with <code>__profcxx_</code>.
+   Make sure they transform
+   in no code with <code>-D_NO_GLBICXX_PROFILE_MAGIC</code>.
+   Make sure all calls to any method in namespace <code>__cxxprof_impl</code>
+   is protected against reentrance using macro
+   <code>_GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD</code>.
+   All names of methods in namespace <code>__cxxprof_impl</code> called from
+   <code>profiler.h</code> must start with <code>__trace_magic_</code>.
+  </para>
+
+  <para>Add the implementation of the diagnostic.
+   <itemizedlist>
+     <listitem><para>
+      Create new file <code>include/profile/impl/profiler_magic.h</code>.
+     </para></listitem>
+     <listitem><para>
+      Define class <code>__magic_info: public __object_info_base</code>.
+      This is the representation of a line in the object table.
+      The <code>__merge</code> method is used to aggregate information
+      across all dynamic instances created at the same call context.
+      The <code>__magnitude</code> must return the estimation of the benefit
+      as a number of small operations, e.g., number of words copied.
+      The <code>__write</code> method is used to produce the raw trace.
+      The <code>__advice</code> method is used to produce the advice string.
+     </para></listitem>
+     <listitem><para>
+      Define class <code>__magic_stack_info: public __magic_info</code>.
+      This defines the content of a line in the stack table.
+     </para></listitem>
+     <listitem><para>
+      Define class <code>__trace_magic: public __trace_base&lt;__magic_info, 
+      __magic_stack_info&gt;</code>.
+      It defines the content of the trace associated with this diagnostic.
+     </para></listitem>
+    </itemizedlist>
+  </para>
+
+  <para>Add initialization and reporting calls in
+   <code>include/profile/impl/profiler_trace.h</code>.  Use
+   <code>__trace_vector_to_list</code> as an example.
+  </para>
+
+  <para>Add documentation in file <code>doc/xml/manual/profile_mode.xml</code>.
+  </para>
+</sect2>
+</sect1>
+
+<sect1 id="manual.ext.profile_mode.diagnostics">
+<title>Diagnostics</title>
+
+  <para>
+  The table below presents all the diagnostics we intend to implement.
+  Each diagnostic has a corresponding compile time switch
+  <code>-D_GLIBCXX_PROFILE_&lt;diagnostic&gt;</code>.
+  Groups of related diagnostics can be turned on with a single switch.
+  For instance, <code>-D_GLIBCXX_PROFILE_LOCALITY</code> is equivalent to
+  <code>-D_GLIBCXX_PROFILE_SOFTWARE_PREFETCH 
+  -D_GLIBCXX_PROFILE_RBTREE_LOCALITY</code>.
+  </para>
+
+  <para>
+  The benefit, cost, expected frequency and accuracy of each diagnostic
+  was given a grade from 1 to 10, where 10 is highest.
+  A high benefit means that, if the diagnostic is accurate, the expected
+  performance improvement is high.
+  A high cost means that turning this diagnostic on leads to high slowdown.
+  A high frequency means that we expect this to occur relatively often.
+  A high accuracy means that the diagnostic is unlikely to be wrong.
+  These grades are not perfect.  They are just meant to guide users with
+  specific needs or time budgets.
+  </para>
+
+<table frame='all'>
+<title>Diagnostics</title>
+<tgroup cols='6' align='left' colsep='1' rowsep='1'>
+<colspec colname='c1'></colspec>
+<colspec colname='c2'></colspec>
+<colspec colname='c3'></colspec>
+<colspec colname='c4'></colspec>
+<colspec colname='c5'></colspec>
+<colspec colname='c6'></colspec>
+<colspec colname='c7'></colspec>
+
+<thead>
+  <row>
+    <entry>Group</entry>
+    <entry>Flag</entry>
+    <entry>Benefit</entry>
+    <entry>Cost</entry>
+    <entry>Freq.</entry>
+    <entry>Implemented</entry>
+  </row>
+</thead>
+<tbody>
+  <row>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.containers">
+    CONTAINERS</ulink></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.hashtable_too_small">
+    HASHTABLE_TOO_SMALL</ulink></entry>
+    <entry>10</entry>
+    <entry>1</entry>
+    <entry></entry>
+    <entry>10</entry>
+    <entry>yes</entry>
+  </row>
+  <row>
+    <entry></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.hashtable_too_large">
+    HASHTABLE_TOO_LARGE</ulink></entry>
+    <entry>5</entry>
+    <entry>1</entry>
+    <entry></entry>
+    <entry>10</entry>
+    <entry>yes</entry>
+  </row>
+  <row>
+    <entry></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.inefficient_hash">
+    INEFFICIENT_HASH</ulink></entry>
+    <entry>7</entry>
+    <entry>3</entry>
+    <entry></entry>
+    <entry>10</entry>
+    <entry>yes</entry>
+  </row>
+  <row>
+    <entry></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.vector_too_small">
+    VECTOR_TOO_SMALL</ulink></entry>
+    <entry>8</entry>
+    <entry>1</entry>
+    <entry></entry>
+    <entry>10</entry>
+    <entry>yes</entry>
+  </row>
+  <row>
+    <entry></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.vector_too_large">
+    VECTOR_TOO_LARGE</ulink></entry>
+    <entry>5</entry>
+    <entry>1</entry>
+    <entry></entry>
+    <entry>10</entry>
+    <entry>yes</entry>
+  </row>
+  <row>
+    <entry></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.vector_to_hashtable">
+    VECTOR_TO_HASHTABLE</ulink></entry>
+    <entry>7</entry>
+    <entry>7</entry>
+    <entry></entry>
+    <entry>10</entry>
+    <entry>no</entry>
+  </row>
+  <row>
+    <entry></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.hashtable_to_vector">
+    HASHTABLE_TO_VECTOR</ulink></entry>
+    <entry>7</entry>
+    <entry>7</entry>
+    <entry></entry>
+    <entry>10</entry>
+    <entry>no</entry>
+  </row>
+  <row>
+    <entry></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.vector_to_list">
+    VECTOR_TO_LIST</ulink></entry>
+    <entry>8</entry>
+    <entry>5</entry>
+    <entry></entry>
+    <entry>10</entry>
+    <entry>yes</entry>
+  </row>
+  <row>
+    <entry></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.list_to_vector">
+    LIST_TO_VECTOR</ulink></entry>
+    <entry>10</entry>
+    <entry>5</entry>
+    <entry></entry>
+    <entry>10</entry>
+    <entry>no</entry>
+  </row>
+  <row>
+    <entry></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.assoc_ord_to_unord">
+    ORDERED_TO_UNORDERED</ulink></entry>
+    <entry>10</entry>
+    <entry>5</entry>
+    <entry></entry>
+    <entry>10</entry>
+    <entry>only map/unordered_map</entry>
+  </row>
+  <row>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.algorithms">
+    ALGORITHMS</ulink></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.algorithms.sort">
+    SORT</ulink></entry>
+    <entry>7</entry>
+    <entry>8</entry>
+    <entry></entry>
+    <entry>7</entry>
+    <entry>no</entry>
+  </row>
+  <row>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.locality">
+    LOCALITY</ulink></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.locality.sw_prefetch">
+    SOFTWARE_PREFETCH</ulink></entry>
+    <entry>8</entry>
+    <entry>8</entry>
+    <entry></entry>
+    <entry>5</entry>
+    <entry>no</entry>
+  </row>
+  <row>
+    <entry></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.locality.linked">
+    RBTREE_LOCALITY</ulink></entry>
+    <entry>4</entry>
+    <entry>8</entry>
+    <entry></entry>
+    <entry>5</entry>
+    <entry>no</entry>
+  </row>
+  <row>
+    <entry></entry>
+    <entry><ulink url="#manual.ext.profile_mode.analysis.mthread.false_share">
+    FALSE_SHARING</ulink></entry>
+    <entry>8</entry>
+    <entry>10</entry>
+    <entry></entry>
+    <entry>10</entry>
+    <entry>no</entry>
+  </row>
+</tbody>
+</tgroup>
+</table>
+
+<sect2 id="manual.ext.profile_mode.analysis.template" 
+ xreflabel="Template">
+<title>Diagnostic Template</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_&lt;diagnostic&gt;</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis>  What problem will it diagnose?
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis>.
+  What is the fundamental reason why this is a problem</para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>
+  Percentage reduction in execution time.  When reduction is more than
+  a constant factor, describe the reduction rate formula.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis>
+  What would the advise look like?</para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis>
+  What stdlibc++ components need to be instrumented?</para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  How do we decide when to issue the advice?</para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  How do we measure benefits?  Math goes here.</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis>
+<programlisting>
+program code
+...
+advice sample
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.analysis.containers" 
+ xreflabel="Containers">
+<title>Containers</title>
+
+<para>
+<emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_CONTAINERS</code>.
+</para>
+
+<sect3 id="manual.ext.profile_mode.analysis.hashtable_too_small" 
+ xreflabel="Hashtable Too Small">
+<title>Hashtable Too Small</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_HASHTABLE_TOO_SMALL</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis> Detect hashtables with many 
+  rehash operations, small construction size and large destruction size.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis> Rehash is very expensive.
+  Read content, follow chains within bucket, evaluate hash function, place at
+  new location in different order.</para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis> 36%.
+  Code similar to example below.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis> 
+  Set initial size to N at construction site S.
+  </para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis> 
+  <code>unordered_set, unordered_map</code> constructor, destructor, rehash.
+  </para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  For each dynamic instance of <code>unordered_[multi]set|map</code>,
+  record initial size and call context of the constructor.
+  Record size increase, if any, after each relevant operation such as insert.
+  Record the estimated rehash cost.</para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  Number of individual rehash operations * cost per rehash.</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis> 
+<programlisting>
+1 unordered_set&lt;int&gt; us;
+2 for (int k = 0; k &lt; 1000000; ++k) {
+3   us.insert(k);
+4 }
+
+foo.cc:1: advice: Changing initial unordered_set size from 10 to 1000000 saves 1025530 rehash operations.
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+
+<sect3 id="manual.ext.profile_mode.analysis.hashtable_too_large" 
+ xreflabel="Hashtable Too Large">
+<title>Hashtable Too Large</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_HASHTABLE_TOO_LARGE</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis> Detect hashtables which are
+  never filled up because fewer elements than reserved are ever
+  inserted.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis> Save memory, which
+  is good in itself and may also improve memory reference performance through
+  fewer cache and TLB misses.</para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis> unknown.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis> 
+  Set initial size to N at construction site S.
+  </para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis> 
+  <code>unordered_set, unordered_map</code> constructor, destructor, rehash.
+  </para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  For each dynamic instance of <code>unordered_[multi]set|map</code>,
+  record initial size and call context of the constructor, and correlate it
+  with its size at destruction time.
+  </para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  Number of iteration operations + memory saved.</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis> 
+<programlisting>
+1 vector&lt;unordered_set&lt;int&gt;&gt; v(100000, unordered_set&lt;int&gt;(100)) ;
+2 for (int k = 0; k &lt; 100000; ++k) {
+3   for (int j = 0; j &lt; 10; ++j) {
+4     v[k].insert(k + j);
+5  }
+6 }
+
+foo.cc:1: advice: Changing initial unordered_set size from 100 to 10 saves N
+bytes of memory and M iteration steps.
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+<sect3 id="manual.ext.profile_mode.analysis.inefficient_hash"
+ xreflabel="Inefficient Hash">
+<title>Inefficient Hash</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_INEFFICIENT_HASH</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis> Detect hashtables with polarized
+  distribution.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis> A non-uniform 
+  distribution may lead to long chains, thus possibly increasing complexity
+  by a factor up to the number of elements.
+  </para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis> factor up
+   to container size.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis> Change hash function
+  for container built at site S.  Distribution score = N.  Access score = S.
+  Longest chain = C, in bucket B.
+  </para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis>
+  <code>unordered_set, unordered_map</code> constructor, destructor, [],
+  insert, iterator.
+  </para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  Count the exact number of link traversals.
+  </para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  Total number of links traversed.</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis> 
+<programlisting>
+class dumb_hash {
+ public:
+  size_t operator() (int i) const { return 0; }
+};
+...
+  unordered_set&lt;int, dumb_hash&gt; hs;
+  ...
+  for (int i = 0; i &lt; COUNT; ++i) {
+    hs.find(i);
+  }
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+<sect3 id="manual.ext.profile_mode.analysis.vector_too_small" 
+ xreflabel="Vector Too Small">
+<title>Vector Too Small</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_VECTOR_TOO_SMALL</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis>Detect vectors with many 
+  resize operations, small construction size and large destruction size..
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis>Resizing can be expensive.
+  Copying large amounts of data takes time.  Resizing many small vectors may
+  have allocation overhead and affect locality.</para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>%.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis>
+  Set initial size to N at construction site S.</para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis><code>vector</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  For each dynamic instance of <code>vector</code>,
+  record initial size and call context of the constructor.
+  Record size increase, if any, after each relevant operation such as 
+  <code>push_back</code>.  Record the estimated resize cost.
+  </para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  Total number of words copied * time to copy a word.</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis> 
+<programlisting>
+1 vector&lt;int&gt; v;
+2 for (int k = 0; k &lt; 1000000; ++k) {
+3   v.push_back(k);
+4 }
+
+foo.cc:1: advice: Changing initial vector size from 10 to 1000000 saves 
+copying 4000000 bytes and 20 memory allocations and deallocations.
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+<sect3 id="manual.ext.profile_mode.analysis.vector_too_large" 
+ xreflabel="Vector Too Large">
+<title>Vector Too Large</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_VECTOR_TOO_LARGE</code>
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis>Detect vectors which are
+  never filled up because fewer elements than reserved are ever
+  inserted.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis>Save memory, which
+  is good in itself and may also improve memory reference performance through
+  fewer cache and TLB misses.</para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>%.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis>
+  Set initial size to N at construction site S.</para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis><code>vector</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  For each dynamic instance of <code>vector</code>,
+  record initial size and call context of the constructor, and correlate it
+  with its size at destruction time.</para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  Total amount of memory saved.</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis> 
+<programlisting>
+1 vector&lt;vector&lt;int&gt;&gt; v(100000, vector&lt;int&gt;(100)) ;
+2 for (int k = 0; k &lt; 100000; ++k) {
+3   for (int j = 0; j &lt; 10; ++j) {
+4     v[k].insert(k + j);
+5  }
+6 }
+
+foo.cc:1: advice: Changing initial vector size from 100 to 10 saves N
+bytes of memory and may reduce the number of cache and TLB misses.
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+<sect3 id="manual.ext.profile_mode.analysis.vector_to_hashtable" 
+ xreflabel="Vector to Hashtable">
+<title>Vector to Hashtable</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_VECTOR_TO_HASHTABLE</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis> Detect uses of 
+  <code>vector</code> that can be substituted with <code>unordered_set</code>
+  to reduce execution time.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis>
+  Linear search in a vector is very expensive, whereas searching in a hashtable
+  is very quick.</para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>factor up
+   to container size.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis>Replace 
+  <code>vector</code> with <code>unordered_set</code> at site S.
+  </para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis><code>vector</code>
+  operations and access methods.</para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  For each dynamic instance of <code>vector</code>,
+  record call context of the constructor.  Issue the advice only if the
+  only methods called on this <code>vector</code> are <code>push_back</code>, 
+  <code>insert</code> and <code>find</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  Cost(vector::push_back) + cost(vector::insert) + cost(find, vector) -
+  cost(unordered_set::insert) + cost(unordered_set::find).
+  </para></listitem>
+  <listitem><para><emphasis>Example:</emphasis>
+<programlisting>
+1  vector&lt;int&gt; v;
+...
+2  for (int i = 0; i &lt; 1000; ++i) {
+3    find(v.begin(), v.end(), i);
+4  }
+
+foo.cc:1: advice: Changing "vector" to "unordered_set" will save about 500,000
+comparisons.
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+<sect3 id="manual.ext.profile_mode.analysis.hashtable_to_vector" 
+ xreflabel="Hashtable to Vector">
+<title>Hashtable to Vector</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_HASHTABLE_TO_VECTOR</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis> Detect uses of 
+  <code>unordered_set</code> that can be substituted with <code>vector</code>
+  to reduce execution time.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis>
+  Hashtable iterator is slower than vector iterator.</para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>95%.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis>Replace 
+  <code>unordered_set</code> with <code>vector</code> at site S.
+  </para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis><code>unordered_set</code>
+  operations and access methods.</para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  For each dynamic instance of <code>unordered_set</code>,
+  record call context of the constructor.  Issue the advice only if the
+  number of <code>find</code>, <code>insert</code> and <code>[]</code> 
+  operations on this <code>unordered_set</code> are small relative to the
+  number of elements, and methods <code>begin</code> or <code>end</code>
+  are invoked (suggesting iteration).</para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  Number of .</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis>
+<programlisting>
+1  unordered_set&lt;int&gt; us;
+...
+2  int s = 0;
+3  for (unordered_set&lt;int&gt;::iterator it = us.begin(); it != us.end(); ++it) {
+4    s += *it;
+5  }
+
+foo.cc:1: advice: Changing "unordered_set" to "vector" will save about N
+indirections and may achieve better data locality.
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+<sect3 id="manual.ext.profile_mode.analysis.vector_to_list"
+ xreflabel="Vector to List">
+<title>Vector to List</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_VECTOR_TO_LIST</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis> Detect cases where 
+  <code>vector</code> could be substituted with <code>list</code> for
+  better performance.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis>
+  Inserting in the middle of a vector is expensive compared to inserting in a 
+  list.
+  </para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>factor up to
+   container size.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis>Replace vector with list
+  at site S.</para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis><code>vector</code>
+  operations and access methods.</para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  For each dynamic instance of <code>vector</code>,
+  record the call context of the constructor.  Record the overhead of each
+  <code>insert</code> operation based on current size and insert position.
+  Report instance with high insertion overhead.
+  </para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  (Sum(cost(vector::method)) - Sum(cost(list::method)), for
+  method in [push_back, insert, erase])
+  + (Cost(iterate vector) - Cost(iterate list))</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis> 
+<programlisting>
+1  vector&lt;int&gt; v;
+2  for (int i = 0; i &lt; 10000; ++i) {
+3    v.insert(v.begin(), i);
+4  }
+
+foo.cc:1: advice: Changing "vector" to "list" will save about 5,000,000 
+operations.
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+<sect3 id="manual.ext.profile_mode.analysis.list_to_vector"
+ xreflabel="List to Vector">
+<title>List to Vector</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_LIST_TO_VECTOR</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis> Detect cases where 
+  <code>list</code> could be substituted with <code>vector</code> for
+  better performance.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis>
+  Iterating through a vector is faster than through a list.
+  </para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>64%.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis>Replace list with vector
+  at site S.</para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis><code>vector</code>
+  operations and access methods.</para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  Issue the advice if there are no <code>insert</code> operations.
+  </para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+    (Sum(cost(vector::method)) - Sum(cost(list::method)), for
+  method in [push_back, insert, erase])
+  + (Cost(iterate vector) - Cost(iterate list))</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis> 
+<programlisting>
+1  list&lt;int&gt; l;
+...
+2  int sum = 0;
+3  for (list&lt;int&gt;::iterator it = l.begin(); it != l.end(); ++it) {
+4    sum += *it;
+5  }
+
+foo.cc:1: advice: Changing "list" to "vector" will save about 1000000 indirect
+memory references.
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+<sect3 id="manual.ext.profile_mode.analysis.assoc_ord_to_unord"
+ xreflabel="Ordered to Unordered Associative Container">
+<title>Ordered to Unordered Associative Container</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_ORDERED_TO_UNORDERED</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis>  Detect cases where ordered
+  associative containers can be replaced with unordered ones.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis>
+  Insert and search are quicker in a hashtable than in 
+  a red-black tree.</para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>52%.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis>
+  Replace set with unordered_set at site S.</para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis>
+  <code>set</code>, <code>multiset</code>, <code>map</code>,
+  <code>multimap</code> methods.</para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  Issue the advice only if we are not using operator <code>++</code> on any
+  iterator on a particular <code>[multi]set|map</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  (Sum(cost(hashtable::method)) - Sum(cost(rbtree::method)), for
+  method in [insert, erase, find])
+  + (Cost(iterate hashtable) - Cost(iterate rbtree))</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis>
+<programlisting>
+1  set&lt;int&gt; s;
+2  for (int i = 0; i &lt; 100000; ++i) {
+3    s.insert(i);
+4  }
+5  int sum = 0;
+6  for (int i = 0; i &lt; 100000; ++i) {
+7    sum += *s.find(i);
+8  }
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+</sect2>
+
+
+
+<sect2 id="manual.ext.profile_mode.analysis.algorithms"
+ xreflabel="Algorithms">
+<title>Algorithms</title>
+
+  <para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_ALGORITHMS</code>.
+  </para>
+
+<sect3 id="manual.ext.profile_mode.analysis.algorithms.sort"
+ xreflabel="Sorting">
+<title>Sort Algorithm Performance</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_SORT</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis> Give measure of sort algorithm
+  performance based on actual input.  For instance, advise Radix Sort over
+  Quick Sort for a particular call context.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis>
+  See papers: 
+  <ulink url="http://portal.acm.org/citation.cfm?doid=1065944.1065981">
+  A framework for adaptive algorithm selection in STAPL</ulink> and 
+  <ulink url="http://ieeexplore.ieee.org/search/wrapper.jsp?arnumber=4228227">
+  Optimizing Sorting with Machine Learning Algorithms</ulink>.
+  </para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>60%.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis> Change sort algorithm
+  at site S from X Sort to Y Sort.</para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis> <code>sort</code>
+  algorithm.</para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  Issue the advice if the cost model tells us that another sort algorithm
+  would do better on this input.  Requires us to know what algorithm we 
+  are using in our sort implementation in release mode.</para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  Runtime(algo) for algo in [radix, quick, merge, ...]</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis>
+<programlisting>
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.analysis.locality"
+ xreflabel="Data Locality">
+<title>Data Locality</title>
+
+  <para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_LOCALITY</code>.
+  </para>
+
+<sect3 id="manual.ext.profile_mode.analysis.locality.sw_prefetch"
+ xreflabel="Need Software Prefetch">
+<title>Need Software Prefetch</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_SOFTWARE_PREFETCH</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis> Discover sequences of indirect
+  memory accesses that are not regular, thus cannot be predicted by
+  hardware prefetchers.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis>
+  Indirect references are hard to predict and are very expensive when they
+  miss in caches.</para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>25%.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis> Insert prefetch 
+  instruction.</para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis> Vector iterator and
+  access operator [].
+  </para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  First, get cache line size and page size from system.
+  Then record iterator dereference sequences for which the value is a pointer.
+  For each sequence within a container, issue a warning if successive pointer 
+  addresses are not within cache lines and do not form a linear pattern
+  (otherwise they may be prefetched by hardware).
+  If they also step across page boundaries, make the warning stronger.
+  </para>
+  <para>The same analysis applies to containers other than vector.
+  However, we cannot give the same advice for linked structures, such as list,
+  as there is no random access to the n-th element.  The user may still be
+  able to benefit from this information, for instance by employing frays (user
+  level light weight threads) to hide the latency of chasing pointers.
+  </para>
+  <para>
+  This analysis is a little oversimplified.  A better cost model could be
+  created by understanding the capability of the hardware prefetcher.
+  This model could be trained automatically by running a set of synthetic 
+  cases.
+  </para>
+  </listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  Total distance between pointer values of successive elements in vectors
+  of pointers.</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis> 
+<programlisting>
+1 int zero = 0;
+2 vector&lt;int*&gt; v(10000000, &amp;zero);
+3 for (int k = 0; k &lt; 10000000; ++k) {
+4   v[random() % 10000000] = new int(k);
+5 }
+6 for (int j = 0; j &lt; 10000000; ++j) {
+7   count += (*v[j] == 0 ? 0 : 1);
+8 }
+
+foo.cc:7: advice: Insert prefetch instruction.
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+<sect3 id="manual.ext.profile_mode.analysis.locality.linked"
+ xreflabel="Linked Structure Locality">
+<title>Linked Structure Locality</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_RBTREE_LOCALITY</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis> Give measure of locality of
+  objects stored in linked structures (lists, red-black trees and hashtables)
+  with respect to their actual traversal patterns.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis>Allocation can be tuned
+  to a specific traversal pattern, to result in better data locality.
+  See paper: 
+  <ulink url="http://www.springerlink.com/content/8085744l00x72662/">
+  Custom Memory Allocation for Free</ulink>.
+  </para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>30%.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis>
+  High scatter score N for container built at site S.
+  Consider changing allocation sequence or choosing a structure conscious
+  allocator.</para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis> Methods of all 
+  containers using linked structures.</para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  First, get cache line size and page size from system.
+  Then record the number of successive elements that are on different line
+  or page, for each traversal method such as <code>find</code>.  Give advice
+  only if the ratio between this number and the number of total node hops
+  is above a threshold.</para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  Sum(same_cache_line(this,previous))</para></listitem>
+  <listitem><para><emphasis>Example:</emphasis>
+<programlisting>
+ 1  set&lt;int&gt; s;
+ 2  for (int i = 0; i &lt; 10000000; ++i) {
+ 3    s.insert(i);
+ 4  }
+ 5  set&lt;int&gt; s1, s2;
+ 6  for (int i = 0; i &lt; 10000000; ++i) {
+ 7    s1.insert(i);
+ 8    s2.insert(i);
+ 9  }
+...
+      // Fast, better locality.
+10    for (set&lt;int&gt;::iterator it = s.begin(); it != s.end(); ++it) {
+11      sum += *it;
+12    }
+      // Slow, elements are further apart.
+13    for (set&lt;int&gt;::iterator it = s1.begin(); it != s1.end(); ++it) {
+14      sum += *it;
+15    }
+
+foo.cc:5: advice: High scatter score NNN for set built here.  Consider changing
+the allocation sequence or switching to a structure conscious allocator.
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.analysis.mthread"
+ xreflabel="Multithreaded Data Access">
+<title>Multithreaded Data Access</title>
+
+  <para>
+  The diagnostics in this group are not meant to be implemented short term.
+  They require compiler support to know when container elements are written
+  to.  Instrumentation can only tell us when elements are referenced.
+  </para>
+
+  <para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_MULTITHREADED</code>.
+  </para>
+
+<sect3 id="manual.ext.profile_mode.analysis.mthread.ddtest"
+ xreflabel="Dependence Violations at Container Level">
+<title>Data Dependence Violations at Container Level</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_DDTEST</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis> Detect container elements
+  that are referenced from multiple threads in the parallel region or
+  across parallel regions.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis>
+  Sharing data between threads requires communication and perhaps locking,
+  which may be expensive.
+  </para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>?%.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis> Change data
+  distribution or parallel algorithm.</para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis> Container access methods
+  and iterators.
+  </para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  Keep a shadow for each container.  Record iterator dereferences and
+  container member accesses.  Issue advice for elements referenced by
+  multiple threads.
+  See paper: <ulink url="http://portal.acm.org/citation.cfm?id=207110.207148">
+  The LRPD test: speculative run-time parallelization of loops with 
+  privatization and reduction parallelization</ulink>.
+  </para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  Number of accesses to elements referenced from multiple threads
+  </para></listitem>
+  <listitem><para><emphasis>Example:</emphasis>
+<programlisting>
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+<sect3 id="manual.ext.profile_mode.analysis.mthread.false_share"
+ xreflabel="False Sharing">
+<title>False Sharing</title>
+<itemizedlist>
+  <listitem><para><emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_FALSE_SHARING</code>.
+  </para></listitem>
+  <listitem><para><emphasis>Goal:</emphasis> Detect elements in the
+  same container which share a cache line, are written by at least one 
+  thread, and accessed by different threads.
+  </para></listitem>
+  <listitem><para><emphasis>Fundamentals:</emphasis> Under these assumptions,
+  cache protocols require
+  communication to invalidate lines, which may be expensive.
+  </para></listitem>
+  <listitem><para><emphasis>Sample runtime reduction:</emphasis>68%.
+  </para></listitem>
+  <listitem><para><emphasis>Recommendation:</emphasis> Reorganize container
+  or use padding to avoid false sharing.</para></listitem>
+  <listitem><para><emphasis>To instrument:</emphasis> Container access methods
+  and iterators.
+  </para></listitem>
+  <listitem><para><emphasis>Analysis:</emphasis>
+  First, get the cache line size.
+  For each shared container, record all the associated iterator dereferences 
+  and member access methods with the thread id.  Compare the address lists
+  across threads to detect references in two different threads to the same 
+  cache line.  Issue a warning only if the ratio to total references is 
+  significant.  Do the same for iterator dereference values if they are 
+  pointers.</para></listitem>
+  <listitem><para><emphasis>Cost model:</emphasis>
+  Number of accesses to same cache line from different threads.
+  </para></listitem>
+  <listitem><para><emphasis>Example:</emphasis> 
+<programlisting>
+1     vector&lt;int&gt; v(2, 0);
+2 #pragma omp parallel for shared(v, SIZE) schedule(static, 1)
+3     for (i = 0; i &lt; SIZE; ++i) {
+4       v[i % 2] += i;
+5     }
+
+OMP_NUM_THREADS=2 ./a.out
+foo.cc:1: advice: Change container structure or padding to avoid false 
+sharing in multithreaded access at foo.cc:4.  Detected N shared cache lines.
+</programlisting>
+</para></listitem>
+</itemizedlist>
+</sect3>
+
+</sect2>
+
+
+<sect2 id="manual.ext.profile_mode.analysis.statistics" 
+ xreflabel="Statistics">
+<title>Statistics</title>
+
+<para>
+<emphasis>Switch:</emphasis>
+  <code>_GLIBCXX_PROFILE_STATISTICS</code>.
+</para>
+
+<para>
+  In some cases the cost model may not tell us anything because the costs
+  appear to offset the benefits.  Consider the choice between a vector and
+  a list.  When there are both inserts and iteration, an automatic advice
+  may not be issued.  However, the programmer may still be able to make use
+  of this information in a different way.
+</para>
+<para>
+  This diagnostic will not issue any advice, but it will print statistics for
+  each container construction site.  The statistics will contain the cost
+  of each operation actually performed on the container.
+</para>
+
+</sect2>
+
+
+</sect1>
+
+
+<bibliography id="profile_mode.biblio">
+<title>Bibliography</title>
+
+  <biblioentry>
+    <title>
+      Perflint: A Context Sensitive Performance Advisor for C++ Programs
+    </title>
+
+    <author>
+      <firstname>Lixia</firstname>
+      <surname>Liu</surname>
+    </author>
+    <author>
+      <firstname>Silvius</firstname>
+      <surname>Rus</surname>
+    </author>
+
+    <copyright>
+      <year>2009</year>
+      <holder></holder>
+    </copyright>
+
+    <publisher>
+      <publishername>
+       Proceedings of the 2009 International Symposium on Code Generation
+        and Optimization
+      </publishername>
+    </publisher>
+  </biblioentry> 
+</bibliography>
+
+
+</chapter>
index 55d0236..f3dcd19 100644 (file)
@@ -1,4 +1,4 @@
-## Makefile for the include subdirectory of the GNU C++ Standard library.
+#o# Makefile for the include subdirectory of the GNU C++ Standard library.
 ##
 ## Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
 ## Free Software Foundation, Inc.
@@ -771,6 +771,37 @@ else
 parallel_headers =
 endif
 
+# Profile mode headers
+profile_srcdir = ${glibcxx_srcdir}/include/profile
+profile_builddir = ./profile
+profile_headers = \
+       ${profile_srcdir}/base.h \
+       ${profile_srcdir}/unordered_map \
+       ${profile_srcdir}/unordered_set \
+       ${profile_srcdir}/vector \
+       ${profile_srcdir}/bitset \
+       ${profile_srcdir}/deque \
+       ${profile_srcdir}/list \
+       ${profile_srcdir}/map \
+       ${profile_srcdir}/map.h \
+       ${profile_srcdir}/multimap.h \
+       ${profile_srcdir}/multiset.h \
+       ${profile_srcdir}/set \
+       ${profile_srcdir}/set.h \
+       ${profile_srcdir}/hashtable.h
+profile_impl_srcdir = ${glibcxx_srcdir}/include/profile/impl
+profile_impl_builddir = ./profile/impl
+profile_impl_headers = \
+       ${profile_impl_srcdir}/profiler.h \
+       ${profile_impl_srcdir}/profiler_container_size.h \
+       ${profile_impl_srcdir}/profiler_hash_func.h \
+       ${profile_impl_srcdir}/profiler_hashtable_size.h \
+       ${profile_impl_srcdir}/profiler_map_to_unordered_map.h \
+       ${profile_impl_srcdir}/profiler_node.h \
+       ${profile_impl_srcdir}/profiler_state.h \
+       ${profile_impl_srcdir}/profiler_trace.h \
+       ${profile_impl_srcdir}/profiler_vector_size.h \
+       ${profile_impl_srcdir}/profiler_vector_to_list.h
 
 # Some of the different "C" header models need extra files.
 # Some "C" header schemes require the "C" compatibility headers.
@@ -865,7 +896,8 @@ endif
 allstamped = \
        stamp-std stamp-bits stamp-c_base stamp-c_base_extra \
        stamp-c_compatibility  stamp-backward stamp-ext stamp-pb \
-       stamp-tr1 stamp-tr1-impl stamp-debug stamp-parallel stamp-host
+       stamp-tr1 stamp-tr1-impl stamp-debug stamp-parallel stamp-host \
+    stamp-profile stamp-profile-impl
 
 # List of all files that are created by explicit building, editing, or
 # catenation.
@@ -989,6 +1021,16 @@ stamp-parallel: ${parallel_headers}
        @-cd ${parallel_builddir} && $(LN_S) $? . 2>/dev/null
        @$(STAMP) stamp-parallel
 
+stamp-profile: ${profile_headers}
+       @-mkdir -p ${profile_builddir}
+       @-cd ${profile_builddir} && $(LN_S) $? . 2>/dev/null
+       @$(STAMP) stamp-profile
+
+stamp-profile-impl: ${profile_impl_headers}
+       @-mkdir -p ${profile_impl_builddir}
+       @-cd ${profile_impl_builddir} && $(LN_S) $? . 2>/dev/null
+       @$(STAMP) stamp-profile-impl
+
 stamp-${host_alias}:
        @-mkdir -p ${host_builddir}
        @$(STAMP) stamp-${host_alias}
@@ -1217,6 +1259,12 @@ install-headers:
          $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${parallel_builddir};\
        for file in $$parallel_headers_install; do \
          $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${parallel_builddir}; done
+       $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${profile_builddir}
+       for file in ${profile_headers}; do \
+         $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${profile_builddir}; done
+       $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${profile_impl_builddir}
+       for file in ${profile_impl_headers}; do \
+         $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${profile_impl_builddir}; done
        $(mkinstalldirs) $(DESTDIR)${host_installdir}
        for file in ${host_headers} ${host_headers_extra} \
         ${thread_host_headers}; do \
index 47995ef..4c69a2b 100644 (file)
@@ -1001,6 +1001,39 @@ parallel_builddir = ./parallel
 @ENABLE_PARALLEL_TRUE@        ${parallel_srcdir}/unique_copy.h \
 @ENABLE_PARALLEL_TRUE@        ${parallel_srcdir}/workstealing.h
 
+
+# Profile mode headers
+profile_srcdir = ${glibcxx_srcdir}/include/profile
+profile_builddir = ./profile
+profile_headers = \
+    ${profile_srcdir}/base.h \
+    ${profile_srcdir}/unordered_map \
+    ${profile_srcdir}/unordered_set \
+    ${profile_srcdir}/vector \
+    ${profile_srcdir}/bitset \
+    ${profile_srcdir}/deque \
+    ${profile_srcdir}/list \
+    ${profile_srcdir}/map \
+    ${profile_srcdir}/map.h \
+    ${profile_srcdir}/multimap.h \
+    ${profile_srcdir}/multiset.h \
+    ${profile_srcdir}/set \
+    ${profile_srcdir}/set.h \
+    ${profile_srcdir}/hashtable.h
+profile_impl_srcdir = ${glibcxx_srcdir}/include/profile/impl
+profile_impl_builddir = ./profile/impl
+profile_impl_headers = \
+       ${profile_impl_srcdir}/profiler.h \
+       ${profile_impl_srcdir}/profiler_container_size.h \
+       ${profile_impl_srcdir}/profiler_hash_func.h \
+       ${profile_impl_srcdir}/profiler_hashtable_size.h \
+       ${profile_impl_srcdir}/profiler_map_to_unordered_map.h \
+       ${profile_impl_srcdir}/profiler_node.h \
+       ${profile_impl_srcdir}/profiler_state.h \
+       ${profile_impl_srcdir}/profiler_trace.h \
+       ${profile_impl_srcdir}/profiler_vector_size.h \
+       ${profile_impl_srcdir}/profiler_vector_to_list.h
+
 @GLIBCXX_C_HEADERS_EXTRA_FALSE@c_base_headers_extra = 
 
 # Some of the different "C" header models need extra files.
@@ -1083,7 +1116,8 @@ PCHFLAGS = -x c++-header $(CXXFLAGS)
 allstamped = \
        stamp-std stamp-bits stamp-c_base stamp-c_base_extra \
        stamp-c_compatibility  stamp-backward stamp-ext stamp-pb \
-       stamp-tr1 stamp-tr1-impl stamp-debug stamp-parallel stamp-host
+       stamp-tr1 stamp-tr1-impl stamp-debug stamp-parallel stamp-host \
+    stamp-profile stamp-profile-impl
 
 
 # List of all files that are created by explicit building, editing, or
@@ -1400,6 +1434,16 @@ stamp-parallel: ${parallel_headers}
        @-cd ${parallel_builddir} && $(LN_S) $? . 2>/dev/null
        @$(STAMP) stamp-parallel
 
+stamp-profile: ${profile_headers}
+       @-mkdir -p ${profile_builddir}
+       @-cd ${profile_builddir} && $(LN_S) $? . 2>/dev/null
+       @$(STAMP) stamp-profile
+
+stamp-profile-impl: ${profile_impl_headers}
+       @-mkdir -p ${profile_impl_builddir}
+       @-cd ${profile_impl_builddir} && $(LN_S) $? . 2>/dev/null
+       @$(STAMP) stamp-profile-impl
+
 stamp-${host_alias}:
        @-mkdir -p ${host_builddir}
        @$(STAMP) stamp-${host_alias}
@@ -1616,6 +1660,13 @@ install-headers:
          $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${parallel_builddir};\
        for file in $$parallel_headers_install; do \
          $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${parallel_builddir}; done
+       $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${profile_builddir} \
+               $(DESTDIR)${gxx_include_dir}/${profile_builddir}/impl
+       for file in ${profile_headers}; do \
+         $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${profile_builddir}; done
+       $(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${profile_impl_builddir}
+       for file in ${profile_impl_headers}; do \
+         $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${profile_impl_builddir}; done
        $(mkinstalldirs) $(DESTDIR)${host_installdir}
        for file in ${host_headers} ${host_headers_extra} \
         ${thread_host_headers}; do \
index 469429c..cb31687 100644 (file)
 
 #include "backward_warning.h"
 #include <bits/c++config.h>
+#ifdef _GLIBCXX_PROFILE
+#include <profile/hashtable.h>
+#else
 #include <backward/hashtable.h>
+#endif
 #include <bits/concept_check.h>
 
 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
index 32fa220..d2bd03b 100644 (file)
 
 #include "backward_warning.h"
 #include <bits/c++config.h>
+#ifdef _GLIBCXX_PROFILE
+#include <profile/hashtable.h>
+#else
 #include <backward/hashtable.h>
+#endif
 #include <bits/concept_check.h>
 
 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
index d5babc3..724f373 100644 (file)
 # define _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL 1
 #endif
 
+// Namespace association for profile
+#ifdef _GLIBCXX_PROFILE
+# define _GLIBCXX_NAMESPACE_ASSOCIATION_PROFILE 1
+#endif
+
 #define _GLIBCXX_NAMESPACE_ASSOCIATION_VERSION 
 
 // Defined if any namespace association modes are active.
 #if _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG \
   || _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL \
+  || _GLIBCXX_NAMESPACE_ASSOCIATION_PROFILE \
   || _GLIBCXX_NAMESPACE_ASSOCIATION_VERSION
 # define _GLIBCXX_USE_NAMESPACE_ASSOCIATION 1
 #endif
 #ifndef _GLIBCXX_USE_NAMESPACE_ASSOCIATION
 # define _GLIBCXX_STD_D _GLIBCXX_STD
 # define _GLIBCXX_STD_P _GLIBCXX_STD
+# define _GLIBCXX_STD_PR _GLIBCXX_STD
 # define _GLIBCXX_STD std
 # define _GLIBCXX_BEGIN_NESTED_NAMESPACE(X, Y) _GLIBCXX_BEGIN_NAMESPACE(X)
 # define _GLIBCXX_END_NESTED_NAMESPACE _GLIBCXX_END_NAMESPACE
 # endif
 
 //  debug
-# if _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG && !_GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL
+# if _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG && !_GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL && !_GLIBCXX_NAMESPACE_ASSOCIATION_PROFILE
 #  define _GLIBCXX_STD_D __norm
 #  define _GLIBCXX_STD_P _GLIBCXX_STD
 #  define _GLIBCXX_STD __cxx1998
 # endif
 
 // parallel
-# if _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL && !_GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG 
+# if _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL && !_GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG && !_GLIBCXX_NAMESPACE_ASSOCIATION_PROFILE
 #  define _GLIBCXX_STD_D _GLIBCXX_STD
 #  define _GLIBCXX_STD_P __norm
 #  define _GLIBCXX_STD __cxx1998
 # endif
 
 // debug + parallel
-# if _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL && _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG 
+# if _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL && _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG  && !_GLIBCXX_NAMESPACE_ASSOCIATION_PROFILE
 #  define _GLIBCXX_STD_D __norm
 #  define _GLIBCXX_STD_P __norm
 #  define _GLIBCXX_STD __cxx1998
 #  define _GLIBCXX_EXTERN_TEMPLATE -1
 # endif
 
+// profile
+# if _GLIBCXX_NAMESPACE_ASSOCIATION_PROFILE
+#  if _GLIBCXX_NAMESPACE_ASSOCIATION_PARALLEL || _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG
+#   error Cannot use -D_GLIBCXX_PROFILE with -D_GLIBCXX_DEBUG or \
+    -D_GLIBCXX_PARALLEL
+#  endif
+#  define _GLIBCXX_STD_D __norm
+#  define _GLIBCXX_STD_P _GLIBCXX_STD
+#  define _GLIBCXX_STD_PR __norm
+#  define _GLIBCXX_STD __cxx1998
+#  define _GLIBCXX_BEGIN_NAMESPACE(X) namespace X _GLIBCXX_VISIBILITY_ATTR(default) { 
+#  define _GLIBCXX_END_NAMESPACE }
+#  define _GLIBCXX_EXTERN_TEMPLATE -1
+# endif
+
 # if __NO_INLINE__ && !__GXX_WEAK__
 #  warning currently using namespace associated mode which may fail \
    without inlining due to lack of weak symbols
 #endif
 
 // Namespace associations for debug mode.
-#if _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG
+#if _GLIBCXX_NAMESPACE_ASSOCIATION_DEBUG && !_GLIBCXX_NAMESPACE_ASSOCIATION_PROFILE
 namespace std
 { 
   namespace __norm { } 
@@ -182,6 +204,16 @@ namespace std
 }
 #endif
 
+// Namespace associations for profile mode
+#if _GLIBCXX_NAMESPACE_ASSOCIATION_PROFILE
+namespace std
+{ 
+  namespace __norm { } 
+  inline namespace __profile { }
+  inline namespace __cxx1998 { }
+}
+#endif
+
 // Namespace associations for versioning mode.
 #if _GLIBCXX_NAMESPACE_ASSOCIATION_VERSION
 namespace std
diff --git a/libstdc++-v3/include/profile/base.h b/libstdc++-v3/include/profile/base.h
new file mode 100644 (file)
index 0000000..de7bfe9
--- /dev/null
@@ -0,0 +1,68 @@
+// -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/** @file profile/base.h
+ *  @brief Sequential helper functions.
+ *  This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+// Written by Lixia Liu
+
+#ifndef _GLIBCXX_PROFILE_BASE_H
+#define _GLIBCXX_PROFILE_BASE_H 1
+
+#include <cstdio>
+#include <functional>
+#include <bits/c++config.h>
+#include <profile/impl/profiler.h>
+
+// Profiling mode namespaces.
+
+/**
+ * @namespace std::__profile
+ * @brief GNU profile code, replaces standard behavior with profile behavior.
+ */
+namespace std 
+{ 
+  namespace __profile { } 
+}
+
+/**
+ * @namespace __gnu_profile
+ * @brief GNU profile code for public use.
+ */
+namespace __gnu_profile
+{
+  // Import all the profile versions of components in namespace std.
+  using namespace std::__profile;
+}
+
+
+#endif /* _GLIBCXX_PROFILE_BASE_H */
diff --git a/libstdc++-v3/include/profile/bitset b/libstdc++-v3/include/profile/bitset
new file mode 100644 (file)
index 0000000..96a59ea
--- /dev/null
@@ -0,0 +1,345 @@
+// Profiling bitset implementation -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file profile/bitset
+ *  This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_PROFILE_BITSET
+#define _GLIBCXX_PROFILE_BITSET
+
+#include <bitset>
+
+namespace std
+{
+namespace __profile
+{
+  /** @brief Bitset wrapper with performance instrumentation.  */
+  template<size_t _Nb>
+    class bitset
+    : public _GLIBCXX_STD_D::bitset<_Nb>
+    {
+      typedef _GLIBCXX_STD_D::bitset<_Nb> _Base;
+
+    public:
+      // bit reference:
+      class reference
+      : private _Base::reference
+      {
+       typedef typename _Base::reference _Base_ref;
+
+       friend class bitset;
+       reference();
+
+       reference(const _Base_ref& __base, bitset* __seq)
+       : _Base_ref(__base)
+       { }
+
+      public:
+       reference(const reference& __x)
+       : _Base_ref(__x)
+       { }
+
+       reference&
+       operator=(bool __x)
+       {
+         *static_cast<_Base_ref*>(this) = __x;
+         return *this;
+       }
+
+       reference&
+       operator=(const reference& __x)
+       {
+         *static_cast<_Base_ref*>(this) = __x;
+         return *this;
+       }
+
+       bool
+       operator~() const
+       {
+         return ~(*static_cast<const _Base_ref*>(this));
+       }
+
+       operator bool() const
+       {
+         return *static_cast<const _Base_ref*>(this);
+       }
+
+       reference&
+       flip()
+       {
+         _Base_ref::flip();
+         return *this;
+       }
+      };
+
+      // 23.3.5.1 constructors:
+      bitset() : _Base() { }
+
+      bitset(unsigned long __val) : _Base(__val) { }
+
+      template<typename _CharT, typename _Traits, typename _Alloc>
+        explicit
+        bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
+              typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
+              __pos = 0,
+              typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
+              __n = (std::basic_string<_CharT, _Traits, _Alloc>::npos))
+       : _Base(__str, __pos, __n) { }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 396. what are characters zero and one.
+      template<class _CharT, class _Traits, class _Alloc>
+       bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
+              typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
+              __pos,
+              typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
+              __n,
+              _CharT __zero, _CharT __one = _CharT('1'))
+       : _Base(__str, __pos, __n, __zero, __one) { }
+
+      bitset(const _Base& __x) : _Base(__x) { }
+
+      // 23.3.5.2 bitset operations:
+      bitset<_Nb>&
+      operator&=(const bitset<_Nb>& __rhs)
+      {
+       _M_base() &= __rhs;
+       return *this;
+      }
+
+      bitset<_Nb>&
+      operator|=(const bitset<_Nb>& __rhs)
+      {
+       _M_base() |= __rhs;
+       return *this;
+      }
+
+      bitset<_Nb>&
+      operator^=(const bitset<_Nb>& __rhs)
+      {
+       _M_base() ^= __rhs;
+       return *this;
+      }
+
+      bitset<_Nb>&
+      operator<<=(size_t __pos)
+      {
+       _M_base() <<= __pos;
+       return *this;
+      }
+
+      bitset<_Nb>&
+      operator>>=(size_t __pos)
+      {
+       _M_base() >>= __pos;
+       return *this;
+      }
+
+      bitset<_Nb>&
+      set()
+      {
+       _Base::set();
+       return *this;
+      }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 186. bitset::set() second parameter should be bool
+      bitset<_Nb>&
+      set(size_t __pos, bool __val = true)
+      {
+       _Base::set(__pos, __val);
+       return *this;
+      }
+
+      bitset<_Nb>&
+      reset()
+      {
+       _Base::reset();
+       return *this;
+      }
+
+      bitset<_Nb>&
+      reset(size_t __pos)
+      {
+       _Base::reset(__pos);
+       return *this;
+      }
+
+      bitset<_Nb> operator~() const { return bitset(~_M_base()); }
+
+      bitset<_Nb>&
+      flip()
+      {
+       _Base::flip();
+       return *this;
+      }
+
+      bitset<_Nb>&
+      flip(size_t __pos)
+      {
+       _Base::flip(__pos);
+       return *this;
+      }
+
+      // element access:
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 11. Bitset minor problems
+      reference
+      operator[](size_t __pos)
+      {
+       return reference(_M_base()[__pos], this);
+      }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 11. Bitset minor problems
+      bool
+      operator[](size_t __pos) const
+      {
+       return _M_base()[__pos];
+      }
+
+      using _Base::to_ulong;
+
+      template <typename _CharT, typename _Traits, typename _Alloc>
+        std::basic_string<_CharT, _Traits, _Alloc>
+        to_string() const
+        { return _M_base().template to_string<_CharT, _Traits, _Alloc>(); }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 396. what are characters zero and one.
+      template<class _CharT, class _Traits, class _Alloc>
+       std::basic_string<_CharT, _Traits, _Alloc>
+       to_string(_CharT __zero, _CharT __one = _CharT('1')) const
+       {
+         return _M_base().template
+           to_string<_CharT, _Traits, _Alloc>(__zero, __one);
+       }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 434. bitset::to_string() hard to use.
+      template<typename _CharT, typename _Traits>
+        std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
+        to_string() const
+        { return to_string<_CharT, _Traits, std::allocator<_CharT> >(); }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 853. to_string needs updating with zero and one.
+      template<class _CharT, class _Traits>
+       std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
+       to_string(_CharT __zero, _CharT __one = _CharT('1')) const
+       { return to_string<_CharT, _Traits,
+                          std::allocator<_CharT> >(__zero, __one); }
+
+      template<typename _CharT>
+        std::basic_string<_CharT, std::char_traits<_CharT>,
+                          std::allocator<_CharT> >
+        to_string() const
+        {
+          return to_string<_CharT, std::char_traits<_CharT>,
+                           std::allocator<_CharT> >();
+        }
+
+      template<class _CharT>
+       std::basic_string<_CharT, std::char_traits<_CharT>,
+                         std::allocator<_CharT> >
+       to_string(_CharT __zero, _CharT __one = _CharT('1')) const
+       {
+         return to_string<_CharT, std::char_traits<_CharT>,
+                          std::allocator<_CharT> >(__zero, __one);
+       }
+
+      std::basic_string<char, std::char_traits<char>, std::allocator<char> >
+      to_string() const
+      {
+       return to_string<char,std::char_traits<char>,std::allocator<char> >();
+      }
+
+      std::basic_string<char, std::char_traits<char>, std::allocator<char> >
+      to_string(char __zero, char __one = '1') const
+      {
+       return to_string<char, std::char_traits<char>,
+                        std::allocator<char> >(__zero, __one);
+      }
+
+      using _Base::count;
+      using _Base::size;
+
+      bool
+      operator==(const bitset<_Nb>& __rhs) const
+      { return _M_base() == __rhs; }
+
+      bool
+      operator!=(const bitset<_Nb>& __rhs) const
+      { return _M_base() != __rhs; }
+
+      using _Base::test;
+      using _Base::all;
+      using _Base::any;
+      using _Base::none;
+
+      bitset<_Nb>
+      operator<<(size_t __pos) const
+      { return bitset<_Nb>(_M_base() << __pos); }
+
+      bitset<_Nb>
+      operator>>(size_t __pos) const
+      { return bitset<_Nb>(_M_base() >> __pos); }
+
+      _Base&
+      _M_base() { return *this; }
+
+      const _Base&
+      _M_base() const { return *this; }
+    };
+
+  template<size_t _Nb>
+    bitset<_Nb>
+    operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y)
+    { return bitset<_Nb>(__x) &= __y; }
+
+  template<size_t _Nb>
+    bitset<_Nb>
+    operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y)
+    { return bitset<_Nb>(__x) |= __y; }
+
+  template<size_t _Nb>
+    bitset<_Nb>
+    operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y)
+    { return bitset<_Nb>(__x) ^= __y; }
+
+  template<typename _CharT, typename _Traits, size_t _Nb>
+    std::basic_istream<_CharT, _Traits>&
+    operator>>(std::basic_istream<_CharT, _Traits>& __is, bitset<_Nb>& __x)
+    { return __is >> __x._M_base(); }
+
+  template<typename _CharT, typename _Traits, size_t _Nb>
+    std::basic_ostream<_CharT, _Traits>&
+    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
+              const bitset<_Nb>& __x)
+    { return __os << __x._M_base(); }
+} // namespace __profile
+} // namespace std
+
+#endif
diff --git a/libstdc++-v3/include/profile/deque b/libstdc++-v3/include/profile/deque
new file mode 100644 (file)
index 0000000..6ba3679
--- /dev/null
@@ -0,0 +1,420 @@
+// Profiling deque implementation -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file profile/deque
+ *  This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_PROFILE_DEQUE
+#define _GLIBCXX_PROFILE_DEQUE 1
+
+#include <deque>
+
+namespace std
+{
+namespace __profile
+{
+  /** @brief Deque wrapper with performance instrumentation.  */
+  template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
+    class deque
+    : public _GLIBCXX_STD_D::deque<_Tp, _Allocator>
+    {
+      typedef  _GLIBCXX_STD_D::deque<_Tp, _Allocator> _Base;
+
+    public:
+      typedef typename _Base::reference             reference;
+      typedef typename _Base::const_reference       const_reference;
+
+      typedef typename _Base::iterator             iterator;
+      typedef typename _Base::const_iterator       const_iterator;
+      typedef typename _Base::reverse_iterator     reverse_iterator;
+      typedef typename _Base::const_reverse_iterator const_reverse_iterator;
+
+      typedef typename _Base::size_type             size_type;
+      typedef typename _Base::difference_type       difference_type;
+
+      typedef _Tp                                  value_type;
+      typedef _Allocator                           allocator_type;
+      typedef typename _Base::pointer               pointer;
+      typedef typename _Base::const_pointer         const_pointer;
+
+      // 23.2.1.1 construct/copy/destroy:
+      explicit deque(const _Allocator& __a = _Allocator())
+      : _Base(__a) { }
+
+      explicit deque(size_type __n, const _Tp& __value = _Tp(),
+                    const _Allocator& __a = _Allocator())
+      : _Base(__n, __value, __a) { }
+
+      template<class _InputIterator>
+        deque(_InputIterator __first, _InputIterator __last,
+             const _Allocator& __a = _Allocator())
+       : _Base(__first, __last, __a)
+        { }
+
+      deque(const deque& __x)
+      : _Base(__x) { }
+
+      deque(const _Base& __x)
+      : _Base(__x) { }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      deque(deque&& __x)
+      : _Base(std::forward<deque>(__x))
+      { }
+
+      deque(initializer_list<value_type> __l,
+           const allocator_type& __a = allocator_type())
+      : _Base(__l, __a) { }
+#endif
+
+      ~deque() { }
+
+      deque&
+      operator=(const deque& __x)
+      {
+       *static_cast<_Base*>(this) = __x;
+       return *this;
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      deque&
+      operator=(deque&& __x)
+      {
+        // NB: DR 675.
+       this->clear();
+       this->swap(__x);          
+       return *this;
+      }
+
+      deque&
+      operator=(initializer_list<value_type> __l)
+      {
+       *static_cast<_Base*>(this) = __l;
+       return *this;
+      }
+#endif
+
+      template<class _InputIterator>
+        void
+        assign(_InputIterator __first, _InputIterator __last)
+        {
+         _Base::assign(__first, __last);
+       }
+
+      void
+      assign(size_type __n, const _Tp& __t)
+      {
+       _Base::assign(__n, __t);
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      void
+      assign(initializer_list<value_type> __l)
+      {
+       _Base::assign(__l);
+      }
+#endif
+
+      using _Base::get_allocator;
+
+      // iterators:
+      iterator
+      begin()
+      { return iterator(_Base::begin()); }
+
+      const_iterator
+      begin() const
+      { return const_iterator(_Base::begin()); }
+
+      iterator
+      end()
+      { return iterator(_Base::end()); }
+
+      const_iterator
+      end() const
+      { return const_iterator(_Base::end()); }
+
+      reverse_iterator
+      rbegin()
+      { return reverse_iterator(end()); }
+
+      const_reverse_iterator
+      rbegin() const
+      { return const_reverse_iterator(end()); }
+
+      reverse_iterator
+      rend()
+      { return reverse_iterator(begin()); }
+
+      const_reverse_iterator
+      rend() const
+      { return const_reverse_iterator(begin()); }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      const_iterator
+      cbegin() const
+      { return const_iterator(_Base::begin()); }
+
+      const_iterator
+      cend() const
+      { return const_iterator(_Base::end()); }
+
+      const_reverse_iterator
+      crbegin() const
+      { return const_reverse_iterator(end()); }
+
+      const_reverse_iterator
+      crend() const
+      { return const_reverse_iterator(begin()); }
+#endif
+
+      // 23.2.1.2 capacity:
+      using _Base::size;
+      using _Base::max_size;
+
+      void
+      resize(size_type __sz, _Tp __c = _Tp())
+      {
+       _Base::resize(__sz, __c);
+      }
+
+      using _Base::empty;
+
+      // element access:
+      reference
+      operator[](size_type __n)
+      {
+       return _M_base()[__n];
+      }
+
+      const_reference
+      operator[](size_type __n) const
+      {
+       return _M_base()[__n];
+      }
+
+      using _Base::at;
+
+      reference
+      front()
+      {
+       return _Base::front();
+      }
+
+      const_reference
+      front() const
+      {
+       return _Base::front();
+      }
+
+      reference
+      back()
+      {
+       return _Base::back();
+      }
+
+      const_reference
+      back() const
+      {
+       return _Base::back();
+      }
+
+      // 23.2.1.3 modifiers:
+      void
+      push_front(const _Tp& __x)
+      {
+       _Base::push_front(__x);
+      }
+
+      void
+      push_back(const _Tp& __x)
+      {
+       _Base::push_back(__x);
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      void
+      push_front(_Tp&& __x)
+      { emplace_front(std::move(__x)); }
+
+      void
+      push_back(_Tp&& __x)
+      { emplace_back(std::move(__x)); }
+
+      template<typename... _Args>
+        void
+        emplace_front(_Args&&... __args)
+       {
+         _Base::emplace_front(std::forward<_Args>(__args)...);
+       }
+
+      template<typename... _Args>
+        void
+        emplace_back(_Args&&... __args)
+       {
+         _Base::emplace_back(std::forward<_Args>(__args)...);
+       }
+
+      template<typename... _Args>
+        iterator
+        emplace(iterator __position, _Args&&... __args)
+       {
+         typename _Base::iterator __res = _Base::emplace(__position,
+                                           std::forward<_Args>(__args)...);
+         return iterator(__res);
+       }
+#endif
+
+      iterator
+      insert(iterator __position, const _Tp& __x)
+      {
+       typename _Base::iterator __res = _Base::insert(__position, __x);
+       return iterator(__res);
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      iterator
+      insert(iterator __position, _Tp&& __x)
+      { return emplace(__position, std::move(__x)); }
+
+      void
+      insert(iterator __p, initializer_list<value_type> __l)
+      {
+       _Base::insert(__p, __l);
+      }
+#endif
+
+      void
+      insert(iterator __position, size_type __n, const _Tp& __x)
+      {
+       _Base::insert(__position, __n, __x);
+      }
+
+      template<class _InputIterator>
+        void
+        insert(iterator __position,
+              _InputIterator __first, _InputIterator __last)
+        {
+         _Base::insert(__position, __first, __last);
+       }
+
+      void
+      pop_front()
+      {
+       _Base::pop_front();
+      }
+
+      void
+      pop_back()
+      {
+       _Base::pop_back();
+      }
+
+      iterator
+      erase(iterator __position)
+      {
+       if (__position == begin() || __position == end()-1)
+         {
+           return iterator(_Base::erase(__position));
+         }
+       else
+         {
+           typename _Base::iterator __res = _Base::erase(__position);
+           return iterator(__res);
+         }
+      }
+
+      iterator
+      erase(iterator __first, iterator __last)
+      {
+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
+       // 151. can't currently clear() empty container
+        return iterator(_Base::erase(__first, __last));
+      }
+
+      void
+      swap(deque& __x)
+      {
+       _Base::swap(__x);
+      }
+
+      void
+      clear()
+      {
+       _Base::clear();
+      }
+
+      _Base&
+      _M_base()       { return *this; }
+
+      const _Base&
+      _M_base() const { return *this; }
+    };
+
+  template<typename _Tp, typename _Alloc>
+    inline bool
+    operator==(const deque<_Tp, _Alloc>& __lhs,
+              const deque<_Tp, _Alloc>& __rhs)
+    { return __lhs._M_base() == __rhs._M_base(); }
+
+  template<typename _Tp, typename _Alloc>
+    inline bool
+    operator!=(const deque<_Tp, _Alloc>& __lhs,
+              const deque<_Tp, _Alloc>& __rhs)
+    { return __lhs._M_base() != __rhs._M_base(); }
+
+  template<typename _Tp, typename _Alloc>
+    inline bool
+    operator<(const deque<_Tp, _Alloc>& __lhs,
+             const deque<_Tp, _Alloc>& __rhs)
+    { return __lhs._M_base() < __rhs._M_base(); }
+
+  template<typename _Tp, typename _Alloc>
+    inline bool
+    operator<=(const deque<_Tp, _Alloc>& __lhs,
+              const deque<_Tp, _Alloc>& __rhs)
+    { return __lhs._M_base() <= __rhs._M_base(); }
+
+  template<typename _Tp, typename _Alloc>
+    inline bool
+    operator>=(const deque<_Tp, _Alloc>& __lhs,
+              const deque<_Tp, _Alloc>& __rhs)
+    { return __lhs._M_base() >= __rhs._M_base(); }
+
+  template<typename _Tp, typename _Alloc>
+    inline bool
+    operator>(const deque<_Tp, _Alloc>& __lhs,
+             const deque<_Tp, _Alloc>& __rhs)
+    { return __lhs._M_base() > __rhs._M_base(); }
+
+  template<typename _Tp, typename _Alloc>
+    inline void
+    swap(deque<_Tp, _Alloc>& __lhs, deque<_Tp, _Alloc>& __rhs)
+    { __lhs.swap(__rhs); }
+
+} // namespace __profile
+} // namespace std
+
+#endif
diff --git a/libstdc++-v3/include/profile/hashtable.h b/libstdc++-v3/include/profile/hashtable.h
new file mode 100644 (file)
index 0000000..2089187
--- /dev/null
@@ -0,0 +1,1151 @@
+// Hashtable implementation used by containers -*- C++ -*-
+
+// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
+// Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+/*
+ * Copyright (c) 1996,1997
+ * Silicon Graphics Computer Systems, Inc.
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Silicon Graphics makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ *
+ * Copyright (c) 1994
+ * Hewlett-Packard Company
+ *
+ * Permission to use, copy, modify, distribute and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear
+ * in supporting documentation.  Hewlett-Packard Company makes no
+ * representations about the suitability of this software for any
+ * purpose.  It is provided "as is" without express or implied warranty.
+ *
+ */
+
+/** @file profile/hashtable.h copied from backward/hashtable.h
+ *  This file is a GNU extension to the Standard C++ Library (possibly
+ *  containing extensions from the HP/SGI STL subset).
+ */
+
+#ifndef _HASHTABLE_H
+#define _HASHTABLE_H 1
+
+// Hashtable class, used to implement the hashed associative containers
+// hash_set, hash_map, hash_multiset, and hash_multimap.
+// Skip instrumentation on vector.
+#include <vector>
+#include <iterator>
+#include <algorithm>
+#include <bits/stl_function.h>
+#include <backward/hash_fun.h>
+#include <profile/base.h>
+
+_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
+
+  using std::size_t;
+  using std::ptrdiff_t;
+  using std::forward_iterator_tag;
+  using std::input_iterator_tag;
+  using std::_Construct;
+  using std::_Destroy;
+  using std::distance;
+  using std::_GLIBCXX_STD_D::vector;
+  using std::pair;
+  using std::__iterator_category;
+
+  template<class _Val>
+    struct _Hashtable_node
+    {
+      _Hashtable_node* _M_next;
+      _Val _M_val;
+    };
+
+  template<class _Val, class _Key, class _HashFcn, class _ExtractKey, 
+          class _EqualKey, class _Alloc = std::allocator<_Val> >
+    class hashtable;
+
+  template<class _Val, class _Key, class _HashFcn,
+          class _ExtractKey, class _EqualKey, class _Alloc>
+    struct _Hashtable_iterator;
+
+  template<class _Val, class _Key, class _HashFcn,
+          class _ExtractKey, class _EqualKey, class _Alloc>
+    struct _Hashtable_const_iterator;
+
+  template<class _Val, class _Key, class _HashFcn,
+          class _ExtractKey, class _EqualKey, class _Alloc>
+    struct _Hashtable_iterator
+    {
+      typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>
+        _Hashtable;
+      typedef _Hashtable_iterator<_Val, _Key, _HashFcn,
+                                 _ExtractKey, _EqualKey, _Alloc>
+        iterator;
+      typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
+                                       _ExtractKey, _EqualKey, _Alloc>
+        const_iterator;
+      typedef _Hashtable_node<_Val> _Node;
+      typedef forward_iterator_tag iterator_category;
+      typedef _Val value_type;
+      typedef ptrdiff_t difference_type;
+      typedef size_t size_type;
+      typedef _Val& reference;
+      typedef _Val* pointer;
+      
+      _Node* _M_cur;
+      _Hashtable* _M_ht;
+
+      _Hashtable_iterator(_Node* __n, _Hashtable* __tab)
+      : _M_cur(__n), _M_ht(__tab) { }
+
+      _Hashtable_iterator() { }
+
+      reference
+      operator*() const
+      { return _M_cur->_M_val; }
+
+      pointer
+      operator->() const
+      { return &(operator*()); }
+
+      iterator&
+      operator++();
+
+      iterator
+      operator++(int);
+
+      bool
+      operator==(const iterator& __it) const
+      { return _M_cur == __it._M_cur; }
+
+      bool
+      operator!=(const iterator& __it) const
+      { return _M_cur != __it._M_cur; }
+    };
+
+  template<class _Val, class _Key, class _HashFcn,
+          class _ExtractKey, class _EqualKey, class _Alloc>
+    struct _Hashtable_const_iterator
+    {
+      typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>
+        _Hashtable;
+      typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
+                                 _ExtractKey,_EqualKey,_Alloc>
+        iterator;
+      typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
+                                       _ExtractKey, _EqualKey, _Alloc>
+        const_iterator;
+      typedef _Hashtable_node<_Val> _Node;
+
+      typedef forward_iterator_tag iterator_category;
+      typedef _Val value_type;
+      typedef ptrdiff_t difference_type;
+      typedef size_t size_type;
+      typedef const _Val& reference;
+      typedef const _Val* pointer;
+      
+      const _Node* _M_cur;
+      const _Hashtable* _M_ht;
+
+      _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
+      : _M_cur(__n), _M_ht(__tab) { }
+
+      _Hashtable_const_iterator() { }
+
+      _Hashtable_const_iterator(const iterator& __it)
+      : _M_cur(__it._M_cur), _M_ht(__it._M_ht) { }
+
+      reference
+      operator*() const
+      { return _M_cur->_M_val; }
+
+      pointer
+      operator->() const
+      { return &(operator*()); }
+
+      const_iterator&
+      operator++();
+
+      const_iterator
+      operator++(int);
+
+      bool
+      operator==(const const_iterator& __it) const
+      { return _M_cur == __it._M_cur; }
+
+      bool
+      operator!=(const const_iterator& __it) const
+      { return _M_cur != __it._M_cur; }
+    };
+
+  // Note: assumes long is at least 32 bits.
+  enum { _S_num_primes = 28 };
+
+  static const unsigned long __stl_prime_list[_S_num_primes] =
+    {
+      53ul,         97ul,         193ul,       389ul,       769ul,
+      1543ul,       3079ul,       6151ul,      12289ul,     24593ul,
+      49157ul,      98317ul,      196613ul,    393241ul,    786433ul,
+      1572869ul,    3145739ul,    6291469ul,   12582917ul,  25165843ul,
+      50331653ul,   100663319ul,  201326611ul, 402653189ul, 805306457ul,
+      1610612741ul, 3221225473ul, 4294967291ul
+    };
+
+  inline unsigned long
+  __stl_next_prime(unsigned long __n)
+  {
+    const unsigned long* __first = __stl_prime_list;
+    const unsigned long* __last = __stl_prime_list + (int)_S_num_primes;
+    const unsigned long* pos = std::lower_bound(__first, __last, __n);
+    return pos == __last ? *(__last - 1) : *pos;
+  }
+
+  // Forward declaration of operator==.  
+  template<class _Val, class _Key, class _HF, class _Ex,
+          class _Eq, class _All>
+    class hashtable;
+
+  template<class _Val, class _Key, class _HF, class _Ex,
+          class _Eq, class _All>
+    bool
+    operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
+              const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2);
+
+  // Hashtables handle allocators a bit differently than other
+  // containers do.  If we're using standard-conforming allocators, then
+  // a hashtable unconditionally has a member variable to hold its
+  // allocator, even if it so happens that all instances of the
+  // allocator type are identical.  This is because, for hashtables,
+  // this extra storage is negligible.  Additionally, a base class
+  // wouldn't serve any other purposes; it wouldn't, for example,
+  // simplify the exception-handling code.  
+  template<class _Val, class _Key, class _HashFcn,
+          class _ExtractKey, class _EqualKey, class _Alloc>
+    class hashtable
+    {
+    public:
+      typedef _Key key_type;
+      typedef _Val value_type;
+      typedef _HashFcn hasher;
+      typedef _EqualKey key_equal;
+
+      typedef size_t            size_type;
+      typedef ptrdiff_t         difference_type;
+      typedef value_type*       pointer;
+      typedef const value_type* const_pointer;
+      typedef value_type&       reference;
+      typedef const value_type& const_reference;
+
+      hasher
+      hash_funct() const
+      { return _M_hash; }
+
+      key_equal
+      key_eq() const
+      { return _M_equals; }
+
+    private:
+      typedef _Hashtable_node<_Val> _Node;
+
+    public:
+      typedef typename _Alloc::template rebind<value_type>::other allocator_type;
+      allocator_type
+      get_allocator() const
+      { return _M_node_allocator; }
+
+    private:
+      typedef typename _Alloc::template rebind<_Node>::other _Node_Alloc;
+      typedef typename _Alloc::template rebind<_Node*>::other _Nodeptr_Alloc;
+      typedef vector<_Node*, _Nodeptr_Alloc> _Vector_type;
+
+      _Node_Alloc _M_node_allocator;
+
+      _Node*
+      _M_get_node()
+      { return _M_node_allocator.allocate(1); }
+
+      void
+      _M_put_node(_Node* __p)
+      { _M_node_allocator.deallocate(__p, 1); }
+
+    private:
+      hasher                _M_hash;
+      key_equal             _M_equals;
+      _ExtractKey           _M_get_key;
+      _Vector_type          _M_buckets;
+      size_type             _M_num_elements;
+      
+    public:
+      typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey,
+                                 _EqualKey, _Alloc>
+        iterator;
+      typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
+                                       _EqualKey, _Alloc>
+        const_iterator;
+
+      friend struct
+      _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>;
+
+      friend struct
+      _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
+                               _EqualKey, _Alloc>;
+
+    public:
+      hashtable(size_type __n, const _HashFcn& __hf,
+               const _EqualKey& __eql, const _ExtractKey& __ext,
+               const allocator_type& __a = allocator_type())
+      : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql),
+       _M_get_key(__ext), _M_buckets(__a), _M_num_elements(0)
+      { _M_initialize_buckets(__n); }
+
+      hashtable(size_type __n, const _HashFcn& __hf,
+               const _EqualKey& __eql,
+               const allocator_type& __a = allocator_type())
+      : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql),
+       _M_get_key(_ExtractKey()), _M_buckets(__a), _M_num_elements(0)
+      { _M_initialize_buckets(__n); }
+
+      hashtable(const hashtable& __ht)
+      : _M_node_allocator(__ht.get_allocator()), _M_hash(__ht._M_hash),
+      _M_equals(__ht._M_equals), _M_get_key(__ht._M_get_key),
+      _M_buckets(__ht.get_allocator()), _M_num_elements(0)
+      { _M_copy_from(__ht); }
+
+      hashtable&
+      operator= (const hashtable& __ht)
+      {
+       if (&__ht != this)
+         {
+           clear();
+           _M_hash = __ht._M_hash;
+           _M_equals = __ht._M_equals;
+           _M_get_key = __ht._M_get_key;
+           _M_copy_from(__ht);
+         }
+       return *this;
+      }
+
+      ~hashtable()
+      { clear(); }
+
+      size_type
+      size() const
+      { return _M_num_elements; }
+
+      size_type
+      max_size() const
+      { return size_type(-1); }
+
+      bool
+      empty() const
+      { return size() == 0; }
+
+      void
+      swap(hashtable& __ht)
+      {
+       std::swap(_M_hash, __ht._M_hash);
+       std::swap(_M_equals, __ht._M_equals);
+       std::swap(_M_get_key, __ht._M_get_key);
+       _M_buckets.swap(__ht._M_buckets);
+       std::swap(_M_num_elements, __ht._M_num_elements);
+      }
+
+      iterator
+      begin()
+      {
+       for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
+         if (_M_buckets[__n])
+           return iterator(_M_buckets[__n], this);
+       return end();
+      }
+
+      iterator
+      end()
+      { return iterator(0, this); }
+
+      const_iterator
+      begin() const
+      {
+       for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
+         if (_M_buckets[__n])
+           return const_iterator(_M_buckets[__n], this);
+       return end();
+      }
+
+      const_iterator
+      end() const
+      { return const_iterator(0, this); }
+
+      template<class _Vl, class _Ky, class _HF, class _Ex, class _Eq,
+               class _Al>
+        friend bool
+        operator==(const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,
+                  const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
+
+    public:
+      size_type
+      bucket_count() const
+      { return _M_buckets.size(); }
+
+      size_type
+      max_bucket_count() const
+      { return __stl_prime_list[(int)_S_num_primes - 1]; }
+
+      size_type
+      elems_in_bucket(size_type __bucket) const
+      {
+       size_type __result = 0;
+       for (_Node* __n = _M_buckets[__bucket]; __n; __n = __n->_M_next)
+         __result += 1;
+       return __result;
+      }
+
+      pair<iterator, bool>
+      insert_unique(const value_type& __obj)
+      {
+       resize(_M_num_elements + 1);
+       return insert_unique_noresize(__obj);
+      }
+
+      iterator
+      insert_equal(const value_type& __obj)
+      {
+       resize(_M_num_elements + 1);
+       return insert_equal_noresize(__obj);
+      }
+
+      pair<iterator, bool>
+      insert_unique_noresize(const value_type& __obj);
+
+      iterator
+      insert_equal_noresize(const value_type& __obj);
+
+      template<class _InputIterator>
+        void
+        insert_unique(_InputIterator __f, _InputIterator __l)
+        { insert_unique(__f, __l, __iterator_category(__f)); }
+
+      template<class _InputIterator>
+        void
+        insert_equal(_InputIterator __f, _InputIterator __l)
+        { insert_equal(__f, __l, __iterator_category(__f)); }
+
+      template<class _InputIterator>
+        void
+        insert_unique(_InputIterator __f, _InputIterator __l,
+                     input_iterator_tag)
+        {
+         for ( ; __f != __l; ++__f)
+           insert_unique(*__f);
+       }
+
+      template<class _InputIterator>
+        void
+        insert_equal(_InputIterator __f, _InputIterator __l,
+                    input_iterator_tag)
+        {
+         for ( ; __f != __l; ++__f)
+           insert_equal(*__f);
+       }
+
+      template<class _ForwardIterator>
+        void
+        insert_unique(_ForwardIterator __f, _ForwardIterator __l,
+                     forward_iterator_tag)
+        {
+         size_type __n = distance(__f, __l);
+         resize(_M_num_elements + __n);
+         for ( ; __n > 0; --__n, ++__f)
+           insert_unique_noresize(*__f);
+       }
+
+      template<class _ForwardIterator>
+        void
+        insert_equal(_ForwardIterator __f, _ForwardIterator __l,
+                    forward_iterator_tag)
+        {
+         size_type __n = distance(__f, __l);
+         resize(_M_num_elements + __n);
+         for ( ; __n > 0; --__n, ++__f)
+           insert_equal_noresize(*__f);
+       }
+
+      reference
+      find_or_insert(const value_type& __obj);
+
+      iterator
+      find(const key_type& __key)
+      {
+       size_type __n = _M_bkt_num_key(__key);
+       _Node* __first;
+       for (__first = _M_buckets[__n];
+            __first && !_M_equals(_M_get_key(__first->_M_val), __key);
+            __first = __first->_M_next)
+         { }
+       return iterator(__first, this);
+      }
+
+      const_iterator
+      find(const key_type& __key) const
+      {
+       size_type __n = _M_bkt_num_key(__key);
+       const _Node* __first;
+       for (__first = _M_buckets[__n];
+            __first && !_M_equals(_M_get_key(__first->_M_val), __key);
+            __first = __first->_M_next)
+         { }
+       return const_iterator(__first, this);
+      }
+
+      size_type
+      count(const key_type& __key) const
+      {
+       const size_type __n = _M_bkt_num_key(__key);
+       size_type __result = 0;
+       
+       for (const _Node* __cur = _M_buckets[__n]; __cur;
+            __cur = __cur->_M_next)
+         if (_M_equals(_M_get_key(__cur->_M_val), __key))
+           ++__result;
+       return __result;
+      }
+
+      pair<iterator, iterator>
+      equal_range(const key_type& __key);
+
+      pair<const_iterator, const_iterator>
+      equal_range(const key_type& __key) const;
+
+      size_type
+      erase(const key_type& __key);
+      
+      void
+      erase(const iterator& __it);
+
+      void
+      erase(iterator __first, iterator __last);
+
+      void
+      erase(const const_iterator& __it);
+
+      void
+      erase(const_iterator __first, const_iterator __last);
+
+      void
+      resize(size_type __num_elements_hint);
+
+      void
+      clear();
+
+    private:
+      size_type
+      _M_next_size(size_type __n) const
+      { return __stl_next_prime(__n); }
+
+      void
+      _M_initialize_buckets(size_type __n)
+      {
+       const size_type __n_buckets = _M_next_size(__n);
+       _M_buckets.reserve(__n_buckets);
+       _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0);
+       _M_num_elements = 0;
+        __profcxx_hashtable_construct(this, __n_buckets);
+        __profcxx_hashtable_construct2(this);
+      }
+
+      size_type
+      _M_bkt_num_key(const key_type& __key) const
+      { return _M_bkt_num_key(__key, _M_buckets.size()); }
+
+      size_type
+      _M_bkt_num(const value_type& __obj) const
+      { return _M_bkt_num_key(_M_get_key(__obj)); }
+
+      size_type
+      _M_bkt_num_key(const key_type& __key, size_t __n) const
+      { return _M_hash(__key) % __n; }
+
+      size_type
+      _M_bkt_num(const value_type& __obj, size_t __n) const
+      { return _M_bkt_num_key(_M_get_key(__obj), __n); }
+
+      _Node*
+      _M_new_node(const value_type& __obj)
+      {
+       _Node* __n = _M_get_node();
+       __n->_M_next = 0;
+       try
+         {
+           this->get_allocator().construct(&__n->_M_val, __obj);
+           return __n;
+         }
+       catch(...)
+         {
+           _M_put_node(__n);
+           __throw_exception_again;
+         }
+      }
+
+      void
+      _M_delete_node(_Node* __n)
+      {
+       this->get_allocator().destroy(&__n->_M_val);
+       _M_put_node(__n);
+      }
+      
+      void
+      _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);
+
+      void
+      _M_erase_bucket(const size_type __n, _Node* __last);
+
+      void
+      _M_copy_from(const hashtable& __ht);
+    };
+
+  template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
+           class _All>
+    _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
+    _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
+    operator++()
+    {
+      const _Node* __old = _M_cur;
+      _M_cur = _M_cur->_M_next;
+      if (!_M_cur)
+       {
+         size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
+         while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
+           _M_cur = _M_ht->_M_buckets[__bucket];
+       }
+      return *this;
+    }
+
+  template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
+           class _All>
+    inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
+    _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
+    operator++(int)
+    {
+      iterator __tmp = *this;
+      ++*this;
+      return __tmp;
+    }
+
+  template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
+           class _All>
+    _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
+    _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
+    operator++()
+    {
+      const _Node* __old = _M_cur;
+      _M_cur = _M_cur->_M_next;
+      if (!_M_cur)
+       {
+         size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
+         while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
+           _M_cur = _M_ht->_M_buckets[__bucket];
+       }
+      return *this;
+    }
+
+  template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
+           class _All>
+    inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
+    _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
+    operator++(int)
+    {
+      const_iterator __tmp = *this;
+      ++*this;
+      return __tmp;
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    bool
+    operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
+              const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2)
+    {
+      typedef typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_Node _Node;
+
+      if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
+       return false;
+
+      for (size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n)
+       {
+         _Node* __cur1 = __ht1._M_buckets[__n];
+         _Node* __cur2 = __ht2._M_buckets[__n];
+         // Check same length of lists
+         for (; __cur1 && __cur2;
+              __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
+           { } 
+         if (__cur1 || __cur2)
+           return false;
+         // Now check one's elements are in the other
+         for (__cur1 = __ht1._M_buckets[__n] ; __cur1;
+              __cur1 = __cur1->_M_next)
+           {
+             bool _found__cur1 = false;
+             for (__cur2 = __ht2._M_buckets[__n];
+                  __cur2; __cur2 = __cur2->_M_next)
+               {
+                 if (__cur1->_M_val == __cur2->_M_val)
+                   {
+                     _found__cur1 = true;
+                     break;
+                   }
+               }
+             if (!_found__cur1)
+               return false;
+           }
+       }
+      return true;
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    inline bool
+    operator!=(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
+              const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2)
+    { return !(__ht1 == __ht2); }
+
+  template<class _Val, class _Key, class _HF, class _Extract, class _EqKey,
+           class _All>
+    inline void
+    swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
+        hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2)
+    { __ht1.swap(__ht2); }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator, bool>
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    insert_unique_noresize(const value_type& __obj)
+    {
+      const size_type __n = _M_bkt_num(__obj);
+      _Node* __first = _M_buckets[__n];
+      
+      for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
+       if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
+         return pair<iterator, bool>(iterator(__cur, this), false);
+      
+      _Node* __tmp = _M_new_node(__obj);
+      __tmp->_M_next = __first;
+      _M_buckets[__n] = __tmp;
+      ++_M_num_elements;
+      return pair<iterator, bool>(iterator(__tmp, this), true);
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    insert_equal_noresize(const value_type& __obj)
+    {
+      const size_type __n = _M_bkt_num(__obj);
+      _Node* __first = _M_buckets[__n];
+      
+      for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
+       if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
+         {
+           _Node* __tmp = _M_new_node(__obj);
+           __tmp->_M_next = __cur->_M_next;
+           __cur->_M_next = __tmp;
+           ++_M_num_elements;
+           return iterator(__tmp, this);
+         }
+
+      _Node* __tmp = _M_new_node(__obj);
+      __tmp->_M_next = __first;
+      _M_buckets[__n] = __tmp;
+      ++_M_num_elements;
+      return iterator(__tmp, this);
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    find_or_insert(const value_type& __obj)
+    {
+      resize(_M_num_elements + 1);
+
+      size_type __n = _M_bkt_num(__obj);
+      _Node* __first = _M_buckets[__n];
+      
+      for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
+       if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
+         return __cur->_M_val;
+      
+      _Node* __tmp = _M_new_node(__obj);
+      __tmp->_M_next = __first;
+      _M_buckets[__n] = __tmp;
+      ++_M_num_elements;
+      return __tmp->_M_val;
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator,
+        typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator>
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    equal_range(const key_type& __key)
+    {
+      typedef pair<iterator, iterator> _Pii;
+      const size_type __n = _M_bkt_num_key(__key);
+
+      for (_Node* __first = _M_buckets[__n]; __first;
+          __first = __first->_M_next)
+       if (_M_equals(_M_get_key(__first->_M_val), __key))
+         {
+           for (_Node* __cur = __first->_M_next; __cur;
+                __cur = __cur->_M_next)
+             if (!_M_equals(_M_get_key(__cur->_M_val), __key))
+               return _Pii(iterator(__first, this), iterator(__cur, this));
+           for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
+             if (_M_buckets[__m])
+               return _Pii(iterator(__first, this),
+                           iterator(_M_buckets[__m], this));
+           return _Pii(iterator(__first, this), end());
+         }
+      return _Pii(end(), end());
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator,
+        typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator>
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    equal_range(const key_type& __key) const
+    {
+      typedef pair<const_iterator, const_iterator> _Pii;
+      const size_type __n = _M_bkt_num_key(__key);
+
+      for (const _Node* __first = _M_buckets[__n]; __first;
+          __first = __first->_M_next)
+       {
+         if (_M_equals(_M_get_key(__first->_M_val), __key))
+           {
+             for (const _Node* __cur = __first->_M_next; __cur;
+                  __cur = __cur->_M_next)
+               if (!_M_equals(_M_get_key(__cur->_M_val), __key))
+                 return _Pii(const_iterator(__first, this),
+                             const_iterator(__cur, this));
+             for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
+               if (_M_buckets[__m])
+                 return _Pii(const_iterator(__first, this),
+                             const_iterator(_M_buckets[__m], this));
+             return _Pii(const_iterator(__first, this), end());
+           }
+       }
+      return _Pii(end(), end());
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::size_type
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    erase(const key_type& __key)
+    {
+      const size_type __n = _M_bkt_num_key(__key);
+      _Node* __first = _M_buckets[__n];
+      size_type __erased = 0;
+      
+      if (__first)
+       {
+         _Node* __cur = __first;
+         _Node* __next = __cur->_M_next;
+         while (__next)
+           {
+             if (_M_equals(_M_get_key(__next->_M_val), __key))
+               {
+                 __cur->_M_next = __next->_M_next;
+                 _M_delete_node(__next);
+                 __next = __cur->_M_next;
+                 ++__erased;
+                 --_M_num_elements;
+               }
+             else
+               {
+                 __cur = __next;
+                 __next = __cur->_M_next;
+               }
+           }
+         if (_M_equals(_M_get_key(__first->_M_val), __key))
+           {
+             _M_buckets[__n] = __first->_M_next;
+             _M_delete_node(__first);
+             ++__erased;
+             --_M_num_elements;
+           }
+       }
+      return __erased;
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    erase(const iterator& __it)
+    {
+      _Node* __p = __it._M_cur;
+      if (__p)
+       {
+         const size_type __n = _M_bkt_num(__p->_M_val);
+         _Node* __cur = _M_buckets[__n];
+         
+         if (__cur == __p)
+           {
+             _M_buckets[__n] = __cur->_M_next;
+             _M_delete_node(__cur);
+             --_M_num_elements;
+           }
+         else
+           {
+             _Node* __next = __cur->_M_next;
+             while (__next)
+               {
+                 if (__next == __p)
+                   {
+                     __cur->_M_next = __next->_M_next;
+                     _M_delete_node(__next);
+                     --_M_num_elements;
+                     break;
+                   }
+                 else
+                   {
+                     __cur = __next;
+                     __next = __cur->_M_next;
+                   }
+               }
+           }
+       }
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    void
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    erase(iterator __first, iterator __last)
+    {
+      size_type __f_bucket = __first._M_cur ? _M_bkt_num(__first._M_cur->_M_val)
+                                           : _M_buckets.size();
+
+      size_type __l_bucket = __last._M_cur ? _M_bkt_num(__last._M_cur->_M_val)
+                                          : _M_buckets.size();
+
+      if (__first._M_cur == __last._M_cur)
+       return;
+      else if (__f_bucket == __l_bucket)
+       _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
+      else
+       {
+         _M_erase_bucket(__f_bucket, __first._M_cur, 0);
+         for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
+           _M_erase_bucket(__n, 0);
+         if (__l_bucket != _M_buckets.size())
+           _M_erase_bucket(__l_bucket, __last._M_cur);
+       }
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    inline void
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    erase(const_iterator __first, const_iterator __last)
+    {
+      erase(iterator(const_cast<_Node*>(__first._M_cur),
+                    const_cast<hashtable*>(__first._M_ht)),
+           iterator(const_cast<_Node*>(__last._M_cur),
+                    const_cast<hashtable*>(__last._M_ht)));
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    inline void
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    erase(const const_iterator& __it)
+    { erase(iterator(const_cast<_Node*>(__it._M_cur),
+                    const_cast<hashtable*>(__it._M_ht))); }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    void
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    resize(size_type __num_elements_hint)
+    {
+      const size_type __old_n = _M_buckets.size();
+      if (__num_elements_hint > __old_n)
+       {
+         const size_type __n = _M_next_size(__num_elements_hint);
+         if (__n > __old_n)
+           {
+             _Vector_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator());
+             try
+               {
+                 for (size_type __bucket = 0; __bucket < __old_n; ++__bucket)
+                   {
+                     _Node* __first = _M_buckets[__bucket];
+                     while (__first)
+                       {
+                         size_type __new_bucket = _M_bkt_num(__first->_M_val,
+                                                             __n);
+                         _M_buckets[__bucket] = __first->_M_next;
+                         __first->_M_next = __tmp[__new_bucket];
+                         __tmp[__new_bucket] = __first;
+                         __first = _M_buckets[__bucket];
+                       }
+                   }
+                 _M_buckets.swap(__tmp);
+               }
+             catch(...)
+               {
+                 for (size_type __bucket = 0; __bucket < __tmp.size();
+                      ++__bucket)
+                   {
+                     while (__tmp[__bucket])
+                       {
+                         _Node* __next = __tmp[__bucket]->_M_next;
+                         _M_delete_node(__tmp[__bucket]);
+                         __tmp[__bucket] = __next;
+                       }
+                   }
+                 __throw_exception_again;
+               }
+        __profcxx_hashtable_resize(this, __num_elements_hint, __n);
+           }
+       }
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    void
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
+    {
+      _Node* __cur = _M_buckets[__n];
+      if (__cur == __first)
+       _M_erase_bucket(__n, __last);
+      else
+       {
+         _Node* __next;
+         for (__next = __cur->_M_next;
+              __next != __first;
+              __cur = __next, __next = __cur->_M_next)
+           ;
+         while (__next != __last)
+           {
+             __cur->_M_next = __next->_M_next;
+             _M_delete_node(__next);
+             __next = __cur->_M_next;
+             --_M_num_elements;
+           }
+       }
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    void
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    _M_erase_bucket(const size_type __n, _Node* __last)
+    {
+      _Node* __cur = _M_buckets[__n];
+      while (__cur != __last)
+       {
+         _Node* __next = __cur->_M_next;
+         _M_delete_node(__cur);
+         __cur = __next;
+         _M_buckets[__n] = __cur;
+         --_M_num_elements;
+       }
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    void
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    clear()
+    {
+      size_type __hops=0, __lc = 0, __chain = 0;
+      if (_M_num_elements != 0) 
+         __profcxx_hashtable_destruct(this, _M_buckets.size(), _M_num_elements);
+      
+      for (size_type __i = 0; __i < _M_buckets.size(); ++__i)
+       {
+         _Node* __cur = _M_buckets[__i];
+         while (__cur != 0)
+           {
+             _Node* __next = __cur->_M_next;
+             _M_delete_node(__cur);
+             __cur = __next;
+
+          // Compute the longest chain count.
+          __chain++;
+           }
+         _M_buckets[__i] = 0;
+
+      // Collect number of hops.
+      if (__chain > 1) {
+        __lc = __lc > __chain ? __lc : __chain;
+        __hops += (__chain-1) * __chain / 2;
+      }
+      __chain = 0;
+       }
+      if (_M_num_elements) {
+        __profcxx_hashtable_destruct2(this, __lc, _M_num_elements, __hops);
+      }
+      _M_num_elements = 0;
+    }
+
+  template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
+    void
+    hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
+    _M_copy_from(const hashtable& __ht)
+    {
+      _M_buckets.clear();
+      _M_buckets.reserve(__ht._M_buckets.size());
+      _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
+      try
+       {
+         for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
+           const _Node* __cur = __ht._M_buckets[__i];
+           if (__cur)
+             {
+               _Node* __local_copy = _M_new_node(__cur->_M_val);
+               _M_buckets[__i] = __local_copy;
+               
+               for (_Node* __next = __cur->_M_next;
+                    __next;
+                    __cur = __next, __next = __cur->_M_next)
+                 {
+                   __local_copy->_M_next = _M_new_node(__next->_M_val);
+                   __local_copy = __local_copy->_M_next;
+                 }
+             }
+         }
+         _M_num_elements = __ht._M_num_elements;
+       }
+      catch(...)
+       {
+         clear();
+         __throw_exception_again;
+       }
+    }
+
+_GLIBCXX_END_NAMESPACE
+
+#endif
diff --git a/libstdc++-v3/include/profile/impl/profiler.h b/libstdc++-v3/include/profile/impl/profiler.h
new file mode 100644 (file)
index 0000000..f869203
--- /dev/null
@@ -0,0 +1,326 @@
+// -*- C++ -*-
+//
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/** @file profile/impl/profiler.h
+ *  @brief Interface of the profiling runtime library.
+ */
+
+// Written by Lixia Liu and Silvius Rus.
+
+#ifndef PROFCXX_PROFILER_H__
+#define PROFCXX_PROFILER_H__ 1
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <cstddef>
+#else
+#include <stddef.h>
+#endif
+
+/**
+ * @namespace std::__cxxprof_guard
+ * @brief Mechanism to protect all __cxxprof_impl operations against
+ * multithreaded and exception reentrance.
+ */
+namespace __cxxprof_guard
+{
+
+/** @brief Reentrance guard.
+ *
+ * Mechanism to protect all __cxxprof_impl operations against recursion,
+ * multithreaded and exception reentrance.
+ */
+template <int _Unused=0>
+class __reentrance_guard
+{
+ public:
+  static __thread bool __inside_cxxprof_impl;
+  static bool __get_in();
+  __reentrance_guard() {}
+  ~__reentrance_guard() { __inside_cxxprof_impl = false; }
+};
+
+template <int _Unused>
+__thread bool __reentrance_guard<_Unused>::__inside_cxxprof_impl = false;
+
+template <int _Unused>
+bool __reentrance_guard<_Unused>::__get_in()
+{
+  if (__inside_cxxprof_impl) {
+    return false;
+  } else {
+    __inside_cxxprof_impl = true;
+    return true;
+  }
+}
+
+} // namespace __cxxprof_guard
+
+#define _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD(__x...)             \
+  {                                                                \
+    if (__cxxprof_guard::__reentrance_guard<0>::__get_in())        \
+    {                                                              \
+      __cxxprof_guard::__reentrance_guard<0> __auto_get_out;       \
+      __x;                                                         \
+    }                                                              \
+  }
+
+/**
+ * @namespace std::__cxxprof_impl
+ * @brief Implementation of profile extension.
+ */
+namespace __cxxprof_impl
+{
+// Forward declarations of implementation functions.
+// Don't use any __cxxprof_impl:: in user code.
+// Instead, use the __profcxx... macros, which offer guarded access.
+void __turn_on();
+void __turn_off();
+bool __is_invalid();
+bool __is_on();
+bool __is_off();
+void __report(void);
+void __trace_hashtable_size_resize(const void*, size_t, size_t);
+void __trace_hashtable_size_destruct(const void*, size_t, size_t);
+void __trace_hashtable_size_construct(const void*, size_t);
+void __trace_vector_size_resize(const void*, size_t, size_t);
+void __trace_vector_size_destruct(const void*, size_t, size_t);
+void __trace_vector_size_construct(const void*, size_t);
+void __trace_hash_func_destruct(const void*, size_t, size_t, size_t);
+void __trace_hash_func_construct(const void*);
+void __trace_vector_to_list_destruct(const void*);
+void __trace_vector_to_list_construct(const void*);
+void __trace_vector_to_list_insert(const void*, size_t, size_t);
+void __trace_vector_to_list_iterate(const void*, size_t);
+void __trace_vector_to_list_invalid_operator(const void*);
+void __trace_vector_to_list_resize(const void*, size_t, size_t);
+void __trace_map_to_unordered_map_construct(const void*);
+void __trace_map_to_unordered_map_invalidate(const void*);
+void __trace_map_to_unordered_map_insert(const void*, size_t, size_t);
+void __trace_map_to_unordered_map_erase(const void*, size_t, size_t);
+void __trace_map_to_unordered_map_iterate(const void*, size_t);
+void __trace_map_to_unordered_map_find(const void*, size_t);
+void __trace_map_to_unordered_map_destruct(const void*);
+} // namespace __cxxprof_impl
+
+// Master switch turns on all diagnostics.
+#ifdef _GLIBCXX_PROFILE
+#define _GLIBCXX_PROFILE_HASHTABLE_TOO_SMALL
+#define _GLIBCXX_PROFILE_HASHTABLE_TOO_LARGE
+#define _GLIBCXX_PROFILE_VECTOR_TOO_SMALL
+#define _GLIBCXX_PROFILE_VECTOR_TOO_LARGE
+#define _GLIBCXX_PROFILE_INEFFICIENT_HASH
+#define _GLIBCXX_PROFILE_VECTOR_TO_LIST
+#define _GLIBCXX_PROFILE_MAP_TO_UNORDERED_MAP
+#endif
+
+// Expose global management routines to user code.
+#ifdef _GLIBCXX_PROFILE
+#define __profcxx_report() \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD(__cxxprof_impl::__report())
+#define __profcxx_turn_on() \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD(__cxxprof_impl::__turn_on())
+#define __profcxx_turn_off() \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD(__cxxprof_impl::__turn_off())
+#define __profcxx_is_invalid() \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD(__cxxprof_impl::__is_invalid())
+#define __profcxx_is_on() \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD(__cxxprof_impl::__is_on())
+#define __profcxx__is_off() \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD(__cxxprof_impl::__is_off())
+#else
+#define __profcxx_report()
+#define __profcxx_turn_on()
+#define __profcxx_turn_off()
+#define __profcxx_is_invalid()
+#define __profcxx_is_on()
+#define __profcxx_is_off()
+#endif
+
+// Turn on/off instrumentation for HASHTABLE_TOO_SMALL and HASHTABLE_TOO_LARGE.
+#if ((defined(_GLIBCXX_PROFILE_HASHTABLE_TOO_SMALL) \
+      && !defined(_NO_GLIBCXX_PROFILE_HASHTABLE_TOO_SMALL)) \
+     || (defined(_GLIBCXX_PROFILE_HASHTABLE_TOO_LARGE) \
+         && !defined(_NO_GLIBCXX_PROFILE_HASHTABLE_TOO_LARGE)))
+#define __profcxx_hashtable_resize(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_hashtable_size_resize(__x))
+#define __profcxx_hashtable_destruct(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_hashtable_size_destruct(__x))
+#define __profcxx_hashtable_construct(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_hashtable_size_construct(__x))
+#else
+#define __profcxx_hashtable_resize(__x...)  
+#define __profcxx_hashtable_destruct(__x...) 
+#define __profcxx_hashtable_construct(__x...)  
+#endif
+
+// Turn on/off instrumentation for VECTOR_TOO_SMALL and VECTOR_TOO_LARGE.
+#if ((defined(_GLIBCXX_PROFILE_VECTOR_TOO_SMALL) \
+      && !defined(_NO_GLIBCXX_PROFILE_VECTOR_TOO_SMALL)) \
+     || (defined(_GLIBCXX_PROFILE_VECTOR_TOO_LARGE) \
+         && !defined(_NO_GLIBCXX_PROFILE_VECTOR_TOO_LARGE)))
+#define __profcxx_vector_resize(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_vector_size_resize(__x))
+#define __profcxx_vector_destruct(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_vector_size_destruct(__x))
+#define __profcxx_vector_construct(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_vector_size_construct(__x))
+#else
+#define __profcxx_vector_resize(__x...)  
+#define __profcxx_vector_destruct(__x...) 
+#define __profcxx_vector_construct(__x...)  
+#endif 
+
+// Turn on/off instrumentation for INEFFICIENT_HASH.
+#if (defined(_GLIBCXX_PROFILE_INEFFICIENT_HASH) \
+     && !defined(_NO_GLIBCXX_PROFILE_INEFFICIENT_HASH))
+#define __profcxx_hashtable_construct2(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_hash_func_construct(__x))
+#define __profcxx_hashtable_destruct2(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_hash_func_destruct(__x))
+#else
+#define __profcxx_hashtable_destruct2(__x...) 
+#define __profcxx_hashtable_construct2(__x...)  
+#endif
+
+// Turn on/off instrumentation for VECTOR_TO_LIST.
+#if (defined(_GLIBCXX_PROFILE_VECTOR_TO_LIST) \
+     && !defined(_NO_GLIBCXX_PROFILE_VECTOR_TO_LIST))
+#define __profcxx_vector_construct2(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_vector_to_list_construct(__x))
+#define __profcxx_vector_destruct2(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_vector_to_list_destruct(__x))
+#define __profcxx_vector_insert(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_vector_to_list_insert(__x))
+#define __profcxx_vector_iterate(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_vector_to_list_iterate(__x))
+#define __profcxx_vector_invalid_operator(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_vector_to_list_invalid_operator(__x))
+#define __profcxx_vector_resize2(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_vector_to_list_resize(__x))
+#else
+#define __profcxx_vector_destruct2(__x...)
+#define __profcxx_vector_construct2(__x...)
+#define __profcxx_vector_insert(__x...)
+#define __profcxx_vector_iterate(__x...)
+#define __profcxx_vector_invalid_operator(__x...)
+#define __profcxx_vector_resize2(__x...)
+#endif
+
+// Turn on/off instrumentation for MAP_TO_UNORDERED_MAP.
+#if (defined(_GLIBCXX_PROFILE_MAP_TO_UNORDERED_MAP) \
+     && !defined(_NO_GLIBCXX_PROFILE_MAP_TO_UNORDERED_MAP))
+#define __profcxx_map_to_unordered_map_construct(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_map_to_unordered_map_construct(__x))
+#define __profcxx_map_to_unordered_map_destruct(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_map_to_unordered_map_destruct(__x))
+#define __profcxx_map_to_unordered_map_insert(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_map_to_unordered_map_insert(__x))
+#define __profcxx_map_to_unordered_map_erase(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_map_to_unordered_map_erase(__x))
+#define __profcxx_map_to_unordered_map_iterate(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_map_to_unordered_map_iterate(__x))
+#define __profcxx_map_to_unordered_map_invalidate(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_map_to_unordered_map_invalidate(__x))
+#define __profcxx_map_to_unordered_map_find(__x...) \
+  _GLIBCXX_PROFILE_IMPL_REENTRANCE_GUARD( \
+      __cxxprof_impl::__trace_map_to_unordered_map_find(__x))
+#else
+#define __profcxx_map_to_unordered_map_construct(__x...) \
+  
+#define __profcxx_map_to_unordered_map_destruct(__x...)
+#define __profcxx_map_to_unordered_map_insert(__x...)
+#define __profcxx_map_to_unordered_map_erase(__x...)
+#define __profcxx_map_to_unordered_map_iterate(__x...)
+#define __profcxx_map_to_unordered_map_invalidate(__x...)
+#define __profcxx_map_to_unordered_map_find(__x...)
+#endif
+
+// Run multithreaded unless instructed not to do so.
+#ifndef _GLIBCXX_PROFILE_NOTHREADS
+#define _GLIBCXX_PROFILE_THREADS
+#endif
+
+// Set default values for compile-time customizable variables.
+#ifndef _GLIBCXX_PROFILE_TRACE_PATH_ROOT
+#define _GLIBCXX_PROFILE_TRACE_PATH_ROOT "libstdcxx-profile"
+#endif
+#ifndef _GLIBCXX_PROFILE_TRACE_ENV_VAR
+#define _GLIBCXX_PROFILE_TRACE_ENV_VAR "GLIBCXX_PROFILE_TRACE_PATH_ROOT"
+#endif
+#ifndef _GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR
+#define _GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR \
+  "GLIBCXX_PROFILE_MAX_WARN_COUNT"
+#endif
+#ifndef _GLIBCXX_PROFILE_MAX_WARN_COUNT
+#define _GLIBCXX_PROFILE_MAX_WARN_COUNT 10
+#endif
+#ifndef _GLIBCXX_PROFILE_MAX_STACK_DEPTH
+#define _GLIBCXX_PROFILE_MAX_STACK_DEPTH 32
+#endif
+#ifndef _GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR
+#define _GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR \
+  "GLIBCXX_PROFILE_MAX_STACK_DEPTH"
+#endif
+#ifndef _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC
+#define _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC 2 << 27
+#endif
+#ifndef _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR
+#define _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR \
+  "GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC"
+#endif
+
+// Instrumentation hook implementations.
+#include "profile/impl/profiler_hash_func.h"
+#include "profile/impl/profiler_hashtable_size.h"
+#include "profile/impl/profiler_map_to_unordered_map.h"
+#include "profile/impl/profiler_vector_size.h"
+#include "profile/impl/profiler_vector_to_list.h"
+
+#endif // PROFCXX_PROFILER_H__
diff --git a/libstdc++-v3/include/profile/impl/profiler_container_size.h b/libstdc++-v3/include/profile/impl/profiler_container_size.h
new file mode 100644 (file)
index 0000000..330afc5
--- /dev/null
@@ -0,0 +1,250 @@
+// -*- C++ -*-
+//
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/** @file profile/impl/profiler_trace.h
+ *  @brief Diagnostics for container sizes.
+ */
+
+// Written by Lixia Liu and Silvius Rus.
+
+#ifndef PROFCXX_PROFILER_CONTAINER_SIZE_H__
+#define PROFCXX_PROFILER_CONTAINER_SIZE_H__ 1
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#endif
+
+#include "profile/impl/profiler.h"
+#include "profile/impl/profiler_node.h"
+#include "profile/impl/profiler_trace.h"
+
+namespace __cxxprof_impl
+{
+
+/** @brief A container size instrumentation line in the object table.  */
+class __container_size_info: public __object_info_base 
+{
+ public:
+  __container_size_info();
+  __container_size_info(const __container_size_info& __o);
+  __container_size_info(__stack_t __stack, size_t __num);
+  virtual ~__container_size_info() {}
+
+  void __write(FILE* f) const;
+  float __magnitude() const { return static_cast<float>(_M_cost); }
+  const char* __advice() const;
+
+  void __merge(const __container_size_info& __o);
+  // Call if a container is destructed or cleaned.
+  void __destruct(size_t __num, size_t __inum);
+  // Estimate the cost of resize/rehash. 
+  float __resize_cost(size_t __from, size_t __to) { return __from; }
+  // Call if container is resized.
+  void __resize(size_t __from, size_t __to);
+
+ private:
+  size_t _M_init;
+  size_t _M_max;  // range of # buckets
+  size_t _M_min;
+  size_t _M_total;
+  size_t _M_item_min;  // range of # items
+  size_t _M_item_max;
+  size_t _M_item_total;
+  size_t _M_count;
+  size_t _M_resize;
+  size_t _M_cost;
+};
+
+inline const char* __container_size_info::__advice() const
+{
+  const size_t __max_chars_size_t_printed = 20;
+  const char* __message_pattern = 
+      "change initial container size from %d to %d";
+  size_t __message_size = (strlen(__message_pattern) 
+                           + 2 * __max_chars_size_t_printed
+                           - 2 * 2);
+  char* __message = new char[__message_size + 1];
+
+  if (_M_init < _M_item_max)
+    snprintf(__message, __message_size, __message_pattern, _M_init,
+             _M_item_max);
+  else
+    snprintf(__message, __message_size, __message_pattern, _M_init,
+             _M_item_max);
+
+  return __message;
+}
+
+inline void __container_size_info::__destruct(size_t __num, size_t __inum) 
+{
+  _M_max = __max(_M_max, __num);
+  _M_item_max = __max(_M_item_max, __inum);
+  if (_M_min == 0) {
+    _M_min = __num; 
+    _M_item_min = __inum;
+  } else {
+    _M_min = __min(_M_min, __num);
+    _M_item_min = __min(_M_item_min, __inum);
+  }
+  _M_total += __num;
+  _M_item_total += __inum;
+  _M_count += 1;
+}
+
+inline void __container_size_info::__resize(size_t __from, size_t __to) 
+{
+  _M_cost += this->__resize_cost(__from, __to);
+  _M_resize += 1;
+  _M_max = __max(_M_max, __to);
+}
+
+inline __container_size_info::__container_size_info(__stack_t __stack, 
+                                                    size_t __num)
+    : __object_info_base(__stack), _M_init(0), _M_max(0), _M_item_max(0), 
+      _M_min(0), _M_item_min(0), _M_total(0), _M_item_total(0), _M_cost(0), 
+      _M_count(0), _M_resize(0)
+{
+  _M_init = _M_max = __num;
+  _M_item_min = _M_item_max = _M_item_total = _M_total = 0;
+  _M_min = 0;
+  _M_count = 0;
+  _M_resize = 0;
+}
+
+inline void __container_size_info::__merge(const __container_size_info& __o)
+{
+  _M_init        = __max(_M_init, __o._M_init);
+  _M_max         = __max(_M_max, __o._M_max);
+  _M_item_max    = __max(_M_item_max, __o._M_item_max);
+  _M_min         = __min(_M_min, __o._M_min);
+  _M_item_min    = __min(_M_item_min, __o._M_item_min);
+  _M_total      += __o._M_total;
+  _M_item_total += __o._M_item_total;
+  _M_count      += __o._M_count;
+  _M_cost       += __o._M_cost;
+  _M_resize     += __o._M_resize;
+}
+
+inline __container_size_info::__container_size_info()
+    : _M_init(0), _M_max(0), _M_item_max(0), _M_min(0), _M_item_min(0),
+      _M_total(0), _M_item_total(0), _M_cost(0), _M_count(0), _M_resize(0)
+{
+}
+
+inline __container_size_info::__container_size_info(
+    const __container_size_info& __o)
+    : __object_info_base(__o)
+{
+  _M_init        = __o._M_init;
+  _M_max         = __o._M_max;
+  _M_item_max    = __o._M_item_max;
+  _M_min         = __o._M_min;
+  _M_item_min    = __o._M_item_min;
+  _M_total       = __o._M_total;
+  _M_item_total  = __o._M_item_total;
+  _M_cost        = __o._M_cost;
+  _M_count       = __o._M_count;
+  _M_resize      = __o._M_resize;
+}
+
+/** @brief A container size instrumentation line in the stack table.  */
+class __container_size_stack_info: public __container_size_info
+{
+ public:
+  __container_size_stack_info(const __container_size_info& __o)
+      : __container_size_info(__o) {}
+};
+
+/** @brief Container size instrumentation trace producer.  */
+class __trace_container_size
+    : public __trace_base<__container_size_info, __container_size_stack_info> 
+{
+ public:
+  ~__trace_container_size() {}
+  __trace_container_size()
+      : __trace_base<__container_size_info, __container_size_stack_info>() {};
+
+  // Insert a new node at construct with object, callstack and initial size. 
+  void __insert(const __object_t __obj, __stack_t __stack, size_t __num);
+  // Call at destruction/clean to set container final size.
+  void __destruct(const void* __obj, size_t __num, size_t __inum);
+  void __construct(const void* __obj, size_t __inum);
+  // Call at resize to set resize/cost information.
+  void __resize(const void* __obj, int __from, int __to);
+};
+
+inline void __trace_container_size::__insert(const __object_t __obj,
+                                             __stack_t __stack, size_t __num)
+{
+  __add_object(__obj, __container_size_info(__stack, __num));
+}
+
+inline void __container_size_info::__write(FILE* __f) const
+{
+  fprintf(__f, "%Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu\n", 
+          _M_init, _M_count, _M_cost, _M_resize, _M_min, _M_max, _M_total,
+          _M_item_min, _M_item_max, _M_item_total);
+}
+
+inline void __trace_container_size::__destruct(const void* __obj, 
+                                               size_t __num, size_t __inum)
+{
+  if (!__is_on()) return;
+
+  __object_t __obj_handle = static_cast<__object_t>(__obj);
+
+  __container_size_info* __object_info = __get_object_info(__obj_handle);
+  if (!__object_info)
+    return;
+
+  __object_info->__destruct(__num, __inum);
+  __retire_object(__obj_handle);
+}
+
+inline void __trace_container_size::__resize(const void* __obj, int __from, 
+                                             int __to)
+{
+  if (!__is_on()) return;
+
+  __container_size_info* __object_info = __get_object_info(__obj);
+  if (!__object_info)
+    return;
+
+  __object_info->__resize(__from, __to);
+}
+
+} // namespace __cxxprof_impl
+#endif /* PROFCXX_PROFILER_CONTAINER_SIZE_H__ */
diff --git a/libstdc++-v3/include/profile/impl/profiler_hash_func.h b/libstdc++-v3/include/profile/impl/profiler_hash_func.h
new file mode 100644 (file)
index 0000000..cf63954
--- /dev/null
@@ -0,0 +1,192 @@
+// -*- C++ -*-
+//
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/** @file profile/impl/profiler_trace.h
+ *  @brief Data structures to represent profiling traces.
+ */
+
+// Written by Lixia Liu and Silvius Rus.
+
+#ifndef PROFCXX_PROFILER_HASH_FUNC_H__
+#define PROFCXX_PROFILER_HASH_FUNC_H__ 1
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#endif
+#include "profile/impl/profiler.h"
+#include "profile/impl/profiler_node.h"
+#include "profile/impl/profiler_trace.h"
+
+namespace __cxxprof_impl
+{
+
+/** @brief A hash performance instrumentation line in the object table.  */
+class __hashfunc_info: public __object_info_base
+{
+ public:
+  __hashfunc_info()
+      :_M_longest_chain(0), _M_accesses(0), _M_hops(0) {}
+  __hashfunc_info(const __hashfunc_info& o);
+  __hashfunc_info(__stack_t __stack)
+      : __object_info_base(__stack),
+        _M_longest_chain(0), _M_accesses(0), _M_hops(0){} 
+  virtual ~__hashfunc_info() {}
+
+  void __merge(const __hashfunc_info& __o);
+  void __destruct(size_t __chain, size_t __accesses, size_t __hops);
+  void __write(FILE* __f) const;
+  float __magnitude() const { return static_cast<float>(_M_hops); }
+  const char* __advice() const { return "change hash function"; }
+
+private:
+  size_t _M_longest_chain;
+  size_t _M_accesses;
+  size_t _M_hops;
+};
+
+inline __hashfunc_info::__hashfunc_info(const __hashfunc_info& __o)
+    : __object_info_base(__o)
+{
+  _M_longest_chain = __o._M_longest_chain;
+  _M_accesses      = __o._M_accesses;
+  _M_hops          = __o._M_hops;
+}
+
+inline void __hashfunc_info::__merge(const __hashfunc_info& __o)
+{
+  _M_longest_chain  = __max(_M_longest_chain, __o._M_longest_chain);
+  _M_accesses      += __o._M_accesses;
+  _M_hops          += __o._M_hops;
+}
+
+inline void __hashfunc_info::__destruct(size_t __chain, size_t __accesses, 
+                                        size_t __hops)
+{ 
+  _M_longest_chain  = __max(_M_longest_chain, __chain);
+  _M_accesses      += __accesses;
+  _M_hops          += __hops;
+}
+
+/** @brief A hash performance instrumentation line in the stack table.  */
+class __hashfunc_stack_info: public __hashfunc_info {
+ public:
+  __hashfunc_stack_info(const __hashfunc_info& __o) : __hashfunc_info(__o) {}
+};
+
+/** @brief Hash performance instrumentation producer.  */
+class __trace_hash_func
+    : public __trace_base<__hashfunc_info, __hashfunc_stack_info> 
+{
+ public:
+  __trace_hash_func();
+  ~__trace_hash_func() {}
+
+  // Insert a new node at construct with object, callstack and initial size. 
+  void __insert(__object_t __obj, __stack_t __stack);
+  // Call at destruction/clean to set container final size.
+  void __destruct(const void* __obj, size_t __chain,
+                  size_t __accesses, size_t __hops);
+};
+
+inline __trace_hash_func::__trace_hash_func()
+    : __trace_base<__hashfunc_info, __hashfunc_stack_info>()
+{
+  __id = "hash-distr";
+}
+
+inline void __trace_hash_func::__insert(__object_t __obj, __stack_t __stack)
+{
+  __add_object(__obj, __hashfunc_info(__stack));
+}
+
+inline void __hashfunc_info::__write(FILE* __f) const
+{
+  fprintf(__f, "%Zu %Zu %Zu\n", _M_hops, _M_accesses, _M_longest_chain);
+}
+
+inline void __trace_hash_func::__destruct(const void* __obj, size_t __chain,
+                                          size_t __accesses, size_t __hops)
+{
+  if (!__is_on()) return;
+
+  // First find the item from the live objects and update the informations.
+  __hashfunc_info* __objs = __get_object_info(__obj);
+  if (!__objs)
+    return;
+
+  __objs->__destruct(__chain, __accesses, __hops);
+  __retire_object(__obj);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Initialization and report.
+//////////////////////////////////////////////////////////////////////////////
+
+inline void __trace_hash_func_init()
+{
+  __tables<0>::_S_hash_func = new __trace_hash_func();
+}
+
+inline void __trace_hash_func_report(FILE* __f,
+                                     __warning_vector_t& __warnings)
+{
+  if (__tables<0>::_S_hash_func) {
+    __tables<0>::_S_hash_func->__collect_warnings(__warnings);
+    __tables<0>::_S_hash_func->__write(__f);
+  }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Implementations of instrumentation hooks.
+//////////////////////////////////////////////////////////////////////////////
+
+inline void __trace_hash_func_construct(const void* __obj)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_hash_func->__insert(__obj, __get_stack());
+}
+
+inline void __trace_hash_func_destruct(const void* __obj, size_t __chain,
+                                       size_t __accesses, size_t __hops)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_hash_func->__destruct(__obj, __chain, __accesses, __hops);
+}
+
+} // namespace __cxxprof_impl
+#endif /* PROFCXX_PROFILER_HASH_FUNC_H__ */
diff --git a/libstdc++-v3/include/profile/impl/profiler_hashtable_size.h b/libstdc++-v3/include/profile/impl/profiler_hashtable_size.h
new file mode 100644 (file)
index 0000000..2192879
--- /dev/null
@@ -0,0 +1,115 @@
+// -*- C++ -*-
+//
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/** @file profile/impl/profiler_hashtable_size.cc
+ *  @brief Collection of hashtable size traces.
+ */
+
+// Written by Lixia Liu and Silvius Rus.
+
+#ifndef PROFCXX_PROFILER_HASHTABLE_SIZE_H__
+#define PROFCXX_PROFILER_HASHTABLE_SIZE_H__ 1
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#endif
+#include "profile/impl/profiler.h"
+#include "profile/impl/profiler_node.h"
+#include "profile/impl/profiler_trace.h"
+#include "profile/impl/profiler_state.h"
+#include "profile/impl/profiler_container_size.h"
+
+namespace __cxxprof_impl
+{
+
+/** @brief Hashtable size instrumentation trace producer.  */
+class __trace_hashtable_size : public __trace_container_size
+{
+ public:
+  __trace_hashtable_size() : __trace_container_size()
+  {
+    __id = "hashtable-size";
+  }
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// Initialization and report.
+//////////////////////////////////////////////////////////////////////////////
+
+inline void __trace_hashtable_size_init()
+{
+  __tables<0>::_S_hashtable_size = new __trace_hashtable_size();
+}
+
+inline void __trace_hashtable_size_report(FILE* __f, 
+                                          __warning_vector_t& __warnings)
+{
+  if (__tables<0>::_S_hashtable_size) {
+    __tables<0>::_S_hashtable_size->__collect_warnings(__warnings);
+    __tables<0>::_S_hashtable_size->__write(__f);
+  }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Implementations of instrumentation hooks.
+//////////////////////////////////////////////////////////////////////////////
+
+inline void __trace_hashtable_size_construct(const void* __obj, size_t __num)
+{
+  if (!__profcxx_init()) return;
+  
+  __tables<0>::_S_hashtable_size->__insert(__obj, __get_stack(), __num);
+}
+
+inline void __trace_hashtable_size_destruct(const void* __obj, size_t __num, 
+                                            size_t __inum)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_hashtable_size->__destruct(__obj, __num, __inum);
+}
+
+inline void __trace_hashtable_size_resize(const void* __obj, size_t __from, 
+                                          size_t __to)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_hashtable_size->__resize(__obj, __from, __to);
+}
+
+} // namespace __cxxprof_impl
+
+#endif /* PROFCXX_PROFILER_HASHTABLE_SIZE_H__ */
diff --git a/libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h b/libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h
new file mode 100644 (file)
index 0000000..cdb88a8
--- /dev/null
@@ -0,0 +1,305 @@
+// -*- C++ -*-
+//
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/** @file profile/impl/profiler_map_to_unordered_map.h
+ *  @brief Diagnostics for map to unordered_map.
+ */
+
+// Written by Silvius Rus.
+
+#ifndef PROFCXX_PROFILER_MAP_TO_UNORDERED_MAP_H__
+#define PROFCXX_PROFILER_MAP_TO_UNORDERED_MAP_H__ 1
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#endif
+#include "profile/impl/profiler.h"
+#include "profile/impl/profiler_node.h"
+#include "profile/impl/profiler_trace.h"
+
+namespace __cxxprof_impl
+{
+
+// Cost model. XXX: this must be taken from the machine model instead.
+//  Map operations:
+//   - insert: 1.5 * log(size)
+//   - erase: 1.5 * log(size)
+//   - find: log(size)
+//   - iterate: 2.3
+//  Unordered map operations:
+//   - insert: 12
+//   - erase: 12
+//   - find: 10
+//   - iterate: 1.7
+
+const float __map_insert_cost_factor = 1.5;
+const float __map_erase_cost_factor = 1.5;
+const float __map_find_cost_factor = 1;
+const float __map_iterate_cost = 2.3;
+
+const float __umap_insert_cost = 12.0;
+const float __umap_erase_cost = 12.0;
+const float __umap_find_cost = 10.0;
+const float __umap_iterate_cost = 1.7;
+
+inline int __log2(size_t __size)
+{
+  for (int __bit_count = sizeof(size_t) - 1; __bit_count >= 0; --__bit_count) {
+    if ((2 << __bit_count) & __size) {
+      return __bit_count;
+    }
+  }
+  return 0;
+}
+
+inline float __map_insert_cost(size_t __size)
+{
+  return __map_insert_cost_factor * static_cast<float>(__log2(__size));
+}
+
+inline float __map_erase_cost(size_t __size)
+{
+  return __map_erase_cost_factor * static_cast<float>(__log2(__size));
+}
+
+inline float __map_find_cost(size_t __size)
+{
+  return __map_find_cost_factor * static_cast<float>(__log2(__size));
+}
+
+/** @brief A map-to-unordered_map instrumentation line in the object table.  */
+class __map2umap_info: public __object_info_base
+{
+ public:
+  __map2umap_info()
+      : _M_insert(0), _M_erase(0), _M_find(0), _M_iterate(0),
+        _M_map_cost(0.0), _M_umap_cost(0.0), _M_valid(true) {}
+  __map2umap_info(__stack_t __stack)
+      : __object_info_base(__stack), _M_insert(0), _M_erase(0), _M_find(0), 
+        _M_iterate(0), _M_map_cost(0.0), _M_umap_cost(0.0), _M_valid(true) {} 
+  virtual ~__map2umap_info() {}
+  __map2umap_info(const __map2umap_info& o);
+  void __merge(const __map2umap_info& o);
+  void __write(FILE* __f) const;
+  float __magnitude() const { return _M_map_cost - _M_umap_cost; }
+  const char* __advice() const;
+
+  void __record_insert(size_t __size, size_t __count);
+  void __record_erase(size_t __size, size_t __count);
+  void __record_find(size_t __size);
+  void __record_iterate(size_t __count);
+  void __record_invalidate();
+
+ private:
+  size_t _M_insert;
+  size_t _M_erase;
+  size_t _M_find;
+  size_t _M_iterate;
+  float _M_umap_cost;
+  float _M_map_cost;
+  bool  _M_valid;
+};
+
+inline const char* __map2umap_info::__advice() const
+{
+  return "change std::map to std::unordered_map";
+}
+
+inline __map2umap_info::__map2umap_info(const __map2umap_info& __o)
+    : __object_info_base(__o), 
+      _M_insert(__o._M_insert),
+      _M_erase(__o._M_erase),
+      _M_find(__o._M_find),
+      _M_iterate(__o._M_iterate),
+      _M_map_cost(__o._M_map_cost),
+      _M_umap_cost(__o._M_umap_cost),
+      _M_valid(__o._M_valid)
+{}
+
+inline void __map2umap_info::__merge(const __map2umap_info& __o)
+{
+  _M_insert    += __o._M_insert;
+  _M_erase     += __o._M_erase;
+  _M_find      += __o._M_find;
+  _M_map_cost  += __o._M_map_cost;
+  _M_umap_cost += __o._M_umap_cost;
+  _M_valid     &= __o._M_valid;
+}
+
+inline void __map2umap_info:: __record_insert(size_t __size, size_t __count)
+{
+  _M_insert += __count;
+  _M_map_cost += __count * __map_insert_cost(__size);
+  _M_umap_cost += __count * __umap_insert_cost;
+}
+
+inline void __map2umap_info:: __record_erase(size_t __size, size_t __count)
+{
+  _M_erase += __count;
+  _M_map_cost += __count * __map_erase_cost(__size);
+  _M_umap_cost += __count * __umap_erase_cost;
+}
+
+inline void __map2umap_info:: __record_find(size_t __size)
+{
+  _M_find += 1;
+  _M_map_cost += __map_find_cost(__size);
+  _M_umap_cost += __umap_find_cost;
+}
+
+inline void __map2umap_info:: __record_iterate(size_t __count)
+{
+  _M_iterate += __count;
+  _M_map_cost += __count * __map_iterate_cost;
+  _M_umap_cost += __count * __umap_iterate_cost;
+}
+
+inline void __map2umap_info:: __record_invalidate()
+{
+  _M_valid = false;
+}
+
+inline void __map2umap_info::__write(FILE* __f) const
+{
+  fprintf(__f, "%Zu %Zu %Zu %Zu %.0f %.0f %s\n",
+          _M_insert, _M_erase, _M_find, _M_iterate, _M_map_cost, _M_umap_cost,
+          _M_valid ? "valid" : "invalid");
+}
+
+/** @brief A map-to-unordered_map instrumentation line in the stack table.  */
+class __map2umap_stack_info: public __map2umap_info
+{
+ public:
+  __map2umap_stack_info(const __map2umap_info& o) : __map2umap_info(o) {}
+};
+
+/** @brief Map-to-unordered_map instrumentation producer.  */
+class __trace_map2umap
+    : public __trace_base<__map2umap_info, __map2umap_stack_info> 
+{
+ public:
+  __trace_map2umap();
+};
+
+inline __trace_map2umap::__trace_map2umap()
+    : __trace_base<__map2umap_info, __map2umap_stack_info>()
+{
+  __id = "map-to-unordered-map";
+}
+
+inline void __trace_map_to_unordered_map_init()
+{
+  __tables<0>::_S_map2umap = new __trace_map2umap();
+}
+
+inline void __trace_map_to_unordered_map_report(
+    FILE* __f, __warning_vector_t& __warnings)
+{
+  if (__tables<0>::_S_map2umap) {
+    __tables<0>::_S_map2umap->__collect_warnings(__warnings);
+    __tables<0>::_S_map2umap->__write(__f);
+  }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Implementations of instrumentation hooks.
+//////////////////////////////////////////////////////////////////////////////
+
+inline void __trace_map_to_unordered_map_construct(const void* __obj)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_map2umap->__add_object(__obj, 
+                                         __map2umap_info(__get_stack()));
+}
+
+inline void __trace_map_to_unordered_map_destruct(const void* __obj)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_map2umap->__retire_object(__obj);
+}
+
+inline void __trace_map_to_unordered_map_insert(const void* __obj, 
+                                                size_t __size, size_t __count)
+{
+  if (!__profcxx_init()) return;
+
+  __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj);
+
+  if (__info) __info->__record_insert(__size, __count);
+}
+
+inline void __trace_map_to_unordered_map_erase(const void* __obj, 
+                                               size_t __size, size_t __count)
+{
+  if (!__profcxx_init()) return;
+
+  __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj);
+
+  if (__info) __info->__record_erase(__size, __count);
+}
+
+inline void __trace_map_to_unordered_map_find(const void* __obj, size_t __size)
+{
+  if (!__profcxx_init()) return;
+
+  __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj);
+
+  if (__info) __info->__record_find(__size);
+}
+
+inline void __trace_map_to_unordered_map_iterate(const void* __obj, 
+                                                 size_t __count)
+{
+  if (!__profcxx_init()) return;
+
+  __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj);
+
+  if (__info) __info->__record_iterate(__count);
+}
+
+inline void __trace_map_to_unordered_map_invalidate(const void* __obj)
+{
+  if (!__profcxx_init()) return;
+
+  __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj);
+
+  if (__info) __info->__record_invalidate();
+}
+
+} // namespace __cxxprof_impl
+#endif /* PROFCXX_PROFILER_MAP_TO_UNORDERED_MAP_H__ */
diff --git a/libstdc++-v3/include/profile/impl/profiler_node.h b/libstdc++-v3/include/profile/impl/profiler_node.h
new file mode 100644 (file)
index 0000000..cd2b9ab
--- /dev/null
@@ -0,0 +1,172 @@
+// -*- C++ -*-
+//
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/** @file profile/impl/profiler_node.h
+ *  @brief Data structures to represent a single profiling event.
+ */
+
+// Written by Lixia Liu and Silvius Rus.
+
+#ifndef PROFCXX_PROFILER_NODE_H__
+#define PROFCXX_PROFILER_NODE_H__ 1
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <cstdio>
+#include <cstdint>
+#include <cstring>
+#else
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#endif
+#include <vector>
+#if defined HAVE_EXECINFO_H
+#include <execinfo.h>
+#endif
+
+namespace __cxxprof_impl
+{
+typedef const void* __object_t;
+typedef void* __instruction_address_t;
+typedef std::_GLIBCXX_STD_PR::vector<__instruction_address_t> __stack_npt;
+typedef __stack_npt* __stack_t;
+
+size_t __stack_max_depth();
+
+inline __stack_t __get_stack()
+{
+#if defined HAVE_EXECINFO_H
+  size_t __max_depth = __stack_max_depth();
+  if (__max_depth == 0)
+    return NULL;
+  __stack_npt __buffer(__max_depth);
+  int __depth = backtrace(&__buffer[0], __max_depth);
+  __stack_t __stack = new __stack_npt(__depth);
+  memcpy(&(*__stack)[0], &__buffer[0], __depth * sizeof(__object_t));
+  return __stack;
+#else
+  return NULL;
+#endif
+}
+
+inline __size(const __stack_t& __stack)
+{
+  if (!__stack) {
+    return 0;
+  } else {
+    return __stack->size();
+  }
+}
+
+inline void __write(FILE* __f, const __stack_t __stack)
+{
+  if (!__stack) {
+    return;
+  }
+
+  __stack_npt::const_iterator __it;
+  for (__it = __stack->begin(); __it != __stack->end(); ++__it) {
+    fprintf(__f, "%p ", *__it);
+  }
+}
+
+/** @brief Hash function for summary trace using call stack as index.  */
+class __stack_hash 
+{
+ public:
+  size_t operator()(const __stack_t __s) const
+  {
+    if (!__s) {
+      return 0;
+    }
+
+    uintptr_t __index = 0;
+    __stack_npt::const_iterator __it;
+    for (__it = __s->begin(); __it != __s->end(); ++__it) {
+      __index += reinterpret_cast<uintptr_t>(*__it);
+    } 
+    return __index;
+  }
+
+  bool operator() (const __stack_t __stack1, const __stack_t __stack2) const
+  {
+    if (!__stack1 && !__stack2) return true;
+    if (!__stack1 || !__stack2) return false;
+    if (__stack1->size() != __stack2->size()) return false;
+
+    size_t __byte_size = __stack1->size() * sizeof(__stack_npt::value_type);
+    return memcmp(&(*__stack1)[0], &(*__stack2)[0], __byte_size) == 0;
+  }
+};
+
+/** @brief Base class for a line in the object table.  */
+class __object_info_base
+{
+ public:
+  __object_info_base() {}
+  __object_info_base(__stack_t __stack);
+  __object_info_base(const __object_info_base& o);
+  virtual ~__object_info_base() {}
+  bool __is_valid() const { return _M_valid; }
+  __stack_t __stack() const { return _M_stack; }
+  virtual void __write(FILE* f) const = 0;
+
+ protected:
+  __stack_t _M_stack;
+  bool _M_valid;
+};
+
+inline __object_info_base::__object_info_base(__stack_t __stack)
+{
+  _M_stack = __stack;
+  _M_valid = true;
+}
+
+inline __object_info_base::__object_info_base(const __object_info_base& __o)
+{
+  _M_stack = __o._M_stack;
+  _M_valid = __o._M_valid;
+}
+
+/** @brief Base class for a line in the stack table.  */
+template<typename __object_info>
+class __stack_info_base
+{
+ public:
+  __stack_info_base() {}
+  __stack_info_base(const __object_info& __info) = 0;
+  virtual ~__stack_info_base() {}
+  void __merge(const __object_info& __info) = 0;
+  virtual float __magnitude() const = 0;
+  virtual const char* __get_id() const = 0;
+};
+
+} // namespace __cxxprof_impl
+#endif /* PROFCXX_PROFILER_NODE_H__ */
diff --git a/libstdc++-v3/include/profile/impl/profiler_state.h b/libstdc++-v3/include/profile/impl/profiler_state.h
new file mode 100644 (file)
index 0000000..64c10db
--- /dev/null
@@ -0,0 +1,107 @@
+// -*- C++ -*-
+//
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/** @file profile/impl/profiler_state.cc
+ *  @brief Global profiler state.
+ */
+
+// Written by Lixia Liu and Silvius Rus.
+
+#ifndef PROFCXX_PROFILER_STATE_H__
+#define PROFCXX_PROFILER_STATE_H__ 1
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <cstdio>
+#else
+#include <stdio.h>
+#endif
+
+namespace __cxxprof_impl
+{
+
+/** @brief Profiling mode on/off state.  */
+template <int _Unused=0>
+class __state
+{
+ public:
+
+  static __state<_Unused>* _S_diag_state;
+
+  __state() : _M_state(__INVALID) {}
+  ~__state() {}
+
+  bool __is_on() { return _M_state == __ON; }
+  bool __is_off() { return _M_state == __OFF; }
+  bool __is_invalid() { return _M_state == __INVALID; }
+  void __turn_on() { _M_state = __ON; }
+  void __turn_off() { _M_state = __OFF; }
+
+ private:
+  enum __state_type { __ON, __OFF, __INVALID };
+  __state_type _M_state;
+};
+
+template <int _Unused>
+__state<_Unused>* __state<_Unused>::_S_diag_state = NULL;
+
+inline bool __is_on()
+{
+  return __state<0>::_S_diag_state && __state<0>::_S_diag_state->__is_on();
+}
+
+inline bool __is_off()
+{
+  return __state<0>::_S_diag_state && __state<0>::_S_diag_state->__is_off();
+}
+
+inline bool __is_invalid()
+{
+  return (!__state<0>::_S_diag_state 
+          || __state<0>::_S_diag_state->__is_invalid());
+}
+
+inline void __turn_on()
+{
+  if (!__state<0>::_S_diag_state) { 
+    __state<0>::_S_diag_state = new __state<0>();
+  }
+  __state<0>::_S_diag_state->__turn_on();
+}
+
+inline void __turn_off()
+{
+  if (!__state<0>::_S_diag_state) { 
+    __state<0>::_S_diag_state = new __state<0>();
+  }
+  __state<0>::_S_diag_state->__turn_off();
+}
+
+} // end namespace __cxxprof_impl
+#endif /* PROFCXX_PROFILER_STATE_H__ */
diff --git a/libstdc++-v3/include/profile/impl/profiler_trace.h b/libstdc++-v3/include/profile/impl/profiler_trace.h
new file mode 100644 (file)
index 0000000..37bcb64
--- /dev/null
@@ -0,0 +1,564 @@
+// -*- C++ -*-
+//
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/** @file profile/impl/profiler_trace.h
+ *  @brief Data structures to represent profiling traces.
+ */
+
+// Written by Lixia Liu and Silvius Rus.
+
+#ifndef PROFCXX_PROFILER_TRACE_H__
+#define PROFCXX_PROFILER_TRACE_H__ 1
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <cerrno>
+#include <cstdint>
+#include <cstdio>
+#include <cstdlib>
+#define _GLIBCXX_IMPL_UNORDERED_MAP std::_GLIBCXX_STD_PR::unordered_map
+#include <unordered_map>
+#else
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <tr1/unordered_map>
+#define _GLIBCXX_IMPL_UNORDERED_MAP std::tr1::unordered_map
+#endif
+
+#include <algorithm>
+#include <utility>
+
+#if defined _GLIBCXX_PROFILE_THREADS && defined HAVE_TLS
+#include <pthread.h>
+#endif
+
+#include "profile/impl/profiler_state.h"
+#include "profile/impl/profiler_node.h"
+
+namespace __cxxprof_impl
+{
+
+#if defined _GLIBCXX_PROFILE_THREADS && defined HAVE_TLS
+#define _GLIBCXX_IMPL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+typedef pthread_mutex_t __mutex_t;
+/** @brief Pthread mutex wrapper.  */
+template <int _Unused=0>
+class __mutex {
+ public:
+  static __mutex_t __global_lock;
+  static void __lock(__mutex_t& __m) { pthread_mutex_lock(&__m); }
+  static void __unlock(__mutex_t& __m) { pthread_mutex_unlock(&__m); }
+};
+#else
+#define _GLIBCXX_IMPL_MUTEX_INITIALIZER 0
+typedef int __mutex_t;
+/** @brief Mock mutex interface.  */
+template <int _Unused=0>
+class __mutex {
+ public:
+  static __mutex_t __global_lock;
+  static void __lock(__mutex_t& __m) {}
+  static void __unlock(__mutex_t& __m) {}
+};
+#endif
+
+template <int _Unused>
+__mutex_t __mutex<_Unused>::__global_lock = _GLIBCXX_IMPL_MUTEX_INITIALIZER;
+
+/** @brief Representation of a warning.  */
+struct __warning_data
+{
+  float __magnitude;
+  __stack_t __context;
+  const char* __warning_id;
+  const char* __warning_message;
+  __warning_data();
+  __warning_data(float __m, __stack_t __c, const char* __id, 
+                 const char* __msg);
+  bool operator>(const struct __warning_data& other) const;
+};
+
+inline __warning_data::__warning_data()
+    : __magnitude(0.0), __context(NULL), __warning_id(NULL),
+      __warning_message(NULL)
+{
+}
+
+inline __warning_data::__warning_data(float __m, __stack_t __c, 
+                                      const char* __id, const char* __msg)
+    : __magnitude(__m), __context(__c), __warning_id(__id),
+      __warning_message(__msg)
+{
+}
+
+inline bool __warning_data::operator>(const struct __warning_data& other) const
+{
+  return __magnitude > other.__magnitude;
+}
+
+typedef std::_GLIBCXX_STD_PR::vector<__warning_data> __warning_vector_t;
+
+// Defined in profiler_<diagnostic name>.h.
+class __trace_hash_func;
+class __trace_hashtable_size;
+class __trace_map2umap;
+class __trace_vector_size;
+class __trace_vector_to_list;
+void __trace_vector_size_init();
+void __trace_hashtable_size_init();
+void __trace_hash_func_init();
+void __trace_vector_to_list_init();
+void __trace_map_to_unordered_map_init();
+void __trace_vector_size_report(FILE*, __warning_vector_t&);
+void __trace_hashtable_size_report(FILE*, __warning_vector_t&);
+void __trace_hash_func_report(FILE*, __warning_vector_t&);
+void __trace_vector_to_list_report(FILE*, __warning_vector_t&);
+void __trace_map_to_unordered_map_report(FILE*, __warning_vector_t&);
+
+// Utility functions.
+inline size_t __max(size_t __a, size_t __b)
+{
+  return __a >= __b ? __a : __b;
+}
+
+inline size_t __min(size_t __a, size_t __b)
+{
+  return __a <= __b ? __a : __b;
+}
+
+/** @brief Storage for diagnostic table entries.  Has only static fields.  */
+template <int _Unused=0>
+class __tables
+{
+ public:
+  static __trace_hash_func* _S_hash_func;
+  static __trace_hashtable_size* _S_hashtable_size;
+  static __trace_map2umap* _S_map2umap;
+  static __trace_vector_size* _S_vector_size;
+  static __trace_vector_to_list* _S_vector_to_list;
+};
+
+template <int _Unused>
+__trace_hash_func* __tables<_Unused>::_S_hash_func = NULL;
+template <int _Unused>
+__trace_hashtable_size* __tables<_Unused>::_S_hashtable_size = NULL;
+template <int _Unused>
+__trace_map2umap* __tables<_Unused>::_S_map2umap = NULL;
+template <int _Unused>
+__trace_vector_size* __tables<_Unused>::_S_vector_size = NULL;
+template <int _Unused>
+__trace_vector_to_list* __tables<_Unused>::_S_vector_to_list = NULL;
+
+/** @brief Storage for user defined parameters.  Has only static fields.  */
+template <int _Unused=0>
+class __settings {
+ public:
+  static const char* _S_trace_file_name;
+  static size_t _S_max_warn_count;
+  static size_t _S_max_stack_depth;
+  static size_t _S_max_mem;
+};
+
+template <int _Unused>
+const char* __settings<_Unused>::_S_trace_file_name = 
+    _GLIBCXX_PROFILE_TRACE_PATH_ROOT;
+template <int _Unused>
+size_t __settings<_Unused>::_S_max_warn_count =
+    _GLIBCXX_PROFILE_MAX_WARN_COUNT;
+template <int _Unused>
+size_t __settings<_Unused>::_S_max_stack_depth =
+    _GLIBCXX_PROFILE_MAX_STACK_DEPTH;
+template <int _Unused>
+size_t __settings<_Unused>::_S_max_mem =
+    _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC;
+
+inline size_t __stack_max_depth()
+{
+  return __settings<0>::_S_max_stack_depth;
+}
+
+inline size_t __max_mem()
+{
+  return __settings<0>::_S_max_mem;
+}
+
+/** @brief Base class for all trace producers.  */
+template <typename __object_info, typename __stack_info>
+class __trace_base
+{
+ public:
+  __trace_base();
+  virtual ~__trace_base() {}
+
+  void __add_object(__object_t object, __object_info __info);
+  __object_info* __get_object_info(__object_t __object);
+  void __retire_object(__object_t __object);
+  void __write(FILE* f);
+  void __collect_warnings(__warning_vector_t& warnings);
+
+  void __lock_object_table();
+  void __lock_stack_table();
+  void __unlock_object_table();
+  void __unlock_stack_table();
+
+ private:
+  __mutex_t __object_table_lock;
+  __mutex_t __stack_table_lock;
+  typedef _GLIBCXX_IMPL_UNORDERED_MAP<__object_t, 
+                                      __object_info> __object_table_t;
+  typedef _GLIBCXX_IMPL_UNORDERED_MAP<__stack_t, __stack_info, __stack_hash, 
+                                      __stack_hash> __stack_table_t;
+  __object_table_t __object_table;
+  __stack_table_t __stack_table;
+  size_t __stack_table_byte_size;
+
+ protected:
+  const char* __id;
+};
+
+template <typename __object_info, typename __stack_info>
+void __trace_base<__object_info, __stack_info>::__collect_warnings(
+    __warning_vector_t& warnings)
+{
+  typename __stack_table_t::iterator __i = __stack_table.begin();
+  for ( ; __i != __stack_table.end(); ++__i )
+  {
+    warnings.push_back(__warning_data((*__i).second.__magnitude(), 
+                                      (*__i).first, 
+                                      __id,
+                                      (*__i).second.__advice()));
+  }
+}
+
+template <typename __object_info, typename __stack_info>
+void __trace_base<__object_info, __stack_info>::__lock_object_table()
+{
+  __mutex<0>::__lock(this->__object_table_lock);
+}
+
+template <typename __object_info, typename __stack_info>
+void __trace_base<__object_info, __stack_info>::__lock_stack_table()
+{
+  __mutex<0>::__lock(this->__stack_table_lock);
+}
+
+template <typename __object_info, typename __stack_info>
+void __trace_base<__object_info, __stack_info>::__unlock_object_table()
+{
+  __mutex<0>::__unlock(this->__object_table_lock);
+}
+
+template <typename __object_info, typename __stack_info>
+void __trace_base<__object_info, __stack_info>::__unlock_stack_table()
+{
+  __mutex<0>::__unlock(this->__stack_table_lock);
+}
+
+template <typename __object_info, typename __stack_info>
+__trace_base<__object_info, __stack_info>::__trace_base()
+{
+  // Do not pick the initial size too large, as we don't know which diagnostics
+  // are more active.
+  __object_table.rehash(10000);
+  __stack_table.rehash(10000);
+  __stack_table_byte_size = 0;
+  __id = NULL;
+  __object_table_lock = __stack_table_lock = _GLIBCXX_IMPL_MUTEX_INITIALIZER;
+}
+
+template <typename __object_info, typename __stack_info>
+void __trace_base<__object_info, __stack_info>::__add_object(
+    __object_t __object, __object_info __info)
+{
+  if (__max_mem() == 0 
+      || __object_table.size() * sizeof(__object_info) <= __max_mem()) {
+    __lock_object_table();
+    __object_table.insert(
+        typename __object_table_t::value_type(__object, __info));
+    __unlock_object_table();
+  }
+}
+
+template <typename __object_info, typename __stack_info>
+__object_info* __trace_base<__object_info, __stack_info>::__get_object_info(
+    __object_t __object)
+{
+  // XXX: Revisit this to see if we can decrease mutex spans.
+  // Without this mutex, the object table could be rehashed during an
+  // insertion on another thread, which could result in a segfault.
+  __lock_object_table();
+  typename __object_table_t::iterator __object_it = 
+      __object_table.find(__object);
+  if (__object_it == __object_table.end()){
+    __unlock_object_table();
+    return NULL;
+  } else {
+    __unlock_object_table();
+    return &__object_it->second;
+  }
+}
+
+template <typename __object_info, typename __stack_info>
+void __trace_base<__object_info, __stack_info>::__retire_object(
+    __object_t __object)
+{
+  __lock_object_table();
+  __lock_stack_table();
+  typename __object_table_t::iterator __object_it =
+      __object_table.find(__object);
+  if (__object_it != __object_table.end()){
+    const __object_info& __info = __object_it->second;
+    const __stack_t& __stack = __info.__stack();
+    typename __stack_table_t::iterator __stack_it = 
+        __stack_table.find(__stack);
+    if (__stack_it == __stack_table.end()) {
+      // First occurence of this call context.
+      if (__max_mem() == 0 || __stack_table_byte_size < __max_mem()) {
+        __stack_table_byte_size += 
+            (sizeof(__instruction_address_t) * __size(__stack)
+             + sizeof(__stack) + sizeof(__stack_info));
+        __stack_table.insert(make_pair(__stack, __stack_info(__info)));
+      }
+    } else {
+      // Merge object info into info summary for this call context.
+      __stack_it->second.__merge(__info);
+      delete __stack;
+    }
+    __object_table.erase(__object);
+  }
+  __unlock_stack_table();
+  __unlock_object_table();
+}
+
+template <typename __object_info, typename __stack_info>
+void __trace_base<__object_info, __stack_info>::__write(FILE* __f)
+{
+  typename __stack_table_t::iterator __it;
+
+  for (__it = __stack_table.begin(); __it != __stack_table.end(); __it++) {
+    if (__it->second.__is_valid()) {
+      fprintf(__f, __id);
+      fprintf(__f, "|");
+      __cxxprof_impl::__write(__f, __it->first);
+      fprintf(__f, "|");
+      __it->second.__write(__f);
+    }
+  }
+}
+
+inline size_t __env_to_size_t(const char* __env_var, size_t __default_value)
+{
+  char* __env_value = getenv(__env_var);
+  if (__env_value) {
+    long int __converted_value = strtol(__env_value, NULL, 10);
+    if (errno || __converted_value < 0) {
+      fprintf(stderr, "Bad value for environment variable '%s'.", __env_var);
+      abort();
+    } else {
+      return static_cast<size_t>(__converted_value);
+    }
+  } else {
+    return __default_value;
+  }
+}
+
+inline void __set_max_stack_trace_depth()
+{
+  __settings<0>::_S_max_stack_depth = __env_to_size_t(
+      _GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR,
+      __settings<0>::_S_max_stack_depth);
+}
+
+inline void __set_max_mem()
+{
+  __settings<0>::_S_max_mem = __env_to_size_t(
+      _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR, __settings<0>::_S_max_mem);
+}
+
+inline int __log_magnitude(float f)
+{
+  const float log_base = 10.0;
+  int result = 0;
+  int sign = 1;
+  if (f < 0) {
+    f = -f;
+    sign = -1;
+  }
+  while (f > log_base) {
+    ++result;
+    f /= 10.0;
+  }
+  return sign * result;
+}
+
+struct __warn
+{
+  FILE* __file;
+  __warn(FILE* __f) { __file = __f; }
+  void operator() (const __warning_data& __info)
+  {
+    fprintf(__file,  __info.__warning_id);
+    fprintf(__file, ": improvement = %d", __log_magnitude(__info.__magnitude));
+    fprintf(__file, ": call stack = ");
+    __cxxprof_impl::__write(__file, __info.__context);
+    fprintf(__file, ": advice = %s\n", __info.__warning_message);
+  }
+};
+
+inline FILE* __open_output_file(const char* extension)
+{
+  // The path is made of _S_trace_file_name + "." + extension.
+  size_t root_len = strlen(__settings<0>::_S_trace_file_name);
+  size_t ext_len = strlen(extension);
+  char* file_name = new char[root_len + 1 + ext_len + 1];
+  char* p = file_name;
+  memcpy(file_name, __settings<0>::_S_trace_file_name, root_len);
+  *(file_name + root_len) = '.';
+  memcpy(file_name + root_len + 1, extension, ext_len + 1);
+  FILE* out_file = fopen(file_name, "w");
+  if (out_file) {
+    return out_file;
+  } else {
+    fprintf(stderr, "Could not open trace file '%s'.", file_name);
+    abort();
+  }
+}
+
+/** @brief Final report method, registered with "atexit".
+ *
+ * This can also be called directly by user code, including signal handlers.
+ * It is protected against deadlocks by the reentrance guard in profiler.h.
+ * However, when called from a signal handler that triggers while within
+ * __cxxprof_impl (under the guarded zone), no output will be produced.
+ */
+inline void __report(void)
+{
+  __mutex<0>::__lock(__mutex<0>::__global_lock);
+
+  __warning_vector_t __warnings;
+
+  FILE* __raw_file = __open_output_file("raw");
+  __trace_vector_size_report(__raw_file, __warnings);
+  __trace_hashtable_size_report(__raw_file, __warnings);
+  __trace_hash_func_report(__raw_file, __warnings);
+  __trace_vector_to_list_report(__raw_file, __warnings);
+  __trace_map_to_unordered_map_report(__raw_file, __warnings);
+  fclose(__raw_file);
+
+  // Sort data by magnitude.
+  // XXX: instead of sorting, should collect only top N for better performance.
+  size_t __cutoff = __min(__settings<0>::_S_max_warn_count, 
+                          __warnings.size());
+
+  std::sort(__warnings.begin(), __warnings.end(),
+            std::greater<__warning_vector_t::value_type>());
+  __warnings.resize(__cutoff);
+
+  FILE* __warn_file = __open_output_file("txt");
+  std::for_each(__warnings.begin(), __warnings.end(), __warn(__warn_file));
+  fclose(__warn_file);
+
+  __mutex<0>::__unlock(__mutex<0>::__global_lock);
+}
+
+inline void __set_trace_path()
+{
+  char* __env_trace_file_name = getenv(_GLIBCXX_PROFILE_TRACE_ENV_VAR);
+
+  if (__env_trace_file_name) { 
+    __settings<0>::_S_trace_file_name = __env_trace_file_name; 
+  }
+
+  // Make sure early that we can create the trace file.
+  fclose(__open_output_file("txt"));
+}
+
+inline void __set_max_warn_count()
+{
+  char* __env_max_warn_count_str = getenv(
+      _GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR);
+
+  if (__env_max_warn_count_str) {
+    __settings<0>::_S_max_warn_count = static_cast<size_t>(
+        atoi(__env_max_warn_count_str));
+  }
+}
+
+inline void __profcxx_init_unconditional()
+{
+  __mutex<0>::__lock(__mutex<0>::__global_lock);
+
+  __set_max_warn_count();
+
+  if (__is_invalid()) {
+
+    if (__settings<0>::_S_max_warn_count == 0) {
+
+      __turn_off();
+
+    } else {
+
+      __set_max_stack_trace_depth();
+      __set_max_mem();
+      __set_trace_path();
+
+      __trace_vector_size_init();
+      __trace_hashtable_size_init();
+      __trace_hash_func_init();
+      __trace_vector_to_list_init();
+      __trace_map_to_unordered_map_init();
+
+      atexit(__report);
+
+      __turn_on();
+
+    }
+  }
+
+  __mutex<0>::__unlock(__mutex<0>::__global_lock);
+}
+
+/** @brief This function must be called by each instrumentation point.
+ *
+ * The common path is inlined fully.
+ */
+inline bool __profcxx_init(void)
+{
+  if (__is_invalid()) {
+    __profcxx_init_unconditional();
+  }
+
+  return __is_on();
+}
+
+} // namespace __cxxprof_impl
+
+#endif /* PROFCXX_PROFILER_TRACE_H__ */
diff --git a/libstdc++-v3/include/profile/impl/profiler_vector_size.h b/libstdc++-v3/include/profile/impl/profiler_vector_size.h
new file mode 100644 (file)
index 0000000..dd42959
--- /dev/null
@@ -0,0 +1,112 @@
+// -*- C++ -*-
+//
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/** @file profile/impl/profiler_vector_size.h
+ *  @brief Collection of vector size traces.
+ */
+
+// Written by Lixia Liu and Silvius Rus.
+
+#ifndef PROFCXX_PROFILER_VECTOR_SIZE_H__
+#define PROFCXX_PROFILER_VECTOR_SIZE_H__ 1
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#endif
+#include "profile/impl/profiler.h"
+#include "profile/impl/profiler_node.h"
+#include "profile/impl/profiler_trace.h"
+#include "profile/impl/profiler_state.h"
+#include "profile/impl/profiler_container_size.h"
+
+namespace __cxxprof_impl
+{
+
+/** @brief Hashtable size instrumentation trace producer.  */
+class __trace_vector_size : public __trace_container_size
+{
+ public:
+  __trace_vector_size() : __trace_container_size() { __id = "vector-size"; }
+};
+
+//////////////////////////////////////////////////////////////////////////////
+// Initialization and report.
+//////////////////////////////////////////////////////////////////////////////
+
+inline void __trace_vector_size_init()
+{
+  __tables<0>::_S_vector_size = new __trace_vector_size();
+}
+
+inline void __trace_vector_size_report(FILE* __f, 
+                                       __warning_vector_t& __warnings)
+{
+  if (__tables<0>::_S_vector_size) {
+    __tables<0>::_S_vector_size->__collect_warnings(__warnings);
+    __tables<0>::_S_vector_size->__write(__f);
+  }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Implementations of instrumentation hooks.
+//////////////////////////////////////////////////////////////////////////////
+
+inline void __trace_vector_size_construct(const void* __obj, size_t __num)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_vector_size->__insert(__obj, __get_stack(), __num);
+}
+
+inline void __trace_vector_size_destruct(const void* __obj, size_t __num,
+                                         size_t __inum)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_vector_size->__destruct(__obj, __num, __inum);
+}
+
+inline void __trace_vector_size_resize(const void* __obj, size_t __from,
+                                       size_t __to)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_vector_size->__resize(__obj, __from, __to);
+}
+
+} // namespace __cxxprof_impl
+
+#endif /* PROFCXX_PROFILER_VECTOR_SIZE_H__ */
diff --git a/libstdc++-v3/include/profile/impl/profiler_vector_to_list.h b/libstdc++-v3/include/profile/impl/profiler_vector_to_list.h
new file mode 100644 (file)
index 0000000..ec3dfbc
--- /dev/null
@@ -0,0 +1,318 @@
+// -*- C++ -*-
+//
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the terms
+// of the GNU General Public License as published by the Free Software
+// Foundation; either version 2, or (at your option) any later
+// version.
+
+// This library is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this library; see the file COPYING.  If not, write to
+// the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
+// MA 02111-1307, USA.
+
+// As a special exception, you may use this file as part of a free
+// software library without restriction.  Specifically, if other files
+// instantiate templates or use macros or inline functions from this
+// file, or you compile this file and link it with other files to
+// produce an executable, this file does not by itself cause the
+// resulting executable to be covered by the GNU General Public
+// License.  This exception does not however invalidate any other
+// reasons why the executable file might be covered by the GNU General
+// Public License.
+
+/** @file profile/impl/profiler_trace.h
+ *  @brief Data structures to represent profiling traces.
+ */
+
+// Written by Lixia Liu and Silvius Rus.
+
+#ifndef PROFCXX_PROFILER_VECTOR_TO_LIST_H__
+#define PROFCXX_PROFILER_VECTOR_TO_LIST_H__ 1
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#else
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#endif
+#include "profile/impl/profiler.h"
+#include "profile/impl/profiler_node.h"
+#include "profile/impl/profiler_trace.h"
+
+namespace __cxxprof_impl
+{
+
+/** @brief A vector-to-list instrumentation line in the object table.  */
+class __vector2list_info: public __object_info_base
+{
+ public:
+  __vector2list_info()
+      :_M_shift_count(0), _M_iterate(0), _M_resize(0), _M_list_cost(0),
+       _M_vector_cost(0), _M_valid(true) {}
+  __vector2list_info(__stack_t __stack)
+      : __object_info_base(__stack), _M_shift_count(0), _M_iterate(0),
+        _M_resize(0), _M_list_cost(0), _M_vector_cost(0), _M_valid(true) {} 
+  virtual ~__vector2list_info() {}
+  __vector2list_info(const __vector2list_info& __o);
+  void __merge(const __vector2list_info& __o);
+  void __write(FILE* __f) const;
+  float __magnitude() const { return _M_vector_cost - _M_list_cost; }
+  const char* __advice() const { return "change std::vector to std::list"; }
+
+  size_t __shift_count() { return _M_shift_count; }
+  size_t __iterate()   { return _M_iterate; }
+  float __list_cost() { return _M_list_cost; }
+  size_t __resize() { return _M_resize; }
+  void __set_list_cost(float __lc) { _M_list_cost = __lc; }
+  void __set_vector_cost(float __vc) { _M_vector_cost = __vc; }
+  bool __is_valid() { return _M_valid; }
+  void __set_invalid() { _M_valid = false; }
+
+  void __opr_insert(size_t __pos, size_t __num);
+  void __opr_iterate(size_t __num) { _M_iterate += __num; }
+  void __resize(size_t __from, size_t __to);
+
+private:
+  size_t _M_shift_count;
+  size_t _M_iterate;
+  size_t _M_resize;
+  float _M_list_cost;
+  float _M_vector_cost;
+  bool  _M_valid;
+};
+
+inline __vector2list_info::__vector2list_info(const __vector2list_info& __o)
+    : __object_info_base(__o)
+{
+  _M_shift_count  = __o._M_shift_count;
+  _M_iterate      = __o._M_iterate;
+  _M_vector_cost  = __o._M_vector_cost;
+  _M_list_cost    = __o._M_list_cost;
+  _M_valid        = __o._M_valid;
+  _M_resize       = __o._M_resize;
+}
+
+inline void __vector2list_info::__merge(const __vector2list_info& __o)
+{
+  _M_shift_count  += __o._M_shift_count;
+  _M_iterate      += __o._M_iterate;
+  _M_vector_cost  += __o._M_vector_cost;
+  _M_list_cost    += __o._M_list_cost;
+  _M_valid        &= __o._M_valid;
+  _M_resize       += __o._M_resize;
+}
+
+inline void __vector2list_info::__opr_insert(size_t __pos, size_t __num)
+{
+  _M_shift_count += __num - __pos;
+}
+
+inline void __vector2list_info::__resize(size_t __from, size_t __to)
+{
+  _M_resize += __from;
+}
+
+/** @brief A vector-to-list instrumentation line in the stack table.  */
+class __vector2list_stack_info: public __vector2list_info {
+ public:
+  __vector2list_stack_info(const __vector2list_info& __o) 
+      : __vector2list_info(__o) {}
+};
+
+/** @brief Vector-to-list instrumentation producer.  */
+class __trace_vector_to_list
+    : public __trace_base<__vector2list_info, __vector2list_stack_info> 
+{
+ public:
+  __trace_vector_to_list();
+  ~__trace_vector_to_list() {}
+
+  // Insert a new node at construct with object, callstack and initial size. 
+  void __insert(__object_t __obj, __stack_t __stack);
+  // Call at destruction/clean to set container final size.
+  void __destruct(const void* __obj);
+
+  // Find the node in the live map.
+  __vector2list_info* __find(const void* __obj);
+
+  // Collect cost of operations.
+  void __opr_insert(const void* __obj, size_t __pos, size_t __num);
+  void __opr_iterate(const void* __obj, size_t __num);
+  void __invalid_operator(const void* __obj);
+  void __resize(const void* __obj, size_t __from, size_t __to);
+  float __vector_cost(size_t __shift, size_t __iterate, size_t __resize);
+  float __list_cost(size_t __shift, size_t __iterate, size_t __resize);
+};
+
+inline __trace_vector_to_list::__trace_vector_to_list()
+    : __trace_base<__vector2list_info, __vector2list_stack_info>()
+{
+  __id = "vector-to-list";
+}
+
+inline void __trace_vector_to_list::__insert(__object_t __obj,
+                                             __stack_t __stack)
+{
+  __add_object(__obj, __vector2list_info(__stack));
+}
+
+inline void __vector2list_info::__write(FILE* __f) const
+{
+  fprintf(__f, "%Zu %Zu %Zu %.0f %.0f\n",
+          _M_shift_count, _M_resize, _M_iterate, _M_vector_cost, _M_list_cost);
+}
+
+// Cost model.  XXX: get this from the cost model database instead.
+//  Vector operation cost:
+//   - Cost per shift: 1
+//   - Cost per access: 1
+//   - Cost per resize: 1
+//  List operation cost:
+//   - Cost per shift: 0
+//   - Cost per access: 10
+//   - Cost per resize: 0
+
+inline float __trace_vector_to_list::__vector_cost(size_t __shift, 
+                                                   size_t __iterate,
+                                                   size_t __resize)
+{
+  return __shift * 1 + __iterate * 1 + __resize * 1; 
+}
+
+inline float __trace_vector_to_list::__list_cost(size_t __shift, 
+                                                 size_t __iterate,
+                                                 size_t __resize)
+{
+  return __shift * 0 + __iterate * 10 + __resize * 0; 
+}
+
+inline void __trace_vector_to_list::__destruct(const void* __obj)
+{
+  if (!__is_on())
+    return;
+
+ __vector2list_info* __res = __get_object_info(__obj);
+  if (!__res)
+    return;
+
+  float __vc = __vector_cost(__res->__shift_count(), __res->__iterate(),
+                             __res->__resize());
+  float __lc = __list_cost(__res->__shift_count(), __res->__iterate(),
+                           __res->__resize());
+  __res->__set_vector_cost(__vc);
+  __res->__set_list_cost(__lc);
+
+  __retire_object(__obj);
+}
+
+inline void __trace_vector_to_list::__opr_insert(const void* __obj, 
+                                                 size_t __pos, size_t __num)
+{
+  __vector2list_info* __res = __get_object_info(__obj);
+  if (__res)
+    __res->__opr_insert(__pos, __num);
+}
+
+inline void __trace_vector_to_list::__opr_iterate(const void* __obj,
+                                                  size_t __num)
+{
+  __vector2list_info* __res = __get_object_info(__obj);
+  if (__res)
+    __res->__opr_iterate(__num);
+}
+
+inline void __trace_vector_to_list::__invalid_operator(const void* __obj)
+{
+  __vector2list_info* __res = __get_object_info(__obj);
+  if (__res)
+    __res->__set_invalid();
+}
+
+inline void __trace_vector_to_list::__resize(const void* __obj, size_t __from, 
+                                             size_t __to)
+{
+  __vector2list_info* __res = __get_object_info(__obj);
+  if (__res)
+    __res->__resize(__from, __to);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Initialization and report.
+//////////////////////////////////////////////////////////////////////////////
+
+inline void __trace_vector_to_list_init()
+{
+  __tables<0>::_S_vector_to_list = new __trace_vector_to_list();
+}
+
+inline void __trace_vector_to_list_report(FILE* __f, 
+                                          __warning_vector_t& __warnings)
+{
+  if (__tables<0>::_S_vector_to_list) {
+    __tables<0>::_S_vector_to_list->__collect_warnings(__warnings);
+    __tables<0>::_S_vector_to_list->__write(__f);
+  }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Implementations of instrumentation hooks.
+//////////////////////////////////////////////////////////////////////////////
+
+inline void __trace_vector_to_list_construct(const void* __obj)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_vector_to_list->__insert(__obj, __get_stack());
+}
+
+inline void __trace_vector_to_list_destruct(const void* __obj)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_vector_to_list->__destruct(__obj);
+}
+
+inline void __trace_vector_to_list_insert(const void* __obj, 
+                                          size_t __pos, size_t __num)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_vector_to_list->__opr_insert(__obj, __pos, __num);
+}
+
+
+inline void __trace_vector_to_list_iterate(const void* __obj, size_t __num)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_vector_to_list->__opr_iterate(__obj, __num);
+}
+
+inline void __trace_vector_to_list_invalid_operator(const void* __obj)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_vector_to_list->__invalid_operator(__obj);
+}
+
+inline void __trace_vector_to_list_resize(const void* __obj, 
+                                          size_t __from, size_t __to)
+{
+  if (!__profcxx_init()) return;
+
+  __tables<0>::_S_vector_to_list->__resize(__obj, __from, __to);
+}
+
+} // namespace __cxxprof_impl
+#endif /* PROFCXX_PROFILER_VECTOR_TO_LIST_H__ */
diff --git a/libstdc++-v3/include/profile/list b/libstdc++-v3/include/profile/list
new file mode 100644 (file)
index 0000000..061c506
--- /dev/null
@@ -0,0 +1,520 @@
+// Profiling list implementation -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file profile/list
+ *  This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_PROFILE_LIST
+#define _GLIBCXX_PROFILE_LIST 1
+
+#include <list>
+
+namespace std
+{
+namespace __profile
+{
+  /** @brief List wrapper with performance instrumentation.  */
+  template<typename _Tp, typename _Allocator = std::allocator<_Tp> >
+    class list
+    : public _GLIBCXX_STD_D::list<_Tp, _Allocator>
+    {
+      typedef _GLIBCXX_STD_D::list<_Tp, _Allocator> _Base;
+
+    public:
+      typedef typename _Base::reference             reference;
+      typedef typename _Base::const_reference       const_reference;
+
+      typedef typename _Base::iterator              iterator;
+      typedef typename _Base::const_iterator        const_iterator;
+
+      typedef typename _Base::size_type             size_type;
+      typedef typename _Base::difference_type       difference_type;
+
+      typedef _Tp                                  value_type;
+      typedef _Allocator                           allocator_type;
+      typedef typename _Base::pointer               pointer;
+      typedef typename _Base::const_pointer         const_pointer;
+      typedef std::reverse_iterator<iterator>       reverse_iterator;
+      typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+      // 23.2.2.1 construct/copy/destroy:
+      explicit list(const _Allocator& __a = _Allocator())
+      : _Base(__a) { }
+
+      explicit list(size_type __n, const _Tp& __value = _Tp(),
+                   const _Allocator& __a = _Allocator())
+      : _Base(__n, __value, __a) { }
+
+      template<class _InputIterator>
+      list(_InputIterator __first, _InputIterator __last,
+          const _Allocator& __a = _Allocator())
+      : _Base(__first, __last, __a)
+      { }
+
+
+      list(const list& __x)
+      : _Base(__x) { }
+
+      list(const _Base& __x)
+      : _Base(__x) { }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      list(list&& __x)
+      : _Base(std::forward<list>(__x))
+      { }
+
+      list(initializer_list<value_type> __l,
+           const allocator_type& __a = allocator_type())
+        : _Base(__l, __a) { }
+#endif
+
+      ~list() { }
+
+      list&
+      operator=(const list& __x)
+      {
+       static_cast<_Base&>(*this) = __x;
+       return *this;
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      list&
+      operator=(list&& __x)
+      {
+        // NB: DR 675.
+       this->clear();
+       this->swap(__x);
+       return *this;
+      }
+
+      list&
+      operator=(initializer_list<value_type> __l)
+      {
+       static_cast<_Base&>(*this) = __l;
+       return *this;
+      }
+
+      void
+      assign(initializer_list<value_type> __l)
+      {
+       _Base::assign(__l);
+      }
+#endif
+
+      template<class _InputIterator>
+        void
+        assign(_InputIterator __first, _InputIterator __last)
+        {
+         _Base::assign(__first, __last);
+       }
+
+      void
+      assign(size_type __n, const _Tp& __t)
+      {
+       _Base::assign(__n, __t);
+      }
+
+      using _Base::get_allocator;
+
+      // iterators:
+      iterator
+      begin()
+      { return iterator(_Base::begin()); }
+
+      const_iterator
+      begin() const
+      { return const_iterator(_Base::begin()); }
+
+      iterator
+      end()
+      { return iterator(_Base::end()); }
+
+      const_iterator
+      end() const
+      { return const_iterator(_Base::end()); }
+
+      reverse_iterator
+      rbegin()
+      { return reverse_iterator(end()); }
+
+      const_reverse_iterator
+      rbegin() const
+      { return const_reverse_iterator(end()); }
+
+      reverse_iterator
+      rend()
+      { return reverse_iterator(begin()); }
+
+      const_reverse_iterator
+      rend() const
+      { return const_reverse_iterator(begin()); }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      const_iterator
+      cbegin() const
+      { return const_iterator(_Base::begin()); }
+
+      const_iterator
+      cend() const
+      { return const_iterator(_Base::end()); }
+
+      const_reverse_iterator
+      crbegin() const
+      { return const_reverse_iterator(end()); }
+
+      const_reverse_iterator
+      crend() const
+      { return const_reverse_iterator(begin()); }
+#endif
+
+      // 23.2.2.2 capacity:
+      using _Base::empty;
+      using _Base::size;
+      using _Base::max_size;
+
+      void
+      resize(size_type __sz, _Tp __c = _Tp())
+      {
+        _Base::resize(__sz, __c);
+      }
+
+      // element access:
+      reference
+      front()
+      {
+       return _Base::front();
+      }
+
+      const_reference
+      front() const
+      {
+       return _Base::front();
+      }
+
+      reference
+      back()
+      {
+       return _Base::back();
+      }
+
+      const_reference
+      back() const
+      {
+       return _Base::back();
+      }
+
+      // 23.2.2.3 modifiers:
+      using _Base::push_front;
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      using _Base::emplace_front;
+#endif
+
+      void
+      pop_front()
+      {
+       iterator __victim = begin();
+       _Base::pop_front();
+      }
+
+      using _Base::push_back;
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      using _Base::emplace_back;
+#endif
+
+      void
+      pop_back()
+      {
+       iterator __victim = end();
+       --__victim;
+       _Base::pop_back();
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      template<typename... _Args>
+        iterator
+        emplace(iterator __position, _Args&&... __args)
+       {
+         return iterator(_Base::emplace(__position,
+                                       std::forward<_Args>(__args)...));
+       }
+#endif
+
+      iterator
+      insert(iterator __position, const _Tp& __x)
+      {
+       return iterator(_Base::insert(__position, __x));
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      iterator
+      insert(iterator __position, _Tp&& __x)
+      { return emplace(__position, std::move(__x)); }
+
+      void
+      insert(iterator __p, initializer_list<value_type> __l)
+      {
+       _Base::insert(__p, __l);
+      }
+#endif
+
+      void
+      insert(iterator __position, size_type __n, const _Tp& __x)
+      {
+       _Base::insert(__position, __n, __x);
+      }
+
+      template<class _InputIterator>
+        void
+        insert(iterator __position, _InputIterator __first,
+              _InputIterator __last)
+        {
+         _Base::insert(__position, __first, __last);
+       }
+
+      iterator
+      erase(iterator __position)
+      {
+       return iterator(_Base::erase(__position));
+      }
+
+      iterator
+      erase(iterator __position, iterator __last)
+      {
+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
+       // 151. can't currently clear() empty container
+       return iterator(_Base::erase(__position, __last));
+      }
+
+      void
+      swap(list& __x)
+      {
+       _Base::swap(__x);
+      }
+
+      void
+      clear()
+      {
+       _Base::clear();
+      }
+
+      // 23.2.2.4 list operations:
+      void
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      splice(iterator __position, list&& __x)
+#else
+      splice(iterator __position, list& __x)
+#endif
+      {
+       this->splice(__position, _GLIBCXX_MOVE(__x), __x.begin(), __x.end());
+      }
+
+      void
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      splice(iterator __position, list&& __x, iterator __i)
+#else
+      splice(iterator __position, list& __x, iterator __i)
+#endif
+      {
+       // We used to perform the splice_alloc check:  not anymore, redundant
+       // after implementing the relevant bits of N1599.
+
+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
+       _Base::splice(__position, _GLIBCXX_MOVE(__x._M_base()),
+                     __i);
+      }
+
+      void
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      splice(iterator __position, list&& __x, iterator __first,
+            iterator __last)
+#else
+      splice(iterator __position, list& __x, iterator __first,
+            iterator __last)
+#endif
+      {
+       // We used to perform the splice_alloc check:  not anymore, redundant
+       // after implementing the relevant bits of N1599.
+
+       _Base::splice(__position, _GLIBCXX_MOVE(__x._M_base()),
+                     __first, __last);
+      }
+
+      void
+      remove(const _Tp& __value)
+      {
+       for (iterator __x = begin(); __x != _Base::end(); )
+         {
+           if (*__x == __value)
+             __x = erase(__x);
+           else
+             ++__x;
+         }
+      }
+
+      template<class _Predicate>
+        void
+        remove_if(_Predicate __pred)
+        {
+         for (iterator __x = begin(); __x != _Base::end(); )
+           {
+             if (__pred(*__x))
+               __x = erase(__x);
+             else
+               ++__x;
+           }
+       }
+
+      void
+      unique()
+      {
+       iterator __first = begin();
+       iterator __last = end();
+       if (__first == __last)
+         return;
+       iterator __next = __first;
+       while (++__next != __last)
+         {
+           if (*__first == *__next)
+             erase(__next);
+           else
+             __first = __next;
+           __next = __first;
+         }
+      }
+
+      template<class _BinaryPredicate>
+        void
+        unique(_BinaryPredicate __binary_pred)
+        {
+         iterator __first = begin();
+         iterator __last = end();
+         if (__first == __last)
+           return;
+         iterator __next = __first;
+         while (++__next != __last)
+           {
+             if (__binary_pred(*__first, *__next))
+               erase(__next);
+             else
+               __first = __next;
+             __next = __first;
+           }
+       }
+
+      void
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      merge(list&& __x)
+#else
+      merge(list& __x)
+#endif
+      {
+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
+       // 300. list::merge() specification incomplete
+       if (this != &__x)
+         {
+           _Base::merge(_GLIBCXX_MOVE(__x._M_base()));
+         }
+      }
+
+      template<class _Compare>
+        void
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+        merge(list&& __x, _Compare __comp)
+#else
+        merge(list& __x, _Compare __comp)
+#endif
+        {
+         // _GLIBCXX_RESOLVE_LIB_DEFECTS
+         // 300. list::merge() specification incomplete
+         if (this != &__x)
+           {
+             _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp);
+           }
+       }
+
+      void
+      sort() { _Base::sort(); }
+
+      template<typename _StrictWeakOrdering>
+        void
+        sort(_StrictWeakOrdering __pred) { _Base::sort(__pred); }
+
+      using _Base::reverse;
+
+      _Base&
+      _M_base()       { return *this; }
+
+      const _Base&
+      _M_base() const { return *this; }
+
+    };
+
+  template<typename _Tp, typename _Alloc>
+    inline bool
+    operator==(const list<_Tp, _Alloc>& __lhs,
+              const list<_Tp, _Alloc>& __rhs)
+    { return __lhs._M_base() == __rhs._M_base(); }
+
+  template<typename _Tp, typename _Alloc>
+    inline bool
+    operator!=(const list<_Tp, _Alloc>& __lhs,
+              const list<_Tp, _Alloc>& __rhs)
+    { return __lhs._M_base() != __rhs._M_base(); }
+
+  template<typename _Tp, typename _Alloc>
+    inline bool
+    operator<(const list<_Tp, _Alloc>& __lhs,
+             const list<_Tp, _Alloc>& __rhs)
+    { return __lhs._M_base() < __rhs._M_base(); }
+
+  template<typename _Tp, typename _Alloc>
+    inline bool
+    operator<=(const list<_Tp, _Alloc>& __lhs,
+              const list<_Tp, _Alloc>& __rhs)
+    { return __lhs._M_base() <= __rhs._M_base(); }
+
+  template<typename _Tp, typename _Alloc>
+    inline bool
+    operator>=(const list<_Tp, _Alloc>& __lhs,
+              const list<_Tp, _Alloc>& __rhs)
+    { return __lhs._M_base() >= __rhs._M_base(); }
+
+  template<typename _Tp, typename _Alloc>
+    inline bool
+    operator>(const list<_Tp, _Alloc>& __lhs,
+             const list<_Tp, _Alloc>& __rhs)
+    { return __lhs._M_base() > __rhs._M_base(); }
+
+  template<typename _Tp, typename _Alloc>
+    inline void
+    swap(list<_Tp, _Alloc>& __lhs, list<_Tp, _Alloc>& __rhs)
+    { __lhs.swap(__rhs); }
+
+} // namespace __profile
+} // namespace std
+
+#endif
diff --git a/libstdc++-v3/include/profile/map b/libstdc++-v3/include/profile/map
new file mode 100644 (file)
index 0000000..e396b85
--- /dev/null
@@ -0,0 +1,41 @@
+// Profiling map/multimap implementation -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+/** @file profile/map
+ *  This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_PROFILE_MAP
+#define _GLIBCXX_PROFILE_MAP 1
+
+#include <map>
+#include <profile/map.h>
+#include <profile/multimap.h>
+
+#endif
diff --git a/libstdc++-v3/include/profile/map.h b/libstdc++-v3/include/profile/map.h
new file mode 100644 (file)
index 0000000..aa9e535
--- /dev/null
@@ -0,0 +1,489 @@
+// Profiling map implementation -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+/** @file profile/map.h
+ *  This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_PROFILE_MAP_H
+#define _GLIBCXX_PROFILE_MAP_H 1
+
+#include <utility>
+#include <profile/base.h>
+
+namespace std
+{
+namespace __profile
+{
+  /** @brief Map wrapper with performance instrumentation.  */
+  template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
+          typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > >
+    class map
+    : public _GLIBCXX_STD_D::map<_Key, _Tp, _Compare, _Allocator>
+    {
+      typedef _GLIBCXX_STD_D::map<_Key, _Tp, _Compare, _Allocator> _Base;
+
+    public:
+      // types:
+      typedef _Key                                  key_type;
+      typedef _Tp                                   mapped_type;
+      typedef std::pair<const _Key, _Tp>            value_type;
+      typedef _Compare                              key_compare;
+      typedef _Allocator                            allocator_type;
+      typedef typename _Base::reference             reference;
+      typedef typename _Base::const_reference       const_reference;
+
+      typedef typename _Base::iterator       iterator;
+      typedef typename _Base::const_iterator       const_iterator;
+      typedef typename _Base::size_type             size_type;
+      typedef typename _Base::difference_type       difference_type;
+      typedef typename _Base::pointer               pointer;
+      typedef typename _Base::const_pointer         const_pointer;
+      typedef std::reverse_iterator<iterator>       reverse_iterator;
+      typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+      using _Base::value_compare;
+
+      // 23.3.1.1 construct/copy/destroy:
+      explicit map(const _Compare& __comp = _Compare(),
+                  const _Allocator& __a = _Allocator())
+      : _Base(__comp, __a) {
+          __profcxx_map_to_unordered_map_construct(this);
+      }
+
+      template<typename _InputIterator>
+        map(_InputIterator __first, _InputIterator __last,
+           const _Compare& __comp = _Compare(),
+           const _Allocator& __a = _Allocator())
+       : _Base(__first, __last, __comp, __a) {
+          __profcxx_map_to_unordered_map_construct(this);
+        }
+
+      map(const map& __x)
+      : _Base(__x) {
+          __profcxx_map_to_unordered_map_construct(this);
+      }
+
+      map(const _Base& __x)
+      : _Base(__x) {
+          __profcxx_map_to_unordered_map_construct(this);
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      map(map&& __x)
+      : _Base(std::forward<map>(__x))
+      { }
+
+      map(initializer_list<value_type> __l,
+         const _Compare& __c = _Compare(),
+         const allocator_type& __a = allocator_type())
+      : _Base(__l, __c, __a) { }
+#endif
+
+      ~map() {
+          __profcxx_map_to_unordered_map_destruct(this);
+      }
+
+      map&
+      operator=(const map& __x)
+      {
+       *static_cast<_Base*>(this) = __x;
+       return *this;
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      map&
+      operator=(map&& __x)
+      {
+        // NB: DR 675.
+       this->clear();
+       this->swap(__x);
+       return *this;
+      }
+
+      map&
+      operator=(initializer_list<value_type> __l)
+      {
+       this->clear();
+       this->insert(__l);
+       return *this;
+      }
+#endif
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 133. map missing get_allocator()
+      using _Base::get_allocator;
+
+      // iterators:
+      iterator 
+      begin()
+      { return _Base::begin(); }
+
+      const_iterator
+      begin() const
+      { return _Base::begin(); }
+
+      iterator
+      end()
+      { return _Base::end(); }
+
+      const_iterator
+      end() const
+      { return _Base::end(); }
+
+      reverse_iterator
+      rbegin()
+      { 
+        __profcxx_map_to_unordered_map_invalidate(this);
+        return reverse_iterator(end()); 
+      }
+
+      const_reverse_iterator
+      rbegin() const
+      {
+        __profcxx_map_to_unordered_map_invalidate(this);
+        return const_reverse_iterator(end());
+      }
+
+      reverse_iterator
+      rend()
+      {
+        __profcxx_map_to_unordered_map_invalidate(this);
+        return reverse_iterator(begin());
+      }
+
+      const_reverse_iterator
+      rend() const
+      {
+        __profcxx_map_to_unordered_map_invalidate(this);
+        return const_reverse_iterator(begin());
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      const_iterator
+      cbegin() const
+      { return const_iterator(_Base::begin()); }
+
+      const_iterator
+      cend() const
+      { return const_iterator(_Base::end()); }
+
+      const_reverse_iterator
+      crbegin() const
+      {
+        __profcxx_map_to_unordered_map_invalidate(this);
+        return const_reverse_iterator(end());
+      }
+
+      const_reverse_iterator
+      crend() const
+      {
+        __profcxx_map_to_unordered_map_invalidate(this);
+        return const_reverse_iterator(begin());
+      }
+#endif
+
+      // capacity:
+      using _Base::empty;
+      using _Base::size;
+      using _Base::max_size;
+
+      // 23.3.1.2 element access:
+      mapped_type&
+      operator[](const key_type& __k)
+      {
+        __profcxx_map_to_unordered_map_find(this, size());
+        return _Base::operator[](__k);
+      }
+
+      mapped_type&
+      at(const key_type& __k)
+      {
+        __profcxx_map_to_unordered_map_find(this, size());
+        return _Base::at(__k);
+      }
+
+      const mapped_type&
+      at(const key_type& __k) const
+      {
+        __profcxx_map_to_unordered_map_find(this, size());
+        return _Base::at(__k);
+      }
+
+      // modifiers:
+      std::pair<iterator, bool>
+      insert(const value_type& __x)
+      {
+        __profcxx_map_to_unordered_map_insert(this, size(), 1);
+       typedef typename _Base::iterator _Base_iterator;
+       std::pair<_Base_iterator, bool> __res = _Base::insert(__x);
+       return std::pair<iterator, bool>(iterator(__res.first),
+                                        __res.second);
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      void
+      insert(std::initializer_list<value_type> __list)
+      { 
+        size_type size_before = size();
+        _Base::insert(__list); 
+        __profcxx_map_to_unordered_map_insert(this, size_before, 
+                                                size() - size_before);
+      }
+#endif
+
+      iterator
+      insert(iterator __position, const value_type& __x)
+      {
+        size_type size_before = size();
+       return iterator(_Base::insert(__position, __x));
+        __profcxx_map_to_unordered_map_insert(this, size_before, 
+                                                size() - size_before);
+      }
+
+      template<typename _InputIterator>
+        void
+        insert(_InputIterator __first, _InputIterator __last)
+        {
+          size_type size_before = size();
+         _Base::insert(__first, __last);
+          __profcxx_map_to_unordered_map_insert(this, size_before, 
+                                                size() - size_before);
+       }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      iterator
+      erase(iterator __position)
+      {
+       iterator __i = _Base::erase(__position);
+        __profcxx_map_to_unordered_map_erase(this, size(), 1);
+        return __i;
+      }
+#else
+      void
+      erase(iterator __position)
+      {
+       _Base::erase(__position);
+        __profcxx_map_to_unordered_map_erase(this, size(), 1);
+      }
+#endif
+
+      size_type
+      erase(const key_type& __x)
+      {
+       iterator __victim = find(__x);
+       if (__victim == end())
+         return 0;
+       else
+       {
+         _Base::erase(__victim);
+         return 1;
+       }
+      }
+
+      void
+      erase(iterator __first, iterator __last)
+      {
+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
+       // 151. can't currently clear() empty container
+       while (__first != __last)
+         this->erase(__first++);
+      }
+
+      void
+
+      swap(map& __x)
+      {
+       _Base::swap(__x);
+      }
+
+      void
+      clear()
+      { this->erase(begin(), end()); }
+
+      // observers:
+      using _Base::key_comp;
+      using _Base::value_comp;
+
+      // 23.3.1.3 map operations:
+      iterator
+      find(const key_type& __x)
+      {
+        __profcxx_map_to_unordered_map_find(this, size());
+        return iterator(_Base::find(__x));
+      }
+
+      const_iterator
+      find(const key_type& __x) const
+      {
+        __profcxx_map_to_unordered_map_find(this, size());
+        return const_iterator(_Base::find(__x));
+      }
+
+      size_type
+      count(const key_type& __x) const
+      {
+        __profcxx_map_to_unordered_map_find(this, size());
+        return _Base::count(__x);
+      }
+
+      iterator
+      lower_bound(const key_type& __x)
+      { 
+        __profcxx_map_to_unordered_map_invalidate(this);
+        return iterator(_Base::lower_bound(__x)); 
+      }
+
+      const_iterator
+      lower_bound(const key_type& __x) const
+      { 
+        __profcxx_map_to_unordered_map_invalidate(this);
+        return const_iterator(_Base::lower_bound(__x)); 
+      }
+
+      iterator
+      upper_bound(const key_type& __x)
+      { 
+        __profcxx_map_to_unordered_map_invalidate(this);
+        return iterator(_Base::upper_bound(__x)); 
+      }
+
+      const_iterator
+      upper_bound(const key_type& __x) const
+      { 
+        __profcxx_map_to_unordered_map_invalidate(this);
+        return const_iterator(_Base::upper_bound(__x)); 
+      }
+
+      std::pair<iterator,iterator>
+      equal_range(const key_type& __x)
+      {
+       typedef typename _Base::iterator _Base_iterator;
+       std::pair<_Base_iterator, _Base_iterator> __res =
+       _Base::equal_range(__x);
+       return std::make_pair(iterator(__res.first),
+                             iterator(__res.second));
+      }
+
+      std::pair<const_iterator,const_iterator>
+      equal_range(const key_type& __x) const
+      {
+        __profcxx_map_to_unordered_map_find(this, size());
+       typedef typename _Base::const_iterator _Base_const_iterator;
+       std::pair<_Base_const_iterator, _Base_const_iterator> __res =
+       _Base::equal_range(__x);
+       return std::make_pair(const_iterator(__res.first),
+                             const_iterator(__res.second));
+      }
+
+      _Base& 
+      _M_base() { return *this; }
+
+      const _Base&
+      _M_base() const { return *this; }
+
+    };
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline bool
+    operator==(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
+              const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    { 
+      __profcxx_map_to_unordered_map_invalidate(&__lhs);
+      __profcxx_map_to_unordered_map_invalidate(&__rhs);
+      return __lhs._M_base() == __rhs._M_base(); 
+    }
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline bool
+    operator!=(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
+              const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    { 
+      __profcxx_map_to_unordered_map_invalidate(&__lhs);
+      __profcxx_map_to_unordered_map_invalidate(&__rhs);
+      return __lhs._M_base() != __rhs._M_base(); 
+    }
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline bool
+    operator<(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
+             const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    {
+      __profcxx_map_to_unordered_map_invalidate(&__lhs);
+      __profcxx_map_to_unordered_map_invalidate(&__rhs);
+      return __lhs._M_base() < __rhs._M_base(); 
+    }
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline bool
+    operator<=(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
+              const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    {
+      __profcxx_map_to_unordered_map_invalidate(&__lhs);
+      __profcxx_map_to_unordered_map_invalidate(&__rhs);
+      return __lhs._M_base() <= __rhs._M_base();
+    }
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline bool
+    operator>=(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
+              const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    {
+      __profcxx_map_to_unordered_map_invalidate(&__lhs);
+      __profcxx_map_to_unordered_map_invalidate(&__rhs);
+      return __lhs._M_base() >= __rhs._M_base();
+    }
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline bool
+    operator>(const map<_Key, _Tp, _Compare, _Allocator>& __lhs,
+             const map<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    {
+      __profcxx_map_to_unordered_map_invalidate(&__lhs);
+      __profcxx_map_to_unordered_map_invalidate(&__rhs);
+      return __lhs._M_base() > __rhs._M_base();
+    }
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline void
+    swap(map<_Key, _Tp, _Compare, _Allocator>& __lhs,
+        map<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    { __lhs.swap(__rhs); }
+
+} // namespace __profile
+} // namespace std
+
+#endif
diff --git a/libstdc++-v3/include/profile/multimap.h b/libstdc++-v3/include/profile/multimap.h
new file mode 100644 (file)
index 0000000..b1fc70b
--- /dev/null
@@ -0,0 +1,363 @@
+// Profiling multimap implementation -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file profile/multimap.h
+ *  This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_PROFILE_MULTIMAP_H
+#define _GLIBCXX_PROFILE_MULTIMAP_H 1
+
+#include <utility>
+
+namespace std
+{
+namespace __profile
+{
+  /** @brief Multimap wrapper with performance instrumentation.  */
+  template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>,
+          typename _Allocator = std::allocator<std::pair<const _Key, _Tp> > >
+    class multimap
+    : public _GLIBCXX_STD_D::multimap<_Key, _Tp, _Compare, _Allocator>
+    {
+      typedef _GLIBCXX_STD_D::multimap<_Key, _Tp, _Compare, _Allocator> _Base;
+
+    public:
+      // types:
+      typedef _Key                                  key_type;
+      typedef _Tp                                   mapped_type;
+      typedef std::pair<const _Key, _Tp>             value_type;
+      typedef _Compare                               key_compare;
+      typedef _Allocator                             allocator_type;
+      typedef typename _Base::reference              reference;
+      typedef typename _Base::const_reference        const_reference;
+
+      typedef typename _Base::iterator               iterator;
+      typedef typename _Base::const_iterator         const_iterator;
+      typedef typename _Base::reverse_iterator       reverse_iterator;
+      typedef typename _Base::const_reverse_iterator const_reverse_iterator;
+
+      typedef typename _Base::size_type              size_type;
+      typedef typename _Base::difference_type        difference_type;
+      typedef typename _Base::pointer                pointer;
+      typedef typename _Base::const_pointer          const_pointer;
+
+      using _Base::value_compare;
+
+      // 23.3.1.1 construct/copy/destroy:
+      explicit multimap(const _Compare& __comp = _Compare(),
+                       const _Allocator& __a = _Allocator())
+      : _Base(__comp, __a) { }
+
+      template<typename _InputIterator>
+      multimap(_InputIterator __first, _InputIterator __last,
+              const _Compare& __comp = _Compare(),
+              const _Allocator& __a = _Allocator())
+      : _Base(__first, __last, __comp, __a) { }
+
+      multimap(const multimap& __x)
+      : _Base(__x) { }
+
+      multimap(const _Base& __x)
+      : _Base(__x) { }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      multimap(multimap&& __x)
+      : _Base(std::forward<multimap>(__x))
+      { }
+
+      multimap(initializer_list<value_type> __l,
+              const _Compare& __c = _Compare(),
+              const allocator_type& __a = allocator_type())
+      : _Base(__l, __c, __a) { }
+#endif
+
+      ~multimap() { }
+
+      multimap&
+      operator=(const multimap& __x)
+      {
+       *static_cast<_Base*>(this) = __x;
+       return *this;
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      multimap&
+      operator=(multimap&& __x)
+      {
+        // NB: DR 675.
+       this->clear();
+       this->swap(__x);
+       return *this;
+      }
+
+      multimap&
+      operator=(initializer_list<value_type> __l)
+      {
+       this->clear();
+       this->insert(__l);
+       return *this;
+      }
+#endif
+
+      using _Base::get_allocator;
+
+      // iterators:
+      iterator
+      begin()
+      { return iterator(_Base::begin()); }
+
+      const_iterator
+      begin() const
+      { return const_iterator(_Base::begin()); }
+
+      iterator
+      end()
+      { return iterator(_Base::end()); }
+
+      const_iterator
+      end() const
+      { return const_iterator(_Base::end()); }
+
+      reverse_iterator
+      rbegin()
+      { return reverse_iterator(end()); }
+
+      const_reverse_iterator
+      rbegin() const
+      { return const_reverse_iterator(end()); }
+
+      reverse_iterator
+      rend()
+      { return reverse_iterator(begin()); }
+
+      const_reverse_iterator
+      rend() const
+      { return const_reverse_iterator(begin()); }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      const_iterator
+      cbegin() const
+      { return const_iterator(_Base::begin()); }
+
+      const_iterator
+      cend() const
+      { return const_iterator(_Base::end()); }
+
+      const_reverse_iterator
+      crbegin() const
+      { return const_reverse_iterator(end()); }
+
+      const_reverse_iterator
+      crend() const
+      { return const_reverse_iterator(begin()); }
+#endif
+
+      // capacity:
+      using _Base::empty;
+      using _Base::size;
+      using _Base::max_size;
+
+      // modifiers:
+      iterator
+      insert(const value_type& __x)
+      { return iterator(_Base::insert(__x)); }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      void
+      insert(std::initializer_list<value_type> __list)
+      { _Base::insert(__list); }
+#endif
+
+      iterator
+      insert(iterator __position, const value_type& __x)
+      {
+       return iterator(_Base::insert(__position, __x));
+      }
+
+      template<typename _InputIterator>
+        void
+        insert(_InputIterator __first, _InputIterator __last)
+        {
+         _Base::insert(__first, __last);
+       }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      iterator
+      erase(iterator __position)
+      {
+        return _Base::erase(__position);
+      }
+#else
+      void
+      erase(iterator __position)
+      {
+       _Base::erase(__position);
+      }
+#endif
+
+      size_type
+      erase(const key_type& __x)
+      {
+       std::pair<iterator, iterator> __victims = this->equal_range(__x);
+       size_type __count = 0;
+       while (__victims.first != __victims.second)
+       {
+         iterator __victim = __victims.first++;
+         _Base::erase(__victim);
+         ++__count;
+       }
+       return __count;
+      }
+
+      void
+      erase(iterator __first, iterator __last)
+      {
+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
+       // 151. can't currently clear() empty container
+       while (__first != __last)
+       this->erase(__first++);
+      }
+
+      void
+      swap(multimap& __x)
+      {
+       _Base::swap(__x);
+      }
+
+      void
+      clear()
+      { this->erase(begin(), end()); }
+
+      // observers:
+      using _Base::key_comp;
+      using _Base::value_comp;
+
+      // 23.3.1.3 multimap operations:
+      iterator
+      find(const key_type& __x)
+      { return iterator(_Base::find(__x)); }
+
+      const_iterator
+      find(const key_type& __x) const
+      { return const_iterator(_Base::find(__x)); }
+
+      using _Base::count;
+
+      iterator
+      lower_bound(const key_type& __x)
+      { return iterator(_Base::lower_bound(__x)); }
+
+      const_iterator
+      lower_bound(const key_type& __x) const
+      { return const_iterator(_Base::lower_bound(__x)); }
+
+      iterator
+      upper_bound(const key_type& __x)
+      { return iterator(_Base::upper_bound(__x)); }
+
+      const_iterator
+      upper_bound(const key_type& __x) const
+      { return const_iterator(_Base::upper_bound(__x)); }
+
+      std::pair<iterator,iterator>
+      equal_range(const key_type& __x)
+      {
+       typedef typename _Base::iterator _Base_iterator;
+       std::pair<_Base_iterator, _Base_iterator> __res =
+       _Base::equal_range(__x);
+       return std::make_pair(iterator(__res.first),
+                             iterator(__res.second));
+      }
+
+      std::pair<const_iterator,const_iterator>
+      equal_range(const key_type& __x) const
+      {
+       typedef typename _Base::const_iterator _Base_const_iterator;
+       std::pair<_Base_const_iterator, _Base_const_iterator> __res =
+       _Base::equal_range(__x);
+       return std::make_pair(const_iterator(__res.first),
+                             const_iterator(__res.second));
+      }
+
+      _Base&
+      _M_base() { return *this; }
+
+      const _Base&
+      _M_base() const { return *this; }
+    };
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline bool
+    operator==(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
+              const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() == __rhs._M_base(); }
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline bool
+    operator!=(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
+              const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() != __rhs._M_base(); }
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline bool
+    operator<(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
+             const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() < __rhs._M_base(); }
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline bool
+    operator<=(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
+              const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() <= __rhs._M_base(); }
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline bool
+    operator>=(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
+              const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() >= __rhs._M_base(); }
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline bool
+    operator>(const multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
+             const multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() > __rhs._M_base(); }
+
+  template<typename _Key, typename _Tp,
+          typename _Compare, typename _Allocator>
+    inline void
+    swap(multimap<_Key, _Tp, _Compare, _Allocator>& __lhs,
+        multimap<_Key, _Tp, _Compare, _Allocator>& __rhs)
+    { __lhs.swap(__rhs); }
+
+} // namespace __profile
+} // namespace std
+
+#endif
diff --git a/libstdc++-v3/include/profile/multiset.h b/libstdc++-v3/include/profile/multiset.h
new file mode 100644 (file)
index 0000000..759761b
--- /dev/null
@@ -0,0 +1,363 @@
+// Profiling multiset implementation -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file profile/multiset.h
+ *  This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_PROFILE_MULTISET_H
+#define _GLIBCXX_PROFILE_MULTISET_H 1
+
+#include <utility>
+
+namespace std
+{
+namespace __profile
+{
+  /** @brief Multiset wrapper with performance instrumentation.  */
+  template<typename _Key, typename _Compare = std::less<_Key>,
+          typename _Allocator = std::allocator<_Key> >
+    class multiset
+    : public _GLIBCXX_STD_D::multiset<_Key, _Compare, _Allocator>
+    {
+      typedef _GLIBCXX_STD_D::multiset<_Key, _Compare, _Allocator> _Base;
+
+    public:
+      // types:
+      typedef _Key                                  key_type;
+      typedef _Key                                  value_type;
+      typedef _Compare                              key_compare;
+      typedef _Compare                              value_compare;
+      typedef _Allocator                            allocator_type;
+      typedef typename _Base::reference                     reference;
+      typedef typename _Base::const_reference        const_reference;
+
+      typedef typename _Base::iterator               iterator;
+      typedef typename _Base::const_iterator         const_iterator;
+      typedef typename _Base::reverse_iterator       reverse_iterator;
+      typedef typename _Base::const_reverse_iterator const_reverse_iterator;
+
+      typedef typename _Base::size_type              size_type;
+      typedef typename _Base::difference_type        difference_type;
+      typedef typename _Base::pointer                pointer;
+      typedef typename _Base::const_pointer          const_pointer;
+
+      // 23.3.3.1 construct/copy/destroy:
+      explicit multiset(const _Compare& __comp = _Compare(),
+                       const _Allocator& __a = _Allocator())
+      : _Base(__comp, __a) { }
+
+      template<typename _InputIterator>
+        multiset(_InputIterator __first, _InputIterator __last,
+                const _Compare& __comp = _Compare(),
+                const _Allocator& __a = _Allocator())
+       : _Base(__first, __last, __comp, __a) { }
+
+      multiset(const multiset& __x)
+      : _Base(__x) { }
+
+      multiset(const _Base& __x)
+      : _Base(__x) { }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      multiset(multiset&& __x)
+      : _Base(std::forward<multiset>(__x))
+      { }
+
+      multiset(initializer_list<value_type> __l,
+              const _Compare& __comp = _Compare(),
+              const allocator_type& __a = allocator_type())
+      : _Base(__l, __comp, __a) { }
+#endif
+
+      ~multiset() { }
+
+      multiset&
+      operator=(const multiset& __x)
+      {
+       *static_cast<_Base*>(this) = __x;
+       return *this;
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      multiset&
+      operator=(multiset&& __x)
+      {
+        // NB: DR 675.
+       this->clear();
+       this->swap(__x);
+       return *this;
+      }
+
+      multiset&
+      operator=(initializer_list<value_type> __l)
+      {
+       this->clear();
+       this->insert(__l);
+       return *this;
+      }
+#endif
+
+      using _Base::get_allocator;
+
+      // iterators:
+      iterator
+      begin()
+      { return iterator(_Base::begin()); }
+
+      const_iterator
+      begin() const
+      { return const_iterator(_Base::begin()); }
+
+      iterator
+      end()
+      { return iterator(_Base::end()); }
+
+      const_iterator
+      end() const
+      { return const_iterator(_Base::end()); }
+
+      reverse_iterator
+      rbegin()
+      { return reverse_iterator(end()); }
+
+      const_reverse_iterator
+      rbegin() const
+      { return const_reverse_iterator(end()); }
+
+      reverse_iterator
+      rend()
+      { return reverse_iterator(begin()); }
+
+      const_reverse_iterator
+      rend() const
+      { return const_reverse_iterator(begin()); }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      const_iterator
+      cbegin() const
+      { return const_iterator(_Base::begin()); }
+
+      const_iterator
+      cend() const
+      { return const_iterator(_Base::end()); }
+
+      const_reverse_iterator
+      crbegin() const
+      { return const_reverse_iterator(end()); }
+
+      const_reverse_iterator
+      crend() const
+      { return const_reverse_iterator(begin()); }
+#endif
+
+      // capacity:
+      using _Base::empty;
+      using _Base::size;
+      using _Base::max_size;
+
+      // modifiers:
+      iterator
+      insert(const value_type& __x)
+      { return iterator(_Base::insert(__x)); }
+
+      iterator
+      insert(iterator __position, const value_type& __x)
+      {
+       return iterator(_Base::insert(__position, __x));
+      }
+
+      template<typename _InputIterator>
+      void
+      insert(_InputIterator __first, _InputIterator __last)
+      {
+       _Base::insert(__first, __last);
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      void
+      insert(initializer_list<value_type> __l)
+      { _Base::insert(__l); }
+#endif
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      iterator
+      erase(iterator __position)
+      {
+        return _Base::erase(__position);
+      }
+#else
+      void
+      erase(iterator __position)
+      {
+       _Base::erase(__position);
+      }
+#endif
+
+      size_type
+      erase(const key_type& __x)
+      {
+       std::pair<iterator, iterator> __victims = this->equal_range(__x);
+       size_type __count = 0;
+       while (__victims.first != __victims.second)
+       {
+         iterator __victim = __victims.first++;
+         _Base::erase(__victim);
+         ++__count;
+       }
+       return __count;
+      }
+
+      void
+      erase(iterator __first, iterator __last)
+      {
+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
+       // 151. can't currently clear() empty container
+       while (__first != __last)
+       this->erase(__first++);
+      }
+
+      void
+      swap(multiset& __x)
+      {
+       _Base::swap(__x);
+      }
+
+      void
+      clear()
+      { this->erase(begin(), end()); }
+
+      // observers:
+      using _Base::key_comp;
+      using _Base::value_comp;
+
+      // multiset operations:
+      iterator
+      find(const key_type& __x)
+      { return iterator(_Base::find(__x)); }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 214. set::find() missing const overload
+      const_iterator
+      find(const key_type& __x) const
+      { return const_iterator(_Base::find(__x)); }
+
+      using _Base::count;
+
+      iterator
+      lower_bound(const key_type& __x)
+      { return iterator(_Base::lower_bound(__x)); }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 214. set::find() missing const overload
+      const_iterator
+      lower_bound(const key_type& __x) const
+      { return const_iterator(_Base::lower_bound(__x)); }
+
+      iterator
+      upper_bound(const key_type& __x)
+      { return iterator(_Base::upper_bound(__x)); }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 214. set::find() missing const overload
+      const_iterator
+      upper_bound(const key_type& __x) const
+      { return const_iterator(_Base::upper_bound(__x)); }
+
+      std::pair<iterator,iterator>
+      equal_range(const key_type& __x)
+      {
+       typedef typename _Base::iterator _Base_iterator;
+       std::pair<_Base_iterator, _Base_iterator> __res =
+        _Base::equal_range(__x);
+       return std::make_pair(iterator(__res.first),
+                             iterator(__res.second));
+      }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 214. set::find() missing const overload
+      std::pair<const_iterator,const_iterator>
+      equal_range(const key_type& __x) const
+      {
+       typedef typename _Base::const_iterator _Base_iterator;
+       std::pair<_Base_iterator, _Base_iterator> __res =
+        _Base::equal_range(__x);
+       return std::make_pair(const_iterator(__res.first),
+                             const_iterator(__res.second));
+      }
+
+      _Base&
+      _M_base() { return *this; }
+
+      const _Base&
+      _M_base() const { return *this; }
+
+    };
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    inline bool
+    operator==(const multiset<_Key, _Compare, _Allocator>& __lhs,
+              const multiset<_Key, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() == __rhs._M_base(); }
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    inline bool
+    operator!=(const multiset<_Key, _Compare, _Allocator>& __lhs,
+              const multiset<_Key, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() != __rhs._M_base(); }
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    inline bool
+    operator<(const multiset<_Key, _Compare, _Allocator>& __lhs,
+             const multiset<_Key, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() < __rhs._M_base(); }
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    inline bool
+    operator<=(const multiset<_Key, _Compare, _Allocator>& __lhs,
+              const multiset<_Key, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() <= __rhs._M_base(); }
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    inline bool
+    operator>=(const multiset<_Key, _Compare, _Allocator>& __lhs,
+              const multiset<_Key, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() >= __rhs._M_base(); }
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    inline bool
+    operator>(const multiset<_Key, _Compare, _Allocator>& __lhs,
+             const multiset<_Key, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() > __rhs._M_base(); }
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    void
+    swap(multiset<_Key, _Compare, _Allocator>& __x,
+        multiset<_Key, _Compare, _Allocator>& __y)
+    { return __x.swap(__y); }
+
+} // namespace __profile
+} // namespace std
+
+#endif
diff --git a/libstdc++-v3/include/profile/set b/libstdc++-v3/include/profile/set
new file mode 100644 (file)
index 0000000..11603a8
--- /dev/null
@@ -0,0 +1,41 @@
+// Profiling set/multiset implementation -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+/** @file profile/set
+ *  This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_PROFILE_SET
+#define _GLIBCXX_PROFILE_SET 1
+
+#include <set>
+#include <profile/set.h>
+#include <profile/multiset.h>
+
+#endif
diff --git a/libstdc++-v3/include/profile/set.h b/libstdc++-v3/include/profile/set.h
new file mode 100644 (file)
index 0000000..50fb16f
--- /dev/null
@@ -0,0 +1,367 @@
+// Profiling set implementation -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file profile/set.h
+ *  This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_PROFILE_SET_H
+#define _GLIBCXX_PROFILE_SET_H 1
+
+#include <utility>
+
+namespace std 
+{
+namespace __profile
+{
+  /** @brief Set wrapper with performance instrumentation.  */
+  template<typename _Key, typename _Compare = std::less<_Key>,
+          typename _Allocator = std::allocator<_Key> >
+    class set
+    : public _GLIBCXX_STD_D::set<_Key,_Compare,_Allocator>
+    {
+      typedef _GLIBCXX_STD_D::set<_Key, _Compare, _Allocator> _Base;
+
+    public:
+      // types:
+      typedef _Key                                 key_type;
+      typedef _Key                                 value_type;
+      typedef _Compare                             key_compare;
+      typedef _Compare                             value_compare;
+      typedef _Allocator                           allocator_type;
+      typedef typename _Base::reference             reference;
+      typedef typename _Base::const_reference       const_reference;
+
+      typedef typename _Base::iterator               iterator;
+      typedef typename _Base::const_iterator         const_iterator;
+      typedef typename _Base::reverse_iterator       reverse_iterator;
+      typedef typename _Base::const_reverse_iterator const_reverse_iterator;
+
+      typedef typename _Base::size_type             size_type;
+      typedef typename _Base::difference_type       difference_type;
+      typedef typename _Base::pointer               pointer;
+      typedef typename _Base::const_pointer         const_pointer;
+
+      // 23.3.3.1 construct/copy/destroy:
+      explicit set(const _Compare& __comp = _Compare(),
+                  const _Allocator& __a = _Allocator())
+      : _Base(__comp, __a) { }
+
+      template<typename _InputIterator>
+        set(_InputIterator __first, _InputIterator __last,
+           const _Compare& __comp = _Compare(),
+           const _Allocator& __a = _Allocator())
+       : _Base(__first, __last, __comp, __a) { }
+
+      set(const set& __x)
+      : _Base(__x) { }
+
+      set(const _Base& __x)
+      : _Base(__x) { }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      set(set&& __x)
+      : _Base(std::forward<set>(__x))
+      { }
+
+      set(initializer_list<value_type> __l,
+         const _Compare& __comp = _Compare(),
+         const allocator_type& __a = allocator_type())
+      : _Base(__l, __comp, __a) { }
+#endif
+
+      ~set() { }
+
+      set&
+      operator=(const set& __x)
+      {
+       *static_cast<_Base*>(this) = __x;
+       return *this;
+      }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      set&
+      operator=(set&& __x)
+      {
+        // NB: DR 675.
+       this->clear();
+       this->swap(__x);
+       return *this;
+      }
+
+      set&
+      operator=(initializer_list<value_type> __l)
+      {
+       this->clear();
+       this->insert(__l);
+       return *this;
+      }
+#endif
+
+      using _Base::get_allocator;
+
+      // iterators:
+      iterator
+      begin()
+      { return iterator(_Base::begin()); }
+
+      const_iterator
+      begin() const
+      { return const_iterator(_Base::begin()); }
+
+      iterator
+      end()
+      { return iterator(_Base::end()); }
+
+      const_iterator
+      end() const
+      { return const_iterator(_Base::end()); }
+
+      reverse_iterator
+      rbegin()
+      { return reverse_iterator(end()); }
+
+      const_reverse_iterator
+      rbegin() const
+      { return const_reverse_iterator(end()); }
+
+      reverse_iterator
+      rend()
+      { return reverse_iterator(begin()); }
+
+      const_reverse_iterator
+      rend() const
+      { return const_reverse_iterator(begin()); }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      const_iterator
+      cbegin() const
+      { return const_iterator(_Base::begin()); }
+
+      const_iterator
+      cend() const
+      { return const_iterator(_Base::end()); }
+
+      const_reverse_iterator
+      crbegin() const
+      { return const_reverse_iterator(end()); }
+
+      const_reverse_iterator
+      crend() const
+      { return const_reverse_iterator(begin()); }
+#endif
+
+      // capacity:
+      using _Base::empty;
+      using _Base::size;
+      using _Base::max_size;
+
+      // modifiers:
+      std::pair<iterator, bool>
+      insert(const value_type& __x)
+      {
+       typedef typename _Base::iterator _Base_iterator;
+       std::pair<_Base_iterator, bool> __res = _Base::insert(__x);
+       return std::pair<iterator, bool>(iterator(__res.first),
+                                        __res.second);
+      }
+
+      iterator
+      insert(iterator __position, const value_type& __x)
+      {
+       return iterator(_Base::insert(__position, __x));
+      }
+
+      template <typename _InputIterator>
+        void
+        insert(_InputIterator __first, _InputIterator __last)
+        {
+         _Base::insert(__first, __last);
+       }
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      void
+      insert(initializer_list<value_type> __l)
+      { _Base::insert(__l); }
+#endif
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      iterator
+      erase(iterator __position)
+      {
+        return _Base::erase(__position);
+      }
+#else
+      void
+      erase(iterator __position)
+      {
+       _Base::erase(__position);
+      }
+#endif
+
+      size_type
+      erase(const key_type& __x)
+      {
+       iterator __victim = find(__x);
+       if (__victim == end())
+          return 0;
+       else
+        {
+         _Base::erase(__victim);
+         return 1;
+        }
+      }
+
+      void
+      erase(iterator __first, iterator __last)
+      {
+       // _GLIBCXX_RESOLVE_LIB_DEFECTS
+       // 151. can't currently clear() empty container
+       while (__first != __last)
+        this->erase(__first++);
+      }
+
+      void
+      swap(set& __x)
+      {
+       _Base::swap(__x);
+      }
+
+      void
+      clear()
+      { this->erase(begin(), end()); }
+
+      // observers:
+      using _Base::key_comp;
+      using _Base::value_comp;
+
+      // set operations:
+      iterator
+      find(const key_type& __x)
+      { return iterator(_Base::find(__x)); }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 214. set::find() missing const overload
+      const_iterator
+      find(const key_type& __x) const
+      { return const_iterator(_Base::find(__x)); }
+
+      using _Base::count;
+
+      iterator
+      lower_bound(const key_type& __x)
+      { return iterator(_Base::lower_bound(__x)); }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 214. set::find() missing const overload
+      const_iterator
+      lower_bound(const key_type& __x) const
+      { return const_iterator(_Base::lower_bound(__x)); }
+
+      iterator
+      upper_bound(const key_type& __x)
+      { return iterator(_Base::upper_bound(__x)); }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 214. set::find() missing const overload
+      const_iterator
+      upper_bound(const key_type& __x) const
+      { return const_iterator(_Base::upper_bound(__x)); }
+
+      std::pair<iterator,iterator>
+      equal_range(const key_type& __x)
+      {
+       typedef typename _Base::iterator _Base_iterator;
+       std::pair<_Base_iterator, _Base_iterator> __res =
+        _Base::equal_range(__x);
+       return std::make_pair(iterator(__res.first),
+                             iterator(__res.second));
+      }
+
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 214. set::find() missing const overload
+      std::pair<const_iterator,const_iterator>
+      equal_range(const key_type& __x) const
+      {
+       typedef typename _Base::const_iterator _Base_iterator;
+       std::pair<_Base_iterator, _Base_iterator> __res =
+        _Base::equal_range(__x);
+       return std::make_pair(const_iterator(__res.first),
+                             const_iterator(__res.second));
+      }
+
+      _Base&
+      _M_base() { return *this; }
+
+      const _Base&
+      _M_base() const { return *this; }
+
+    };
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    inline bool
+    operator==(const set<_Key, _Compare, _Allocator>& __lhs,
+              const set<_Key, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() == __rhs._M_base(); }
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    inline bool
+    operator!=(const set<_Key, _Compare, _Allocator>& __lhs,
+              const set<_Key, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() != __rhs._M_base(); }
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    inline bool
+    operator<(const set<_Key, _Compare, _Allocator>& __lhs,
+             const set<_Key, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() < __rhs._M_base(); }
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    inline bool
+    operator<=(const set<_Key, _Compare, _Allocator>& __lhs,
+              const set<_Key, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() <= __rhs._M_base(); }
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    inline bool
+    operator>=(const set<_Key, _Compare, _Allocator>& __lhs,
+              const set<_Key, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() >= __rhs._M_base(); }
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    inline bool
+    operator>(const set<_Key, _Compare, _Allocator>& __lhs,
+             const set<_Key, _Compare, _Allocator>& __rhs)
+    { return __lhs._M_base() > __rhs._M_base(); }
+
+  template<typename _Key, typename _Compare, typename _Allocator>
+    void
+    swap(set<_Key, _Compare, _Allocator>& __x,
+        set<_Key, _Compare, _Allocator>& __y)
+    { return __x.swap(__y); }
+
+} // namespace __profile
+} // namespace std
+
+#endif
diff --git a/libstdc++-v3/include/profile/unordered_map b/libstdc++-v3/include/profile/unordered_map
new file mode 100644 (file)
index 0000000..d1cb921
--- /dev/null
@@ -0,0 +1,498 @@
+// Profiling unordered_map/unordered_multimap implementation -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+/** @file profile/unordered_map
+ *  This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_PROFILE_UNORDERED_MAP
+#define _GLIBCXX_PROFILE_UNORDERED_MAP 1
+
+#include <profile/base.h>
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+# include <unordered_map>
+#else
+# include <c++0x_warning.h>
+#endif
+
+#include <initializer_list>
+
+#define _GLIBCXX_BASE unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
+#define _GLIBCXX_STD_BASE _GLIBCXX_STD_PR::_GLIBCXX_BASE
+
+namespace std
+{
+namespace __profile
+{
+  /** @brief Unordered_map wrapper with performance instrumentation.  */
+  template<typename _Key, typename _Tp,
+          typename _Hash  = std::hash<_Key>,
+          typename _Pred = std::equal_to<_Key>,
+          typename _Alloc =  std::allocator<_Key> >
+    class unordered_map
+    : public _GLIBCXX_STD_BASE
+    {
+      typedef typename _GLIBCXX_STD_BASE _Base;
+
+    public:
+      typedef typename _Base::size_type       size_type;
+      typedef typename _Base::hasher          hasher;
+      typedef typename _Base::key_equal       key_equal;
+      typedef typename _Base::allocator_type  allocator_type;
+      typedef typename _Base::key_type        key_type;
+      typedef typename _Base::value_type      value_type;
+      typedef typename _Base::difference_type difference_type;
+      typedef typename _Base::reference       reference;
+      typedef typename _Base::const_reference const_reference;
+      typedef typename _Base::mapped_type      mapped_type;
+      typedef std::pair<typename _Base::iterator, bool> pair_type;
+      typedef typename _Base::insert_return_type insert_return_type;
+
+      typedef typename _Base::iterator iterator;
+      typedef typename _Base::const_iterator const_iterator;
+
+      explicit
+      unordered_map(size_type __n = 10,
+                   const hasher& __hf = hasher(),
+                   const key_equal& __eql = key_equal(),
+                   const allocator_type& __a = allocator_type())
+      : _Base(__n, __hf, __eql, __a)
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+        __profcxx_hashtable_construct2(this);
+      }
+
+      template<typename _InputIterator>
+        unordered_map(_InputIterator __f, _InputIterator __l,
+              size_type __n = 10,
+              const hasher& __hf = hasher(),
+              const key_equal& __eql = key_equal(),
+              const allocator_type& __a = allocator_type())
+      : _Base(__f, __l, __n, __hf, __eql, __a)
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+        __profcxx_hashtable_construct2(this);
+      }
+
+      unordered_map(const _Base& __x)
+      : _Base(__x) 
+      { 
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+        __profcxx_hashtable_construct2(this);
+      }
+
+      unordered_map(unordered_map&& __x)
+      : _Base(std::forward<_Base>(__x)) 
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+        __profcxx_hashtable_construct2(this);
+      }
+
+      unordered_map(initializer_list<value_type> __l,
+                   size_type __n = 10,
+                   const hasher& __hf = hasher(),
+                   const key_equal& __eql = key_equal(),
+                   const allocator_type& __a = allocator_type())
+      : _Base(__l, __n, __hf, __eql, __a) { }
+
+      unordered_map&
+      operator=(const unordered_map& __x)
+      {
+       *static_cast<_Base*>(this) = __x;
+       return *this;
+      }
+
+      unordered_map&
+      operator=(unordered_map&& __x)
+      {
+        // NB: DR 675.
+       this->clear();
+       this->swap(__x);
+       return *this;
+      }
+
+      unordered_map&
+      operator=(initializer_list<value_type> __l)
+      {
+       this->clear();
+       this->insert(__l);
+       return *this;
+      }
+
+      ~unordered_map()
+      {
+        __profcxx_hashtable_destruct(this, _Base::bucket_count(), _Base::size());
+        _M_profile_destruct();
+      }
+
+      _Base&
+      _M_base()       { return *this; }
+
+      const _Base&
+      _M_base() const { return *this; }
+
+
+      void
+      clear()
+      {
+        __profcxx_hashtable_destruct(this, _Base::bucket_count(), _Base::size());
+        _M_profile_destruct();
+        _Base::clear();
+      }
+
+      void
+      insert(std::initializer_list<value_type> __l)
+      { 
+        size_type __old_size = _Base::bucket_count(); 
+        _Base::insert(__l);
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+      }
+
+       insert_return_type
+      insert(const value_type& __obj)
+      {
+        size_type __old_size =  _Base::bucket_count();
+        insert_return_type __res = _Base::insert(__obj);
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+        return __res;
+      }
+      iterator
+      insert(iterator __iter, const value_type& __v)
+      { 
+        size_type __old_size = _Base::bucket_count(); 
+        iterator res = _Base::insert(__iter, __v);
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+        return res;
+      }
+
+      const_iterator
+      insert(const_iterator __iter, const value_type& __v)
+      { 
+        size_type __old_size = _Base::bucket_count(); 
+        const_iterator res =_Base::insert(__iter, __v);
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+        return res;
+      }
+
+      template<typename _InputIter>
+      void
+      insert(_InputIter __first, _InputIter __last)
+      {
+        size_type __old_size = _Base::bucket_count(); 
+        _Base::insert(__first.base(), __last.base());
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+      }
+
+      void
+      insert(const value_type* __first, const value_type* __last)
+      {
+        size_type __old_size = _Base::bucket_count(); 
+        _Base::insert(__first, __last);
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+      }
+     
+      // operator []
+      mapped_type&
+      operator[](const _Key& _k)
+      {
+        size_type __old_size =  _Base::bucket_count();
+        mapped_type& __res = _M_base()[_k];
+        size_type __new_size =  _Base::bucket_count();
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+        return __res;
+      }   
+
+      void
+      swap(unordered_map& __x)
+      {
+        _Base::swap(__x);
+      }
+      
+      void rehash(size_type __n)
+      {
+        size_type __old_size =  _Base::bucket_count();
+        _Base::rehash(__n);
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+      }
+    private:
+      void _M_profile_resize(size_type __old_size, size_type __new_size)
+      {
+        if (__old_size != __new_size)
+        {
+          __profcxx_hashtable_resize(this, __old_size, __new_size);
+        }
+      }
+      void _M_profile_destruct()
+      {
+        size_type __hops = 0, __lc = 0, __chain = 0;
+        for (iterator it = _M_base().begin(); it != _M_base().end(); it++)
+        {
+          while (it._M_cur_node->_M_next) {
+             __chain++;
+             it++;
+          }
+          if (__chain) {
+            __chain++;
+            __lc = __lc > __chain ? __lc : __chain;  
+            __hops += __chain * (__chain - 1) / 2;
+            __chain = 0;
+          }
+        }
+        __profcxx_hashtable_destruct2(this, __lc,  _Base::size(), __hops); 
+      }
+   };
+  template<typename _Key, typename _Tp, typename _Hash,
+       typename _Pred, typename _Alloc>
+    inline void
+    swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
+     unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
+    { __x.swap(__y); }
+
+#undef _GLIBCXX_BASE
+#undef _GLIBCXX_STD_BASE
+#define _GLIBCXX_BASE unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>
+#define _GLIBCXX_STD_BASE _GLIBCXX_STD_PR::_GLIBCXX_BASE
+
+  /** @brief Unordered_multimap wrapper with performance instrumentation.  */
+  template<typename _Key, typename _Tp,
+          typename _Hash  = std::hash<_Key>,
+          typename _Pred = std::equal_to<_Key>,
+          typename _Alloc =  std::allocator<_Key> >
+    class unordered_multimap
+    : public _GLIBCXX_STD_BASE
+    {      
+      typedef typename _GLIBCXX_STD_BASE _Base;
+
+    public:
+      typedef typename _Base::size_type       size_type;
+      typedef typename _Base::hasher          hasher;
+      typedef typename _Base::key_equal       key_equal;
+      typedef typename _Base::allocator_type  allocator_type;
+      typedef typename _Base::key_type        key_type;
+      typedef typename _Base::value_type      value_type;
+      typedef typename _Base::difference_type difference_type;
+      typedef typename _Base::reference       reference;
+      typedef typename _Base::const_reference const_reference;
+      typedef std::pair<typename _Base::iterator, bool> pair_type;
+      typedef typename _Base::insert_return_type insert_return_type;
+
+      typedef typename _Base::iterator iterator;
+      typedef typename _Base::const_iterator const_iterator;
+
+      explicit
+      unordered_multimap(size_type __n = 10,
+                   const hasher& __hf = hasher(),
+                   const key_equal& __eql = key_equal(),
+                   const allocator_type& __a = allocator_type())
+      : _Base(__n, __hf, __eql, __a)
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+      }
+      template<typename _InputIterator>
+        unordered_multimap(_InputIterator __f, _InputIterator __l,
+              size_type __n = 10,
+              const hasher& __hf = hasher(),
+              const key_equal& __eql = key_equal(),
+              const allocator_type& __a = allocator_type())
+      : _Base(__f, __l, __n, __hf, __eql, __a)
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+      }
+
+      unordered_multimap(const _Base& __x)
+      : _Base(__x)
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+      }
+
+      unordered_multimap(unordered_multimap&& __x)
+      : _Base(std::forward<_Base>(__x))
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+      }
+
+      unordered_multimap(initializer_list<value_type> __l,
+                        size_type __n = 10,
+                        const hasher& __hf = hasher(),
+                        const key_equal& __eql = key_equal(),
+                        const allocator_type& __a = allocator_type())
+      : _Base(__l, __n, __hf, __eql, __a) { }
+
+      unordered_multimap&
+      operator=(const unordered_multimap& __x)
+      {
+       *static_cast<_Base*>(this) = __x;
+       return *this;
+      }
+
+      unordered_multimap&
+      operator=(unordered_multimap&& __x)
+      {
+        // NB: DR 675.
+       this->clear();
+       this->swap(__x);
+       return *this;
+      }
+
+      unordered_multimap&
+      operator=(initializer_list<value_type> __l)
+      {
+       this->clear();
+       this->insert(__l);
+       return *this;
+      }
+
+      ~unordered_multimap()
+      {
+        __profcxx_hashtable_destruct(this, _Base::bucket_count(), _Base::size());
+        _M_profile_destruct();
+      }
+
+      _Base&
+      _M_base()       { return *this; }
+
+      const _Base&
+      _M_base() const { return *this; }
+
+
+      void
+      clear()
+      {
+        __profcxx_hashtable_destruct(this, _Base::bucket_count(), _Base::size());
+        _M_profile_destruct();
+        _Base::clear();
+      }
+
+      void
+      insert(std::initializer_list<value_type> __l)
+      { 
+        size_type __old_size =  _Base::bucket_count();
+        _Base::insert(__l);
+        _M_profile_resize(__old_size, _Base::bucket_count());
+      }
+
+      insert_return_type
+      insert(const value_type& __obj)
+      {
+        size_type __old_size =  _Base::bucket_count();
+        insert_return_type __res = _Base::insert(__obj);
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+        return __res;
+      }
+      iterator
+      insert(iterator __iter, const value_type& __v)
+      { 
+        size_type __old_size = _Base::bucket_count(); 
+        iterator res = _Base::insert(__iter, __v);
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+        return res;
+      }
+
+      const_iterator
+      insert(const_iterator __iter, const value_type& __v)
+      { 
+        size_type __old_size = _Base::bucket_count(); 
+        const_iterator res =_Base::insert(__iter, __v);
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+        return res;
+      }
+
+      template<typename _InputIter>
+      void
+      insert(_InputIter __first, _InputIter __last)
+      {
+        size_type __old_size = _Base::bucket_count(); 
+        _Base::insert(__first.base(), __last.base());
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+      }
+
+      void
+      insert(const value_type* __first, const value_type* __last)
+      {
+        size_type __old_size = _Base::bucket_count(); 
+        _Base::insert(__first, __last);
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+      }
+
+      void
+      swap(unordered_multimap& __x)
+      {
+        _Base::swap(__x);
+      }
+
+      void rehash(size_type __n)
+      {
+        size_type __old_size =  _Base::bucket_count();
+        _Base::rehash(__n);
+        _M_profile_resize(__old_size, _Base::bucket_count()); 
+      }
+    private:
+      void _M_profile_resize(size_type __old_size, size_type __new_size)
+      {
+        if (__old_size != __new_size)
+        {
+          __profcxx_hashtable_resize(this, __old_size, __new_size);
+        }
+      }
+
+      void _M_profile_destruct()
+      {
+        size_type __hops = 0, __lc = 0, __chain = 0;
+        for (iterator it = _M_base().begin(); it != _M_base().end(); it++)
+        {
+          while (it._M_cur_node->_M_next) {
+             __chain++;
+             it++;
+          }
+          if (__chain) {
+            __chain++;
+            __lc = __lc > __chain ? __lc : __chain;
+            __hops += __chain * (__chain - 1) / 2;
+            __chain = 0;
+          }
+        }
+        __profcxx_hashtable_destruct2(this, __lc,  _Base::size(), __hops);
+      }
+
+    };
+  template<typename _Key, typename _Tp, typename _Hash,
+       typename _Pred, typename _Alloc>
+    inline void
+    swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
+     unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
+    { __x.swap(__y); }
+
+} // namespace __profile
+} // namespace std
+
+#undef _GLIBCXX_BASE
+#undef _GLIBCXX_STD_BASE
+
+#endif
diff --git a/libstdc++-v3/include/profile/unordered_set b/libstdc++-v3/include/profile/unordered_set
new file mode 100644 (file)
index 0000000..6c2dd77
--- /dev/null
@@ -0,0 +1,480 @@
+// Profiling unordered_set/unordered_multiset implementation -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// As a special exception, you may use this file as part of a free software
+// library without restriction.  Specifically, if other files instantiate
+// templates or use macros or inline functions from this file, or you compile
+// this file and link it with other files to produce an executable, this
+// file does not by itself cause the resulting executable to be covered by
+// the GNU General Public License.  This exception does not however
+// invalidate any other reasons why the executable file might be covered by
+// the GNU General Public License.
+
+/** @file profile/unordered_set
+ *  This file is a GNU profile extension to the Standard C++ Library.
+ */
+
+#ifndef _GLIBCXX_PROFILE_UNORDERED_SET
+#define _GLIBCXX_PROFILE_UNORDERED_SET 1
+
+#include <profile/base.h>
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+# include <unordered_set>
+#else
+# include <c++0x_warning.h>
+#endif
+
+#include <initializer_list>
+
+#define _GLIBCXX_BASE unordered_set<_Key, _Hash, _Pred, _Alloc>
+#define _GLIBCXX_STD_BASE _GLIBCXX_STD_PR::_GLIBCXX_BASE
+
+namespace std
+{
+namespace __profile
+{
+  /** @brief Unordered_set wrapper with performance instrumentation.  */
+  template<typename _Key, 
+          typename _Hash  = std::hash<_Key>,
+          typename _Pred = std::equal_to<_Key>,
+          typename _Alloc =  std::allocator<_Key> >
+    class unordered_set
+    : public _GLIBCXX_STD_BASE
+    {
+      typedef typename _GLIBCXX_STD_BASE _Base;
+
+    public:
+      typedef typename _Base::size_type       size_type;
+      typedef typename _Base::hasher          hasher;
+      typedef typename _Base::key_equal       key_equal;
+      typedef typename _Base::allocator_type  allocator_type;
+      typedef typename _Base::key_type        key_type;
+      typedef typename _Base::value_type      value_type;
+      typedef typename _Base::difference_type difference_type;
+      typedef typename _Base::reference       reference;
+      typedef typename _Base::const_reference const_reference;
+      typedef typename _Base::insert_return_type insert_return_type;
+
+      typedef typename _Base::iterator iterator;
+      typedef typename _Base::const_iterator const_iterator;
+
+      explicit
+      unordered_set(size_type __n = 10,
+                   const hasher& __hf = hasher(),
+                   const key_equal& __eql = key_equal(),
+                   const allocator_type& __a = allocator_type())
+      : _Base(__n, __hf, __eql, __a)
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+        __profcxx_hashtable_construct2(this);
+      }
+
+      template<typename _InputIterator>
+        unordered_set(_InputIterator __f, _InputIterator __l,
+              size_type __n = 10,
+              const hasher& __hf = hasher(),
+              const key_equal& __eql = key_equal(),
+              const allocator_type& __a = allocator_type())
+      : _Base(__f, __l, __n, __hf, __eql, __a)
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+        __profcxx_hashtable_construct2(this);
+      }
+
+      unordered_set(const _Base& __x)
+      : _Base(__x) 
+      { 
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+        __profcxx_hashtable_construct2(this);
+      }
+
+      unordered_set(unordered_set&& __x)
+      : _Base(std::forward<_Base>(__x)) 
+      { 
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+        __profcxx_hashtable_construct2(this);
+      }
+
+      unordered_set(initializer_list<value_type> __l,
+                   size_type __n = 10,
+                   const hasher& __hf = hasher(),
+                   const key_equal& __eql = key_equal(),
+                   const allocator_type& __a = allocator_type())
+      : _Base(__l, __n, __hf, __eql, __a) { }
+
+      unordered_set&
+      operator=(const unordered_set& __x)
+      {
+       *static_cast<_Base*>(this) = __x;
+       return *this;
+      }
+
+      unordered_set&
+      operator=(unordered_set&& __x)
+      {
+        // NB: DR 675.
+       this->clear();
+       this->swap(__x);
+       return *this;
+      }
+
+      unordered_set&
+      operator=(initializer_list<value_type> __l)
+      {
+       this->clear();
+       this->insert(__l);
+       return *this;
+      }
+
+      ~unordered_set()
+      {
+        __profcxx_hashtable_destruct(this, _Base::bucket_count(), 
+                                     _Base::size());
+        _M_profile_destruct();
+      }
+
+      void
+      swap(unordered_set& __x)
+      {
+        _Base::swap(__x);
+      }
+
+      void
+      clear()
+      {
+        __profcxx_hashtable_destruct(this, _Base::bucket_count(), 
+                                     _Base::size());
+        _M_profile_destruct();
+        _Base::clear();
+      }
+      void
+      insert(std::initializer_list<value_type> __l)
+      { 
+        size_type __old_size =  _Base::bucket_count();
+        _Base::insert(__l); 
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+      }
+      insert_return_type insert(const value_type& __obj)
+      {
+        size_type __old_size =  _Base::bucket_count();
+        insert_return_type __res = _Base::insert(__obj);
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+        return __res;
+      }
+      iterator
+      insert(iterator __iter, const value_type& __v)
+      { 
+        size_type __old_size = _Base::bucket_count(); 
+        iterator res = _Base::insert(__iter, __v);
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+        return res;
+      }
+
+      const_iterator
+      insert(const_iterator __iter, const value_type& __v)
+      { 
+        size_type __old_size = _Base::bucket_count(); 
+        const_iterator res =_Base::insert(__iter, __v);
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+        return res;
+      }
+
+      template<typename _InputIter>
+      void
+      insert(_InputIter __first, _InputIter __last)
+      {
+        size_type __old_size = _Base::bucket_count(); 
+        _Base::insert(__first, __last);
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+      }
+
+      void
+      insert(const value_type* __first, const value_type* __last)
+      {
+        size_type __old_size = _Base::bucket_count(); 
+        _Base::insert(__first, __last);
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+      }
+     
+      void rehash(size_type __n)
+      {
+        size_type __old_size =  _Base::bucket_count();
+        _Base::rehash(__n);
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+      }
+    private:
+      _Base&
+      _M_base()       { return *this; }
+
+      const _Base&
+      _M_base() const { return *this; }
+
+      void _M_profile_resize(size_type __old_size, size_type __new_size)
+      {
+        if (__old_size != __new_size)
+        {
+          __profcxx_hashtable_resize(this, __old_size, __new_size);
+        }
+      }
+      void _M_profile_destruct()
+      {
+        size_type __hops = 0, __lc = 0, __chain = 0;
+        for (iterator it = _M_base().begin(); it != _M_base().end(); it++)
+        {
+          while (it._M_cur_node->_M_next) {
+             __chain++;
+             it++;
+          }
+          if (__chain) {
+            __chain++;
+            __lc = __lc > __chain ? __lc : __chain;
+            __hops += __chain * (__chain - 1) / 2;
+            __chain = 0;
+          }
+        }
+        __profcxx_hashtable_destruct2(this, __lc,  _Base::size(), __hops);
+      }
+
+   };
+  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
+    inline void
+    swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
+     unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
+    { __x.swap(__y); }
+
+#undef _GLIBCXX_BASE
+#undef _GLIBCXX_STD_BASE
+#define _GLIBCXX_STD_BASE _GLIBCXX_STD_PR::_GLIBCXX_BASE
+#define _GLIBCXX_BASE unordered_multiset<_Value, _Hash, _Pred, _Alloc>
+
+  /** @brief Unordered_multiset wrapper with performance instrumentation.  */
+  template<typename _Value,
+       typename _Hash  = std::hash<_Value>,
+       typename _Pred = std::equal_to<_Value>,
+       typename _Alloc =  std::allocator<_Value> >
+    class unordered_multiset
+    : public _GLIBCXX_STD_BASE
+    {
+      typedef typename _GLIBCXX_STD_BASE _Base;
+
+    public:
+      typedef typename _Base::size_type       size_type;
+      typedef typename _Base::hasher          hasher;
+      typedef typename _Base::key_equal       key_equal;
+      typedef typename _Base::allocator_type  allocator_type;
+      typedef typename _Base::key_type        key_type;
+      typedef typename _Base::value_type      value_type;
+      typedef typename _Base::difference_type difference_type;
+      typedef typename _Base::reference       reference;
+      typedef typename _Base::const_reference const_reference;
+      typedef typename _Base::insert_return_type insert_return_type;
+
+      typedef typename _Base::iterator iterator;
+      typedef typename _Base::const_iterator const_iterator;
+
+      explicit
+      unordered_multiset(size_type __n = 10,
+                   const hasher& __hf = hasher(),
+                   const key_equal& __eql = key_equal(),
+                   const allocator_type& __a = allocator_type())
+      : _Base(__n, __hf, __eql, __a)
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+      }
+
+      template<typename _InputIterator>
+        unordered_multiset(_InputIterator __f, _InputIterator __l,
+              size_type __n = 10,
+              const hasher& __hf = hasher(),
+              const key_equal& __eql = key_equal(),
+              const allocator_type& __a = allocator_type())
+      : _Base(__f, __l, __n, __hf, __eql, __a)
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+      }
+
+      unordered_multiset(const _Base& __x)
+      : _Base(__x)
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+      }
+
+      unordered_multiset(unordered_multiset&& __x)
+      : _Base(std::forward<_Base>(__x))
+      {
+        __profcxx_hashtable_construct(this, _Base::bucket_count());
+      }
+
+      unordered_multiset(initializer_list<value_type> __l,
+                        size_type __n = 10,
+                        const hasher& __hf = hasher(),
+                        const key_equal& __eql = key_equal(),
+                        const allocator_type& __a = allocator_type())
+      : _Base(__l, __n, __hf, __eql, __a) { }
+
+      unordered_multiset&
+      operator=(const unordered_multiset& __x)
+      {
+       *static_cast<_Base*>(this) = __x;
+       return *this;
+      }
+
+      unordered_multiset&
+      operator=(unordered_multiset&& __x)
+      {
+        // NB: DR 675.
+       this->clear();
+       this->swap(__x);
+       return *this;
+      }
+
+      unordered_multiset&
+      operator=(initializer_list<value_type> __l)
+      {
+       this->clear();
+       this->insert(__l);
+       return *this;
+      }
+
+      ~unordered_multiset()
+      {
+        __profcxx_hashtable_destruct(this, _Base::bucket_count(), 
+                                     _Base::size());
+        _M_profile_destruct();
+      }
+
+      void
+      swap(unordered_multiset& __x)
+      {
+        _Base::swap(__x);
+      }
+
+      void
+      clear()
+      {
+        __profcxx_hashtable_destruct(this, _Base::bucket_count(), 
+                                     _Base::size());
+        _M_profile_destruct();
+        _Base::clear();
+      }
+      void
+      insert(std::initializer_list<value_type> __l)
+      { 
+        size_type __old_size =  _Base::bucket_count();
+        _Base::insert(__l); 
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+      }
+      insert_return_type insert(const value_type& __obj)
+      {
+        size_type __old_size =  _Base::bucket_count();
+        insert_return_type __res = _Base::insert(__obj);
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+        return __res;
+      }
+      iterator
+      insert(iterator __iter, const value_type& __v)
+      { 
+        size_type __old_size = _Base::bucket_count(); 
+        iterator res = _Base::insert(__iter, __v);
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+        return res;
+      }
+
+      const_iterator
+      insert(const_iterator __iter, const value_type& __v)
+      { 
+        size_type __old_size = _Base::bucket_count(); 
+        const_iterator res =_Base::insert(__iter, __v);
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+        return res;
+      }
+
+      template<typename _InputIter>
+      void
+      insert(_InputIter __first, _InputIter __last)
+      {
+        size_type __old_size = _Base::bucket_count(); 
+        _Base::insert(__first, __last);
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+      }
+
+      void
+      insert(const value_type* __first, const value_type* __last)
+      {
+        size_type __old_size = _Base::bucket_count(); 
+        _Base::insert(__first, __last);
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+      }
+     
+      void rehash(size_type __n)
+      {
+        size_type __old_size =  _Base::bucket_count();
+        _Base::rehash(__n);
+        _M_profile_resize(__old_size,  _Base::bucket_count()); 
+      }
+    private:
+      _Base&
+      _M_base()       { return *this; }
+
+      const _Base&
+      _M_base() const { return *this; }
+
+      void _M_profile_resize(size_type __old_size, size_type __new_size)
+      {
+        if (__old_size != __new_size)
+        {
+          __profcxx_hashtable_resize(this, __old_size, __new_size);
+        }
+      }
+
+      void _M_profile_destruct()
+      {
+        size_type __hops = 0, __lc = 0, __chain = 0;
+        for (iterator it = _M_base().begin(); it != _M_base().end(); it++)
+        {
+          while (it._M_cur_node->_M_next) {
+             __chain++;
+             it++;
+          }
+          if (__chain) {
+            __chain++;
+            __lc = __lc > __chain ? __lc : __chain;
+            __hops += __chain * (__chain - 1) / 2;
+            __chain = 0;
+          }
+        }
+        __profcxx_hashtable_destruct2(this, __lc,  _Base::size(), __hops);
+      }
+
+   };
+  template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
+    inline void
+    swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
+     unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
+    { __x.swap(__y); }
+
+} // namespace __profile
+} // namespace std
+
+#undef _GLIBCXX_BASE
+#undef _GLIBCXX_STD_BASE
+
+#endif
diff --git a/libstdc++-v3/include/profile/vector b/libstdc++-v3/include/profile/vector
new file mode 100644 (file)
index 0000000..e6aeb68
--- /dev/null
@@ -0,0 +1,369 @@
+// Profiling vector implementation -*- C++ -*-
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+