2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "InstanceCounter.h"
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"
38 #if ENABLE(INSTANCE_COUNTER) || ENABLE(GC_PROFILING) || ENABLE(DETAILED_MEMORY_INFRA)
41 const size_t extractNameFunctionPrefixLength
= sizeof("const char *WTF::extractNameFunction() [T = ") - 1;
42 const size_t extractNameFunctionPostfixLength
= sizeof("]") - 1;
44 const size_t extractNameFunctionPrefixLength
= sizeof("const char* WTF::extractNameFunction() [with T = ") - 1;
45 const size_t extractNameFunctionPostfixLength
= sizeof("]") - 1;
47 const size_t extractNameFunctionPrefixLength
= sizeof("const char *__cdecl WTF::extractNameFunction<class ") - 1;
48 const size_t extractNameFunctionPostfixLength
= sizeof(">(void)") - 1;
50 #warning "Extracting typename is supported only in compiler GCC, CLANG and MSVC at this moment"
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
)
57 #if COMPILER(CLANG) || COMPILER(GCC) || COMPILER(MSVC)
58 size_t funcNameLength
= strlen(funcName
);
59 ASSERT(funcNameLength
> extractNameFunctionPrefixLength
+ extractNameFunctionPostfixLength
);
61 const char* funcNameWithoutPrefix
= funcName
+ extractNameFunctionPrefixLength
;
62 return String(funcNameWithoutPrefix
, funcNameLength
- extractNameFunctionPrefixLength
- extractNameFunctionPostfixLength
);
64 return String("unknown");
68 class InstanceCounter
{
70 void incrementInstanceCount(const String
& instanceName
, void* ptr
);
71 void decrementInstanceCount(const String
& instanceName
, void* ptr
);
74 static InstanceCounter
* instance()
76 DEFINE_STATIC_LOCAL(InstanceCounter
, self
, ());
84 HashMap
<String
, int> m_counterMap
;
87 void incrementInstanceCount(const char* extractNameFunctionName
, void* ptr
)
89 String instanceName
= extractTypeNameFromFunctionName(extractNameFunctionName
);
90 InstanceCounter::instance()->incrementInstanceCount(instanceName
, ptr
);
93 void decrementInstanceCount(const char* extractNameFunctionName
, void* ptr
)
95 String instanceName
= extractTypeNameFromFunctionName(extractNameFunctionName
);
96 InstanceCounter::instance()->decrementInstanceCount(instanceName
, ptr
);
99 String
dumpRefCountedInstanceCounts()
101 return InstanceCounter::instance()->dump();
104 void InstanceCounter::incrementInstanceCount(const String
& instanceName
, void* ptr
)
106 MutexLocker
locker(m_mutex
);
107 HashMap
<String
, int>::AddResult result
= m_counterMap
.add(instanceName
, 1);
108 if (!result
.isNewEntry
)
109 ++(result
.storedValue
->value
);
112 void InstanceCounter::decrementInstanceCount(const String
& instanceName
, void* ptr
)
114 MutexLocker
locker(m_mutex
);
115 HashMap
<String
, int>::iterator it
= m_counterMap
.find(instanceName
);
116 ASSERT(it
!= m_counterMap
.end());
120 m_counterMap
.remove(it
);
123 String
InstanceCounter::dump()
125 MutexLocker
locker(m_mutex
);
127 StringBuilder builder
;
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())
136 builder
.append(it
->key
);
137 builder
.appendLiteral("\": ");
138 builder
.appendNumber(it
->value
);
142 return builder
.toString();
147 String
dumpRefCountedInstanceCounts()
152 #endif // ENABLE(INSTANCE_COUNTER) || ENABLE(GC_PROFILING)