SamplingCounter.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * Copyright (C) 2011 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14. * its contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #ifndef SamplingCounter_h
  29. #define SamplingCounter_h
  30. #include <stdint.h>
  31. #include <wtf/Assertions.h>
  32. namespace JSC {
  33. // AbstractSamplingCounter:
  34. //
  35. // Implements a named set of counters, printed on exit if ENABLE(SAMPLING_COUNTERS).
  36. // See subclasses below, SamplingCounter, GlobalSamplingCounter and DeletableSamplingCounter.
  37. class AbstractSamplingCounter {
  38. friend class DeletableSamplingCounter;
  39. public:
  40. void count(uint32_t count = 1)
  41. {
  42. m_counter += count;
  43. }
  44. JS_EXPORT_PRIVATE static void dump();
  45. int64_t* addressOfCounter() { return &m_counter; }
  46. protected:
  47. // Effectively the contructor, however called lazily in the case of GlobalSamplingCounter.
  48. void init(const char* name)
  49. {
  50. m_counter = 0;
  51. m_name = name;
  52. // Set m_next to point to the head of the chain, and inform whatever is
  53. // currently at the head that this node will now hold the pointer to it.
  54. m_next = s_abstractSamplingCounterChain;
  55. s_abstractSamplingCounterChain->m_referer = &m_next;
  56. // Add this node to the head of the list.
  57. s_abstractSamplingCounterChain = this;
  58. m_referer = &s_abstractSamplingCounterChain;
  59. }
  60. int64_t m_counter;
  61. const char* m_name;
  62. AbstractSamplingCounter* m_next;
  63. // This is a pointer to the pointer to this node in the chain; used to
  64. // allow fast linked list deletion.
  65. AbstractSamplingCounter** m_referer;
  66. // Null object used to detect end of static chain.
  67. static AbstractSamplingCounter s_abstractSamplingCounterChainEnd;
  68. JS_EXPORTDATA static AbstractSamplingCounter* s_abstractSamplingCounterChain;
  69. static bool s_completed;
  70. };
  71. #if ENABLE(SAMPLING_COUNTERS)
  72. // SamplingCounter:
  73. //
  74. // This class is suitable and (hopefully!) convenient for cases where a counter is
  75. // required within the scope of a single function. It can be instantiated as a
  76. // static variable since it contains a constructor but not a destructor (static
  77. // variables in WebKit cannot have destructors).
  78. //
  79. // For example:
  80. //
  81. // void someFunction()
  82. // {
  83. // static SamplingCounter countMe("This is my counter. There are many like it, but this one is mine.");
  84. // countMe.count();
  85. // // ...
  86. // }
  87. //
  88. class SamplingCounter : public AbstractSamplingCounter {
  89. public:
  90. SamplingCounter(const char* name) { init(name); }
  91. };
  92. // GlobalSamplingCounter:
  93. //
  94. // This class is suitable for use where a counter is to be declared globally,
  95. // since it contains neither a constructor nor destructor. Instead, ensure
  96. // that 'name()' is called to provide the counter with a name (and also to
  97. // allow it to be printed out on exit).
  98. //
  99. // GlobalSamplingCounter globalCounter;
  100. //
  101. // void firstFunction()
  102. // {
  103. // // Put this within a function that is definitely called!
  104. // // (Or alternatively alongside all calls to 'count()').
  105. // globalCounter.name("I Name You Destroyer.");
  106. // globalCounter.count();
  107. // // ...
  108. // }
  109. //
  110. // void secondFunction()
  111. // {
  112. // globalCounter.count();
  113. // // ...
  114. // }
  115. //
  116. class GlobalSamplingCounter : public AbstractSamplingCounter {
  117. public:
  118. void name(const char* name)
  119. {
  120. // Global objects should be mapped in zero filled memory, so this should
  121. // be a safe (albeit not necessarily threadsafe) check for 'first call'.
  122. if (!m_next)
  123. init(name);
  124. }
  125. };
  126. // DeletableSamplingCounter:
  127. //
  128. // The above classes (SamplingCounter, GlobalSamplingCounter), are intended for
  129. // use within a global or static scope, and as such cannot have a destructor.
  130. // This means there is no convenient way for them to remove themselves from the
  131. // static list of counters, and should an instance of either class be freed
  132. // before 'dump()' has walked over the list it will potentially walk over an
  133. // invalid pointer.
  134. //
  135. // This class is intended for use where the counter may possibly be deleted before
  136. // the program exits. Should this occur, the counter will print it's value to
  137. // stderr, and remove itself from the static list. Example:
  138. //
  139. // DeletableSamplingCounter* counter = new DeletableSamplingCounter("The Counter With No Name");
  140. // counter->count();
  141. // delete counter;
  142. //
  143. class DeletableSamplingCounter : public AbstractSamplingCounter {
  144. public:
  145. DeletableSamplingCounter(const char* name) { init(name); }
  146. ~DeletableSamplingCounter()
  147. {
  148. if (!s_completed)
  149. dataFile("DeletableSamplingCounter \"%s\" deleted early (with count %lld)\n", m_name, m_counter);
  150. // Our m_referer pointer should know where the pointer to this node is,
  151. // and m_next should know that this node is the previous node in the list.
  152. ASSERT(*m_referer == this);
  153. ASSERT(m_next->m_referer == &m_next);
  154. // Remove this node from the list, and inform m_next that we have done so.
  155. m_next->m_referer = m_referer;
  156. *m_referer = m_next;
  157. }
  158. };
  159. #endif
  160. } // namespace JSC
  161. #endif // SamplingCounter_h