1// -*- C++ -*- 2// 3// Copyright (C) 2009 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the terms 7// of the GNU General Public License as published by the Free Software 8// Foundation; either version 2, or (at your option) any later 9// version. 10 11// This library is distributed in the hope that it will be useful, but 12// WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14// General Public License for more details. 15 16// You should have received a copy of the GNU General Public License 17// along with this library; see the file COPYING. If not, write to 18// the Free Software Foundation, 59 Temple Place - Suite 330, Boston, 19// MA 02111-1307, USA. 20 21// As a special exception, you may use this file as part of a free 22// software library without restriction. Specifically, if other files 23// instantiate templates or use macros or inline functions from this 24// file, or you compile this file and link it with other files to 25// produce an executable, this file does not by itself cause the 26// resulting executable to be covered by the GNU General Public 27// License. This exception does not however invalidate any other 28// reasons why the executable file might be covered by the GNU General 29// Public License. 30 31/** @file profile/impl/profiler_vector_to_list.h 32 * @brief diagnostics for vector to list. 33 */ 34 35// Written by Lixia Liu and Silvius Rus. 36 37#ifndef _GLIBCXX_PROFILE_PROFILER_VECTOR_TO_LIST_H 38#define _GLIBCXX_PROFILE_PROFILER_VECTOR_TO_LIST_H 1 39 40#ifdef __GXX_EXPERIMENTAL_CXX0X__ 41#include <cstdio> 42#include <cstdlib> 43#include <cstring> 44#else 45#include <stdio.h> 46#include <stdint.h> 47#include <string.h> 48#endif 49#include "profile/impl/profiler.h" 50#include "profile/impl/profiler_node.h" 51#include "profile/impl/profiler_trace.h" 52 53namespace __gnu_profile 54{ 55 56/** @brief A vector-to-list instrumentation line in the object table. */ 57class __vector2list_info: public __object_info_base 58{ 59 public: 60 __vector2list_info() 61 :_M_shift_count(0), _M_iterate(0), _M_resize(0), _M_list_cost(0), 62 _M_vector_cost(0), _M_valid(true) {} 63 __vector2list_info(__stack_t __stack) 64 : __object_info_base(__stack), _M_shift_count(0), _M_iterate(0), 65 _M_resize(0), _M_list_cost(0), _M_vector_cost(0), _M_valid(true) {} 66 virtual ~__vector2list_info() {} 67 __vector2list_info(const __vector2list_info& __o); 68 void __merge(const __vector2list_info& __o); 69 void __write(FILE* __f) const; 70 float __magnitude() const { return _M_vector_cost - _M_list_cost; } 71 const char* __advice() const 72 { return strdup("change std::vector to std::list"); } 73 74 size_t __shift_count() { return _M_shift_count; } 75 size_t __iterate() { return _M_iterate; } 76 float __list_cost() { return _M_list_cost; } 77 size_t __resize() { return _M_resize; } 78 void __set_list_cost(float __lc) { _M_list_cost = __lc; } 79 void __set_vector_cost(float __vc) { _M_vector_cost = __vc; } 80 bool __is_valid() { return _M_valid; } 81 void __set_invalid() { _M_valid = false; } 82 83 void __opr_insert(size_t __pos, size_t __num); 84 void __opr_iterate(size_t __num); 85 void __resize(size_t __from, size_t __to); 86 void __opr_find(size_t __size); 87 88private: 89 size_t _M_shift_count; 90 size_t _M_iterate; 91 size_t _M_resize; 92 float _M_list_cost; 93 float _M_vector_cost; 94 bool _M_valid; 95}; 96 97inline __vector2list_info::__vector2list_info(const __vector2list_info& __o) 98 : __object_info_base(__o) 99{ 100 _M_shift_count = __o._M_shift_count; 101 _M_iterate = __o._M_iterate; 102 _M_vector_cost = __o._M_vector_cost; 103 _M_list_cost = __o._M_list_cost; 104 _M_valid = __o._M_valid; 105 _M_resize = __o._M_resize; 106} 107 108inline void __vector2list_info::__merge(const __vector2list_info& __o) 109{ 110 _M_shift_count += __o._M_shift_count; 111 _M_iterate += __o._M_iterate; 112 _M_vector_cost += __o._M_vector_cost; 113 _M_list_cost += __o._M_list_cost; 114 _M_valid &= __o._M_valid; 115 _M_resize += __o._M_resize; 116} 117 118inline void __vector2list_info::__opr_insert(size_t __pos, size_t __num) 119{ 120 _M_shift_count += __num - __pos; 121} 122 123inline void __vector2list_info::__resize(size_t __from, size_t __to) 124{ 125 _M_resize += __from; 126} 127 128inline void __vector2list_info::__opr_iterate(size_t __num) 129{ 130 _M_iterate += __num; 131} 132 133inline void __vector2list_info::__opr_find(size_t __size) 134{ 135 // Use average case complexity. 136 _M_iterate += 3.0 / 4.0 * __size; 137} 138 139/** @brief A vector-to-list instrumentation line in the stack table. */ 140class __vector2list_stack_info: public __vector2list_info { 141 public: 142 __vector2list_stack_info(const __vector2list_info& __o) 143 : __vector2list_info(__o) {} 144}; 145 146/** @brief Vector-to-list instrumentation producer. */ 147class __trace_vector_to_list 148 : public __trace_base<__vector2list_info, __vector2list_stack_info> 149{ 150 public: 151 __trace_vector_to_list(); 152 ~__trace_vector_to_list() {} 153 154 // Insert a new node at construct with object, callstack and initial size. 155 void __insert(__object_t __obj, __stack_t __stack); 156 // Call at destruction/clean to set container final size. 157 void __destruct(const void* __obj); 158 159 // Find the node in the live map. 160 __vector2list_info* __find(const void* __obj); 161 162 // Collect cost of operations. 163 void __opr_insert(const void* __obj, size_t __pos, size_t __num); 164 void __opr_iterate(const void* __obj, size_t __num); 165 void __invalid_operator(const void* __obj); 166 void __resize(const void* __obj, size_t __from, size_t __to); 167 float __vector_cost(size_t __shift, size_t __iterate, size_t __resize); 168 float __list_cost(size_t __shift, size_t __iterate, size_t __resize); 169 void __opr_find(const void* __obj, size_t __size); 170}; 171 172inline __trace_vector_to_list::__trace_vector_to_list() 173 : __trace_base<__vector2list_info, __vector2list_stack_info>() 174{ 175 __id = "vector-to-list"; 176} 177 178inline void __trace_vector_to_list::__insert(__object_t __obj, 179 __stack_t __stack) 180{ 181 __add_object(__obj, __vector2list_info(__stack)); 182} 183 184inline void __vector2list_info::__write(FILE* __f) const 185{ 186 fprintf(__f, "%Zu %Zu %Zu %.0f %.0f\n", 187 _M_shift_count, _M_resize, _M_iterate, _M_vector_cost, _M_list_cost); 188} 189 190inline float __trace_vector_to_list::__vector_cost(size_t __shift, 191 size_t __iterate, 192 size_t __resize) 193{ 194 return ( 195 __shift * _GLIBCXX_PROFILE_DATA(__vector_shift_cost_factor).__value 196 + __iterate * _GLIBCXX_PROFILE_DATA(__vector_iterate_cost_factor).__value 197 + __resize * _GLIBCXX_PROFILE_DATA(__vector_resize_cost_factor).__value 198 ); 199} 200 201inline float __trace_vector_to_list::__list_cost(size_t __shift, 202 size_t __iterate, 203 size_t __resize) 204{ 205 return ( 206 __shift * _GLIBCXX_PROFILE_DATA(__list_shift_cost_factor).__value 207 + __iterate * _GLIBCXX_PROFILE_DATA(__list_iterate_cost_factor).__value 208 + __resize * _GLIBCXX_PROFILE_DATA(__list_resize_cost_factor).__value); 209} 210 211inline void __trace_vector_to_list::__destruct(const void* __obj) 212{ 213 if (!__is_on()) 214 return; 215 216 __vector2list_info* __res = __get_object_info(__obj); 217 if (!__res) 218 return; 219 220 float __vc = __vector_cost(__res->__shift_count(), __res->__iterate(), 221 __res->__resize()); 222 float __lc = __list_cost(__res->__shift_count(), __res->__iterate(), 223 __res->__resize()); 224 __res->__set_vector_cost(__vc); 225 __res->__set_list_cost(__lc); 226 227 __retire_object(__obj); 228} 229 230inline void __trace_vector_to_list::__opr_insert(const void* __obj, 231 size_t __pos, size_t __num) 232{ 233 __vector2list_info* __res = __get_object_info(__obj); 234 if (__res) 235 __res->__opr_insert(__pos, __num); 236} 237 238inline void __trace_vector_to_list::__opr_iterate(const void* __obj, 239 size_t __num) 240{ 241 __vector2list_info* __res = __get_object_info(__obj); 242 if (__res) 243 __res->__opr_iterate(__num); 244} 245 246inline void __trace_vector_to_list::__invalid_operator(const void* __obj) 247{ 248 __vector2list_info* __res = __get_object_info(__obj); 249 if (__res) 250 __res->__set_invalid(); 251} 252 253inline void __trace_vector_to_list::__resize(const void* __obj, size_t __from, 254 size_t __to) 255{ 256 __vector2list_info* __res = __get_object_info(__obj); 257 if (__res) 258 __res->__resize(__from, __to); 259} 260 261inline void __trace_vector_to_list::__opr_find(const void* __obj, 262 size_t __size) 263{ 264 __vector2list_info* __res = __get_object_info(__obj); 265 if (__res) 266 __res->__opr_find(__size); 267} 268 269inline void __trace_vector_to_list_init() 270{ 271 _GLIBCXX_PROFILE_DATA(_S_vector_to_list) = new __trace_vector_to_list(); 272} 273 274inline void __trace_vector_to_list_report(FILE* __f, 275 __warning_vector_t& __warnings) 276{ 277 if (_GLIBCXX_PROFILE_DATA(_S_vector_to_list)) { 278 _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__collect_warnings(__warnings); 279 _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__write(__f); 280 } 281} 282 283inline void __trace_vector_to_list_construct(const void* __obj) 284{ 285 if (!__profcxx_init()) return; 286 287 _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__insert(__obj, __get_stack()); 288} 289 290inline void __trace_vector_to_list_destruct(const void* __obj) 291{ 292 if (!__profcxx_init()) return; 293 294 _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__destruct(__obj); 295} 296 297inline void __trace_vector_to_list_insert(const void* __obj, 298 size_t __pos, size_t __num) 299{ 300 if (!__profcxx_init()) return; 301 302 _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__opr_insert(__obj, __pos, __num); 303} 304 305 306inline void __trace_vector_to_list_iterate(const void* __obj, size_t __num = 1) 307{ 308 if (!__profcxx_init()) return; 309 310 _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__opr_iterate(__obj, __num); 311} 312 313inline void __trace_vector_to_list_invalid_operator(const void* __obj) 314{ 315 if (!__profcxx_init()) return; 316 317 _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__invalid_operator(__obj); 318} 319 320inline void __trace_vector_to_list_resize(const void* __obj, 321 size_t __from, size_t __to) 322{ 323 if (!__profcxx_init()) return; 324 325 _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__resize(__obj, __from, __to); 326} 327 328inline void __trace_vector_to_list_find(const void* __obj, size_t __size) 329{ 330 if (!__profcxx_init()) return; 331 332 _GLIBCXX_PROFILE_DATA(_S_vector_to_list)->__opr_find(__obj, __size); 333} 334 335} // namespace __gnu_profile 336#endif /* _GLIBCXX_PROFILE_PROFILER_VECTOR_TO_LIST_H */ 337