diff options
Diffstat (limited to 'libstdc++-v3/include/profile/impl')
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler.h | 402 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler_algos.h | 111 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler_container_size.h | 215 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler_hash_func.h | 174 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler_hashtable_size.h | 98 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler_list_to_slist.h | 208 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler_list_to_vector.h | 324 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h | 290 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler_node.h | 166 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler_state.h | 66 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler_trace.h | 659 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler_vector_size.h | 97 | ||||
-rw-r--r-- | libstdc++-v3/include/profile/impl/profiler_vector_to_list.h | 347 |
13 files changed, 3157 insertions, 0 deletions
diff --git a/libstdc++-v3/include/profile/impl/profiler.h b/libstdc++-v3/include/profile/impl/profiler.h new file mode 100644 index 000000000..49785bbee --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler.h @@ -0,0 +1,402 @@ +// -*- C++ -*- +// +// Copyright (C) 2009, 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @file profile/impl/profiler.h + * @brief Interface of the profiling runtime library. + */ + +// Written by Lixia Liu and Silvius Rus. + +#ifndef _GLIBCXX_PROFILE_PROFILER_H +#define _GLIBCXX_PROFILE_PROFILER_H 1 + +#include <bits/c++config.h> + +// Mechanism to define data with inline linkage. +#define _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__type, __name) \ + inline __type& \ + __get_##__name() \ + { \ + static __type __name; \ + return __name; \ + } +#define _GLIBCXX_PROFILE_DEFINE_DATA(__type, __name, __initial_value...) \ + inline __type& __get_##__name() { \ + static __type __name(__initial_value); \ + return __name; \ + } +#define _GLIBCXX_PROFILE_DATA(__name) \ + __get_##__name() + +namespace __gnu_profile +{ + /** @brief Reentrance guard. + * + * Mechanism to protect all __gnu_profile operations against recursion, + * multithreaded and exception reentrance. + */ + struct __reentrance_guard + { + static bool + __get_in() + { + if (__inside() == true) + return false; + else + { + __inside() = true; + return true; + } + } + + static bool& + __inside() + { + static __thread bool _S_inside(false); + return _S_inside; + } + + __reentrance_guard() { } + ~__reentrance_guard() { __inside() = false; } + }; + +#define _GLIBCXX_PROFILE_REENTRANCE_GUARD(__x...) \ + { \ + if (__gnu_profile::__reentrance_guard::__get_in()) \ + { \ + __gnu_profile::__reentrance_guard __get_out; \ + __x; \ + } \ + } + + // Forward declarations of implementation functions. + // Don't use any __gnu_profile:: in user code. + // Instead, use the __profcxx... macros, which offer guarded access. + bool __turn_on(); + bool __turn_off(); + bool __is_invalid(); + bool __is_on(); + bool __is_off(); + void __report(void); + void __trace_hashtable_size_resize(const void*, std::size_t, std::size_t); + void __trace_hashtable_size_destruct(const void*, std::size_t, std::size_t); + void __trace_hashtable_size_construct(const void*, std::size_t); + void __trace_vector_size_resize(const void*, std::size_t, std::size_t); + void __trace_vector_size_destruct(const void*, std::size_t, std::size_t); + void __trace_vector_size_construct(const void*, std::size_t); + void __trace_hash_func_destruct(const void*, std::size_t, std::size_t, + std::size_t); + void __trace_hash_func_construct(const void*); + void __trace_vector_to_list_destruct(const void*); + void __trace_vector_to_list_construct(const void*); + void __trace_vector_to_list_insert(const void*, std::size_t, std::size_t); + void __trace_vector_to_list_iterate(const void*, std::size_t); + void __trace_vector_to_list_invalid_operator(const void*); + void __trace_vector_to_list_resize(const void*, std::size_t, std::size_t); + void __trace_vector_to_list_find(const void*, std::size_t); + + void __trace_list_to_slist_destruct(const void*); + void __trace_list_to_slist_construct(const void*); + void __trace_list_to_slist_rewind(const void*); + void __trace_list_to_slist_operation(const void*); + + void __trace_list_to_vector_destruct(const void*); + void __trace_list_to_vector_construct(const void*); + void __trace_list_to_vector_insert(const void*, std::size_t, std::size_t); + void __trace_list_to_vector_iterate(const void*, std::size_t); + void __trace_list_to_vector_invalid_operator(const void*); + void __trace_list_to_vector_resize(const void*, std::size_t, std::size_t); + + void __trace_list_to_set_destruct(const void*); + void __trace_list_to_set_construct(const void*); + void __trace_list_to_set_insert(const void*, std::size_t, std::size_t); + void __trace_list_to_set_iterate(const void*, std::size_t); + void __trace_list_to_set_invalid_operator(const void*); + void __trace_list_to_set_find(const void*, std::size_t); + + void __trace_map_to_unordered_map_construct(const void*); + void __trace_map_to_unordered_map_invalidate(const void*); + void __trace_map_to_unordered_map_insert(const void*, std::size_t, + std::size_t); + void __trace_map_to_unordered_map_erase(const void*, std::size_t, + std::size_t); + void __trace_map_to_unordered_map_iterate(const void*, std::size_t); + void __trace_map_to_unordered_map_find(const void*, std::size_t); + void __trace_map_to_unordered_map_destruct(const void*); +} // namespace __gnu_profile + +// Master switch turns on all diagnostics that are not explicitly turned off. +#ifdef _GLIBCXX_PROFILE +#ifndef _GLIBCXX_PROFILE_NO_HASHTABLE_TOO_SMALL +#define _GLIBCXX_PROFILE_HASHTABLE_TOO_SMALL +#endif +#ifndef _GLIBCXX_PROFILE_NO_HASHTABLE_TOO_LARGE +#define _GLIBCXX_PROFILE_HASHTABLE_TOO_LARGE +#endif +#ifndef _GLIBCXX_PROFILE_NO_VECTOR_TOO_SMALL +#define _GLIBCXX_PROFILE_VECTOR_TOO_SMALL +#endif +#ifndef _GLIBCXX_PROFILE_NO_VECTOR_TOO_LARGE +#define _GLIBCXX_PROFILE_VECTOR_TOO_LARGE +#endif +#ifndef _GLIBCXX_PROFILE_NO_INEFFICIENT_HASH +#define _GLIBCXX_PROFILE_INEFFICIENT_HASH +#endif +#ifndef _GLIBCXX_PROFILE_NO_VECTOR_TO_LIST +#define _GLIBCXX_PROFILE_VECTOR_TO_LIST +#endif +#ifndef _GLIBCXX_PROFILE_NO_LIST_TO_SLIST +#define _GLIBCXX_PROFILE_LIST_TO_SLIST +#endif +#ifndef _GLIBCXX_PROFILE_NO_LIST_TO_VECTOR +#define _GLIBCXX_PROFILE_LIST_TO_VECTOR +#endif +#ifndef _GLIBCXX_PROFILE_NO_MAP_TO_UNORDERED_MAP +#define _GLIBCXX_PROFILE_MAP_TO_UNORDERED_MAP +#endif +#endif + +// Expose global management routines to user code. +#ifdef _GLIBCXX_PROFILE +#define __profcxx_report() \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__report()) +#define __profcxx_turn_on() \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__turn_on()) +#define __profcxx_turn_off() \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__turn_off()) +#define __profcxx_is_invalid() \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_invalid()) +#define __profcxx_is_on() \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_on()) +#define __profcxx__is_off() \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD(__gnu_profile::__is_off()) +#else +#define __profcxx_report() +#define __profcxx_turn_on() +#define __profcxx_turn_off() +#define __profcxx_is_invalid() +#define __profcxx_is_on() +#define __profcxx_is_off() +#endif + +// Turn on/off instrumentation for HASHTABLE_TOO_SMALL and HASHTABLE_TOO_LARGE. +#if (defined(_GLIBCXX_PROFILE_HASHTABLE_TOO_SMALL) \ + || defined(_GLIBCXX_PROFILE_HASHTABLE_TOO_LARGE)) +#define __profcxx_hashtable_resize(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_hashtable_size_resize(__x)) +#define __profcxx_hashtable_destruct(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_hashtable_size_destruct(__x)) +#define __profcxx_hashtable_construct(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_hashtable_size_construct(__x)) +#else +#define __profcxx_hashtable_resize(__x...) +#define __profcxx_hashtable_destruct(__x...) +#define __profcxx_hashtable_construct(__x...) +#endif + +// Turn on/off instrumentation for VECTOR_TOO_SMALL and VECTOR_TOO_LARGE. +#if (defined(_GLIBCXX_PROFILE_VECTOR_TOO_SMALL) \ + || defined(_GLIBCXX_PROFILE_VECTOR_TOO_LARGE)) +#define __profcxx_vector_resize(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_vector_size_resize(__x)) +#define __profcxx_vector_destruct(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_vector_size_destruct(__x)) +#define __profcxx_vector_construct(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_vector_size_construct(__x)) +#else +#define __profcxx_vector_resize(__x...) +#define __profcxx_vector_destruct(__x...) +#define __profcxx_vector_construct(__x...) +#endif + +// Turn on/off instrumentation for INEFFICIENT_HASH. +#if defined(_GLIBCXX_PROFILE_INEFFICIENT_HASH) +#define __profcxx_hashtable_construct2(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_hash_func_construct(__x)) +#define __profcxx_hashtable_destruct2(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_hash_func_destruct(__x)) +#else +#define __profcxx_hashtable_destruct2(__x...) +#define __profcxx_hashtable_construct2(__x...) +#endif + +// Turn on/off instrumentation for VECTOR_TO_LIST. +#if defined(_GLIBCXX_PROFILE_VECTOR_TO_LIST) +#define __profcxx_vector_construct2(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_vector_to_list_construct(__x)) +#define __profcxx_vector_destruct2(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_vector_to_list_destruct(__x)) +#define __profcxx_vector_insert(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_vector_to_list_insert(__x)) +#define __profcxx_vector_iterate(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_vector_to_list_iterate(__x)) +#define __profcxx_vector_invalid_operator(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_vector_to_list_invalid_operator(__x)) +#define __profcxx_vector_resize2(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_vector_to_list_resize(__x)) +#define __profcxx_vector_find(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_vector_to_list_find(__x)) +#else +#define __profcxx_vector_destruct2(__x...) +#define __profcxx_vector_construct2(__x...) +#define __profcxx_vector_insert(__x...) +#define __profcxx_vector_iterate(__x...) +#define __profcxx_vector_invalid_operator(__x...) +#define __profcxx_vector_resize2(__x...) +#define __profcxx_vector_find(__x...) +#endif + +// Turn on/off instrumentation for LIST_TO_VECTOR. +#if defined(_GLIBCXX_PROFILE_LIST_TO_VECTOR) +#define __profcxx_list_construct2(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_list_to_vector_construct(__x)) +#define __profcxx_list_destruct2(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_list_to_vector_destruct(__x)) +#define __profcxx_list_insert(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_list_to_vector_insert(__x)) +#define __profcxx_list_iterate(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_list_to_vector_iterate(__x)) +#define __profcxx_list_invalid_operator(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_list_to_vector_invalid_operator(__x)) +#else +#define __profcxx_list_destruct2(__x...) +#define __profcxx_list_construct2(__x...) +#define __profcxx_list_insert(__x...) +#define __profcxx_list_iterate(__x...) +#define __profcxx_list_invalid_operator(__x...) +#endif + +// Turn on/off instrumentation for LIST_TO_SLIST. +#if defined(_GLIBCXX_PROFILE_LIST_TO_SLIST) +#define __profcxx_list_rewind(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_list_to_slist_rewind(__x)) +#define __profcxx_list_operation(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_list_to_slist_operation(__x)) +#define __profcxx_list_destruct(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_list_to_slist_destruct(__x)) +#define __profcxx_list_construct(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_list_to_slist_construct(__x)) +#else +#define __profcxx_list_rewind(__x...) +#define __profcxx_list_operation(__x...) +#define __profcxx_list_destruct(__x...) +#define __profcxx_list_construct(__x...) +#endif + +// Turn on/off instrumentation for MAP_TO_UNORDERED_MAP. +#if defined(_GLIBCXX_PROFILE_MAP_TO_UNORDERED_MAP) +#define __profcxx_map_to_unordered_map_construct(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_map_to_unordered_map_construct(__x)) +#define __profcxx_map_to_unordered_map_destruct(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_map_to_unordered_map_destruct(__x)) +#define __profcxx_map_to_unordered_map_insert(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_map_to_unordered_map_insert(__x)) +#define __profcxx_map_to_unordered_map_erase(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_map_to_unordered_map_erase(__x)) +#define __profcxx_map_to_unordered_map_iterate(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_map_to_unordered_map_iterate(__x)) +#define __profcxx_map_to_unordered_map_invalidate(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_map_to_unordered_map_invalidate(__x)) +#define __profcxx_map_to_unordered_map_find(__x...) \ + _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ + __gnu_profile::__trace_map_to_unordered_map_find(__x)) +#else +#define __profcxx_map_to_unordered_map_construct(__x...) \ + +#define __profcxx_map_to_unordered_map_destruct(__x...) +#define __profcxx_map_to_unordered_map_insert(__x...) +#define __profcxx_map_to_unordered_map_erase(__x...) +#define __profcxx_map_to_unordered_map_iterate(__x...) +#define __profcxx_map_to_unordered_map_invalidate(__x...) +#define __profcxx_map_to_unordered_map_find(__x...) +#endif + +// Set default values for compile-time customizable variables. +#ifndef _GLIBCXX_PROFILE_TRACE_PATH_ROOT +#define _GLIBCXX_PROFILE_TRACE_PATH_ROOT "libstdcxx-profile" +#endif +#ifndef _GLIBCXX_PROFILE_TRACE_ENV_VAR +#define _GLIBCXX_PROFILE_TRACE_ENV_VAR "_GLIBCXX_PROFILE_TRACE_PATH_ROOT" +#endif +#ifndef _GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR +#define _GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR \ + "_GLIBCXX_PROFILE_MAX_WARN_COUNT" +#endif +#ifndef _GLIBCXX_PROFILE_MAX_WARN_COUNT +#define _GLIBCXX_PROFILE_MAX_WARN_COUNT 10 +#endif +#ifndef _GLIBCXX_PROFILE_MAX_STACK_DEPTH +#define _GLIBCXX_PROFILE_MAX_STACK_DEPTH 32 +#endif +#ifndef _GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR +#define _GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR \ + "_GLIBCXX_PROFILE_MAX_STACK_DEPTH" +#endif +#ifndef _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC +#define _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC (1 << 28) +#endif +#ifndef _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR +#define _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR \ + "_GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC" +#endif + +// Instrumentation hook implementations. +#include "profile/impl/profiler_hash_func.h" +#include "profile/impl/profiler_hashtable_size.h" +#include "profile/impl/profiler_map_to_unordered_map.h" +#include "profile/impl/profiler_vector_size.h" +#include "profile/impl/profiler_vector_to_list.h" +#include "profile/impl/profiler_list_to_slist.h" +#include "profile/impl/profiler_list_to_vector.h" + +#endif // _GLIBCXX_PROFILE_PROFILER_H diff --git a/libstdc++-v3/include/profile/impl/profiler_algos.h b/libstdc++-v3/include/profile/impl/profiler_algos.h new file mode 100644 index 000000000..977afaa80 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_algos.h @@ -0,0 +1,111 @@ +// -*- C++ -*- +// +// Copyright (C) 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @file profile/impl/profiler_algos.h + * @brief Algorithms used by the profile extension. + * + * This file is needed to avoid including <algorithm> or <bits/stl_algo.h>. + * Including those files would result in recursive includes. + * These implementations are oversimplified. In general, efficiency may be + * sacrificed to minimize maintenance overhead. + */ + +#ifndef _GLIBCXX_PROFILE_PROFILER_ALGOS_H +#define _GLIBCXX_PROFILE_PROFILER_ALGOS_H 1 + +namespace __gnu_profile +{ + /* Helper for __top_n. Insert in sorted vector, but not beyond Nth elem. */ + template<typename _Container> + void + __insert_top_n(_Container& __output, + const typename _Container::value_type& __value, + typename _Container::size_type __n) + { + typename _Container::iterator __it = __output.begin(); + typename _Container::size_type __count = 0; + + // Skip up to N - 1 elements larger than VALUE. + // XXX: Could do binary search for random iterators. + while (true) + { + if (__count >= __n) + // VALUE is not in top N. + return; + + if (__it == __output.end()) + break; + + if (*__it < __value) + break; + + ++__it; + ++__count; + } + + __output.insert(__it, __value); + } + + /* Copy the top N elements in INPUT, sorted in reverse order, to OUTPUT. */ + template<typename _Container> + void + __top_n(const _Container& __input, _Container& __output, + typename _Container::size_type __n) + { + __output.clear(); + typename _Container::const_iterator __it; + for (__it = __input.begin(); __it != __input.end(); ++__it) + __insert_top_n(__output, *__it, __n); + } + + /* Simplified clone of std::for_each. */ + template<typename _InputIterator, typename _Function> + _Function + __for_each(_InputIterator __first, _InputIterator __last, _Function __f) + { + for (; __first != __last; ++__first) + __f(*__first); + return __f; + } + + /* Simplified clone of std::remove. */ + template<typename _ForwardIterator, typename _Tp> + _ForwardIterator + __remove(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __value) + { + if(__first == __last) + return __first; + _ForwardIterator __result = __first; + ++__first; + for(; __first != __last; ++__first) + if(!(*__first == __value)) + { + *__result = *__first; + ++__result; + } + return __result; + } +} // namespace __gnu_profile + +#endif /* _GLIBCXX_PROFILE_PROFILER_ALGOS_H */ diff --git a/libstdc++-v3/include/profile/impl/profiler_container_size.h b/libstdc++-v3/include/profile/impl/profiler_container_size.h new file mode 100644 index 000000000..26b2c72c2 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_container_size.h @@ -0,0 +1,215 @@ +// -*- C++ -*- +// +// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @file profile/impl/profiler_container_size.h + * @brief Diagnostics for container sizes. + */ + +// Written by Lixia Liu and Silvius Rus. + +#ifndef _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H +#define _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H 1 + +#include <sstream> + +#include "profile/impl/profiler.h" +#include "profile/impl/profiler_node.h" +#include "profile/impl/profiler_trace.h" + +namespace __gnu_profile +{ + /** @brief A container size instrumentation line in the object table. */ + class __container_size_info + : public __object_info_base + { + public: + __container_size_info() + : _M_init(0), _M_max(0), _M_min(0), _M_total(0), _M_item_min(0), + _M_item_max(0), _M_item_total(0), _M_count(0), _M_resize(0), _M_cost(0) + { } + + __container_size_info(const __container_size_info& __o) + : __object_info_base(__o), _M_init(__o._M_init), _M_max(__o._M_max), + _M_min(__o._M_min), _M_total(__o._M_total), + _M_item_min(__o._M_item_min), _M_item_max(__o._M_item_max), + _M_item_total(__o._M_item_total), _M_count(__o._M_count), + _M_resize(__o._M_resize), _M_cost(__o._M_cost) + { } + + __container_size_info(__stack_t __stack, std::size_t __num) + : __object_info_base(__stack), _M_init(__num), _M_max(__num), + _M_min(0), _M_total(0), _M_item_min(0), _M_item_max(0), + _M_item_total(0), _M_count(0), _M_resize(0), _M_cost(0) + { } + + virtual ~__container_size_info() { } + + void + __write(FILE* __f) const + { + std::fprintf(__f, "%Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu\n", + _M_init, _M_count, _M_cost, _M_resize, _M_min, _M_max, + _M_total, _M_item_min, _M_item_max, _M_item_total); + } + + float + __magnitude() const + { return static_cast<float>(_M_cost); } + + std::string + __advice() const + { + std::stringstream __message; + if (_M_init < _M_item_max) + __message << "change initial container size from " << _M_init + << " to " << _M_item_max; + return __message.str(); + } + + void + __merge(const __container_size_info& __o) + { + _M_init = std::max(_M_init, __o._M_init); + _M_max = std::max(_M_max, __o._M_max); + _M_item_max = std::max(_M_item_max, __o._M_item_max); + _M_min = std::min(_M_min, __o._M_min); + _M_item_min = std::min(_M_item_min, __o._M_item_min); + _M_total += __o._M_total; + _M_item_total += __o._M_item_total; + _M_count += __o._M_count; + _M_cost += __o._M_cost; + _M_resize += __o._M_resize; + } + + // Call if a container is destructed or cleaned. + void + __destruct(std::size_t __num, std::size_t __inum) + { + _M_max = std::max(_M_max, __num); + _M_item_max = std::max(_M_item_max, __inum); + if (_M_min == 0) + { + _M_min = __num; + _M_item_min = __inum; + } + else + { + _M_min = std::min(_M_min, __num); + _M_item_min = std::min(_M_item_min, __inum); + } + _M_total += __num; + _M_item_total += __inum; + _M_count += 1; + } + + // Estimate the cost of resize/rehash. + float + __resize_cost(std::size_t __from, std::size_t) + { return __from; } + + // Call if container is resized. + void + __resize(std::size_t __from, std::size_t __to) + { + _M_cost += this->__resize_cost(__from, __to); + _M_resize += 1; + _M_max = std::max(_M_max, __to); + } + + private: + std::size_t _M_init; + std::size_t _M_max; // range of # buckets + std::size_t _M_min; + std::size_t _M_total; + std::size_t _M_item_min; // range of # items + std::size_t _M_item_max; + std::size_t _M_item_total; + std::size_t _M_count; + std::size_t _M_resize; + std::size_t _M_cost; + }; + + + /** @brief A container size instrumentation line in the stack table. */ + class __container_size_stack_info + : public __container_size_info + { + public: + __container_size_stack_info(const __container_size_info& __o) + : __container_size_info(__o) { } + }; + + + /** @brief Container size instrumentation trace producer. */ + class __trace_container_size + : public __trace_base<__container_size_info, __container_size_stack_info> + { + public: + ~__trace_container_size() { } + + __trace_container_size() + : __trace_base<__container_size_info, __container_size_stack_info>() { }; + + // Insert a new node at construct with object, callstack and initial size. + void + __insert(const __object_t __obj, __stack_t __stack, std::size_t __num) + { __add_object(__obj, __container_size_info(__stack, __num)); } + + // XXX Undefined? + void + __construct(const void* __obj, std::size_t __inum); + + // Call at destruction/clean to set container final size. + void + __destruct(const void* __obj, std::size_t __num, std::size_t __inum) + { + if (!__is_on()) + return; + + __object_t __obj_handle = static_cast<__object_t>(__obj); + + __container_size_info* __object_info = __get_object_info(__obj_handle); + if (!__object_info) + return; + + __object_info->__destruct(__num, __inum); + __retire_object(__obj_handle); + } + + // Call at resize to set resize/cost information. + void + __resize(const void* __obj, int __from, int __to) + { + if (!__is_on()) + return; + + __container_size_info* __object_info = __get_object_info(__obj); + if (!__object_info) + return; + + __object_info->__resize(__from, __to); + } + }; + +} // namespace __gnu_profile +#endif /* _GLIBCXX_PROFILE_PROFILER_CONTAINER_SIZE_H */ diff --git a/libstdc++-v3/include/profile/impl/profiler_hash_func.h b/libstdc++-v3/include/profile/impl/profiler_hash_func.h new file mode 100644 index 000000000..7ff11cd03 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_hash_func.h @@ -0,0 +1,174 @@ +// -*- C++ -*- +// +// Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @file profile/impl/profiler_hash_func.h + * @brief Data structures to represent profiling traces. + */ + +// Written by Lixia Liu and Silvius Rus. + +#ifndef _GLIBCXX_PROFILE_PROFILER_HASH_FUNC_H +#define _GLIBCXX_PROFILE_PROFILER_HASH_FUNC_H 1 + +#include "profile/impl/profiler.h" +#include "profile/impl/profiler_node.h" +#include "profile/impl/profiler_trace.h" + +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) + : __object_info_base(__o), _M_longest_chain(__o._M_longest_chain), + _M_accesses(__o._M_accesses), _M_hops(__o._M_hops) { } + + __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) + { + _M_longest_chain = std::max(_M_longest_chain, __o._M_longest_chain); + _M_accesses += __o._M_accesses; + _M_hops += __o._M_hops; + } + + void + __destruct(std::size_t __chain, std::size_t __accesses, + std::size_t __hops) + { + _M_longest_chain = std::max(_M_longest_chain, __chain); + _M_accesses += __accesses; + _M_hops += __hops; + } + + void + __write(FILE* __f) const + { std::fprintf(__f, "%Zu %Zu %Zu\n", _M_hops, + _M_accesses, _M_longest_chain); } + + float + __magnitude() const + { return static_cast<float>(_M_hops); } + + std::string + __advice() const + { return "change hash function"; } + + private: + std::size_t _M_longest_chain; + std::size_t _M_accesses; + std::size_t _M_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_base<__hashfunc_info, __hashfunc_stack_info>() + { __id = "hash-distr"; } + + ~__trace_hash_func() {} + + // Insert a new node at construct with object, callstack and initial size. + void + __insert(__object_t __obj, __stack_t __stack) + { __add_object(__obj, __hashfunc_info(__stack)); } + + // Call at destruction/clean to set container final size. + void + __destruct(const void* __obj, std::size_t __chain, + std::size_t __accesses, std::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 + __trace_hash_func_init() + { _GLIBCXX_PROFILE_DATA(_S_hash_func) = new __trace_hash_func(); } + + 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 + __trace_hash_func_construct(const void* __obj) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_hash_func)->__insert(__obj, __get_stack()); + } + + inline void + __trace_hash_func_destruct(const void* __obj, std::size_t __chain, + std::size_t __accesses, std::size_t __hops) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_hash_func)->__destruct(__obj, __chain, + __accesses, __hops); + } + +} // namespace __gnu_profile +#endif /* _GLIBCXX_PROFILE_PROFILER_HASH_FUNC_H */ diff --git a/libstdc++-v3/include/profile/impl/profiler_hashtable_size.h b/libstdc++-v3/include/profile/impl/profiler_hashtable_size.h new file mode 100644 index 000000000..8557a6073 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_hashtable_size.h @@ -0,0 +1,98 @@ +// -*- C++ -*- +// +// Copyright (C) 2009, 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @file profile/impl/profiler_hashtable_size.h + * @brief Collection of hashtable size traces. + */ + +// Written by Lixia Liu and Silvius Rus. + +#ifndef _GLIBCXX_PROFILE_PROFILER_HASHTABLE_SIZE_H +#define _GLIBCXX_PROFILE_PROFILER_HASHTABLE_SIZE_H 1 + +#include "profile/impl/profiler.h" +#include "profile/impl/profiler_node.h" +#include "profile/impl/profiler_trace.h" +#include "profile/impl/profiler_state.h" +#include "profile/impl/profiler_container_size.h" + +namespace __gnu_profile +{ + /** @brief Hashtable size instrumentation trace producer. */ + class __trace_hashtable_size + : public __trace_container_size + { + public: + __trace_hashtable_size() + : __trace_container_size() + { __id = "hashtable-size"; } + }; + + inline void + __trace_hashtable_size_init() + { _GLIBCXX_PROFILE_DATA(_S_hashtable_size) = new __trace_hashtable_size(); } + + 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 + __trace_hashtable_size_construct(const void* __obj, std::size_t __num) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_hashtable_size)->__insert(__obj, __get_stack(), + __num); + } + + inline void + __trace_hashtable_size_destruct(const void* __obj, std::size_t __num, + std::size_t __inum) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_hashtable_size)->__destruct(__obj, __num, __inum); + } + + inline void + __trace_hashtable_size_resize(const void* __obj, std::size_t __from, + std::size_t __to) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_hashtable_size)->__resize(__obj, __from, __to); + } + +} // namespace __gnu_profile + +#endif /* _GLIBCXX_PROFILE_PROFILER_HASHTABLE_SIZE_H */ diff --git a/libstdc++-v3/include/profile/impl/profiler_list_to_slist.h b/libstdc++-v3/include/profile/impl/profiler_list_to_slist.h new file mode 100644 index 000000000..2195ccf90 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_list_to_slist.h @@ -0,0 +1,208 @@ +// -*- C++ -*- +// +// Copyright (C) 2009, 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @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 + +#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) + : __object_info_base(__stack), _M_rewind(false), _M_operations(0) { } + + 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&) { } + + void + __write(FILE* __f) const + { std::fprintf(__f, "%s\n", _M_rewind ? "invalid" : "valid"); } + + std::string + __advice() const + { return "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; + std::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) + { + __list2slist_info* __res = __get_object_info(__obj); + if (__res) + __res->__opr_rewind(); + } + + void + __record_operation(const void* __obj) + { + __list2slist_info* __res = __get_object_info(__obj); + if (__res) + __res->__record_operation(); + } + + void + __insert(const __object_t __obj, __stack_t __stack) + { __add_object(__obj, __list2slist_info(__stack)); } + + void + __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_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 */ diff --git a/libstdc++-v3/include/profile/impl/profiler_list_to_vector.h b/libstdc++-v3/include/profile/impl/profiler_list_to_vector.h new file mode 100644 index 000000000..b3840a747 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_list_to_vector.h @@ -0,0 +1,324 @@ +// -*- C++ -*- +// +// Copyright (C) 2009, 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @file profile/impl/profiler_list_to_vector.h + * @brief diagnostics for list to vector. + */ + +// Written by Changhee Jung. + +#ifndef _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H +#define _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H 1 + +#include <sstream> + +#include "profile/impl/profiler.h" +#include "profile/impl/profiler_node.h" +#include "profile/impl/profiler_trace.h" + +namespace __gnu_profile +{ + /** @brief A list-to-vector instrumentation line in the object table. */ + class __list2vector_info + : public __object_info_base + { + public: + __list2vector_info() + : _M_shift_count(0), _M_iterate(0), _M_resize(0), _M_list_cost(0), + _M_vector_cost(0), _M_valid(true), _M_max_size(0) { } + + __list2vector_info(__stack_t __stack) + : __object_info_base(__stack), _M_shift_count(0), _M_iterate(0), + _M_resize(0), _M_list_cost(0), _M_vector_cost(0), _M_valid(true), + _M_max_size(0) { } + + virtual ~__list2vector_info() { } + + __list2vector_info(const __list2vector_info& __o) + : __object_info_base(__o), _M_shift_count(__o._M_shift_count), + _M_iterate(__o._M_iterate), _M_resize(__o._M_resize), + _M_list_cost(__o._M_list_cost), _M_vector_cost(__o._M_vector_cost), + _M_valid(__o._M_valid), _M_max_size(__o._M_max_size) { } + + void + __merge(const __list2vector_info& __o) + { + _M_shift_count += __o._M_shift_count; + _M_iterate += __o._M_iterate; + _M_vector_cost += __o._M_vector_cost; + _M_list_cost += __o._M_list_cost; + _M_valid &= __o._M_valid; + _M_resize += __o._M_resize; + _M_max_size = std::max( _M_max_size, __o._M_max_size); + } + + void + __write(FILE* __f) const + { + std::fprintf(__f, "%Zu %Zu %Zu %.0f %.0f\n", _M_shift_count, + _M_resize, _M_iterate, _M_vector_cost, _M_list_cost); + } + + float + __magnitude() const + { return _M_list_cost - _M_vector_cost; } + + std::string + __advice() const + { + std::stringstream __sstream; + __sstream + << "change std::list to std::vector and its initial size from 0 to " + << _M_max_size; + return __sstream.str(); + } + + std::size_t + __shift_count() + { return _M_shift_count; } + + std::size_t + __iterate() + { return _M_iterate; } + + float + __list_cost() + { return _M_list_cost; } + + std::size_t + __resize() + { return _M_resize; } + + void + __set_list_cost(float __lc) + { _M_list_cost = __lc; } + + void + __set_vector_cost(float __vc) + { _M_vector_cost = __vc; } + + bool + __is_valid() + { return _M_valid; } + + void + __set_invalid() + { _M_valid = false; } + + void + __opr_insert(std::size_t __shift, std::size_t __size) + { + _M_shift_count += __shift; + _M_max_size = std::max(_M_max_size, __size); + } + + void + __opr_iterate(std::size_t __num) + { _M_iterate += __num;} + + void + __resize(std::size_t __from, std::size_t) + { _M_resize += __from; } + + private: + std::size_t _M_shift_count; + std::size_t _M_iterate; + std::size_t _M_resize; + float _M_list_cost; + float _M_vector_cost; + bool _M_valid; + std::size_t _M_max_size; + }; + + class __list2vector_stack_info + : public __list2vector_info + { + public: + __list2vector_stack_info(const __list2vector_info& __o) + : __list2vector_info(__o) {} + }; + + class __trace_list_to_vector + : public __trace_base<__list2vector_info, __list2vector_stack_info> + { + public: + __trace_list_to_vector() + : __trace_base<__list2vector_info, __list2vector_stack_info>() + { __id = "list-to-vector"; } + + ~__trace_list_to_vector() { } + + // Insert a new node at construct with object, callstack and initial size. + void + __insert(__object_t __obj, __stack_t __stack) + { __add_object(__obj, __list2vector_info(__stack)); } + + // Call at destruction/clean to set container final size. + void + __destruct(const void* __obj) + { + if (!__is_on()) + return; + + __list2vector_info* __res = __get_object_info(__obj); + if (!__res) + return; + + float __vc = __vector_cost(__res->__shift_count(), __res->__iterate()); + float __lc = __list_cost(__res->__shift_count(), __res->__iterate()); + __res->__set_vector_cost(__vc); + __res->__set_list_cost(__lc); + __retire_object(__obj); + } + + // Find the node in the live map. + __list2vector_info* __find(const void* __obj); + + // Collect cost of operations. + void + __opr_insert(const void* __obj, std::size_t __shift, std::size_t __size) + { + __list2vector_info* __res = __get_object_info(__obj); + if (__res) + __res->__opr_insert(__shift, __size); + } + + void + __opr_iterate(const void* __obj, std::size_t __num) + { + __list2vector_info* __res = __get_object_info(__obj); + if (__res) + __res->__opr_iterate(__num); + } + + void + __invalid_operator(const void* __obj) + { + __list2vector_info* __res = __get_object_info(__obj); + if (__res) + __res->__set_invalid(); + } + + void + __resize(const void* __obj, std::size_t __from, std::size_t __to) + { + __list2vector_info* __res = __get_object_info(__obj); + if (__res) + __res->__resize(__from, __to); + } + + float + __vector_cost(std::size_t __shift, std::size_t __iterate) + { + // The resulting vector will use a 'reserve' method. + return (__shift + * _GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor).__value + + __iterate + * _GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor).__value); + } + + float + __list_cost(std::size_t __shift, std::size_t __iterate) + { + return (__shift + * _GLIBCXX_PROFILE_DATA(__list_shift_cost_factor).__value + + __iterate + * _GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor).__value); + } + }; + + + inline void + __trace_list_to_vector_init() + { _GLIBCXX_PROFILE_DATA(_S_list_to_vector) = new __trace_list_to_vector(); } + + inline void + __trace_list_to_vector_report(FILE* __f, __warning_vector_t& __warnings) + { + if (_GLIBCXX_PROFILE_DATA(_S_list_to_vector)) + { + _GLIBCXX_PROFILE_DATA(_S_list_to_vector)-> + __collect_warnings(__warnings); + _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__write(__f); + } + } + + inline void + __trace_list_to_vector_construct(const void* __obj) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__insert(__obj, __get_stack()); + } + + inline void + __trace_list_to_vector_destruct(const void* __obj) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__destruct(__obj); + } + + inline void + __trace_list_to_vector_insert(const void* __obj, + std::size_t __shift, std::size_t __size) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__opr_insert(__obj, __shift, + __size); + } + + inline void + __trace_list_to_vector_iterate(const void* __obj, std::size_t __num = 1) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__opr_iterate(__obj, __num); + } + + inline void + __trace_list_to_vector_invalid_operator(const void* __obj) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__invalid_operator(__obj); + } + + inline void + __trace_list_to_vector_resize(const void* __obj, + std::size_t __from, std::size_t __to) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_list_to_vector)->__resize(__obj, __from, __to); + } + +} // namespace __gnu_profile +#endif /* _GLIBCXX_PROFILE_PROFILER_LIST_TO_VECTOR_H__ */ diff --git a/libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h b/libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h new file mode 100644 index 000000000..e232effe8 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h @@ -0,0 +1,290 @@ +// -*- C++ -*- +// +// Copyright (C) 2009, 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @file profile/impl/profiler_map_to_unordered_map.h + * @brief Diagnostics for map to unordered_map. + */ + +// Written by Silvius Rus. + +#ifndef _GLIBCXX_PROFILE_PROFILER_MAP_TO_UNORDERED_MAP_H +#define _GLIBCXX_PROFILE_PROFILER_MAP_TO_UNORDERED_MAP_H 1 + +#include "profile/impl/profiler.h" +#include "profile/impl/profiler_node.h" +#include "profile/impl/profiler_trace.h" + +namespace __gnu_profile +{ + inline int + __log2(std::size_t __size) + { + for (int __bit_count = sizeof(std::size_t) - 1; __bit_count >= 0; + -- __bit_count) + if ((2 << __bit_count) & __size) + return __bit_count; + return 0; + } + + inline float + __map_insert_cost(std::size_t __size) + { return (_GLIBCXX_PROFILE_DATA(__map_insert_cost_factor).__value + * static_cast<float>(__log2(__size))); } + + inline float + __map_erase_cost(std::size_t __size) + { return (_GLIBCXX_PROFILE_DATA(__map_erase_cost_factor).__value + * static_cast<float>(__log2(__size))); } + + inline float + __map_find_cost(std::size_t __size) + { return (_GLIBCXX_PROFILE_DATA(__map_find_cost_factor).__value + * static_cast<float>(__log2(__size))); } + + /** @brief A map-to-unordered_map instrumentation line in the + object table. */ + class __map2umap_info + : public __object_info_base + { + public: + __map2umap_info() + : _M_insert(0), _M_erase(0), _M_find(0), _M_iterate(0), + _M_umap_cost(0.0), _M_map_cost(0.0), _M_valid(true) { } + + __map2umap_info(__stack_t __stack) + : __object_info_base(__stack), _M_insert(0), _M_erase(0), _M_find(0), + _M_iterate(0), _M_umap_cost(0.0), _M_map_cost(0.0), _M_valid(true) { } + + virtual ~__map2umap_info() { } + + __map2umap_info(const __map2umap_info& __o) + : __object_info_base(__o), _M_insert(__o._M_insert), + _M_erase(__o._M_erase), _M_find(__o._M_find), + _M_iterate(__o._M_iterate), _M_umap_cost(__o._M_umap_cost), + _M_map_cost(__o._M_map_cost), _M_valid(__o._M_valid) { } + + void + __merge(const __map2umap_info& __o) + { + _M_insert += __o._M_insert; + _M_erase += __o._M_erase; + _M_find += __o._M_find; + _M_umap_cost += __o._M_umap_cost; + _M_map_cost += __o._M_map_cost; + _M_valid &= __o._M_valid; + } + + void + __write(FILE* __f) const + { + std::fprintf(__f, "%Zu %Zu %Zu %Zu %.0f %.0f %s\n", + _M_insert, _M_erase, _M_find, _M_iterate, _M_map_cost, + _M_umap_cost, _M_valid ? "valid" : "invalid"); + } + + float + __magnitude() const + { return _M_map_cost - _M_umap_cost; } + + std::string + __advice() const + { return "change std::map to std::unordered_map"; } + + void + __record_insert(std::size_t __size, std::size_t __count) + { + _M_insert += __count; + _M_map_cost += __count * __map_insert_cost(__size); + _M_umap_cost + += (__count + * _GLIBCXX_PROFILE_DATA(__umap_insert_cost_factor).__value); + } + + void + __record_erase(std::size_t __size, std::size_t __count) + { + _M_erase += __count; + _M_map_cost += __count * __map_erase_cost(__size); + _M_umap_cost + += (__count + * _GLIBCXX_PROFILE_DATA(__umap_erase_cost_factor).__value); + } + + void + __record_find(std::size_t __size) + { + _M_find += 1; + _M_map_cost += __map_find_cost(__size); + _M_umap_cost += _GLIBCXX_PROFILE_DATA(__umap_find_cost_factor).__value; + } + + void + __record_iterate(std::size_t __count) + { + _M_iterate += __count; + _M_map_cost + += (__count + * _GLIBCXX_PROFILE_DATA(__map_iterate_cost_factor).__value); + _M_umap_cost + += (__count + * _GLIBCXX_PROFILE_DATA(__umap_iterate_cost_factor).__value); + } + + void + __record_invalidate() + { _M_valid = false; } + + private: + std::size_t _M_insert; + std::size_t _M_erase; + std::size_t _M_find; + std::size_t _M_iterate; + float _M_umap_cost; + float _M_map_cost; + bool _M_valid; + }; + + + /** @brief A map-to-unordered_map instrumentation line in the + stack table. */ + class __map2umap_stack_info + : public __map2umap_info + { + public: + __map2umap_stack_info(const __map2umap_info& __o) + : __map2umap_info(__o) { } + }; + + /** @brief Map-to-unordered_map instrumentation producer. */ + class __trace_map2umap + : public __trace_base<__map2umap_info, __map2umap_stack_info> + { + public: + __trace_map2umap() + : __trace_base<__map2umap_info, __map2umap_stack_info>() + { __id = "map-to-unordered-map"; } + }; + + inline void + __trace_map_to_unordered_map_init() + { _GLIBCXX_PROFILE_DATA(_S_map2umap) = new __trace_map2umap(); } + + inline void + __trace_map_to_unordered_map_report(FILE* __f, + __warning_vector_t& __warnings) + { + if (_GLIBCXX_PROFILE_DATA(_S_map2umap)) + { + _GLIBCXX_PROFILE_DATA(_S_map2umap)->__collect_warnings(__warnings); + _GLIBCXX_PROFILE_DATA(_S_map2umap)->__write(__f); + } + } + + inline void + __trace_map_to_unordered_map_construct(const void* __obj) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_map2umap)-> + __add_object(__obj, __map2umap_info(__get_stack())); + } + + inline void + __trace_map_to_unordered_map_destruct(const void* __obj) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_map2umap)->__retire_object(__obj); + } + + inline void + __trace_map_to_unordered_map_insert(const void* __obj, + std::size_t __size, std::size_t __count) + { + if (!__profcxx_init()) + return; + + __map2umap_info* __info + = _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); + + if (__info) + __info->__record_insert(__size, __count); + } + + inline void + __trace_map_to_unordered_map_erase(const void* __obj, + std::size_t __size, std::size_t __count) + { + if (!__profcxx_init()) + return; + + __map2umap_info* __info + = _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); + + if (__info) + __info->__record_erase(__size, __count); + } + + inline void + __trace_map_to_unordered_map_find(const void* __obj, std::size_t __size) + { + if (!__profcxx_init()) + return; + + __map2umap_info* __info + = _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); + + if (__info) + __info->__record_find(__size); + } + + inline void + __trace_map_to_unordered_map_iterate(const void* __obj, std::size_t __count) + { + if (!__profcxx_init()) + return; + + __map2umap_info* __info + = _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); + + if (__info) + __info->__record_iterate(__count); + } + + inline void + __trace_map_to_unordered_map_invalidate(const void* __obj) + { + if (!__profcxx_init()) + return; + + __map2umap_info* __info + = _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); + + if (__info) + __info->__record_invalidate(); + } + +} // namespace __gnu_profile +#endif /* _GLIBCXX_PROFILE_PROFILER_MAP_TO_UNORDERED_MAP_H */ diff --git a/libstdc++-v3/include/profile/impl/profiler_node.h b/libstdc++-v3/include/profile/impl/profiler_node.h new file mode 100644 index 000000000..acc0cb5bf --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_node.h @@ -0,0 +1,166 @@ +// -*- C++ -*- +// +// Copyright (C) 2009, 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @file profile/impl/profiler_node.h + * @brief Data structures to represent a single profiling event. + */ + +// Written by Lixia Liu and Silvius Rus. + +#ifndef _GLIBCXX_PROFILE_PROFILER_NODE_H +#define _GLIBCXX_PROFILE_PROFILER_NODE_H 1 + +#include <cstdio> // FILE, fprintf + +#include <vector> +#if defined _GLIBCXX_HAVE_EXECINFO_H +#include <execinfo.h> +#endif + +namespace __gnu_profile +{ + typedef const void* __object_t; + typedef void* __instruction_address_t; + typedef std::_GLIBCXX_STD_C::vector<__instruction_address_t> __stack_npt; + typedef __stack_npt* __stack_t; + + std::size_t __stack_max_depth(); + + inline __stack_t + __get_stack() + { +#if defined _GLIBCXX_HAVE_EXECINFO_H + std::size_t __max_depth = __stack_max_depth(); + if (__max_depth == 0) + return 0; + __stack_npt __buffer(__max_depth); + int __depth = backtrace(&__buffer[0], __max_depth); + __stack_t __stack = new __stack_npt(__depth); + __builtin_memcpy(&(*__stack)[0], &__buffer[0], + __depth * sizeof(__object_t)); + return __stack; +#else + return 0; +#endif + } + + inline std::size_t + __size(__stack_t __stack) + { + if (!__stack) + return 0; + else + return __stack->size(); + } + + // XXX + inline void + __write(FILE* __f, __stack_t __stack) + { + if (!__stack) + return; + + __stack_npt::const_iterator __it; + for (__it = __stack->begin(); __it != __stack->end(); ++__it) + std::fprintf(__f, "%p ", *__it); + } + + /** @brief Hash function for summary trace using call stack as index. */ + class __stack_hash + { + public: + std::size_t + operator()(__stack_t __s) const + { + if (!__s) + return 0; + + __UINTPTR_TYPE__ __index = 0; + __stack_npt::const_iterator __it; + for (__it = __s->begin(); __it != __s->end(); ++__it) + __index += reinterpret_cast<__UINTPTR_TYPE__>(*__it); + return __index; + } + + bool operator() (__stack_t __stack1, __stack_t __stack2) const + { + if (!__stack1 && !__stack2) + return true; + if (!__stack1 || !__stack2) + return false; + if (__stack1->size() != __stack2->size()) + return false; + + std::size_t __byte_size + = __stack1->size() * sizeof(__stack_npt::value_type); + return __builtin_memcmp(&(*__stack1)[0], &(*__stack2)[0], + __byte_size) == 0; + } + }; + + + /** @brief Base class for a line in the object table. */ + class __object_info_base + { + public: + __object_info_base() { } + + __object_info_base(__stack_t __stack) + : _M_stack(__stack), _M_valid(true) { } + + __object_info_base(const __object_info_base& __o) + : _M_stack(__o._M_stack), _M_valid(__o._M_valid) { } + + 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; + }; + + + /** @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 +#endif /* _GLIBCXX_PROFILE_PROFILER_NODE_H */ diff --git a/libstdc++-v3/include/profile/impl/profiler_state.h b/libstdc++-v3/include/profile/impl/profiler_state.h new file mode 100644 index 000000000..1f39df548 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_state.h @@ -0,0 +1,66 @@ +// -*- C++ -*- +// +// Copyright (C) 2009, 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @file profile/impl/profiler_state.h + * @brief Global profiler state. + */ + +// Written by Lixia Liu and Silvius Rus. + +#ifndef _GLIBCXX_PROFILE_PROFILER_STATE_H +#define _GLIBCXX_PROFILE_PROFILER_STATE_H 1 + +namespace __gnu_profile +{ + enum __state_type { __ON, __OFF, __INVALID }; + + _GLIBCXX_PROFILE_DEFINE_DATA(__state_type, __state, __INVALID); + + inline bool + __turn(__state_type __s) + { return (_GLIBCXX_PROFILE_DATA(__state) + == __sync_val_compare_and_swap(&_GLIBCXX_PROFILE_DATA(__state), + __INVALID, __s)); } + + inline bool + __turn_on() + { return __turn(__ON); } + + inline bool + __turn_off() + { return __turn(__OFF); } + + inline bool + __is_on() + { return _GLIBCXX_PROFILE_DATA(__state) == __ON; } + + inline bool + __is_off() + { return _GLIBCXX_PROFILE_DATA(__state) == __OFF; } + + inline bool + __is_invalid() + { return _GLIBCXX_PROFILE_DATA(__state) == __INVALID; } + +} // end namespace __gnu_profile +#endif /* _GLIBCXX_PROFILE_PROFILER_STATE_H */ diff --git a/libstdc++-v3/include/profile/impl/profiler_trace.h b/libstdc++-v3/include/profile/impl/profiler_trace.h new file mode 100644 index 000000000..dadc5cac5 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_trace.h @@ -0,0 +1,659 @@ +// -*- C++ -*- +// +// Copyright (C) 2009, 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @file profile/impl/profiler_trace.h + * @brief Data structures to represent profiling traces. + */ + +// Written by Lixia Liu and Silvius Rus. + +#ifndef _GLIBCXX_PROFILE_PROFILER_TRACE_H +#define _GLIBCXX_PROFILE_PROFILER_TRACE_H 1 + +#include <cstdio> // fopen, fclose, fprintf, FILE +#include <cerrno> +#include <cstdlib> // atof, atoi, strtol, getenv, atexit, abort + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#define _GLIBCXX_IMPL_UNORDERED_MAP std::_GLIBCXX_STD_C::unordered_map +#include <unordered_map> +#else +#include <tr1/unordered_map> +#define _GLIBCXX_IMPL_UNORDERED_MAP std::tr1::unordered_map +#endif + +#include <ext/concurrence.h> +#include <fstream> +#include <string> +#include <utility> +#include <vector> + +#include "profile/impl/profiler_algos.h" +#include "profile/impl/profiler_state.h" +#include "profile/impl/profiler_node.h" + +namespace __gnu_profile +{ + /** @brief Internal environment. Values can be set one of two ways: + 1. In config file "var = value". The default config file path is + libstdcxx-profile.conf. + 2. By setting process environment variables. For instance, in a Bash + shell you can set the unit cost of iterating through a map like this: + export __map_iterate_cost_factor=5.0. + If a value is set both in the input file and through an environment + variable, the environment value takes precedence. */ + typedef _GLIBCXX_IMPL_UNORDERED_MAP<std::string, std::string> __env_t; + + _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__env_t, __env); + + /** @brief Master lock. */ + _GLIBCXX_PROFILE_DEFINE_UNINIT_DATA(__gnu_cxx::__mutex, __global_lock); + + /** @brief Representation of a warning. */ + struct __warning_data + { + float __magnitude; + __stack_t __context; + const char* __warning_id; + std::string __warning_message; + + __warning_data() + : __magnitude(0.0), __context(0), __warning_id(0) { } + + __warning_data(float __m, __stack_t __c, const char* __id, + const std::string& __msg) + : __magnitude(__m), __context(__c), __warning_id(__id), + __warning_message(__msg) { } + + bool + operator<(const __warning_data& __other) const + { return __magnitude < __other.__magnitude; } + }; + + typedef std::_GLIBCXX_STD_C::vector<__warning_data> __warning_vector_t; + + // Defined in profiler_<diagnostic name>.h. + class __trace_hash_func; + class __trace_hashtable_size; + class __trace_map2umap; + class __trace_vector_size; + class __trace_vector_to_list; + class __trace_list_to_slist; + class __trace_list_to_vector; + void __trace_vector_size_init(); + void __trace_hashtable_size_init(); + void __trace_hash_func_init(); + void __trace_vector_to_list_init(); + void __trace_list_to_slist_init(); + void __trace_list_to_vector_init(); + void __trace_map_to_unordered_map_init(); + void __trace_vector_size_report(FILE*, __warning_vector_t&); + void __trace_hashtable_size_report(FILE*, __warning_vector_t&); + void __trace_hash_func_report(FILE*, __warning_vector_t&); + void __trace_vector_to_list_report(FILE*, __warning_vector_t&); + void __trace_list_to_slist_report(FILE*, __warning_vector_t&); + void __trace_list_to_vector_report(FILE*, __warning_vector_t&); + void __trace_map_to_unordered_map_report(FILE*, __warning_vector_t&); + + struct __cost_factor + { + const char* __env_var; + float __value; + }; + + typedef std::_GLIBCXX_STD_C::vector<__cost_factor*> __cost_factor_vector; + + _GLIBCXX_PROFILE_DEFINE_DATA(__trace_hash_func*, _S_hash_func, 0); + _GLIBCXX_PROFILE_DEFINE_DATA(__trace_hashtable_size*, _S_hashtable_size, 0); + _GLIBCXX_PROFILE_DEFINE_DATA(__trace_map2umap*, _S_map2umap, 0); + _GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_size*, _S_vector_size, 0); + _GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_to_list*, _S_vector_to_list, 0); + _GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_slist*, _S_list_to_slist, 0); + _GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_vector*, _S_list_to_vector, 0); + + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_shift_cost_factor, + {"__vector_shift_cost_factor", 1.0}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_iterate_cost_factor, + {"__vector_iterate_cost_factor", 1.0}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __vector_resize_cost_factor, + {"__vector_resize_cost_factor", 1.0}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_shift_cost_factor, + {"__list_shift_cost_factor", 0.0}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_iterate_cost_factor, + {"__list_iterate_cost_factor", 10.0}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __list_resize_cost_factor, + {"__list_resize_cost_factor", 0.0}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_insert_cost_factor, + {"__map_insert_cost_factor", 1.5}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_erase_cost_factor, + {"__map_erase_cost_factor", 1.5}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_find_cost_factor, + {"__map_find_cost_factor", 1}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __map_iterate_cost_factor, + {"__map_iterate_cost_factor", 2.3}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_insert_cost_factor, + {"__umap_insert_cost_factor", 12.0}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_erase_cost_factor, + {"__umap_erase_cost_factor", 12.0}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_find_cost_factor, + {"__umap_find_cost_factor", 10.0}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor, __umap_iterate_cost_factor, + {"__umap_iterate_cost_factor", 1.7}); + _GLIBCXX_PROFILE_DEFINE_DATA(__cost_factor_vector*, __cost_factors, 0); + + _GLIBCXX_PROFILE_DEFINE_DATA(const char*, _S_trace_file_name, + _GLIBCXX_PROFILE_TRACE_PATH_ROOT); + _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_warn_count, + _GLIBCXX_PROFILE_MAX_WARN_COUNT); + _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_stack_depth, + _GLIBCXX_PROFILE_MAX_STACK_DEPTH); + _GLIBCXX_PROFILE_DEFINE_DATA(std::size_t, _S_max_mem, + _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC); + + inline std::size_t + __stack_max_depth() + { return _GLIBCXX_PROFILE_DATA(_S_max_stack_depth); } + + inline std::size_t + __max_mem() + { return _GLIBCXX_PROFILE_DATA(_S_max_mem); } + + /** @brief Base class for all trace producers. */ + template<typename __object_info, typename __stack_info> + class __trace_base + { + public: + // Do not pick the initial size too large, as we don't know which + // diagnostics are more active. + __trace_base() + : __object_table(10000), __stack_table(10000), + __stack_table_byte_size(0), __id(0) { } + + virtual ~__trace_base() { } + + void __add_object(__object_t object, __object_info __info); + __object_info* __get_object_info(__object_t __object); + void __retire_object(__object_t __object); + void __write(FILE* __f); + void __collect_warnings(__warning_vector_t& __warnings); + + private: + __gnu_cxx::__mutex __object_table_lock; + __gnu_cxx::__mutex __stack_table_lock; + typedef _GLIBCXX_IMPL_UNORDERED_MAP<__object_t, + __object_info> __object_table_t; + typedef _GLIBCXX_IMPL_UNORDERED_MAP<__stack_t, __stack_info, + __stack_hash, + __stack_hash> __stack_table_t; + __object_table_t __object_table; + __stack_table_t __stack_table; + std::size_t __stack_table_byte_size; + + protected: + const char* __id; + }; + + template<typename __object_info, typename __stack_info> + void + __trace_base<__object_info, __stack_info>:: + __collect_warnings(__warning_vector_t& __warnings) + { + for (typename __stack_table_t::iterator __it + = __stack_table.begin(); __it != __stack_table.end(); ++__it) + __warnings.push_back(__warning_data((*__it).second.__magnitude(), + (*__it).first, __id, + (*__it).second.__advice())); + } + + template<typename __object_info, typename __stack_info> + void + __trace_base<__object_info, __stack_info>:: + __add_object(__object_t __object, __object_info __info) + { + if (__max_mem() == 0 + || __object_table.size() * sizeof(__object_info) <= __max_mem()) + { + this->__object_table_lock.lock(); + __object_table.insert(typename __object_table_t:: + value_type(__object, __info)); + this->__object_table_lock.unlock(); + } + } + + template<typename __object_info, typename __stack_info> + __object_info* + __trace_base<__object_info, __stack_info>:: + __get_object_info(__object_t __object) + { + // XXX: Revisit this to see if we can decrease mutex spans. + // Without this mutex, the object table could be rehashed during an + // insertion on another thread, which could result in a segfault. + this->__object_table_lock.lock(); + typename __object_table_t::iterator __object_it + = __object_table.find(__object); + + if (__object_it == __object_table.end()) + { + this->__object_table_lock.unlock(); + return 0; + } + else + { + this->__object_table_lock.unlock(); + return &__object_it->second; + } + } + + template<typename __object_info, typename __stack_info> + void + __trace_base<__object_info, __stack_info>:: + __retire_object(__object_t __object) + { + this->__object_table_lock.lock(); + this->__stack_table_lock.lock(); + typename __object_table_t::iterator __object_it + = __object_table.find(__object); + + if (__object_it != __object_table.end()) + { + const __object_info& __info = __object_it->second; + const __stack_t& __stack = __info.__stack(); + typename __stack_table_t::iterator __stack_it + = __stack_table.find(__stack); + + if (__stack_it == __stack_table.end()) + { + // First occurence of this call context. + if (__max_mem() == 0 || __stack_table_byte_size < __max_mem()) + { + __stack_table_byte_size + += (sizeof(__instruction_address_t) * __size(__stack) + + sizeof(__stack) + sizeof(__stack_info)); + __stack_table.insert(make_pair(__stack, + __stack_info(__info))); + } + } + else + { + // Merge object info into info summary for this call context. + __stack_it->second.__merge(__info); + delete __stack; + } + __object_table.erase(__object); + } + + this->__object_table_lock.unlock(); + this->__stack_table_lock.unlock(); + } + + template<typename __object_info, typename __stack_info> + void + __trace_base<__object_info, __stack_info>:: + __write(FILE* __f) + { + for (typename __stack_table_t::iterator __it + = __stack_table.begin(); __it != __stack_table.end(); ++__it) + if (__it->second.__is_valid()) + { + std::fprintf(__f, __id); + std::fprintf(__f, "|"); + __gnu_profile::__write(__f, __it->first); + std::fprintf(__f, "|"); + __it->second.__write(__f); + } + } + + inline std::size_t + __env_to_size_t(const char* __env_var, std::size_t __default_value) + { + char* __env_value = std::getenv(__env_var); + if (__env_value) + { + errno = 0; + long __converted_value = std::strtol(__env_value, 0, 10); + if (errno || __converted_value < 0) + { + std::fprintf(stderr, + "Bad value for environment variable '%s'.\n", + __env_var); + std::abort(); + } + else + return static_cast<std::size_t>(__converted_value); + } + else + return __default_value; + } + + inline void + __set_max_stack_trace_depth() + { + _GLIBCXX_PROFILE_DATA(_S_max_stack_depth) + = __env_to_size_t(_GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR, + _GLIBCXX_PROFILE_DATA(_S_max_stack_depth)); + } + + inline void + __set_max_mem() + { + _GLIBCXX_PROFILE_DATA(_S_max_mem) + = __env_to_size_t(_GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR, + _GLIBCXX_PROFILE_DATA(_S_max_mem)); + } + + inline int + __log_magnitude(float __f) + { + const float __log_base = 10.0; + int __result = 0; + int __sign = 1; + + if (__f < 0) + { + __f = -__f; + __sign = -1; + } + + while (__f > __log_base) + { + ++__result; + __f /= 10.0; + } + return __sign * __result; + } + + inline FILE* + __open_output_file(const char* __extension) + { + // The path is made of _S_trace_file_name + "." + extension. + std::size_t __root_len + = __builtin_strlen(_GLIBCXX_PROFILE_DATA(_S_trace_file_name)); + std::size_t __ext_len = __builtin_strlen(__extension); + char* __file_name = new char[__root_len + 1 + __ext_len + 1]; + __builtin_memcpy(__file_name, + _GLIBCXX_PROFILE_DATA(_S_trace_file_name), + __root_len); + *(__file_name + __root_len) = '.'; + __builtin_memcpy(__file_name + __root_len + 1, + __extension, __ext_len + 1); + + FILE* __out_file = std::fopen(__file_name, "w"); + if (!__out_file) + { + std::fprintf(stderr, "Could not open trace file '%s'.\n", + __file_name); + std::abort(); + } + + delete[] __file_name; + return __out_file; + } + + struct __warn + { + FILE* __file; + + __warn(FILE* __f) + { __file = __f; } + + void + operator()(const __warning_data& __info) + { + std::fprintf(__file, __info.__warning_id); + std::fprintf(__file, ": improvement = %d", + __log_magnitude(__info.__magnitude)); + std::fprintf(__file, ": call stack = "); + __gnu_profile::__write(__file, __info.__context); + std::fprintf(__file, ": advice = %s\n", + __info.__warning_message.c_str()); + } + }; + + /** @brief Final report method, registered with @b atexit. + * + * This can also be called directly by user code, including signal handlers. + * It is protected against deadlocks by the reentrance guard in profiler.h. + * However, when called from a signal handler that triggers while within + * __gnu_profile (under the guarded zone), no output will be produced. + */ + inline void + __report(void) + { + _GLIBCXX_PROFILE_DATA(__global_lock).lock(); + + __warning_vector_t __warnings, __top_warnings; + + FILE* __raw_file = __open_output_file("raw"); + __trace_vector_size_report(__raw_file, __warnings); + __trace_hashtable_size_report(__raw_file, __warnings); + __trace_hash_func_report(__raw_file, __warnings); + __trace_vector_to_list_report(__raw_file, __warnings); + __trace_list_to_slist_report(__raw_file, __warnings); + __trace_list_to_vector_report(__raw_file, __warnings); + __trace_map_to_unordered_map_report(__raw_file, __warnings); + std::fclose(__raw_file); + + // Sort data by magnitude, keeping just top N. + std::size_t __cutoff = std::min(_GLIBCXX_PROFILE_DATA(_S_max_warn_count), + __warnings.size()); + __top_n(__warnings, __top_warnings, __cutoff); + + FILE* __warn_file = __open_output_file("txt"); + __for_each(__top_warnings.begin(), __top_warnings.end(), + __warn(__warn_file)); + std::fclose(__warn_file); + + _GLIBCXX_PROFILE_DATA(__global_lock).unlock(); + } + + inline void + __set_trace_path() + { + char* __env_trace_file_name = std::getenv(_GLIBCXX_PROFILE_TRACE_ENV_VAR); + + if (__env_trace_file_name) + _GLIBCXX_PROFILE_DATA(_S_trace_file_name) = __env_trace_file_name; + + // Make sure early that we can create the trace file. + std::fclose(__open_output_file("txt")); + } + + inline void + __set_max_warn_count() + { + char* __env_max_warn_count_str + = std::getenv(_GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR); + + if (__env_max_warn_count_str) + _GLIBCXX_PROFILE_DATA(_S_max_warn_count) + = static_cast<std::size_t>(std::atoi(__env_max_warn_count_str)); + } + + inline void + __read_cost_factors() + { + std::string __conf_file_name(_GLIBCXX_PROFILE_DATA(_S_trace_file_name)); + __conf_file_name += ".conf"; + + std::ifstream __conf_file(__conf_file_name.c_str()); + + if (__conf_file.is_open()) + { + std::string __line; + + while (std::getline(__conf_file, __line)) + { + std::string::size_type __i = __line.find_first_not_of(" \t\n\v"); + + if (__line.length() <= 0 || __line[__i] == '#') + // Skip empty lines or comments. + continue; + } + + // Trim. + __line.erase(__remove(__line.begin(), __line.end(), ' '), + __line.end()); + std::string::size_type __pos = __line.find("="); + std::string __factor_name = __line.substr(0, __pos); + std::string::size_type __end = __line.find_first_of(";\n"); + std::string __factor_value = __line.substr(__pos + 1, __end - __pos); + + _GLIBCXX_PROFILE_DATA(__env)[__factor_name] = __factor_value; + } + } + + struct __cost_factor_writer + { + FILE* __file; + + __cost_factor_writer(FILE* __f) + : __file(__f) { } + + void + operator() (const __cost_factor* __factor) + { std::fprintf(__file, "%s = %f\n", __factor->__env_var, + __factor->__value); } + }; + + inline void + __write_cost_factors() + { + FILE* __file = __open_output_file("conf.out"); + __for_each(_GLIBCXX_PROFILE_DATA(__cost_factors)->begin(), + _GLIBCXX_PROFILE_DATA(__cost_factors)->end(), + __cost_factor_writer(__file)); + std::fclose(__file); + } + + struct __cost_factor_setter + { + void + operator()(__cost_factor* __factor) + { + // Look it up in the process environment first. + const char* __env_value = std::getenv(__factor->__env_var); + + if (!__env_value) + { + // Look it up in the config file. + __env_t::iterator __it + = _GLIBCXX_PROFILE_DATA(__env).find(__factor->__env_var); + if (__it != _GLIBCXX_PROFILE_DATA(__env).end()) + __env_value = (*__it).second.c_str(); + } + + if (__env_value) + __factor->__value = std::atof(__env_value); + } + }; + + inline void + __set_cost_factors() + { + _GLIBCXX_PROFILE_DATA(__cost_factors) = new __cost_factor_vector; + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__vector_resize_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__list_shift_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__list_resize_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__map_insert_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__map_erase_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__map_find_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__map_iterate_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__umap_insert_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__umap_erase_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__umap_find_cost_factor)); + _GLIBCXX_PROFILE_DATA(__cost_factors)-> + push_back(&_GLIBCXX_PROFILE_DATA(__umap_iterate_cost_factor)); + __for_each(_GLIBCXX_PROFILE_DATA(__cost_factors)->begin(), + _GLIBCXX_PROFILE_DATA(__cost_factors)->end(), + __cost_factor_setter()); + } + + inline void + __profcxx_init_unconditional() + { + _GLIBCXX_PROFILE_DATA(__global_lock).lock(); + + if (__is_invalid()) + { + __set_max_warn_count(); + + if (_GLIBCXX_PROFILE_DATA(_S_max_warn_count) == 0) + __turn_off(); + else + { + __set_max_stack_trace_depth(); + __set_max_mem(); + __set_trace_path(); + __read_cost_factors(); + __set_cost_factors(); + __write_cost_factors(); + + __trace_vector_size_init(); + __trace_hashtable_size_init(); + __trace_hash_func_init(); + __trace_vector_to_list_init(); + __trace_list_to_slist_init(); + __trace_list_to_vector_init(); + __trace_map_to_unordered_map_init(); + + std::atexit(__report); + + __turn_on(); + } + } + + _GLIBCXX_PROFILE_DATA(__global_lock).unlock(); + } + + /** @brief This function must be called by each instrumentation point. + * + * The common path is inlined fully. + */ + inline bool + __profcxx_init() + { + if (__is_invalid()) + __profcxx_init_unconditional(); + + return __is_on(); + } + +} // namespace __gnu_profile + +#endif /* _GLIBCXX_PROFILE_PROFILER_TRACE_H */ diff --git a/libstdc++-v3/include/profile/impl/profiler_vector_size.h b/libstdc++-v3/include/profile/impl/profiler_vector_size.h new file mode 100644 index 000000000..604984577 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_vector_size.h @@ -0,0 +1,97 @@ +// -*- C++ -*- +// +// Copyright (C) 2009, 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @file profile/impl/profiler_vector_size.h + * @brief Collection of vector size traces. + */ + +// Written by Lixia Liu and Silvius Rus. + +#ifndef _GLIBCXX_PROFILE_PROFILER_VECTOR_SIZE_H +#define _GLIBCXX_PROFILE_PROFILER_VECTOR_SIZE_H 1 + +#include "profile/impl/profiler.h" +#include "profile/impl/profiler_node.h" +#include "profile/impl/profiler_trace.h" +#include "profile/impl/profiler_state.h" +#include "profile/impl/profiler_container_size.h" + +namespace __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"; } + }; + + inline void + __trace_vector_size_init() + { _GLIBCXX_PROFILE_DATA(_S_vector_size) = new __trace_vector_size(); } + + inline void + __trace_vector_size_report(FILE* __f, __warning_vector_t& __warnings) + { + if (_GLIBCXX_PROFILE_DATA(_S_vector_size)) + { + _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, std::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, std::size_t __num, + std::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, std::size_t __from, + std::size_t __to) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_vector_size)->__resize(__obj, __from, __to); + } + +} // namespace __gnu_profile + +#endif /* _GLIBCXX_PROFILE_PROFILER_VECTOR_SIZE_H */ diff --git a/libstdc++-v3/include/profile/impl/profiler_vector_to_list.h b/libstdc++-v3/include/profile/impl/profiler_vector_to_list.h new file mode 100644 index 000000000..7387ab614 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_vector_to_list.h @@ -0,0 +1,347 @@ +// -*- C++ -*- +// +// Copyright (C) 2009, 2010 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +/** @file profile/impl/profiler_vector_to_list.h + * @brief diagnostics for vector to list. + */ + +// Written by Lixia Liu and Silvius Rus. + +#ifndef _GLIBCXX_PROFILE_PROFILER_VECTOR_TO_LIST_H +#define _GLIBCXX_PROFILE_PROFILER_VECTOR_TO_LIST_H 1 + +#include "profile/impl/profiler.h" +#include "profile/impl/profiler_node.h" +#include "profile/impl/profiler_trace.h" + +namespace __gnu_profile +{ + /** @brief A vector-to-list instrumentation line in the object table. */ + class __vector2list_info + : public __object_info_base + { + public: + __vector2list_info() + : _M_shift_count(0), _M_iterate(0), _M_resize(0), _M_list_cost(0), + _M_vector_cost(0), _M_valid(true) { } + + __vector2list_info(__stack_t __stack) + : __object_info_base(__stack), _M_shift_count(0), _M_iterate(0), + _M_resize(0), _M_list_cost(0), _M_vector_cost(0), _M_valid(true) { } + + virtual ~__vector2list_info() { } + + __vector2list_info(const __vector2list_info& __o) + : __object_info_base(__o), _M_shift_count(__o._M_shift_count), + _M_iterate(__o._M_iterate), _M_resize(__o._M_resize), + _M_list_cost(__o._M_list_cost), _M_vector_cost(__o._M_vector_cost), + _M_valid(__o._M_valid) { } + + void + __merge(const __vector2list_info& __o) + { + _M_shift_count += __o._M_shift_count; + _M_iterate += __o._M_iterate; + _M_vector_cost += __o._M_vector_cost; + _M_list_cost += __o._M_list_cost; + _M_valid &= __o._M_valid; + _M_resize += __o._M_resize; + } + + void + __write(FILE* __f) const + { + std::fprintf(__f, "%Zu %Zu %Zu %.0f %.0f\n", _M_shift_count, + _M_resize, _M_iterate, _M_vector_cost, _M_list_cost); + } + + float + __magnitude() const + { return _M_vector_cost - _M_list_cost; } + + std::string + __advice() const + { return "change std::vector to std::list"; } + + std::size_t + __shift_count() + { return _M_shift_count; } + + std::size_t + __iterate() + { return _M_iterate; } + + float + __list_cost() + { return _M_list_cost; } + + std::size_t + __resize() + { return _M_resize; } + + void + __set_list_cost(float __lc) + { _M_list_cost = __lc; } + + void + __set_vector_cost(float __vc) + { _M_vector_cost = __vc; } + + bool + __is_valid() + { return _M_valid; } + + void + __set_invalid() + { _M_valid = false; } + + void + __opr_insert(std::size_t __pos, std::size_t __num) + { _M_shift_count += __num - __pos; } + + void + __opr_iterate(std::size_t __num) + { _M_iterate += __num; } + + void + __resize(std::size_t __from, std::size_t) + { _M_resize += __from; } + + void + __opr_find(std::size_t __size) + { + // Use average case complexity. + _M_iterate += 3.0 / 4.0 * __size; + } + + private: + std::size_t _M_shift_count; + std::size_t _M_iterate; + std::size_t _M_resize; + float _M_list_cost; + float _M_vector_cost; + bool _M_valid; + }; + + + /** @brief A vector-to-list instrumentation line in the stack table. */ + class __vector2list_stack_info + : public __vector2list_info + { + public: + __vector2list_stack_info(const __vector2list_info& __o) + : __vector2list_info(__o) { } + }; + + + /** @brief Vector-to-list instrumentation producer. */ + class __trace_vector_to_list + : public __trace_base<__vector2list_info, __vector2list_stack_info> + { + public: + __trace_vector_to_list() + : __trace_base<__vector2list_info, __vector2list_stack_info>() + { __id = "vector-to-list"; } + + ~__trace_vector_to_list() { } + + // Insert a new node at construct with object, callstack and initial size. + void + __insert(__object_t __obj, __stack_t __stack) + { __add_object(__obj, __vector2list_info(__stack)); } + + // Call at destruction/clean to set container final size. + void + __destruct(const void* __obj) + { + if (!__is_on()) + return; + + __vector2list_info* __res = __get_object_info(__obj); + if (!__res) + return; + + float __vc = __vector_cost(__res->__shift_count(), __res->__iterate(), + __res->__resize()); + float __lc = __list_cost(__res->__shift_count(), __res->__iterate(), + __res->__resize()); + __res->__set_vector_cost(__vc); + __res->__set_list_cost(__lc); + + __retire_object(__obj); + } + + // Find the node in the live map. + // XXX Undefined?!? + __vector2list_info* __find(const void* __obj); + + // Collect cost of operations. + void + __opr_insert(const void* __obj, std::size_t __pos, std::size_t __num) + { + __vector2list_info* __res = __get_object_info(__obj); + if (__res) + __res->__opr_insert(__pos, __num); + } + + void + __opr_iterate(const void* __obj, std::size_t __num) + { + __vector2list_info* __res = __get_object_info(__obj); + if (__res) + __res->__opr_iterate(__num); + } + + void + __invalid_operator(const void* __obj) + { + __vector2list_info* __res = __get_object_info(__obj); + if (__res) + __res->__set_invalid(); + } + + void + __resize(const void* __obj, std::size_t __from, std::size_t __to) + { + __vector2list_info* __res = __get_object_info(__obj); + if (__res) + __res->__resize(__from, __to); + } + + float + __vector_cost(std::size_t __shift, std::size_t __iterate, + std::size_t __resize) + { + return (__shift + * _GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor).__value + + __iterate + * _GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor).__value + + __resize + * _GLIBCXX_PROFILE_DATA(__vector_resize_cost_factor).__value); + } + + float + __list_cost(std::size_t __shift, std::size_t __iterate, + std::size_t __resize) + { + return (__shift + * _GLIBCXX_PROFILE_DATA(__list_shift_cost_factor).__value + + __iterate + * _GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor).__value + + __resize + * _GLIBCXX_PROFILE_DATA(__list_resize_cost_factor).__value); + } + + void + __opr_find(const void* __obj, std::size_t __size) + { + __vector2list_info* __res = __get_object_info(__obj); + if (__res) + __res->__opr_find(__size); + } + }; + + + inline void + __trace_vector_to_list_init() + { _GLIBCXX_PROFILE_DATA(_S_vector_to_list) = new __trace_vector_to_list(); } + + inline void + __trace_vector_to_list_report(FILE* __f, __warning_vector_t& __warnings) + { + if (_GLIBCXX_PROFILE_DATA(_S_vector_to_list)) + { + _GLIBCXX_PROFILE_DATA(_S_vector_to_list)-> + __collect_warnings(__warnings); + _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__write(__f); + } + } + + inline void + __trace_vector_to_list_construct(const void* __obj) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__insert(__obj, __get_stack()); + } + + inline void + __trace_vector_to_list_destruct(const void* __obj) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__destruct(__obj); + } + + inline void + __trace_vector_to_list_insert(const void* __obj, std::size_t __pos, + std::size_t __num) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__opr_insert(__obj, __pos, + __num); + } + + inline void + __trace_vector_to_list_iterate(const void* __obj, std::size_t __num = 1) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__opr_iterate(__obj, __num); + } + + inline void + __trace_vector_to_list_invalid_operator(const void* __obj) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__invalid_operator(__obj); + } + + inline void + __trace_vector_to_list_resize(const void* __obj, std::size_t __from, + std::size_t __to) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__resize(__obj, __from, __to); + } + + inline void + __trace_vector_to_list_find(const void* __obj, std::size_t __size) + { + if (!__profcxx_init()) + return; + + _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__opr_find(__obj, __size); + } + +} // namespace __gnu_profile +#endif /* _GLIBCXX_PROFILE_PROFILER_VECTOR_TO_LIST_H */ |