• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 Google 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  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 #include "InstanceCounter.h"
28 
29 #include "wtf/HashMap.h"
30 #include "wtf/StdLibExtras.h"
31 #include "wtf/ThreadingPrimitives.h"
32 #include "wtf/text/StringBuilder.h"
33 #include "wtf/text/StringHash.h"
34 #include "wtf/text/WTFString.h"
35 
36 namespace WTF {
37 
38 #ifdef ENABLE_INSTANCE_COUNTER
39 
40 // This function is used to stringify a typename T without using RTTI.
41 // The result of extractNameFunc<T>() is given as |funcName|. |extractNameFromFunctionName| then extracts a typename string from |funcName|.
extractNameFromFunctionName(const char * funcName)42 String extractNameFromFunctionName(const char* funcName)
43 {
44 #if COMPILER(GCC)
45     const size_t prefixLength = sizeof("const char* WTF::extractNameFunc() [with T = ") - 1;
46 
47     size_t funcNameLength = strlen(funcName);
48     ASSERT(funcNameLength > prefixLength + 1);
49 
50     const char* funcNameWithoutPrefix = funcName + prefixLength;
51     return String(funcNameWithoutPrefix, funcNameLength - prefixLength - 1 /* last ] */);
52 #else
53     // FIXME: Support other compilers
54     ASSERT(false);
55 #endif
56 }
57 
58 class InstanceCounter {
59 public:
60     void incrementInstanceCount(const String& instanceName, void* ptr);
61     void decrementInstanceCount(const String& instanceName, void* ptr);
62     String dump();
63 
instance()64     static InstanceCounter* instance()
65     {
66         DEFINE_STATIC_LOCAL(InstanceCounter, self, ());
67         return &self;
68     }
69 
70 private:
InstanceCounter()71     InstanceCounter() { }
72 
73     Mutex m_mutex;
74     HashMap<String, int> m_counterMap;
75 };
76 
incrementInstanceCount(const char * extractNameFuncName,void * ptr)77 void incrementInstanceCount(const char* extractNameFuncName, void* ptr)
78 {
79     String instanceName = extractNameFromFunctionName(extractNameFuncName);
80     InstanceCounter::instance()->incrementInstanceCount(instanceName, ptr);
81 }
82 
decrementInstanceCount(const char * extractNameFuncName,void * ptr)83 void decrementInstanceCount(const char* extractNameFuncName, void* ptr)
84 {
85     String instanceName = extractNameFromFunctionName(extractNameFuncName);
86     InstanceCounter::instance()->decrementInstanceCount(instanceName, ptr);
87 }
88 
dumpRefCountedInstanceCounts()89 String dumpRefCountedInstanceCounts()
90 {
91     return InstanceCounter::instance()->dump();
92 }
93 
incrementInstanceCount(const String & instanceName,void * ptr)94 void InstanceCounter::incrementInstanceCount(const String& instanceName, void* ptr)
95 {
96     MutexLocker locker(m_mutex);
97     HashMap<String, int>::AddResult result = m_counterMap.add(instanceName, 1);
98     if (!result.isNewEntry)
99         ++(result.iterator->value);
100 }
101 
decrementInstanceCount(const String & instanceName,void * ptr)102 void InstanceCounter::decrementInstanceCount(const String& instanceName, void* ptr)
103 {
104     MutexLocker locker(m_mutex);
105     HashMap<String, int>::iterator it = m_counterMap.find(instanceName);
106     ASSERT(it != m_counterMap.end());
107 
108     --(it->value);
109     if (!it->value)
110         m_counterMap.remove(it);
111 }
112 
dump()113 String InstanceCounter::dump()
114 {
115     MutexLocker locker(m_mutex);
116 
117     StringBuilder builder;
118 
119     builder.append("{");
120     HashMap<String, int>::iterator it = m_counterMap.begin();
121     HashMap<String, int>::iterator itEnd = m_counterMap.end();
122     for (; it != itEnd; ++it) {
123         if (it != m_counterMap.begin())
124             builder.append(",");
125         builder.append("\"");
126         builder.append(it->key);
127         builder.append("\": ");
128         builder.append(String::number(it->value));
129     }
130     builder.append("}");
131 
132     return builder.toString();
133 }
134 
135 #else
136 
137 String dumpRefCountedInstanceCounts()
138 {
139     return String("{}");
140 }
141 
142 #endif // ENABLE_INSTANCE_COUNTER
143 
144 } // namespace WTF
145