<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[24843] trunk/JavaScriptCore</title>
</head>
<body>
<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/24843">24843</a></dd>
<dt>Author</dt> <dd>bdash</dd>
<dt>Date</dt> <dd>2007-08-03 09:21:44 -0700 (Fri, 03 Aug 2007)</dd>
</dl>
<h3>Log Message</h3>
<pre>2007-08-02 Mark Rowe <mrowe@apple.com>
Reviewed by Geoff Garen.
<rdar://problem/4212199> 'leaks' reports false leaks in WebKit (because the WTF allocator uses mmap?)
Implement malloc zone introspection routines to allow leaks, heap, and friends to request information
about specific memory regions that were allocated by FastMalloc or the JavaScriptCore collector.
This requires tool-side support before the regions will be displayed. The addition of that support is
tracked by <rdar://problems/5353057&5353060>.
* JavaScriptCore.exp: Export the two variables that are used by leaks to introspect the allocators.
* JavaScriptCore.xcodeproj/project.pbxproj:
* kjs/AllInOneFile.cpp:
* kjs/CollectorZone.cpp: Added.
(KJS::):
(KJS::CollectorZone::registerZone):
(KJS::CollectorZone::CollectorZone): Create and register our zone with the system.
(KJS::CollectorZone::zoneEnumerator): Iterate over the CollectorBlocks that are in use and report them to the caller as being used.
* kjs/CollectorZone.h: Added.
(KJS::CollectorZone::zoneObjectSize): Return zero to indicate the specified pointer does not belong to this zone.
* kjs/collector.cpp:
(KJS::Collector::registerThread): Register the CollectorZone with the system when the first thread is registered with the collector.
* wtf/FastMalloc.cpp:
(WTF::TCMalloc_PageHeap::GetDescriptorEnsureSafe):
(WTF::TCMalloc_ThreadCache_FreeList::enumerateFreeObjects): Enumerate the objects on the free list.
(WTF::TCMalloc_ThreadCache::enumerateFreeObjects): Ditto.
(WTF::TCMalloc_Central_FreeList::enumerateFreeObjects): Ditto.
(WTF::TCMalloc_ThreadCache::InitModule): Register the FastMallocZone with the system when initializing TCMalloc.
(WTF::FreeObjectFinder::FreeObjectFinder):
(WTF::FreeObjectFinder::visit): Add an object to the free list.
(WTF::FreeObjectFinder::isFreeObject):
(WTF::FreeObjectFinder::freeObjectCount):
(WTF::FreeObjectFinder::findFreeObjects): Find the free objects within a thread cache or free list.
(WTF::PageMapFreeObjectFinder::PageMapFreeObjectFinder): Find the free objects within a TC_PageMap.
(WTF::PageMapFreeObjectFinder::visit): Called once per allocated span. Record whether the span or any subobjects are free.
(WTF::PageMapMemoryUsageRecorder::PageMapMemoryUsageRecorder):
(WTF::PageMapMemoryUsageRecorder::visit): Called once per allocated span. Report the range of memory as being allocated, and the span or
it's subobjects as being used if they do not appear on the free list.
(WTF::FastMallocZone::zoneEnumerator): Map the key remote TCMalloc data structures into our address space. We then locate all free memory ranges
before reporting the other ranges as being in use.
(WTF::FastMallocZone::zoneObjectSize): Determine whether the given pointer originates from within our allocation zone. If so,
we return its allocation size.
(WTF::FastMallocZone::zoneMalloc):
(WTF::FastMallocZone::zoneCalloc):
(WTF::FastMallocZone::zoneFree):
(WTF::FastMallocZone::zoneRealloc):
(WTF::):
(WTF::FastMallocZone::FastMallocZone): Create and register our zone with the system.
(WTF::FastMallocZone::registerZone):
* wtf/MallocZoneSupport.h: Added.
(WTF::RemoteMemoryReader::RemoteMemoryReader): A helper class to ease the process of mapping memory in a different process into
our local address space
(WTF::RemoteMemoryReader::operator()):
* wtf/TCPageMap.h:
(TCMalloc_PageMap2::visit): Walk over the heap and visit each allocated span.
(TCMalloc_PageMap3::visit): Ditto.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJavaScriptCoreChangeLog">trunk/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkJavaScriptCoreJavaScriptCoreexp">trunk/JavaScriptCore/JavaScriptCore.exp</a></li>
<li><a href="#trunkJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkJavaScriptCorekjsAllInOneFilecpp">trunk/JavaScriptCore/kjs/AllInOneFile.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjscollectorcpp">trunk/JavaScriptCore/kjs/collector.cpp</a></li>
<li><a href="#trunkJavaScriptCorewtfFastMalloccpp">trunk/JavaScriptCore/wtf/FastMalloc.cpp</a></li>
<li><a href="#trunkJavaScriptCorewtfTCPageMaph">trunk/JavaScriptCore/wtf/TCPageMap.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJavaScriptCorekjsCollectorHeapIntrospectorcpp">trunk/JavaScriptCore/kjs/CollectorHeapIntrospector.cpp</a></li>
<li><a href="#trunkJavaScriptCorekjsCollectorHeapIntrospectorh">trunk/JavaScriptCore/kjs/CollectorHeapIntrospector.h</a></li>
<li><a href="#trunkJavaScriptCorewtfMallocZoneSupporth">trunk/JavaScriptCore/wtf/MallocZoneSupport.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/ChangeLog (24842 => 24843)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/ChangeLog        2007-08-03 14:29:26 UTC (rev 24842)
+++ trunk/JavaScriptCore/ChangeLog        2007-08-03 16:21:44 UTC (rev 24843)
</span><span class="lines">@@ -1,5 +1,64 @@
</span><span class="cx"> 2007-08-02 Mark Rowe <mrowe@apple.com>
</span><span class="cx">
</span><ins>+ Reviewed by Geoff Garen.
+
+ <rdar://problem/4212199> 'leaks' reports false leaks in WebKit (because the WTF allocator uses mmap?)
+
+ Implement malloc zone introspection routines to allow leaks, heap, and friends to request information
+ about specific memory regions that were allocated by FastMalloc or the JavaScriptCore collector.
+
+ This requires tool-side support before the regions will be displayed. The addition of that support is
+ tracked by <rdar://problems/5353057&5353060>.
+
+ * JavaScriptCore.exp: Export the two variables that are used by leaks to introspect the allocators.
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * kjs/AllInOneFile.cpp:
+ * kjs/CollectorHeapIntrospector.cpp: Added.
+ (KJS::):
+ (KJS::CollectorHeapIntrospector::init):
+ (KJS::CollectorHeapIntrospector::CollectorHeapIntrospector): Create and register our zone with the system.
+ (KJS::CollectorHeapIntrospector::enumerate): Iterate over the CollectorBlocks that are in use and report them to the caller as being used.
+ * kjs/CollectorHeapIntrospector.h: Added.
+ (KJS::CollectorHeapIntrospector::size): Return zero to indicate the specified pointer does not belong to this zone.
+ * kjs/collector.cpp:
+ (KJS::Collector::registerThread): Register the CollectorHeapIntrospector with the system when the first thread is registered with the collector.
+ * wtf/FastMalloc.cpp:
+ (WTF::TCMalloc_PageHeap::GetDescriptorEnsureSafe):
+ (WTF::TCMalloc_ThreadCache_FreeList::enumerateFreeObjects): Enumerate the objects on the free list.
+ (WTF::TCMalloc_ThreadCache::enumerateFreeObjects): Ditto.
+ (WTF::TCMalloc_Central_FreeList::enumerateFreeObjects): Ditto.
+ (WTF::TCMalloc_ThreadCache::InitModule): Register the FastMallocZone with the system when initializing TCMalloc.
+ (WTF::FreeObjectFinder::FreeObjectFinder):
+ (WTF::FreeObjectFinder::visit): Add an object to the free list.
+ (WTF::FreeObjectFinder::isFreeObject):
+ (WTF::FreeObjectFinder::freeObjectCount):
+ (WTF::FreeObjectFinder::findFreeObjects): Find the free objects within a thread cache or free list.
+ (WTF::PageMapFreeObjectFinder::PageMapFreeObjectFinder): Find the free objects within a TC_PageMap.
+ (WTF::PageMapFreeObjectFinder::visit): Called once per allocated span. Record whether the span or any subobjects are free.
+ (WTF::PageMapMemoryUsageRecorder::PageMapMemoryUsageRecorder):
+ (WTF::PageMapMemoryUsageRecorder::visit): Called once per allocated span. Report the range of memory as being allocated, and the span or
+ its subobjects as being used if they do not appear on the free list.
+ (WTF::FastMallocZone::enumerate): Map the key remote TCMalloc data structures into our address space. We then locate all free memory ranges
+ before reporting the other ranges as being in use.
+ (WTF::FastMallocZone::size): Determine whether the given pointer originates from within our allocation zone. If so,
+ we return its allocation size.
+ (WTF::FastMallocZone::zoneMalloc):
+ (WTF::FastMallocZone::zoneCalloc):
+ (WTF::FastMallocZone::zoneFree):
+ (WTF::FastMallocZone::zoneRealloc):
+ (WTF::):
+ (WTF::FastMallocZone::FastMallocZone): Create and register our zone with the system.
+ (WTF::FastMallocZone::init):
+ * wtf/MallocZoneSupport.h: Added.
+ (WTF::RemoteMemoryReader::RemoteMemoryReader): A helper class to ease the process of mapping memory in a different process into
+ our local address space
+ (WTF::RemoteMemoryReader::operator()):
+ * wtf/TCPageMap.h:
+ (TCMalloc_PageMap2::visit): Walk over the heap and visit each allocated span.
+ (TCMalloc_PageMap3::visit): Ditto.
+
+2007-08-02 Mark Rowe <mrowe@apple.com>
+
</ins><span class="cx"> Build fix.
</span><span class="cx">
</span><span class="cx"> * kjs/ustring.cpp:
</span></span></pre></div>
<a id="trunkJavaScriptCoreJavaScriptCoreexp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/JavaScriptCore.exp (24842 => 24843)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/JavaScriptCore.exp        2007-08-03 14:29:26 UTC (rev 24842)
+++ trunk/JavaScriptCore/JavaScriptCore.exp        2007-08-03 16:21:44 UTC (rev 24843)
</span><span class="lines">@@ -1,3 +1,5 @@
</span><ins>+_jscore_collector_introspection
+_jscore_fastmalloc_introspection
</ins><span class="cx"> _JSCheckScriptSyntax
</span><span class="cx"> _JSClassCreate
</span><span class="cx"> _JSClassRelease
</span></span></pre></div>
<a id="trunkJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (24842 => 24843)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2007-08-03 14:29:26 UTC (rev 24842)
+++ trunk/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2007-08-03 16:21:44 UTC (rev 24843)
</span><span class="lines">@@ -81,6 +81,8 @@
</span><span class="cx">                 14F137830A3A765B00F26F90 /* context.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F137820A3A765B00F26F90 /* context.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 1CAF34890A6C421700ABE06E /* WebScriptObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CAF34880A6C421700ABE06E /* WebScriptObject.h */; };
</span><span class="cx">                 51F648D70BB4E2CA0033D760 /* RetainPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F648D60BB4E2CA0033D760 /* RetainPtr.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                5DBD18AC0C54018700C15EAE /* CollectorHeapIntrospector.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DBD18AA0C54018700C15EAE /* CollectorHeapIntrospector.h */; };
+                5DBD18B00C5401A700C15EAE /* MallocZoneSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 5DBD18AF0C5401A700C15EAE /* MallocZoneSupport.h */; };
</ins><span class="cx">                 65400C120A69BAF200509887 /* PropertyNameArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 65400C100A69BAF200509887 /* PropertyNameArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 6541BD7208E80A17002CBEE7 /* TCPageMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD6E08E80A17002CBEE7 /* TCPageMap.h */; };
</span><span class="cx">                 6541BD7308E80A17002CBEE7 /* TCSpinLock.h in Headers */ = {isa = PBXBuildFile; fileRef = 6541BD6F08E80A17002CBEE7 /* TCSpinLock.h */; };
</span><span class="lines">@@ -480,6 +482,9 @@
</span><span class="cx">                 51F0EC9605C88DC700E6DF1B /* objc_utility.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; name = objc_utility.h; path = bindings/objc/objc_utility.h; sourceTree = "<group>"; tabWidth = 8; };
</span><span class="cx">                 51F0EC9705C88DC700E6DF1B /* objc_utility.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = objc_utility.mm; path = bindings/objc/objc_utility.mm; sourceTree = "<group>"; tabWidth = 8; };
</span><span class="cx">                 51F648D60BB4E2CA0033D760 /* RetainPtr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RetainPtr.h; sourceTree = "<group>"; };
</span><ins>+                5DBD18A90C54018700C15EAE /* CollectorHeapIntrospector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollectorHeapIntrospector.cpp; sourceTree = "<group>"; };
+                5DBD18AA0C54018700C15EAE /* CollectorHeapIntrospector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectorHeapIntrospector.h; sourceTree = "<group>"; };
+                5DBD18AF0C5401A700C15EAE /* MallocZoneSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MallocZoneSupport.h; sourceTree = "<group>"; };
</ins><span class="cx">                 651F6412039D5B5F0078395C /* dtoa.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dtoa.cpp; sourceTree = "<group>"; tabWidth = 8; };
</span><span class="cx">                 651F6413039D5B5F0078395C /* dtoa.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = dtoa.h; sourceTree = "<group>"; tabWidth = 8; };
</span><span class="cx">                 65400C0F0A69BAF200509887 /* PropertyNameArray.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyNameArray.cpp; sourceTree = "<group>"; };
</span><span class="lines">@@ -907,6 +912,7 @@
</span><span class="cx">                                 65DFC92F08EA173A00F7300B /* HashTraits.h */,
</span><span class="cx">                                 657EB7450B708F540063461B /* ListHashSet.h */,
</span><span class="cx">                                 148A1626095D16BB00666D0D /* ListRefPtr.h */,
</span><ins>+                                5DBD18AF0C5401A700C15EAE /* MallocZoneSupport.h */,
</ins><span class="cx">                                 BCF6553B0A2048DE0038A194 /* MathExtras.h */,
</span><span class="cx">                                 9303F5690991190000AD71B8 /* Noncopyable.h */,
</span><span class="cx">                                 9303F5A409911A5800AD71B8 /* OwnArrayPtr.h */,
</span><span class="lines">@@ -946,6 +952,8 @@
</span><span class="cx">                                 704FD35305697E6D003DBED9 /* bool_object.h */,
</span><span class="cx">                                 F692A8520255597D01FF60F7 /* collector.cpp */,
</span><span class="cx">                                 F692A8530255597D01FF60F7 /* collector.h */,
</span><ins>+                                5DBD18AA0C54018700C15EAE /* CollectorHeapIntrospector.h */,
+                                5DBD18A90C54018700C15EAE /* CollectorHeapIntrospector.cpp */,
</ins><span class="cx">                                 F5BB2BC5030F772101FCFE1D /* completion.h */,
</span><span class="cx">                                 F68EBB8C0255D4C601FF60F7 /* config.h */,
</span><span class="cx">                                 14F137580A3A727E00F26F90 /* Context.cpp */,
</span><span class="lines">@@ -1239,6 +1247,8 @@
</span><span class="cx">                                 657EB7460B708F540063461B /* ListHashSet.h in Headers */,
</span><span class="cx">                                 65EA73650BAE35D1001BB560 /* CommonIdentifiers.h in Headers */,
</span><span class="cx">                                 51F648D70BB4E2CA0033D760 /* RetainPtr.h in Headers */,
</span><ins>+                                5DBD18AC0C54018700C15EAE /* CollectorHeapIntrospector.h in Headers */,
+                                5DBD18B00C5401A700C15EAE /* MallocZoneSupport.h in Headers */,
</ins><span class="cx">                         );
</span><span class="cx">                         runOnlyForDeploymentPostprocessing = 0;
</span><span class="cx">                 };
</span><span class="lines">@@ -1352,6 +1362,7 @@
</span><span class="cx">                 0867D690FE84028FC02AAC07 /* Project object */ = {
</span><span class="cx">                         isa = PBXProject;
</span><span class="cx">                         buildConfigurationList = 149C277108902AFE008A9EFC /* Build configuration list for PBXProject "JavaScriptCore" */;
</span><ins>+                        compatibilityVersion = "Xcode 2.4";
</ins><span class="cx">                         hasScannedForEncodings = 1;
</span><span class="cx">                         mainGroup = 0867D691FE84028FC02AAC07 /* JavaScriptCore */;
</span><span class="cx">                         productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsAllInOneFilecpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/AllInOneFile.cpp (24842 => 24843)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/AllInOneFile.cpp        2007-08-03 14:29:26 UTC (rev 24842)
+++ trunk/JavaScriptCore/kjs/AllInOneFile.cpp        2007-08-03 16:21:44 UTC (rev 24843)
</span><span class="lines">@@ -24,12 +24,16 @@
</span><span class="cx"> // that see a significant speed gain from this.
</span><span class="cx">
</span><span class="cx"> #define KDE_USE_FINAL 1
</span><ins>+#include "config.h"
</ins><span class="cx">
</span><span class="cx"> #include "function.cpp"
</span><span class="cx"> #include "debugger.cpp"
</span><span class="cx"> #include "array_object.cpp"
</span><span class="cx"> #include "bool_object.cpp"
</span><span class="cx"> #include "collector.cpp"
</span><ins>+#if PLATFORM(DARWIN)
+#include "CollectorHeapIntrospector.cpp"
+#endif
</ins><span class="cx"> #include "CommonIdentifiers.cpp"
</span><span class="cx"> #include "Context.cpp"
</span><span class="cx"> #include "date_object.cpp"
</span></span></pre></div>
<a id="trunkJavaScriptCorekjsCollectorHeapIntrospectorcpp"></a>
<div class="addfile"><h4>Added: trunk/JavaScriptCore/kjs/CollectorHeapIntrospector.cpp (0 => 24843)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/CollectorHeapIntrospector.cpp         (rev 0)
+++ trunk/JavaScriptCore/kjs/CollectorHeapIntrospector.cpp        2007-08-03 16:21:44 UTC (rev 24843)
</span><span class="lines">@@ -0,0 +1,83 @@
</span><ins>+/*
+ * Copyright (C) 2007 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 "CollectorHeapIntrospector.h"
+
+#include "collector.h"
+#include "MallocZoneSupport.h"
+
+namespace KJS {
+
+extern "C" {
+malloc_introspection_t jscore_collector_introspection = { &CollectorHeapIntrospector::enumerate, 0, 0, 0, 0, 0, 0, 0 };
+}
+
+void CollectorHeapIntrospector::init(CollectorHeap* heap)
+{
+ static CollectorHeapIntrospector zone(heap);
+}
+
+CollectorHeapIntrospector::CollectorHeapIntrospector(CollectorHeap* heap)
+ : m_heap(heap)
+{
+ memset(&m_zone, 0, sizeof(m_zone));
+ m_zone.zone_name = "JavaScriptCore Collector";
+ m_zone.size = &CollectorHeapIntrospector::size;
+ m_zone.introspect = &jscore_collector_introspection;
+ malloc_zone_register(&m_zone);
+}
+
+kern_return_t CollectorHeapIntrospector::enumerate(task_t task, void* context, unsigned typeMask, vm_address_t zoneAddress, memory_reader_t reader, vm_range_recorder_t recorder)
+{
+ RemoteMemoryReader memoryReader(task, reader);
+ CollectorHeapIntrospector* zone = memoryReader(reinterpret_cast<CollectorHeapIntrospector*>(zoneAddress));
+ CollectorHeap* heap = memoryReader(zone->m_heap);
+
+ if (!heap->blocks)
+ return 0;
+
+ CollectorBlock** blocks = memoryReader(heap->blocks);
+ for (unsigned i = 0; i < heap->usedBlocks; i++) {
+ vm_address_t remoteBlockAddress = reinterpret_cast<vm_address_t>(blocks[i]);
+ vm_range_t ptrRange = { remoteBlockAddress, sizeof(CollectorBlock) };
+
+ if (typeMask & (MALLOC_PTR_REGION_RANGE_TYPE | MALLOC_ADMIN_REGION_RANGE_TYPE))
+ (*recorder)(task, context, MALLOC_PTR_REGION_RANGE_TYPE, &ptrRange, 1);
+
+ // Recording individual cells causes frequent false-positives. Any garbage cells
+ // which have yet to be collected are labeled as leaks. Recording on a per-block
+ // basis provides less detail but avoids these false-positives.
+ if (memoryReader(blocks[i])->usedCells && (typeMask & MALLOC_PTR_IN_USE_RANGE_TYPE))
+ (*recorder)(task, context, MALLOC_PTR_IN_USE_RANGE_TYPE, &ptrRange, 1);
+ }
+
+ return 0;
+}
+
+} // namespace KJS
</ins></span></pre></div>
<a id="trunkJavaScriptCorekjsCollectorHeapIntrospectorh"></a>
<div class="addfile"><h4>Added: trunk/JavaScriptCore/kjs/CollectorHeapIntrospector.h (0 => 24843)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/CollectorHeapIntrospector.h         (rev 0)
+++ trunk/JavaScriptCore/kjs/CollectorHeapIntrospector.h        2007-08-03 16:21:44 UTC (rev 24843)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+/*
+ * Copyright (C) 2007 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 CollectorHeapIntrospector_h
+#define CollectorHeapIntrospector_h
+
+#include <malloc/malloc.h>
+
+namespace KJS {
+
+struct CollectorHeap;
+
+class CollectorHeapIntrospector {
+public:
+ static void init(CollectorHeap*);
+ static kern_return_t enumerate(task_t, void* context, unsigned typeMask, vm_address_t zoneAddress, memory_reader_t, vm_range_recorder_t);
+
+private:
+ CollectorHeapIntrospector(CollectorHeap*);
+ static size_t size(malloc_zone_t*, const void*) { return 0; }
+
+ malloc_zone_t m_zone;
+ CollectorHeap* m_heap;
+};
+
+}
+
+#endif // CollectorHeapIntrospector_h
</ins></span></pre></div>
<a id="trunkJavaScriptCorekjscollectorcpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/kjs/collector.cpp (24842 => 24843)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/kjs/collector.cpp        2007-08-03 14:29:26 UTC (rev 24842)
+++ trunk/JavaScriptCore/kjs/collector.cpp        2007-08-03 16:21:44 UTC (rev 24843)
</span><span class="lines">@@ -45,6 +45,8 @@
</span><span class="cx"> #include <mach/thread_act.h>
</span><span class="cx"> #include <mach/vm_map.h>
</span><span class="cx">
</span><ins>+#include "CollectorHeapIntrospector.h"
+
</ins><span class="cx"> #elif PLATFORM(WIN_OS)
</span><span class="cx">
</span><span class="cx"> #include <windows.h>
</span><span class="lines">@@ -403,6 +405,11 @@
</span><span class="cx"> if (!pthread_getspecific(registeredThreadKey)) {
</span><span class="cx"> if (!onMainThread())
</span><span class="cx"> WTF::fastMallocSetIsMultiThreaded();
</span><ins>+#if PLATFORM(DARWIN)
+ else
+ CollectorHeapIntrospector::init(&heap);
+#endif
+
</ins><span class="cx"> Collector::Thread *thread = new Collector::Thread(pthread_self(), getCurrentPlatformThread());
</span><span class="cx">
</span><span class="cx"> thread->next = registeredThreads;
</span></span></pre></div>
<a id="trunkJavaScriptCorewtfFastMalloccpp"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/wtf/FastMalloc.cpp (24842 => 24843)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/wtf/FastMalloc.cpp        2007-08-03 14:29:26 UTC (rev 24842)
+++ trunk/JavaScriptCore/wtf/FastMalloc.cpp        2007-08-03 16:21:44 UTC (rev 24843)
</span><span class="lines">@@ -166,6 +166,12 @@
</span><span class="cx">
</span><span class="cx"> } // namespace WTF
</span><span class="cx">
</span><ins>+#if PLATFORM(DARWIN)
+// This symbol is present in the JavaScriptCore exports file even when FastMalloc is disabled.
+// It will never be used in this case, so it's type and value are less interesting than its presence.
+extern "C" const int jscore_fastmalloc_introspection = 0;
+#endif
+
</ins><span class="cx"> #else
</span><span class="cx">
</span><span class="cx"> #if HAVE(STDINT_H)
</span><span class="lines">@@ -190,6 +196,10 @@
</span><span class="cx"> #include <string.h>
</span><span class="cx">
</span><span class="cx"> #if WTF_CHANGES
</span><ins>+#if PLATFORM(DARWIN)
+#include "MallocZoneSupport.h"
+#endif
+
</ins><span class="cx"> namespace WTF {
</span><span class="cx">
</span><span class="cx"> #define malloc fastMalloc
</span><span class="lines">@@ -200,8 +210,35 @@
</span><span class="cx"> #define MESSAGE LOG_ERROR
</span><span class="cx"> #define CHECK_CONDITION ASSERT
</span><span class="cx">
</span><ins>+#if PLATFORM(DARWIN)
+class TCMalloc_PageHeap;
+class TCMalloc_ThreadCache;
+class TCMalloc_Central_FreeListPadded;
+
+class FastMallocZone {
+public:
+ static void init();
+
+ static kern_return_t enumerate(task_t, void*, unsigned typeMmask, vm_address_t zoneAddress, memory_reader_t, vm_range_recorder_t);
+
+private:
+ FastMallocZone(TCMalloc_PageHeap*, TCMalloc_ThreadCache**, TCMalloc_Central_FreeListPadded*);
+ static size_t size(malloc_zone_t*, const void*);
+ static void* zoneMalloc(malloc_zone_t*, size_t);
+ static void* zoneCalloc(malloc_zone_t*, size_t numItems, size_t size);
+ static void zoneFree(malloc_zone_t*, void*);
+ static void* zoneRealloc(malloc_zone_t*, void*, size_t);
+
+ malloc_zone_t m_zone;
+ TCMalloc_PageHeap* m_pageHeap;
+ TCMalloc_ThreadCache** m_threadHeaps;
+ TCMalloc_Central_FreeListPadded* m_centralCaches;
+};
+
</ins><span class="cx"> #endif
</span><span class="cx">
</span><ins>+#endif
+
</ins><span class="cx"> #if HAVE(INTTYPES_H)
</span><span class="cx"> #define __STDC_FORMAT_MACROS
</span><span class="cx"> #include <inttypes.h>
</span><span class="lines">@@ -707,6 +744,14 @@
</span><span class="cx"> return reinterpret_cast<Span*>(pagemap_.get(p));
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+#ifdef WTF_CHANGES
+ inline Span* GetDescriptorEnsureSafe(PageID p)
+ {
+ pagemap_.Ensure(p, 1);
+ return GetDescriptor(p);
+ }
+#endif
+
</ins><span class="cx"> // Dump state to stderr
</span><span class="cx"> #ifndef WTF_CHANGES
</span><span class="cx"> void Dump(TCMalloc_Printer* out);
</span><span class="lines">@@ -755,6 +800,9 @@
</span><span class="cx"> pagemap_.set(span->start + span->length - 1, span);
</span><span class="cx"> }
</span><span class="cx"> }
</span><ins>+#if defined(WTF_CHANGES) && PLATFORM(DARWIN)
+ friend class FastMallocZone;
+#endif
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> void TCMalloc_PageHeap::init()
</span><span class="lines">@@ -1060,6 +1108,15 @@
</span><span class="cx"> if (length_ < lowater_) lowater_ = length_;
</span><span class="cx"> return result;
</span><span class="cx"> }
</span><ins>+
+#ifdef WTF_CHANGES
+ template <class Finder, class Reader>
+ void enumerateFreeObjects(Finder& finder, const Reader& reader)
+ {
+ for (void* nextObject = list_; nextObject; nextObject = *reader(reinterpret_cast<void**>(nextObject)))
+ finder.visit(nextObject);
+ }
+#endif
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> //-------------------------------------------------------------------
</span><span class="lines">@@ -1115,6 +1172,15 @@
</span><span class="cx"> static void* CreateCacheIfNecessary();
</span><span class="cx"> static void DeleteCache(void* ptr);
</span><span class="cx"> static void RecomputeThreadCacheSize();
</span><ins>+
+#ifdef WTF_CHANGES
+ template <class Finder, class Reader>
+ void enumerateFreeObjects(Finder& finder, const Reader& reader)
+ {
+ for (unsigned sizeClass = 0; sizeClass < kNumClasses; sizeClass++)
+ list_[sizeClass].enumerateFreeObjects(finder, reader);
+ }
+#endif
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> //-------------------------------------------------------------------
</span><span class="lines">@@ -1147,6 +1213,21 @@
</span><span class="cx"> // Lock -- exposed because caller grabs it before touching this object
</span><span class="cx"> SpinLock lock_;
</span><span class="cx">
</span><ins>+#ifdef WTF_CHANGES
+ template <class Finder, class Reader>
+ void enumerateFreeObjects(Finder& finder, const Reader& reader)
+ {
+ for (Span* span = &empty_; span && span != &empty_; span = (span->next ? reader(span->next) : 0))
+ ASSERT(!span->objects);
+
+ ASSERT(!nonempty_.objects);
+ for (Span* span = reader(nonempty_.next); span && span != &nonempty_; span = (span->next ? reader(span->next) : 0)) {
+ for (void* nextObject = span->objects; nextObject; nextObject = *reader(reinterpret_cast<void**>(nextObject)))
+ finder.visit(nextObject);
+ }
+ }
+#endif
+
</ins><span class="cx"> private:
</span><span class="cx"> // We keep linked lists of empty and non-emoty spans.
</span><span class="cx"> size_t size_class_; // My size class
</span><span class="lines">@@ -1559,6 +1640,9 @@
</span><span class="cx"> }
</span><span class="cx"> pageheap->init();
</span><span class="cx"> phinited = 1;
</span><ins>+#if defined(WTF_CHANGES) && PLATFORM(DARWIN)
+ FastMallocZone::init();
+#endif
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -2407,6 +2491,231 @@
</span><span class="cx">
</span><span class="cx"> #endif
</span><span class="cx">
</span><ins>+#if defined(WTF_CHANGES) && PLATFORM(DARWIN)
+#include <wtf/HashSet.h>
+
+class FreeObjectFinder {
+ const RemoteMemoryReader& m_reader;
+ HashSet<void*> m_freeObjects;
+
+public:
+ FreeObjectFinder(const RemoteMemoryReader& reader) : m_reader(reader) { }
+
+ void visit(void* ptr) { m_freeObjects.add(ptr); }
+ bool isFreeObject(void* ptr) const { return m_freeObjects.contains(ptr); }
+ size_t freeObjectCount() const { return m_freeObjects.size(); }
+
+ void findFreeObjects(TCMalloc_ThreadCache* threadCache)
+ {
+ for (; threadCache; threadCache = threadCache->next_)
+ threadCache->enumerateFreeObjects(*this, m_reader);
+ }
+
+ void findFreeObjects(TCMalloc_Central_FreeListPadded* centralFreeList, size_t numSizes)
+ {
+ for (unsigned i = 0; i < numSizes; i++)
+ centralFreeList[i].enumerateFreeObjects(*this, m_reader);
+ }
+};
+
+class PageMapFreeObjectFinder {
+ const RemoteMemoryReader& m_reader;
+ FreeObjectFinder& m_freeObjectFinder;
+
+public:
+ PageMapFreeObjectFinder(const RemoteMemoryReader& reader, FreeObjectFinder& freeObjectFinder)
+ : m_reader(reader)
+ , m_freeObjectFinder(freeObjectFinder)
+ { }
+
+ int visit(void* ptr) const
+ {
+ if (!ptr)
+ return 1;
+
+ Span* span = m_reader(reinterpret_cast<Span*>(ptr));
+ if (span->free) {
+ void* ptr = reinterpret_cast<void*>(span->start << kPageShift);
+ m_freeObjectFinder.visit(ptr);
+ } else if (span->sizeclass) {
+ // Walk the free list of the small-object span, keeping track of each object seen
+ for (void* nextObject = span->objects; nextObject; nextObject = *m_reader(reinterpret_cast<void**>(nextObject)))
+ m_freeObjectFinder.visit(nextObject);
+ }
+ return span->length;
+ }
+};
+
+class PageMapMemoryUsageRecorder {
+ task_t m_task;
+ void* m_context;
+ unsigned m_typeMask;
+ vm_range_recorder_t* m_recorder;
+ const RemoteMemoryReader& m_reader;
+ const FreeObjectFinder& m_freeObjectFinder;
+ mutable HashSet<void*> m_seenPointers;
+
+public:
+ PageMapMemoryUsageRecorder(task_t task, void* context, unsigned typeMask, vm_range_recorder_t* recorder, const RemoteMemoryReader& reader, const FreeObjectFinder& freeObjectFinder)
+ : m_task(task)
+ , m_context(context)
+ , m_typeMask(typeMask)
+ , m_recorder(recorder)
+ , m_reader(reader)
+ , m_freeObjectFinder(freeObjectFinder)
+ { }
+
+ int visit(void* ptr) const
+ {
+ if (!ptr)
+ return 1;
+
+ Span* span = m_reader(reinterpret_cast<Span*>(ptr));
+ if (m_seenPointers.contains(ptr))
+ return span->length;
+ m_seenPointers.add(ptr);
+
+ // Mark the memory used for the Span itself as an administrative region
+ vm_range_t ptrRange = { reinterpret_cast<vm_address_t>(ptr), sizeof(Span) };
+ if (m_typeMask & (MALLOC_PTR_REGION_RANGE_TYPE | MALLOC_ADMIN_REGION_RANGE_TYPE))
+ (*m_recorder)(m_task, m_context, MALLOC_ADMIN_REGION_RANGE_TYPE, &ptrRange, 1);
+
+ ptrRange.address = span->start << kPageShift;
+ ptrRange.size = span->length * kPageSize;
+
+ // Mark the memory region the span represents as candidates for containing pointers
+ if (m_typeMask & (MALLOC_PTR_REGION_RANGE_TYPE | MALLOC_ADMIN_REGION_RANGE_TYPE))
+ (*m_recorder)(m_task, m_context, MALLOC_PTR_REGION_RANGE_TYPE, &ptrRange, 1);
+
+ if (!span->free && (m_typeMask & MALLOC_PTR_IN_USE_RANGE_TYPE)) {
+ // If it's an allocated large object span, mark it as in use
+ if (span->sizeclass == 0 && !m_freeObjectFinder.isFreeObject(reinterpret_cast<void*>(ptrRange.address)))
+ (*m_recorder)(m_task, m_context, MALLOC_PTR_IN_USE_RANGE_TYPE, &ptrRange, 1);
+ else if (span->sizeclass) {
+ const size_t byteSize = ByteSizeForClass(span->sizeclass);
+ unsigned totalObjects = (span->length << kPageShift) / byteSize;
+ ASSERT(span->refcount <= totalObjects);
+ char* ptr = reinterpret_cast<char*>(span->start << kPageShift);
+
+ // Mark each allocated small object within the span as in use
+ for (unsigned i = 0; i < totalObjects; i++) {
+ char* thisObject = ptr + (i * byteSize);
+ if (m_freeObjectFinder.isFreeObject(thisObject))
+ continue;
+
+ vm_range_t objectRange = { reinterpret_cast<vm_address_t>(thisObject), byteSize };
+ (*m_recorder)(m_task, m_context, MALLOC_PTR_IN_USE_RANGE_TYPE, &objectRange, 1);
+ }
+ }
+ }
+
+ return span->length;
+ }
+};
+
+kern_return_t FastMallocZone::enumerate(task_t task, void* context, unsigned typeMask, vm_address_t zoneAddress, memory_reader_t reader, vm_range_recorder_t recorder)
+{
+ RemoteMemoryReader memoryReader(task, reader);
+
+ InitSizeClasses();
+
+ FastMallocZone* mzone = memoryReader(reinterpret_cast<FastMallocZone*>(zoneAddress));
+ TCMalloc_PageHeap* pageHeap = memoryReader(mzone->m_pageHeap);
+ TCMalloc_ThreadCache** threadHeapsPointer = memoryReader(mzone->m_threadHeaps);
+ TCMalloc_ThreadCache* threadHeaps = memoryReader(*threadHeapsPointer);
+
+ TCMalloc_Central_FreeListPadded* centralCaches = memoryReader(mzone->m_centralCaches, sizeof(TCMalloc_Central_FreeListPadded) * kNumClasses);
+
+ // Rebuild the linked list in our address space, mapping over the remote pointers as needed
+ for (TCMalloc_ThreadCache* threadHeap = threadHeaps; threadHeap->next_; threadHeap = threadHeap->next_) {
+ threadHeap->next_ = memoryReader(threadHeap->next_);
+ threadHeap->next_->prev_ = threadHeap;
+ }
+
+ FreeObjectFinder finder(memoryReader);
+ finder.findFreeObjects(threadHeaps);
+ finder.findFreeObjects(centralCaches, kNumClasses);
+
+ TCMalloc_PageHeap::PageMap* pageMap = &pageHeap->pagemap_;
+ PageMapFreeObjectFinder pageMapFinder(memoryReader, finder);
+ pageMap->visit(pageMapFinder, memoryReader);
+
+ PageMapMemoryUsageRecorder usageRecorder(task, context, typeMask, recorder, memoryReader, finder);
+ pageMap->visit(usageRecorder, memoryReader);
+
+ return 0;
+}
+
+size_t FastMallocZone::size(malloc_zone_t* zone, const void* ptr)
+{
+ if (!ptr || !pageheap)
+ return 0;
+
+ const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
+ Span* span = pageheap->GetDescriptorEnsureSafe(p);
+ if (!span)
+ return 0;
+
+ if (span->sizeclass == 0)
+ return span->length * kPageSize;
+
+ return ByteSizeForClass(span->sizeclass);
+}
+
+void* FastMallocZone::zoneMalloc(malloc_zone_t* zone, size_t size)
+{
+ return fastMalloc(size);
+}
+
+void* FastMallocZone::zoneCalloc(malloc_zone_t*, size_t numItems, size_t size)
+{
+ return fastCalloc(numItems, size);
+}
+
+void FastMallocZone::zoneFree(malloc_zone_t*, void* ptr)
+{
+ return fastFree(ptr);
+}
+
+void* FastMallocZone::zoneRealloc(malloc_zone_t*, void* ptr, size_t size)
+{
+ return fastRealloc(ptr, size);
+}
+
+
+#undef malloc
+#undef free
+#undef realloc
+#undef calloc
+
+extern "C" {
+malloc_introspection_t jscore_fastmalloc_introspection = { &FastMallocZone::enumerate, 0, 0, 0, 0, 0, 0, 0 };
+}
+
+FastMallocZone::FastMallocZone(TCMalloc_PageHeap* pageHeap, TCMalloc_ThreadCache** threadHeaps, TCMalloc_Central_FreeListPadded* centralCaches)
+ : m_pageHeap(pageHeap)
+ , m_threadHeaps(threadHeaps)
+ , m_centralCaches(centralCaches)
+{
+ memset(&m_zone, 0, sizeof(m_zone));
+ m_zone.zone_name = "JavaScriptCore FastMalloc";
+ m_zone.size = &FastMallocZone::size;
+ m_zone.malloc = &FastMallocZone::zoneMalloc;
+ m_zone.calloc = &FastMallocZone::zoneCalloc;
+ m_zone.realloc = &FastMallocZone::zoneRealloc;
+ m_zone.free = &FastMallocZone::zoneFree;
+ m_zone.introspect = &jscore_fastmalloc_introspection;
+ malloc_zone_register(&m_zone);
+}
+
+
+void FastMallocZone::init()
+{
+ static FastMallocZone zone(getPageHeap(), &thread_heaps, static_cast<TCMalloc_Central_FreeListPadded*>(central_cache));
+}
+
+#endif
+
</ins><span class="cx"> #if WTF_CHANGES
</span><span class="cx"> } // namespace WTF
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkJavaScriptCorewtfMallocZoneSupporth"></a>
<div class="addfile"><h4>Added: trunk/JavaScriptCore/wtf/MallocZoneSupport.h (0 => 24843)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/wtf/MallocZoneSupport.h         (rev 0)
+++ trunk/JavaScriptCore/wtf/MallocZoneSupport.h        2007-08-03 16:21:44 UTC (rev 24843)
</span><span class="lines">@@ -0,0 +1,65 @@
</span><ins>+/*
+ * Copyright (C) 2007 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 MallocZoneSupport_h
+#define MallocZoneSupport_h
+
+#include <malloc/malloc.h>
+
+namespace WTF {
+
+class RemoteMemoryReader {
+ task_t m_task;
+ memory_reader_t* m_reader;
+
+public:
+ RemoteMemoryReader(task_t task, memory_reader_t* reader)
+ : m_task(task)
+ , m_reader(reader)
+ { }
+
+ void* operator()(vm_address_t address, size_t size) const
+ {
+ void* output;
+ kern_return_t err = (*m_reader)(m_task, address, size, static_cast<void**>(&output));
+ ASSERT(!err);
+ if (err)
+ output = 0;
+ return output;
+ }
+
+ template <typename T>
+ T* operator()(T* address, size_t size=sizeof(T)) const
+ {
+ return static_cast<T*>((*this)(reinterpret_cast<vm_address_t>(address), size));
+ }
+};
+
+} // namespace WTF
+
+#endif // MallocZoneSupport_h
</ins></span></pre></div>
<a id="trunkJavaScriptCorewtfTCPageMaph"></a>
<div class="modfile"><h4>Modified: trunk/JavaScriptCore/wtf/TCPageMap.h (24842 => 24843)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JavaScriptCore/wtf/TCPageMap.h        2007-08-03 14:29:26 UTC (rev 24842)
+++ trunk/JavaScriptCore/wtf/TCPageMap.h        2007-08-03 16:21:44 UTC (rev 24843)
</span><span class="lines">@@ -156,6 +156,21 @@
</span><span class="cx"> }
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><ins>+
+#ifdef WTF_CHANGES
+ template<class Visitor, class MemoryReader>
+ void visit(const Visitor& visitor, const MemoryReader& reader)
+ {
+ for (int i = 0; i < ROOT_LENGTH; i++) {
+ if (!root_[i])
+ continue;
+
+ Leaf* l = reader(reinterpret_cast<Leaf*>(root_[i]));
+ for (int j = 0; j < LEAF_LENGTH; j += visitor.visit(l->values[j]))
+ ;
+ }
+ }
+#endif
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> // Three-level radix tree
</span><span class="lines">@@ -240,6 +255,27 @@
</span><span class="cx"> }
</span><span class="cx"> return true;
</span><span class="cx"> }
</span><ins>+
+#ifdef WTF_CHANGES
+ template<class Visitor, class MemoryReader>
+ void visit(const Visitor& visitor, const MemoryReader& reader) {
+ Node* root = reader(root_);
+ for (int i = 0; i < INTERIOR_LENGTH; i++) {
+ if (!root->ptrs[i])
+ continue;
+
+ Node* n = reader(root->ptrs[i]);
+ for (int j = 0; j < INTERIOR_LENGTH; j++) {
+ if (!n->ptrs[j])
+ continue;
+
+ Leaf* l = reader(reinterpret_cast<Leaf*>(n->ptrs[j]));
+ for (int k = 0; k < LEAF_LENGTH; k += visitor.visit(l->values[k]))
+ ;
+ }
+ }
+ }
+#endif
</ins><span class="cx"> };
</span><span class="cx">
</span><span class="cx"> #endif // TCMALLOC_PAGEMAP_H__
</span></span></pre>
</div>
</div>
</body>
</html>