e37958227e50585eeb5efd81a3544600ccf07f9f
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / wtf / InstanceCounter.cpp
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 #if ENABLE(INSTANCE_COUNTER) || ENABLE(GC_PROFILING)
39
40 #if COMPILER(CLANG)
41 const size_t extractNameFunctionPrefixLength = sizeof("const char *WTF::extractNameFunction() [T = ") - 1;
42 const size_t extractNameFunctionPostfixLength = sizeof("]") - 1;
43 #elif COMPILER(GCC)
44 const size_t extractNameFunctionPrefixLength = sizeof("const char* WTF::extractNameFunction() [with T = ") - 1;
45 const size_t extractNameFunctionPostfixLength = sizeof("]") - 1;
46 #elif COMPILER(MSVC)
47 const size_t extractNameFunctionPrefixLength = sizeof("const char *__cdecl WTF::extractNameFunction<class ") - 1;
48 const size_t extractNameFunctionPostfixLength = sizeof(">(void)") - 1;
49 #else
50 #warning "Extracting typename is supported only in compiler GCC, CLANG and MSVC at this moment"
51 #endif
52
53 // This function is used to stringify a typename T without using RTTI.
54 // The result of extractNameFunction<T>() is given as |funcName|. |extractTypeNameFromFunctionName| then extracts a typename string from |funcName|.
55 String extractTypeNameFromFunctionName(const char* funcName)
56 {
57 #if COMPILER(CLANG) || COMPILER(GCC) || COMPILER(MSVC)
58     size_t funcNameLength = strlen(funcName);
59     ASSERT(funcNameLength > extractNameFunctionPrefixLength + extractNameFunctionPostfixLength);
60
61     const char* funcNameWithoutPrefix = funcName + extractNameFunctionPrefixLength;
62     return String(funcNameWithoutPrefix, funcNameLength - extractNameFunctionPrefixLength - extractNameFunctionPostfixLength);
63 #else
64     return String("unknown");
65 #endif
66 }
67
68 class InstanceCounter {
69 public:
70     void incrementInstanceCount(const String& instanceName, void* ptr);
71     void decrementInstanceCount(const String& instanceName, void* ptr);
72     String dump();
73
74     static InstanceCounter* instance()
75     {
76         DEFINE_STATIC_LOCAL(InstanceCounter, self, ());
77         return &self;
78     }
79
80 private:
81     InstanceCounter() { }
82
83     Mutex m_mutex;
84     HashMap<String, int> m_counterMap;
85 };
86
87 void incrementInstanceCount(const char* extractNameFunctionName, void* ptr)
88 {
89     String instanceName = extractTypeNameFromFunctionName(extractNameFunctionName);
90     InstanceCounter::instance()->incrementInstanceCount(instanceName, ptr);
91 }
92
93 void decrementInstanceCount(const char* extractNameFunctionName, void* ptr)
94 {
95     String instanceName = extractTypeNameFromFunctionName(extractNameFunctionName);
96     InstanceCounter::instance()->decrementInstanceCount(instanceName, ptr);
97 }
98
99 String dumpRefCountedInstanceCounts()
100 {
101     return InstanceCounter::instance()->dump();
102 }
103
104 void InstanceCounter::incrementInstanceCount(const String& instanceName, void* ptr)
105 {
106     MutexLocker locker(m_mutex);
107     HashMap<String, int>::AddResult result = m_counterMap.add(instanceName, 1);
108     if (!result.isNewEntry)
109         ++(result.storedValue->value);
110 }
111
112 void InstanceCounter::decrementInstanceCount(const String& instanceName, void* ptr)
113 {
114     MutexLocker locker(m_mutex);
115     HashMap<String, int>::iterator it = m_counterMap.find(instanceName);
116     ASSERT(it != m_counterMap.end());
117
118     --(it->value);
119     if (!it->value)
120         m_counterMap.remove(it);
121 }
122
123 String InstanceCounter::dump()
124 {
125     MutexLocker locker(m_mutex);
126
127     StringBuilder builder;
128
129     builder.append("{");
130     HashMap<String, int>::iterator it = m_counterMap.begin();
131     HashMap<String, int>::iterator itEnd = m_counterMap.end();
132     for (; it != itEnd; ++it) {
133         if (it != m_counterMap.begin())
134             builder.append(",");
135         builder.append("\"");
136         builder.append(it->key);
137         builder.append("\": ");
138         builder.append(String::number(it->value));
139     }
140     builder.append("}");
141
142     return builder.toString();
143 }
144
145 #else
146
147 String dumpRefCountedInstanceCounts()
148 {
149     return String("{}");
150 }
151
152 #endif // ENABLE(INSTANCE_COUNTER) || ENABLE(GC_PROFILING)
153
154 } // namespace WTF