Commit a1360f57 by Silvius Rus Committed by Silvius Rus

libstdc++ profile mode bug fixes and minor updates

From-SVN: r155786
parent 9b2adcdb
2010-01-10 Silvius Rus <rus@google.com>
* configure.ac: Add detection of execinfo.h.
* configure: Same.
* config.h.in: Same.
* doc/xml/manual/profile_mode.xml: Add list_to_slist manual.
Also, correct user interface mistakes.
* include/Makefile.in: Add references to new include files.
* include/Makefile.am: Add references to new include files.
* include/backward/hash_map: Remove profile include.
* include/backward/hash_set: Remove profile include.
* include/profile/hashtable.h: Delete file.
* include/profile/iterator_tracker.h: New file.
* include/profile/vector: Add instrumentation for tracked iterator.
* include/profile/list: Same.
* include/profile/impl/profiler_list_to_slist.h: New file.
* include/profile/impl/profiler_list_to_vector.h: Same.
* include/profile/impl/profiler.h: Add list_to_slist and
list_to_vector instrumentation hook interfaces. Fixed broken
diagnostic disabling mechanism.
(_GLIBCXX_PROFILE_DEFINE_DATA,_GLIBCXX_PROFILE_DATA) New macros.
(__reentrance_guard) Fix bug.
* include/profile/impl/profiler_trace.h: Replace dummy templates
with _GLIBCXX_PROFILE_DEFINE_DATA.
* include/profile/impl/profiler_container_size.h: Same.
* include/profile/impl/profiler_vector_size.h: Same.
* include/profile/impl/profiler_hash_func.h: Same.
* include/profile/impl/profiler_vector_to_list.h: Same.
* include/profile/impl/profiler_map_to_unordered_map.h: Same.
* include/profile/impl/profiler_hashtable_size.h: Same.
* include/profile/impl/profiler_node.h: Same.
* include/profile/impl/profiler_state.h: Same. Also, remove
class __state. Also, use __sync_val_compare_and_swap to set state.
2010-01-09 H.J. Lu <hongjiu.lu@intel.com> 2010-01-09 H.J. Lu <hongjiu.lu@intel.com>
PR other/42230 PR other/42230
......
...@@ -66,6 +66,9 @@ ...@@ -66,6 +66,9 @@
/* Define to 1 if you have the <endian.h> header file. */ /* Define to 1 if you have the <endian.h> header file. */
#undef HAVE_ENDIAN_H #undef HAVE_ENDIAN_H
/* Define to 1 if you have the <execinfo.h> header file. */
#undef HAVE_EXECINFO_H
/* Define if ENODATA exists. */ /* Define if ENODATA exists. */
#undef HAVE_ENODATA #undef HAVE_ENODATA
......
...@@ -19449,8 +19449,8 @@ fi ...@@ -19449,8 +19449,8 @@ fi
# Check for available headers. # Check for available headers.
for ac_header in endian.h float.h fp.h ieeefp.h inttypes.h locale.h \ for ac_header in endian.h execinfo.h float.h fp.h ieeefp.h inttypes.h \
machine/endian.h machine/param.h nan.h stdint.h stdlib.h string.h \ locale.h machine/endian.h machine/param.h nan.h stdint.h stdlib.h string.h \
strings.h sys/ipc.h sys/isa_defs.h sys/machine.h sys/param.h \ strings.h sys/ipc.h sys/isa_defs.h sys/machine.h sys/param.h \
sys/resource.h sys/sem.h sys/stat.h sys/time.h sys/types.h unistd.h \ sys/resource.h sys/sem.h sys/stat.h sys/time.h sys/types.h unistd.h \
wchar.h wctype.h wchar.h wctype.h
...@@ -165,8 +165,8 @@ GLIBCXX_CHECK_GTHREADS ...@@ -165,8 +165,8 @@ GLIBCXX_CHECK_GTHREADS
AC_LC_MESSAGES AC_LC_MESSAGES
# Check for available headers. # Check for available headers.
AC_CHECK_HEADERS([endian.h float.h fp.h ieeefp.h inttypes.h locale.h \ AC_CHECK_HEADERS([endian.h execinfo.h float.h fp.h ieeefp.h inttypes.h \
machine/endian.h machine/param.h nan.h stdint.h stdlib.h string.h \ locale.h machine/endian.h machine/param.h nan.h stdint.h stdlib.h string.h \
strings.h sys/ipc.h sys/isa_defs.h sys/machine.h sys/param.h \ strings.h sys/ipc.h sys/isa_defs.h sys/machine.h sys/param.h \
sys/resource.h sys/sem.h sys/stat.h sys/time.h sys/types.h unistd.h \ sys/resource.h sys/sem.h sys/stat.h sys/time.h sys/types.h unistd.h \
wchar.h wctype.h]) wchar.h wctype.h])
......
...@@ -134,7 +134,7 @@ vector-size: improvement = 3: call stack = 0x804842c ... ...@@ -134,7 +134,7 @@ vector-size: improvement = 3: call stack = 0x804842c ...
</itemizedlist> </itemizedlist>
</para> </para>
<para>Two files are generated. <code>libstdcxx-profile.txt</code> <para>Three files are generated. <code>libstdcxx-profile.txt</code>
contains human readable advice. <code>libstdcxx-profile.raw</code> contains human readable advice. <code>libstdcxx-profile.raw</code>
contains implementation specific data about each diagnostic. contains implementation specific data about each diagnostic.
Their format is not documented. They are sufficient to generate Their format is not documented. They are sufficient to generate
...@@ -142,6 +142,9 @@ vector-size: improvement = 3: call stack = 0x804842c ... ...@@ -142,6 +142,9 @@ vector-size: improvement = 3: call stack = 0x804842c ...
of keeping this raw format is that traces from multiple executions can of keeping this raw format is that traces from multiple executions can
be aggregated simply by concatenating the raw traces. We intend to be aggregated simply by concatenating the raw traces. We intend to
offer an external utility program that can issue advice from a trace. offer an external utility program that can issue advice from a trace.
<code>libstdcxx-profile.conf.out</code> lists the actual diagnostic
parameters used. To alter parameters, edit this file and rename it to
<code>libstdcxx-profile.conf</code>.
</para> </para>
<para>Advice is given regardless whether the transformation is valid. <para>Advice is given regardless whether the transformation is valid.
...@@ -163,19 +166,19 @@ vector-size: improvement = 3: call stack = 0x804842c ... ...@@ -163,19 +166,19 @@ vector-size: improvement = 3: call stack = 0x804842c ...
in the environment where the program is run, before starting execution. in the environment where the program is run, before starting execution.
<itemizedlist> <itemizedlist>
<listitem><para> <listitem><para>
<code>[NO]_GLIBCXX_PROFILE_&lt;diagnostic&gt;</code>: <code>_GLIBCXX_PROFILE_NO_&lt;diagnostic&gt;</code>:
enable/disable specific diagnostics. disable specific diagnostics.
See section Diagnostics for possible values. See section Diagnostics for possible values.
(Environment variables not supported.) (Environment variables not supported.)
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
<code>GLIBCXX_PROFILE_TRACE_PATH_ROOT</code>: set an alternative root <code>_GLIBCXX_PROFILE_TRACE_PATH_ROOT</code>: set an alternative root
path for the output files. path for the output files.
</para></listitem> </para></listitem>
<listitem><para>GLIBCXX_PROFILE_MAX_WARN_COUNT: set it to the maximum <listitem><para>_GLIBCXX_PROFILE_MAX_WARN_COUNT: set it to the maximum
number of warnings desired. The default value is 10.</para></listitem> number of warnings desired. The default value is 10.</para></listitem>
<listitem><para> <listitem><para>
<code>GLIBCXX_PROFILE_MAX_STACK_DEPTH</code>: if set to 0, <code>_GLIBCXX_PROFILE_MAX_STACK_DEPTH</code>: if set to 0,
the advice will the advice will
be collected and reported for the program as a whole, and not for each be collected and reported for the program as a whole, and not for each
call context. call context.
...@@ -184,7 +187,7 @@ vector-size: improvement = 3: call stack = 0x804842c ... ...@@ -184,7 +187,7 @@ vector-size: improvement = 3: call stack = 0x804842c ...
The default value is 32. The default value is 32.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
<code>GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC</code>: <code>_GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC</code>:
set a limit on how much memory to use for the accounting tables for each 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 diagnostic type. When this limit is reached, new events are ignored
until the memory usage decreases under the limit. Generally, this means until the memory usage decreases under the limit. Generally, this means
...@@ -192,16 +195,16 @@ vector-size: improvement = 3: call stack = 0x804842c ... ...@@ -192,16 +195,16 @@ vector-size: improvement = 3: call stack = 0x804842c ...
live containers are deleted. The default is 128 MB. live containers are deleted. The default is 128 MB.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
<code>GLIBCXX_PROFILE_NOTHREADS</code>: <code>_GLIBCXX_PROFILE_NO_THREADS</code>:
Make the library not use threads. Otherwise, pthread mutexes are used Make the library not use threads. If thread local storage (TLS) is not
to protect access to internal data structures. This should be useful available, you will get a preprocessor error asking you to set
only if the program is single threaded and you want to avoid the overhead -D_GLIBCXX_PROFILE_NO_THREADS if your program is single-threaded.
of aquiring/releasing locks unnecessarily. Multithreded execution without TLS is not supported.
(Environment variable not supported.) (Environment variable not supported.)
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
<code>HAVE_EXECINFO_H</code>: <code>_GLIBCXX_HAVE_EXECINFO_H</code>:
This name should be defined at library configuration time. This name should be defined automatically at library configuration time.
If your library was configured without <code>execinfo.h</code>, but If your library was configured without <code>execinfo.h</code>, but
you have it in your include path, you can define it explicitly. Without 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 it, advice is collected for the program as a whole, and not for each
...@@ -1320,6 +1323,52 @@ memory references. ...@@ -1320,6 +1323,52 @@ memory references.
</itemizedlist> </itemizedlist>
</sect3> </sect3>
<sect3 id="manual.ext.profile_mode.analysis.list_to_slist"
xreflabel="List to Forward List">
<title>List to Forward List (Slist)</title>
<itemizedlist>
<listitem><para><emphasis>Switch:</emphasis>
<code>_GLIBCXX_PROFILE_LIST_TO_SLIST</code>.
</para></listitem>
<listitem><para><emphasis>Goal:</emphasis> Detect cases where
<code>list</code> could be substituted with <code>forward_list</code> for
better performance.
</para></listitem>
<listitem><para><emphasis>Fundamentals:</emphasis>
The memory footprint of a forward_list is smaller than that of a list.
This has beneficial effects on memory subsystem, e.g., fewer cache misses.
</para></listitem>
<listitem><para><emphasis>Sample runtime reduction:</emphasis>40%.
Note that the reduction is only noticeable if the size of the forward_list
node is in fact larger than that of the list node. For memory allocators
with size classes, you will only notice an effect when the two node sizes
belong to different allocator size classes.
</para></listitem>
<listitem><para><emphasis>Recommendation:</emphasis>Replace list with
forward_list at site S.</para></listitem>
<listitem><para><emphasis>To instrument:</emphasis><code>list</code>
operations and iteration methods.</para></listitem>
<listitem><para><emphasis>Analysis:</emphasis>
Issue the advice if there are no <code>backwards</code> traversals
or insertion before a given node.
</para></listitem>
<listitem><para><emphasis>Cost model:</emphasis>
Always true.</para></listitem>
<listitem><para><emphasis>Example:</emphasis>
<programlisting>
1 list&lt;int&gt; l;
...
2 int sum = 0;
3 for (list&lt;int&gt;::iterator it = l.begin(); it != l.end(); ++it) {
4 sum += *it;
5 }
foo.cc:1: advice: Change "list" to "forward_list".
</programlisting>
</para></listitem>
</itemizedlist>
</sect3>
<sect3 id="manual.ext.profile_mode.analysis.assoc_ord_to_unord" <sect3 id="manual.ext.profile_mode.analysis.assoc_ord_to_unord"
xreflabel="Ordered to Unordered Associative Container"> xreflabel="Ordered to Unordered Associative Container">
<title>Ordered to Unordered Associative Container</title> <title>Ordered to Unordered Associative Container</title>
......
...@@ -793,7 +793,7 @@ profile_headers = \ ...@@ -793,7 +793,7 @@ profile_headers = \
${profile_srcdir}/multiset.h \ ${profile_srcdir}/multiset.h \
${profile_srcdir}/set \ ${profile_srcdir}/set \
${profile_srcdir}/set.h \ ${profile_srcdir}/set.h \
${profile_srcdir}/hashtable.h ${profile_srcdir}/iterator_tracker.h
profile_impl_srcdir = ${glibcxx_srcdir}/include/profile/impl profile_impl_srcdir = ${glibcxx_srcdir}/include/profile/impl
profile_impl_builddir = ./profile/impl profile_impl_builddir = ./profile/impl
profile_impl_headers = \ profile_impl_headers = \
...@@ -806,7 +806,9 @@ profile_impl_headers = \ ...@@ -806,7 +806,9 @@ profile_impl_headers = \
${profile_impl_srcdir}/profiler_state.h \ ${profile_impl_srcdir}/profiler_state.h \
${profile_impl_srcdir}/profiler_trace.h \ ${profile_impl_srcdir}/profiler_trace.h \
${profile_impl_srcdir}/profiler_vector_size.h \ ${profile_impl_srcdir}/profiler_vector_size.h \
${profile_impl_srcdir}/profiler_vector_to_list.h ${profile_impl_srcdir}/profiler_vector_to_list.h \
${profile_impl_srcdir}/profiler_list_to_vector.h \
${profile_impl_srcdir}/profiler_list_to_slist.h
# Some of the different "C" header models need extra files. # Some of the different "C" header models need extra files.
# Some "C" header schemes require the "C" compatibility headers. # Some "C" header schemes require the "C" compatibility headers.
......
...@@ -1026,7 +1026,7 @@ profile_headers = \ ...@@ -1026,7 +1026,7 @@ profile_headers = \
${profile_srcdir}/multiset.h \ ${profile_srcdir}/multiset.h \
${profile_srcdir}/set \ ${profile_srcdir}/set \
${profile_srcdir}/set.h \ ${profile_srcdir}/set.h \
${profile_srcdir}/hashtable.h ${profile_srcdir}/iterator_tracker.h
profile_impl_srcdir = ${glibcxx_srcdir}/include/profile/impl profile_impl_srcdir = ${glibcxx_srcdir}/include/profile/impl
profile_impl_builddir = ./profile/impl profile_impl_builddir = ./profile/impl
...@@ -1040,7 +1040,9 @@ profile_impl_headers = \ ...@@ -1040,7 +1040,9 @@ profile_impl_headers = \
${profile_impl_srcdir}/profiler_state.h \ ${profile_impl_srcdir}/profiler_state.h \
${profile_impl_srcdir}/profiler_trace.h \ ${profile_impl_srcdir}/profiler_trace.h \
${profile_impl_srcdir}/profiler_vector_size.h \ ${profile_impl_srcdir}/profiler_vector_size.h \
${profile_impl_srcdir}/profiler_vector_to_list.h ${profile_impl_srcdir}/profiler_vector_to_list.h \
${profile_impl_srcdir}/profiler_list_to_vector.h \
${profile_impl_srcdir}/profiler_list_to_slist.h
@GLIBCXX_C_HEADERS_EXTRA_FALSE@c_base_headers_extra = @GLIBCXX_C_HEADERS_EXTRA_FALSE@c_base_headers_extra =
......
...@@ -58,11 +58,7 @@ ...@@ -58,11 +58,7 @@
#include "backward_warning.h" #include "backward_warning.h"
#include <bits/c++config.h> #include <bits/c++config.h>
#ifdef _GLIBCXX_PROFILE
#include <profile/hashtable.h>
#else
#include <backward/hashtable.h> #include <backward/hashtable.h>
#endif
#include <bits/concept_check.h> #include <bits/concept_check.h>
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
......
...@@ -58,11 +58,7 @@ ...@@ -58,11 +58,7 @@
#include "backward_warning.h" #include "backward_warning.h"
#include <bits/c++config.h> #include <bits/c++config.h>
#ifdef _GLIBCXX_PROFILE
#include <profile/hashtable.h>
#else
#include <backward/hashtable.h> #include <backward/hashtable.h>
#endif
#include <bits/concept_check.h> #include <bits/concept_check.h>
_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
......
...@@ -52,143 +52,134 @@ ...@@ -52,143 +52,134 @@
namespace __gnu_profile namespace __gnu_profile
{ {
/** @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 /** @brief A hash performance instrumentation line in the object table. */
__hashfunc_info::__merge(const __hashfunc_info& __o) class __hashfunc_info: public __object_info_base
{ {
_M_longest_chain = __max(_M_longest_chain, __o._M_longest_chain); public:
_M_accesses += __o._M_accesses; __hashfunc_info()
_M_hops += __o._M_hops; :_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 strdup("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 inline void __hashfunc_info::__merge(const __hashfunc_info& __o)
__hashfunc_info::__destruct(size_t __chain, size_t __accesses, size_t __hops) {
{ _M_longest_chain = __max(_M_longest_chain, __o._M_longest_chain);
_M_longest_chain = __max(_M_longest_chain, __chain); _M_accesses += __o._M_accesses;
_M_accesses += __accesses; _M_hops += __o._M_hops;
_M_hops += __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";
}
/** @brief A hash performance instrumentation line in the stack table. */ inline void __trace_hash_func::__insert(__object_t __obj, __stack_t __stack)
class __hashfunc_stack_info: public __hashfunc_info {
{ __add_object(__obj, __hashfunc_info(__stack));
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);
}
inline void __hashfunc_info::__write(FILE* __f) const
{
fprintf(__f, "%Zu %Zu %Zu\n", _M_hops, _M_accesses, _M_longest_chain);
}
// Initialization and report. inline void __trace_hash_func::__destruct(const void* __obj, size_t __chain,
inline void size_t __accesses, size_t __hops)
__trace_hash_func_init() {
{ __tables<0>::_S_hash_func = new __trace_hash_func(); } if (!__is_on()) return;
inline void // First find the item from the live objects and update the informations.
__trace_hash_func_report(FILE* __f, __warning_vector_t& __warnings) __hashfunc_info* __objs = __get_object_info(__obj);
{ if (!__objs)
if (__tables<0>::_S_hash_func) return;
{
__tables<0>::_S_hash_func->__collect_warnings(__warnings);
__tables<0>::_S_hash_func->__write(__f);
}
}
__objs->__destruct(__chain, __accesses, __hops);
__retire_object(__obj);
}
// Implementations of instrumentation hooks. inline void __trace_hash_func_init()
inline void {
__trace_hash_func_construct(const void* __obj) _GLIBCXX_PROFILE_DATA(_S_hash_func) = new __trace_hash_func();
{ }
if (!__profcxx_init())
return;
__tables<0>::_S_hash_func->__insert(__obj, __get_stack()); inline void __trace_hash_func_report(FILE* __f,
__warning_vector_t& __warnings)
{
if (_GLIBCXX_PROFILE_DATA(_S_hash_func)) {
_GLIBCXX_PROFILE_DATA(_S_hash_func)->__collect_warnings(__warnings);
_GLIBCXX_PROFILE_DATA(_S_hash_func)->__write(__f);
} }
}
inline void inline void __trace_hash_func_construct(const void* __obj)
__trace_hash_func_destruct(const void* __obj, size_t __chain, {
size_t __accesses, size_t __hops) if (!__profcxx_init()) return;
{
if (!__profcxx_init())
return;
__tables<0>::_S_hash_func->__destruct(__obj, __chain, __accesses, __hops); _GLIBCXX_PROFILE_DATA(_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;
_GLIBCXX_PROFILE_DATA(_S_hash_func)->__destruct(__obj, __chain, __accesses,
__hops);
}
} // namespace __gnu_profile } // namespace __gnu_profile
#endif /* _GLIBCXX_PROFILE_PROFILER_HASH_FUNC_H */ #endif /* _GLIBCXX_PROFILE_PROFILER_HASH_FUNC_H */
...@@ -54,57 +54,54 @@ ...@@ -54,57 +54,54 @@
namespace __gnu_profile namespace __gnu_profile
{ {
/** @brief Hashtable size instrumentation trace producer. */
class __trace_hashtable_size : public __trace_container_size /** @brief Hashtable size instrumentation trace producer. */
{ class __trace_hashtable_size : public __trace_container_size
public: {
__trace_hashtable_size() : __trace_container_size() public:
{ __id = "hashtable-size"; } __trace_hashtable_size() : __trace_container_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) __id = "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_init()
inline void {
__trace_hashtable_size_construct(const void* __obj, size_t __num) _GLIBCXX_PROFILE_DATA(_S_hashtable_size) = new __trace_hashtable_size();
{ }
if (!__profcxx_init())
return;
__tables<0>::_S_hashtable_size->__insert(__obj, __get_stack(), __num); inline void __trace_hashtable_size_report(FILE* __f,
__warning_vector_t& __warnings)
{
if (_GLIBCXX_PROFILE_DATA(_S_hashtable_size)) {
_GLIBCXX_PROFILE_DATA(_S_hashtable_size)->__collect_warnings(__warnings);
_GLIBCXX_PROFILE_DATA(_S_hashtable_size)->__write(__f);
} }
}
inline void inline void __trace_hashtable_size_construct(const void* __obj, size_t __num)
__trace_hashtable_size_destruct(const void* __obj, size_t __num, {
size_t __inum) if (!__profcxx_init()) return;
{
if (!__profcxx_init()) _GLIBCXX_PROFILE_DATA(_S_hashtable_size)->__insert(__obj, __get_stack(),
return; __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); _GLIBCXX_PROFILE_DATA(_S_hashtable_size)->__destruct(__obj, __num, __inum);
} }
inline void inline void __trace_hashtable_size_resize(const void* __obj, size_t __from,
__trace_hashtable_size_resize(const void* __obj, size_t __from, size_t __to) size_t __to)
{ {
if (!__profcxx_init()) if (!__profcxx_init()) return;
return;
__tables<0>::_S_hashtable_size->__resize(__obj, __from, __to); _GLIBCXX_PROFILE_DATA(_S_hashtable_size)->__resize(__obj, __from, __to);
} }
} // namespace __gnu_profile } // namespace __gnu_profile
......
// -*- 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_list_to_slist.h
* @brief Diagnostics for list to slist.
*/
// Written by Changhee Jung.
#ifndef _GLIBCXX_PROFILE_PROFILER_LIST_TO_SLIST_H
#define _GLIBCXX_PROFILE_PROFILER_LIST_TO_SLIST_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 __gnu_profile
{
class __list2slist_info: public __object_info_base
{
public:
__list2slist_info() : _M_rewind(false), _M_operations(0) {}
__list2slist_info(__stack_t __stack)
: _M_rewind(false), _M_operations(0),__object_info_base(__stack) {}
virtual ~__list2slist_info() {}
__list2slist_info(const __list2slist_info& __o) : __object_info_base(__o)
{ _M_rewind = __o._M_rewind; _M_operations = __o._M_operations; }
// XXX: the magnitude should be multiplied with a constant factor F,
// where F is 1 when the malloc size class of list nodes is different
// from the malloc size class of slist nodes. When they fall into the same
// class, the only slist benefit is from having to set fewer links, so
// the factor F should be much smaller, closer to 0 than to 1.
// This could be implemented by passing the size classes in the config file.
// For now, we always assume F to be 1.
float __magnitude() const
{ if (!_M_rewind) return _M_operations; else return 0; }
void __merge(const __list2slist_info& __o) {};
void __write(FILE* __f) const;
const char* __advice() const
{ return strdup("change std::list to std::forward_list"); }
void __opr_rewind() { _M_rewind = true; _M_valid = false;}
void __record_operation() { _M_operations++; }
bool __has_rewind() { return _M_rewind; }
private:
bool _M_rewind;
size_t _M_operations;
};
class __list2slist_stack_info: public __list2slist_info {
public:
__list2slist_stack_info(const __list2slist_info& __o)
: __list2slist_info(__o) {}
};
class __trace_list_to_slist
: public __trace_base<__list2slist_info, __list2slist_stack_info>
{
public:
~__trace_list_to_slist() {}
__trace_list_to_slist()
: __trace_base<__list2slist_info, __list2slist_stack_info>()
{ __id = "list-to-slist"; }
void __opr_rewind(const void* __obj);
void __record_operation(const void* __obj);
void __insert(const __object_t __obj, __stack_t __stack)
{ __add_object(__obj, __list2slist_info(__stack)); }
void __destruct(const void* __obj);
};
inline void __list2slist_info::__write(FILE* __f) const
{
fprintf(__f, "%s\n", _M_rewind ? "invalid" : "valid");
}
inline void __trace_list_to_slist::__destruct(const void* __obj)
{
if (!__is_on())
return;
__list2slist_info* __res = __get_object_info(__obj);
if (!__res)
return;
__retire_object(__obj);
}
inline void __trace_list_to_slist_init()
{
_GLIBCXX_PROFILE_DATA(_S_list_to_slist) = new __trace_list_to_slist();
}
inline void __trace_list_to_slist_report(FILE* __f,
__warning_vector_t& __warnings)
{
if (_GLIBCXX_PROFILE_DATA(_S_list_to_slist)) {
_GLIBCXX_PROFILE_DATA(_S_list_to_slist)->__collect_warnings(__warnings);
_GLIBCXX_PROFILE_DATA(_S_list_to_slist)->__write(__f);
}
}
inline void __trace_list_to_slist::__opr_rewind(const void* __obj)
{
__list2slist_info* __res = __get_object_info(__obj);
if (__res)
__res->__opr_rewind();
}
inline void __trace_list_to_slist::__record_operation(const void* __obj)
{
__list2slist_info* __res = __get_object_info(__obj);
if (__res)
__res->__record_operation();
}
inline void __trace_list_to_slist_rewind(const void* __obj)
{
if (!__profcxx_init()) return;
_GLIBCXX_PROFILE_DATA(_S_list_to_slist)->__opr_rewind(__obj);
}
inline void __trace_list_to_slist_operation(const void* __obj)
{
if (!__profcxx_init()) return;
_GLIBCXX_PROFILE_DATA(_S_list_to_slist)->__record_operation(__obj);
}
inline void __trace_list_to_slist_construct(const void* __obj)
{
if (!__profcxx_init()) return;
_GLIBCXX_PROFILE_DATA(_S_list_to_slist)->__insert(__obj, __get_stack());
}
inline void __trace_list_to_slist_destruct(const void* __obj)
{
if (!__profcxx_init()) return;
_GLIBCXX_PROFILE_DATA(_S_list_to_slist)->__destruct(__obj);
}
} // namespace __gnu_profile
#endif /* _GLIBCXX_PROFILE_PROFILER_LIST_TO_SLIST_H */
...@@ -47,122 +47,126 @@ ...@@ -47,122 +47,126 @@
#include <string.h> #include <string.h>
#endif #endif
#include <vector> #include <vector>
#if defined HAVE_EXECINFO_H #if defined _GLIBCXX_HAVE_EXECINFO_H
#include <execinfo.h> #include <execinfo.h>
#endif #endif
namespace __gnu_profile namespace __gnu_profile
{ {
typedef const void* __object_t; typedef const void* __object_t;
typedef void* __instruction_address_t; typedef void* __instruction_address_t;
typedef std::_GLIBCXX_STD_PR::vector<__instruction_address_t> __stack_npt; typedef std::_GLIBCXX_STD_PR::vector<__instruction_address_t> __stack_npt;
typedef __stack_npt* __stack_t; typedef __stack_npt* __stack_t;
size_t __stack_max_depth(); size_t __stack_max_depth();
inline __stack_t __get_stack() inline __stack_t __get_stack()
{ {
#if defined HAVE_EXECINFO_H #if defined _GLIBCXX_HAVE_EXECINFO_H
size_t __max_depth = __stack_max_depth(); size_t __max_depth = __stack_max_depth();
if (__max_depth == 0) 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; 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 #endif
}
inline __size(const __stack_t& __stack)
{
if (!__stack) {
return 0;
} else {
return __stack->size();
} }
}
inline __size(const __stack_t& __stack) inline void __write(FILE* __f, const __stack_t __stack)
{ {
if (!__stack) if (!__stack) {
return 0; return;
else }
return __stack->size();
__stack_npt::const_iterator __it;
for (__it = __stack->begin(); __it != __stack->end(); ++__it) {
fprintf(__f, "%p ", *__it);
} }
}
inline void __write(FILE* __f, const __stack_t __stack) /** @brief Hash function for summary trace using call stack as index. */
class __stack_hash
{
public:
size_t operator()(const __stack_t __s) const
{ {
if (!__stack) if (!__s) {
return; return 0;
}
uintptr_t __index = 0;
__stack_npt::const_iterator __it; __stack_npt::const_iterator __it;
for (__it = __stack->begin(); __it != __stack->end(); ++__it) for (__it = __s->begin(); __it != __s->end(); ++__it) {
fprintf(__f, "%p ", *__it); __index += reinterpret_cast<uintptr_t>(*__it);
}
return __index;
} }
/** @brief Hash function for summary trace using call stack as index. */ bool operator() (const __stack_t __stack1, const __stack_t __stack2) const
class __stack_hash
{ {
public: if (!__stack1 && !__stack2) return true;
size_t operator()(const __stack_t __s) const if (!__stack1 || !__stack2) return false;
{ if (__stack1->size() != __stack2->size()) return false;
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 size_t __byte_size = __stack1->size() * sizeof(__stack_npt::value_type);
{ return memcmp(&(*__stack1)[0], &(*__stack2)[0], __byte_size) == 0;
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); /** @brief Base class for a line in the object table. */
return memcmp(&(*__stack1)[0], &(*__stack2)[0], __byte_size) == 0; 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;
}
/** @brief Base class for a line in the object table. */ inline __object_info_base::__object_info_base(const __object_info_base& __o)
class __object_info_base {
{ _M_stack = __o._M_stack;
public: _M_valid = __o._M_valid;
__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) /** @brief Base class for a line in the stack table. */
{ template<typename __object_info>
_M_stack = __o._M_stack; class __stack_info_base
_M_valid = __o._M_valid; {
} 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;
};
/** @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 __gnu_profile } // namespace __gnu_profile
#endif /* _GLIBCXX_PROFILE_PROFILER_NODE_H */ #endif /* _GLIBCXX_PROFILE_PROFILER_NODE_H */
...@@ -37,72 +37,34 @@ ...@@ -37,72 +37,34 @@
#ifndef _GLIBCXX_PROFILE_PROFILER_STATE_H #ifndef _GLIBCXX_PROFILE_PROFILER_STATE_H
#define _GLIBCXX_PROFILE_PROFILER_STATE_H 1 #define _GLIBCXX_PROFILE_PROFILER_STATE_H 1
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <cstdio>
#else
#include <stdio.h>
#endif
namespace __gnu_profile namespace __gnu_profile
{ {
/** @brief Profiling mode on/off state. */
template<int _Unused=0> enum __state_type { __ON, __OFF, __INVALID };
class __state
{ _GLIBCXX_PROFILE_DEFINE_DATA(__state_type, __state, __INVALID);
private:
enum __state_type { __ON, __OFF, __INVALID }; inline bool __turn(__state_type __s)
{
__state_type _M_state; return (_GLIBCXX_PROFILE_DATA(__state)
== __sync_val_compare_and_swap(&_GLIBCXX_PROFILE_DATA(__state),
public: __INVALID, __s));
static __state<_Unused>* _S_diag_state; }
__state() : _M_state(__INVALID) { } inline bool __turn_on()
~__state() { } { return __turn(__ON); }
bool __is_on() { return _M_state == __ON; } inline bool __turn_off()
bool __is_off() { return _M_state == __OFF; } { return __turn(__OFF); }
bool __is_invalid() { return _M_state == __INVALID; }
void __turn_on() { _M_state = __ON; } inline bool __is_on()
void __turn_off() { _M_state = __OFF; } { return _GLIBCXX_PROFILE_DATA(__state) == __ON; }
};
inline bool __is_off()
template<int _Unused> { return _GLIBCXX_PROFILE_DATA(__state) == __OFF; }
__state<_Unused>* __state<_Unused>::_S_diag_state = NULL;
inline bool __is_invalid()
inline bool { return _GLIBCXX_PROFILE_DATA(__state) == __INVALID; }
__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 __gnu_profile } // end namespace __gnu_profile
#endif /* _GLIBCXX_PROFILE_PROFILER_STATE_H */ #endif /* _GLIBCXX_PROFILE_PROFILER_STATE_H */
...@@ -54,49 +54,51 @@ ...@@ -54,49 +54,51 @@
namespace __gnu_profile namespace __gnu_profile
{ {
/** @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. /** @brief Hashtable size instrumentation trace producer. */
inline void class __trace_vector_size : public __trace_container_size
__trace_vector_size_construct(const void* __obj, size_t __num) {
{ public:
if (!__profcxx_init()) return; __trace_vector_size() : __trace_container_size() { __id = "vector-size"; }
__tables<0>::_S_vector_size->__insert(__obj, __get_stack(), __num); };
}
inline void inline void __trace_vector_size_init()
__trace_vector_size_destruct(const void* __obj, size_t __num, size_t __inum) {
{ _GLIBCXX_PROFILE_DATA(_S_vector_size) = new __trace_vector_size();
if (!__profcxx_init()) return; }
__tables<0>::_S_vector_size->__destruct(__obj, __num, __inum);
}
inline void inline void __trace_vector_size_report(FILE* __f,
__trace_vector_size_resize(const void* __obj, size_t __from, size_t __to) __warning_vector_t& __warnings)
{ {
if (!__profcxx_init()) return; if (_GLIBCXX_PROFILE_DATA(_S_vector_size)) {
__tables<0>::_S_vector_size->__resize(__obj, __from, __to); _GLIBCXX_PROFILE_DATA(_S_vector_size)->__collect_warnings(__warnings);
_GLIBCXX_PROFILE_DATA(_S_vector_size)->__write(__f);
} }
}
inline void __trace_vector_size_construct(const void* __obj, size_t __num)
{
if (!__profcxx_init()) return;
_GLIBCXX_PROFILE_DATA(_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;
_GLIBCXX_PROFILE_DATA(_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;
_GLIBCXX_PROFILE_DATA(_S_vector_size)->__resize(__obj, __from, __to);
}
} // namespace __gnu_profile } // namespace __gnu_profile
#endif /* _GLIBCXX_PROFILE_PROFILER_VECTOR_SIZE_H */ #endif /* _GLIBCXX_PROFILE_PROFILER_VECTOR_SIZE_H */
#ifndef _GLIBCXX_PROFILE_ITERATOR_TRACKER
#define _GLIBCXX_PROFILE_ITERATOR_TRACKER 1
#include <ext/type_traits.h>
namespace std
{
namespace __profile
{
template<typename _Iterator, typename _Sequence>
class __iterator_tracker
{
typedef __iterator_tracker _Self;
// The underlying iterator
_Iterator _M_current;
// The underlying data structure
const _Sequence* _M_ds;
typedef std::iterator_traits<_Iterator> _Traits;
public:
typedef _Iterator _Base_iterator;
typedef typename _Traits::iterator_category iterator_category;
typedef typename _Traits::value_type value_type;
typedef typename _Traits::difference_type difference_type;
typedef typename _Traits::reference reference;
typedef typename _Traits::pointer pointer;
__iterator_tracker() : _M_current(), _M_ds(0) { }
__iterator_tracker(const _Iterator& __i, const _Sequence* seq)
: _M_current(__i), _M_ds(seq) { }
__iterator_tracker(const __iterator_tracker& __x)
: _M_current(__x._M_current), _M_ds(__x._M_ds) { }
template<typename _MutableIterator>
__iterator_tracker(const __iterator_tracker<_MutableIterator, typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator, typename _Sequence::iterator::_Base_iterator>::__value), _Sequence>::__type>& __x)
: _M_current(__x.base()), _M_ds(__x._M_get_sequence()) { }
_Iterator
base() const { return _M_current; }
/**
* @brief Conversion to underlying non-debug iterator to allow
* better interaction with non-profile containers.
*/
operator _Iterator() const { return _M_current; }
pointer
operator->() const { return &*_M_current; }
__iterator_tracker&
operator++()
{
_M_ds->_M_profile_iterate();
++_M_current;
return *this;
}
__iterator_tracker&
operator++(int)
{
_M_ds->_M_profile_iterate();
__iterator_tracker __tmp(*this);
++_M_current;
return __tmp;
}
__iterator_tracker&
operator--()
{
_M_ds->_M_profile_iterate(1);
--_M_current;
return *this;
}
__iterator_tracker&
operator--(int)
{
_M_ds->_M_profile_iterate(1);
__iterator_tracker __tmp(*this);
--_M_current;
return __tmp;
}
__iterator_tracker&
operator=(const __iterator_tracker& __x)
{
_M_current = __x._M_current;
return *this;
}
reference
operator*() const
{
return *_M_current;
}
// ------ Random access iterator requirements ------
reference
operator[](const difference_type& __n) const
{
return _M_current[__n];
}
__iterator_tracker&
operator+=(const difference_type& __n)
{
_M_current += __n;
return *this;
}
__iterator_tracker
operator+(const difference_type& __n) const
{
__iterator_tracker __tmp(*this);
__tmp += __n;
return __tmp;
}
__iterator_tracker&
operator-=(const difference_type& __n)
{
_M_current += -__n;
return *this;
}
__iterator_tracker
operator-(const difference_type& __n) const
{
__iterator_tracker __tmp(*this);
__tmp -= __n;
return __tmp;
}
void
_M_find()
{
_M_ds->_M_profile_find();
}
const _Sequence*
_M_get_sequence() const
{
return static_cast<const _Sequence*>(_M_ds);
}
};
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator==(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
{
return __lhs.base() == __rhs.base();
}
template<typename _Iterator, typename _Sequence>
inline bool
operator==(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
{
return __lhs.base() == __rhs.base();
}
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator!=(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
{
return __lhs.base() != __rhs.base();
}
template<typename _Iterator, typename _Sequence>
inline bool
operator!=(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
{
return __lhs.base() != __rhs.base();
}
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator<(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
{
return __lhs.base() < __rhs.base();
}
template<typename _Iterator, typename _Sequence>
inline bool
operator<(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
{
return __lhs.base() < __rhs.base();
}
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator<=(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
{
return __lhs.base() <= __rhs.base();
}
template<typename _Iterator, typename _Sequence>
inline bool
operator<=(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
{
return __lhs.base() <= __rhs.base();
}
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator>(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
{
return __lhs.base() > __rhs.base();
}
template<typename _Iterator, typename _Sequence>
inline bool
operator>(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
{
return __lhs.base() > __rhs.base();
}
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline bool
operator>=(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
{
return __lhs.base() >= __rhs.base();
}
template<typename _Iterator, typename _Sequence>
inline bool
operator>=(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
{
return __lhs.base() >= __rhs.base();
}
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// According to the resolution of DR179 not only the various comparison
// operators but also operator- must accept mixed iterator/const_iterator
// parameters.
template<typename _IteratorL, typename _IteratorR, typename _Sequence>
inline typename __iterator_tracker<_IteratorL, _Sequence>::difference_type
operator-(const __iterator_tracker<_IteratorL, _Sequence>& __lhs,
const __iterator_tracker<_IteratorR, _Sequence>& __rhs)
{
return __lhs.base() - __rhs.base();
}
template<typename _Iterator, typename _Sequence>
inline typename __iterator_tracker<_Iterator, _Sequence>::difference_type
operator-(const __iterator_tracker<_Iterator, _Sequence>& __lhs,
const __iterator_tracker<_Iterator, _Sequence>& __rhs)
{
return __lhs.base() - __rhs.base();
}
template<typename _Iterator, typename _Sequence>
inline __iterator_tracker<_Iterator, _Sequence>
operator+(typename __iterator_tracker<_Iterator,_Sequence>::difference_type
__n,
const __iterator_tracker<_Iterator, _Sequence>& __i)
{
return __i + __n;
}
} // namespace __profile
} // namespace std
#endif
...@@ -37,12 +37,12 @@ ...@@ -37,12 +37,12 @@
#include <vector> #include <vector>
#include <utility> #include <utility>
#include <profile/base.h> #include <profile/base.h>
#include <profile/iterator_tracker.h>
namespace std namespace std
{ {
namespace __profile namespace __profile
{ {
/// Class std::vector wrapper with performance instrumentation.
template<typename _Tp, template<typename _Tp,
typename _Allocator = std::allocator<_Tp> > typename _Allocator = std::allocator<_Tp> >
class vector class vector
...@@ -54,17 +54,21 @@ namespace __profile ...@@ -54,17 +54,21 @@ namespace __profile
typedef typename _Base::reference reference; typedef typename _Base::reference reference;
typedef typename _Base::const_reference const_reference; typedef typename _Base::const_reference const_reference;
typedef typename _Base::iterator iterator; typedef __iterator_tracker<typename _Base::iterator, vector>
typedef typename _Base::const_iterator const_iterator; iterator;
typedef __iterator_tracker<typename _Base::const_iterator, vector>
const_iterator;
typedef typename _Base::size_type size_type; typedef typename _Base::size_type size_type;
typedef typename _Base::difference_type difference_type; typedef typename _Base::difference_type difference_type;
typedef _Tp value_type; typedef _Tp value_type;
typedef _Allocator allocator_type; typedef _Allocator allocator_type;
typedef typename _Base::pointer pointer; typedef typename _Base::pointer pointer;
typedef typename _Base::const_pointer const_pointer; typedef typename _Base::const_pointer const_pointer;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
_Base& _Base&
_M_base() { return *this; } _M_base() { return *this; }
...@@ -158,6 +162,58 @@ namespace __profile ...@@ -158,6 +162,58 @@ namespace __profile
using _Base::assign; using _Base::assign;
using _Base::get_allocator; using _Base::get_allocator;
// iterators:
iterator
begin()
{ return iterator(_Base::begin(), this); }
const_iterator
begin() const
{ return const_iterator(_Base::begin(), this); }
iterator
end()
{ return iterator(_Base::end(), this); }
const_iterator
end() const
{ return const_iterator(_Base::end(), this); }
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(), this); }
const_iterator
cend() const
{ return const_iterator(_Base::end(), this); }
const_reverse_iterator
crbegin() const
{ return const_reverse_iterator(end()); }
const_reverse_iterator
crend() const
{ return const_reverse_iterator(begin()); }
#endif
// 23.2.4.2 capacity: // 23.2.4.2 capacity:
using _Base::size; using _Base::size;
using _Base::max_size; using _Base::max_size;
...@@ -243,22 +299,24 @@ namespace __profile ...@@ -243,22 +299,24 @@ namespace __profile
iterator iterator
insert(iterator __position, const _Tp& __x) insert(iterator __position, const _Tp& __x)
{ {
__profcxx_vector_insert(this, __position-_Base::begin(), this->size()); __profcxx_vector_insert(this, __position.base() - _Base::begin(),
this->size());
size_type __old_size = this->capacity(); size_type __old_size = this->capacity();
typename _Base::iterator __res = _Base::insert(__position,__x); typename _Base::iterator __res = _Base::insert(__position.base(), __x);
_M_profile_resize(this, __old_size, this->capacity()); _M_profile_resize(this, __old_size, this->capacity());
return __res; return iterator(__res, this);
} }
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
iterator iterator
insert(iterator __position, _Tp&& __x) insert(iterator __position, _Tp&& __x)
{ {
__profcxx_vector_insert(this, __position-_Base::begin(), this->size()); __profcxx_vector_insert(this, __position.base() - _Base::begin(),
this->size());
size_type __old_size = this->capacity(); size_type __old_size = this->capacity();
typename _Base::iterator __res = _Base::insert(__position,__x); typename _Base::iterator __res = _Base::insert(__position.base(), __x);
_M_profile_resize(this, __old_size, this->capacity()); _M_profile_resize(this, __old_size, this->capacity());
return __res; return iterator(__res, this);
} }
void void
...@@ -266,20 +324,27 @@ namespace __profile ...@@ -266,20 +324,27 @@ namespace __profile
{ this->insert(__position, __l.begin(), __l.end()); } { this->insert(__position, __l.begin(), __l.end()); }
#endif #endif
#ifdef __GXX_EXPERIMENTAL_CXX0X__
void void
swap(vector&& __x)
{
_Base::swap(__x);
}
#endif
void
swap(vector& __x) swap(vector& __x)
{ {
_Base::swap(__x); _Base::swap(__x);
} }
void void
insert(iterator __position, size_type __n, const _Tp& __x) insert(iterator __position, size_type __n, const _Tp& __x)
{ {
__profcxx_vector_insert(this, __position-_Base::begin(), this->size()); __profcxx_vector_insert(this, __position.base() - _Base::begin(),
this->size());
size_type __old_size = this->capacity(); size_type __old_size = this->capacity();
_Base::insert(__position, __n, __x); _Base::insert(__position, __n, __x);
_M_profile_resize(this, __old_size, this->capacity()); _M_profile_resize(this, __old_size, this->capacity());
} }
...@@ -288,12 +353,31 @@ namespace __profile ...@@ -288,12 +353,31 @@ namespace __profile
insert(iterator __position, insert(iterator __position,
_InputIterator __first, _InputIterator __last) _InputIterator __first, _InputIterator __last)
{ {
__profcxx_vector_insert(this, __position-_Base::begin(), this->size()); __profcxx_vector_insert(this, __position.base()-_Base::begin(),
this->size());
size_type __old_size = this->capacity(); size_type __old_size = this->capacity();
_Base::insert(__position, __first, __last); _Base::insert(__position, __first, __last);
_M_profile_resize(this, __old_size, this->capacity()); _M_profile_resize(this, __old_size, this->capacity());
} }
iterator
erase(iterator __position)
{
typename _Base::iterator __res = _Base::erase(__position.base());
return iterator(__res, this);
}
iterator
erase(iterator __first, iterator __last)
{
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// 151. can't currently clear() empty container
typename _Base::iterator __res = _Base::erase(__first.base(),
__last.base());
return iterator(__res, this);
}
void void
clear() clear()
{ {
...@@ -302,17 +386,14 @@ namespace __profile ...@@ -302,17 +386,14 @@ namespace __profile
_Base::clear(); _Base::clear();
} }
// iterators: inline void _M_profile_find() const
iterator
begin()
{ {
return _Base::begin(); __profcxx_vector_find(this, size());
} }
const_iterator inline void _M_profile_iterate(int __rewind = 0) const
begin() const
{ {
return _Base::begin(); __profcxx_vector_iterate(this);
} }
private: private:
...@@ -367,6 +448,18 @@ namespace __profile ...@@ -367,6 +448,18 @@ namespace __profile
swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs) swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs)
{ __lhs.swap(__rhs); } { __lhs.swap(__rhs); }
#ifdef __GXX_EXPERIMENTAL_CXX0X__
template<typename _Tp, typename _Alloc>
inline void
swap(vector<_Tp, _Alloc>&& __lhs, vector<_Tp, _Alloc>& __rhs)
{ __lhs.swap(__rhs); }
template<typename _Tp, typename _Alloc>
inline void
swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>&& __rhs)
{ __lhs.swap(__rhs); }
#endif
} // namespace __profile } // namespace __profile
using _GLIBCXX_STD_D::_S_word_bit; using _GLIBCXX_STD_D::_S_word_bit;
} // namespace std } // namespace std
......
...@@ -28,7 +28,9 @@ typedef std::char_traits<char_t> traits_t; ...@@ -28,7 +28,9 @@ typedef std::char_traits<char_t> traits_t;
typedef __gnu_cxx::throw_allocator_random<char_t> allocator_t; typedef __gnu_cxx::throw_allocator_random<char_t> allocator_t;
typedef std::basic_string<char_t, traits_t, allocator_t> string_t; typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
#ifndef _GLIBCXX_PROFILE
string_t s("bayou bend"); string_t s("bayou bend");
#endif
int main() int main()
{ {
......
...@@ -29,12 +29,15 @@ typedef std::basic_string<char_t, traits_t, allocator_t> string_t; ...@@ -29,12 +29,15 @@ typedef std::basic_string<char_t, traits_t, allocator_t> string_t;
int main() int main()
{ {
#ifndef _GLIBCXX_PROFILE
{ {
string_t s; string_t s;
s += "bayou bend"; s += "bayou bend";
} }
#endif
if (__gnu_test::counter::count() != 0) if (__gnu_test::counter::count() != 0)
throw std::runtime_error("count not zero"); throw std::runtime_error("count not zero");
return 0; return 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment