Commit 6b223191 by Benjamin Kosnik Committed by Benjamin Kosnik

profiler_container_size.h: Fix include guard, formatting fixes.

2009-12-09  Benjamin Kosnik  <bkoz@redhat.com>

	* include/profile/impl/profiler_container_size.h: Fix include
	guard, formatting fixes.
	* include/profile/impl/profiler_vector_size.h: Same.
	* include/profile/impl/profiler_hash_func.h: Same.
	* include/profile/impl/profiler_trace.h: Same.
	* include/profile/impl/profiler_vector_to_list.h: Same.
	* include/profile/impl/profiler.h: Same.
	* include/profile/impl/profiler_state.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.

From-SVN: r155123
parent 14aa6352
2009-12-09 Benjamin Kosnik <bkoz@redhat.com>
* include/profile/impl/profiler_container_size.h: Fix include
guard, formatting fixes.
* include/profile/impl/profiler_vector_size.h: Same.
* include/profile/impl/profiler_hash_func.h: Same.
* include/profile/impl/profiler_trace.h: Same.
* include/profile/impl/profiler_vector_to_list.h: Same.
* include/profile/impl/profiler.h: Same.
* include/profile/impl/profiler_state.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.
2009-12-09 Roman Odaisky <to.roma.from.bugcc@qwertty.com> 2009-12-09 Roman Odaisky <to.roma.from.bugcc@qwertty.com>
PR libstdc++/42273 PR libstdc++/42273
......
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
// Written by Lixia Liu and Silvius Rus. // Written by Lixia Liu and Silvius Rus.
#ifndef PROFCXX_PROFILER_H__ #ifndef _GLIBCXX_PROFILE_PROFILER_H
#define PROFCXX_PROFILER_H__ 1 #define _GLIBCXX_PROFILE_PROFILER_H 1
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <cstddef> #include <cstddef>
...@@ -311,4 +311,4 @@ namespace __gnu_profile ...@@ -311,4 +311,4 @@ namespace __gnu_profile
#include "profile/impl/profiler_vector_size.h" #include "profile/impl/profiler_vector_size.h"
#include "profile/impl/profiler_vector_to_list.h" #include "profile/impl/profiler_vector_to_list.h"
#endif // PROFCXX_PROFILER_H__ #endif // _GLIBCXX_PROFILE_PROFILER_H
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
// Written by Lixia Liu and Silvius Rus. // Written by Lixia Liu and Silvius Rus.
#ifndef PROFCXX_PROFILER_CONTAINER_SIZE_H__ #ifndef _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H
#define PROFCXX_PROFILER_CONTAINER_SIZE_H__ 1 #define _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H 1
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <cstdlib> #include <cstdlib>
...@@ -53,43 +53,46 @@ ...@@ -53,43 +53,46 @@
namespace __gnu_profile namespace __gnu_profile
{ {
/** @brief A container size instrumentation line in the object table. */
/** @brief A container size instrumentation line in the object table. */ class __container_size_info: public __object_info_base
class __container_size_info: public __object_info_base {
{
public: public:
__container_size_info(); __container_size_info();
__container_size_info(const __container_size_info& __o); __container_size_info(const __container_size_info& __o);
__container_size_info(__stack_t __stack, size_t __num); __container_size_info(__stack_t __stack, size_t __num);
virtual ~__container_size_info() {} virtual ~__container_size_info() { }
void __write(FILE* f) const; void __write(FILE* f) const;
float __magnitude() const { return static_cast<float>(_M_cost); } float __magnitude() const { return static_cast<float>(_M_cost); }
const char* __advice() const; const char* __advice() const;
void __merge(const __container_size_info& __o); void __merge(const __container_size_info& __o);
// Call if a container is destructed or cleaned. // Call if a container is destructed or cleaned.
void __destruct(size_t __num, size_t __inum); void __destruct(size_t __num, size_t __inum);
// Estimate the cost of resize/rehash. // Estimate the cost of resize/rehash.
float __resize_cost(size_t __from, size_t __to) { return __from; } float __resize_cost(size_t __from, size_t __to) { return __from; }
// Call if container is resized. // Call if container is resized.
void __resize(size_t __from, size_t __to); void __resize(size_t __from, size_t __to);
private: private:
size_t _M_init; size_t _M_init;
size_t _M_max; // range of # buckets size_t _M_max; // Range of # buckets.
size_t _M_min; size_t _M_min;
size_t _M_total; size_t _M_total;
size_t _M_item_min; // range of # items size_t _M_item_min; // Range of # items.
size_t _M_item_max; size_t _M_item_max;
size_t _M_item_total; size_t _M_item_total;
size_t _M_count; size_t _M_count;
size_t _M_resize; size_t _M_resize;
size_t _M_cost; size_t _M_cost;
}; };
inline const char* __container_size_info::__advice() const inline const char*
{ __container_size_info::__advice() const
{
const size_t __max_chars_size_t_printed = 20; const size_t __max_chars_size_t_printed = 20;
const char* __message_pattern = const char* __message_pattern =
"change initial container size from %d to %d"; "change initial container size from %d to %d";
...@@ -106,46 +109,39 @@ inline const char* __container_size_info::__advice() const ...@@ -106,46 +109,39 @@ inline const char* __container_size_info::__advice() const
_M_item_max); _M_item_max);
return __message; return __message;
} }
inline void __container_size_info::__destruct(size_t __num, size_t __inum) inline void
{ __container_size_info::__destruct(size_t __num, size_t __inum)
{
_M_max = __max(_M_max, __num); _M_max = __max(_M_max, __num);
_M_item_max = __max(_M_item_max, __inum); _M_item_max = __max(_M_item_max, __inum);
if (_M_min == 0) { if (_M_min == 0)
{
_M_min = __num; _M_min = __num;
_M_item_min = __inum; _M_item_min = __inum;
} else { }
else
{
_M_min = __min(_M_min, __num); _M_min = __min(_M_min, __num);
_M_item_min = __min(_M_item_min, __inum); _M_item_min = __min(_M_item_min, __inum);
} }
_M_total += __num; _M_total += __num;
_M_item_total += __inum; _M_item_total += __inum;
_M_count += 1; _M_count += 1;
} }
inline void __container_size_info::__resize(size_t __from, size_t __to) inline void
{ __container_size_info::__resize(size_t __from, size_t __to)
{
_M_cost += this->__resize_cost(__from, __to); _M_cost += this->__resize_cost(__from, __to);
_M_resize += 1; _M_resize += 1;
_M_max = __max(_M_max, __to); _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) inline void
{ __container_size_info::__merge(const __container_size_info& __o)
{
_M_init = __max(_M_init, __o._M_init); _M_init = __max(_M_init, __o._M_init);
_M_max = __max(_M_max, __o._M_max); _M_max = __max(_M_max, __o._M_max);
_M_item_max = __max(_M_item_max, __o._M_item_max); _M_item_max = __max(_M_item_max, __o._M_item_max);
...@@ -156,18 +152,29 @@ inline void __container_size_info::__merge(const __container_size_info& __o) ...@@ -156,18 +152,29 @@ inline void __container_size_info::__merge(const __container_size_info& __o)
_M_count += __o._M_count; _M_count += __o._M_count;
_M_cost += __o._M_cost; _M_cost += __o._M_cost;
_M_resize += __o._M_resize; _M_resize += __o._M_resize;
} }
inline __container_size_info::__container_size_info() 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_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_total(0), _M_item_total(0), _M_cost(0), _M_count(0), _M_resize(0)
{ { }
}
inline __container_size_info::__container_size_info( inline __container_size_info::__container_size_info(__stack_t __stack,
const __container_size_info& __o) 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 __container_size_info::__container_size_info(const __container_size_info& __o)
: __object_info_base(__o) : __object_info_base(__o)
{ {
_M_init = __o._M_init; _M_init = __o._M_init;
_M_max = __o._M_max; _M_max = __o._M_max;
_M_item_max = __o._M_item_max; _M_item_max = __o._M_item_max;
...@@ -178,50 +185,54 @@ inline __container_size_info::__container_size_info( ...@@ -178,50 +185,54 @@ inline __container_size_info::__container_size_info(
_M_cost = __o._M_cost; _M_cost = __o._M_cost;
_M_count = __o._M_count; _M_count = __o._M_count;
_M_resize = __o._M_resize; _M_resize = __o._M_resize;
} }
/** @brief A container size instrumentation line in the stack table. */ /** @brief A container size instrumentation line in the stack table. */
class __container_size_stack_info: public __container_size_info class __container_size_stack_info: public __container_size_info
{ {
public: public:
__container_size_stack_info(const __container_size_info& __o) __container_size_stack_info(const __container_size_info& __o)
: __container_size_info(__o) {} : __container_size_info(__o) { }
}; };
/** @brief Container size instrumentation trace producer. */ /** @brief Container size instrumentation trace producer. */
class __trace_container_size class __trace_container_size
: public __trace_base<__container_size_info, __container_size_stack_info> : public __trace_base<__container_size_info, __container_size_stack_info>
{ {
public: public:
~__trace_container_size() {}
__trace_container_size() __trace_container_size()
: __trace_base<__container_size_info, __container_size_stack_info>() {}; : __trace_base<__container_size_info, __container_size_stack_info>() { };
~__trace_container_size() { }
// Insert a new node at construct with object, callstack and initial size. // Insert a new node at construct with object, callstack and initial size.
void __insert(const __object_t __obj, __stack_t __stack, size_t __num); void __insert(const __object_t __obj, __stack_t __stack, size_t __num);
// Call at destruction/clean to set container final size. // Call at destruction/clean to set container final size.
void __destruct(const void* __obj, size_t __num, size_t __inum); void __destruct(const void* __obj, size_t __num, size_t __inum);
void __construct(const void* __obj, size_t __inum); void __construct(const void* __obj, size_t __inum);
// Call at resize to set resize/cost information. // Call at resize to set resize/cost information.
void __resize(const void* __obj, int __from, int __to); void __resize(const void* __obj, int __from, int __to);
}; };
inline void __trace_container_size::__insert(const __object_t __obj, inline void
__trace_container_size::__insert(const __object_t __obj,
__stack_t __stack, size_t __num) __stack_t __stack, size_t __num)
{ { __add_object(__obj, __container_size_info(__stack, __num)); }
__add_object(__obj, __container_size_info(__stack, __num));
}
inline void __container_size_info::__write(FILE* __f) const inline void
{ __container_size_info::__write(FILE* __f) const
{
fprintf(__f, "%Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu\n", 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_init, _M_count, _M_cost, _M_resize, _M_min, _M_max, _M_total,
_M_item_min, _M_item_max, _M_item_total); _M_item_min, _M_item_max, _M_item_total);
} }
inline void __trace_container_size::__destruct(const void* __obj, inline void
size_t __num, size_t __inum) __trace_container_size::__destruct(const void* __obj, size_t __num,
{ size_t __inum)
{
if (!__is_on()) return; if (!__is_on()) return;
__object_t __obj_handle = static_cast<__object_t>(__obj); __object_t __obj_handle = static_cast<__object_t>(__obj);
...@@ -232,11 +243,11 @@ inline void __trace_container_size::__destruct(const void* __obj, ...@@ -232,11 +243,11 @@ inline void __trace_container_size::__destruct(const void* __obj,
__object_info->__destruct(__num, __inum); __object_info->__destruct(__num, __inum);
__retire_object(__obj_handle); __retire_object(__obj_handle);
} }
inline void __trace_container_size::__resize(const void* __obj, int __from, inline void
int __to) __trace_container_size::__resize(const void* __obj, int __from, int __to)
{ {
if (!__is_on()) return; if (!__is_on()) return;
__container_size_info* __object_info = __get_object_info(__obj); __container_size_info* __object_info = __get_object_info(__obj);
...@@ -244,7 +255,6 @@ inline void __trace_container_size::__resize(const void* __obj, int __from, ...@@ -244,7 +255,6 @@ inline void __trace_container_size::__resize(const void* __obj, int __from,
return; return;
__object_info->__resize(__from, __to); __object_info->__resize(__from, __to);
} }
} // namespace __gnu_profile } // namespace __gnu_profile
#endif /* PROFCXX_PROFILER_CONTAINER_SIZE_H__ */ #endif /* _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H */
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
// Written by Lixia Liu and Silvius Rus. // Written by Lixia Liu and Silvius Rus.
#ifndef PROFCXX_PROFILER_HASH_FUNC_H__ #ifndef _GLIBCXX_PROFILE_PROFILER_HASH_FUNC_H
#define PROFCXX_PROFILER_HASH_FUNC_H__ 1 #define _GLIBCXX_PROFILE_PROFILER_HASH_FUNC_H 1
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <cstdlib> #include <cstdlib>
...@@ -52,18 +52,19 @@ ...@@ -52,18 +52,19 @@
namespace __gnu_profile namespace __gnu_profile
{ {
/** @brief A hash performance instrumentation line in the object table. */
/** @brief A hash performance instrumentation line in the object table. */ class __hashfunc_info: public __object_info_base
class __hashfunc_info: public __object_info_base {
{
public: public:
__hashfunc_info() __hashfunc_info() :_M_longest_chain(0), _M_accesses(0), _M_hops(0) { }
:_M_longest_chain(0), _M_accesses(0), _M_hops(0) {}
__hashfunc_info(const __hashfunc_info& o); __hashfunc_info(const __hashfunc_info& o);
__hashfunc_info(__stack_t __stack) __hashfunc_info(__stack_t __stack)
: __object_info_base(__stack), : __object_info_base(__stack), _M_longest_chain(0),
_M_longest_chain(0), _M_accesses(0), _M_hops(0){} _M_accesses(0), _M_hops(0) { }
virtual ~__hashfunc_info() {}
virtual ~__hashfunc_info() { }
void __merge(const __hashfunc_info& __o); void __merge(const __hashfunc_info& __o);
void __destruct(size_t __chain, size_t __accesses, size_t __hops); void __destruct(size_t __chain, size_t __accesses, size_t __hops);
...@@ -71,76 +72,77 @@ class __hashfunc_info: public __object_info_base ...@@ -71,76 +72,77 @@ class __hashfunc_info: public __object_info_base
float __magnitude() const { return static_cast<float>(_M_hops); } float __magnitude() const { return static_cast<float>(_M_hops); }
const char* __advice() const { return "change hash function"; } const char* __advice() const { return "change hash function"; }
private: private:
size_t _M_longest_chain; size_t _M_longest_chain;
size_t _M_accesses; size_t _M_accesses;
size_t _M_hops; size_t _M_hops;
}; };
inline __hashfunc_info::__hashfunc_info(const __hashfunc_info& __o) inline __hashfunc_info::__hashfunc_info(const __hashfunc_info& __o)
: __object_info_base(__o) : __object_info_base(__o)
{ {
_M_longest_chain = __o._M_longest_chain; _M_longest_chain = __o._M_longest_chain;
_M_accesses = __o._M_accesses; _M_accesses = __o._M_accesses;
_M_hops = __o._M_hops; _M_hops = __o._M_hops;
} }
inline void __hashfunc_info::__merge(const __hashfunc_info& __o) inline void
{ __hashfunc_info::__merge(const __hashfunc_info& __o)
{
_M_longest_chain = __max(_M_longest_chain, __o._M_longest_chain); _M_longest_chain = __max(_M_longest_chain, __o._M_longest_chain);
_M_accesses += __o._M_accesses; _M_accesses += __o._M_accesses;
_M_hops += __o._M_hops; _M_hops += __o._M_hops;
} }
inline void __hashfunc_info::__destruct(size_t __chain, size_t __accesses, inline void
size_t __hops) __hashfunc_info::__destruct(size_t __chain, size_t __accesses, size_t __hops)
{ {
_M_longest_chain = __max(_M_longest_chain, __chain); _M_longest_chain = __max(_M_longest_chain, __chain);
_M_accesses += __accesses; _M_accesses += __accesses;
_M_hops += __hops; _M_hops += __hops;
} }
/** @brief A hash performance instrumentation line in the stack table. */ /** @brief A hash performance instrumentation line in the stack table. */
class __hashfunc_stack_info: public __hashfunc_info { class __hashfunc_stack_info: public __hashfunc_info
{
public: public:
__hashfunc_stack_info(const __hashfunc_info& __o) : __hashfunc_info(__o) {} __hashfunc_stack_info(const __hashfunc_info& __o) : __hashfunc_info(__o) { }
}; };
/** @brief Hash performance instrumentation producer. */ /** @brief Hash performance instrumentation producer. */
class __trace_hash_func class __trace_hash_func
: public __trace_base<__hashfunc_info, __hashfunc_stack_info> : public __trace_base<__hashfunc_info, __hashfunc_stack_info>
{ {
public: public:
__trace_hash_func(); __trace_hash_func();
~__trace_hash_func() {} ~__trace_hash_func() { }
// Insert a new node at construct with object, callstack and initial size. // Insert a new node at construct with object, callstack and initial size.
void __insert(__object_t __obj, __stack_t __stack); void __insert(__object_t __obj, __stack_t __stack);
// Call at destruction/clean to set container final size. // Call at destruction/clean to set container final size.
void __destruct(const void* __obj, size_t __chain, void __destruct(const void* __obj, size_t __chain, size_t __accesses,
size_t __accesses, size_t __hops); size_t __hops);
}; };
inline __trace_hash_func::__trace_hash_func() inline __trace_hash_func::__trace_hash_func()
: __trace_base<__hashfunc_info, __hashfunc_stack_info>() : __trace_base<__hashfunc_info, __hashfunc_stack_info>()
{ { __id = "hash-distr"; }
__id = "hash-distr";
}
inline void __trace_hash_func::__insert(__object_t __obj, __stack_t __stack) inline void
{ __trace_hash_func::__insert(__object_t __obj, __stack_t __stack)
__add_object(__obj, __hashfunc_info(__stack)); { __add_object(__obj, __hashfunc_info(__stack)); }
}
inline void __hashfunc_info::__write(FILE* __f) const inline void
{ __hashfunc_info::__write(FILE* __f) const
fprintf(__f, "%Zu %Zu %Zu\n", _M_hops, _M_accesses, _M_longest_chain); { 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, inline void
__trace_hash_func::__destruct(const void* __obj, size_t __chain,
size_t __accesses, size_t __hops) size_t __accesses, size_t __hops)
{ {
if (!__is_on()) return; if (!__is_on())
return;
// First find the item from the live objects and update the informations. // First find the item from the live objects and update the informations.
__hashfunc_info* __objs = __get_object_info(__obj); __hashfunc_info* __objs = __get_object_info(__obj);
...@@ -149,44 +151,44 @@ inline void __trace_hash_func::__destruct(const void* __obj, size_t __chain, ...@@ -149,44 +151,44 @@ inline void __trace_hash_func::__destruct(const void* __obj, size_t __chain,
__objs->__destruct(__chain, __accesses, __hops); __objs->__destruct(__chain, __accesses, __hops);
__retire_object(__obj); __retire_object(__obj);
} }
//////////////////////////////////////////////////////////////////////////////
// Initialization and report.
//////////////////////////////////////////////////////////////////////////////
inline void __trace_hash_func_init() // Initialization and report.
{ inline void
__tables<0>::_S_hash_func = new __trace_hash_func(); __trace_hash_func_init()
} { __tables<0>::_S_hash_func = new __trace_hash_func(); }
inline void __trace_hash_func_report(FILE* __f, inline void
__warning_vector_t& __warnings) __trace_hash_func_report(FILE* __f, __warning_vector_t& __warnings)
{ {
if (__tables<0>::_S_hash_func) { if (__tables<0>::_S_hash_func)
{
__tables<0>::_S_hash_func->__collect_warnings(__warnings); __tables<0>::_S_hash_func->__collect_warnings(__warnings);
__tables<0>::_S_hash_func->__write(__f); __tables<0>::_S_hash_func->__write(__f);
} }
} }
//////////////////////////////////////////////////////////////////////////////
// Implementations of instrumentation hooks.
//////////////////////////////////////////////////////////////////////////////
inline void __trace_hash_func_construct(const void* __obj) // Implementations of instrumentation hooks.
{ inline void
if (!__profcxx_init()) return; __trace_hash_func_construct(const void* __obj)
{
if (!__profcxx_init())
return;
__tables<0>::_S_hash_func->__insert(__obj, __get_stack()); __tables<0>::_S_hash_func->__insert(__obj, __get_stack());
} }
inline void __trace_hash_func_destruct(const void* __obj, size_t __chain, inline void
__trace_hash_func_destruct(const void* __obj, size_t __chain,
size_t __accesses, size_t __hops) size_t __accesses, size_t __hops)
{ {
if (!__profcxx_init()) return; if (!__profcxx_init())
return;
__tables<0>::_S_hash_func->__destruct(__obj, __chain, __accesses, __hops); __tables<0>::_S_hash_func->__destruct(__obj, __chain, __accesses, __hops);
} }
} // namespace __gnu_profile } // namespace __gnu_profile
#endif /* PROFCXX_PROFILER_HASH_FUNC_H__ */ #endif /* _GLIBCXX_PROFILE_PROFILER_HASH_FUNC_H */
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
// Written by Lixia Liu and Silvius Rus. // Written by Lixia Liu and Silvius Rus.
#ifndef PROFCXX_PROFILER_HASHTABLE_SIZE_H__ #ifndef _GLIBCXX_PROFILE_PROFILER_HASHTABLE_SIZE_H
#define PROFCXX_PROFILER_HASHTABLE_SIZE_H__ 1 #define _GLIBCXX_PROFILE_PROFILER_HASHTABLE_SIZE_H 1
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <cstdlib> #include <cstdlib>
...@@ -54,62 +54,58 @@ ...@@ -54,62 +54,58 @@
namespace __gnu_profile namespace __gnu_profile
{ {
/** @brief Hashtable size instrumentation trace producer. */
/** @brief Hashtable size instrumentation trace producer. */ class __trace_hashtable_size : public __trace_container_size
class __trace_hashtable_size : public __trace_container_size {
{
public: public:
__trace_hashtable_size() : __trace_container_size() __trace_hashtable_size() : __trace_container_size()
{ { __id = "hashtable-size"; }
__id = "hashtable-size"; };
}
};
////////////////////////////////////////////////////////////////////////////// // Initialization and report.
// Initialization and report. inline void
////////////////////////////////////////////////////////////////////////////// __trace_hashtable_size_init()
{ __tables<0>::_S_hashtable_size = new __trace_hashtable_size(); }
inline void __trace_hashtable_size_init() inline void
{ __trace_hashtable_size_report(FILE* __f, __warning_vector_t& __warnings)
__tables<0>::_S_hashtable_size = new __trace_hashtable_size(); {
} if (__tables<0>::_S_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->__collect_warnings(__warnings);
__tables<0>::_S_hashtable_size->__write(__f); __tables<0>::_S_hashtable_size->__write(__f);
} }
} }
//////////////////////////////////////////////////////////////////////////////
// Implementations of instrumentation hooks.
//////////////////////////////////////////////////////////////////////////////
inline void __trace_hashtable_size_construct(const void* __obj, size_t __num) // Implementations of instrumentation hooks.
{ inline void
if (!__profcxx_init()) return; __trace_hashtable_size_construct(const void* __obj, size_t __num)
{
if (!__profcxx_init())
return;
__tables<0>::_S_hashtable_size->__insert(__obj, __get_stack(), __num); __tables<0>::_S_hashtable_size->__insert(__obj, __get_stack(), __num);
} }
inline void __trace_hashtable_size_destruct(const void* __obj, size_t __num, inline void
__trace_hashtable_size_destruct(const void* __obj, size_t __num,
size_t __inum) size_t __inum)
{ {
if (!__profcxx_init()) return; if (!__profcxx_init())
return;
__tables<0>::_S_hashtable_size->__destruct(__obj, __num, __inum); __tables<0>::_S_hashtable_size->__destruct(__obj, __num, __inum);
} }
inline void __trace_hashtable_size_resize(const void* __obj, size_t __from, inline void
size_t __to) __trace_hashtable_size_resize(const void* __obj, size_t __from, size_t __to)
{ {
if (!__profcxx_init()) return; if (!__profcxx_init())
return;
__tables<0>::_S_hashtable_size->__resize(__obj, __from, __to); __tables<0>::_S_hashtable_size->__resize(__obj, __from, __to);
} }
} // namespace __gnu_profile } // namespace __gnu_profile
#endif /* PROFCXX_PROFILER_HASHTABLE_SIZE_H__ */ #endif /* _GLIBCXX_PROFILE_PROFILER_HASHTABLE_SIZE_H */
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
// Written by Silvius Rus. // Written by Silvius Rus.
#ifndef PROFCXX_PROFILER_MAP_TO_UNORDERED_MAP_H__ #ifndef _GLIBCXX_PROFILE_PROFILER_MAP_TO_UNORDERED_MAP_H
#define PROFCXX_PROFILER_MAP_TO_UNORDERED_MAP_H__ 1 #define _GLIBCXX_PROFILE_PROFILER_MAP_TO_UNORDERED_MAP_H 1
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <cstdlib> #include <cstdlib>
...@@ -52,66 +52,68 @@ ...@@ -52,66 +52,68 @@
namespace __gnu_profile namespace __gnu_profile
{ {
// Cost model.
// Cost model. XXX: this must be taken from the machine model instead. // Map operations:
// Map operations: // - insert: 1.5 * log(size)
// - insert: 1.5 * log(size) // - erase: 1.5 * log(size)
// - erase: 1.5 * log(size) // - find: log(size)
// - find: log(size) // - iterate: 2.3
// - iterate: 2.3 // Unordered map operations:
// Unordered map operations: // - insert: 12
// - insert: 12 // - erase: 12
// - erase: 12 // - find: 10
// - find: 10 // - iterate: 1.7
// - iterate: 1.7 // XXX: this must be taken from the machine model instead.
const float __map_insert_cost_factor = 1.5;
const float __map_insert_cost_factor = 1.5; const float __map_erase_cost_factor = 1.5;
const float __map_erase_cost_factor = 1.5; const float __map_find_cost_factor = 1;
const float __map_find_cost_factor = 1; const float __map_iterate_cost = 2.3;
const float __map_iterate_cost = 2.3;
const float __umap_insert_cost = 12.0;
const float __umap_insert_cost = 12.0; const float __umap_erase_cost = 12.0;
const float __umap_erase_cost = 12.0; const float __umap_find_cost = 10.0;
const float __umap_find_cost = 10.0; const float __umap_iterate_cost = 1.7;
const float __umap_iterate_cost = 1.7;
inline int
inline int __log2(size_t __size) __log2(size_t __size)
{ {
for (int __bit_count = sizeof(size_t) - 1; __bit_count >= 0; --__bit_count) { int __bit_count = sizeof(size_t) - 1;
if ((2 << __bit_count) & __size) { for (; __bit_count >= 0; --__bit_count)
{
if ((2 << __bit_count) & __size)
return __bit_count; return __bit_count;
} }
}
return 0; return 0;
} }
inline float __map_insert_cost(size_t __size) inline float
{ __map_insert_cost(size_t __size)
return __map_insert_cost_factor * static_cast<float>(__log2(__size)); { return __map_insert_cost_factor * static_cast<float>(__log2(__size)); }
}
inline float __map_erase_cost(size_t __size) inline float
{ __map_erase_cost(size_t __size)
return __map_erase_cost_factor * static_cast<float>(__log2(__size)); { return __map_erase_cost_factor * static_cast<float>(__log2(__size)); }
}
inline float __map_find_cost(size_t __size) inline float
{ __map_find_cost(size_t __size)
return __map_find_cost_factor * static_cast<float>(__log2(__size)); { return __map_find_cost_factor * static_cast<float>(__log2(__size)); }
}
/** @brief A map-to-unordered_map instrumentation line in the object table. */ /** @brief A map-to-unordered_map instrumentation line in the object table. */
class __map2umap_info: public __object_info_base class __map2umap_info: public __object_info_base
{ {
public: public:
__map2umap_info() __map2umap_info()
: _M_insert(0), _M_erase(0), _M_find(0), _M_iterate(0), : _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) {} _M_map_cost(0.0), _M_umap_cost(0.0), _M_valid(true) { }
__map2umap_info(__stack_t __stack) __map2umap_info(__stack_t __stack)
: __object_info_base(__stack), _M_insert(0), _M_erase(0), _M_find(0), : __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) {} _M_iterate(0), _M_map_cost(0.0), _M_umap_cost(0.0), _M_valid(true) { }
virtual ~__map2umap_info() {}
virtual ~__map2umap_info() { }
__map2umap_info(const __map2umap_info& o); __map2umap_info(const __map2umap_info& o);
void __merge(const __map2umap_info& o); void __merge(const __map2umap_info& o);
void __write(FILE* __f) const; void __write(FILE* __f) const;
float __magnitude() const { return _M_map_cost - _M_umap_cost; } float __magnitude() const { return _M_map_cost - _M_umap_cost; }
...@@ -131,14 +133,9 @@ class __map2umap_info: public __object_info_base ...@@ -131,14 +133,9 @@ class __map2umap_info: public __object_info_base
float _M_umap_cost; float _M_umap_cost;
float _M_map_cost; float _M_map_cost;
bool _M_valid; 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) inline __map2umap_info::__map2umap_info(const __map2umap_info& __o)
: __object_info_base(__o), : __object_info_base(__o),
_M_insert(__o._M_insert), _M_insert(__o._M_insert),
_M_erase(__o._M_erase), _M_erase(__o._M_erase),
...@@ -147,159 +144,183 @@ inline __map2umap_info::__map2umap_info(const __map2umap_info& __o) ...@@ -147,159 +144,183 @@ inline __map2umap_info::__map2umap_info(const __map2umap_info& __o)
_M_map_cost(__o._M_map_cost), _M_map_cost(__o._M_map_cost),
_M_umap_cost(__o._M_umap_cost), _M_umap_cost(__o._M_umap_cost),
_M_valid(__o._M_valid) _M_valid(__o._M_valid)
{} { }
inline void __map2umap_info::__merge(const __map2umap_info& __o) inline const char*
{ __map2umap_info::__advice() const
{ return "change std::map to std::unordered_map"; }
inline void
__map2umap_info::__merge(const __map2umap_info& __o)
{
_M_insert += __o._M_insert; _M_insert += __o._M_insert;
_M_erase += __o._M_erase; _M_erase += __o._M_erase;
_M_find += __o._M_find; _M_find += __o._M_find;
_M_map_cost += __o._M_map_cost; _M_map_cost += __o._M_map_cost;
_M_umap_cost += __o._M_umap_cost; _M_umap_cost += __o._M_umap_cost;
_M_valid &= __o._M_valid; _M_valid &= __o._M_valid;
} }
inline void __map2umap_info:: __record_insert(size_t __size, size_t __count) inline void
{ __map2umap_info:: __record_insert(size_t __size, size_t __count)
{
_M_insert += __count; _M_insert += __count;
_M_map_cost += __count * __map_insert_cost(__size); _M_map_cost += __count * __map_insert_cost(__size);
_M_umap_cost += __count * __umap_insert_cost; _M_umap_cost += __count * __umap_insert_cost;
} }
inline void __map2umap_info:: __record_erase(size_t __size, size_t __count) inline void
{ __map2umap_info:: __record_erase(size_t __size, size_t __count)
{
_M_erase += __count; _M_erase += __count;
_M_map_cost += __count * __map_erase_cost(__size); _M_map_cost += __count * __map_erase_cost(__size);
_M_umap_cost += __count * __umap_erase_cost; _M_umap_cost += __count * __umap_erase_cost;
} }
inline void __map2umap_info:: __record_find(size_t __size) inline void
{ __map2umap_info:: __record_find(size_t __size)
{
_M_find += 1; _M_find += 1;
_M_map_cost += __map_find_cost(__size); _M_map_cost += __map_find_cost(__size);
_M_umap_cost += __umap_find_cost; _M_umap_cost += __umap_find_cost;
} }
inline void __map2umap_info:: __record_iterate(size_t __count) inline void
{ __map2umap_info:: __record_iterate(size_t __count)
{
_M_iterate += __count; _M_iterate += __count;
_M_map_cost += __count * __map_iterate_cost; _M_map_cost += __count * __map_iterate_cost;
_M_umap_cost += __count * __umap_iterate_cost; _M_umap_cost += __count * __umap_iterate_cost;
} }
inline void __map2umap_info:: __record_invalidate() inline void
{ __map2umap_info:: __record_invalidate()
{
_M_valid = false; _M_valid = false;
} }
inline void __map2umap_info::__write(FILE* __f) const inline void
{ __map2umap_info::__write(FILE* __f) const
{
fprintf(__f, "%Zu %Zu %Zu %Zu %.0f %.0f %s\n", 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_insert, _M_erase, _M_find, _M_iterate, _M_map_cost, _M_umap_cost,
_M_valid ? "valid" : "invalid"); _M_valid ? "valid" : "invalid");
} }
/** @brief A map-to-unordered_map instrumentation line in the stack table. */ /** @brief A map-to-unordered_map instrumentation line in the stack table. */
class __map2umap_stack_info: public __map2umap_info class __map2umap_stack_info: public __map2umap_info
{ {
public: public:
__map2umap_stack_info(const __map2umap_info& o) : __map2umap_info(o) {} __map2umap_stack_info(const __map2umap_info& o) : __map2umap_info(o) { }
}; };
/** @brief Map-to-unordered_map instrumentation producer. */ /** @brief Map-to-unordered_map instrumentation producer. */
class __trace_map2umap class __trace_map2umap
: public __trace_base<__map2umap_info, __map2umap_stack_info> : public __trace_base<__map2umap_info, __map2umap_stack_info>
{ {
public: public:
__trace_map2umap(); __trace_map2umap();
}; };
inline __trace_map2umap::__trace_map2umap() inline __trace_map2umap::__trace_map2umap()
: __trace_base<__map2umap_info, __map2umap_stack_info>() : __trace_base<__map2umap_info, __map2umap_stack_info>()
{ { __id = "map-to-unordered-map"; }
__id = "map-to-unordered-map";
}
inline void __trace_map_to_unordered_map_init() inline void
{ __trace_map_to_unordered_map_init()
__tables<0>::_S_map2umap = new __trace_map2umap(); { __tables<0>::_S_map2umap = new __trace_map2umap(); }
}
inline void __trace_map_to_unordered_map_report( inline void
FILE* __f, __warning_vector_t& __warnings) __trace_map_to_unordered_map_report(FILE* __f, __warning_vector_t& __warnings)
{ {
if (__tables<0>::_S_map2umap) { if (__tables<0>::_S_map2umap)
{
__tables<0>::_S_map2umap->__collect_warnings(__warnings); __tables<0>::_S_map2umap->__collect_warnings(__warnings);
__tables<0>::_S_map2umap->__write(__f); __tables<0>::_S_map2umap->__write(__f);
} }
} }
//////////////////////////////////////////////////////////////////////////////
// Implementations of instrumentation hooks.
//////////////////////////////////////////////////////////////////////////////
inline void __trace_map_to_unordered_map_construct(const void* __obj) // Implementations of instrumentation hooks.
{ inline void
if (!__profcxx_init()) return; __trace_map_to_unordered_map_construct(const void* __obj)
{
if (!__profcxx_init())
return;
__tables<0>::_S_map2umap->__add_object(__obj, __tables<0>::_S_map2umap->__add_object(__obj,
__map2umap_info(__get_stack())); __map2umap_info(__get_stack()));
} }
inline void __trace_map_to_unordered_map_destruct(const void* __obj) inline void
{ __trace_map_to_unordered_map_destruct(const void* __obj)
if (!__profcxx_init()) return; {
if (!__profcxx_init())
return;
__tables<0>::_S_map2umap->__retire_object(__obj); __tables<0>::_S_map2umap->__retire_object(__obj);
} }
inline void __trace_map_to_unordered_map_insert(const void* __obj, inline void
size_t __size, size_t __count) __trace_map_to_unordered_map_insert(const void* __obj, size_t __size,
{ size_t __count)
if (!__profcxx_init()) return; {
if (!__profcxx_init())
return;
__map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj); __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj);
if (__info) __info->__record_insert(__size, __count); if (__info)
} __info->__record_insert(__size, __count);
}
inline void __trace_map_to_unordered_map_erase(const void* __obj, inline void
size_t __size, size_t __count) __trace_map_to_unordered_map_erase(const void* __obj, size_t __size,
{ size_t __count)
if (!__profcxx_init()) return; {
if (!__profcxx_init())
return;
__map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj); __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj);
if (__info) __info->__record_erase(__size, __count); if (__info)
} __info->__record_erase(__size, __count);
}
inline void __trace_map_to_unordered_map_find(const void* __obj, size_t __size) inline void
{ __trace_map_to_unordered_map_find(const void* __obj, size_t __size)
if (!__profcxx_init()) return; {
if (!__profcxx_init())
return;
__map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj); __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj);
if (__info) __info->__record_find(__size); if (__info)
} __info->__record_find(__size);
}
inline void __trace_map_to_unordered_map_iterate(const void* __obj, inline void
size_t __count) __trace_map_to_unordered_map_iterate(const void* __obj, size_t __count)
{ {
if (!__profcxx_init()) return; if (!__profcxx_init())
return;
__map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj); __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj);
if (__info) __info->__record_iterate(__count); if (__info)
} __info->__record_iterate(__count);
}
inline void __trace_map_to_unordered_map_invalidate(const void* __obj) inline void
{ __trace_map_to_unordered_map_invalidate(const void* __obj)
if (!__profcxx_init()) return; {
if (!__profcxx_init())
return;
__map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj); __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj);
if (__info) __info->__record_invalidate(); if (__info)
} __info->__record_invalidate();
}
} // namespace __gnu_profile } // namespace __gnu_profile
#endif /* PROFCXX_PROFILER_MAP_TO_UNORDERED_MAP_H__ */ #endif /* _GLIBCXX_PROFILE_PROFILER_MAP_TO_UNORDERED_MAP_H */
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
// Written by Lixia Liu and Silvius Rus. // Written by Lixia Liu and Silvius Rus.
#ifndef PROFCXX_PROFILER_NODE_H__ #ifndef _GLIBCXX_PROFILE_PROFILER_NODE_H
#define PROFCXX_PROFILER_NODE_H__ 1 #define _GLIBCXX_PROFILE_PROFILER_NODE_H 1
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <cstdio> #include <cstdio>
...@@ -53,15 +53,15 @@ ...@@ -53,15 +53,15 @@
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 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)
...@@ -74,42 +74,39 @@ inline __stack_t __get_stack() ...@@ -74,42 +74,39 @@ inline __stack_t __get_stack()
#else #else
return NULL; return NULL;
#endif #endif
} }
inline __size(const __stack_t& __stack) inline __size(const __stack_t& __stack)
{ {
if (!__stack) { if (!__stack)
return 0; return 0;
} else { else
return __stack->size(); return __stack->size();
} }
}
inline void __write(FILE* __f, const __stack_t __stack) inline void __write(FILE* __f, const __stack_t __stack)
{ {
if (!__stack) { if (!__stack)
return; return;
}
__stack_npt::const_iterator __it; __stack_npt::const_iterator __it;
for (__it = __stack->begin(); __it != __stack->end(); ++__it) { for (__it = __stack->begin(); __it != __stack->end(); ++__it)
fprintf(__f, "%p ", *__it); fprintf(__f, "%p ", *__it);
} }
}
/** @brief Hash function for summary trace using call stack as index. */ /** @brief Hash function for summary trace using call stack as index. */
class __stack_hash class __stack_hash
{ {
public: public:
size_t operator()(const __stack_t __s) const size_t operator()(const __stack_t __s) const
{ {
if (!__s) { if (!__s)
return 0; return 0;
}
uintptr_t __index = 0; uintptr_t __index = 0;
__stack_npt::const_iterator __it; __stack_npt::const_iterator __it;
for (__it = __s->begin(); __it != __s->end(); ++__it) { for (__it = __s->begin(); __it != __s->end(); ++__it)
{
__index += reinterpret_cast<uintptr_t>(*__it); __index += reinterpret_cast<uintptr_t>(*__it);
} }
return __index; return __index;
...@@ -124,16 +121,16 @@ class __stack_hash ...@@ -124,16 +121,16 @@ class __stack_hash
size_t __byte_size = __stack1->size() * sizeof(__stack_npt::value_type); size_t __byte_size = __stack1->size() * sizeof(__stack_npt::value_type);
return memcmp(&(*__stack1)[0], &(*__stack2)[0], __byte_size) == 0; return memcmp(&(*__stack1)[0], &(*__stack2)[0], __byte_size) == 0;
} }
}; };
/** @brief Base class for a line in the object table. */ /** @brief Base class for a line in the object table. */
class __object_info_base class __object_info_base
{ {
public: public:
__object_info_base() {} __object_info_base() { }
__object_info_base(__stack_t __stack); __object_info_base(__stack_t __stack);
__object_info_base(const __object_info_base& o); __object_info_base(const __object_info_base& o);
virtual ~__object_info_base() {} virtual ~__object_info_base() { }
bool __is_valid() const { return _M_valid; } bool __is_valid() const { return _M_valid; }
__stack_t __stack() const { return _M_stack; } __stack_t __stack() const { return _M_stack; }
virtual void __write(FILE* f) const = 0; virtual void __write(FILE* f) const = 0;
...@@ -141,32 +138,31 @@ class __object_info_base ...@@ -141,32 +138,31 @@ class __object_info_base
protected: protected:
__stack_t _M_stack; __stack_t _M_stack;
bool _M_valid; bool _M_valid;
}; };
inline __object_info_base::__object_info_base(__stack_t __stack) inline __object_info_base::__object_info_base(__stack_t __stack)
{ {
_M_stack = __stack; _M_stack = __stack;
_M_valid = true; _M_valid = true;
} }
inline __object_info_base::__object_info_base(const __object_info_base& __o) inline __object_info_base::__object_info_base(const __object_info_base& __o)
{ {
_M_stack = __o._M_stack; _M_stack = __o._M_stack;
_M_valid = __o._M_valid; _M_valid = __o._M_valid;
} }
/** @brief Base class for a line in the stack table. */ /** @brief Base class for a line in the stack table. */
template<typename __object_info> template<typename __object_info>
class __stack_info_base class __stack_info_base
{ {
public: public:
__stack_info_base() {} __stack_info_base() { }
__stack_info_base(const __object_info& __info) = 0; __stack_info_base(const __object_info& __info) = 0;
virtual ~__stack_info_base() {} virtual ~__stack_info_base() { }
void __merge(const __object_info& __info) = 0; void __merge(const __object_info& __info) = 0;
virtual float __magnitude() const = 0; virtual float __magnitude() const = 0;
virtual const char* __get_id() const = 0; virtual const char* __get_id() const = 0;
}; };
} // namespace __gnu_profile } // namespace __gnu_profile
#endif /* PROFCXX_PROFILER_NODE_H__ */ #endif /* _GLIBCXX_PROFILE_PROFILER_NODE_H */
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
// Written by Lixia Liu and Silvius Rus. // Written by Lixia Liu and Silvius Rus.
#ifndef PROFCXX_PROFILER_STATE_H__ #ifndef _GLIBCXX_PROFILE_PROFILER_STATE_H
#define PROFCXX_PROFILER_STATE_H__ 1 #define _GLIBCXX_PROFILE_PROFILER_STATE_H 1
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <cstdio> #include <cstdio>
...@@ -45,63 +45,64 @@ ...@@ -45,63 +45,64 @@
namespace __gnu_profile namespace __gnu_profile
{ {
/** @brief Profiling mode on/off state. */
template<int _Unused=0>
class __state
{
private:
enum __state_type { __ON, __OFF, __INVALID };
/** @brief Profiling mode on/off state. */ __state_type _M_state;
template <int _Unused=0>
class __state
{
public:
public:
static __state<_Unused>* _S_diag_state; static __state<_Unused>* _S_diag_state;
__state() : _M_state(__INVALID) {} __state() : _M_state(__INVALID) { }
~__state() {} ~__state() { }
bool __is_on() { return _M_state == __ON; } bool __is_on() { return _M_state == __ON; }
bool __is_off() { return _M_state == __OFF; } bool __is_off() { return _M_state == __OFF; }
bool __is_invalid() { return _M_state == __INVALID; } bool __is_invalid() { return _M_state == __INVALID; }
void __turn_on() { _M_state = __ON; } void __turn_on() { _M_state = __ON; }
void __turn_off() { _M_state = __OFF; } void __turn_off() { _M_state = __OFF; }
};
private: template<int _Unused>
enum __state_type { __ON, __OFF, __INVALID }; __state<_Unused>* __state<_Unused>::_S_diag_state = NULL;
__state_type _M_state;
};
template <int _Unused> inline bool
__state<_Unused>* __state<_Unused>::_S_diag_state = NULL; __is_on()
{
inline bool __is_on()
{
return __state<0>::_S_diag_state && __state<0>::_S_diag_state->__is_on(); return __state<0>::_S_diag_state && __state<0>::_S_diag_state->__is_on();
} }
inline bool __is_off() inline bool
{ __is_off()
{
return __state<0>::_S_diag_state && __state<0>::_S_diag_state->__is_off(); return __state<0>::_S_diag_state && __state<0>::_S_diag_state->__is_off();
} }
inline bool __is_invalid() inline bool
{ __is_invalid()
return (!__state<0>::_S_diag_state {
|| __state<0>::_S_diag_state->__is_invalid()); return (!__state<0>::_S_diag_state || __state<0>::_S_diag_state->__is_invalid());
} }
inline void __turn_on() inline void
{ __turn_on()
if (!__state<0>::_S_diag_state) { {
if (!__state<0>::_S_diag_state)
__state<0>::_S_diag_state = new __state<0>(); __state<0>::_S_diag_state = new __state<0>();
}
__state<0>::_S_diag_state->__turn_on(); __state<0>::_S_diag_state->__turn_on();
} }
inline void __turn_off() inline void
{ __turn_off()
if (!__state<0>::_S_diag_state) { {
if (!__state<0>::_S_diag_state)
__state<0>::_S_diag_state = new __state<0>(); __state<0>::_S_diag_state = new __state<0>();
}
__state<0>::_S_diag_state->__turn_off(); __state<0>::_S_diag_state->__turn_off();
} }
} // end namespace __gnu_profile } // end namespace __gnu_profile
#endif /* PROFCXX_PROFILER_STATE_H__ */ #endif /* _GLIBCXX_PROFILE_PROFILER_STATE_H */
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
// Written by Lixia Liu and Silvius Rus. // Written by Lixia Liu and Silvius Rus.
#ifndef PROFCXX_PROFILER_TRACE_H__ #ifndef _GLIBCXX_PROFILE_PROFILER_TRACE_H
#define PROFCXX_PROFILER_TRACE_H__ 1 #define _GLIBCXX_PROFILE_PROFILER_TRACE_H 1
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <cerrno> #include <cerrno>
...@@ -65,37 +65,40 @@ ...@@ -65,37 +65,40 @@
namespace __gnu_profile namespace __gnu_profile
{ {
#if defined _GLIBCXX_PROFILE_THREADS && defined HAVE_TLS #if defined _GLIBCXX_PROFILE_THREADS && defined HAVE_TLS
#define _GLIBCXX_IMPL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER #define _GLIBCXX_IMPL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
typedef pthread_mutex_t __mutex_t; typedef pthread_mutex_t __mutex_t;
/** @brief Pthread mutex wrapper. */
template <int _Unused=0> /** @brief Pthread mutex wrapper. */
class __mutex { template<int _Unused=0>
class __mutex
{
public: public:
static __mutex_t __global_lock; static __mutex_t __global_lock;
static void __lock(__mutex_t& __m) { pthread_mutex_lock(&__m); } static void __lock(__mutex_t& __m) { pthread_mutex_lock(&__m); }
static void __unlock(__mutex_t& __m) { pthread_mutex_unlock(&__m); } static void __unlock(__mutex_t& __m) { pthread_mutex_unlock(&__m); }
}; };
#else #else
#define _GLIBCXX_IMPL_MUTEX_INITIALIZER 0 #define _GLIBCXX_IMPL_MUTEX_INITIALIZER 0
typedef int __mutex_t; typedef int __mutex_t;
/** @brief Mock mutex interface. */
template <int _Unused=0> /** @brief Mock mutex interface. */
class __mutex { template<int _Unused=0>
class __mutex
{
public: public:
static __mutex_t __global_lock; static __mutex_t __global_lock;
static void __lock(__mutex_t& __m) {} static void __lock(__mutex_t& __m) { }
static void __unlock(__mutex_t& __m) {} static void __unlock(__mutex_t& __m) { }
}; };
#endif #endif
template <int _Unused> template<int _Unused>
__mutex_t __mutex<_Unused>::__global_lock = _GLIBCXX_IMPL_MUTEX_INITIALIZER; __mutex_t __mutex<_Unused>::__global_lock = _GLIBCXX_IMPL_MUTEX_INITIALIZER;
/** @brief Representation of a warning. */ /** @brief Representation of a warning. */
struct __warning_data struct __warning_data
{ {
float __magnitude; float __magnitude;
__stack_t __context; __stack_t __context;
const char* __warning_id; const char* __warning_id;
...@@ -104,119 +107,116 @@ struct __warning_data ...@@ -104,119 +107,116 @@ struct __warning_data
__warning_data(float __m, __stack_t __c, const char* __id, __warning_data(float __m, __stack_t __c, const char* __id,
const char* __msg); const char* __msg);
bool operator>(const struct __warning_data& other) const; bool operator>(const struct __warning_data& other) const;
}; };
inline __warning_data::__warning_data() inline __warning_data::__warning_data()
: __magnitude(0.0), __context(NULL), __warning_id(NULL), : __magnitude(0.0), __context(NULL), __warning_id(NULL),
__warning_message(NULL) __warning_message(NULL)
{ { }
}
inline __warning_data::__warning_data(float __m, __stack_t __c, inline __warning_data::__warning_data(float __m, __stack_t __c,
const char* __id, const char* __msg) const char* __id, const char* __msg)
: __magnitude(__m), __context(__c), __warning_id(__id), : __magnitude(__m), __context(__c), __warning_id(__id),
__warning_message(__msg) __warning_message(__msg)
{ { }
}
inline bool
inline bool __warning_data::operator>(const struct __warning_data& other) const __warning_data::operator>(const struct __warning_data& other) const
{ { return __magnitude > other.__magnitude; }
return __magnitude > other.__magnitude;
} typedef std::_GLIBCXX_STD_PR::vector<__warning_data> __warning_vector_t;
typedef std::_GLIBCXX_STD_PR::vector<__warning_data> __warning_vector_t; // Defined in profiler_<diagnostic name>.h.
class __trace_hash_func;
// Defined in profiler_<diagnostic name>.h. class __trace_hashtable_size;
class __trace_hash_func; class __trace_map2umap;
class __trace_hashtable_size; class __trace_vector_size;
class __trace_map2umap; class __trace_vector_to_list;
class __trace_vector_size; void __trace_vector_size_init();
class __trace_vector_to_list; void __trace_hashtable_size_init();
void __trace_vector_size_init(); void __trace_hash_func_init();
void __trace_hashtable_size_init(); void __trace_vector_to_list_init();
void __trace_hash_func_init(); void __trace_map_to_unordered_map_init();
void __trace_vector_to_list_init(); void __trace_vector_size_report(FILE*, __warning_vector_t&);
void __trace_map_to_unordered_map_init(); void __trace_hashtable_size_report(FILE*, __warning_vector_t&);
void __trace_vector_size_report(FILE*, __warning_vector_t&); void __trace_hash_func_report(FILE*, __warning_vector_t&);
void __trace_hashtable_size_report(FILE*, __warning_vector_t&); void __trace_vector_to_list_report(FILE*, __warning_vector_t&);
void __trace_hash_func_report(FILE*, __warning_vector_t&); void __trace_map_to_unordered_map_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
// Utility functions. __max(size_t __a, size_t __b) { return __a >= __b ? __a : __b; }
inline size_t __max(size_t __a, size_t __b)
{ inline size_t
return __a >= __b ? __a : __b; __min(size_t __a, size_t __b) { return __a <= __b ? __a : __b; }
}
/** @brief Storage for diagnostic table entries. Has only static fields. */
inline size_t __min(size_t __a, size_t __b) template<int _Unused=0>
{ class __tables
return __a <= __b ? __a : __b; {
}
/** @brief Storage for diagnostic table entries. Has only static fields. */
template <int _Unused=0>
class __tables
{
public: public:
static __trace_hash_func* _S_hash_func; static __trace_hash_func* _S_hash_func;
static __trace_hashtable_size* _S_hashtable_size; static __trace_hashtable_size* _S_hashtable_size;
static __trace_map2umap* _S_map2umap; static __trace_map2umap* _S_map2umap;
static __trace_vector_size* _S_vector_size; static __trace_vector_size* _S_vector_size;
static __trace_vector_to_list* _S_vector_to_list; static __trace_vector_to_list* _S_vector_to_list;
}; };
template <int _Unused> template<int _Unused>
__trace_hash_func* __tables<_Unused>::_S_hash_func = NULL; __trace_hash_func* __tables<_Unused>::_S_hash_func = NULL;
template <int _Unused>
__trace_hashtable_size* __tables<_Unused>::_S_hashtable_size = NULL; template<int _Unused>
template <int _Unused> __trace_hashtable_size* __tables<_Unused>::_S_hashtable_size = NULL;
__trace_map2umap* __tables<_Unused>::_S_map2umap = NULL;
template <int _Unused> template<int _Unused>
__trace_vector_size* __tables<_Unused>::_S_vector_size = NULL; __trace_map2umap* __tables<_Unused>::_S_map2umap = NULL;
template <int _Unused>
__trace_vector_to_list* __tables<_Unused>::_S_vector_to_list = NULL; template<int _Unused>
__trace_vector_size* __tables<_Unused>::_S_vector_size = NULL;
/** @brief Storage for user defined parameters. Has only static fields. */
template <int _Unused=0> template<int _Unused>
class __settings { __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: public:
static const char* _S_trace_file_name; static const char* _S_trace_file_name;
static size_t _S_max_warn_count; static size_t _S_max_warn_count;
static size_t _S_max_stack_depth; static size_t _S_max_stack_depth;
static size_t _S_max_mem; static size_t _S_max_mem;
}; };
template <int _Unused> template<int _Unused>
const char* __settings<_Unused>::_S_trace_file_name = const char* __settings<_Unused>::_S_trace_file_name =
_GLIBCXX_PROFILE_TRACE_PATH_ROOT; _GLIBCXX_PROFILE_TRACE_PATH_ROOT;
template <int _Unused>
size_t __settings<_Unused>::_S_max_warn_count = template<int _Unused>
size_t __settings<_Unused>::_S_max_warn_count =
_GLIBCXX_PROFILE_MAX_WARN_COUNT; _GLIBCXX_PROFILE_MAX_WARN_COUNT;
template <int _Unused>
size_t __settings<_Unused>::_S_max_stack_depth = template<int _Unused>
size_t __settings<_Unused>::_S_max_stack_depth =
_GLIBCXX_PROFILE_MAX_STACK_DEPTH; _GLIBCXX_PROFILE_MAX_STACK_DEPTH;
template <int _Unused>
size_t __settings<_Unused>::_S_max_mem = template<int _Unused>
size_t __settings<_Unused>::_S_max_mem =
_GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC; _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC;
inline size_t __stack_max_depth() inline size_t
{ __stack_max_depth() { return __settings<0>::_S_max_stack_depth; }
return __settings<0>::_S_max_stack_depth;
}
inline size_t __max_mem() inline size_t
{ __max_mem() { return __settings<0>::_S_max_mem; }
return __settings<0>::_S_max_mem;
}
/** @brief Base class for all trace producers. */ /** @brief Base class for all trace producers. */
template <typename __object_info, typename __stack_info> template<typename __object_info, typename __stack_info>
class __trace_base class __trace_base
{ {
public: public:
__trace_base(); __trace_base();
virtual ~__trace_base() {} virtual ~__trace_base() { }
void __add_object(__object_t object, __object_info __info); void __add_object(__object_t object, __object_info __info);
__object_info* __get_object_info(__object_t __object); __object_info* __get_object_info(__object_t __object);
...@@ -242,112 +242,119 @@ class __trace_base ...@@ -242,112 +242,119 @@ class __trace_base
protected: protected:
const char* __id; const char* __id;
}; };
template <typename __object_info, typename __stack_info> template<typename __object_info, typename __stack_info>
void __trace_base<__object_info, __stack_info>::__collect_warnings( void
__warning_vector_t& warnings) __trace_base<__object_info, __stack_info>::__collect_warnings(__warning_vector_t& warnings)
{ {
typename __stack_table_t::iterator __i = __stack_table.begin(); typename __stack_table_t::iterator __i = __stack_table.begin();
for ( ; __i != __stack_table.end(); ++__i ) for ( ; __i != __stack_table.end(); ++__i)
{ {
warnings.push_back(__warning_data((*__i).second.__magnitude(), warnings.push_back(__warning_data((*__i).second.__magnitude(),
(*__i).first, (*__i).first,
__id, __id,
(*__i).second.__advice())); (*__i).second.__advice()));
} }
} }
template <typename __object_info, typename __stack_info> template<typename __object_info, typename __stack_info>
void __trace_base<__object_info, __stack_info>::__lock_object_table() void
{ __trace_base<__object_info, __stack_info>::__lock_object_table()
__mutex<0>::__lock(this->__object_table_lock); { __mutex<0>::__lock(this->__object_table_lock); }
}
template <typename __object_info, typename __stack_info> template<typename __object_info, typename __stack_info>
void __trace_base<__object_info, __stack_info>::__lock_stack_table() void
{ __trace_base<__object_info, __stack_info>::__lock_stack_table()
__mutex<0>::__lock(this->__stack_table_lock); { __mutex<0>::__lock(this->__stack_table_lock); }
}
template <typename __object_info, typename __stack_info> template<typename __object_info, typename __stack_info>
void __trace_base<__object_info, __stack_info>::__unlock_object_table() void __trace_base<__object_info, __stack_info>::__unlock_object_table()
{ { __mutex<0>::__unlock(this->__object_table_lock); }
__mutex<0>::__unlock(this->__object_table_lock);
}
template <typename __object_info, typename __stack_info> template<typename __object_info, typename __stack_info>
void __trace_base<__object_info, __stack_info>::__unlock_stack_table() void __trace_base<__object_info, __stack_info>::__unlock_stack_table()
{ { __mutex<0>::__unlock(this->__stack_table_lock); }
__mutex<0>::__unlock(this->__stack_table_lock);
}
template <typename __object_info, typename __stack_info> template<typename __object_info, typename __stack_info>
__trace_base<__object_info, __stack_info>::__trace_base() __trace_base<__object_info, __stack_info>::__trace_base()
{ {
// Do not pick the initial size too large, as we don't know which diagnostics // Do not pick the initial size too large, as we don't know which
// are more active. // diagnostics are more active.
__object_table.rehash(10000); __object_table.rehash(10000);
__stack_table.rehash(10000); __stack_table.rehash(10000);
__stack_table_byte_size = 0; __stack_table_byte_size = 0;
__id = NULL; __id = NULL;
__object_table_lock = __stack_table_lock = _GLIBCXX_IMPL_MUTEX_INITIALIZER; __stack_table_lock = _GLIBCXX_IMPL_MUTEX_INITIALIZER;
} __object_table_lock = __stack_table_lock;
}
template <typename __object_info, typename __stack_info> template<typename __object_info, typename __stack_info>
void __trace_base<__object_info, __stack_info>::__add_object( void
__object_t __object, __object_info __info) __trace_base<__object_info, __stack_info>::__add_object(__object_t __object, __object_info __info)
{ {
typedef typename __object_table_t::value_type value_type;
if (__max_mem() == 0 if (__max_mem() == 0
|| __object_table.size() * sizeof(__object_info) <= __max_mem()) { || __object_table.size() * sizeof(__object_info) <= __max_mem())
{
__lock_object_table(); __lock_object_table();
__object_table.insert( __object_table.insert(value_type(__object, __info));
typename __object_table_t::value_type(__object, __info));
__unlock_object_table(); __unlock_object_table();
} }
} }
template <typename __object_info, typename __stack_info> template<typename __object_info, typename __stack_info>
__object_info* __trace_base<__object_info, __stack_info>::__get_object_info( __object_info*
__object_t __object) __trace_base<__object_info, __stack_info>::__get_object_info(__object_t __object)
{ {
// XXX: Revisit this to see if we can decrease mutex spans. // XXX: Revisit this to see if we can decrease mutex spans.
// Without this mutex, the object table could be rehashed during an // Without this mutex, the object table could be rehashed during an
// insertion on another thread, which could result in a segfault. // insertion on another thread, which could result in a segfault.
__lock_object_table(); __lock_object_table();
typename __object_table_t::iterator __object_it = typename __object_table_t::iterator __object_it =
__object_table.find(__object); __object_table.find(__object);
if (__object_it == __object_table.end()){
if (__object_it == __object_table.end())
{
__unlock_object_table(); __unlock_object_table();
return NULL; return NULL;
} else { }
else
{
__unlock_object_table(); __unlock_object_table();
return &__object_it->second; return &__object_it->second;
} }
} }
template <typename __object_info, typename __stack_info> template<typename __object_info, typename __stack_info>
void __trace_base<__object_info, __stack_info>::__retire_object( void
__object_t __object) __trace_base<__object_info, __stack_info>::__retire_object(__object_t __object)
{ {
__lock_object_table(); __lock_object_table();
__lock_stack_table(); __lock_stack_table();
typename __object_table_t::iterator __object_it = typename __object_table_t::iterator __object_it =
__object_table.find(__object); __object_table.find(__object);
if (__object_it != __object_table.end()){
if (__object_it != __object_table.end())
{
const __object_info& __info = __object_it->second; const __object_info& __info = __object_it->second;
const __stack_t& __stack = __info.__stack(); const __stack_t& __stack = __info.__stack();
typename __stack_table_t::iterator __stack_it = typename __stack_table_t::iterator __stack_it =
__stack_table.find(__stack); __stack_table.find(__stack);
if (__stack_it == __stack_table.end()) {
if (__stack_it == __stack_table.end())
{
// First occurence of this call context. // First occurence of this call context.
if (__max_mem() == 0 || __stack_table_byte_size < __max_mem()) { if (__max_mem() == 0 || __stack_table_byte_size < __max_mem())
{
__stack_table_byte_size += __stack_table_byte_size +=
(sizeof(__instruction_address_t) * __size(__stack) (sizeof(__instruction_address_t) * __size(__stack)
+ sizeof(__stack) + sizeof(__stack_info)); + sizeof(__stack) + sizeof(__stack_info));
__stack_table.insert(make_pair(__stack, __stack_info(__info))); __stack_table.insert(make_pair(__stack, __stack_info(__info)));
} }
} else { }
else
{
// Merge object info into info summary for this call context. // Merge object info into info summary for this call context.
__stack_it->second.__merge(__info); __stack_it->second.__merge(__info);
delete __stack; delete __stack;
...@@ -356,15 +363,18 @@ void __trace_base<__object_info, __stack_info>::__retire_object( ...@@ -356,15 +363,18 @@ void __trace_base<__object_info, __stack_info>::__retire_object(
} }
__unlock_stack_table(); __unlock_stack_table();
__unlock_object_table(); __unlock_object_table();
} }
template <typename __object_info, typename __stack_info> template<typename __object_info, typename __stack_info>
void __trace_base<__object_info, __stack_info>::__write(FILE* __f) void
{ __trace_base<__object_info, __stack_info>::__write(FILE* __f)
{
typename __stack_table_t::iterator __it; typename __stack_table_t::iterator __it;
for (__it = __stack_table.begin(); __it != __stack_table.end(); __it++) { for (__it = __stack_table.begin(); __it != __stack_table.end(); __it++)
if (__it->second.__is_valid()) { {
if (__it->second.__is_valid())
{
fprintf(__f, __id); fprintf(__f, __id);
fprintf(__f, "|"); fprintf(__f, "|");
__gnu_profile::__write(__f, __it->first); __gnu_profile::__write(__f, __it->first);
...@@ -372,69 +382,83 @@ void __trace_base<__object_info, __stack_info>::__write(FILE* __f) ...@@ -372,69 +382,83 @@ void __trace_base<__object_info, __stack_info>::__write(FILE* __f)
__it->second.__write(__f); __it->second.__write(__f);
} }
} }
} }
inline size_t __env_to_size_t(const char* __env_var, size_t __default_value) inline size_t
{ __env_to_size_t(const char* __env_var, size_t __default_value)
{
char* __env_value = getenv(__env_var); char* __env_value = getenv(__env_var);
if (__env_value) { if (__env_value)
{
long int __converted_value = strtol(__env_value, NULL, 10); long int __converted_value = strtol(__env_value, NULL, 10);
if (errno || __converted_value < 0) { if (errno || __converted_value < 0)
fprintf(stderr, "Bad value for environment variable '%s'.", __env_var); {
fprintf(stderr, "Bad value for environment variable '%s'.",
__env_var);
abort(); abort();
} else { }
else
{
return static_cast<size_t>(__converted_value); return static_cast<size_t>(__converted_value);
} }
} else { }
else
{
return __default_value; return __default_value;
} }
} }
inline void __set_max_stack_trace_depth() 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 = __env_to_size_t(_GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR, __settings<0>::_S_max_stack_depth);
__settings<0>::_S_max_stack_depth); }
}
inline void __set_max_mem() 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); __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) inline int
{ __log_magnitude(float f)
{
const float log_base = 10.0; const float log_base = 10.0;
int result = 0; int result = 0;
int sign = 1; int sign = 1;
if (f < 0) { if (f < 0)
{
f = -f; f = -f;
sign = -1; sign = -1;
} }
while (f > log_base) { while (f > log_base)
{
++result; ++result;
f /= 10.0; f /= 10.0;
} }
return sign * result; return sign * result;
} }
struct __warn struct __warn
{ {
FILE* __file; FILE* __file;
__warn(FILE* __f) { __file = __f; } __warn(FILE* __f) { __file = __f; }
void operator() (const __warning_data& __info) void operator() (const __warning_data& __info)
{ {
fprintf(__file, __info.__warning_id); fprintf(__file, __info.__warning_id);
fprintf(__file, ": improvement = %d", __log_magnitude(__info.__magnitude)); fprintf(__file, ": improvement = %d",
__log_magnitude(__info.__magnitude));
fprintf(__file, ": call stack = "); fprintf(__file, ": call stack = ");
__gnu_profile::__write(__file, __info.__context); __gnu_profile::__write(__file, __info.__context);
fprintf(__file, ": advice = %s\n", __info.__warning_message); fprintf(__file, ": advice = %s\n", __info.__warning_message);
} }
}; };
inline FILE* __open_output_file(const char* extension) inline FILE*
{ __open_output_file(const char* extension)
{
// The path is made of _S_trace_file_name + "." + extension. // The path is made of _S_trace_file_name + "." + extension.
size_t root_len = strlen(__settings<0>::_S_trace_file_name); size_t root_len = strlen(__settings<0>::_S_trace_file_name);
size_t ext_len = strlen(extension); size_t ext_len = strlen(extension);
...@@ -444,23 +468,25 @@ inline FILE* __open_output_file(const char* extension) ...@@ -444,23 +468,25 @@ inline FILE* __open_output_file(const char* extension)
*(file_name + root_len) = '.'; *(file_name + root_len) = '.';
memcpy(file_name + root_len + 1, extension, ext_len + 1); memcpy(file_name + root_len + 1, extension, ext_len + 1);
FILE* out_file = fopen(file_name, "w"); FILE* out_file = fopen(file_name, "w");
if (out_file) { if (out_file)
return out_file; return out_file;
} else { else
{
fprintf(stderr, "Could not open trace file '%s'.", file_name); fprintf(stderr, "Could not open trace file '%s'.", file_name);
abort(); abort();
} }
} }
/** @brief Final report method, registered with "atexit". /** @brief Final report method, registered with "atexit".
* *
* This can also be called directly by user code, including signal handlers. * This can also be called directly by user code, including signal handlers.
* It is protected against deadlocks by the reentrance guard in profiler.h. * It is protected against deadlocks by the reentrance guard in profiler.h.
* However, when called from a signal handler that triggers while within * However, when called from a signal handler that triggers while within
* __gnu_profile (under the guarded zone), no output will be produced. * __gnu_profile (under the guarded zone), no output will be produced.
*/ */
inline void __report(void) inline void
{ __report(void)
{
__mutex<0>::__lock(__mutex<0>::__global_lock); __mutex<0>::__lock(__mutex<0>::__global_lock);
__warning_vector_t __warnings; __warning_vector_t __warnings;
...@@ -474,7 +500,9 @@ inline void __report(void) ...@@ -474,7 +500,9 @@ inline void __report(void)
fclose(__raw_file); fclose(__raw_file);
// Sort data by magnitude. // Sort data by magnitude.
// XXX: instead of sorting, should collect only top N for better performance.
// XXX: instead of sorting, should collect only top N for better
// performance.
size_t __cutoff = __min(__settings<0>::_S_max_warn_count, size_t __cutoff = __min(__settings<0>::_S_max_warn_count,
__warnings.size()); __warnings.size());
...@@ -487,45 +515,47 @@ inline void __report(void) ...@@ -487,45 +515,47 @@ inline void __report(void)
fclose(__warn_file); fclose(__warn_file);
__mutex<0>::__unlock(__mutex<0>::__global_lock); __mutex<0>::__unlock(__mutex<0>::__global_lock);
} }
inline void __set_trace_path() inline void
{ __set_trace_path()
{
char* __env_trace_file_name = getenv(_GLIBCXX_PROFILE_TRACE_ENV_VAR); char* __env_trace_file_name = getenv(_GLIBCXX_PROFILE_TRACE_ENV_VAR);
if (__env_trace_file_name) { if (__env_trace_file_name)
__settings<0>::_S_trace_file_name = __env_trace_file_name; __settings<0>::_S_trace_file_name = __env_trace_file_name;
}
// Make sure early that we can create the trace file. // Make sure early that we can create the trace file.
fclose(__open_output_file("txt")); fclose(__open_output_file("txt"));
} }
inline void __set_max_warn_count() inline void
{ __set_max_warn_count()
char* __env_max_warn_count_str = getenv( {
_GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR); char* __env_max_warn_count_str = getenv(_GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR);
if (__env_max_warn_count_str) { if (__env_max_warn_count_str)
__settings<0>::_S_max_warn_count = static_cast<size_t>( {
atoi(__env_max_warn_count_str)); int i = atoi(__env_max_warn_count_str);
__settings<0>::_S_max_warn_count = static_cast<size_t>(i);
}
} }
}
inline void __profcxx_init_unconditional() inline void
{ __profcxx_init_unconditional()
{
__mutex<0>::__lock(__mutex<0>::__global_lock); __mutex<0>::__lock(__mutex<0>::__global_lock);
__set_max_warn_count(); __set_max_warn_count();
if (__is_invalid()) { if (__is_invalid())
{
if (__settings<0>::_S_max_warn_count == 0) { if (__settings<0>::_S_max_warn_count == 0)
{
__turn_off(); __turn_off();
}
} else { else
{
__set_max_stack_trace_depth(); __set_max_stack_trace_depth();
__set_max_mem(); __set_max_mem();
__set_trace_path(); __set_trace_path();
...@@ -539,26 +569,24 @@ inline void __profcxx_init_unconditional() ...@@ -539,26 +569,24 @@ inline void __profcxx_init_unconditional()
atexit(__report); atexit(__report);
__turn_on(); __turn_on();
} }
} }
__mutex<0>::__unlock(__mutex<0>::__global_lock); __mutex<0>::__unlock(__mutex<0>::__global_lock);
} }
/** @brief This function must be called by each instrumentation point. /** @brief This function must be called by each instrumentation point.
* *
* The common path is inlined fully. * The common path is inlined fully.
*/ */
inline bool __profcxx_init(void) inline bool
{ __profcxx_init(void)
if (__is_invalid()) { {
if (__is_invalid())
__profcxx_init_unconditional(); __profcxx_init_unconditional();
}
return __is_on(); return __is_on();
} }
} // namespace __gnu_profile } // namespace __gnu_profile
#endif /* PROFCXX_PROFILER_TRACE_H__ */ #endif /* _GLIBCXX_PROFILE_PROFILER_TRACE_H */
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
// Written by Lixia Liu and Silvius Rus. // Written by Lixia Liu and Silvius Rus.
#ifndef PROFCXX_PROFILER_VECTOR_SIZE_H__ #ifndef _GLIBCXX_PROFILE_PROFILER_VECTOR_SIZE_H
#define PROFCXX_PROFILER_VECTOR_SIZE_H__ 1 #define _GLIBCXX_PROFILE_PROFILER_VECTOR_SIZE_H 1
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <cstdlib> #include <cstdlib>
...@@ -54,59 +54,49 @@ ...@@ -54,59 +54,49 @@
namespace __gnu_profile namespace __gnu_profile
{ {
/** @brief Hashtable size instrumentation trace producer. */
/** @brief Hashtable size instrumentation trace producer. */ class __trace_vector_size : public __trace_container_size
class __trace_vector_size : public __trace_container_size {
{
public: public:
__trace_vector_size() : __trace_container_size() { __id = "vector-size"; } __trace_vector_size() : __trace_container_size() { __id = "vector-size"; }
}; };
////////////////////////////////////////////////////////////////////////////// // Initialization and report.
// Initialization and report. inline void
////////////////////////////////////////////////////////////////////////////// __trace_vector_size_init()
{ __tables<0>::_S_vector_size = new __trace_vector_size(); }
inline void __trace_vector_size_init()
{ inline void
__tables<0>::_S_vector_size = new __trace_vector_size(); __trace_vector_size_report(FILE* __f, __warning_vector_t& __warnings)
} {
if (__tables<0>::_S_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->__collect_warnings(__warnings);
__tables<0>::_S_vector_size->__write(__f); __tables<0>::_S_vector_size->__write(__f);
} }
} }
//////////////////////////////////////////////////////////////////////////////
// Implementations of instrumentation hooks.
//////////////////////////////////////////////////////////////////////////////
inline void __trace_vector_size_construct(const void* __obj, size_t __num) // Implementations of instrumentation hooks.
{ inline void
__trace_vector_size_construct(const void* __obj, size_t __num)
{
if (!__profcxx_init()) return; if (!__profcxx_init()) return;
__tables<0>::_S_vector_size->__insert(__obj, __get_stack(), __num); __tables<0>::_S_vector_size->__insert(__obj, __get_stack(), __num);
} }
inline void __trace_vector_size_destruct(const void* __obj, size_t __num, inline void
size_t __inum) __trace_vector_size_destruct(const void* __obj, size_t __num, size_t __inum)
{ {
if (!__profcxx_init()) return; if (!__profcxx_init()) return;
__tables<0>::_S_vector_size->__destruct(__obj, __num, __inum); __tables<0>::_S_vector_size->__destruct(__obj, __num, __inum);
} }
inline void __trace_vector_size_resize(const void* __obj, size_t __from, inline void
size_t __to) __trace_vector_size_resize(const void* __obj, size_t __from, size_t __to)
{ {
if (!__profcxx_init()) return; if (!__profcxx_init()) return;
__tables<0>::_S_vector_size->__resize(__obj, __from, __to); __tables<0>::_S_vector_size->__resize(__obj, __from, __to);
} }
} // namespace __gnu_profile } // namespace __gnu_profile
#endif /* PROFCXX_PROFILER_VECTOR_SIZE_H__ */ #endif /* _GLIBCXX_PROFILE_PROFILER_VECTOR_SIZE_H */
...@@ -34,8 +34,8 @@ ...@@ -34,8 +34,8 @@
// Written by Lixia Liu and Silvius Rus. // Written by Lixia Liu and Silvius Rus.
#ifndef PROFCXX_PROFILER_VECTOR_TO_LIST_H__ #ifndef _GLIBCXX_PROFILE_PROFILER_VECTOR_TO_LIST_H
#define PROFCXX_PROFILER_VECTOR_TO_LIST_H__ 1 #define _GLIBCXX_PROFILE_PROFILER_VECTOR_TO_LIST_H 1
#ifdef __GXX_EXPERIMENTAL_CXX0X__ #ifdef __GXX_EXPERIMENTAL_CXX0X__
#include <cstdio> #include <cstdio>
...@@ -52,19 +52,21 @@ ...@@ -52,19 +52,21 @@
namespace __gnu_profile namespace __gnu_profile
{ {
/** @brief A vector-to-list instrumentation line in the object table. */
/** @brief A vector-to-list instrumentation line in the object table. */ class __vector2list_info: public __object_info_base
class __vector2list_info: public __object_info_base {
{
public: public:
__vector2list_info() __vector2list_info()
:_M_shift_count(0), _M_iterate(0), _M_resize(0), _M_list_cost(0), :_M_shift_count(0), _M_iterate(0), _M_resize(0), _M_list_cost(0),
_M_vector_cost(0), _M_valid(true) {} _M_vector_cost(0), _M_valid(true) { }
__vector2list_info(__stack_t __stack) __vector2list_info(__stack_t __stack)
: __object_info_base(__stack), _M_shift_count(0), _M_iterate(0), : __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) {} _M_resize(0), _M_list_cost(0), _M_vector_cost(0), _M_valid(true) { }
virtual ~__vector2list_info() {}
virtual ~__vector2list_info() { }
__vector2list_info(const __vector2list_info& __o); __vector2list_info(const __vector2list_info& __o);
void __merge(const __vector2list_info& __o); void __merge(const __vector2list_info& __o);
void __write(FILE* __f) const; void __write(FILE* __f) const;
float __magnitude() const { return _M_vector_cost - _M_list_cost; } float __magnitude() const { return _M_vector_cost - _M_list_cost; }
...@@ -83,63 +85,64 @@ class __vector2list_info: public __object_info_base ...@@ -83,63 +85,64 @@ class __vector2list_info: public __object_info_base
void __opr_iterate(size_t __num) { _M_iterate += __num; } void __opr_iterate(size_t __num) { _M_iterate += __num; }
void __resize(size_t __from, size_t __to); void __resize(size_t __from, size_t __to);
private: private:
size_t _M_shift_count; size_t _M_shift_count;
size_t _M_iterate; size_t _M_iterate;
size_t _M_resize; size_t _M_resize;
float _M_list_cost; float _M_list_cost;
float _M_vector_cost; float _M_vector_cost;
bool _M_valid; bool _M_valid;
}; };
inline __vector2list_info::__vector2list_info(const __vector2list_info& __o) inline __vector2list_info::__vector2list_info(const __vector2list_info& __o)
: __object_info_base(__o) : __object_info_base(__o)
{ {
_M_shift_count = __o._M_shift_count; _M_shift_count = __o._M_shift_count;
_M_iterate = __o._M_iterate; _M_iterate = __o._M_iterate;
_M_vector_cost = __o._M_vector_cost; _M_vector_cost = __o._M_vector_cost;
_M_list_cost = __o._M_list_cost; _M_list_cost = __o._M_list_cost;
_M_valid = __o._M_valid; _M_valid = __o._M_valid;
_M_resize = __o._M_resize; _M_resize = __o._M_resize;
} }
inline void __vector2list_info::__merge(const __vector2list_info& __o) inline void
{ __vector2list_info::__merge(const __vector2list_info& __o)
{
_M_shift_count += __o._M_shift_count; _M_shift_count += __o._M_shift_count;
_M_iterate += __o._M_iterate; _M_iterate += __o._M_iterate;
_M_vector_cost += __o._M_vector_cost; _M_vector_cost += __o._M_vector_cost;
_M_list_cost += __o._M_list_cost; _M_list_cost += __o._M_list_cost;
_M_valid &= __o._M_valid; _M_valid &= __o._M_valid;
_M_resize += __o._M_resize; _M_resize += __o._M_resize;
} }
inline void __vector2list_info::__opr_insert(size_t __pos, size_t __num) inline void
{ __vector2list_info::__opr_insert(size_t __pos, size_t __num)
_M_shift_count += __num - __pos; { _M_shift_count += __num - __pos; }
}
inline void __vector2list_info::__resize(size_t __from, size_t __to) inline void
{ __vector2list_info::__resize(size_t __from, size_t __to)
_M_resize += __from; { _M_resize += __from; }
}
/** @brief A vector-to-list instrumentation line in the stack table. */ /** @brief A vector-to-list instrumentation line in the stack table. */
class __vector2list_stack_info: public __vector2list_info { class __vector2list_stack_info: public __vector2list_info
{
public: public:
__vector2list_stack_info(const __vector2list_info& __o) __vector2list_stack_info(const __vector2list_info& __o)
: __vector2list_info(__o) {} : __vector2list_info(__o) { }
}; };
/** @brief Vector-to-list instrumentation producer. */ /** @brief Vector-to-list instrumentation producer. */
class __trace_vector_to_list class __trace_vector_to_list
: public __trace_base<__vector2list_info, __vector2list_stack_info> : public __trace_base<__vector2list_info, __vector2list_stack_info>
{ {
public: public:
__trace_vector_to_list(); __trace_vector_to_list();
~__trace_vector_to_list() {} ~__trace_vector_to_list() { }
// Insert a new node at construct with object, callstack and initial size. // Insert a new node at construct with object, callstack and initial size.
void __insert(__object_t __obj, __stack_t __stack); void __insert(__object_t __obj, __stack_t __stack);
// Call at destruction/clean to set container final size. // Call at destruction/clean to set container final size.
void __destruct(const void* __obj); void __destruct(const void* __obj);
...@@ -153,52 +156,46 @@ class __trace_vector_to_list ...@@ -153,52 +156,46 @@ class __trace_vector_to_list
void __resize(const void* __obj, size_t __from, size_t __to); void __resize(const void* __obj, size_t __from, size_t __to);
float __vector_cost(size_t __shift, size_t __iterate, size_t __resize); float __vector_cost(size_t __shift, size_t __iterate, size_t __resize);
float __list_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() inline __trace_vector_to_list::__trace_vector_to_list()
: __trace_base<__vector2list_info, __vector2list_stack_info>() : __trace_base<__vector2list_info, __vector2list_stack_info>()
{ { __id = "vector-to-list"; }
__id = "vector-to-list";
}
inline void __trace_vector_to_list::__insert(__object_t __obj, inline void
__stack_t __stack) __trace_vector_to_list::__insert(__object_t __obj, __stack_t __stack)
{ { __add_object(__obj, __vector2list_info(__stack)); }
__add_object(__obj, __vector2list_info(__stack));
}
inline void __vector2list_info::__write(FILE* __f) const 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); 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 model.
// - Cost per shift: 1 // Vector operation cost:
// - Cost per access: 1 // - Cost per shift: 1
// - Cost per resize: 1 // - Cost per access: 1
// List operation cost: // - Cost per resize: 1
// - Cost per shift: 0 // List operation cost:
// - Cost per access: 10 // - Cost per shift: 0
// - Cost per resize: 0 // - Cost per access: 10
// - Cost per resize: 0
inline float __trace_vector_to_list::__vector_cost(size_t __shift, // XXX: get this from the cost model database instead.
size_t __iterate, inline float
__trace_vector_to_list::__vector_cost(size_t __shift, size_t __iterate,
size_t __resize) size_t __resize)
{ { return __shift * 1 + __iterate * 1 + __resize * 1; }
return __shift * 1 + __iterate * 1 + __resize * 1;
}
inline float __trace_vector_to_list::__list_cost(size_t __shift, inline float
size_t __iterate, __trace_vector_to_list::__list_cost(size_t __shift, size_t __iterate,
size_t __resize) size_t __resize)
{ { return __shift * 0 + __iterate * 10 + __resize * 0; }
return __shift * 0 + __iterate * 10 + __resize * 0;
}
inline void __trace_vector_to_list::__destruct(const void* __obj) inline void
{ __trace_vector_to_list::__destruct(const void* __obj)
{
if (!__is_on()) if (!__is_on())
return; return;
...@@ -214,105 +211,99 @@ inline void __trace_vector_to_list::__destruct(const void* __obj) ...@@ -214,105 +211,99 @@ inline void __trace_vector_to_list::__destruct(const void* __obj)
__res->__set_list_cost(__lc); __res->__set_list_cost(__lc);
__retire_object(__obj); __retire_object(__obj);
} }
inline void __trace_vector_to_list::__opr_insert(const void* __obj, inline void
size_t __pos, size_t __num) __trace_vector_to_list::__opr_insert(const void* __obj, size_t __pos,
{ size_t __num)
{
__vector2list_info* __res = __get_object_info(__obj); __vector2list_info* __res = __get_object_info(__obj);
if (__res) if (__res)
__res->__opr_insert(__pos, __num); __res->__opr_insert(__pos, __num);
} }
inline void __trace_vector_to_list::__opr_iterate(const void* __obj, inline void
size_t __num) __trace_vector_to_list::__opr_iterate(const void* __obj, size_t __num)
{ {
__vector2list_info* __res = __get_object_info(__obj); __vector2list_info* __res = __get_object_info(__obj);
if (__res) if (__res)
__res->__opr_iterate(__num); __res->__opr_iterate(__num);
} }
inline void __trace_vector_to_list::__invalid_operator(const void* __obj) inline void
{ __trace_vector_to_list::__invalid_operator(const void* __obj)
{
__vector2list_info* __res = __get_object_info(__obj); __vector2list_info* __res = __get_object_info(__obj);
if (__res) if (__res)
__res->__set_invalid(); __res->__set_invalid();
} }
inline void __trace_vector_to_list::__resize(const void* __obj, size_t __from, inline void
__trace_vector_to_list::__resize(const void* __obj, size_t __from,
size_t __to) size_t __to)
{ {
__vector2list_info* __res = __get_object_info(__obj); __vector2list_info* __res = __get_object_info(__obj);
if (__res) if (__res)
__res->__resize(__from, __to); __res->__resize(__from, __to);
} }
//////////////////////////////////////////////////////////////////////////////
// Initialization and report.
//////////////////////////////////////////////////////////////////////////////
inline void __trace_vector_to_list_init() // Initialization and report.
{ inline void
__tables<0>::_S_vector_to_list = new __trace_vector_to_list(); __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, inline void
__warning_vector_t& __warnings) __trace_vector_to_list_report(FILE* __f, __warning_vector_t& __warnings)
{ {
if (__tables<0>::_S_vector_to_list) { if (__tables<0>::_S_vector_to_list)
{
__tables<0>::_S_vector_to_list->__collect_warnings(__warnings); __tables<0>::_S_vector_to_list->__collect_warnings(__warnings);
__tables<0>::_S_vector_to_list->__write(__f); __tables<0>::_S_vector_to_list->__write(__f);
} }
} }
//////////////////////////////////////////////////////////////////////////////
// Implementations of instrumentation hooks.
//////////////////////////////////////////////////////////////////////////////
inline void __trace_vector_to_list_construct(const void* __obj) // Implementations of instrumentation hooks.
{ inline void
__trace_vector_to_list_construct(const void* __obj)
{
if (!__profcxx_init()) return; if (!__profcxx_init()) return;
__tables<0>::_S_vector_to_list->__insert(__obj, __get_stack()); __tables<0>::_S_vector_to_list->__insert(__obj, __get_stack());
} }
inline void __trace_vector_to_list_destruct(const void* __obj) inline void
{ __trace_vector_to_list_destruct(const void* __obj)
{
if (!__profcxx_init()) return; if (!__profcxx_init()) return;
__tables<0>::_S_vector_to_list->__destruct(__obj); __tables<0>::_S_vector_to_list->__destruct(__obj);
} }
inline void __trace_vector_to_list_insert(const void* __obj, inline void
size_t __pos, size_t __num) __trace_vector_to_list_insert(const void* __obj, size_t __pos, size_t __num)
{ {
if (!__profcxx_init()) return; if (!__profcxx_init()) return;
__tables<0>::_S_vector_to_list->__opr_insert(__obj, __pos, __num); __tables<0>::_S_vector_to_list->__opr_insert(__obj, __pos, __num);
} }
inline void __trace_vector_to_list_iterate(const void* __obj, size_t __num) inline void
{ __trace_vector_to_list_iterate(const void* __obj, size_t __num)
{
if (!__profcxx_init()) return; if (!__profcxx_init()) return;
__tables<0>::_S_vector_to_list->__opr_iterate(__obj, __num); __tables<0>::_S_vector_to_list->__opr_iterate(__obj, __num);
} }
inline void __trace_vector_to_list_invalid_operator(const void* __obj) inline void
{ __trace_vector_to_list_invalid_operator(const void* __obj)
{
if (!__profcxx_init()) return; if (!__profcxx_init()) return;
__tables<0>::_S_vector_to_list->__invalid_operator(__obj); __tables<0>::_S_vector_to_list->__invalid_operator(__obj);
} }
inline void __trace_vector_to_list_resize(const void* __obj, inline void
size_t __from, size_t __to) __trace_vector_to_list_resize(const void* __obj, size_t __from, size_t __to)
{ {
if (!__profcxx_init()) return; if (!__profcxx_init()) return;
__tables<0>::_S_vector_to_list->__resize(__obj, __from, __to); __tables<0>::_S_vector_to_list->__resize(__obj, __from, __to);
} }
} // namespace __gnu_profile } // namespace __gnu_profile
#endif /* PROFCXX_PROFILER_VECTOR_TO_LIST_H__ */ #endif /* _GLIBCXX_PROFILE_PROFILER_VECTOR_TO_LIST_H */
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