Commit d6bcd37d authored by fpizlo@apple.com's avatar fpizlo@apple.com

The GC does not have a facility for profiling the kinds of objects

that occupy the heap
https://bugs.webkit.org/show_bug.cgi?id=66849

Reviewed by Geoffrey Garen.

Destructor calls and object scans are now optionally counted, per
vtable. When the heap is destroyed and profiling is enabled, the
counts are dumped, with care taken to print the names of classes
(modulo C++ mangling) sorted in descending commonality.

* GNUmakefile.list.am:
* JavaScriptCore.exp:
* JavaScriptCore.pro:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* heap/Heap.cpp:
(JSC::Heap::destroy):
* heap/Heap.h:
* heap/MarkStack.cpp:
(JSC::SlotVisitor::visitChildren):
(JSC::SlotVisitor::drain):
* heap/MarkStack.h:
* heap/MarkedBlock.cpp:
(JSC::MarkedBlock::callDestructor):
* heap/MarkedBlock.h:
* heap/VTableSpectrum.cpp: Added.
(JSC::VTableSpectrum::VTableSpectrum):
(JSC::VTableSpectrum::~VTableSpectrum):
(JSC::VTableSpectrum::countVPtr):
(JSC::VTableSpectrum::count):
(JSC::VTableAndCount::VTableAndCount):
(JSC::VTableAndCount::operator<):
(JSC::VTableSpectrum::dump):
* heap/VTableSpectrum.h: Added.
* wtf/Platform.h:


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@93918 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent a4fd718d
2011-08-26 Filip Pizlo <fpizlo@apple.com>
The GC does not have a facility for profiling the kinds of objects
that occupy the heap
https://bugs.webkit.org/show_bug.cgi?id=66849
Reviewed by Geoffrey Garen.
Destructor calls and object scans are now optionally counted, per
vtable. When the heap is destroyed and profiling is enabled, the
counts are dumped, with care taken to print the names of classes
(modulo C++ mangling) sorted in descending commonality.
* GNUmakefile.list.am:
* JavaScriptCore.exp:
* JavaScriptCore.pro:
* JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
* JavaScriptCore.xcodeproj/project.pbxproj:
* heap/Heap.cpp:
(JSC::Heap::destroy):
* heap/Heap.h:
* heap/MarkStack.cpp:
(JSC::SlotVisitor::visitChildren):
(JSC::SlotVisitor::drain):
* heap/MarkStack.h:
* heap/MarkedBlock.cpp:
(JSC::MarkedBlock::callDestructor):
* heap/MarkedBlock.h:
* heap/VTableSpectrum.cpp: Added.
(JSC::VTableSpectrum::VTableSpectrum):
(JSC::VTableSpectrum::~VTableSpectrum):
(JSC::VTableSpectrum::countVPtr):
(JSC::VTableSpectrum::count):
(JSC::VTableAndCount::VTableAndCount):
(JSC::VTableAndCount::operator<):
(JSC::VTableSpectrum::dump):
* heap/VTableSpectrum.h: Added.
* wtf/Platform.h:
2011-08-26 Juan C. Montemayor <jmont@apple.com>
Update topCallFrame when calling host functions in the JIT
......
......@@ -149,6 +149,8 @@ javascriptcore_sources += \
Source/JavaScriptCore/heap/OldSpace.cpp \
Source/JavaScriptCore/heap/OldSpace.h \
Source/JavaScriptCore/heap/Strong.h \
Source/JavaScriptCore/heap/VTableSpectrum.cpp \
Source/JavaScriptCore/heap/VTableSpectrum.h \
Source/JavaScriptCore/heap/Weak.h \
Source/JavaScriptCore/heap/WriteBarrierSupport.cpp \
Source/JavaScriptCore/heap/WriteBarrierSupport.h \
......
......@@ -174,6 +174,7 @@ __ZN3JSC14SamplingThread5startEj
__ZN3JSC14ScopeChainNode6s_infoE
__ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE
__ZN3JSC14TimeoutChecker5resetEv
__ZN3JSC14VTableSpectrum5countEPNS_6JSCellE
__ZN3JSC14throwTypeErrorEPNS_9ExecStateE
__ZN3JSC15JSWrapperObject13visitChildrenERNS_11SlotVisitorE
__ZN3JSC15WeakHandleOwner26isReachableFromOpaqueRootsENS_6HandleINS_7UnknownEEEPvRNS_11SlotVisitorE
......
......@@ -79,6 +79,7 @@ SOURCES += \
heap/MarkedBlock.cpp \
heap/NewSpace.cpp \
heap/OldSpace.cpp \
heap/VTableSpectrum.cpp \
heap/WriteBarrierSupport.cpp \
debugger/DebuggerActivation.cpp \
debugger/DebuggerCallFrame.cpp \
......
......@@ -1965,6 +1965,14 @@
RelativePath="..\..\heap\LocalScope.h"
>
</File>
<File
RelativePath="..\..\heap\VTableSpectrum.h"
>
</File>
<File
RelativePath="..\..\heap\VTableSpectrum.cpp"
>
</File>
<File
RelativePath="..\..\heap\Weak.h"
>
......
......@@ -52,6 +52,8 @@
0F7700901402FDE40078EB39 /* SamplingCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F77008E1402FDD60078EB39 /* SamplingCounter.h */; settings = {ATTRIBUTES = (Private, ); }; };
0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7700911402FF280078EB39 /* SamplingCounter.cpp */; };
0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FC815151405119B00CFA603 /* VTableSpectrum.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC815141405118D00CFA603 /* VTableSpectrum.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FC81516140511B500CFA603 /* VTableSpectrum.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC815121405118600CFA603 /* VTableSpectrum.cpp */; };
0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */; };
1400067712A6F7830064D123 /* OSAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1400067612A6F7830064D123 /* OSAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -737,6 +739,8 @@
0F77008E1402FDD60078EB39 /* SamplingCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingCounter.h; sourceTree = "<group>"; };
0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = "<group>"; };
0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueProfile.h; sourceTree = "<group>"; };
0FC815121405118600CFA603 /* VTableSpectrum.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VTableSpectrum.cpp; sourceTree = "<group>"; };
0FC815141405118D00CFA603 /* VTableSpectrum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTableSpectrum.h; sourceTree = "<group>"; };
0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteBarrierSupport.cpp; sourceTree = "<group>"; };
0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierSupport.h; sourceTree = "<group>"; };
1400067612A6F7830064D123 /* OSAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSAllocator.h; sourceTree = "<group>"; };
......@@ -1509,6 +1513,8 @@
142E312A134FF0A600AFADB5 /* heap */ = {
isa = PBXGroup;
children = (
0FC815141405118D00CFA603 /* VTableSpectrum.h */,
0FC815121405118600CFA603 /* VTableSpectrum.cpp */,
0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */,
0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */,
146B14DB12EB5B12001BEC1B /* ConservativeRoots.cpp */,
......@@ -2245,6 +2251,7 @@
86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */,
BC18C3E60E16F5CD00B34460 /* ArrayConstructor.h in Headers */,
0FC815151405119B00CFA603 /* VTableSpectrum.h in Headers */,
0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */,
0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */,
BC18C3E70E16F5CD00B34460 /* ArrayPrototype.h in Headers */,
......@@ -2855,6 +2862,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0FC81516140511B500CFA603 /* VTableSpectrum.cpp in Sources */,
0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */,
0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */,
147F39BD107EC37600427A48 /* ArgList.cpp in Sources */,
......
......@@ -312,6 +312,11 @@ void Heap::destroy()
shrink();
ASSERT(!size());
#if ENABLE(SIMPLE_HEAP_PROFILING)
m_slotVisitor.m_visitedTypeCounts.dump(stderr, "Visited Type Counts");
m_destroyedTypeCounts.dump(stderr, "Destroyed Type Counts");
#endif
#if ENABLE(LAZY_BLOCK_FREEING)
releaseFreeBlocks();
#endif
......
......@@ -124,6 +124,8 @@ namespace JSC {
void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
private:
friend class MarkedBlock;
typedef HashSet<MarkedBlock*>::iterator BlockIterator;
static const size_t minExtraCost = 256;
......@@ -185,6 +187,10 @@ namespace JSC {
bool m_blockFreeingThreadShouldQuit;
#endif
#if ENABLE(SIMPLE_HEAP_PROFILING)
VTableSpectrum m_destroyedTypeCounts;
#endif
size_t m_extraCost;
ProtectCountSet m_protectedValues;
......
......@@ -53,6 +53,10 @@ void MarkStack::append(ConservativeRoots& conservativeRoots)
inline void SlotVisitor::visitChildren(JSCell* cell)
{
#if ENABLE(SIMPLE_HEAP_PROFILING)
m_visitedTypeCounts.count(cell);
#endif
ASSERT(Heap::isMarked(cell));
if (cell->structure()->typeInfo().type() < CompoundType) {
cell->JSCell::visitChildren(*this);
......@@ -108,6 +112,9 @@ void SlotVisitor::drain()
}
if (cell->structure()->typeInfo().type() < CompoundType) {
#if ENABLE(SIMPLE_HEAP_PROFILING)
m_visitedTypeCounts.count(cell);
#endif
cell->JSCell::visitChildren(*this);
if (current.m_values == end) {
m_markSets.removeLast();
......
......@@ -29,6 +29,8 @@
#include "HandleTypes.h"
#include "JSValue.h"
#include "Register.h"
#include "VTableSpectrum.h"
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
#include <wtf/Vector.h>
#include <wtf/Noncopyable.h>
......@@ -97,6 +99,10 @@ namespace JSC {
void reset();
#if ENABLE(SIMPLE_HEAP_PROFILING)
VTableSpectrum m_visitedTypeCounts;
#endif
protected:
#if ENABLE(GC_VALIDATION)
static void validateSet(JSValue*, size_t);
......@@ -114,7 +120,7 @@ namespace JSC {
MarkStackArray<MarkSet> m_markSets;
MarkStackArray<JSCell*> m_values;
HashSet<void*> m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector.
#if !ASSERT_DISABLED
public:
bool m_isCheckingForDefaultMarkViolation;
......
......@@ -67,6 +67,9 @@ void MarkedBlock::callDestructor(JSCell* cell, void* jsFinalObjectVPtr)
return;
void* vptr = cell->vptr();
if (specializedDestructorState == AllFreeCellsHaveObjects || vptr) {
#if ENABLE(SIMPLE_HEAP_PROFILING)
m_heap->m_destroyedTypeCounts.countVPtr(vptr);
#endif
if (vptr == jsFinalObjectVPtr) {
JSFinalObject* object = reinterpret_cast<JSFinalObject*>(cell);
object->JSFinalObject::~JSFinalObject();
......
......@@ -172,7 +172,7 @@ namespace JSC {
size_t ownerSetNumber(const JSCell*);
template<DestructorState destructorState>
static void callDestructor(JSCell*, void* jsFinalObjectVPtr);
void callDestructor(JSCell*, void* jsFinalObjectVPtr);
template<DestructorState destructorState>
void specializedReset();
......
/*
* Copyright (C) 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "VTableSpectrum.h"
#include "JSObject.h"
#include "Structure.h"
#include <algorithm>
#include <stdio.h>
#include <wtf/Platform.h>
#include <wtf/Vector.h>
#if PLATFORM(MAC)
#include <dlfcn.h>
#endif
namespace JSC {
VTableSpectrum::VTableSpectrum()
{
}
VTableSpectrum::~VTableSpectrum()
{
}
void VTableSpectrum::countVPtr(void* vTablePointer)
{
std::pair<HashMap<void*, unsigned long>::iterator, bool> result = m_map.add(vTablePointer, 1);
if (!result.second)
result.first->second++;
}
void VTableSpectrum::count(JSCell* cell)
{
countVPtr(cell->vptr());
}
struct VTableAndCount {
void* vtable;
unsigned long count;
VTableAndCount() { }
VTableAndCount(void* vtable, unsigned long count)
: vtable(vtable)
, count(count)
{
}
bool operator<(const VTableAndCount& other) const
{
if (count != other.count)
return count < other.count;
return vtable > other.vtable; // this results in lower-addressed vtables being printed first
}
};
void VTableSpectrum::dump(FILE* output, const char* comment)
{
fprintf(output, "%s:\n", comment);
HashMap<void*, unsigned long>::iterator begin = m_map.begin();
HashMap<void*, unsigned long>::iterator end = m_map.end();
Vector<VTableAndCount, 0> list;
for (HashMap<void*, unsigned long>::iterator iter = begin; iter != end; ++iter)
list.append(VTableAndCount(iter->first, iter->second));
std::sort(list.begin(), list.end());
for (size_t index = list.size(); index-- > 0;) {
VTableAndCount item = list.at(index);
#if PLATFORM(MAC)
Dl_info info;
if (dladdr(item.vtable, &info)) {
char* findResult = strrchr(info.dli_fname, '/');
const char* strippedFileName;
if (findResult)
strippedFileName = findResult + 1;
else
strippedFileName = info.dli_fname;
fprintf(output, " %s:%s(%p): %lu\n", strippedFileName, info.dli_sname, item.vtable, item.count);
continue;
}
#endif
fprintf(output, " %p: %lu\n", item.vtable, item.count);
}
fflush(output);
}
} // namespace JSC
/*
* Copyright (C) 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef VTableSpectrum_h
#define VTableSpectrum_h
#include <stdio.h>
#include <wtf/HashMap.h>
namespace JSC {
class JSCell;
class VTableSpectrum {
public:
VTableSpectrum();
~VTableSpectrum();
void countVPtr(void*);
void count(JSCell*);
void dump(FILE* output, const char* comment);
private:
HashMap<void*, unsigned long> m_map;
};
} // namespace JSC
#endif // VTableSpectrum_h
......@@ -963,6 +963,10 @@
#define ENABLE_VERBOSE_VALUE_PROFILE 0
#endif
#if !defined(ENABLE_SIMPLE_HEAP_PROFILING)
#define ENABLE_SIMPLE_HEAP_PROFILING 0
#endif
/* Counts uses of write barriers using sampling counters. Be sure to also
set ENABLE_SAMPLING_COUNTERS to 1. */
#if !defined(ENABLE_WRITE_BARRIER_PROFILING)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment