diff options
Diffstat (limited to 'libstdc++-v3/include/profile')
16 files changed, 2713 insertions, 2780 deletions
diff --git a/libstdc++-v3/include/profile/hashtable.h b/libstdc++-v3/include/profile/hashtable.h deleted file mode 100644 index 20891877121..00000000000 --- a/libstdc++-v3/include/profile/hashtable.h +++ /dev/null @@ -1,1151 +0,0 @@ -// Hashtable implementation used by containers -*- C++ -*- - -// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 -// Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 2, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License along -// with this library; see the file COPYING. If not, write to the Free -// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, -// USA. - -// As a special exception, you may use this file as part of a free software -// library without restriction. Specifically, if other files instantiate -// templates or use macros or inline functions from this file, or you compile -// this file and link it with other files to produce an executable, this -// file does not by itself cause the resulting executable to be covered by -// the GNU General Public License. This exception does not however -// invalidate any other reasons why the executable file might be covered by -// the GNU General Public License. - -/* - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -/** @file profile/hashtable.h copied from backward/hashtable.h - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _HASHTABLE_H -#define _HASHTABLE_H 1 - -// Hashtable class, used to implement the hashed associative containers -// hash_set, hash_map, hash_multiset, and hash_multimap. -// Skip instrumentation on vector. -#include <vector> -#include <iterator> -#include <algorithm> -#include <bits/stl_function.h> -#include <backward/hash_fun.h> -#include <profile/base.h> - -_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) - - using std::size_t; - using std::ptrdiff_t; - using std::forward_iterator_tag; - using std::input_iterator_tag; - using std::_Construct; - using std::_Destroy; - using std::distance; - using std::_GLIBCXX_STD_D::vector; - using std::pair; - using std::__iterator_category; - - template<class _Val> - struct _Hashtable_node - { - _Hashtable_node* _M_next; - _Val _M_val; - }; - - template<class _Val, class _Key, class _HashFcn, class _ExtractKey, - class _EqualKey, class _Alloc = std::allocator<_Val> > - class hashtable; - - template<class _Val, class _Key, class _HashFcn, - class _ExtractKey, class _EqualKey, class _Alloc> - struct _Hashtable_iterator; - - template<class _Val, class _Key, class _HashFcn, - class _ExtractKey, class _EqualKey, class _Alloc> - struct _Hashtable_const_iterator; - - template<class _Val, class _Key, class _HashFcn, - class _ExtractKey, class _EqualKey, class _Alloc> - struct _Hashtable_iterator - { - typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc> - _Hashtable; - typedef _Hashtable_iterator<_Val, _Key, _HashFcn, - _ExtractKey, _EqualKey, _Alloc> - iterator; - typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, - _ExtractKey, _EqualKey, _Alloc> - const_iterator; - typedef _Hashtable_node<_Val> _Node; - typedef forward_iterator_tag iterator_category; - typedef _Val value_type; - typedef ptrdiff_t difference_type; - typedef size_t size_type; - typedef _Val& reference; - typedef _Val* pointer; - - _Node* _M_cur; - _Hashtable* _M_ht; - - _Hashtable_iterator(_Node* __n, _Hashtable* __tab) - : _M_cur(__n), _M_ht(__tab) { } - - _Hashtable_iterator() { } - - reference - operator*() const - { return _M_cur->_M_val; } - - pointer - operator->() const - { return &(operator*()); } - - iterator& - operator++(); - - iterator - operator++(int); - - bool - operator==(const iterator& __it) const - { return _M_cur == __it._M_cur; } - - bool - operator!=(const iterator& __it) const - { return _M_cur != __it._M_cur; } - }; - - template<class _Val, class _Key, class _HashFcn, - class _ExtractKey, class _EqualKey, class _Alloc> - struct _Hashtable_const_iterator - { - typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc> - _Hashtable; - typedef _Hashtable_iterator<_Val,_Key,_HashFcn, - _ExtractKey,_EqualKey,_Alloc> - iterator; - typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, - _ExtractKey, _EqualKey, _Alloc> - const_iterator; - typedef _Hashtable_node<_Val> _Node; - - typedef forward_iterator_tag iterator_category; - typedef _Val value_type; - typedef ptrdiff_t difference_type; - typedef size_t size_type; - typedef const _Val& reference; - typedef const _Val* pointer; - - const _Node* _M_cur; - const _Hashtable* _M_ht; - - _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab) - : _M_cur(__n), _M_ht(__tab) { } - - _Hashtable_const_iterator() { } - - _Hashtable_const_iterator(const iterator& __it) - : _M_cur(__it._M_cur), _M_ht(__it._M_ht) { } - - reference - operator*() const - { return _M_cur->_M_val; } - - pointer - operator->() const - { return &(operator*()); } - - const_iterator& - operator++(); - - const_iterator - operator++(int); - - bool - operator==(const const_iterator& __it) const - { return _M_cur == __it._M_cur; } - - bool - operator!=(const const_iterator& __it) const - { return _M_cur != __it._M_cur; } - }; - - // Note: assumes long is at least 32 bits. - enum { _S_num_primes = 28 }; - - static const unsigned long __stl_prime_list[_S_num_primes] = - { - 53ul, 97ul, 193ul, 389ul, 769ul, - 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, - 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, - 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, - 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul, - 1610612741ul, 3221225473ul, 4294967291ul - }; - - inline unsigned long - __stl_next_prime(unsigned long __n) - { - const unsigned long* __first = __stl_prime_list; - const unsigned long* __last = __stl_prime_list + (int)_S_num_primes; - const unsigned long* pos = std::lower_bound(__first, __last, __n); - return pos == __last ? *(__last - 1) : *pos; - } - - // Forward declaration of operator==. - template<class _Val, class _Key, class _HF, class _Ex, - class _Eq, class _All> - class hashtable; - - template<class _Val, class _Key, class _HF, class _Ex, - class _Eq, class _All> - bool - operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, - const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2); - - // Hashtables handle allocators a bit differently than other - // containers do. If we're using standard-conforming allocators, then - // a hashtable unconditionally has a member variable to hold its - // allocator, even if it so happens that all instances of the - // allocator type are identical. This is because, for hashtables, - // this extra storage is negligible. Additionally, a base class - // wouldn't serve any other purposes; it wouldn't, for example, - // simplify the exception-handling code. - template<class _Val, class _Key, class _HashFcn, - class _ExtractKey, class _EqualKey, class _Alloc> - class hashtable - { - public: - typedef _Key key_type; - typedef _Val value_type; - typedef _HashFcn hasher; - typedef _EqualKey key_equal; - - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - - hasher - hash_funct() const - { return _M_hash; } - - key_equal - key_eq() const - { return _M_equals; } - - private: - typedef _Hashtable_node<_Val> _Node; - - public: - typedef typename _Alloc::template rebind<value_type>::other allocator_type; - allocator_type - get_allocator() const - { return _M_node_allocator; } - - private: - typedef typename _Alloc::template rebind<_Node>::other _Node_Alloc; - typedef typename _Alloc::template rebind<_Node*>::other _Nodeptr_Alloc; - typedef vector<_Node*, _Nodeptr_Alloc> _Vector_type; - - _Node_Alloc _M_node_allocator; - - _Node* - _M_get_node() - { return _M_node_allocator.allocate(1); } - - void - _M_put_node(_Node* __p) - { _M_node_allocator.deallocate(__p, 1); } - - private: - hasher _M_hash; - key_equal _M_equals; - _ExtractKey _M_get_key; - _Vector_type _M_buckets; - size_type _M_num_elements; - - public: - typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, - _EqualKey, _Alloc> - iterator; - typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey, - _EqualKey, _Alloc> - const_iterator; - - friend struct - _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>; - - friend struct - _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey, - _EqualKey, _Alloc>; - - public: - hashtable(size_type __n, const _HashFcn& __hf, - const _EqualKey& __eql, const _ExtractKey& __ext, - const allocator_type& __a = allocator_type()) - : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql), - _M_get_key(__ext), _M_buckets(__a), _M_num_elements(0) - { _M_initialize_buckets(__n); } - - hashtable(size_type __n, const _HashFcn& __hf, - const _EqualKey& __eql, - const allocator_type& __a = allocator_type()) - : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql), - _M_get_key(_ExtractKey()), _M_buckets(__a), _M_num_elements(0) - { _M_initialize_buckets(__n); } - - hashtable(const hashtable& __ht) - : _M_node_allocator(__ht.get_allocator()), _M_hash(__ht._M_hash), - _M_equals(__ht._M_equals), _M_get_key(__ht._M_get_key), - _M_buckets(__ht.get_allocator()), _M_num_elements(0) - { _M_copy_from(__ht); } - - hashtable& - operator= (const hashtable& __ht) - { - if (&__ht != this) - { - clear(); - _M_hash = __ht._M_hash; - _M_equals = __ht._M_equals; - _M_get_key = __ht._M_get_key; - _M_copy_from(__ht); - } - return *this; - } - - ~hashtable() - { clear(); } - - size_type - size() const - { return _M_num_elements; } - - size_type - max_size() const - { return size_type(-1); } - - bool - empty() const - { return size() == 0; } - - void - swap(hashtable& __ht) - { - std::swap(_M_hash, __ht._M_hash); - std::swap(_M_equals, __ht._M_equals); - std::swap(_M_get_key, __ht._M_get_key); - _M_buckets.swap(__ht._M_buckets); - std::swap(_M_num_elements, __ht._M_num_elements); - } - - iterator - begin() - { - for (size_type __n = 0; __n < _M_buckets.size(); ++__n) - if (_M_buckets[__n]) - return iterator(_M_buckets[__n], this); - return end(); - } - - iterator - end() - { return iterator(0, this); } - - const_iterator - begin() const - { - for (size_type __n = 0; __n < _M_buckets.size(); ++__n) - if (_M_buckets[__n]) - return const_iterator(_M_buckets[__n], this); - return end(); - } - - const_iterator - end() const - { return const_iterator(0, this); } - - template<class _Vl, class _Ky, class _HF, class _Ex, class _Eq, - class _Al> - friend bool - operator==(const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&, - const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&); - - public: - size_type - bucket_count() const - { return _M_buckets.size(); } - - size_type - max_bucket_count() const - { return __stl_prime_list[(int)_S_num_primes - 1]; } - - size_type - elems_in_bucket(size_type __bucket) const - { - size_type __result = 0; - for (_Node* __n = _M_buckets[__bucket]; __n; __n = __n->_M_next) - __result += 1; - return __result; - } - - pair<iterator, bool> - insert_unique(const value_type& __obj) - { - resize(_M_num_elements + 1); - return insert_unique_noresize(__obj); - } - - iterator - insert_equal(const value_type& __obj) - { - resize(_M_num_elements + 1); - return insert_equal_noresize(__obj); - } - - pair<iterator, bool> - insert_unique_noresize(const value_type& __obj); - - iterator - insert_equal_noresize(const value_type& __obj); - - template<class _InputIterator> - void - insert_unique(_InputIterator __f, _InputIterator __l) - { insert_unique(__f, __l, __iterator_category(__f)); } - - template<class _InputIterator> - void - insert_equal(_InputIterator __f, _InputIterator __l) - { insert_equal(__f, __l, __iterator_category(__f)); } - - template<class _InputIterator> - void - insert_unique(_InputIterator __f, _InputIterator __l, - input_iterator_tag) - { - for ( ; __f != __l; ++__f) - insert_unique(*__f); - } - - template<class _InputIterator> - void - insert_equal(_InputIterator __f, _InputIterator __l, - input_iterator_tag) - { - for ( ; __f != __l; ++__f) - insert_equal(*__f); - } - - template<class _ForwardIterator> - void - insert_unique(_ForwardIterator __f, _ForwardIterator __l, - forward_iterator_tag) - { - size_type __n = distance(__f, __l); - resize(_M_num_elements + __n); - for ( ; __n > 0; --__n, ++__f) - insert_unique_noresize(*__f); - } - - template<class _ForwardIterator> - void - insert_equal(_ForwardIterator __f, _ForwardIterator __l, - forward_iterator_tag) - { - size_type __n = distance(__f, __l); - resize(_M_num_elements + __n); - for ( ; __n > 0; --__n, ++__f) - insert_equal_noresize(*__f); - } - - reference - find_or_insert(const value_type& __obj); - - iterator - find(const key_type& __key) - { - size_type __n = _M_bkt_num_key(__key); - _Node* __first; - for (__first = _M_buckets[__n]; - __first && !_M_equals(_M_get_key(__first->_M_val), __key); - __first = __first->_M_next) - { } - return iterator(__first, this); - } - - const_iterator - find(const key_type& __key) const - { - size_type __n = _M_bkt_num_key(__key); - const _Node* __first; - for (__first = _M_buckets[__n]; - __first && !_M_equals(_M_get_key(__first->_M_val), __key); - __first = __first->_M_next) - { } - return const_iterator(__first, this); - } - - size_type - count(const key_type& __key) const - { - const size_type __n = _M_bkt_num_key(__key); - size_type __result = 0; - - for (const _Node* __cur = _M_buckets[__n]; __cur; - __cur = __cur->_M_next) - if (_M_equals(_M_get_key(__cur->_M_val), __key)) - ++__result; - return __result; - } - - pair<iterator, iterator> - equal_range(const key_type& __key); - - pair<const_iterator, const_iterator> - equal_range(const key_type& __key) const; - - size_type - erase(const key_type& __key); - - void - erase(const iterator& __it); - - void - erase(iterator __first, iterator __last); - - void - erase(const const_iterator& __it); - - void - erase(const_iterator __first, const_iterator __last); - - void - resize(size_type __num_elements_hint); - - void - clear(); - - private: - size_type - _M_next_size(size_type __n) const - { return __stl_next_prime(__n); } - - void - _M_initialize_buckets(size_type __n) - { - const size_type __n_buckets = _M_next_size(__n); - _M_buckets.reserve(__n_buckets); - _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0); - _M_num_elements = 0; - __profcxx_hashtable_construct(this, __n_buckets); - __profcxx_hashtable_construct2(this); - } - - size_type - _M_bkt_num_key(const key_type& __key) const - { return _M_bkt_num_key(__key, _M_buckets.size()); } - - size_type - _M_bkt_num(const value_type& __obj) const - { return _M_bkt_num_key(_M_get_key(__obj)); } - - size_type - _M_bkt_num_key(const key_type& __key, size_t __n) const - { return _M_hash(__key) % __n; } - - size_type - _M_bkt_num(const value_type& __obj, size_t __n) const - { return _M_bkt_num_key(_M_get_key(__obj), __n); } - - _Node* - _M_new_node(const value_type& __obj) - { - _Node* __n = _M_get_node(); - __n->_M_next = 0; - try - { - this->get_allocator().construct(&__n->_M_val, __obj); - return __n; - } - catch(...) - { - _M_put_node(__n); - __throw_exception_again; - } - } - - void - _M_delete_node(_Node* __n) - { - this->get_allocator().destroy(&__n->_M_val); - _M_put_node(__n); - } - - void - _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last); - - void - _M_erase_bucket(const size_type __n, _Node* __last); - - void - _M_copy_from(const hashtable& __ht); - }; - - template<class _Val, class _Key, class _HF, class _ExK, class _EqK, - class _All> - _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>& - _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: - operator++() - { - const _Node* __old = _M_cur; - _M_cur = _M_cur->_M_next; - if (!_M_cur) - { - size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val); - while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size()) - _M_cur = _M_ht->_M_buckets[__bucket]; - } - return *this; - } - - template<class _Val, class _Key, class _HF, class _ExK, class _EqK, - class _All> - inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All> - _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: - operator++(int) - { - iterator __tmp = *this; - ++*this; - return __tmp; - } - - template<class _Val, class _Key, class _HF, class _ExK, class _EqK, - class _All> - _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>& - _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: - operator++() - { - const _Node* __old = _M_cur; - _M_cur = _M_cur->_M_next; - if (!_M_cur) - { - size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val); - while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size()) - _M_cur = _M_ht->_M_buckets[__bucket]; - } - return *this; - } - - template<class _Val, class _Key, class _HF, class _ExK, class _EqK, - class _All> - inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All> - _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: - operator++(int) - { - const_iterator __tmp = *this; - ++*this; - return __tmp; - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - bool - operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, - const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2) - { - typedef typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_Node _Node; - - if (__ht1._M_buckets.size() != __ht2._M_buckets.size()) - return false; - - for (size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n) - { - _Node* __cur1 = __ht1._M_buckets[__n]; - _Node* __cur2 = __ht2._M_buckets[__n]; - // Check same length of lists - for (; __cur1 && __cur2; - __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next) - { } - if (__cur1 || __cur2) - return false; - // Now check one's elements are in the other - for (__cur1 = __ht1._M_buckets[__n] ; __cur1; - __cur1 = __cur1->_M_next) - { - bool _found__cur1 = false; - for (__cur2 = __ht2._M_buckets[__n]; - __cur2; __cur2 = __cur2->_M_next) - { - if (__cur1->_M_val == __cur2->_M_val) - { - _found__cur1 = true; - break; - } - } - if (!_found__cur1) - return false; - } - } - return true; - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - inline bool - operator!=(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, - const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2) - { return !(__ht1 == __ht2); } - - template<class _Val, class _Key, class _HF, class _Extract, class _EqKey, - class _All> - inline void - swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1, - hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) - { __ht1.swap(__ht2); } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator, bool> - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - insert_unique_noresize(const value_type& __obj) - { - const size_type __n = _M_bkt_num(__obj); - _Node* __first = _M_buckets[__n]; - - for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) - if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) - return pair<iterator, bool>(iterator(__cur, this), false); - - _Node* __tmp = _M_new_node(__obj); - __tmp->_M_next = __first; - _M_buckets[__n] = __tmp; - ++_M_num_elements; - return pair<iterator, bool>(iterator(__tmp, this), true); - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - insert_equal_noresize(const value_type& __obj) - { - const size_type __n = _M_bkt_num(__obj); - _Node* __first = _M_buckets[__n]; - - for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) - if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) - { - _Node* __tmp = _M_new_node(__obj); - __tmp->_M_next = __cur->_M_next; - __cur->_M_next = __tmp; - ++_M_num_elements; - return iterator(__tmp, this); - } - - _Node* __tmp = _M_new_node(__obj); - __tmp->_M_next = __first; - _M_buckets[__n] = __tmp; - ++_M_num_elements; - return iterator(__tmp, this); - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - find_or_insert(const value_type& __obj) - { - resize(_M_num_elements + 1); - - size_type __n = _M_bkt_num(__obj); - _Node* __first = _M_buckets[__n]; - - for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) - if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) - return __cur->_M_val; - - _Node* __tmp = _M_new_node(__obj); - __tmp->_M_next = __first; - _M_buckets[__n] = __tmp; - ++_M_num_elements; - return __tmp->_M_val; - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator, - typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator> - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - equal_range(const key_type& __key) - { - typedef pair<iterator, iterator> _Pii; - const size_type __n = _M_bkt_num_key(__key); - - for (_Node* __first = _M_buckets[__n]; __first; - __first = __first->_M_next) - if (_M_equals(_M_get_key(__first->_M_val), __key)) - { - for (_Node* __cur = __first->_M_next; __cur; - __cur = __cur->_M_next) - if (!_M_equals(_M_get_key(__cur->_M_val), __key)) - return _Pii(iterator(__first, this), iterator(__cur, this)); - for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m) - if (_M_buckets[__m]) - return _Pii(iterator(__first, this), - iterator(_M_buckets[__m], this)); - return _Pii(iterator(__first, this), end()); - } - return _Pii(end(), end()); - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator, - typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator> - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - equal_range(const key_type& __key) const - { - typedef pair<const_iterator, const_iterator> _Pii; - const size_type __n = _M_bkt_num_key(__key); - - for (const _Node* __first = _M_buckets[__n]; __first; - __first = __first->_M_next) - { - if (_M_equals(_M_get_key(__first->_M_val), __key)) - { - for (const _Node* __cur = __first->_M_next; __cur; - __cur = __cur->_M_next) - if (!_M_equals(_M_get_key(__cur->_M_val), __key)) - return _Pii(const_iterator(__first, this), - const_iterator(__cur, this)); - for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m) - if (_M_buckets[__m]) - return _Pii(const_iterator(__first, this), - const_iterator(_M_buckets[__m], this)); - return _Pii(const_iterator(__first, this), end()); - } - } - return _Pii(end(), end()); - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::size_type - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - erase(const key_type& __key) - { - const size_type __n = _M_bkt_num_key(__key); - _Node* __first = _M_buckets[__n]; - size_type __erased = 0; - - if (__first) - { - _Node* __cur = __first; - _Node* __next = __cur->_M_next; - while (__next) - { - if (_M_equals(_M_get_key(__next->_M_val), __key)) - { - __cur->_M_next = __next->_M_next; - _M_delete_node(__next); - __next = __cur->_M_next; - ++__erased; - --_M_num_elements; - } - else - { - __cur = __next; - __next = __cur->_M_next; - } - } - if (_M_equals(_M_get_key(__first->_M_val), __key)) - { - _M_buckets[__n] = __first->_M_next; - _M_delete_node(__first); - ++__erased; - --_M_num_elements; - } - } - return __erased; - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - erase(const iterator& __it) - { - _Node* __p = __it._M_cur; - if (__p) - { - const size_type __n = _M_bkt_num(__p->_M_val); - _Node* __cur = _M_buckets[__n]; - - if (__cur == __p) - { - _M_buckets[__n] = __cur->_M_next; - _M_delete_node(__cur); - --_M_num_elements; - } - else - { - _Node* __next = __cur->_M_next; - while (__next) - { - if (__next == __p) - { - __cur->_M_next = __next->_M_next; - _M_delete_node(__next); - --_M_num_elements; - break; - } - else - { - __cur = __next; - __next = __cur->_M_next; - } - } - } - } - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - erase(iterator __first, iterator __last) - { - size_type __f_bucket = __first._M_cur ? _M_bkt_num(__first._M_cur->_M_val) - : _M_buckets.size(); - - size_type __l_bucket = __last._M_cur ? _M_bkt_num(__last._M_cur->_M_val) - : _M_buckets.size(); - - if (__first._M_cur == __last._M_cur) - return; - else if (__f_bucket == __l_bucket) - _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur); - else - { - _M_erase_bucket(__f_bucket, __first._M_cur, 0); - for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n) - _M_erase_bucket(__n, 0); - if (__l_bucket != _M_buckets.size()) - _M_erase_bucket(__l_bucket, __last._M_cur); - } - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - inline void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - erase(const_iterator __first, const_iterator __last) - { - erase(iterator(const_cast<_Node*>(__first._M_cur), - const_cast<hashtable*>(__first._M_ht)), - iterator(const_cast<_Node*>(__last._M_cur), - const_cast<hashtable*>(__last._M_ht))); - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - inline void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - erase(const const_iterator& __it) - { erase(iterator(const_cast<_Node*>(__it._M_cur), - const_cast<hashtable*>(__it._M_ht))); } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - resize(size_type __num_elements_hint) - { - const size_type __old_n = _M_buckets.size(); - if (__num_elements_hint > __old_n) - { - const size_type __n = _M_next_size(__num_elements_hint); - if (__n > __old_n) - { - _Vector_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator()); - try - { - for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) - { - _Node* __first = _M_buckets[__bucket]; - while (__first) - { - size_type __new_bucket = _M_bkt_num(__first->_M_val, - __n); - _M_buckets[__bucket] = __first->_M_next; - __first->_M_next = __tmp[__new_bucket]; - __tmp[__new_bucket] = __first; - __first = _M_buckets[__bucket]; - } - } - _M_buckets.swap(__tmp); - } - catch(...) - { - for (size_type __bucket = 0; __bucket < __tmp.size(); - ++__bucket) - { - while (__tmp[__bucket]) - { - _Node* __next = __tmp[__bucket]->_M_next; - _M_delete_node(__tmp[__bucket]); - __tmp[__bucket] = __next; - } - } - __throw_exception_again; - } - __profcxx_hashtable_resize(this, __num_elements_hint, __n); - } - } - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last) - { - _Node* __cur = _M_buckets[__n]; - if (__cur == __first) - _M_erase_bucket(__n, __last); - else - { - _Node* __next; - for (__next = __cur->_M_next; - __next != __first; - __cur = __next, __next = __cur->_M_next) - ; - while (__next != __last) - { - __cur->_M_next = __next->_M_next; - _M_delete_node(__next); - __next = __cur->_M_next; - --_M_num_elements; - } - } - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - _M_erase_bucket(const size_type __n, _Node* __last) - { - _Node* __cur = _M_buckets[__n]; - while (__cur != __last) - { - _Node* __next = __cur->_M_next; - _M_delete_node(__cur); - __cur = __next; - _M_buckets[__n] = __cur; - --_M_num_elements; - } - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - clear() - { - size_type __hops=0, __lc = 0, __chain = 0; - if (_M_num_elements != 0) - __profcxx_hashtable_destruct(this, _M_buckets.size(), _M_num_elements); - - for (size_type __i = 0; __i < _M_buckets.size(); ++__i) - { - _Node* __cur = _M_buckets[__i]; - while (__cur != 0) - { - _Node* __next = __cur->_M_next; - _M_delete_node(__cur); - __cur = __next; - - // Compute the longest chain count. - __chain++; - } - _M_buckets[__i] = 0; - - // Collect number of hops. - if (__chain > 1) { - __lc = __lc > __chain ? __lc : __chain; - __hops += (__chain-1) * __chain / 2; - } - __chain = 0; - } - if (_M_num_elements) { - __profcxx_hashtable_destruct2(this, __lc, _M_num_elements, __hops); - } - _M_num_elements = 0; - } - - template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> - void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - _M_copy_from(const hashtable& __ht) - { - _M_buckets.clear(); - _M_buckets.reserve(__ht._M_buckets.size()); - _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0); - try - { - for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) { - const _Node* __cur = __ht._M_buckets[__i]; - if (__cur) - { - _Node* __local_copy = _M_new_node(__cur->_M_val); - _M_buckets[__i] = __local_copy; - - for (_Node* __next = __cur->_M_next; - __next; - __cur = __next, __next = __cur->_M_next) - { - __local_copy->_M_next = _M_new_node(__next->_M_val); - __local_copy = __local_copy->_M_next; - } - } - } - _M_num_elements = __ht._M_num_elements; - } - catch(...) - { - clear(); - __throw_exception_again; - } - } - -_GLIBCXX_END_NAMESPACE - -#endif diff --git a/libstdc++-v3/include/profile/impl/profiler.h b/libstdc++-v3/include/profile/impl/profiler.h index c9db6cde4c3..81d8dbad462 100644 --- a/libstdc++-v3/include/profile/impl/profiler.h +++ b/libstdc++-v3/include/profile/impl/profiler.h @@ -43,6 +43,20 @@ #include <stddef.h> #endif +// Mechanism to define data with inline linkage. +#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 std::__cxxprof_guard + * @brief Mechanism to protect all __gnu_profile operations against + * multithreaded and exception reentrance. + */ namespace __gnu_profile { /** @brief Reentrance guard. @@ -53,80 +67,127 @@ namespace __gnu_profile struct __reentrance_guard { static bool - _S_set_in() + __get_in() { - if (_S_get_in()) + if (__inside() == true) return false; else { - _S_get_in() = true; + __inside() = true; return true; } } static bool& - _S_get_in() + __inside() { static __thread bool _S_inside(false); return _S_inside; } __reentrance_guard() { } - ~__reentrance_guard() { _S_get_in() = false; } + ~__reentrance_guard() { __inside() = false; } }; #define _GLIBCXX_PROFILE_REENTRANCE_GUARD(__x...) \ { \ - if (__gnu_profile::__reentrance_guard::_S_get_in()) \ + if (__gnu_profile::__reentrance_guard::__get_in()) \ { \ __gnu_profile::__reentrance_guard __get_out; \ __x; \ } \ } +} + +/** + * @namespace std::__gnu_profile + * @brief Implementation of profile extension. + */ +namespace __gnu_profile +{ +// 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*, size_t, size_t); +void __trace_hashtable_size_destruct(const void*, size_t, size_t); +void __trace_hashtable_size_construct(const void*, size_t); +void __trace_vector_size_resize(const void*, size_t, size_t); +void __trace_vector_size_destruct(const void*, size_t, size_t); +void __trace_vector_size_construct(const void*, size_t); +void __trace_hash_func_destruct(const void*, size_t, size_t, size_t); +void __trace_hash_func_construct(const void*); +void __trace_vector_to_list_destruct(const void*); +void __trace_vector_to_list_construct(const void*); +void __trace_vector_to_list_insert(const void*, size_t, size_t); +void __trace_vector_to_list_iterate(const void*, size_t); +void __trace_vector_to_list_invalid_operator(const void*); +void __trace_vector_to_list_resize(const void*, size_t, size_t); +void __trace_vector_to_list_find(const void*, 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*, size_t, size_t); +void __trace_list_to_vector_iterate(const void*, size_t); +void __trace_list_to_vector_invalid_operator(const void*); +void __trace_list_to_vector_resize(const void*, size_t, 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*, size_t, size_t); +void __trace_list_to_set_iterate(const void*, size_t); +void __trace_list_to_set_invalid_operator(const void*); +void __trace_list_to_set_find(const void*, size_t); - // Forward declarations of implementation functions. - // Don't use any __gnu_profile:: in user code. - // Instead, use the __profcxx... macros, which offer guarded access. - void __turn_on(); - void __turn_off(); - bool __is_invalid(); - bool __is_on(); - bool __is_off(); - void __report(void); - void __trace_hashtable_size_resize(const void*, size_t, size_t); - void __trace_hashtable_size_destruct(const void*, size_t, size_t); - void __trace_hashtable_size_construct(const void*, size_t); - void __trace_vector_size_resize(const void*, size_t, size_t); - void __trace_vector_size_destruct(const void*, size_t, size_t); - void __trace_vector_size_construct(const void*, size_t); - void __trace_hash_func_destruct(const void*, size_t, size_t, size_t); - void __trace_hash_func_construct(const void*); - void __trace_vector_to_list_destruct(const void*); - void __trace_vector_to_list_construct(const void*); - void __trace_vector_to_list_insert(const void*, size_t, size_t); - void __trace_vector_to_list_iterate(const void*, size_t); - void __trace_vector_to_list_invalid_operator(const void*); - void __trace_vector_to_list_resize(const void*, size_t, size_t); - void __trace_map_to_unordered_map_construct(const void*); - void __trace_map_to_unordered_map_invalidate(const void*); - void __trace_map_to_unordered_map_insert(const void*, size_t, size_t); - void __trace_map_to_unordered_map_erase(const void*, size_t, size_t); - void __trace_map_to_unordered_map_iterate(const void*, size_t); - void __trace_map_to_unordered_map_find(const void*, size_t); - void __trace_map_to_unordered_map_destruct(const void*); +void __trace_map_to_unordered_map_construct(const void*); +void __trace_map_to_unordered_map_invalidate(const void*); +void __trace_map_to_unordered_map_insert(const void*, size_t, size_t); +void __trace_map_to_unordered_map_erase(const void*, size_t, size_t); +void __trace_map_to_unordered_map_iterate(const void*, size_t); +void __trace_map_to_unordered_map_find(const void*, size_t); +void __trace_map_to_unordered_map_destruct(const void*); } // namespace __gnu_profile -// Master switch turns on all diagnostics. +// 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 @@ -152,10 +213,8 @@ namespace __gnu_profile #endif // Turn on/off instrumentation for HASHTABLE_TOO_SMALL and HASHTABLE_TOO_LARGE. -#if ((defined(_GLIBCXX_PROFILE_HASHTABLE_TOO_SMALL) \ - && !defined(_NO_GLIBCXX_PROFILE_HASHTABLE_TOO_SMALL)) \ - || (defined(_GLIBCXX_PROFILE_HASHTABLE_TOO_LARGE) \ - && !defined(_NO_GLIBCXX_PROFILE_HASHTABLE_TOO_LARGE))) +#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)) @@ -166,16 +225,14 @@ namespace __gnu_profile _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...) +#define __profcxx_hashtable_resize(__x...) +#define __profcxx_hashtable_destruct(__x...) +#define __profcxx_hashtable_construct(__x...) #endif // Turn on/off instrumentation for VECTOR_TOO_SMALL and VECTOR_TOO_LARGE. -#if ((defined(_GLIBCXX_PROFILE_VECTOR_TOO_SMALL) \ - && !defined(_NO_GLIBCXX_PROFILE_VECTOR_TOO_SMALL)) \ - || (defined(_GLIBCXX_PROFILE_VECTOR_TOO_LARGE) \ - && !defined(_NO_GLIBCXX_PROFILE_VECTOR_TOO_LARGE))) +#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)) @@ -186,14 +243,13 @@ namespace __gnu_profile _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 +#define __profcxx_vector_resize(__x...) +#define __profcxx_vector_destruct(__x...) +#define __profcxx_vector_construct(__x...) +#endif // Turn on/off instrumentation for INEFFICIENT_HASH. -#if (defined(_GLIBCXX_PROFILE_INEFFICIENT_HASH) \ - && !defined(_NO_GLIBCXX_PROFILE_INEFFICIENT_HASH)) +#if defined(_GLIBCXX_PROFILE_INEFFICIENT_HASH) #define __profcxx_hashtable_construct2(__x...) \ _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ __gnu_profile::__trace_hash_func_construct(__x)) @@ -201,13 +257,12 @@ namespace __gnu_profile _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ __gnu_profile::__trace_hash_func_destruct(__x)) #else -#define __profcxx_hashtable_destruct2(__x...) -#define __profcxx_hashtable_construct2(__x...) +#define __profcxx_hashtable_destruct2(__x...) +#define __profcxx_hashtable_construct2(__x...) #endif // Turn on/off instrumentation for VECTOR_TO_LIST. -#if (defined(_GLIBCXX_PROFILE_VECTOR_TO_LIST) \ - && !defined(_NO_GLIBCXX_PROFILE_VECTOR_TO_LIST)) +#if defined(_GLIBCXX_PROFILE_VECTOR_TO_LIST) #define __profcxx_vector_construct2(__x...) \ _GLIBCXX_PROFILE_REENTRANCE_GUARD( \ __gnu_profile::__trace_vector_to_list_construct(__x)) @@ -226,6 +281,9 @@ namespace __gnu_profile #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...) @@ -233,11 +291,57 @@ namespace __gnu_profile #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) \ - && !defined(_NO_GLIBCXX_PROFILE_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)) @@ -261,7 +365,7 @@ namespace __gnu_profile __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...) @@ -271,7 +375,7 @@ namespace __gnu_profile #endif // Run multithreaded unless instructed not to do so. -#ifndef _GLIBCXX_PROFILE_NOTHREADS +#ifndef _GLIBCXX_PROFILE_NO_THREADS #define _GLIBCXX_PROFILE_THREADS #endif @@ -280,11 +384,11 @@ namespace __gnu_profile #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" +#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" + "_GLIBCXX_PROFILE_MAX_WARN_COUNT" #endif #ifndef _GLIBCXX_PROFILE_MAX_WARN_COUNT #define _GLIBCXX_PROFILE_MAX_WARN_COUNT 10 @@ -294,14 +398,14 @@ namespace __gnu_profile #endif #ifndef _GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR #define _GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR \ - "GLIBCXX_PROFILE_MAX_STACK_DEPTH" + "_GLIBCXX_PROFILE_MAX_STACK_DEPTH" #endif #ifndef _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC #define _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC 2 << 27 #endif #ifndef _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR #define _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR \ - "GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC" + "_GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC" #endif // Instrumentation hook implementations. @@ -310,5 +414,7 @@ namespace __gnu_profile #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_container_size.h b/libstdc++-v3/include/profile/impl/profiler_container_size.h index 71f5556fa93..bfbab85199b 100644 --- a/libstdc++-v3/include/profile/impl/profiler_container_size.h +++ b/libstdc++-v3/include/profile/impl/profiler_container_size.h @@ -47,214 +47,196 @@ #include <string.h> #endif +#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(); - __container_size_info(const __container_size_info& __o); - __container_size_info(__stack_t __stack, size_t __num); - virtual ~__container_size_info() { } - - void __write(FILE* f) const; - float __magnitude() const { return static_cast<float>(_M_cost); } - const char* __advice() const; - - void __merge(const __container_size_info& __o); - - // Call if a container is destructed or cleaned. - void __destruct(size_t __num, size_t __inum); - - // Estimate the cost of resize/rehash. - float __resize_cost(size_t __from, size_t __to) { return __from; } - - // Call if container is resized. - void __resize(size_t __from, size_t __to); - - private: - size_t _M_init; - size_t _M_max; // Range of # buckets. - size_t _M_min; - size_t _M_total; - size_t _M_item_min; // Range of # items. - size_t _M_item_max; - size_t _M_item_total; - size_t _M_count; - size_t _M_resize; - size_t _M_cost; - }; - - inline const char* - __container_size_info::__advice() const - { - const size_t __max_chars_size_t_printed = 20; - const char* __message_pattern = - "change initial container size from %d to %d"; - size_t __message_size = (strlen(__message_pattern) - + 2 * __max_chars_size_t_printed - - 2 * 2); - char* __message = new char[__message_size + 1]; - - if (_M_init < _M_item_max) - snprintf(__message, __message_size, __message_pattern, _M_init, - _M_item_max); - else - snprintf(__message, __message_size, __message_pattern, _M_init, - _M_item_max); - - return __message; - } - inline void - __container_size_info::__destruct(size_t __num, size_t __inum) - { - _M_max = __max(_M_max, __num); - _M_item_max = __max(_M_item_max, __inum); - if (_M_min == 0) - { - _M_min = __num; - _M_item_min = __inum; - } - else - { - _M_min = __min(_M_min, __num); - _M_item_min = __min(_M_item_min, __inum); - } - _M_total += __num; - _M_item_total += __inum; - _M_count += 1; - } +/** @brief A container size instrumentation line in the object table. */ +class __container_size_info: public __object_info_base +{ + public: + __container_size_info(); + __container_size_info(const __container_size_info& __o); + __container_size_info(__stack_t __stack, size_t __num); + virtual ~__container_size_info() {} + + void __write(FILE* f) const; + float __magnitude() const { return static_cast<float>(_M_cost); } + const char* __advice() const; + + void __merge(const __container_size_info& __o); + // Call if a container is destructed or cleaned. + void __destruct(size_t __num, size_t __inum); + // Estimate the cost of resize/rehash. + float __resize_cost(size_t __from, size_t __to) { return __from; } + // Call if container is resized. + void __resize(size_t __from, size_t __to); + + private: + size_t _M_init; + size_t _M_max; // range of # buckets + size_t _M_min; + size_t _M_total; + size_t _M_item_min; // range of # items + size_t _M_item_max; + size_t _M_item_total; + size_t _M_count; + size_t _M_resize; + size_t _M_cost; +}; + +inline const char* __container_size_info::__advice() const +{ + std::stringstream __message; + if (_M_init < _M_item_max) + __message << "change initial container size from " << _M_init + << " to " << _M_item_max; - inline void - __container_size_info::__resize(size_t __from, size_t __to) - { - _M_cost += this->__resize_cost(__from, __to); - _M_resize += 1; - _M_max = __max(_M_max, __to); - } + return strdup(__message.str().c_str()); +} - inline void - __container_size_info::__merge(const __container_size_info& __o) - { - _M_init = __max(_M_init, __o._M_init); - _M_max = __max(_M_max, __o._M_max); - _M_item_max = __max(_M_item_max, __o._M_item_max); - _M_min = __min(_M_min, __o._M_min); - _M_item_min = __min(_M_item_min, __o._M_item_min); - _M_total += __o._M_total; - _M_item_total += __o._M_item_total; - _M_count += __o._M_count; - _M_cost += __o._M_cost; - _M_resize += __o._M_resize; +inline void __container_size_info::__destruct(size_t __num, size_t __inum) +{ + _M_max = __max(_M_max, __num); + _M_item_max = __max(_M_item_max, __inum); + if (_M_min == 0) { + _M_min = __num; + _M_item_min = __inum; + } else { + _M_min = __min(_M_min, __num); + _M_item_min = __min(_M_item_min, __inum); } + _M_total += __num; + _M_item_total += __inum; + _M_count += 1; +} - inline __container_size_info::__container_size_info() - : _M_init(0), _M_max(0), _M_item_max(0), _M_min(0), _M_item_min(0), - _M_total(0), _M_item_total(0), _M_cost(0), _M_count(0), _M_resize(0) - { } - - inline __container_size_info::__container_size_info(__stack_t __stack, - size_t __num) - : __object_info_base(__stack), _M_init(0), _M_max(0), _M_item_max(0), - _M_min(0), _M_item_min(0), _M_total(0), _M_item_total(0), _M_cost(0), - _M_count(0), _M_resize(0) - { - _M_init = _M_max = __num; - _M_item_min = _M_item_max = _M_item_total = _M_total = 0; - _M_min = 0; - _M_count = 0; - _M_resize = 0; - } +inline void __container_size_info::__resize(size_t __from, size_t __to) +{ + _M_cost += this->__resize_cost(__from, __to); + _M_resize += 1; + _M_max = __max(_M_max, __to); +} + +inline __container_size_info::__container_size_info(__stack_t __stack, + size_t __num) + : __object_info_base(__stack), _M_init(0), _M_max(0), _M_item_max(0), + _M_min(0), _M_item_min(0), _M_total(0), _M_item_total(0), _M_cost(0), + _M_count(0), _M_resize(0) +{ + _M_init = _M_max = __num; + _M_item_min = _M_item_max = _M_item_total = _M_total = 0; + _M_min = 0; + _M_count = 0; + _M_resize = 0; +} + +inline void __container_size_info::__merge(const __container_size_info& __o) +{ + _M_init = __max(_M_init, __o._M_init); + _M_max = __max(_M_max, __o._M_max); + _M_item_max = __max(_M_item_max, __o._M_item_max); + _M_min = __min(_M_min, __o._M_min); + _M_item_min = __min(_M_item_min, __o._M_item_min); + _M_total += __o._M_total; + _M_item_total += __o._M_item_total; + _M_count += __o._M_count; + _M_cost += __o._M_cost; + _M_resize += __o._M_resize; +} + +inline __container_size_info::__container_size_info() + : _M_init(0), _M_max(0), _M_item_max(0), _M_min(0), _M_item_min(0), + _M_total(0), _M_item_total(0), _M_cost(0), _M_count(0), _M_resize(0) +{ +} - inline __container_size_info::__container_size_info(const __container_size_info& __o) +inline __container_size_info::__container_size_info( + const __container_size_info& __o) : __object_info_base(__o) - { - _M_init = __o._M_init; - _M_max = __o._M_max; - _M_item_max = __o._M_item_max; - _M_min = __o._M_min; - _M_item_min = __o._M_item_min; - _M_total = __o._M_total; - _M_item_total = __o._M_item_total; - _M_cost = __o._M_cost; - _M_count = __o._M_count; - _M_resize = __o._M_resize; - } +{ + _M_init = __o._M_init; + _M_max = __o._M_max; + _M_item_max = __o._M_item_max; + _M_min = __o._M_min; + _M_item_min = __o._M_item_min; + _M_total = __o._M_total; + _M_item_total = __o._M_item_total; + _M_cost = __o._M_cost; + _M_count = __o._M_count; + _M_resize = __o._M_resize; +} + +/** @brief A container size instrumentation line in the stack table. */ +class __container_size_stack_info: public __container_size_info +{ + public: + __container_size_stack_info(const __container_size_info& __o) + : __container_size_info(__o) {} +}; + +/** @brief Container size instrumentation trace producer. */ +class __trace_container_size + : public __trace_base<__container_size_info, __container_size_stack_info> +{ + public: + ~__trace_container_size() {} + __trace_container_size() + : __trace_base<__container_size_info, __container_size_stack_info>() {}; + + // Insert a new node at construct with object, callstack and initial size. + void __insert(const __object_t __obj, __stack_t __stack, size_t __num); + // Call at destruction/clean to set container final size. + void __destruct(const void* __obj, size_t __num, size_t __inum); + void __construct(const void* __obj, size_t __inum); + // Call at resize to set resize/cost information. + void __resize(const void* __obj, int __from, int __to); +}; + +inline void __trace_container_size::__insert(const __object_t __obj, + __stack_t __stack, size_t __num) +{ + __add_object(__obj, __container_size_info(__stack, __num)); +} - /** @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_base<__container_size_info, __container_size_stack_info>() { }; - - ~__trace_container_size() { } - - // Insert a new node at construct with object, callstack and initial size. - void __insert(const __object_t __obj, __stack_t __stack, size_t __num); - - // Call at destruction/clean to set container final size. - void __destruct(const void* __obj, size_t __num, size_t __inum); - void __construct(const void* __obj, size_t __inum); - - // Call at resize to set resize/cost information. - void __resize(const void* __obj, int __from, int __to); - }; - - inline void - __trace_container_size::__insert(const __object_t __obj, - __stack_t __stack, size_t __num) - { __add_object(__obj, __container_size_info(__stack, __num)); } - - inline void - __container_size_info::__write(FILE* __f) const - { - fprintf(__f, "%Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu\n", - _M_init, _M_count, _M_cost, _M_resize, _M_min, _M_max, _M_total, - _M_item_min, _M_item_max, _M_item_total); - } +inline void __container_size_info::__write(FILE* __f) const +{ + fprintf(__f, "%Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu %Zu\n", + _M_init, _M_count, _M_cost, _M_resize, _M_min, _M_max, _M_total, + _M_item_min, _M_item_max, _M_item_total); +} - inline void - __trace_container_size::__destruct(const void* __obj, size_t __num, - size_t __inum) - { - if (!__is_on()) return; +inline void __trace_container_size::__destruct(const void* __obj, + size_t __num, size_t __inum) +{ + if (!__is_on()) return; - __object_t __obj_handle = static_cast<__object_t>(__obj); + __object_t __obj_handle = static_cast<__object_t>(__obj); - __container_size_info* __object_info = __get_object_info(__obj_handle); - if (!__object_info) - return; + __container_size_info* __object_info = __get_object_info(__obj_handle); + if (!__object_info) + return; - __object_info->__destruct(__num, __inum); - __retire_object(__obj_handle); - } + __object_info->__destruct(__num, __inum); + __retire_object(__obj_handle); +} - inline void - __trace_container_size::__resize(const void* __obj, int __from, int __to) - { - if (!__is_on()) return; +inline void __trace_container_size::__resize(const void* __obj, int __from, + int __to) +{ + if (!__is_on()) return; - __container_size_info* __object_info = __get_object_info(__obj); - if (!__object_info) - return; + __container_size_info* __object_info = __get_object_info(__obj); + if (!__object_info) + return; + + __object_info->__resize(__from, __to); +} - __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 index 86859e5601a..95fad192590 100644 --- a/libstdc++-v3/include/profile/impl/profiler_hash_func.h +++ b/libstdc++-v3/include/profile/impl/profiler_hash_func.h @@ -52,143 +52,134 @@ namespace __gnu_profile { - /** @brief A hash performance instrumentation line in the object table. */ - class __hashfunc_info: public __object_info_base - { - public: - __hashfunc_info() :_M_longest_chain(0), _M_accesses(0), _M_hops(0) { } - - __hashfunc_info(const __hashfunc_info& o); - - __hashfunc_info(__stack_t __stack) - : __object_info_base(__stack), _M_longest_chain(0), - _M_accesses(0), _M_hops(0) { } - - virtual ~__hashfunc_info() { } - - void __merge(const __hashfunc_info& __o); - void __destruct(size_t __chain, size_t __accesses, size_t __hops); - void __write(FILE* __f) const; - float __magnitude() const { return static_cast<float>(_M_hops); } - const char* __advice() const { return "change hash function"; } - - private: - size_t _M_longest_chain; - size_t _M_accesses; - size_t _M_hops; - }; - - inline __hashfunc_info::__hashfunc_info(const __hashfunc_info& __o) - : __object_info_base(__o) - { - _M_longest_chain = __o._M_longest_chain; - _M_accesses = __o._M_accesses; - _M_hops = __o._M_hops; - } - inline void - __hashfunc_info::__merge(const __hashfunc_info& __o) - { - _M_longest_chain = __max(_M_longest_chain, __o._M_longest_chain); - _M_accesses += __o._M_accesses; - _M_hops += __o._M_hops; - } +/** @brief A hash performance instrumentation line in the object table. */ +class __hashfunc_info: public __object_info_base +{ + public: + __hashfunc_info() + :_M_longest_chain(0), _M_accesses(0), _M_hops(0) {} + __hashfunc_info(const __hashfunc_info& o); + __hashfunc_info(__stack_t __stack) + : __object_info_base(__stack), + _M_longest_chain(0), _M_accesses(0), _M_hops(0){} + virtual ~__hashfunc_info() {} + + void __merge(const __hashfunc_info& __o); + void __destruct(size_t __chain, size_t __accesses, size_t __hops); + void __write(FILE* __f) const; + float __magnitude() const { return static_cast<float>(_M_hops); } + const char* __advice() const { return strdup("change hash function"); } + +private: + size_t _M_longest_chain; + size_t _M_accesses; + size_t _M_hops; +}; + +inline __hashfunc_info::__hashfunc_info(const __hashfunc_info& __o) + : __object_info_base(__o) +{ + _M_longest_chain = __o._M_longest_chain; + _M_accesses = __o._M_accesses; + _M_hops = __o._M_hops; +} - inline void - __hashfunc_info::__destruct(size_t __chain, size_t __accesses, size_t __hops) - { - _M_longest_chain = __max(_M_longest_chain, __chain); - _M_accesses += __accesses; - _M_hops += __hops; - } +inline void __hashfunc_info::__merge(const __hashfunc_info& __o) +{ + _M_longest_chain = __max(_M_longest_chain, __o._M_longest_chain); + _M_accesses += __o._M_accesses; + _M_hops += __o._M_hops; +} + +inline void __hashfunc_info::__destruct(size_t __chain, size_t __accesses, + size_t __hops) +{ + _M_longest_chain = __max(_M_longest_chain, __chain); + _M_accesses += __accesses; + _M_hops += __hops; +} + +/** @brief A hash performance instrumentation line in the stack table. */ +class __hashfunc_stack_info: public __hashfunc_info { + public: + __hashfunc_stack_info(const __hashfunc_info& __o) : __hashfunc_info(__o) {} +}; + +/** @brief Hash performance instrumentation producer. */ +class __trace_hash_func + : public __trace_base<__hashfunc_info, __hashfunc_stack_info> +{ + public: + __trace_hash_func(); + ~__trace_hash_func() {} + + // Insert a new node at construct with object, callstack and initial size. + void __insert(__object_t __obj, __stack_t __stack); + // Call at destruction/clean to set container final size. + void __destruct(const void* __obj, size_t __chain, + size_t __accesses, size_t __hops); +}; + +inline __trace_hash_func::__trace_hash_func() + : __trace_base<__hashfunc_info, __hashfunc_stack_info>() +{ + __id = "hash-distr"; +} - /** @brief A hash performance instrumentation line in the stack table. */ - class __hashfunc_stack_info: public __hashfunc_info - { - public: - __hashfunc_stack_info(const __hashfunc_info& __o) : __hashfunc_info(__o) { } - }; - - /** @brief Hash performance instrumentation producer. */ - class __trace_hash_func - : public __trace_base<__hashfunc_info, __hashfunc_stack_info> - { - public: - __trace_hash_func(); - ~__trace_hash_func() { } - - // Insert a new node at construct with object, callstack and initial size. - void __insert(__object_t __obj, __stack_t __stack); - - // Call at destruction/clean to set container final size. - void __destruct(const void* __obj, size_t __chain, size_t __accesses, - size_t __hops); - }; - - inline __trace_hash_func::__trace_hash_func() - : __trace_base<__hashfunc_info, __hashfunc_stack_info>() - { __id = "hash-distr"; } - - inline void - __trace_hash_func::__insert(__object_t __obj, __stack_t __stack) - { __add_object(__obj, __hashfunc_info(__stack)); } - - inline void - __hashfunc_info::__write(FILE* __f) const - { fprintf(__f, "%Zu %Zu %Zu\n", _M_hops, _M_accesses, _M_longest_chain); } - - inline void - __trace_hash_func::__destruct(const void* __obj, size_t __chain, - size_t __accesses, size_t __hops) - { - if (!__is_on()) - return; - - // First find the item from the live objects and update the informations. - __hashfunc_info* __objs = __get_object_info(__obj); - if (!__objs) - return; - - __objs->__destruct(__chain, __accesses, __hops); - __retire_object(__obj); - } +inline void __trace_hash_func::__insert(__object_t __obj, __stack_t __stack) +{ + __add_object(__obj, __hashfunc_info(__stack)); +} +inline void __hashfunc_info::__write(FILE* __f) const +{ + fprintf(__f, "%Zu %Zu %Zu\n", _M_hops, _M_accesses, _M_longest_chain); +} - // Initialization and report. - inline void - __trace_hash_func_init() - { __tables<0>::_S_hash_func = new __trace_hash_func(); } +inline void __trace_hash_func::__destruct(const void* __obj, size_t __chain, + size_t __accesses, size_t __hops) +{ + if (!__is_on()) return; - inline void - __trace_hash_func_report(FILE* __f, __warning_vector_t& __warnings) - { - if (__tables<0>::_S_hash_func) - { - __tables<0>::_S_hash_func->__collect_warnings(__warnings); - __tables<0>::_S_hash_func->__write(__f); - } - } + // 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); +} - // Implementations of instrumentation hooks. - inline void - __trace_hash_func_construct(const void* __obj) - { - if (!__profcxx_init()) - return; +inline void __trace_hash_func_init() +{ + _GLIBCXX_PROFILE_DATA(_S_hash_func) = new __trace_hash_func(); +} - __tables<0>::_S_hash_func->__insert(__obj, __get_stack()); +inline void __trace_hash_func_report(FILE* __f, + __warning_vector_t& __warnings) +{ + if (_GLIBCXX_PROFILE_DATA(_S_hash_func)) { + _GLIBCXX_PROFILE_DATA(_S_hash_func)->__collect_warnings(__warnings); + _GLIBCXX_PROFILE_DATA(_S_hash_func)->__write(__f); } +} - inline void - __trace_hash_func_destruct(const void* __obj, size_t __chain, - size_t __accesses, size_t __hops) - { - if (!__profcxx_init()) - return; +inline void __trace_hash_func_construct(const void* __obj) +{ + if (!__profcxx_init()) return; - __tables<0>::_S_hash_func->__destruct(__obj, __chain, __accesses, __hops); - } + _GLIBCXX_PROFILE_DATA(_S_hash_func)->__insert(__obj, __get_stack()); +} + +inline void __trace_hash_func_destruct(const void* __obj, size_t __chain, + size_t __accesses, size_t __hops) +{ + if (!__profcxx_init()) return; + + _GLIBCXX_PROFILE_DATA(_S_hash_func)->__destruct(__obj, __chain, __accesses, + __hops); +} } // namespace __gnu_profile #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 index da89c071138..8248f47e75d 100644 --- a/libstdc++-v3/include/profile/impl/profiler_hashtable_size.h +++ b/libstdc++-v3/include/profile/impl/profiler_hashtable_size.h @@ -54,57 +54,54 @@ 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"; } - }; - - // Initialization and report. - inline void - __trace_hashtable_size_init() - { __tables<0>::_S_hashtable_size = new __trace_hashtable_size(); } - - inline void - __trace_hashtable_size_report(FILE* __f, __warning_vector_t& __warnings) + +/** @brief Hashtable size instrumentation trace producer. */ +class __trace_hashtable_size : public __trace_container_size +{ + public: + __trace_hashtable_size() : __trace_container_size() { - if (__tables<0>::_S_hashtable_size) - { - __tables<0>::_S_hashtable_size->__collect_warnings(__warnings); - __tables<0>::_S_hashtable_size->__write(__f); - } + __id = "hashtable-size"; } +}; - // Implementations of instrumentation hooks. - inline void - __trace_hashtable_size_construct(const void* __obj, size_t __num) - { - if (!__profcxx_init()) - return; +inline void __trace_hashtable_size_init() +{ + _GLIBCXX_PROFILE_DATA(_S_hashtable_size) = new __trace_hashtable_size(); +} - __tables<0>::_S_hashtable_size->__insert(__obj, __get_stack(), __num); +inline void __trace_hashtable_size_report(FILE* __f, + __warning_vector_t& __warnings) +{ + if (_GLIBCXX_PROFILE_DATA(_S_hashtable_size)) { + _GLIBCXX_PROFILE_DATA(_S_hashtable_size)->__collect_warnings(__warnings); + _GLIBCXX_PROFILE_DATA(_S_hashtable_size)->__write(__f); } +} - inline void - __trace_hashtable_size_destruct(const void* __obj, size_t __num, - size_t __inum) - { - if (!__profcxx_init()) - return; +inline void __trace_hashtable_size_construct(const void* __obj, 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, size_t __num, + size_t __inum) +{ + if (!__profcxx_init()) return; - __tables<0>::_S_hashtable_size->__destruct(__obj, __num, __inum); - } + _GLIBCXX_PROFILE_DATA(_S_hashtable_size)->__destruct(__obj, __num, __inum); +} - inline void - __trace_hashtable_size_resize(const void* __obj, size_t __from, size_t __to) - { - if (!__profcxx_init()) - return; +inline void __trace_hashtable_size_resize(const void* __obj, size_t __from, + size_t __to) +{ + if (!__profcxx_init()) return; - __tables<0>::_S_hashtable_size->__resize(__obj, __from, __to); - } + _GLIBCXX_PROFILE_DATA(_S_hashtable_size)->__resize(__obj, __from, __to); +} } // namespace __gnu_profile 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 00000000000..073bdf27587 --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_list_to_slist.h @@ -0,0 +1,182 @@ +// -*- C++ -*- +// +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License as published by the Free Software +// Foundation; either version 2, or (at your option) any later +// version. + +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, Boston, +// MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +/** @file profile/impl/profiler_list_to_slist.h + * @brief Diagnostics for list to slist. + */ + +// Written by Changhee Jung. + +#ifndef _GLIBCXX_PROFILE_PROFILER_LIST_TO_SLIST_H +#define _GLIBCXX_PROFILE_PROFILER_LIST_TO_SLIST_H 1 + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#include <cstdlib> +#include <cstdio> +#include <cstring> +#else +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#endif +#include "profile/impl/profiler.h" +#include "profile/impl/profiler_node.h" +#include "profile/impl/profiler_trace.h" + +namespace __gnu_profile +{ + +class __list2slist_info: public __object_info_base +{ + public: + __list2slist_info() : _M_rewind(false), _M_operations(0) {} + __list2slist_info(__stack_t __stack) + : _M_rewind(false), _M_operations(0),__object_info_base(__stack) {} + virtual ~__list2slist_info() {} + __list2slist_info(const __list2slist_info& __o) : __object_info_base(__o) + { _M_rewind = __o._M_rewind; _M_operations = __o._M_operations; } + // XXX: the magnitude should be multiplied with a constant factor F, + // where F is 1 when the malloc size class of list nodes is different + // from the malloc size class of slist nodes. When they fall into the same + // class, the only slist benefit is from having to set fewer links, so + // the factor F should be much smaller, closer to 0 than to 1. + // This could be implemented by passing the size classes in the config file. + // For now, we always assume F to be 1. + float __magnitude() const + { if (!_M_rewind) return _M_operations; else return 0; } + void __merge(const __list2slist_info& __o) {}; + void __write(FILE* __f) const; + const char* __advice() const + { return strdup("change std::list to std::forward_list"); } + void __opr_rewind() { _M_rewind = true; _M_valid = false;} + void __record_operation() { _M_operations++; } + bool __has_rewind() { return _M_rewind; } + +private: + bool _M_rewind; + size_t _M_operations; +}; + +class __list2slist_stack_info: public __list2slist_info { + public: + __list2slist_stack_info(const __list2slist_info& __o) + : __list2slist_info(__o) {} +}; + +class __trace_list_to_slist + : public __trace_base<__list2slist_info, __list2slist_stack_info> +{ + public: + ~__trace_list_to_slist() {} + __trace_list_to_slist() + : __trace_base<__list2slist_info, __list2slist_stack_info>() + { __id = "list-to-slist"; } + void __opr_rewind(const void* __obj); + void __record_operation(const void* __obj); + void __insert(const __object_t __obj, __stack_t __stack) + { __add_object(__obj, __list2slist_info(__stack)); } + void __destruct(const void* __obj); +}; + +inline void __list2slist_info::__write(FILE* __f) const +{ + fprintf(__f, "%s\n", _M_rewind ? "invalid" : "valid"); +} + +inline void __trace_list_to_slist::__destruct(const void* __obj) +{ + if (!__is_on()) + return; + + __list2slist_info* __res = __get_object_info(__obj); + if (!__res) + return; + + __retire_object(__obj); +} + +inline void __trace_list_to_slist_init() +{ + _GLIBCXX_PROFILE_DATA(_S_list_to_slist) = new __trace_list_to_slist(); +} + +inline void __trace_list_to_slist_report(FILE* __f, + __warning_vector_t& __warnings) +{ + if (_GLIBCXX_PROFILE_DATA(_S_list_to_slist)) { + _GLIBCXX_PROFILE_DATA(_S_list_to_slist)->__collect_warnings(__warnings); + _GLIBCXX_PROFILE_DATA(_S_list_to_slist)->__write(__f); + } +} + +inline void __trace_list_to_slist::__opr_rewind(const void* __obj) +{ + __list2slist_info* __res = __get_object_info(__obj); + if (__res) + __res->__opr_rewind(); +} + +inline void __trace_list_to_slist::__record_operation(const void* __obj) +{ + __list2slist_info* __res = __get_object_info(__obj); + if (__res) + __res->__record_operation(); +} + +inline void __trace_list_to_slist_rewind(const void* __obj) +{ + if (!__profcxx_init()) return; + + _GLIBCXX_PROFILE_DATA(_S_list_to_slist)->__opr_rewind(__obj); +} + +inline void __trace_list_to_slist_operation(const void* __obj) +{ + if (!__profcxx_init()) return; + + _GLIBCXX_PROFILE_DATA(_S_list_to_slist)->__record_operation(__obj); +} + +inline void __trace_list_to_slist_construct(const void* __obj) +{ + if (!__profcxx_init()) return; + + _GLIBCXX_PROFILE_DATA(_S_list_to_slist)->__insert(__obj, __get_stack()); +} + +inline void __trace_list_to_slist_destruct(const void* __obj) +{ + if (!__profcxx_init()) return; + + _GLIBCXX_PROFILE_DATA(_S_list_to_slist)->__destruct(__obj); +} + +} // namespace __gnu_profile +#endif /* _GLIBCXX_PROFILE_PROFILER_LIST_TO_SLIST_H */ 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 00000000000..d3a3713954c --- /dev/null +++ b/libstdc++-v3/include/profile/impl/profiler_list_to_vector.h @@ -0,0 +1,313 @@ +// -*- C++ -*- +// +// Copyright (C) 2009 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License as published by the Free Software +// Foundation; either version 2, or (at your option) any later +// version. + +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this library; see the file COPYING. If not, write to +// the Free Software Foundation, 59 Temple Place - Suite 330, Boston, +// MA 02111-1307, USA. + +// As a special exception, you may use this file as part of a free +// software library without restriction. Specifically, if other files +// instantiate templates or use macros or inline functions from this +// file, or you compile this file and link it with other files to +// produce an executable, this file does not by itself cause the +// resulting executable to be covered by the GNU General Public +// License. This exception does not however invalidate any other +// reasons why the executable file might be covered by the GNU General +// Public License. + +/** @file profile/impl/profiler_list_to_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 + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +#include <cstdio> +#include <cstdlib> +#include <cstring> +#else +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#endif +#include <string> +#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); + void __merge(const __list2vector_info& __o); + void __write(FILE* __f) const; + float __magnitude() const { return _M_list_cost - _M_vector_cost; } + const char* __advice() const; + size_t __shift_count() { return _M_shift_count; } + size_t __iterate() { return _M_iterate; } + float __list_cost() { return _M_list_cost; } + size_t __resize() { return _M_resize; } + void __set_list_cost(float __lc) { _M_list_cost = __lc; } + void __set_vector_cost(float __vc) { _M_vector_cost = __vc; } + bool __is_valid() { return _M_valid; } + void __set_invalid() { _M_valid = false; } + + void __opr_insert(size_t __shift, size_t __size); + void __opr_iterate(size_t __num) { _M_iterate += __num;} + + void __resize(size_t __from, size_t __to); + +private: + size_t _M_shift_count; + size_t _M_iterate; + size_t _M_resize; + float _M_list_cost; + float _M_vector_cost; + bool _M_valid; + size_t _M_max_size; +}; + +inline __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_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 = __o._M_max_size; +} + +inline const char* __list2vector_info::__advice() const { + std::stringstream __sstream; + __sstream + << "change std::list to std::vector and its initial size from 0 to " + << _M_max_size; + return strdup(__sstream.str().c_str()); +} + +inline void __list2vector_info::__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 = __max( _M_max_size, __o._M_max_size); +} + +inline void __list2vector_info::__opr_insert(size_t __shift, size_t __size) +{ + _M_shift_count += __shift; + _M_max_size = __max(_M_max_size, __size); +} + +inline void __list2vector_info::__resize(size_t __from, size_t __to) +{ + _M_resize += __from; +} + +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_list_to_vector() {} + + // Insert a new node at construct with object, callstack and initial size. + void __insert(__object_t __obj, __stack_t __stack); + // Call at destruction/clean to set container final size. + void __destruct(const void* __obj); + + // Find the node in the live map. + __list2vector_info* __find(const void* __obj); + + // Collect cost of operations. + void __opr_insert(const void* __obj, size_t __shift, size_t __size); + void __opr_iterate(const void* __obj, size_t __num); + void __invalid_operator(const void* __obj); + void __resize(const void* __obj, size_t __from, size_t __to); + float __vector_cost(size_t __shift, size_t __iterate); + float __list_cost(size_t __shift, size_t __iterate); +}; + +inline __trace_list_to_vector::__trace_list_to_vector() + : __trace_base<__list2vector_info, __list2vector_stack_info>() +{ + __id = "list-to-vector"; +} + +inline void __trace_list_to_vector::__insert(__object_t __obj, + __stack_t __stack) +{ + __add_object(__obj, __list2vector_info(__stack)); +} + +inline void __list2vector_info::__write(FILE* __f) const +{ + fprintf(__f, "%Zu %Zu %Zu %.0f %.0f\n", + _M_shift_count, _M_resize, _M_iterate, _M_vector_cost, _M_list_cost); +} + +inline float __trace_list_to_vector::__vector_cost(size_t __shift, + 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; +} + +inline float __trace_list_to_vector::__list_cost(size_t __shift, + 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::__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); +} + +inline void __trace_list_to_vector::__opr_insert(const void* __obj, + size_t __shift, size_t __size) +{ + __list2vector_info* __res = __get_object_info(__obj); + if (__res) + __res->__opr_insert(__shift, __size); +} + +inline void __trace_list_to_vector::__opr_iterate(const void* __obj, + size_t __num) +{ + __list2vector_info* __res = __get_object_info(__obj); + if (__res) { + __res->__opr_iterate(__num); + } +} + +inline void __trace_list_to_vector::__invalid_operator(const void* __obj) +{ + __list2vector_info* __res = __get_object_info(__obj); + if (__res) + __res->__set_invalid(); +} + +inline void __trace_list_to_vector::__resize(const void* __obj, size_t __from, + size_t __to) +{ + __list2vector_info* __res = __get_object_info(__obj); + if (__res) + __res->__resize(__from, __to); +} + +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, + size_t __shift, 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, 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, + size_t __from, 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 index 6c90e7a0377..e715e4cd467 100644 --- a/libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h +++ b/libstdc++-v3/include/profile/impl/profiler_map_to_unordered_map.h @@ -52,275 +52,241 @@ namespace __gnu_profile { - // Cost model. - // Map operations: - // - insert: 1.5 * log(size) - // - erase: 1.5 * log(size) - // - find: log(size) - // - iterate: 2.3 - // Unordered map operations: - // - insert: 12 - // - erase: 12 - // - find: 10 - // - iterate: 1.7 - // XXX: this must be taken from the machine model instead. - const float __map_insert_cost_factor = 1.5; - const float __map_erase_cost_factor = 1.5; - const float __map_find_cost_factor = 1; - const float __map_iterate_cost = 2.3; - - const float __umap_insert_cost = 12.0; - const float __umap_erase_cost = 12.0; - const float __umap_find_cost = 10.0; - const float __umap_iterate_cost = 1.7; - - inline int - __log2(size_t __size) + +inline int __log2(size_t __size) +{ + for (int __bit_count = sizeof(size_t) - 1; __bit_count >= 0; -- __bit_count) { - int __bit_count = sizeof(size_t) - 1; - for (; __bit_count >= 0; --__bit_count) - { - if ((2 << __bit_count) & __size) - return __bit_count; - } - return 0; + if ((2 << __bit_count) & __size) { + return __bit_count; + } } + return 0; +} - inline float - __map_insert_cost(size_t __size) - { return __map_insert_cost_factor * static_cast<float>(__log2(__size)); } - - inline float - __map_erase_cost(size_t __size) - { return __map_erase_cost_factor * static_cast<float>(__log2(__size)); } - - inline float - __map_find_cost(size_t __size) - { return __map_find_cost_factor * static_cast<float>(__log2(__size)); } +inline float __map_insert_cost(size_t __size) +{ + return (_GLIBCXX_PROFILE_DATA(__map_insert_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_map_cost(0.0), _M_umap_cost(0.0), _M_valid(true) { } - - __map2umap_info(__stack_t __stack) - : __object_info_base(__stack), _M_insert(0), _M_erase(0), _M_find(0), - _M_iterate(0), _M_map_cost(0.0), _M_umap_cost(0.0), _M_valid(true) { } - - virtual ~__map2umap_info() { } - - __map2umap_info(const __map2umap_info& o); - - void __merge(const __map2umap_info& o); - void __write(FILE* __f) const; - float __magnitude() const { return _M_map_cost - _M_umap_cost; } - const char* __advice() const; - - void __record_insert(size_t __size, size_t __count); - void __record_erase(size_t __size, size_t __count); - void __record_find(size_t __size); - void __record_iterate(size_t __count); - void __record_invalidate(); - - private: - size_t _M_insert; - size_t _M_erase; - size_t _M_find; - size_t _M_iterate; - float _M_umap_cost; - float _M_map_cost; - bool _M_valid; - }; - - inline __map2umap_info::__map2umap_info(const __map2umap_info& __o) - : __object_info_base(__o), - _M_insert(__o._M_insert), - _M_erase(__o._M_erase), - _M_find(__o._M_find), - _M_iterate(__o._M_iterate), - _M_map_cost(__o._M_map_cost), - _M_umap_cost(__o._M_umap_cost), - _M_valid(__o._M_valid) - { } - - inline const char* - __map2umap_info::__advice() const - { return "change std::map to std::unordered_map"; } - - inline void - __map2umap_info::__merge(const __map2umap_info& __o) - { - _M_insert += __o._M_insert; - _M_erase += __o._M_erase; - _M_find += __o._M_find; - _M_map_cost += __o._M_map_cost; - _M_umap_cost += __o._M_umap_cost; - _M_valid &= __o._M_valid; - } +inline float __map_erase_cost(size_t __size) +{ + return (_GLIBCXX_PROFILE_DATA(__map_erase_cost_factor).__value + * static_cast<float>(__log2(__size))); +} - inline void - __map2umap_info:: __record_insert(size_t __size, size_t __count) - { - _M_insert += __count; - _M_map_cost += __count * __map_insert_cost(__size); - _M_umap_cost += __count * __umap_insert_cost; - } +inline float __map_find_cost(size_t __size) +{ + return (_GLIBCXX_PROFILE_DATA(__map_find_cost_factor).__value + * static_cast<float>(__log2(__size))); +} - inline void - __map2umap_info:: __record_erase(size_t __size, size_t __count) - { - _M_erase += __count; - _M_map_cost += __count * __map_erase_cost(__size); - _M_umap_cost += __count * __umap_erase_cost; - } +/** @brief A map-to-unordered_map instrumentation line in the object table. */ +class __map2umap_info: public __object_info_base +{ + public: + __map2umap_info() + : _M_insert(0), _M_erase(0), _M_find(0), _M_iterate(0), + _M_map_cost(0.0), _M_umap_cost(0.0), _M_valid(true) {} + __map2umap_info(__stack_t __stack) + : __object_info_base(__stack), _M_insert(0), _M_erase(0), _M_find(0), + _M_iterate(0), _M_map_cost(0.0), _M_umap_cost(0.0), _M_valid(true) {} + virtual ~__map2umap_info() {} + __map2umap_info(const __map2umap_info& o); + void __merge(const __map2umap_info& o); + void __write(FILE* __f) const; + float __magnitude() const { return _M_map_cost - _M_umap_cost; } + const char* __advice() const; + + void __record_insert(size_t __size, size_t __count); + void __record_erase(size_t __size, size_t __count); + void __record_find(size_t __size); + void __record_iterate(size_t __count); + void __record_invalidate(); + + private: + size_t _M_insert; + size_t _M_erase; + size_t _M_find; + size_t _M_iterate; + float _M_umap_cost; + float _M_map_cost; + bool _M_valid; +}; + +inline const char* __map2umap_info::__advice() const +{ + return strdup("change std::map to std::unordered_map"); +} + +inline __map2umap_info::__map2umap_info(const __map2umap_info& __o) + : __object_info_base(__o), + _M_insert(__o._M_insert), + _M_erase(__o._M_erase), + _M_find(__o._M_find), + _M_iterate(__o._M_iterate), + _M_map_cost(__o._M_map_cost), + _M_umap_cost(__o._M_umap_cost), + _M_valid(__o._M_valid) +{} + +inline void __map2umap_info::__merge(const __map2umap_info& __o) +{ + _M_insert += __o._M_insert; + _M_erase += __o._M_erase; + _M_find += __o._M_find; + _M_map_cost += __o._M_map_cost; + _M_umap_cost += __o._M_umap_cost; + _M_valid &= __o._M_valid; +} + +inline void __map2umap_info:: __record_insert(size_t __size, size_t __count) +{ + _M_insert += __count; + _M_map_cost += __count * __map_insert_cost(__size); + _M_umap_cost += (__count + * _GLIBCXX_PROFILE_DATA(__umap_insert_cost_factor).__value); +} - inline void - __map2umap_info:: __record_find(size_t __size) - { - _M_find += 1; - _M_map_cost += __map_find_cost(__size); - _M_umap_cost += __umap_find_cost; - } +inline void __map2umap_info:: __record_erase(size_t __size, 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); +} - inline void - __map2umap_info:: __record_iterate(size_t __count) - { - _M_iterate += __count; - _M_map_cost += __count * __map_iterate_cost; - _M_umap_cost += __count * __umap_iterate_cost; - } +inline void __map2umap_info:: __record_find(size_t __size) +{ + _M_find += 1; + _M_map_cost += __map_find_cost(__size); + _M_umap_cost += _GLIBCXX_PROFILE_DATA(__umap_find_cost_factor).__value; +} - inline void - __map2umap_info:: __record_invalidate() - { - _M_valid = false; - } +inline void __map2umap_info:: __record_iterate(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); +} + +inline void __map2umap_info:: __record_invalidate() +{ + _M_valid = false; +} - inline void - __map2umap_info::__write(FILE* __f) const - { - fprintf(__f, "%Zu %Zu %Zu %Zu %.0f %.0f %s\n", - _M_insert, _M_erase, _M_find, _M_iterate, _M_map_cost, _M_umap_cost, - _M_valid ? "valid" : "invalid"); - } +inline void __map2umap_info::__write(FILE* __f) const +{ + fprintf(__f, "%Zu %Zu %Zu %Zu %.0f %.0f %s\n", + _M_insert, _M_erase, _M_find, _M_iterate, _M_map_cost, _M_umap_cost, + _M_valid ? "valid" : "invalid"); +} - /** @brief A map-to-unordered_map instrumentation line in the stack table. */ - class __map2umap_stack_info: public __map2umap_info - { - public: - __map2umap_stack_info(const __map2umap_info& o) : __map2umap_info(o) { } - }; +/** @brief 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(); - }; +/** @brief Map-to-unordered_map instrumentation producer. */ +class __trace_map2umap + : public __trace_base<__map2umap_info, __map2umap_stack_info> +{ + public: + __trace_map2umap(); +}; - inline __trace_map2umap::__trace_map2umap() - : __trace_base<__map2umap_info, __map2umap_stack_info>() - { __id = "map-to-unordered-map"; } +inline __trace_map2umap::__trace_map2umap() + : __trace_base<__map2umap_info, __map2umap_stack_info>() +{ + __id = "map-to-unordered-map"; +} - inline void - __trace_map_to_unordered_map_init() - { __tables<0>::_S_map2umap = new __trace_map2umap(); } +inline void __trace_map_to_unordered_map_init() +{ + _GLIBCXX_PROFILE_DATA(_S_map2umap) = new __trace_map2umap(); +} - inline void - __trace_map_to_unordered_map_report(FILE* __f, __warning_vector_t& __warnings) - { - if (__tables<0>::_S_map2umap) - { - __tables<0>::_S_map2umap->__collect_warnings(__warnings); - __tables<0>::_S_map2umap->__write(__f); - } +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); } +} - // Implementations of instrumentation hooks. - inline void - __trace_map_to_unordered_map_construct(const void* __obj) - { - if (!__profcxx_init()) - return; +inline void __trace_map_to_unordered_map_construct(const void* __obj) +{ + if (!__profcxx_init()) return; - __tables<0>::_S_map2umap->__add_object(__obj, - __map2umap_info(__get_stack())); - } + _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; +inline void __trace_map_to_unordered_map_destruct(const void* __obj) +{ + if (!__profcxx_init()) return; - __tables<0>::_S_map2umap->__retire_object(__obj); - } + _GLIBCXX_PROFILE_DATA(_S_map2umap)->__retire_object(__obj); +} - inline void - __trace_map_to_unordered_map_insert(const void* __obj, size_t __size, - size_t __count) - { - if (!__profcxx_init()) - return; +inline void __trace_map_to_unordered_map_insert(const void* __obj, + size_t __size, size_t __count) +{ + if (!__profcxx_init()) return; - __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj); + __map2umap_info* __info = + _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); - if (__info) - __info->__record_insert(__size, __count); - } + if (__info) __info->__record_insert(__size, __count); +} - inline void - __trace_map_to_unordered_map_erase(const void* __obj, size_t __size, - size_t __count) - { - if (!__profcxx_init()) - return; +inline void __trace_map_to_unordered_map_erase(const void* __obj, + size_t __size, size_t __count) +{ + if (!__profcxx_init()) return; - __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj); + __map2umap_info* __info = + _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); - if (__info) - __info->__record_erase(__size, __count); - } + if (__info) __info->__record_erase(__size, __count); +} - inline void - __trace_map_to_unordered_map_find(const void* __obj, size_t __size) - { - if (!__profcxx_init()) - return; +inline void __trace_map_to_unordered_map_find(const void* __obj, size_t __size) +{ + if (!__profcxx_init()) return; - __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj); + __map2umap_info* __info = + _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); - if (__info) - __info->__record_find(__size); - } + if (__info) __info->__record_find(__size); +} - inline void - __trace_map_to_unordered_map_iterate(const void* __obj, size_t __count) - { - if (!__profcxx_init()) - return; +inline void __trace_map_to_unordered_map_iterate(const void* __obj, + size_t __count) +{ + if (!__profcxx_init()) return; - __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj); + __map2umap_info* __info = + _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); - if (__info) - __info->__record_iterate(__count); - } + if (__info) __info->__record_iterate(__count); +} - inline void - __trace_map_to_unordered_map_invalidate(const void* __obj) - { - if (!__profcxx_init()) - return; +inline void __trace_map_to_unordered_map_invalidate(const void* __obj) +{ + if (!__profcxx_init()) return; - __map2umap_info* __info = __tables<0>::_S_map2umap->__get_object_info(__obj); + __map2umap_info* __info = + _GLIBCXX_PROFILE_DATA(_S_map2umap)->__get_object_info(__obj); - if (__info) - __info->__record_invalidate(); - } + 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 index 66101a7ef71..77654a8f813 100644 --- a/libstdc++-v3/include/profile/impl/profiler_node.h +++ b/libstdc++-v3/include/profile/impl/profiler_node.h @@ -47,122 +47,126 @@ #include <string.h> #endif #include <vector> -#if defined HAVE_EXECINFO_H +#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_PR::vector<__instruction_address_t> __stack_npt; - typedef __stack_npt* __stack_t; +typedef const void* __object_t; +typedef void* __instruction_address_t; +typedef std::_GLIBCXX_STD_PR::vector<__instruction_address_t> __stack_npt; +typedef __stack_npt* __stack_t; - size_t __stack_max_depth(); +size_t __stack_max_depth(); - inline __stack_t __get_stack() - { -#if defined HAVE_EXECINFO_H - size_t __max_depth = __stack_max_depth(); - if (__max_depth == 0) - return NULL; - __stack_npt __buffer(__max_depth); - int __depth = backtrace(&__buffer[0], __max_depth); - __stack_t __stack = new __stack_npt(__depth); - memcpy(&(*__stack)[0], &__buffer[0], __depth * sizeof(__object_t)); - return __stack; -#else +inline __stack_t __get_stack() +{ +#if defined _GLIBCXX_HAVE_EXECINFO_H + size_t __max_depth = __stack_max_depth(); + if (__max_depth == 0) return NULL; + __stack_npt __buffer(__max_depth); + int __depth = backtrace(&__buffer[0], __max_depth); + __stack_t __stack = new __stack_npt(__depth); + memcpy(&(*__stack)[0], &__buffer[0], __depth * sizeof(__object_t)); + return __stack; +#else + return NULL; #endif +} + +inline __size(const __stack_t& __stack) +{ + if (!__stack) { + return 0; + } else { + return __stack->size(); } +} - inline __size(const __stack_t& __stack) - { - if (!__stack) - return 0; - else - return __stack->size(); +inline void __write(FILE* __f, const __stack_t __stack) +{ + if (!__stack) { + return; + } + + __stack_npt::const_iterator __it; + for (__it = __stack->begin(); __it != __stack->end(); ++__it) { + fprintf(__f, "%p ", *__it); } +} - inline void __write(FILE* __f, const __stack_t __stack) +/** @brief Hash function for summary trace using call stack as index. */ +class __stack_hash +{ + public: + size_t operator()(const __stack_t __s) const { - if (!__stack) - return; + if (!__s) { + return 0; + } + uintptr_t __index = 0; __stack_npt::const_iterator __it; - for (__it = __stack->begin(); __it != __stack->end(); ++__it) - fprintf(__f, "%p ", *__it); + for (__it = __s->begin(); __it != __s->end(); ++__it) { + __index += reinterpret_cast<uintptr_t>(*__it); + } + return __index; } - /** @brief Hash function for summary trace using call stack as index. */ - class __stack_hash + bool operator() (const __stack_t __stack1, const __stack_t __stack2) const { - public: - size_t operator()(const __stack_t __s) const - { - if (!__s) - return 0; - - uintptr_t __index = 0; - __stack_npt::const_iterator __it; - for (__it = __s->begin(); __it != __s->end(); ++__it) - { - __index += reinterpret_cast<uintptr_t>(*__it); - } - return __index; - } + if (!__stack1 && !__stack2) return true; + if (!__stack1 || !__stack2) return false; + if (__stack1->size() != __stack2->size()) return false; - bool operator() (const __stack_t __stack1, const __stack_t __stack2) const - { - if (!__stack1 && !__stack2) return true; - if (!__stack1 || !__stack2) return false; - if (__stack1->size() != __stack2->size()) return false; + size_t __byte_size = __stack1->size() * sizeof(__stack_npt::value_type); + return memcmp(&(*__stack1)[0], &(*__stack2)[0], __byte_size) == 0; + } +}; - size_t __byte_size = __stack1->size() * sizeof(__stack_npt::value_type); - return memcmp(&(*__stack1)[0], &(*__stack2)[0], __byte_size) == 0; - } - }; +/** @brief Base class for a line in the object table. */ +class __object_info_base +{ + public: + __object_info_base() {} + __object_info_base(__stack_t __stack); + __object_info_base(const __object_info_base& o); + virtual ~__object_info_base() {} + bool __is_valid() const { return _M_valid; } + __stack_t __stack() const { return _M_stack; } + virtual void __write(FILE* f) const = 0; + + protected: + __stack_t _M_stack; + bool _M_valid; +}; + +inline __object_info_base::__object_info_base(__stack_t __stack) +{ + _M_stack = __stack; + _M_valid = true; +} - /** @brief Base class for a line in the object table. */ - class __object_info_base - { - public: - __object_info_base() { } - __object_info_base(__stack_t __stack); - __object_info_base(const __object_info_base& o); - virtual ~__object_info_base() { } - bool __is_valid() const { return _M_valid; } - __stack_t __stack() const { return _M_stack; } - virtual void __write(FILE* f) const = 0; - - protected: - __stack_t _M_stack; - bool _M_valid; - }; - - inline __object_info_base::__object_info_base(__stack_t __stack) - { - _M_stack = __stack; - _M_valid = true; - } +inline __object_info_base::__object_info_base(const __object_info_base& __o) +{ + _M_stack = __o._M_stack; + _M_valid = __o._M_valid; +} - inline __object_info_base::__object_info_base(const __object_info_base& __o) - { - _M_stack = __o._M_stack; - _M_valid = __o._M_valid; - } +/** @brief Base class for a line in the stack table. */ +template<typename __object_info> +class __stack_info_base +{ + public: + __stack_info_base() {} + __stack_info_base(const __object_info& __info) = 0; + virtual ~__stack_info_base() {} + void __merge(const __object_info& __info) = 0; + virtual float __magnitude() const = 0; + virtual const char* __get_id() const = 0; +}; - /** @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 index 347b5e248b0..540c3e4bf0c 100644 --- a/libstdc++-v3/include/profile/impl/profiler_state.h +++ b/libstdc++-v3/include/profile/impl/profiler_state.h @@ -37,72 +37,34 @@ #ifndef _GLIBCXX_PROFILE_PROFILER_STATE_H #define _GLIBCXX_PROFILE_PROFILER_STATE_H 1 -#ifdef __GXX_EXPERIMENTAL_CXX0X__ -#include <cstdio> -#else -#include <stdio.h> -#endif - namespace __gnu_profile { - /** @brief Profiling mode on/off state. */ - template<int _Unused=0> - class __state - { - private: - enum __state_type { __ON, __OFF, __INVALID }; - - __state_type _M_state; - - public: - static __state<_Unused>* _S_diag_state; - - __state() : _M_state(__INVALID) { } - ~__state() { } - - bool __is_on() { return _M_state == __ON; } - bool __is_off() { return _M_state == __OFF; } - bool __is_invalid() { return _M_state == __INVALID; } - void __turn_on() { _M_state = __ON; } - void __turn_off() { _M_state = __OFF; } - }; - - template<int _Unused> - __state<_Unused>* __state<_Unused>::_S_diag_state = NULL; - - inline bool - __is_on() - { - return __state<0>::_S_diag_state && __state<0>::_S_diag_state->__is_on(); - } - - inline bool - __is_off() - { - return __state<0>::_S_diag_state && __state<0>::_S_diag_state->__is_off(); - } - - inline bool - __is_invalid() - { - return (!__state<0>::_S_diag_state || __state<0>::_S_diag_state->__is_invalid()); - } - - inline void - __turn_on() - { - if (!__state<0>::_S_diag_state) - __state<0>::_S_diag_state = new __state<0>(); - __state<0>::_S_diag_state->__turn_on(); - } - - inline void - __turn_off() - { - if (!__state<0>::_S_diag_state) - __state<0>::_S_diag_state = new __state<0>(); - __state<0>::_S_diag_state->__turn_off(); - } + +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 index 173b647421b..75126774d5b 100644 --- a/libstdc++-v3/include/profile/impl/profiler_trace.h +++ b/libstdc++-v3/include/profile/impl/profiler_trace.h @@ -54,9 +54,17 @@ #endif #include <algorithm> +#include <fstream> +#include <string> #include <utility> -#if defined _GLIBCXX_PROFILE_THREADS && defined HAVE_TLS +#if (defined _GLIBCXX_PROFILE_THREADS) && !(defined _GLIBCXX_HAVE_TLS) +#error You do not seem to have TLS support, which is required by the profile \ + mode. If your program is not multithreaded, recompile with \ + -D_GLIBCXX_PROFILE_NO_THREADS +#endif + +#if defined _GLIBCXX_PROFILE_THREADS && defined _GLIBCXX_HAVE_TLS #include <pthread.h> #endif @@ -65,528 +73,611 @@ namespace __gnu_profile { -#if defined _GLIBCXX_PROFILE_THREADS && defined HAVE_TLS + +#if defined _GLIBCXX_PROFILE_THREADS && defined _GLIBCXX_HAVE_TLS #define _GLIBCXX_IMPL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER - typedef pthread_mutex_t __mutex_t; - - /** @brief Pthread mutex wrapper. */ - template<int _Unused=0> - class __mutex - { - public: - static __mutex_t __global_lock; - static void __lock(__mutex_t& __m) { pthread_mutex_lock(&__m); } - static void __unlock(__mutex_t& __m) { pthread_mutex_unlock(&__m); } - }; +typedef pthread_mutex_t __mutex_t; +/** @brief Pthread mutex wrapper. */ +_GLIBCXX_PROFILE_DEFINE_DATA(__mutex_t, __global_lock, + PTHREAD_MUTEX_INITIALIZER); +inline void __lock(__mutex_t& __m) { pthread_mutex_lock(&__m); } +inline void __unlock(__mutex_t& __m) { pthread_mutex_unlock(&__m); } #else +typedef int __mutex_t; +/** @brief Mock mutex interface. */ #define _GLIBCXX_IMPL_MUTEX_INITIALIZER 0 - typedef int __mutex_t; - - /** @brief Mock mutex interface. */ - template<int _Unused=0> - class __mutex - { - public: - static __mutex_t __global_lock; - static void __lock(__mutex_t& __m) { } - static void __unlock(__mutex_t& __m) { } - }; +_GLIBCXX_PROFILE_DEFINE_DATA(__mutex_t, __global_lock, 0); +inline void __lock(__mutex_t& __m) {} +inline void __unlock(__mutex_t& __m) {} #endif - template<int _Unused> - __mutex_t __mutex<_Unused>::__global_lock = _GLIBCXX_IMPL_MUTEX_INITIALIZER; +/** @brief Representation of a warning. */ +struct __warning_data +{ + float __magnitude; + __stack_t __context; + const char* __warning_id; + const char* __warning_message; + __warning_data(); + __warning_data(float __m, __stack_t __c, const char* __id, + const char* __msg); + bool operator>(const struct __warning_data& other) const; +}; + +inline __warning_data::__warning_data() + : __magnitude(0.0), __context(NULL), __warning_id(NULL), + __warning_message(NULL) +{ +} - /** @brief Representation of a warning. */ - struct __warning_data - { - float __magnitude; - __stack_t __context; - const char* __warning_id; - const char* __warning_message; - __warning_data(); - __warning_data(float __m, __stack_t __c, const char* __id, - const char* __msg); - bool operator>(const struct __warning_data& other) const; - }; - - inline __warning_data::__warning_data() - : __magnitude(0.0), __context(NULL), __warning_id(NULL), - __warning_message(NULL) - { } - - inline __warning_data::__warning_data(float __m, __stack_t __c, - const char* __id, const char* __msg) - : __magnitude(__m), __context(__c), __warning_id(__id), - __warning_message(__msg) - { } - - inline bool - __warning_data::operator>(const struct __warning_data& other) const - { return __magnitude > other.__magnitude; } - - typedef std::_GLIBCXX_STD_PR::vector<__warning_data> __warning_vector_t; - - // Defined in profiler_<diagnostic name>.h. - class __trace_hash_func; - class __trace_hashtable_size; - class __trace_map2umap; - class __trace_vector_size; - class __trace_vector_to_list; - void __trace_vector_size_init(); - void __trace_hashtable_size_init(); - void __trace_hash_func_init(); - void __trace_vector_to_list_init(); - void __trace_map_to_unordered_map_init(); - void __trace_vector_size_report(FILE*, __warning_vector_t&); - void __trace_hashtable_size_report(FILE*, __warning_vector_t&); - void __trace_hash_func_report(FILE*, __warning_vector_t&); - void __trace_vector_to_list_report(FILE*, __warning_vector_t&); - void __trace_map_to_unordered_map_report(FILE*, __warning_vector_t&); - - // Utility functions. - inline size_t - __max(size_t __a, size_t __b) { return __a >= __b ? __a : __b; } - - inline size_t - __min(size_t __a, size_t __b) { return __a <= __b ? __a : __b; } - - /** @brief Storage for diagnostic table entries. Has only static fields. */ - template<int _Unused=0> - class __tables - { - public: - static __trace_hash_func* _S_hash_func; - static __trace_hashtable_size* _S_hashtable_size; - static __trace_map2umap* _S_map2umap; - static __trace_vector_size* _S_vector_size; - static __trace_vector_to_list* _S_vector_to_list; - }; - - template<int _Unused> - __trace_hash_func* __tables<_Unused>::_S_hash_func = NULL; - - template<int _Unused> - __trace_hashtable_size* __tables<_Unused>::_S_hashtable_size = NULL; - - template<int _Unused> - __trace_map2umap* __tables<_Unused>::_S_map2umap = NULL; - - template<int _Unused> - __trace_vector_size* __tables<_Unused>::_S_vector_size = NULL; - - template<int _Unused> - __trace_vector_to_list* __tables<_Unused>::_S_vector_to_list = NULL; - - /** @brief Storage for user defined parameters. Has only static fields. */ - template<int _Unused=0> - class __settings - { - public: - static const char* _S_trace_file_name; - static size_t _S_max_warn_count; - static size_t _S_max_stack_depth; - static size_t _S_max_mem; - }; - - template<int _Unused> - const char* __settings<_Unused>::_S_trace_file_name = - _GLIBCXX_PROFILE_TRACE_PATH_ROOT; - - template<int _Unused> - size_t __settings<_Unused>::_S_max_warn_count = - _GLIBCXX_PROFILE_MAX_WARN_COUNT; - - template<int _Unused> - size_t __settings<_Unused>::_S_max_stack_depth = - _GLIBCXX_PROFILE_MAX_STACK_DEPTH; - - template<int _Unused> - size_t __settings<_Unused>::_S_max_mem = - _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC; - - inline size_t - __stack_max_depth() { return __settings<0>::_S_max_stack_depth; } - - inline size_t - __max_mem() { return __settings<0>::_S_max_mem; } - - /** @brief Base class for all trace producers. */ - template<typename __object_info, typename __stack_info> - class __trace_base - { - public: - __trace_base(); - virtual ~__trace_base() { } - - void __add_object(__object_t object, __object_info __info); - __object_info* __get_object_info(__object_t __object); - void __retire_object(__object_t __object); - void __write(FILE* f); - void __collect_warnings(__warning_vector_t& warnings); - - void __lock_object_table(); - void __lock_stack_table(); - void __unlock_object_table(); - void __unlock_stack_table(); - - private: - __mutex_t __object_table_lock; - __mutex_t __stack_table_lock; - typedef _GLIBCXX_IMPL_UNORDERED_MAP<__object_t, - __object_info> __object_table_t; - typedef _GLIBCXX_IMPL_UNORDERED_MAP<__stack_t, __stack_info, __stack_hash, - __stack_hash> __stack_table_t; - __object_table_t __object_table; - __stack_table_t __stack_table; - size_t __stack_table_byte_size; - - protected: - const char* __id; - }; - - template<typename __object_info, typename __stack_info> - void - __trace_base<__object_info, __stack_info>::__collect_warnings(__warning_vector_t& warnings) - { - typename __stack_table_t::iterator __i = __stack_table.begin(); - for ( ; __i != __stack_table.end(); ++__i) - { - warnings.push_back(__warning_data((*__i).second.__magnitude(), - (*__i).first, - __id, - (*__i).second.__advice())); - } - } +inline __warning_data::__warning_data(float __m, __stack_t __c, + const char* __id, const char* __msg) + : __magnitude(__m), __context(__c), __warning_id(__id), + __warning_message(__msg) +{ +} - template<typename __object_info, typename __stack_info> - void - __trace_base<__object_info, __stack_info>::__lock_object_table() - { __mutex<0>::__lock(this->__object_table_lock); } - - template<typename __object_info, typename __stack_info> - void - __trace_base<__object_info, __stack_info>::__lock_stack_table() - { __mutex<0>::__lock(this->__stack_table_lock); } - - template<typename __object_info, typename __stack_info> - void __trace_base<__object_info, __stack_info>::__unlock_object_table() - { __mutex<0>::__unlock(this->__object_table_lock); } - - template<typename __object_info, typename __stack_info> - void __trace_base<__object_info, __stack_info>::__unlock_stack_table() - { __mutex<0>::__unlock(this->__stack_table_lock); } - - template<typename __object_info, typename __stack_info> - __trace_base<__object_info, __stack_info>::__trace_base() - { - // Do not pick the initial size too large, as we don't know which - // diagnostics are more active. - __object_table.rehash(10000); - __stack_table.rehash(10000); - __stack_table_byte_size = 0; - __id = NULL; - __stack_table_lock = _GLIBCXX_IMPL_MUTEX_INITIALIZER; - __object_table_lock = __stack_table_lock; - } +inline bool __warning_data::operator>(const struct __warning_data& other) const +{ + return __magnitude > other.__magnitude; +} + +typedef std::_GLIBCXX_STD_PR::vector<__warning_data> __warning_vector_t; + +// Defined in profiler_<diagnostic name>.h. +class __trace_hash_func; +class __trace_hashtable_size; +class __trace_map2umap; +class __trace_vector_size; +class __trace_vector_to_list; +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&); + +// Utility functions. +inline size_t __max(size_t __a, size_t __b) +{ + return __a >= __b ? __a : __b; +} - template<typename __object_info, typename __stack_info> - void - __trace_base<__object_info, __stack_info>::__add_object(__object_t __object, __object_info __info) +inline size_t __min(size_t __a, size_t __b) +{ + return __a <= __b ? __a : __b; +} + +struct __cost_factor +{ + const char* __env_var; + float __value; +}; + +typedef std::_GLIBCXX_STD_PR::vector<__cost_factor*> __cost_factor_vector; + +_GLIBCXX_PROFILE_DEFINE_DATA(__trace_hash_func*, _S_hash_func, NULL); +_GLIBCXX_PROFILE_DEFINE_DATA(__trace_hashtable_size*, _S_hashtable_size, NULL); +_GLIBCXX_PROFILE_DEFINE_DATA(__trace_map2umap*, _S_map2umap, NULL); +_GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_size*, _S_vector_size, NULL); +_GLIBCXX_PROFILE_DEFINE_DATA(__trace_vector_to_list*, _S_vector_to_list, NULL); +_GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_slist*, _S_list_to_slist, NULL); +_GLIBCXX_PROFILE_DEFINE_DATA(__trace_list_to_vector*, _S_list_to_vector, NULL); + +_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, NULL); + +_GLIBCXX_PROFILE_DEFINE_DATA(const char*, _S_trace_file_name, + _GLIBCXX_PROFILE_TRACE_PATH_ROOT); +_GLIBCXX_PROFILE_DEFINE_DATA(size_t, _S_max_warn_count, + _GLIBCXX_PROFILE_MAX_WARN_COUNT); +_GLIBCXX_PROFILE_DEFINE_DATA(size_t, _S_max_stack_depth, + _GLIBCXX_PROFILE_MAX_STACK_DEPTH); +_GLIBCXX_PROFILE_DEFINE_DATA(size_t, _S_max_mem, + _GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC); + +inline size_t __stack_max_depth() +{ + return _GLIBCXX_PROFILE_DATA(_S_max_stack_depth); +} + +inline 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: + __trace_base(); + virtual ~__trace_base() {} + + void __add_object(__object_t object, __object_info __info); + __object_info* __get_object_info(__object_t __object); + void __retire_object(__object_t __object); + void __write(FILE* f); + void __collect_warnings(__warning_vector_t& __warnings); + + void __lock_object_table(); + void __lock_stack_table(); + void __unlock_object_table(); + void __unlock_stack_table(); + + private: + __mutex_t __object_table_lock; + __mutex_t __stack_table_lock; + typedef _GLIBCXX_IMPL_UNORDERED_MAP<__object_t, + __object_info> __object_table_t; + typedef _GLIBCXX_IMPL_UNORDERED_MAP<__stack_t, __stack_info, __stack_hash, + __stack_hash> __stack_table_t; + __object_table_t __object_table; + __stack_table_t __stack_table; + size_t __stack_table_byte_size; + + protected: + const char* __id; +}; + +template <typename __object_info, typename __stack_info> +void __trace_base<__object_info, __stack_info>::__collect_warnings( + __warning_vector_t& __warnings) +{ + typename __stack_table_t::iterator __i = __stack_table.begin(); + for ( ; __i != __stack_table.end(); ++__i ) { - typedef typename __object_table_t::value_type value_type; - if (__max_mem() == 0 - || __object_table.size() * sizeof(__object_info) <= __max_mem()) - { - __lock_object_table(); - __object_table.insert(value_type(__object, __info)); - __unlock_object_table(); - } + __warnings.push_back(__warning_data((*__i).second.__magnitude(), + (*__i).first, + __id, + (*__i).second.__advice())); } +} - template<typename __object_info, typename __stack_info> - __object_info* - __trace_base<__object_info, __stack_info>::__get_object_info(__object_t __object) - { - // XXX: Revisit this to see if we can decrease mutex spans. - // Without this mutex, the object table could be rehashed during an - // insertion on another thread, which could result in a segfault. - __lock_object_table(); - typename __object_table_t::iterator __object_it = - __object_table.find(__object); +template <typename __object_info, typename __stack_info> +void __trace_base<__object_info, __stack_info>::__lock_object_table() +{ + __lock(this->__object_table_lock); +} - if (__object_it == __object_table.end()) - { - __unlock_object_table(); - return NULL; - } - else - { - __unlock_object_table(); - return &__object_it->second; - } - } +template <typename __object_info, typename __stack_info> +void __trace_base<__object_info, __stack_info>::__lock_stack_table() +{ + __lock(this->__stack_table_lock); +} - template<typename __object_info, typename __stack_info> - void - __trace_base<__object_info, __stack_info>::__retire_object(__object_t __object) - { - __lock_object_table(); - __lock_stack_table(); - typename __object_table_t::iterator __object_it = - __object_table.find(__object); +template <typename __object_info, typename __stack_info> +void __trace_base<__object_info, __stack_info>::__unlock_object_table() +{ + __unlock(this->__object_table_lock); +} - if (__object_it != __object_table.end()) - { - const __object_info& __info = __object_it->second; - const __stack_t& __stack = __info.__stack(); - typename __stack_table_t::iterator __stack_it = - __stack_table.find(__stack); - - if (__stack_it == __stack_table.end()) - { - // First occurence of this call context. - if (__max_mem() == 0 || __stack_table_byte_size < __max_mem()) - { - __stack_table_byte_size += - (sizeof(__instruction_address_t) * __size(__stack) - + sizeof(__stack) + sizeof(__stack_info)); - __stack_table.insert(make_pair(__stack, __stack_info(__info))); - } - } - else - { - // Merge object info into info summary for this call context. - __stack_it->second.__merge(__info); - delete __stack; - } - __object_table.erase(__object); - } - __unlock_stack_table(); +template <typename __object_info, typename __stack_info> +void __trace_base<__object_info, __stack_info>::__unlock_stack_table() +{ + __unlock(this->__stack_table_lock); +} + +template <typename __object_info, typename __stack_info> +__trace_base<__object_info, __stack_info>::__trace_base() +{ + // Do not pick the initial size too large, as we don't know which diagnostics + // are more active. + __object_table.rehash(10000); + __stack_table.rehash(10000); + __stack_table_byte_size = 0; + __id = NULL; + __object_table_lock = __stack_table_lock = _GLIBCXX_IMPL_MUTEX_INITIALIZER; +} + +template <typename __object_info, typename __stack_info> +void __trace_base<__object_info, __stack_info>::__add_object( + __object_t __object, __object_info __info) +{ + if (__max_mem() == 0 + || __object_table.size() * sizeof(__object_info) <= __max_mem()) { + __lock_object_table(); + __object_table.insert( + typename __object_table_t::value_type(__object, __info)); __unlock_object_table(); } +} - template<typename __object_info, typename __stack_info> - void - __trace_base<__object_info, __stack_info>::__write(FILE* __f) - { - typename __stack_table_t::iterator __it; - - for (__it = __stack_table.begin(); __it != __stack_table.end(); __it++) - { - if (__it->second.__is_valid()) - { - fprintf(__f, __id); - fprintf(__f, "|"); - __gnu_profile::__write(__f, __it->first); - fprintf(__f, "|"); - __it->second.__write(__f); - } - } +template <typename __object_info, typename __stack_info> +__object_info* __trace_base<__object_info, __stack_info>::__get_object_info( + __object_t __object) +{ + // XXX: Revisit this to see if we can decrease mutex spans. + // Without this mutex, the object table could be rehashed during an + // insertion on another thread, which could result in a segfault. + __lock_object_table(); + typename __object_table_t::iterator __object_it = + __object_table.find(__object); + if (__object_it == __object_table.end()){ + __unlock_object_table(); + return NULL; + } else { + __unlock_object_table(); + return &__object_it->second; } +} - inline size_t - __env_to_size_t(const char* __env_var, size_t __default_value) - { - char* __env_value = getenv(__env_var); - if (__env_value) - { - long int __converted_value = strtol(__env_value, NULL, 10); - if (errno || __converted_value < 0) - { - fprintf(stderr, "Bad value for environment variable '%s'.", - __env_var); - abort(); - } - else - { - return static_cast<size_t>(__converted_value); - } - } - else - { - return __default_value; +template <typename __object_info, typename __stack_info> +void __trace_base<__object_info, __stack_info>::__retire_object( + __object_t __object) +{ + __lock_object_table(); + __lock_stack_table(); + typename __object_table_t::iterator __object_it = + __object_table.find(__object); + if (__object_it != __object_table.end()){ + const __object_info& __info = __object_it->second; + const __stack_t& __stack = __info.__stack(); + typename __stack_table_t::iterator __stack_it = + __stack_table.find(__stack); + if (__stack_it == __stack_table.end()) { + // First occurence of this call context. + if (__max_mem() == 0 || __stack_table_byte_size < __max_mem()) { + __stack_table_byte_size += + (sizeof(__instruction_address_t) * __size(__stack) + + sizeof(__stack) + sizeof(__stack_info)); + __stack_table.insert(make_pair(__stack, __stack_info(__info))); } + } else { + // Merge object info into info summary for this call context. + __stack_it->second.__merge(__info); + delete __stack; + } + __object_table.erase(__object); } + __unlock_stack_table(); + __unlock_object_table(); +} - inline void - __set_max_stack_trace_depth() - { - __settings<0>::_S_max_stack_depth = __env_to_size_t(_GLIBCXX_PROFILE_MAX_STACK_DEPTH_ENV_VAR, __settings<0>::_S_max_stack_depth); +template <typename __object_info, typename __stack_info> +void __trace_base<__object_info, __stack_info>::__write(FILE* __f) +{ + typename __stack_table_t::iterator __it; + + for (__it = __stack_table.begin(); __it != __stack_table.end(); __it++) { + if (__it->second.__is_valid()) { + fprintf(__f, __id); + fprintf(__f, "|"); + __gnu_profile::__write(__f, __it->first); + fprintf(__f, "|"); + __it->second.__write(__f); + } } +} - inline void - __set_max_mem() - { - __settings<0>::_S_max_mem = __env_to_size_t(_GLIBCXX_PROFILE_MEM_PER_DIAGNOSTIC_ENV_VAR, __settings<0>::_S_max_mem); +inline size_t __env_to_size_t(const char* __env_var, size_t __default_value) +{ + char* __env_value = getenv(__env_var); + if (__env_value) { + long int __converted_value = strtol(__env_value, NULL, 10); + if (errno || __converted_value < 0) { + fprintf(stderr, "Bad value for environment variable '%s'.\n", __env_var); + abort(); + } else { + return static_cast<size_t>(__converted_value); + } + } else { + return __default_value; } +} - 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 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; +} - struct __warn +struct __warn +{ + FILE* __file; + __warn(FILE* __f) { __file = __f; } + void operator() (const __warning_data& __info) { - FILE* __file; - - __warn(FILE* __f) { __file = __f; } - - void operator() (const __warning_data& __info) - { - fprintf(__file, __info.__warning_id); - fprintf(__file, ": improvement = %d", - __log_magnitude(__info.__magnitude)); - fprintf(__file, ": call stack = "); - __gnu_profile::__write(__file, __info.__context); - fprintf(__file, ": advice = %s\n", __info.__warning_message); - } - }; + fprintf(__file, __info.__warning_id); + fprintf(__file, ": improvement = %d", __log_magnitude(__info.__magnitude)); + fprintf(__file, ": call stack = "); + __gnu_profile::__write(__file, __info.__context); + fprintf(__file, ": advice = %s\n", __info.__warning_message); + free( + const_cast<void*>( + reinterpret_cast<const void*>(__info.__warning_message))); + } +}; - inline FILE* - __open_output_file(const char* extension) - { - // The path is made of _S_trace_file_name + "." + extension. - size_t root_len = strlen(__settings<0>::_S_trace_file_name); - size_t ext_len = strlen(extension); - char* file_name = new char[root_len + 1 + ext_len + 1]; - char* p = file_name; - memcpy(file_name, __settings<0>::_S_trace_file_name, root_len); - *(file_name + root_len) = '.'; - memcpy(file_name + root_len + 1, extension, ext_len + 1); - FILE* out_file = fopen(file_name, "w"); - if (out_file) - return out_file; - else - { - fprintf(stderr, "Could not open trace file '%s'.", file_name); - abort(); - } +inline FILE* __open_output_file(const char* extension) +{ + // The path is made of _S_trace_file_name + "." + extension. + size_t root_len = strlen(_GLIBCXX_PROFILE_DATA(_S_trace_file_name)); + size_t ext_len = strlen(extension); + char* file_name = new char[root_len + 1 + ext_len + 1]; + memcpy(file_name, _GLIBCXX_PROFILE_DATA(_S_trace_file_name), root_len); + *(file_name + root_len) = '.'; + memcpy(file_name + root_len + 1, extension, ext_len + 1); + FILE* out_file = fopen(file_name, "w"); + if (out_file) { + return out_file; + } else { + fprintf(stderr, "Could not open trace file '%s'.\n", file_name); + abort(); } +} + +/** @brief Final report method, registered with "atexit". + * + * This can also be called directly by user code, including signal handlers. + * It is protected against deadlocks by the reentrance guard in profiler.h. + * However, when called from a signal handler that triggers while within + * __gnu_profile (under the guarded zone), no output will be produced. + */ +inline void __report(void) +{ + __lock(_GLIBCXX_PROFILE_DATA(__global_lock)); - /** @brief Final report method, registered with "atexit". - * - * This can also be called directly by user code, including signal handlers. - * It is protected against deadlocks by the reentrance guard in profiler.h. - * However, when called from a signal handler that triggers while within - * __gnu_profile (under the guarded zone), no output will be produced. - */ - inline void - __report(void) - { - __mutex<0>::__lock(__mutex<0>::__global_lock); + __warning_vector_t __warnings; - __warning_vector_t __warnings; + FILE* __raw_file = __open_output_file("raw"); + __trace_vector_size_report(__raw_file, __warnings); + __trace_hashtable_size_report(__raw_file, __warnings); + __trace_hash_func_report(__raw_file, __warnings); + __trace_vector_to_list_report(__raw_file, __warnings); + __trace_list_to_slist_report(__raw_file, __warnings); + __trace_list_to_vector_report(__raw_file, __warnings); + __trace_map_to_unordered_map_report(__raw_file, __warnings); + fclose(__raw_file); - FILE* __raw_file = __open_output_file("raw"); - __trace_vector_size_report(__raw_file, __warnings); - __trace_hashtable_size_report(__raw_file, __warnings); - __trace_hash_func_report(__raw_file, __warnings); - __trace_vector_to_list_report(__raw_file, __warnings); - __trace_map_to_unordered_map_report(__raw_file, __warnings); - fclose(__raw_file); + // Sort data by magnitude. + // XXX: instead of sorting, should collect only top N for better performance. + size_t __cutoff = __min(_GLIBCXX_PROFILE_DATA(_S_max_warn_count), + __warnings.size()); - // Sort data by magnitude. + std::sort(__warnings.begin(), __warnings.end(), + std::greater<__warning_vector_t::value_type>()); + __warnings.resize(__cutoff); - // XXX: instead of sorting, should collect only top N for better - // performance. - size_t __cutoff = __min(__settings<0>::_S_max_warn_count, - __warnings.size()); + FILE* __warn_file = __open_output_file("txt"); + std::for_each(__warnings.begin(), __warnings.end(), __warn(__warn_file)); + fclose(__warn_file); - std::sort(__warnings.begin(), __warnings.end(), - std::greater<__warning_vector_t::value_type>()); - __warnings.resize(__cutoff); + __unlock(_GLIBCXX_PROFILE_DATA(__global_lock)); +} - FILE* __warn_file = __open_output_file("txt"); - std::for_each(__warnings.begin(), __warnings.end(), __warn(__warn_file)); - fclose(__warn_file); +inline void __set_trace_path() +{ + char* __env_trace_file_name = getenv(_GLIBCXX_PROFILE_TRACE_ENV_VAR); - __mutex<0>::__unlock(__mutex<0>::__global_lock); + if (__env_trace_file_name) { + _GLIBCXX_PROFILE_DATA(_S_trace_file_name) = __env_trace_file_name; } - inline void - __set_trace_path() - { - char* __env_trace_file_name = getenv(_GLIBCXX_PROFILE_TRACE_ENV_VAR); + // Make sure early that we can create the trace file. + fclose(__open_output_file("txt")); +} - if (__env_trace_file_name) - __settings<0>::_S_trace_file_name = __env_trace_file_name; +inline void __set_max_warn_count() +{ + char* __env_max_warn_count_str = getenv( + _GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR); - // Make sure early that we can create the trace file. - fclose(__open_output_file("txt")); + if (__env_max_warn_count_str) { + _GLIBCXX_PROFILE_DATA(_S_max_warn_count) = static_cast<size_t>( + atoi(__env_max_warn_count_str)); } +} - inline void - __set_max_warn_count() - { - char* __env_max_warn_count_str = getenv(_GLIBCXX_PROFILE_MAX_WARN_COUNT_ENV_VAR); +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 (getline(__conf_file, __line)) { + std::string::size_type __i = __line.find_first_not_of(" \t\n\v"); - if (__env_max_warn_count_str) - { - int i = atoi(__env_max_warn_count_str); - __settings<0>::_S_max_warn_count = static_cast<size_t>(i); + if (__line.length() <= 0 || __line[__i] == '#') { + // Skip empty lines or comments. + continue; + } + + // Trim. + __line.erase(std::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); + + setenv(__factor_name.c_str(), __factor_value.c_str(), 0); } + } +} + +struct __cost_factor_writer +{ + FILE* __file; + __cost_factor_writer(FILE* __f) : __file(__f) {} + void operator() (const __cost_factor* __factor) + { + fprintf(__file, "%s = %f\n", __factor->__env_var, __factor->__value); } +}; - inline void - __profcxx_init_unconditional() +inline void __write_cost_factors() +{ + FILE* __file = __open_output_file("conf.out"); + std::for_each(_GLIBCXX_PROFILE_DATA(__cost_factors)->begin(), + _GLIBCXX_PROFILE_DATA(__cost_factors)->end(), + __cost_factor_writer(__file)); + fclose(__file); +} + +struct __cost_factor_setter +{ + void operator() (__cost_factor* __factor) { - __mutex<0>::__lock(__mutex<0>::__global_lock); + char* __env_cost_factor; + if (__env_cost_factor = getenv(__factor->__env_var)) + __factor->__value = atof(__env_cost_factor); + } +}; + +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)); + std::for_each(_GLIBCXX_PROFILE_DATA(__cost_factors)->begin(), + _GLIBCXX_PROFILE_DATA(__cost_factors)->end(), + __cost_factor_setter()); +} + +inline void __profcxx_init_unconditional() +{ + __lock(_GLIBCXX_PROFILE_DATA(__global_lock)); + + if (__is_invalid()) { __set_max_warn_count(); - if (__is_invalid()) - { - if (__settings<0>::_S_max_warn_count == 0) - { - __turn_off(); - } - else - { - __set_max_stack_trace_depth(); - __set_max_mem(); - __set_trace_path(); - - __trace_vector_size_init(); - __trace_hashtable_size_init(); - __trace_hash_func_init(); - __trace_vector_to_list_init(); - __trace_map_to_unordered_map_init(); - - atexit(__report); - - __turn_on(); - } - } + 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(); + + atexit(__report); + + __turn_on(); - __mutex<0>::__unlock(__mutex<0>::__global_lock); + } } - /** @brief This function must be called by each instrumentation point. - * - * The common path is inlined fully. - */ - inline bool - __profcxx_init(void) - { - if (__is_invalid()) - __profcxx_init_unconditional(); - return __is_on(); + __unlock(_GLIBCXX_PROFILE_DATA(__global_lock)); +} + +/** @brief This function must be called by each instrumentation point. + * + * The common path is inlined fully. + */ +inline bool __profcxx_init(void) +{ + if (__is_invalid()) { + __profcxx_init_unconditional(); } + return __is_on(); +} + } // namespace __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 index 151e5d4bfb7..8d630e4d90b 100644 --- a/libstdc++-v3/include/profile/impl/profiler_vector_size.h +++ b/libstdc++-v3/include/profile/impl/profiler_vector_size.h @@ -54,49 +54,51 @@ namespace __gnu_profile { - /** @brief Hashtable size instrumentation trace producer. */ - class __trace_vector_size : public __trace_container_size - { - public: - __trace_vector_size() : __trace_container_size() { __id = "vector-size"; } - }; - - // Initialization and report. - inline void - __trace_vector_size_init() - { __tables<0>::_S_vector_size = new __trace_vector_size(); } - - inline void - __trace_vector_size_report(FILE* __f, __warning_vector_t& __warnings) - { - if (__tables<0>::_S_vector_size) - { - __tables<0>::_S_vector_size->__collect_warnings(__warnings); - __tables<0>::_S_vector_size->__write(__f); - } - } - // Implementations of instrumentation hooks. - inline void - __trace_vector_size_construct(const void* __obj, size_t __num) - { - if (!__profcxx_init()) return; - __tables<0>::_S_vector_size->__insert(__obj, __get_stack(), __num); - } +/** @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_destruct(const void* __obj, size_t __num, size_t __inum) - { - if (!__profcxx_init()) return; - __tables<0>::_S_vector_size->__destruct(__obj, __num, __inum); - } +inline void __trace_vector_size_init() +{ + _GLIBCXX_PROFILE_DATA(_S_vector_size) = new __trace_vector_size(); +} - inline void - __trace_vector_size_resize(const void* __obj, size_t __from, size_t __to) - { - if (!__profcxx_init()) return; - __tables<0>::_S_vector_size->__resize(__obj, __from, __to); +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, size_t __num) +{ + if (!__profcxx_init()) return; + + _GLIBCXX_PROFILE_DATA(_S_vector_size)->__insert(__obj, __get_stack(), __num); +} + +inline void __trace_vector_size_destruct(const void* __obj, size_t __num, + size_t __inum) +{ + if (!__profcxx_init()) return; + + _GLIBCXX_PROFILE_DATA(_S_vector_size)->__destruct(__obj, __num, __inum); +} + +inline void __trace_vector_size_resize(const void* __obj, size_t __from, + size_t __to) +{ + if (!__profcxx_init()) return; + + _GLIBCXX_PROFILE_DATA(_S_vector_size)->__resize(__obj, __from, __to); +} + } // namespace __gnu_profile #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 index 45076f8eb79..d4113da8b4e 100644 --- a/libstdc++-v3/include/profile/impl/profiler_vector_to_list.h +++ b/libstdc++-v3/include/profile/impl/profiler_vector_to_list.h @@ -28,8 +28,8 @@ // reasons why the executable file might be covered by the GNU General // Public License. -/** @file profile/impl/profiler_trace.h - * @brief Data structures to represent profiling traces. +/** @file profile/impl/profiler_vector_to_list.h + * @brief diagnostics for vector to list. */ // Written by Lixia Liu and Silvius Rus. @@ -52,258 +52,285 @@ 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); - - void __merge(const __vector2list_info& __o); - void __write(FILE* __f) const; - float __magnitude() const { return _M_vector_cost - _M_list_cost; } - const char* __advice() const { return "change std::vector to std::list"; } - - size_t __shift_count() { return _M_shift_count; } - size_t __iterate() { return _M_iterate; } - float __list_cost() { return _M_list_cost; } - size_t __resize() { return _M_resize; } - void __set_list_cost(float __lc) { _M_list_cost = __lc; } - void __set_vector_cost(float __vc) { _M_vector_cost = __vc; } - bool __is_valid() { return _M_valid; } - void __set_invalid() { _M_valid = false; } - - void __opr_insert(size_t __pos, size_t __num); - void __opr_iterate(size_t __num) { _M_iterate += __num; } - void __resize(size_t __from, size_t __to); - - private: - size_t _M_shift_count; - size_t _M_iterate; - size_t _M_resize; - float _M_list_cost; - float _M_vector_cost; - bool _M_valid; - }; - - inline __vector2list_info::__vector2list_info(const __vector2list_info& __o) - : __object_info_base(__o) - { - _M_shift_count = __o._M_shift_count; - _M_iterate = __o._M_iterate; - _M_vector_cost = __o._M_vector_cost; - _M_list_cost = __o._M_list_cost; - _M_valid = __o._M_valid; - _M_resize = __o._M_resize; - } - inline void - __vector2list_info::__merge(const __vector2list_info& __o) - { - _M_shift_count += __o._M_shift_count; - _M_iterate += __o._M_iterate; - _M_vector_cost += __o._M_vector_cost; - _M_list_cost += __o._M_list_cost; - _M_valid &= __o._M_valid; - _M_resize += __o._M_resize; - } +/** @brief A vector-to-list instrumentation line in the object table. */ +class __vector2list_info: public __object_info_base +{ + public: + __vector2list_info() + :_M_shift_count(0), _M_iterate(0), _M_resize(0), _M_list_cost(0), + _M_vector_cost(0), _M_valid(true) {} + __vector2list_info(__stack_t __stack) + : __object_info_base(__stack), _M_shift_count(0), _M_iterate(0), + _M_resize(0), _M_list_cost(0), _M_vector_cost(0), _M_valid(true) {} + virtual ~__vector2list_info() {} + __vector2list_info(const __vector2list_info& __o); + void __merge(const __vector2list_info& __o); + void __write(FILE* __f) const; + float __magnitude() const { return _M_vector_cost - _M_list_cost; } + const char* __advice() const + { return strdup("change std::vector to std::list"); } + + size_t __shift_count() { return _M_shift_count; } + size_t __iterate() { return _M_iterate; } + float __list_cost() { return _M_list_cost; } + size_t __resize() { return _M_resize; } + void __set_list_cost(float __lc) { _M_list_cost = __lc; } + void __set_vector_cost(float __vc) { _M_vector_cost = __vc; } + bool __is_valid() { return _M_valid; } + void __set_invalid() { _M_valid = false; } + + void __opr_insert(size_t __pos, size_t __num); + void __opr_iterate(size_t __num); + void __resize(size_t __from, size_t __to); + void __opr_find(size_t __size); + +private: + size_t _M_shift_count; + size_t _M_iterate; + size_t _M_resize; + float _M_list_cost; + float _M_vector_cost; + bool _M_valid; +}; + +inline __vector2list_info::__vector2list_info(const __vector2list_info& __o) + : __object_info_base(__o) +{ + _M_shift_count = __o._M_shift_count; + _M_iterate = __o._M_iterate; + _M_vector_cost = __o._M_vector_cost; + _M_list_cost = __o._M_list_cost; + _M_valid = __o._M_valid; + _M_resize = __o._M_resize; +} + +inline void __vector2list_info::__merge(const __vector2list_info& __o) +{ + _M_shift_count += __o._M_shift_count; + _M_iterate += __o._M_iterate; + _M_vector_cost += __o._M_vector_cost; + _M_list_cost += __o._M_list_cost; + _M_valid &= __o._M_valid; + _M_resize += __o._M_resize; +} + +inline void __vector2list_info::__opr_insert(size_t __pos, size_t __num) +{ + _M_shift_count += __num - __pos; +} - inline void - __vector2list_info::__opr_insert(size_t __pos, size_t __num) - { _M_shift_count += __num - __pos; } - - inline void - __vector2list_info::__resize(size_t __from, size_t __to) - { _M_resize += __from; } - - /** @brief A vector-to-list instrumentation line in the stack table. */ - class __vector2list_stack_info: public __vector2list_info - { - public: - __vector2list_stack_info(const __vector2list_info& __o) - : __vector2list_info(__o) { } - }; - - /** @brief Vector-to-list instrumentation producer. */ - class __trace_vector_to_list - : public __trace_base<__vector2list_info, __vector2list_stack_info> - { - public: - __trace_vector_to_list(); - ~__trace_vector_to_list() { } - - // Insert a new node at construct with object, callstack and initial size. - void __insert(__object_t __obj, __stack_t __stack); - - // Call at destruction/clean to set container final size. - void __destruct(const void* __obj); - - // Find the node in the live map. - __vector2list_info* __find(const void* __obj); - - // Collect cost of operations. - void __opr_insert(const void* __obj, size_t __pos, size_t __num); - void __opr_iterate(const void* __obj, size_t __num); - void __invalid_operator(const void* __obj); - void __resize(const void* __obj, size_t __from, size_t __to); - float __vector_cost(size_t __shift, size_t __iterate, size_t __resize); - float __list_cost(size_t __shift, size_t __iterate, size_t __resize); - }; - - inline __trace_vector_to_list::__trace_vector_to_list() - : __trace_base<__vector2list_info, __vector2list_stack_info>() - { __id = "vector-to-list"; } - - inline void - __trace_vector_to_list::__insert(__object_t __obj, __stack_t __stack) - { __add_object(__obj, __vector2list_info(__stack)); } - - inline void - __vector2list_info::__write(FILE* __f) const - { - fprintf(__f, "%Zu %Zu %Zu %.0f %.0f\n", _M_shift_count, _M_resize, - _M_iterate, _M_vector_cost, _M_list_cost); - } +inline void __vector2list_info::__resize(size_t __from, size_t __to) +{ + _M_resize += __from; +} - // Cost model. - // Vector operation cost: - // - Cost per shift: 1 - // - Cost per access: 1 - // - Cost per resize: 1 - // List operation cost: - // - Cost per shift: 0 - // - Cost per access: 10 - // - Cost per resize: 0 - // XXX: get this from the cost model database instead. - inline float - __trace_vector_to_list::__vector_cost(size_t __shift, size_t __iterate, - size_t __resize) - { return __shift * 1 + __iterate * 1 + __resize * 1; } - - inline float - __trace_vector_to_list::__list_cost(size_t __shift, size_t __iterate, - size_t __resize) - { return __shift * 0 + __iterate * 10 + __resize * 0; } - - inline void - __trace_vector_to_list::__destruct(const void* __obj) - { - if (!__is_on()) - return; - - __vector2list_info* __res = __get_object_info(__obj); - if (!__res) - return; - - float __vc = __vector_cost(__res->__shift_count(), __res->__iterate(), - __res->__resize()); - float __lc = __list_cost(__res->__shift_count(), __res->__iterate(), - __res->__resize()); - __res->__set_vector_cost(__vc); - __res->__set_list_cost(__lc); - - __retire_object(__obj); - } +inline void __vector2list_info::__opr_iterate(size_t __num) +{ + _M_iterate += __num; +} - inline void - __trace_vector_to_list::__opr_insert(const void* __obj, size_t __pos, - size_t __num) - { - __vector2list_info* __res = __get_object_info(__obj); - if (__res) - __res->__opr_insert(__pos, __num); - } +inline void __vector2list_info::__opr_find(size_t __size) +{ + // Use average case complexity. + _M_iterate += 3.0 / 4.0 * __size; +} + +/** @brief A vector-to-list instrumentation line in the stack table. */ +class __vector2list_stack_info: public __vector2list_info { + public: + __vector2list_stack_info(const __vector2list_info& __o) + : __vector2list_info(__o) {} +}; + +/** @brief Vector-to-list instrumentation producer. */ +class __trace_vector_to_list + : public __trace_base<__vector2list_info, __vector2list_stack_info> +{ + public: + __trace_vector_to_list(); + ~__trace_vector_to_list() {} + + // Insert a new node at construct with object, callstack and initial size. + void __insert(__object_t __obj, __stack_t __stack); + // Call at destruction/clean to set container final size. + void __destruct(const void* __obj); + + // Find the node in the live map. + __vector2list_info* __find(const void* __obj); + + // Collect cost of operations. + void __opr_insert(const void* __obj, size_t __pos, size_t __num); + void __opr_iterate(const void* __obj, size_t __num); + void __invalid_operator(const void* __obj); + void __resize(const void* __obj, size_t __from, size_t __to); + float __vector_cost(size_t __shift, size_t __iterate, size_t __resize); + float __list_cost(size_t __shift, size_t __iterate, size_t __resize); + void __opr_find(const void* __obj, size_t __size); +}; + +inline __trace_vector_to_list::__trace_vector_to_list() + : __trace_base<__vector2list_info, __vector2list_stack_info>() +{ + __id = "vector-to-list"; +} - inline void - __trace_vector_to_list::__opr_iterate(const void* __obj, size_t __num) - { - __vector2list_info* __res = __get_object_info(__obj); - if (__res) - __res->__opr_iterate(__num); - } +inline void __trace_vector_to_list::__insert(__object_t __obj, + __stack_t __stack) +{ + __add_object(__obj, __vector2list_info(__stack)); +} - inline void - __trace_vector_to_list::__invalid_operator(const void* __obj) - { - __vector2list_info* __res = __get_object_info(__obj); - if (__res) - __res->__set_invalid(); - } +inline void __vector2list_info::__write(FILE* __f) const +{ + fprintf(__f, "%Zu %Zu %Zu %.0f %.0f\n", + _M_shift_count, _M_resize, _M_iterate, _M_vector_cost, _M_list_cost); +} - inline void - __trace_vector_to_list::__resize(const void* __obj, size_t __from, - size_t __to) - { - __vector2list_info* __res = __get_object_info(__obj); - if (__res) - __res->__resize(__from, __to); - } +inline float __trace_vector_to_list::__vector_cost(size_t __shift, + size_t __iterate, + 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 + ); +} + +inline float __trace_vector_to_list::__list_cost(size_t __shift, + size_t __iterate, + 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); +} +inline void __trace_vector_to_list::__destruct(const void* __obj) +{ + if (!__is_on()) + return; - // Initialization and report. - inline void - __trace_vector_to_list_init() - { __tables<0>::_S_vector_to_list = new __trace_vector_to_list(); } + __vector2list_info* __res = __get_object_info(__obj); + if (!__res) + return; - inline void - __trace_vector_to_list_report(FILE* __f, __warning_vector_t& __warnings) - { - if (__tables<0>::_S_vector_to_list) - { - __tables<0>::_S_vector_to_list->__collect_warnings(__warnings); - __tables<0>::_S_vector_to_list->__write(__f); - } - } + 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); - // Implementations of instrumentation hooks. - inline void - __trace_vector_to_list_construct(const void* __obj) - { - if (!__profcxx_init()) return; - __tables<0>::_S_vector_to_list->__insert(__obj, __get_stack()); - } + __retire_object(__obj); +} - inline void - __trace_vector_to_list_destruct(const void* __obj) - { - if (!__profcxx_init()) return; - __tables<0>::_S_vector_to_list->__destruct(__obj); - } +inline void __trace_vector_to_list::__opr_insert(const void* __obj, + size_t __pos, size_t __num) +{ + __vector2list_info* __res = __get_object_info(__obj); + if (__res) + __res->__opr_insert(__pos, __num); +} - inline void - __trace_vector_to_list_insert(const void* __obj, size_t __pos, size_t __num) - { - if (!__profcxx_init()) return; - __tables<0>::_S_vector_to_list->__opr_insert(__obj, __pos, __num); - } +inline void __trace_vector_to_list::__opr_iterate(const void* __obj, + size_t __num) +{ + __vector2list_info* __res = __get_object_info(__obj); + if (__res) + __res->__opr_iterate(__num); +} - inline void - __trace_vector_to_list_iterate(const void* __obj, size_t __num) - { - if (!__profcxx_init()) return; - __tables<0>::_S_vector_to_list->__opr_iterate(__obj, __num); - } +inline void __trace_vector_to_list::__invalid_operator(const void* __obj) +{ + __vector2list_info* __res = __get_object_info(__obj); + if (__res) + __res->__set_invalid(); +} - inline void - __trace_vector_to_list_invalid_operator(const void* __obj) - { - if (!__profcxx_init()) return; - __tables<0>::_S_vector_to_list->__invalid_operator(__obj); - } +inline void __trace_vector_to_list::__resize(const void* __obj, size_t __from, + size_t __to) +{ + __vector2list_info* __res = __get_object_info(__obj); + if (__res) + __res->__resize(__from, __to); +} + +inline void __trace_vector_to_list::__opr_find(const void* __obj, + 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_resize(const void* __obj, size_t __from, size_t __to) - { - if (!__profcxx_init()) return; - __tables<0>::_S_vector_to_list->__resize(__obj, __from, __to); +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, + size_t __pos, 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, 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, + size_t __from, 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, 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 */ diff --git a/libstdc++-v3/include/profile/iterator_tracker.h b/libstdc++-v3/include/profile/iterator_tracker.h new file mode 100644 index 00000000000..8e077481f34 --- /dev/null +++ b/libstdc++-v3/include/profile/iterator_tracker.h @@ -0,0 +1,273 @@ +#ifndef _GLIBCXX_PROFILE_ITERATOR_TRACKER +#define _GLIBCXX_PROFILE_ITERATOR_TRACKER 1 + +#include <ext/type_traits.h> + +namespace std +{ +namespace __profile +{ + +template<typename _Iterator, typename _Sequence> +class __iterator_tracker +{ + typedef __iterator_tracker _Self; + // The underlying iterator + _Iterator _M_current; + // The underlying data structure + const _Sequence* _M_ds; + typedef std::iterator_traits<_Iterator> _Traits; + + public: + typedef _Iterator _Base_iterator; + typedef typename _Traits::iterator_category iterator_category; + typedef typename _Traits::value_type value_type; + typedef typename _Traits::difference_type difference_type; + typedef typename _Traits::reference reference; + typedef typename _Traits::pointer pointer; + + __iterator_tracker() : _M_current(), _M_ds(0) { } + __iterator_tracker(const _Iterator& __i, const _Sequence* seq) + : _M_current(__i), _M_ds(seq) { } + __iterator_tracker(const __iterator_tracker& __x) + : _M_current(__x._M_current), _M_ds(__x._M_ds) { } + template<typename _MutableIterator> + __iterator_tracker(const __iterator_tracker<_MutableIterator, typename __gnu_cxx::__enable_if<(std::__are_same<_MutableIterator, typename _Sequence::iterator::_Base_iterator>::__value), _Sequence>::__type>& __x) + : _M_current(__x.base()), _M_ds(__x._M_get_sequence()) { } + + _Iterator + base() const { return _M_current; } + /** + * @brief Conversion to underlying non-debug iterator to allow + * better interaction with non-profile containers. + */ + operator _Iterator() const { return _M_current; } + + pointer + operator->() const { return &*_M_current; } + + __iterator_tracker& + operator++() + { + _M_ds->_M_profile_iterate(); + ++_M_current; + return *this; + } + + __iterator_tracker& + operator++(int) + { + _M_ds->_M_profile_iterate(); + __iterator_tracker __tmp(*this); + ++_M_current; + return __tmp; + } + + __iterator_tracker& + operator--() + { + _M_ds->_M_profile_iterate(1); + --_M_current; + return *this; + } + + __iterator_tracker& + operator--(int) + { + _M_ds->_M_profile_iterate(1); + __iterator_tracker __tmp(*this); + --_M_current; + return __tmp; + } + + __iterator_tracker& + operator=(const __iterator_tracker& __x) + { + _M_current = __x._M_current; + return *this; + } + + reference + operator*() const + { + return *_M_current; + } + + // ------ Random access iterator requirements ------ + reference + operator[](const difference_type& __n) const + { + return _M_current[__n]; + } + + __iterator_tracker& + operator+=(const difference_type& __n) + { + _M_current += __n; + return *this; + } + + __iterator_tracker + operator+(const difference_type& __n) const + { + __iterator_tracker __tmp(*this); + __tmp += __n; + return __tmp; + } + + __iterator_tracker& + operator-=(const difference_type& __n) + { + _M_current += -__n; + return *this; + } + + __iterator_tracker + operator-(const difference_type& __n) const + { + __iterator_tracker __tmp(*this); + __tmp -= __n; + return __tmp; + } + + void + _M_find() + { + _M_ds->_M_profile_find(); + } + + const _Sequence* + _M_get_sequence() const + { + return static_cast<const _Sequence*>(_M_ds); + } +}; + +template<typename _IteratorL, typename _IteratorR, typename _Sequence> +inline bool +operator==(const __iterator_tracker<_IteratorL, _Sequence>& __lhs, + const __iterator_tracker<_IteratorR, _Sequence>& __rhs) +{ + return __lhs.base() == __rhs.base(); +} + +template<typename _Iterator, typename _Sequence> +inline bool +operator==(const __iterator_tracker<_Iterator, _Sequence>& __lhs, + const __iterator_tracker<_Iterator, _Sequence>& __rhs) +{ + return __lhs.base() == __rhs.base(); +} + +template<typename _IteratorL, typename _IteratorR, typename _Sequence> +inline bool +operator!=(const __iterator_tracker<_IteratorL, _Sequence>& __lhs, + const __iterator_tracker<_IteratorR, _Sequence>& __rhs) +{ + return __lhs.base() != __rhs.base(); +} + +template<typename _Iterator, typename _Sequence> +inline bool +operator!=(const __iterator_tracker<_Iterator, _Sequence>& __lhs, + const __iterator_tracker<_Iterator, _Sequence>& __rhs) +{ + return __lhs.base() != __rhs.base(); +} + +template<typename _IteratorL, typename _IteratorR, typename _Sequence> +inline bool +operator<(const __iterator_tracker<_IteratorL, _Sequence>& __lhs, + const __iterator_tracker<_IteratorR, _Sequence>& __rhs) +{ + return __lhs.base() < __rhs.base(); +} + +template<typename _Iterator, typename _Sequence> +inline bool +operator<(const __iterator_tracker<_Iterator, _Sequence>& __lhs, + const __iterator_tracker<_Iterator, _Sequence>& __rhs) +{ + return __lhs.base() < __rhs.base(); +} + +template<typename _IteratorL, typename _IteratorR, typename _Sequence> +inline bool +operator<=(const __iterator_tracker<_IteratorL, _Sequence>& __lhs, + const __iterator_tracker<_IteratorR, _Sequence>& __rhs) +{ + return __lhs.base() <= __rhs.base(); +} + +template<typename _Iterator, typename _Sequence> +inline bool +operator<=(const __iterator_tracker<_Iterator, _Sequence>& __lhs, + const __iterator_tracker<_Iterator, _Sequence>& __rhs) +{ + return __lhs.base() <= __rhs.base(); +} + +template<typename _IteratorL, typename _IteratorR, typename _Sequence> +inline bool +operator>(const __iterator_tracker<_IteratorL, _Sequence>& __lhs, + const __iterator_tracker<_IteratorR, _Sequence>& __rhs) +{ + return __lhs.base() > __rhs.base(); +} + +template<typename _Iterator, typename _Sequence> +inline bool +operator>(const __iterator_tracker<_Iterator, _Sequence>& __lhs, + const __iterator_tracker<_Iterator, _Sequence>& __rhs) +{ + return __lhs.base() > __rhs.base(); +} + +template<typename _IteratorL, typename _IteratorR, typename _Sequence> +inline bool +operator>=(const __iterator_tracker<_IteratorL, _Sequence>& __lhs, + const __iterator_tracker<_IteratorR, _Sequence>& __rhs) +{ + return __lhs.base() >= __rhs.base(); +} + +template<typename _Iterator, typename _Sequence> +inline bool +operator>=(const __iterator_tracker<_Iterator, _Sequence>& __lhs, + const __iterator_tracker<_Iterator, _Sequence>& __rhs) +{ + return __lhs.base() >= __rhs.base(); +} + +// _GLIBCXX_RESOLVE_LIB_DEFECTS +// According to the resolution of DR179 not only the various comparison +// operators but also operator- must accept mixed iterator/const_iterator +// parameters. + template<typename _IteratorL, typename _IteratorR, typename _Sequence> + inline typename __iterator_tracker<_IteratorL, _Sequence>::difference_type + operator-(const __iterator_tracker<_IteratorL, _Sequence>& __lhs, + const __iterator_tracker<_IteratorR, _Sequence>& __rhs) +{ + return __lhs.base() - __rhs.base(); +} + +template<typename _Iterator, typename _Sequence> +inline typename __iterator_tracker<_Iterator, _Sequence>::difference_type +operator-(const __iterator_tracker<_Iterator, _Sequence>& __lhs, + const __iterator_tracker<_Iterator, _Sequence>& __rhs) +{ + return __lhs.base() - __rhs.base(); +} + +template<typename _Iterator, typename _Sequence> +inline __iterator_tracker<_Iterator, _Sequence> +operator+(typename __iterator_tracker<_Iterator,_Sequence>::difference_type + __n, + const __iterator_tracker<_Iterator, _Sequence>& __i) +{ + return __i + __n; +} + +} // namespace __profile +} // namespace std +#endif diff --git a/libstdc++-v3/include/profile/list b/libstdc++-v3/include/profile/list index 09510a04205..01edd2919f6 100644 --- a/libstdc++-v3/include/profile/list +++ b/libstdc++-v3/include/profile/list @@ -30,13 +30,15 @@ #define _GLIBCXX_PROFILE_LIST 1 #include <list> +#include <profile/base.h> +#include <profile/iterator_tracker.h> namespace std { namespace __profile { - /// Class std::list wrapper with performance instrumentation. - template<typename _Tp, typename _Allocator = std::allocator<_Tp> > + /** @brief List wrapper with performance instrumentation. */ +template<typename _Tp, typename _Allocator = std::allocator<_Tp> > class list : public _GLIBCXX_STD_D::list<_Tp, _Allocator> { @@ -46,8 +48,10 @@ namespace __profile typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef typename _Base::iterator iterator; - typedef typename _Base::const_iterator const_iterator; + typedef __iterator_tracker<typename _Base::iterator, list> + iterator; + typedef __iterator_tracker<typename _Base::const_iterator, list> + const_iterator; typedef typename _Base::size_type size_type; typedef typename _Base::difference_type difference_type; @@ -61,35 +65,60 @@ namespace __profile // 23.2.2.1 construct/copy/destroy: explicit list(const _Allocator& __a = _Allocator()) - : _Base(__a) { } + : _Base(__a) + { + __profcxx_list_construct(this); // list2slist + __profcxx_list_construct2(this); // list2vector + } explicit list(size_type __n, const _Tp& __value = _Tp(), const _Allocator& __a = _Allocator()) - : _Base(__n, __value, __a) { } + : _Base(__n, __value, __a) + { + __profcxx_list_construct(this); + __profcxx_list_construct2(this); + } template<class _InputIterator> list(_InputIterator __first, _InputIterator __last, const _Allocator& __a = _Allocator()) : _Base(__first, __last, __a) - { } + { + __profcxx_list_construct(this); + __profcxx_list_construct2(this); + } list(const list& __x) - : _Base(__x) { } + : _Base(__x) + { + __profcxx_list_construct(this); + __profcxx_list_construct2(this); + } list(const _Base& __x) - : _Base(__x) { } + : _Base(__x) + { + __profcxx_list_construct(this); + __profcxx_list_construct2(this); + } #ifdef __GXX_EXPERIMENTAL_CXX0X__ list(list&& __x) : _Base(std::forward<list>(__x)) - { } + { + __profcxx_list_construct(this); + __profcxx_list_construct2(this); + } list(initializer_list<value_type> __l, const allocator_type& __a = allocator_type()) : _Base(__l, __a) { } #endif - ~list() { } + ~list() { + __profcxx_list_destruct(this); + __profcxx_list_destruct2(this); + } list& operator=(const list& __x) @@ -118,7 +147,7 @@ namespace __profile void assign(initializer_list<value_type> __l) - { _Base::assign(__l); } + { _Base::assign(__l); } #endif template<class _InputIterator> @@ -128,34 +157,46 @@ namespace __profile void assign(size_type __n, const _Tp& __t) - { _Base::assign(__n, __t); } + { _Base::assign(__n, __t); } using _Base::get_allocator; // iterators: iterator begin() - { return iterator(_Base::begin()); } + { return iterator(_Base::begin(), this); } const_iterator begin() const - { return const_iterator(_Base::begin()); } + { return const_iterator(_Base::begin(), this); } iterator end() - { return iterator(_Base::end()); } + { + __profcxx_list_rewind(this); + return iterator(_Base::end(), this); + } const_iterator end() const - { return const_iterator(_Base::end()); } + { + __profcxx_list_rewind(this); + return const_iterator(_Base::end(), this); + } reverse_iterator rbegin() - { return reverse_iterator(end()); } + { + __profcxx_list_rewind(this); + return reverse_iterator(end()); + } const_reverse_iterator rbegin() const - { return const_reverse_iterator(end()); } + { + __profcxx_list_rewind(this); + return const_reverse_iterator(end()); + } reverse_iterator rend() @@ -168,11 +209,11 @@ namespace __profile #ifdef __GXX_EXPERIMENTAL_CXX0X__ const_iterator cbegin() const - { return const_iterator(_Base::begin()); } + { return const_iterator(_Base::begin(), this); } const_iterator cend() const - { return const_iterator(_Base::end()); } + { return const_iterator(_Base::end(), this); } const_reverse_iterator crbegin() const @@ -203,14 +244,26 @@ namespace __profile reference back() - { return _Base::back(); } + { + __profcxx_list_rewind(this); + return _Base::back(); + } const_reference back() const - { return _Base::back(); } + { + __profcxx_list_rewind(this); + return _Base::back(); + } // 23.2.2.3 modifiers: - using _Base::push_front; + void + push_front(const value_type& __x) + { + __profcxx_list_invalid_operator(this); + __profcxx_list_operation(this); + _Base::push_front(__x); + } #ifdef __GXX_EXPERIMENTAL_CXX0X__ using _Base::emplace_front; @@ -219,7 +272,7 @@ namespace __profile void pop_front() { - iterator __victim = begin(); + __profcxx_list_operation(this); _Base::pop_front(); } @@ -235,6 +288,7 @@ namespace __profile iterator __victim = end(); --__victim; _Base::pop_back(); + __profcxx_list_rewind(this); } #ifdef __GXX_EXPERIMENTAL_CXX0X__ @@ -242,54 +296,70 @@ namespace __profile iterator emplace(iterator __position, _Args&&... __args) { - return iterator(_Base::emplace(__position, - std::forward<_Args>(__args)...)); + return iterator(_Base::emplace(__position.base(), + std::forward<_Args>(__args)...)); } #endif iterator insert(iterator __position, const _Tp& __x) - { return iterator(_Base::insert(__position, __x)); } + { + _M_profile_insert(this, __position, size()); + return iterator(_Base::insert(__position.base(), __x), this); + } #ifdef __GXX_EXPERIMENTAL_CXX0X__ iterator insert(iterator __position, _Tp&& __x) - { return emplace(__position, std::move(__x)); } + { + _M_profile_insert(this, __position, size()); + return iterator(_Base::emplace(__position.base(), std::move(__x)), + this); + } void - insert(iterator __p, initializer_list<value_type> __l) - { _Base::insert(__p, __l); } + insert(iterator __position, initializer_list<value_type> __l) + { + _M_profile_insert(this, __position, size()); + _Base::insert(__position.base(), __l); + } #endif void insert(iterator __position, size_type __n, const _Tp& __x) - { _Base::insert(__position, __n, __x); } + { + _M_profile_insert(this, __position, size()); + _Base::insert(__position.base(), __n, __x); + } template<class _InputIterator> void insert(iterator __position, _InputIterator __first, _InputIterator __last) - { _Base::insert(__position, __first, __last); } + { + _M_profile_insert(this, __position, size()); + _Base::insert(__position.base(), __first, __last); + } iterator erase(iterator __position) - { return iterator(_Base::erase(__position)); } + { return iterator(_Base::erase(__position.base()), this); } iterator erase(iterator __position, iterator __last) { // _GLIBCXX_RESOLVE_LIB_DEFECTS // 151. can't currently clear() empty container - return iterator(_Base::erase(__position, __last)); + return iterator(_Base::erase(__position.base(), __last.base()), this); } void swap(list& __x) - { _Base::swap(__x); } + { _Base::swap(__x); } void clear() - { _Base::clear(); } + { _Base::clear(); } // 23.2.2.4 list operations: void @@ -306,6 +376,12 @@ namespace __profile { this->splice(__position, std::move(__x)); } #endif +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + void + splice(iterator __position, list& __x, iterator __i) + { this->splice(__position, std::move(__x), __i); } +#endif + void #ifdef __GXX_EXPERIMENTAL_CXX0X__ splice(iterator __position, list&& __x, iterator __i) @@ -317,16 +393,10 @@ namespace __profile // after implementing the relevant bits of N1599. // _GLIBCXX_RESOLVE_LIB_DEFECTS - _Base::splice(__position, _GLIBCXX_MOVE(__x._M_base()), - __i); + _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()), + __i.base()); } -#ifdef __GXX_EXPERIMENTAL_CXX0X__ - void - splice(iterator __position, list& __x, iterator __i) - { this->splice(__position, std::move(__x), __i); } -#endif - void #ifdef __GXX_EXPERIMENTAL_CXX0X__ splice(iterator __position, list&& __x, iterator __first, @@ -339,8 +409,8 @@ namespace __profile // We used to perform the splice_alloc check: not anymore, redundant // after implementing the relevant bits of N1599. - _Base::splice(__position, _GLIBCXX_MOVE(__x._M_base()), - __first, __last); + _Base::splice(__position.base(), _GLIBCXX_MOVE(__x._M_base()), + __first.base(), __last.base()); } #ifdef __GXX_EXPERIMENTAL_CXX0X__ @@ -352,7 +422,7 @@ namespace __profile void remove(const _Tp& __value) { - for (iterator __x = begin(); __x != _Base::end(); ) + for (iterator __x = begin(); __x != end(); ) { if (*__x == __value) __x = erase(__x); @@ -365,8 +435,9 @@ namespace __profile void remove_if(_Predicate __pred) { - for (iterator __x = begin(); __x != _Base::end(); ) + for (iterator __x = begin(); __x != end(); ) { + __profcxx_list_operation(this); if (__pred(*__x)) __x = erase(__x); else @@ -384,6 +455,7 @@ namespace __profile iterator __next = __first; while (++__next != __last) { + __profcxx_list_operation(this); if (*__first == *__next) erase(__next); else @@ -403,6 +475,7 @@ namespace __profile iterator __next = __first; while (++__next != __last) { + __profcxx_list_operation(this); if (__binary_pred(*__first, *__next)) erase(__next); else @@ -421,7 +494,7 @@ namespace __profile // _GLIBCXX_RESOLVE_LIB_DEFECTS // 300. list::merge() specification incomplete if (this != &__x) - _Base::merge(_GLIBCXX_MOVE(__x._M_base())); + { _Base::merge(_GLIBCXX_MOVE(__x._M_base())); } } #ifdef __GXX_EXPERIMENTAL_CXX0X__ @@ -429,7 +502,7 @@ namespace __profile merge(list& __x) { this->merge(std::move(__x)); } #endif - + template<class _Compare> void #ifdef __GXX_EXPERIMENTAL_CXX0X__ @@ -441,7 +514,7 @@ namespace __profile // _GLIBCXX_RESOLVE_LIB_DEFECTS // 300. list::merge() specification incomplete if (this != &__x) - _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp); + { _Base::merge(_GLIBCXX_MOVE(__x._M_base()), __comp); } } #ifdef __GXX_EXPERIMENTAL_CXX0X__ @@ -466,6 +539,28 @@ namespace __profile const _Base& _M_base() const { return *this; } + inline void _M_profile_find() const + { } + + inline void _M_profile_iterate(int __rewind = 0) const + { + __profcxx_list_operation(this); + __profcxx_list_iterate(this); + if (__rewind) + __profcxx_list_rewind(this); + } + + private: + size_type _M_profile_insert(void* obj, iterator __pos, size_type __size) + { + size_type __shift = 0; + typename _Base::iterator __it = __pos.base(); + for ( ; __it!=_Base::end(); __it++) + __shift++; + __profcxx_list_rewind(this); + __profcxx_list_operation(this); + __profcxx_list_insert(this, __shift, __size); + } }; template<typename _Tp, typename _Alloc> diff --git a/libstdc++-v3/include/profile/vector b/libstdc++-v3/include/profile/vector index e4e680f8699..ba4d5e70cd5 100644 --- a/libstdc++-v3/include/profile/vector +++ b/libstdc++-v3/include/profile/vector @@ -37,12 +37,12 @@ #include <vector> #include <utility> #include <profile/base.h> +#include <profile/iterator_tracker.h> namespace std { namespace __profile { - /// Class std::vector wrapper with performance instrumentation. template<typename _Tp, typename _Allocator = std::allocator<_Tp> > class vector @@ -54,17 +54,21 @@ namespace __profile typedef typename _Base::reference reference; typedef typename _Base::const_reference const_reference; - typedef typename _Base::iterator iterator; - typedef typename _Base::const_iterator const_iterator; + typedef __iterator_tracker<typename _Base::iterator, vector> + iterator; + typedef __iterator_tracker<typename _Base::const_iterator, vector> + const_iterator; typedef typename _Base::size_type size_type; typedef typename _Base::difference_type difference_type; - typedef _Tp value_type; - typedef _Allocator allocator_type; + typedef _Tp value_type; + typedef _Allocator allocator_type; typedef typename _Base::pointer pointer; typedef typename _Base::const_pointer const_pointer; - + typedef std::reverse_iterator<iterator> reverse_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + _Base& _M_base() { return *this; } @@ -158,6 +162,58 @@ namespace __profile using _Base::assign; using _Base::get_allocator; + + // iterators: + iterator + begin() + { return iterator(_Base::begin(), this); } + + const_iterator + begin() const + { return const_iterator(_Base::begin(), this); } + + iterator + end() + { return iterator(_Base::end(), this); } + + const_iterator + end() const + { return const_iterator(_Base::end(), this); } + + reverse_iterator + rbegin() + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const + { return const_reverse_iterator(begin()); } + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + const_iterator + cbegin() const + { return const_iterator(_Base::begin(), this); } + + const_iterator + cend() const + { return const_iterator(_Base::end(), this); } + + const_reverse_iterator + crbegin() const + { return const_reverse_iterator(end()); } + + const_reverse_iterator + crend() const + { return const_reverse_iterator(begin()); } +#endif + // 23.2.4.2 capacity: using _Base::size; using _Base::max_size; @@ -243,22 +299,24 @@ namespace __profile iterator insert(iterator __position, const _Tp& __x) { - __profcxx_vector_insert(this, __position-_Base::begin(), this->size()); + __profcxx_vector_insert(this, __position.base() - _Base::begin(), + this->size()); size_type __old_size = this->capacity(); - typename _Base::iterator __res = _Base::insert(__position,__x); + typename _Base::iterator __res = _Base::insert(__position.base(), __x); _M_profile_resize(this, __old_size, this->capacity()); - return __res; + return iterator(__res, this); } #ifdef __GXX_EXPERIMENTAL_CXX0X__ iterator insert(iterator __position, _Tp&& __x) { - __profcxx_vector_insert(this, __position-_Base::begin(), this->size()); + __profcxx_vector_insert(this, __position.base() - _Base::begin(), + this->size()); size_type __old_size = this->capacity(); - typename _Base::iterator __res = _Base::insert(__position,__x); + typename _Base::iterator __res = _Base::insert(__position.base(), __x); _M_profile_resize(this, __old_size, this->capacity()); - return __res; + return iterator(__res, this); } void @@ -266,20 +324,27 @@ namespace __profile { this->insert(__position, __l.begin(), __l.end()); } #endif +#ifdef __GXX_EXPERIMENTAL_CXX0X__ void + swap(vector&& __x) + { + _Base::swap(__x); + } +#endif + void swap(vector& __x) { _Base::swap(__x); } - void insert(iterator __position, size_type __n, const _Tp& __x) { - __profcxx_vector_insert(this, __position-_Base::begin(), this->size()); + __profcxx_vector_insert(this, __position.base() - _Base::begin(), + this->size()); size_type __old_size = this->capacity(); - _Base::insert(__position, __n, __x); + _Base::insert(__position, __n, __x); _M_profile_resize(this, __old_size, this->capacity()); } @@ -288,12 +353,31 @@ namespace __profile insert(iterator __position, _InputIterator __first, _InputIterator __last) { - __profcxx_vector_insert(this, __position-_Base::begin(), this->size()); + __profcxx_vector_insert(this, __position.base()-_Base::begin(), + this->size()); size_type __old_size = this->capacity(); _Base::insert(__position, __first, __last); _M_profile_resize(this, __old_size, this->capacity()); } + + iterator + erase(iterator __position) + { + typename _Base::iterator __res = _Base::erase(__position.base()); + return iterator(__res, this); + } + + iterator + erase(iterator __first, iterator __last) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 151. can't currently clear() empty container + typename _Base::iterator __res = _Base::erase(__first.base(), + __last.base()); + return iterator(__res, this); + } + void clear() { @@ -302,17 +386,14 @@ namespace __profile _Base::clear(); } - // iterators: - iterator - begin() + inline void _M_profile_find() const { - return _Base::begin(); + __profcxx_vector_find(this, size()); } - const_iterator - begin() const + inline void _M_profile_iterate(int __rewind = 0) const { - return _Base::begin(); + __profcxx_vector_iterate(this); } private: @@ -367,6 +448,18 @@ namespace __profile swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>& __rhs) { __lhs.swap(__rhs); } +#ifdef __GXX_EXPERIMENTAL_CXX0X__ + template<typename _Tp, typename _Alloc> + inline void + swap(vector<_Tp, _Alloc>&& __lhs, vector<_Tp, _Alloc>& __rhs) + { __lhs.swap(__rhs); } + + template<typename _Tp, typename _Alloc> + inline void + swap(vector<_Tp, _Alloc>& __lhs, vector<_Tp, _Alloc>&& __rhs) + { __lhs.swap(__rhs); } +#endif + } // namespace __profile using _GLIBCXX_STD_D::_S_word_bit; } // namespace std |