diff options
author | rus <rus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-10-03 02:17:41 +0000 |
---|---|---|
committer | rus <rus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-10-03 02:17:41 +0000 |
commit | c55dc904bf82da75f1a76a6523c4e8ff16352b4f (patch) | |
tree | 4ee10967bd743d512cc41a7b4610019f4ca6adfb /libstdc++-v3 | |
parent | fb5d6a4fa9aec18d9dda9b4d568d0e2be87a34ef (diff) | |
download | gcc-c55dc904bf82da75f1a76a6523c4e8ff16352b4f.tar.gz |
merge branch profile-stdlib
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@152431 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'libstdc++-v3')
58 files changed, 10252 insertions, 33 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 860b2000214..a68aec525e9 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -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>. diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index 41cf9679e4b..506b00e31b2 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -262,6 +262,9 @@ /* 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 diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 1eb77d19193..0ba287cec5a 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -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 diff --git a/libstdc++-v3/doc/Makefile.am b/libstdc++-v3/doc/Makefile.am index d53ae229b8c..22c549c9cfe 100644 --- a/libstdc++-v3/doc/Makefile.am +++ b/libstdc++-v3/doc/Makefile.am @@ -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 \ diff --git a/libstdc++-v3/doc/Makefile.in b/libstdc++-v3/doc/Makefile.in index 6eccd899a35..fd56f3c3e9d 100644 --- a/libstdc++-v3/doc/Makefile.in +++ b/libstdc++-v3/doc/Makefile.in @@ -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 \ diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in index 9c4b6c9bf51..9ffcf1ef75c 100644 --- a/libstdc++-v3/doc/doxygen/user.cfg.in +++ b/libstdc++-v3/doc/doxygen/user.cfg.in @@ -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 diff --git a/libstdc++-v3/doc/xml/manual/debug.xml b/libstdc++-v3/doc/xml/manual/debug.xml index 273196ee1a5..8aa53070377 100644 --- a/libstdc++-v3/doc/xml/manual/debug.xml +++ b/libstdc++-v3/doc/xml/manual/debug.xml @@ -243,4 +243,12 @@ </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> diff --git a/libstdc++-v3/doc/xml/manual/extensions.xml b/libstdc++-v3/doc/xml/manual/extensions.xml index 82e910023a4..889fe1db014 100644 --- a/libstdc++-v3/doc/xml/manual/extensions.xml +++ b/libstdc++-v3/doc/xml/manual/extensions.xml @@ -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 index 00000000000..5bf8eb13207 --- /dev/null +++ b/libstdc++-v3/doc/xml/manual/profile_mode.xml @@ -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 <vector> +int main() { + vector<int> v; + for (int k = 0; k < 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_<name> or by setting variable <name> + in the environment where the program is run, before starting execution. + <itemizedlist> + <listitem><para> + <code>[NO]_GLIBCXX_PROFILE_<diagnostic></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_<diagnostic></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 <profile/vector> +#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<__magic_info, + __magic_stack_info></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_<diagnostic></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_<diagnostic></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<int> us; +2 for (int k = 0; k < 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<unordered_set<int>> v(100000, unordered_set<int>(100)) ; +2 for (int k = 0; k < 100000; ++k) { +3 for (int j = 0; j < 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<int, dumb_hash> hs; + ... + for (int i = 0; i < 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<int> v; +2 for (int k = 0; k < 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<vector<int>> v(100000, vector<int>(100)) ; +2 for (int k = 0; k < 100000; ++k) { +3 for (int j = 0; j < 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<int> v; +... +2 for (int i = 0; i < 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<int> us; +... +2 int s = 0; +3 for (unordered_set<int>::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<int> v; +2 for (int i = 0; i < 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<int> l; +... +2 int sum = 0; +3 for (list<int>::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<int> s; +2 for (int i = 0; i < 100000; ++i) { +3 s.insert(i); +4 } +5 int sum = 0; +6 for (int i = 0; i < 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<int*> v(10000000, &zero); +3 for (int k = 0; k < 10000000; ++k) { +4 v[random() % 10000000] = new int(k); +5 } +6 for (int j = 0; j < 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<int> s; + 2 for (int i = 0; i < 10000000; ++i) { + 3 s.insert(i); + 4 } + 5 set<int> s1, s2; + 6 for (int i = 0; i < 10000000; ++i) { + 7 s1.insert(i); + 8 s2.insert(i); + 9 } +... + // Fast, better locality. +10 for (set<int>::iterator it = s.begin(); it != s.end(); ++it) { +11 sum += *it; +12 } + // Slow, elements are further apart. +13 for (set<int>::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<int> v(2, 0); +2 #pragma omp parallel for shared(v, SIZE) schedule(static, 1) +3 for (i = 0; i < 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> diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 55d02364d11..f3dcd19b79f 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -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 \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 47995ef7d8f..4c69a2be288 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -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 \ diff --git a/libstdc++-v3/include/backward/hash_map b/libstdc++-v3/include/backward/hash_map index 469429ccc24..cb31687c008 100644 --- a/libstdc++-v3/include/backward/hash_map +++ b/libstdc++-v3/include/backward/hash_map @@ -58,7 +58,11 @@ #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) diff --git a/libstdc++-v3/include/backward/hash_set b/libstdc++-v3/include/backward/hash_set index 32fa2205eea..d2bd03bb0b3 100644 --- a/libstdc++-v3/include/backward/hash_set +++ b/libstdc++-v3/include/backward/hash_set @@ -58,7 +58,11 @@ #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) diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index d5babc31959..724f373ebae 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -85,11 +85,17 @@ # 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 @@ -108,6 +114,7 @@ #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 @@ -124,7 +131,7 @@ # 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 @@ -134,7 +141,7 @@ # 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 @@ -144,7 +151,7 @@ # 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 @@ -153,6 +160,21 @@ # 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 @@ -163,7 +185,7 @@ #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 index 00000000000..de7bfe9a56f --- /dev/null +++ b/libstdc++-v3/include/profile/base.h @@ -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 index 00000000000..96a59ea4ad9 --- /dev/null +++ b/libstdc++-v3/include/profile/bitset @@ -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 index 00000000000..6ba3679e0c6 --- /dev/null +++ b/libstdc++-v3/include/profile/deque @@ -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 index 00000000000..20891877121 --- /dev/null +++ b/libstdc++-v3/include/profile/hashtable.h @@ -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 index 00000000000..f86920344fc --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler.h @@ -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 index 00000000000..330afc5ba79 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_container_size.h @@ -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 index 00000000000..cf639545163 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_hash_func.h @@ -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 index 00000000000..2192879325e --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_hashtable_size.h @@ -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 index 00000000000..cdb88a86bcb --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h @@ -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 index 00000000000..cd2b9ab2016 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_node.h @@ -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 index 00000000000..64c10db616c --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_state.h @@ -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 index 00000000000..37bcb6436e5 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_trace.h @@ -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 index 00000000000..dd42959825f --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_vector_size.h @@ -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 index 00000000000..ec3dfbcfb86 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_vector_to_list.h @@ -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 index 00000000000..061c5065826 --- /dev/null +++ b/libstdc++-v3/include/profile/list @@ -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 index 00000000000..e396b852398 --- /dev/null +++ b/libstdc++-v3/include/profile/map @@ -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 index 00000000000..aa9e535a1e4 --- /dev/null +++ b/libstdc++-v3/include/profile/map.h @@ -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 index 00000000000..b1fc70b63b2 --- /dev/null +++ b/libstdc++-v3/include/profile/multimap.h @@ -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 index 00000000000..759761bd52c --- /dev/null +++ b/libstdc++-v3/include/profile/multiset.h @@ -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 index 00000000000..11603a84858 --- /dev/null +++ b/libstdc++-v3/include/profile/set @@ -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 index 00000000000..50fb16faf37 --- /dev/null +++ b/libstdc++-v3/include/profile/set.h @@ -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 index 00000000000..d1cb9217d23 --- /dev/null +++ b/libstdc++-v3/include/profile/unordered_map @@ -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 index 00000000000..6c2dd77cb5f --- /dev/null +++ b/libstdc++-v3/include/profile/unordered_set @@ -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 index 00000000000..e6aeb686a7a --- /dev/null +++ b/libstdc++-v3/include/profile/vector @@ -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 +// 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/vector + * This file is a GNU profile extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_PROFILE_VECTOR +#define _GLIBCXX_PROFILE_VECTOR 1 + +#include <vector> +#include <utility> +#include <profile/base.h> + +namespace std +{ +namespace __profile +{ + /** @brief Vector wrapper with performance instrumentation. */ + template<typename _Tp, + typename _Allocator = std::allocator<_Tp> > + class vector + : public _GLIBCXX_STD_PR::vector<_Tp, _Allocator> + { + typedef _GLIBCXX_STD_PR::vector<_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; + + _Base& + _M_base() { return *this; } + + const _Base& + _M_base() const { return *this; } + + // 23.2.4.1 construct/copy/destroy: + explicit vector(const _Allocator& __a = _Allocator()) + : _Base(__a) + { + __profcxx_vector_construct(this, this->capacity()); + __profcxx_vector_construct2(this); + } + + explicit vector(size_type __n, const _Tp& __value = _Tp(), + const _Allocator& __a = _Allocator()) + : _Base(__n, __value, __a) + { + __profcxx_vector_construct(this, this->capacity()); + __profcxx_vector_construct2(this); + } + + template<class _InputIterator> + vector(_InputIterator __first, _InputIterator __last, + const _Allocator& __a = _Allocator()) + : _Base(__first, __last, __a) + { + __profcxx_vector_construct(this, this->capacity()); + __profcxx_vector_construct2(this); + } + + vector(const vector& __x) + : _Base(__x) + { + __profcxx_vector_construct(this, this->capacity()); + __profcxx_vector_construct2(this); + } + + /// Construction from a release-mode vector + vector(const _Base& __x) + : _Base(__x) + { + __profcxx_vector_construct(this, this->capacity()); + __profcxx_vector_construct2(this); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + vector(vector&& __x) + : _Base(std::forward<vector>(__x)) + { + __profcxx_vector_construct(this, this->capacity()); + __profcxx_vector_construct2(this); + } + + vector(initializer_list<value_type> __l, + const allocator_type& __a = allocator_type()) + : _Base(__l, __a) { } +#endif + + ~vector() { + __profcxx_vector_destruct(this, this->capacity(), this->size()); + __profcxx_vector_destruct2(this); + } + + vector& + operator=(const vector& __x) + { + static_cast<_Base&>(*this) = __x; + return *this; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + vector& + operator=(vector&& __x) + { + // NB: DR 675. + this->clear(); + this->swap(__x); + return *this; + } + + vector& + operator=(initializer_list<value_type> __l) + { + static_cast<_Base&>(*this) = __l; + return *this; + } +#endif + + using _Base::assign; + using _Base::get_allocator; + + // 23.2.4.2 capacity: + using _Base::size; + using _Base::max_size; + + void + resize(size_type __sz, _Tp __c = _Tp()) + { + __profcxx_vector_invalid_operator(this); + _M_profile_resize(this, this->capacity(), __sz); + _Base::resize(__sz, __c); + } + + using _Base::empty; + + // element access: + reference + operator[](size_type __n) + { + __profcxx_vector_invalid_operator(this); + return _M_base()[__n]; + } + const_reference + operator[](size_type __n) const + { + __profcxx_vector_invalid_operator(this); + 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(); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 464. Suggestion for new member functions in standard containers. + using _Base::data; + + // 23.2.4.3 modifiers: + void + push_back(const _Tp& __x) + { + size_type __old_size = this->capacity(); + _Base::push_back(__x); + _M_profile_resize(this, __old_size, this->capacity()); + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + push_back(_Tp&& __x) + { + size_type __old_size = this->capacity(); + _Base::push_back(__x); + _M_profile_resize(this, __old_size, this->capacity()); + } + +#endif + + iterator + insert(iterator __position, const _Tp& __x) + { + __profcxx_vector_insert(this, __position-_Base::begin(), this->size()); + size_type __old_size = this->capacity(); + typename _Base::iterator __res = _Base::insert(__position,__x); + _M_profile_resize(this, __old_size, this->capacity()); + return __res; + } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + iterator + insert(iterator __position, _Tp&& __x) + { + __profcxx_vector_insert(this, __position-_Base::begin(), this->size()); + size_type __old_size = this->capacity(); + typename _Base::iterator __res = _Base::insert(__position,__x); + _M_profile_resize(this, __old_size, this->capacity()); + return __res; + } + + void + insert(iterator __position, initializer_list<value_type> __l) + { this->insert(__position, __l.begin(), __l.end()); } +#endif + + void + + swap(vector& __x) + { + _Base::swap(__x); + } + + + void + insert(iterator __position, size_type __n, const _Tp& __x) + { + __profcxx_vector_insert(this, __position-_Base::begin(), this->size()); + size_type __old_size = this->capacity(); + _Base::insert(__position, __n, __x); + _M_profile_resize(this, __old_size, this->capacity()); + } + + template<class _InputIterator> + void + insert(iterator __position, + _InputIterator __first, _InputIterator __last) + { + __profcxx_vector_insert(this, __position-_Base::begin(), this->size()); + size_type __old_size = this->capacity(); + _Base::insert(__position, __first, __last); + _M_profile_resize(this, __old_size, this->capacity()); + } + + void + clear() + { + __profcxx_vector_destruct(this, this->capacity(), this->size()); + __profcxx_vector_destruct2(this); + _Base::clear(); + } + + // iterators: + iterator + begin() + { + return _Base::begin(); + } + + const_iterator + begin() const + { + return _Base::begin(); + } + + private: + void _M_profile_resize(void* obj, size_type __old_size, + size_type __new_size) + { + if (__old_size < __new_size) { + __profcxx_vector_resize(this, this->size(), __new_size); + __profcxx_vector_resize2(this, this->size(), __new_size); + } + } + }; + + template<typename _Tp, typename _Alloc> + inline bool + operator==(const vector<_Tp, _Alloc>& __lhs, + const vector<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() == __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator!=(const vector<_Tp, _Alloc>& __lhs, + const vector<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() != __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator<(const vector<_Tp, _Alloc>& __lhs, + const vector<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() < __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator<=(const vector<_Tp, _Alloc>& __lhs, + const vector<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() <= __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator>=(const vector<_Tp, _Alloc>& __lhs, + const vector<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() >= __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline bool + operator>(const vector<_Tp, _Alloc>& __lhs, + const vector<_Tp, _Alloc>& __rhs) + { return __lhs._M_base() > __rhs._M_base(); } + + template<typename _Tp, typename _Alloc> + inline void + swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs) + { __lhs.swap(__rhs); } + +} // namespace __profile + using _GLIBCXX_STD_D::_S_word_bit; +} // namespace std + +#endif diff --git a/libstdc++-v3/include/std/bitset b/libstdc++-v3/include/std/bitset index 5ca442989aa..131fe56de2d 100644 --- a/libstdc++-v3/include/std/bitset +++ b/libstdc++-v3/include/std/bitset @@ -1393,4 +1393,8 @@ _GLIBCXX_END_NESTED_NAMESPACE # include <debug/bitset> #endif +#ifdef _GLIBCXX_PROFILE +# include <profile/bitset> +#endif + #endif /* _GLIBCXX_BITSET */ diff --git a/libstdc++-v3/include/std/deque b/libstdc++-v3/include/std/deque index 8f64b005ccf..f8a55f72165 100644 --- a/libstdc++-v3/include/std/deque +++ b/libstdc++-v3/include/std/deque @@ -72,4 +72,8 @@ # include <debug/deque> #endif +#ifdef _GLIBCXX_PROFILE +# include <profile/deque> +#endif + #endif /* _GLIBCXX_DEQUE */ diff --git a/libstdc++-v3/include/std/list b/libstdc++-v3/include/std/list index d199802d736..fcf164b4bd5 100644 --- a/libstdc++-v3/include/std/list +++ b/libstdc++-v3/include/std/list @@ -70,5 +70,9 @@ # include <debug/list> #endif +#ifdef _GLIBCXX_PROFILE +# include <profile/list> +#endif + #endif /* _GLIBCXX_LIST */ diff --git a/libstdc++-v3/include/std/map b/libstdc++-v3/include/std/map index 159bfb3d040..25f86df6976 100644 --- a/libstdc++-v3/include/std/map +++ b/libstdc++-v3/include/std/map @@ -65,4 +65,8 @@ # include <debug/map> #endif +#ifdef _GLIBCXX_PROFILE +# include <profile/map> +#endif + #endif /* _GLIBCXX_MAP */ diff --git a/libstdc++-v3/include/std/set b/libstdc++-v3/include/std/set index 21e3f5a8a1e..0b7805cabec 100644 --- a/libstdc++-v3/include/std/set +++ b/libstdc++-v3/include/std/set @@ -65,4 +65,8 @@ # include <debug/set> #endif +#ifdef _GLIBCXX_PROFILE +# include <profile/set> +#endif + #endif /* _GLIBCXX_SET */ diff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map index 56906d28b5f..f8cd5459787 100644 --- a/libstdc++-v3/include/std/unordered_map +++ b/libstdc++-v3/include/std/unordered_map @@ -53,7 +53,7 @@ # include <tr1_impl/unordered_map> #else # define _GLIBCXX_INCLUDE_AS_CXX0X -#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL) +#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL) || defined(_GLIBCXX_PROFILE) # define _GLIBCXX_BEGIN_NAMESPACE_TR1 namespace _GLIBCXX_STD_D { # define _GLIBCXX_END_NAMESPACE_TR1 } # define _GLIBCXX_TR1 _GLIBCXX_STD_D @@ -73,6 +73,10 @@ # include <debug/unordered_map> #endif +#ifdef _GLIBCXX_PROFILE +# include <profile/unordered_map> +#endif + #endif // __GXX_EXPERIMENTAL_CXX0X__ #endif // _GLIBCXX_UNORDERED_MAP diff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set index 880f3bef4ec..b5b4f108980 100644 --- a/libstdc++-v3/include/std/unordered_set +++ b/libstdc++-v3/include/std/unordered_set @@ -53,7 +53,7 @@ # include <tr1_impl/unordered_set> #else # define _GLIBCXX_INCLUDE_AS_CXX0X -#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL) +#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL) || defined(_GLIBCXX_PROFILE) # define _GLIBCXX_BEGIN_NAMESPACE_TR1 namespace _GLIBCXX_STD_D { # define _GLIBCXX_END_NAMESPACE_TR1 } # define _GLIBCXX_TR1 _GLIBCXX_STD_D @@ -73,6 +73,9 @@ # include <debug/unordered_set> #endif +#ifdef _GLIBCXX_PROFILE +# include <profile/unordered_set> +#endif #endif // __GXX_EXPERIMENTAL_CXX0X__ #endif // _GLIBCXX_UNORDERED_SET diff --git a/libstdc++-v3/include/std/vector b/libstdc++-v3/include/std/vector index 114665b6c96..41ecdde6c7b 100644 --- a/libstdc++-v3/include/std/vector +++ b/libstdc++-v3/include/std/vector @@ -34,7 +34,7 @@ * 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. + ded "as is" without express or implied warranty. * * * Copyright (c) 1996 @@ -73,5 +73,9 @@ # include <debug/vector> #endif +#ifdef _GLIBCXX_PROFILE +# include <profile/vector> +#endif + #endif /* _GLIBCXX_VECTOR */ diff --git a/libstdc++-v3/include/tr1_impl/hashtable b/libstdc++-v3/include/tr1_impl/hashtable index bce550ff1f1..c4776982334 100644 --- a/libstdc++-v3/include/tr1_impl/hashtable +++ b/libstdc++-v3/include/tr1_impl/hashtable @@ -409,6 +409,9 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1 _M_erase_node(_Node*, _Node**); public: + // Expose insert_return_type for profiling mode. + typedef _Insert_Return_Type insert_return_type; + // Insert and erase _Insert_Return_Type insert(const value_type& __v) diff --git a/libstdc++-v3/testsuite/23_containers/deque/capacity/moveable.cc b/libstdc++-v3/testsuite/23_containers/deque/capacity/moveable.cc index 88ea5098f8e..089b10b83a6 100644 --- a/libstdc++-v3/testsuite/23_containers/deque/capacity/moveable.cc +++ b/libstdc++-v3/testsuite/23_containers/deque/capacity/moveable.cc @@ -38,26 +38,26 @@ test01() a.resize(98); a.resize(99); a.resize(100); -#ifndef _GLIBCXX_DEBUG +#if ! defined _GLIBCXX_DEBUG && ! defined _GLIBCXX_PROFILE VERIFY( copycounter::copycount == 100 ); #else VERIFY( copycounter::copycount == 100 + 4 ); #endif a.resize(99); a.resize(0); -#ifndef _GLIBCXX_DEBUG +#if ! defined _GLIBCXX_DEBUG && ! defined _GLIBCXX_PROFILE VERIFY( copycounter::copycount == 100 ); #else VERIFY( copycounter::copycount == 100 + 6 ); #endif a.resize(100); -#ifndef _GLIBCXX_DEBUG +#if ! defined _GLIBCXX_DEBUG && ! defined _GLIBCXX_PROFILE VERIFY( copycounter::copycount == 200 ); #else VERIFY( copycounter::copycount == 200 + 7 ); #endif a.clear(); -#ifndef _GLIBCXX_DEBUG +#if ! defined _GLIBCXX_DEBUG && ! defined _GLIBCXX_PROFILE VERIFY( copycounter::copycount == 200 ); #else VERIFY( copycounter::copycount == 200 + 7 ); diff --git a/libstdc++-v3/testsuite/23_containers/list/capacity/29134.cc b/libstdc++-v3/testsuite/23_containers/list/capacity/29134.cc index 48394079750..d51fc3bb662 100644 --- a/libstdc++-v3/testsuite/23_containers/list/capacity/29134.cc +++ b/libstdc++-v3/testsuite/23_containers/list/capacity/29134.cc @@ -28,7 +28,7 @@ void test01() typedef std::list<int> list_type; list_type l; -#ifndef _GLIBCXX_DEBUG +#if ! defined _GLIBCXX_DEBUG && ! defined _GLIBCXX_PROFILE using std::_List_node; #else using std::_GLIBCXX_STD_D::_List_node; diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/profile/hash_map.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/profile/hash_map.cc new file mode 100644 index 00000000000..7939a35e3ef --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/profile/hash_map.cc @@ -0,0 +1,22 @@ +// { dg-options "-Wno-deprecated" } +/* testing the gcc instrumented */ + +#include <ext/hash_map> +using namespace std; +using __gnu_cxx::hash_map; + +int main() +{ + hash_map <int, int> *tmp; + + for (int j=1; j<=10; j++) + { + tmp = new hash_map<int, int>; + // Insert more than default item + for (int i=0; i<10000*j; i++) { + (*tmp)[i]= i; + } + delete tmp; + } +} + diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/profile/unordered.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/profile/unordered.cc new file mode 100644 index 00000000000..93b506e9832 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/profile/unordered.cc @@ -0,0 +1,47 @@ +// { dg-options "-std=gnu++0x" } +/* testing the gcc instrumented */ + +#include <unordered_map> +#include <unordered_set> +using std::unordered_map; +using std::unordered_set; + +void test_unordered_set() +{ + // Test for unordered set + unordered_set <int> *tmp2; + tmp2 = new unordered_set<int>; + tmp2->insert(1); + delete tmp2; +} +void test_unordered_map() +{ + unordered_map <int, int> *tmp; + for (int i=0; i<20; i++) + { + tmp = new unordered_map<int, int>(i+2); + // Insert more than default item + for (int j=0; j<10000; j++) { + (*tmp)[j]= j; + } + + delete tmp; + } + + tmp = new unordered_map<int, int>; + + // Insert more than default item + for (int i=0; i<150000; i++) { +// (*tmp)[i] = i; + (*tmp).insert(unordered_map<int, int>::value_type(i, i)); + } + + (*tmp).erase(1); + delete tmp; +} +int main() +{ + test_unordered_set(); + test_unordered_map(); +} + diff --git a/libstdc++-v3/testsuite/23_containers/vector/profile/vector.cc b/libstdc++-v3/testsuite/23_containers/vector/profile/vector.cc new file mode 100644 index 00000000000..1e9d01afec5 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/profile/vector.cc @@ -0,0 +1,18 @@ +// Test vector: performance difference 25% (0.444s vs 0.539s) +// Advice: set tmp as 10000 + +#include <vector> + +using std::vector; + +int main() +{ + vector <int> tmp; + + for (int j=0; j<2000; j++) + // Insert more than default item + for (int i=0; i<10000; i++) { + tmp.push_back(i); + } +} + diff --git a/libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc b/libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc index 407f6ed390b..47fdf8fcafa 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/resize/moveable.cc @@ -41,26 +41,26 @@ test01() a.resize(98); a.resize(99); a.resize(100); -#ifndef _GLIBCXX_DEBUG +#if !defined(_GLIBCXX_DEBUG) && !defined(_GLIBCXX_PROFILE) VERIFY( copycounter::copycount == 100 + 1 ); #else VERIFY( copycounter::copycount == 100 + 1 + 4 ); #endif a.resize(99); a.resize(0); -#ifndef _GLIBCXX_DEBUG +#if !defined(_GLIBCXX_DEBUG) && !defined(_GLIBCXX_PROFILE) VERIFY( copycounter::copycount == 100 + 1 ); #else VERIFY( copycounter::copycount == 100 + 1 + 6 ); #endif a.resize(100); -#ifndef _GLIBCXX_DEBUG +#if !defined(_GLIBCXX_DEBUG) && !defined(_GLIBCXX_PROFILE) VERIFY( copycounter::copycount == 200 + 2 ); #else VERIFY( copycounter::copycount == 200 + 2 + 7 ); #endif a.clear(); -#ifndef _GLIBCXX_DEBUG +#if !defined(_GLIBCXX_DEBUG) && !defined(_GLIBCXX_PROFILE) VERIFY( copycounter::copycount == 200 + 2 ); #else VERIFY( copycounter::copycount == 200 + 2 + 7 ); diff --git a/libstdc++-v3/testsuite/Makefile.am b/libstdc++-v3/testsuite/Makefile.am index 73c913b869a..c8176072326 100644 --- a/libstdc++-v3/testsuite/Makefile.am +++ b/libstdc++-v3/testsuite/Makefile.am @@ -196,6 +196,9 @@ libgomp_flags=-B${glibcxx_builddir}/../libgomp \ atomic_flags=$(ATOMIC_FLAGS) parallel_flags="unix/-D_GLIBCXX_PARALLEL/-fopenmp" +# Runs the testsuite in profile mode. +profile_flags = "unix/-D_GLIBCXX_PROFILE" + check-parallel: site.exp -@(if test ! -d $${libgomp_dir}; then \ echo "Testing parallel mode failed as libgomp not present."; \ @@ -214,8 +217,17 @@ check-performance-parallel: testsuite_files_performance ${performance_script} CXXFLAGS="-D_GLIBCXX_PARALLEL -fopenmp $(atomic_flags) $(libgomp_flags)"; export CXXFLAGS; \ ${check_performance_script} ${glibcxx_srcdir} ${glibcxx_builddir}) +check-profile: site.exp + -@(outputdir=profile; export outputdir; \ + if test ! -d $${outputdir}; then \ + mkdir $${outputdir}; \ + fi; \ + srcdir=`$(am__cd) $(srcdir) && pwd`; export srcdir; \ + EXPECT=$(EXPECT); export EXPECT; \ + $(MAKE) CXXFLAGS="$(atomic_flags) " RUNTESTFLAGS="$(RUNTESTFLAGS) conformance.exp --outdir $${outputdir} --objdir $${outputdir} --target_board=$(profile_flags)" check-DEJAGNU; ) + .PHONY: baseline_symbols new-abi-baseline \ - check-abi check-compile check-performance check-parallel + check-abi check-compile check-performance check-parallel check-profile # By adding these files here, automake will remove them for 'make clean' CLEANFILES = *.txt *.tst *.exe core* filebuf_* tmp* ostream_* *.log *.sum \ @@ -224,4 +236,4 @@ CLEANFILES = *.txt *.tst *.exe core* filebuf_* tmp* ostream_* *.log *.sum \ # To remove directories. clean-local: - rm -rf parallel + rm -rf parallel profile diff --git a/libstdc++-v3/testsuite/Makefile.in b/libstdc++-v3/testsuite/Makefile.in index 6ee34ae9400..da2a59ad8bc 100644 --- a/libstdc++-v3/testsuite/Makefile.in +++ b/libstdc++-v3/testsuite/Makefile.in @@ -299,6 +299,9 @@ libgomp_flags = -B${glibcxx_builddir}/../libgomp \ atomic_flags = $(ATOMIC_FLAGS) parallel_flags = "unix/-D_GLIBCXX_PARALLEL/-fopenmp" +# Runs the testsuite in profile +profile_flags = "unix/-D_GLIBCXX_PROFILE" + # By adding these files here, automake will remove them for 'make clean' CLEANFILES = *.txt *.tst *.exe core* filebuf_* tmp* ostream_* *.log *.sum \ testsuite_* site.exp abi_check baseline_symbols *TEST* *.dat \ @@ -642,12 +645,21 @@ check-performance-parallel: testsuite_files_performance ${performance_script} CXXFLAGS="-D_GLIBCXX_PARALLEL -fopenmp $(atomic_flags) $(libgomp_flags)"; export CXXFLAGS; \ ${check_performance_script} ${glibcxx_srcdir} ${glibcxx_builddir}) +check-profile: site.exp + -@(outputdir=profile; export outputdir; \ + if test ! -d $${outputdir}; then \ + mkdir $${outputdir}; \ + fi; \ + srcdir=`$(am__cd) $(srcdir) && pwd`; export srcdir; \ + EXPECT=$(EXPECT); export EXPECT; \ + $(MAKE) CXXFLAGS="$(atomic_flags)" RUNTESTFLAGS="$(RUNTESTFLAGS) conformance.exp --outdir $${outputdir} --objdir $${outputdir} --target_board=$(profile_flags)" check-DEJAGNU; ) + .PHONY: baseline_symbols new-abi-baseline \ - check-abi check-compile check-performance check-parallel + check-abi check-compile check-performance check-parallel check-profile # To remove directories. clean-local: - rm -rf parallel + rm -rf parallel profile # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/libstdc++-v3/testsuite/ext/profile/all.cc b/libstdc++-v3/testsuite/ext/profile/all.cc new file mode 100644 index 00000000000..0a1f9796208 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/profile/all.cc @@ -0,0 +1,50 @@ +// { dg-options "-std=gnu++0x -O0 -D_GLIBCXX_PROFILE" } +// { dg-do compile } + +// -*- C++ -*- + +// Copyright (C) 2006, 2007, 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. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <map> +#include <vector> +#include <unordered_map> + +using std::map; +using std::vector; +using std::unordered_map; + +struct dumb_hash { + size_t operator()(int x) const {return 0;} + size_t operator()(int x, int y) const {return x == y;} +}; + +int main() { + map<int, int> m_to_umap; + vector<int> v_to_list; + unordered_map<int, int> um_too_small; + unordered_map<int, int> um_too_large(1000000); + unordered_map<int, int, dumb_hash, dumb_hash> um_dumb_hash; + + for (int i = 0; i < 10000; ++i) { + m_to_umap[i] = i; + v_to_list.insert(v_to_list.begin(), i); + um_too_small[i] = i; + um_too_small[i] = i; + um_dumb_hash[i] = i; + } +} diff --git a/libstdc++-v3/testsuite/ext/profile/mh.cc b/libstdc++-v3/testsuite/ext/profile/mh.cc new file mode 100644 index 00000000000..dc910949867 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/profile/mh.cc @@ -0,0 +1,65 @@ +// -*- C++ -*- + +// Copyright (C) 2006, 2007, 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. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-D_GLIBCXX_PROFILE" } +// { dg-do compile } + +#include <stdio.h> +#include <malloc.h> +#include <vector> + +using std::vector; + +static void my_init_hook (void); +static void *my_malloc_hook (size_t, const void *); +typedef void* (*malloc_hook) (size_t, const void *); + +malloc_hook old_malloc_hook; + +void (*__malloc_initialize_hook) (void) = my_init_hook; + +static void +my_init_hook (void) +{ + old_malloc_hook = __malloc_hook; + __malloc_hook = my_malloc_hook; +} + +static void * +my_malloc_hook (size_t size, const void *caller) +{ + void *result; + __malloc_hook = old_malloc_hook; + result = malloc (size); + old_malloc_hook = __malloc_hook; + + // With _GLIBCXX_PROFILE, the instrumentation of the vector constructor + // will call back into malloc. + vector<int> v; + + __malloc_hook = my_malloc_hook; + return result; +} + + +int main() { + int* test = (int*) malloc(sizeof(int)); + *test = 1; + return *test; +} diff --git a/libstdc++-v3/testsuite/ext/profile/mutex_extensions.cc b/libstdc++-v3/testsuite/ext/profile/mutex_extensions.cc new file mode 100644 index 00000000000..c8bcf720e1d --- /dev/null +++ b/libstdc++-v3/testsuite/ext/profile/mutex_extensions.cc @@ -0,0 +1,26 @@ +// { dg-options "-D_GLIBCXX_DEBUG -D_GLIBCXX_PROFILE" } +// { dg-do compile } + +// -*- C++ -*- + +// Copyright (C) 2006, 2007, 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. +// +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include <vector> + +// { dg-error "Cannot use -D_GLIBCXX_PROFILE with " "" { target *-*-* } 166 } +// { dg-excess-errors "In file included from" } |