Added WTF::StackStats mechanism.
authormark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Oct 2012 20:09:36 +0000 (20:09 +0000)
committermark.lam@apple.com <mark.lam@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 19 Oct 2012 20:09:36 +0000 (20:09 +0000)
https://bugs.webkit.org/show_bug.cgi?id=99805.

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

Added StackStats checkpoints and probes.

* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::emitNode):
(JSC::BytecodeGenerator::emitNodeInConditionContext):
* heap/SlotVisitor.cpp:
(JSC::SlotVisitor::append):
(JSC::visitChildren):
(JSC::SlotVisitor::donateKnownParallel):
(JSC::SlotVisitor::drain):
(JSC::SlotVisitor::drainFromShared):
(JSC::SlotVisitor::mergeOpaqueRoots):
(JSC::SlotVisitor::internalAppend):
(JSC::SlotVisitor::harvestWeakReferences):
(JSC::SlotVisitor::finalizeUnconditionalFinalizers):
* interpreter/Interpreter.cpp:
(JSC::Interpreter::execute):
(JSC::Interpreter::executeCall):
(JSC::Interpreter::executeConstruct):
(JSC::Interpreter::prepareForRepeatCall):
* parser/Parser.h:
(JSC::Parser::canRecurse):
* runtime/StringRecursionChecker.h:
(StringRecursionChecker):

Source/WebCore:

Added StackStats probes in layout methods.

* dom/Document.cpp:
(WebCore::Document::updateLayout):
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::layout):
* rendering/RenderBox.cpp:
(WebCore::RenderBox::layout):
* rendering/RenderDialog.cpp:
(WebCore::RenderDialog::layout):
* rendering/RenderEmbeddedObject.cpp:
(WebCore::RenderEmbeddedObject::layout):
* rendering/RenderFlowThread.cpp:
(WebCore::RenderFlowThread::layout):
* rendering/RenderFrameSet.cpp:
(WebCore::RenderFrameSet::layout):
* rendering/RenderIFrame.cpp:
(WebCore::RenderIFrame::layout):
* rendering/RenderImage.cpp:
(WebCore::RenderImage::layout):
* rendering/RenderListBox.cpp:
(WebCore::RenderListBox::layout):
* rendering/RenderListItem.cpp:
(WebCore::RenderListItem::layout):
* rendering/RenderListMarker.cpp:
(WebCore::RenderListMarker::layout):
* rendering/RenderMedia.cpp:
(WebCore::RenderMedia::layout):
* rendering/RenderObject.cpp:
(WebCore::RenderObject::layout):
* rendering/RenderObject.h:
* rendering/RenderRegion.cpp:
(WebCore::RenderRegion::layout):
* rendering/RenderReplaced.cpp:
(WebCore::RenderReplaced::layout):
* rendering/RenderReplica.cpp:
(WebCore::RenderReplica::layout):
* rendering/RenderRubyRun.cpp:
(WebCore::RenderRubyRun::layoutSpecialExcludedChild):
* rendering/RenderScrollbarPart.cpp:
(WebCore::RenderScrollbarPart::layout):
* rendering/RenderSlider.cpp:
(WebCore::RenderSlider::layout):
* rendering/RenderTable.cpp:
(WebCore::RenderTable::layout):
* rendering/RenderTableCell.cpp:
(WebCore::RenderTableCell::layout):
* rendering/RenderTableRow.cpp:
(WebCore::RenderTableRow::layout):
* rendering/RenderTableSection.cpp:
(WebCore::RenderTableSection::layout):
* rendering/RenderTextControlSingleLine.cpp:
(WebCore::RenderTextControlSingleLine::layout):
* rendering/RenderTextTrackCue.cpp:
(WebCore::RenderTextTrackCue::layout):
* rendering/RenderVideo.cpp:
(WebCore::RenderVideo::layout):
* rendering/RenderView.cpp:
(WebCore::RenderView::layout):
* rendering/RenderWidget.cpp:
(WebCore::RenderWidget::layout):
* rendering/svg/RenderSVGContainer.cpp:
(WebCore::RenderSVGContainer::layout):
* rendering/svg/RenderSVGForeignObject.cpp:
(WebCore::RenderSVGForeignObject::layout):
* rendering/svg/RenderSVGGradientStop.cpp:
(WebCore::RenderSVGGradientStop::layout):
* rendering/svg/RenderSVGHiddenContainer.cpp:
(WebCore::RenderSVGHiddenContainer::layout):
* rendering/svg/RenderSVGImage.cpp:
(WebCore::RenderSVGImage::layout):
* rendering/svg/RenderSVGResourceContainer.cpp:
(WebCore::RenderSVGResourceContainer::layout):
* rendering/svg/RenderSVGResourceMarker.cpp:
(WebCore::RenderSVGResourceMarker::layout):
* rendering/svg/RenderSVGRoot.cpp:
(WebCore::RenderSVGRoot::layout):
* rendering/svg/RenderSVGShape.cpp:
(WebCore::RenderSVGShape::layout):
* rendering/svg/RenderSVGText.cpp:
(WebCore::RenderSVGText::layout):

Source/WTF:

Disabled by default. Should have no performance and memory cost when
disabled. To enable, #define ENABLE_STACK_STATS 1 in StackStats.h.
The output is currently hardcoded to be dumped in /tmp/stack-stats.log,
and is in the form of stack sample events. By default, it only logs
a sample event when a new high watermark value is encountered.

Also renamed StackBounds::recursiveCheck() to isSafeToRecurse().

* WTF.xcodeproj/project.pbxproj:
* wtf/StackBounds.h:
(StackBounds):
(WTF::StackBounds::size):
(WTF::StackBounds::isSafeToRecurse):
* wtf/StackStats.cpp: Added.
(WTF):
(WTF::StackStats::initialize):
(WTF::StackStats::PerThreadStats::PerThreadStats):
(WTF::StackStats::CheckPoint::CheckPoint):
(WTF::StackStats::CheckPoint::~CheckPoint):
(WTF::StackStats::probe):
(WTF::StackStats::LayoutCheckPoint::LayoutCheckPoint):
(WTF::StackStats::LayoutCheckPoint::~LayoutCheckPoint):
* wtf/StackStats.h: Added.
(WTF):
(StackStats):
(CheckPoint):
(WTF::StackStats::CheckPoint::CheckPoint):
(PerThreadStats):
(WTF::StackStats::PerThreadStats::PerThreadStats):
(LayoutCheckPoint):
(WTF::StackStats::LayoutCheckPoint::LayoutCheckPoint):
(WTF::StackStats::initialize):
(WTF::StackStats::probe):
* wtf/ThreadingPthreads.cpp:
(WTF::initializeThreading):
* wtf/WTFThreadData.cpp:
(WTF::WTFThreadData::WTFThreadData):
* wtf/WTFThreadData.h:
(WTFThreadData):
(WTF::WTFThreadData::stackStats):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@131938 268f45cc-cd09-0410-ab3c-d52691b4dbfc

55 files changed:
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/heap/SlotVisitor.cpp
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/runtime/StringRecursionChecker.h
Source/WTF/ChangeLog
Source/WTF/WTF.xcodeproj/project.pbxproj
Source/WTF/wtf/StackBounds.h
Source/WTF/wtf/StackStats.cpp [new file with mode: 0644]
Source/WTF/wtf/StackStats.h [new file with mode: 0644]
Source/WTF/wtf/ThreadingPthreads.cpp
Source/WTF/wtf/WTFThreadData.cpp
Source/WTF/wtf/WTFThreadData.h
Source/WebCore/ChangeLog
Source/WebCore/dom/Document.cpp
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderBox.cpp
Source/WebCore/rendering/RenderDialog.cpp
Source/WebCore/rendering/RenderEmbeddedObject.cpp
Source/WebCore/rendering/RenderFlowThread.cpp
Source/WebCore/rendering/RenderFrameSet.cpp
Source/WebCore/rendering/RenderIFrame.cpp
Source/WebCore/rendering/RenderImage.cpp
Source/WebCore/rendering/RenderListBox.cpp
Source/WebCore/rendering/RenderListItem.cpp
Source/WebCore/rendering/RenderListMarker.cpp
Source/WebCore/rendering/RenderMedia.cpp
Source/WebCore/rendering/RenderObject.cpp
Source/WebCore/rendering/RenderObject.h
Source/WebCore/rendering/RenderRegion.cpp
Source/WebCore/rendering/RenderReplaced.cpp
Source/WebCore/rendering/RenderReplica.cpp
Source/WebCore/rendering/RenderRubyRun.cpp
Source/WebCore/rendering/RenderScrollbarPart.cpp
Source/WebCore/rendering/RenderSlider.cpp
Source/WebCore/rendering/RenderTable.cpp
Source/WebCore/rendering/RenderTableCell.cpp
Source/WebCore/rendering/RenderTableRow.cpp
Source/WebCore/rendering/RenderTableSection.cpp
Source/WebCore/rendering/RenderTextControlSingleLine.cpp
Source/WebCore/rendering/RenderTextTrackCue.cpp
Source/WebCore/rendering/RenderVideo.cpp
Source/WebCore/rendering/RenderView.cpp
Source/WebCore/rendering/RenderWidget.cpp
Source/WebCore/rendering/svg/RenderSVGContainer.cpp
Source/WebCore/rendering/svg/RenderSVGForeignObject.cpp
Source/WebCore/rendering/svg/RenderSVGGradientStop.cpp
Source/WebCore/rendering/svg/RenderSVGHiddenContainer.cpp
Source/WebCore/rendering/svg/RenderSVGImage.cpp
Source/WebCore/rendering/svg/RenderSVGResourceContainer.cpp
Source/WebCore/rendering/svg/RenderSVGResourceMarker.cpp
Source/WebCore/rendering/svg/RenderSVGRoot.cpp
Source/WebCore/rendering/svg/RenderSVGShape.cpp
Source/WebCore/rendering/svg/RenderSVGText.cpp

index 118a78d..9db5944 100644 (file)
@@ -1,3 +1,35 @@
+2012-10-19  Mark Lam  <mark.lam@apple.com>
+
+        Added WTF::StackStats mechanism.
+        https://bugs.webkit.org/show_bug.cgi?id=99805.
+
+        Reviewed by Geoffrey Garen.
+
+        Added StackStats checkpoints and probes.
+
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::emitNode):
+        (JSC::BytecodeGenerator::emitNodeInConditionContext):
+        * heap/SlotVisitor.cpp:
+        (JSC::SlotVisitor::append):
+        (JSC::visitChildren):
+        (JSC::SlotVisitor::donateKnownParallel):
+        (JSC::SlotVisitor::drain):
+        (JSC::SlotVisitor::drainFromShared):
+        (JSC::SlotVisitor::mergeOpaqueRoots):
+        (JSC::SlotVisitor::internalAppend):
+        (JSC::SlotVisitor::harvestWeakReferences):
+        (JSC::SlotVisitor::finalizeUnconditionalFinalizers):
+        * interpreter/Interpreter.cpp:
+        (JSC::Interpreter::execute):
+        (JSC::Interpreter::executeCall):
+        (JSC::Interpreter::executeConstruct):
+        (JSC::Interpreter::prepareForRepeatCall):
+        * parser/Parser.h:
+        (JSC::Parser::canRecurse):
+        * runtime/StringRecursionChecker.h:
+        (StringRecursionChecker):
+
 2012-10-19  Oliver Hunt  <oliver@apple.com>
 
         REGRESSION(r131822): It made 500+ tests crash on 32 bit platforms
index a08e93a..246530a 100644 (file)
@@ -311,7 +311,7 @@ namespace JSC {
             // Node::emitCode assumes that dst, if provided, is either a local or a referenced temporary.
             ASSERT(!dst || dst == ignoredResult() || !dst->isTemporary() || dst->refCount());
             addLineInfo(n->lineNo());
-            return m_stack.recursionCheck()
+            return m_stack.isSafeToRecurse()
                 ? n->emitBytecode(*this, dst)
                 : emitThrowExpressionTooDeepException();
         }
@@ -324,7 +324,7 @@ namespace JSC {
         void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue)
         {
             addLineInfo(n->lineNo());
-            if (m_stack.recursionCheck())
+            if (m_stack.isSafeToRecurse())
                 n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMeansTrue);
             else
                 emitThrowExpressionTooDeepException();
index 26d056f..7a30deb 100644 (file)
@@ -10,6 +10,7 @@
 #include "JSGlobalData.h"
 #include "JSObject.h"
 #include "JSString.h"
+#include <wtf/StackStats.h>
 
 namespace JSC {
 
@@ -58,6 +59,7 @@ void SlotVisitor::reset()
 
 void SlotVisitor::append(ConservativeRoots& conservativeRoots)
 {
+    StackStats::probe();
     JSCell** roots = conservativeRoots.roots();
     size_t size = conservativeRoots.size();
     for (size_t i = 0; i < size; ++i)
@@ -66,6 +68,7 @@ void SlotVisitor::append(ConservativeRoots& conservativeRoots)
 
 ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell)
 {
+    StackStats::probe();
 #if ENABLE(SIMPLE_HEAP_PROFILING)
     m_visitedTypeCounts.count(cell);
 #endif
@@ -92,6 +95,7 @@ ALWAYS_INLINE static void visitChildren(SlotVisitor& visitor, const JSCell* cell
 
 void SlotVisitor::donateKnownParallel()
 {
+    StackStats::probe();
     // NOTE: Because we re-try often, we can afford to be conservative, and
     // assume that donating is not profitable.
 
@@ -119,6 +123,7 @@ void SlotVisitor::donateKnownParallel()
 
 void SlotVisitor::drain()
 {
+    StackStats::probe();
     ASSERT(m_isInParallelMode);
    
 #if ENABLE(PARALLEL_GC)
@@ -144,6 +149,7 @@ void SlotVisitor::drain()
 
 void SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode)
 {
+    StackStats::probe();
     ASSERT(m_isInParallelMode);
     
     ASSERT(Options::numberOfGCMarkers());
@@ -221,6 +227,7 @@ void SlotVisitor::drainFromShared(SharedDrainMode sharedDrainMode)
 
 void SlotVisitor::mergeOpaqueRoots()
 {
+    StackStats::probe();
     ASSERT(!m_opaqueRoots.isEmpty()); // Should only be called when opaque roots are non-empty.
     {
         MutexLocker locker(m_shared.m_opaqueRootsLock);
@@ -276,6 +283,7 @@ ALWAYS_INLINE void SlotVisitor::internalAppend(JSValue* slot)
     // as it can change the JSValue pointed to be the argument when the original JSValue
     // is a string that contains the same contents as another string.
 
+    StackStats::probe();
     ASSERT(slot);
     JSValue value = *slot;
     ASSERT(value);
@@ -309,12 +317,14 @@ ALWAYS_INLINE void SlotVisitor::internalAppend(JSValue* slot)
 
 void SlotVisitor::harvestWeakReferences()
 {
+    StackStats::probe();
     for (WeakReferenceHarvester* current = m_shared.m_weakReferenceHarvesters.head(); current; current = current->next())
         current->visitWeakReferences(*this);
 }
 
 void SlotVisitor::finalizeUnconditionalFinalizers()
 {
+    StackStats::probe();
     while (m_shared.m_unconditionalFinalizers.hasNext())
         m_shared.m_unconditionalFinalizers.removeNext()->finalizeUnconditionally();
 }
index 27a9617..8c09019 100644 (file)
@@ -65,6 +65,7 @@
 #include "StrongInlines.h"
 #include <limits.h>
 #include <stdio.h>
+#include <wtf/StackStats.h>
 #include <wtf/Threading.h>
 #include <wtf/text/StringBuilder.h>
 
@@ -752,6 +753,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, J
     if (callFrame->globalData().isCollectorBusy())
         CRASH();
 
+    StackStats::CheckPoint stackCheckPoint;
     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
         return checkedReturn(throwStackOverflowError(callFrame));
 
@@ -914,6 +916,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT
     if (callFrame->globalData().isCollectorBusy())
         return jsNull();
 
+    StackStats::CheckPoint stackCheckPoint;
     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
         return checkedReturn(throwStackOverflowError(callFrame));
 
@@ -1009,6 +1012,7 @@ JSObject* Interpreter::executeConstruct(CallFrame* callFrame, JSObject* construc
     if (callFrame->globalData().isCollectorBusy())
         return checkedReturn(throwStackOverflowError(callFrame));
 
+    StackStats::CheckPoint stackCheckPoint;
     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
         return checkedReturn(throwStackOverflowError(callFrame));
 
@@ -1106,6 +1110,7 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* functionE
     if (callFrame->globalData().isCollectorBusy())
         return CallFrameClosure();
 
+    StackStats::CheckPoint stackCheckPoint;
     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth) {
         throwStackOverflowError(callFrame);
         return CallFrameClosure();
@@ -1147,6 +1152,8 @@ JSValue Interpreter::execute(CallFrameClosure& closure)
     ASSERT(!closure.oldCallFrame->globalData().isCollectorBusy());
     if (closure.oldCallFrame->globalData().isCollectorBusy())
         return jsNull();
+
+    StackStats::CheckPoint stackCheckPoint;
     closure.resetCallFrame();
     if (Profiler* profiler = closure.oldCallFrame->globalData().enabledProfiler())
         profiler->willExecute(closure.oldCallFrame, closure.function);
@@ -1189,6 +1196,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue
 
     DynamicGlobalObjectScope globalObjectScope(*scope->globalData(), scope->globalObject());
 
+    StackStats::CheckPoint stackCheckPoint;
     if (m_reentryDepth >= MaxSmallThreadReentryDepth && m_reentryDepth >= callFrame->globalData().maxReentryDepth)
         return checkedReturn(throwStackOverflowError(callFrame));
 
index 4c005fa..dc42d36 100644 (file)
@@ -882,7 +882,7 @@ private:
     
     bool canRecurse()
     {
-        return m_stack.recursionCheck();
+        return m_stack.isSafeToRecurse();
     }
     
     int lastTokenEnd() const
index 127d028..831e25b 100644 (file)
@@ -21,6 +21,7 @@
 #define StringRecursionChecker_h
 
 #include "Interpreter.h"
+#include <wtf/StackStats.h>
 
 namespace JSC {
 
@@ -41,6 +42,8 @@ private:
     ExecState* m_exec;
     JSObject* m_thisObject;
     JSValue m_earlyReturnValue;
+
+    StackStats::CheckPoint stackCheckpoint;
 };
 
 inline JSValue StringRecursionChecker::performCheck()
index 0d12553..e159f99 100644 (file)
@@ -1,3 +1,51 @@
+2012-10-19  Mark Lam  <mark.lam@apple.com>
+
+        Added WTF::StackStats mechanism.
+        https://bugs.webkit.org/show_bug.cgi?id=99805.
+
+        Reviewed by Geoffrey Garen.
+
+        Disabled by default. Should have no performance and memory cost when
+        disabled. To enable, #define ENABLE_STACK_STATS 1 in StackStats.h.
+        The output is currently hardcoded to be dumped in /tmp/stack-stats.log,
+        and is in the form of stack sample events. By default, it only logs
+        a sample event when a new high watermark value is encountered.
+
+        Also renamed StackBounds::recursiveCheck() to isSafeToRecurse().
+
+        * WTF.xcodeproj/project.pbxproj:
+        * wtf/StackBounds.h:
+        (StackBounds):
+        (WTF::StackBounds::size):
+        (WTF::StackBounds::isSafeToRecurse):
+        * wtf/StackStats.cpp: Added.
+        (WTF):
+        (WTF::StackStats::initialize):
+        (WTF::StackStats::PerThreadStats::PerThreadStats):
+        (WTF::StackStats::CheckPoint::CheckPoint):
+        (WTF::StackStats::CheckPoint::~CheckPoint):
+        (WTF::StackStats::probe):
+        (WTF::StackStats::LayoutCheckPoint::LayoutCheckPoint):
+        (WTF::StackStats::LayoutCheckPoint::~LayoutCheckPoint):
+        * wtf/StackStats.h: Added.
+        (WTF):
+        (StackStats):
+        (CheckPoint):
+        (WTF::StackStats::CheckPoint::CheckPoint):
+        (PerThreadStats):
+        (WTF::StackStats::PerThreadStats::PerThreadStats):
+        (LayoutCheckPoint):
+        (WTF::StackStats::LayoutCheckPoint::LayoutCheckPoint):
+        (WTF::StackStats::initialize):
+        (WTF::StackStats::probe):
+        * wtf/ThreadingPthreads.cpp:
+        (WTF::initializeThreading):
+        * wtf/WTFThreadData.cpp:
+        (WTF::WTFThreadData::WTFThreadData):
+        * wtf/WTFThreadData.h:
+        (WTFThreadData):
+        (WTF::WTFThreadData::stackStats):
+
 2012-10-19  Anders Carlsson  <andersca@apple.com>
 
         Deque can use std::reverse_iterator for its reverse iterators
index 39d739b..ab1251e 100644 (file)
                F3525E461619A4EE00278BC1 /* MemoryInstrumentationHashMap.h in Headers */ = {isa = PBXBuildFile; fileRef = F3525E451619A4EE00278BC1 /* MemoryInstrumentationHashMap.h */; };
                F3FBC71E161AF7BF00BB4BD4 /* MemoryInstrumentationHashCountedSet.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FBC71D161AF7BF00BB4BD4 /* MemoryInstrumentationHashCountedSet.h */; };
                F3FBC720161AF7CD00BB4BD4 /* MemoryInstrumentationSequence.h in Headers */ = {isa = PBXBuildFile; fileRef = F3FBC71F161AF7CD00BB4BD4 /* MemoryInstrumentationSequence.h */; };
+               FEDACD3D1630F83F00C69634 /* StackStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEDACD3B1630F83F00C69634 /* StackStats.cpp */; };
+               FEDACD3E1630F83F00C69634 /* StackStats.h in Headers */ = {isa = PBXBuildFile; fileRef = FEDACD3C1630F83F00C69634 /* StackStats.h */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
                F3525E451619A4EE00278BC1 /* MemoryInstrumentationHashMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryInstrumentationHashMap.h; sourceTree = "<group>"; };
                F3FBC71D161AF7BF00BB4BD4 /* MemoryInstrumentationHashCountedSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryInstrumentationHashCountedSet.h; sourceTree = "<group>"; };
                F3FBC71F161AF7CD00BB4BD4 /* MemoryInstrumentationSequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryInstrumentationSequence.h; sourceTree = "<group>"; };
+               FEDACD3B1630F83F00C69634 /* StackStats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StackStats.cpp; sourceTree = "<group>"; };
+               FEDACD3C1630F83F00C69634 /* StackStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackStats.h; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
                                A8A4730D151A825B004123FF /* Spectrum.h */,
                                A8A4730E151A825B004123FF /* StackBounds.cpp */,
                                A8A4730F151A825B004123FF /* StackBounds.h */,
+                               FEDACD3B1630F83F00C69634 /* StackStats.cpp */,
+                               FEDACD3C1630F83F00C69634 /* StackStats.h */,
                                A8A47310151A825B004123FF /* StaticConstructors.h */,
                                A8A47311151A825B004123FF /* StdLibExtras.h */,
                                1A6BB768162F300500DD16DB /* StreamBuffer.h */,
                                A8A47424151A825B004123FF /* SinglyLinkedList.h in Headers */,
                                A8A47426151A825B004123FF /* Spectrum.h in Headers */,
                                A8A47428151A825B004123FF /* StackBounds.h in Headers */,
+                               FEDACD3E1630F83F00C69634 /* StackStats.h in Headers */,
                                A8A47429151A825B004123FF /* StaticConstructors.h in Headers */,
                                A8A4742A151A825B004123FF /* StdLibExtras.h in Headers */,
                                1A6BB769162F300500DD16DB /* StreamBuffer.h in Headers */,
                                A8A47421151A825B004123FF /* SHA1.cpp in Sources */,
                                A8A47425151A825B004123FF /* SizeLimits.cpp in Sources */,
                                A8A47427151A825B004123FF /* StackBounds.cpp in Sources */,
+                               FEDACD3D1630F83F00C69634 /* StackStats.cpp in Sources */,
                                A8A4743C151A825B004123FF /* StringBuilder.cpp in Sources */,
                                A8A4742B151A825B004123FF /* StringExtras.cpp in Sources */,
                                A8A47440151A825B004123FF /* StringImpl.cpp in Sources */,
index afce860..185afec 100644 (file)
 namespace WTF {
 
 class StackBounds {
-    // recursionCheck() / recursionLimit() tests (by default)
+    // isSafeToRecurse() / recursionLimit() tests (by default)
     // that we are at least this far from the end of the stack.
-    const static size_t s_defaultAvailabilityDelta = 4096;
+    //
+    // This 64k number was picked because a sampling of stack usage differences
+    // between consecutive entries into one of the Interpreter::execute...()
+    // functions was seen to be as high as 27k. Hence, 64k is chosen as a
+    // conservative availability value that is not too large but comfortably
+    // exceeds 27k with some buffer for error.
+    const static size_t s_defaultAvailabilityDelta = 64 * 1024;
 
 public:
     StackBounds()
@@ -62,6 +68,13 @@ public:
         return currentPosition;
     }
 
+    size_t size() const
+    {
+        return isGrowingDownward()
+            ? static_cast<char*>(m_origin) - static_cast<char*>(m_bound)
+            : static_cast<char*>(m_bound) - static_cast<char*>(m_origin);
+    }
+
     void* recursionLimit(size_t minAvailableDelta = s_defaultAvailabilityDelta) const
     {
         checkConsistency();
@@ -70,7 +83,7 @@ public:
             : static_cast<char*>(m_bound) - minAvailableDelta;
     }
 
-    bool recursionCheck(size_t minAvailableDelta = s_defaultAvailabilityDelta) const
+    bool isSafeToRecurse(size_t minAvailableDelta = s_defaultAvailabilityDelta) const
     {
         checkConsistency();
         return isGrowingDownward()
@@ -105,6 +118,8 @@ private:
 
     void* m_origin;
     void* m_bound;
+
+    friend class StackStats;
 };
 
 } // namespace WTF
diff --git a/Source/WTF/wtf/StackStats.cpp b/Source/WTF/wtf/StackStats.cpp
new file mode 100644 (file)
index 0000000..0bc11ed
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 2012 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 "StackStats.h"
+
+#if ENABLE(STACK_STATS) 
+
+#include "Assertions.h"
+#include "DataLog.h"
+#include "WTFThreadData.h"
+
+// Define the following flag if you want to collect stats on every single
+// checkpoint. By default, we only log checkpoints that establish new
+// max values.
+
+// #define ENABLE_VERBOSE_STACK_STATS 1
+
+
+namespace WTF {
+
+// CheckPoint management:
+Mutex* StackStats::s_sharedLock = 0;
+StackStats::CheckPoint* StackStats::s_topCheckPoint = 0;
+StackStats::LayoutCheckPoint* StackStats::s_firstLayoutCheckPoint = 0;
+StackStats::LayoutCheckPoint* StackStats::s_topLayoutCheckPoint = 0;
+
+// High watermark stats:
+int StackStats::s_maxCheckPointDiff = 0;
+int StackStats::s_maxStackHeight = 0;
+int StackStats::s_maxReentryDepth = 0;
+
+int StackStats::s_maxLayoutCheckPointDiff = 0;
+int StackStats::s_maxTotalLayoutCheckPointDiff = 0;
+int StackStats::s_maxLayoutReentryDepth = 0;
+
+
+// Initializes locks and the log. Should only be called once.
+void StackStats::initialize()
+{
+    s_sharedLock = new Mutex();
+    dataLog(" === LOG new stack stats ========\n");
+}
+
+StackStats::PerThreadStats::PerThreadStats()
+{
+    const StackBounds& stack = wtfThreadData().stack();
+    m_reentryDepth = 0;
+    m_stackStart = (char*)stack.origin();
+    m_currentCheckPoint = 0;
+
+    dataLog(" === THREAD new stackStart %p ========\n", m_stackStart);
+}
+
+StackStats::CheckPoint::CheckPoint()
+{
+    MutexLocker locker(*StackStats::s_sharedLock);
+    WTFThreadData* threadData = const_cast<WTFThreadData*>(&wtfThreadData());
+    StackStats::PerThreadStats& t = threadData->stackStats();
+    const StackBounds& stack = threadData->stack();
+
+    bool isGrowingDownward = stack.isGrowingDownward();
+    bool needToLog = false;
+    char* current = reinterpret_cast<char*>(this);
+    char* last = reinterpret_cast<char*>(t.m_currentCheckPoint);
+
+    // If there was no previous checkpoint, measure from the start of the stack:
+    if (!last)
+        last = t.m_stackStart;
+
+    // Update the reentry depth stats:
+    t.m_reentryDepth++;
+    if (t.m_reentryDepth > StackStats::s_maxReentryDepth) {
+        StackStats::s_maxReentryDepth = t.m_reentryDepth;
+        needToLog = true;
+    }
+
+    // Update the stack height stats:
+    int height = t.m_stackStart - current;
+    if (!isGrowingDownward)
+        height = -height;
+    if (height > StackStats::s_maxStackHeight) {
+        StackStats::s_maxStackHeight = height;
+        needToLog = true;
+    }
+
+    // Update the checkpoint diff stats:
+    int diff = last - current;
+    if (!isGrowingDownward)
+        diff = -diff;
+    if (diff > StackStats::s_maxCheckPointDiff) {
+        StackStats::s_maxCheckPointDiff = diff;
+        needToLog = true;
+    }
+
+    // Push this checkpoint:
+    m_prev = t.m_currentCheckPoint;
+    t.m_currentCheckPoint = this;
+
+#if ENABLE(VERBOSE_STACK_STATS)
+    needToLog = true; // always log.
+#endif
+
+    // Log this checkpoint if needed:
+    if (needToLog)
+        dataLog(" CHECKPOINT %p diff %d/%.1fk/max %.1fk | reentry %d/max %d | height %.1fk/max %.1fk | stack %p size %.1fk\n",
+            this, diff, diff / 1024.0, StackStats::s_maxCheckPointDiff / 1024.0,
+            t.m_reentryDepth, StackStats::s_maxReentryDepth,
+            height / 1024.0, StackStats::s_maxStackHeight / 1024.0,
+            stack.origin(), stack.size() / 1024.0);
+}
+
+StackStats::CheckPoint::~CheckPoint()
+{
+    MutexLocker locker(*StackStats::s_sharedLock);
+    WTFThreadData* threadData = const_cast<WTFThreadData*>(&wtfThreadData());
+    StackStats::PerThreadStats& t = threadData->stackStats();
+
+    // Pop to previous checkpoint:
+    t.m_currentCheckPoint = m_prev;
+    --t.m_reentryDepth;
+
+    // Log this checkpoint if needed:
+#if ENABLE(VERBOSE_STACK_STATS)
+    if (!m_prev) {
+        const StackBounds& stack = threadData->stack();
+        bool isGrowingDownward = stack.isGrowingDownward();
+
+        char* current = reinterpret_cast<char*>(this);
+        int height = t.m_stackStart - current;
+
+        if (!isGrowingDownward)
+            height = -height;
+
+        dataLog(" POP to %p diff max %.1fk | reentry %d/%d max | height %.1fk/max %.1fk | stack %p size %.1fk)\n",
+            this, StackStats::s_maxCheckPointDiff / 1024.0,
+            t.m_reentryDepth, StackStats::s_maxReentryDepth,
+            height / 1024.0, StackStats::s_maxStackHeight / 1024.0,
+            stack.origin(), stack.size() / 1024.0);
+    }
+#endif
+}
+
+void StackStats::probe()
+{
+    MutexLocker locker(*StackStats::s_sharedLock);
+    WTFThreadData* threadData = const_cast<WTFThreadData*>(&wtfThreadData());
+    StackStats::PerThreadStats& t = threadData->stackStats();
+    const StackBounds& stack = threadData->stack();
+
+    bool isGrowingDownward = stack.isGrowingDownward();
+
+    bool needToLog = false;
+
+    int dummy;
+    char* current = reinterpret_cast<char*>(&dummy);
+    char* last = reinterpret_cast<char*>(t.m_currentCheckPoint);
+
+    // If there was no previous checkpoint, measure from the start of the stack:
+    if (!last)
+        last = t.m_stackStart;
+
+    // We did not reach another checkpoint yet. Hence, we do not touch the
+    // reentry stats.
+
+    // Update the stack height stats:
+    int height = t.m_stackStart - current;
+    if (!isGrowingDownward)
+        height = -height;
+    if (height > StackStats::s_maxStackHeight) {
+        StackStats::s_maxStackHeight = height;
+        needToLog = true;
+    }
+
+    // Update the checkpoint diff stats:
+    int diff = last - current;
+    if (!isGrowingDownward)
+        diff = -diff;
+    if (diff > StackStats::s_maxCheckPointDiff) {
+        StackStats::s_maxCheckPointDiff = diff;
+        needToLog = true;
+    }
+
+#if ENABLE(VERBOSE_STACK_STATS)
+    needToLog = true; // always log.
+#endif
+
+    if (needToLog)
+        dataLog(" PROBE %p diff %d/%.1fk/max %.1fk | reentry %d/max %d | height %.1fk/max %.1fk | stack %p size %.1fk\n",
+            current, diff, diff / 1024.0, StackStats::s_maxCheckPointDiff / 1024.0,
+            t.m_reentryDepth, StackStats::s_maxReentryDepth,
+            height / 1024.0, StackStats::s_maxStackHeight / 1024.0,
+            stack.origin(), stack.size() / 1024.0);
+}
+
+StackStats::LayoutCheckPoint::LayoutCheckPoint()
+{
+    // While a layout checkpoint is not necessarily a checkpoint where we
+    // we will do a recursion check, it is a convenient spot for doing a
+    // probe to measure the height of stack usage.
+    //
+    // We'll do this probe before we commence with the layout checkpoint.
+    // This is because the probe also locks the sharedLock. By calling the
+    // probe first, we can avoid re-entering the lock.
+    StackStats::probe();
+
+    MutexLocker locker(*StackStats::s_sharedLock);
+    WTFThreadData* threadData = const_cast<WTFThreadData*>(&wtfThreadData());
+    StackStats::PerThreadStats& t = threadData->stackStats();
+    const StackBounds& stack = threadData->stack();
+
+    bool isGrowingDownward = stack.isGrowingDownward();
+
+    // Push this checkpoint:
+    m_prev = StackStats::s_topLayoutCheckPoint;
+    if (m_prev)
+        m_depth = m_prev->m_depth + 1;
+    else {
+        StackStats::s_firstLayoutCheckPoint = this;
+        m_depth = 0;
+    }
+    StackStats::s_topLayoutCheckPoint = this;
+
+    // 
+    char* current = reinterpret_cast<char*>(this);
+    char* last = reinterpret_cast<char*>(m_prev);
+    char* root = reinterpret_cast<char*>(StackStats::s_firstLayoutCheckPoint);
+    bool needToLog = false;
+
+    int diff = last - current;
+    if (!last)
+        diff = 0;
+    int totalDiff = root - current;
+    if (!root)
+        totalDiff = 0;
+
+    // Update the stack height stats:
+    int height = t.m_stackStart - current;
+    if (!isGrowingDownward)
+        height = -height;
+    if (height > StackStats::s_maxStackHeight) {
+        StackStats::s_maxStackHeight = height;
+        needToLog = true;
+    }
+
+    // Update the layout checkpoint diff stats:
+    if (!isGrowingDownward)
+        diff = -diff;
+    if (diff > StackStats::s_maxLayoutCheckPointDiff) {
+        StackStats::s_maxLayoutCheckPointDiff = diff;
+        needToLog = true;
+    }
+
+    // Update the total layout checkpoint diff stats:
+    if (!isGrowingDownward)
+        totalDiff = -totalDiff;
+    if (totalDiff > StackStats::s_maxTotalLayoutCheckPointDiff) {
+        StackStats::s_maxTotalLayoutCheckPointDiff = totalDiff;
+        needToLog = true;
+    }
+
+#if ENABLE(VERBOSE_STACK_STATS)
+    needToLog = true; // always log.
+#endif
+
+    if (needToLog)
+        dataLog(" LAYOUT %p diff %d/%.1fk/max %.1fk | reentry %d/max %d | height %.1fk/max %.1fk | stack %p size %.1fk\n",
+            current, diff, diff / 1024.0, StackStats::s_maxLayoutCheckPointDiff / 1024.0,
+            m_depth, StackStats::s_maxLayoutReentryDepth,
+            totalDiff / 1024.0, StackStats::s_maxTotalLayoutCheckPointDiff / 1024.0,
+            stack.origin(), stack.size() / 1024.0);
+}
+
+StackStats::LayoutCheckPoint::~LayoutCheckPoint()
+{
+    MutexLocker locker(*StackStats::s_sharedLock);
+
+    // Pop to the previous layout checkpoint:
+    StackStats::s_topLayoutCheckPoint = m_prev;
+    if (!m_depth)
+        StackStats::s_firstLayoutCheckPoint = 0;
+}
+
+} // namespace WTF
+
+#endif // ENABLE(STACK_STATS)
+
diff --git a/Source/WTF/wtf/StackStats.h b/Source/WTF/wtf/StackStats.h
new file mode 100644 (file)
index 0000000..2635679
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2012 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 StackStats_h
+#define StackStats_h
+
+#include "ExportMacros.h"
+#include "ThreadingPrimitives.h"
+
+
+// Define this flag to enable Stack stats collection. This feature is useful
+// for getting a sample of native stack usage sizes.
+//
+// Enabling this will cause stats to be collected and written to a log file at
+// various  instrumented points in the code. It will result in noticeable
+// performance loss. Hence, this should only be enable when you want to do
+// some stats location in your local build. This code is provided here as a
+// convenience for collecting that data. It is not meant to be enabled by
+// default on release or debug builds.
+
+// #define ENABLE_STACK_STATS 1
+
+
+namespace WTF {
+
+#if !ENABLE(STACK_STATS) 
+
+class StackStats {
+public:
+    // The CheckPoint class is for marking check points corresponding
+    // each location in code where a stack recursion check is being done.
+
+    class CheckPoint {
+    public:
+        CheckPoint() { }
+    };
+
+    class PerThreadStats {
+    public:
+        PerThreadStats() { }
+    };
+
+    class LayoutCheckPoint {
+    public:
+        LayoutCheckPoint() { }
+    };
+
+    static void initialize() { }
+    static void probe() { }
+};
+
+#else // ENABLE(STACK_STATS)
+
+class StackStats {
+public:
+    // The CheckPoint class is for marking check points corresponding
+    // each location in code where a stack recursion check is being done.
+
+    class CheckPoint {
+    public:
+        CheckPoint();
+        ~CheckPoint();
+    private:
+        CheckPoint* m_prev;
+    };
+
+    class PerThreadStats {
+    public:
+        PerThreadStats();
+
+    private:
+        int m_reentryDepth;
+        char* m_stackStart;
+        CheckPoint* m_currentCheckPoint;
+
+        friend class CheckPoint;
+        friend class StackStats;
+    };
+
+    class LayoutCheckPoint {
+    public:
+        WTF_EXPORT_PRIVATE LayoutCheckPoint();
+        WTF_EXPORT_PRIVATE ~LayoutCheckPoint();
+
+    private:
+        LayoutCheckPoint* m_prev;
+        int m_depth;
+    };
+
+    // Initializes locks and the log file. Should only be called once.
+    static void initialize();
+
+    // Used for probing the stack at places where we suspect to be high
+    // points of stack usage but are NOT check points where stack recursion
+    // is checked.
+    //
+    // The more places where we add this probe, the more accurate our
+    // stats data will be. However, adding too many probes will also
+    // result in unnecessary performance loss. So, only add these probes
+    // judiciously where appropriate.
+    static void probe();
+
+private:
+    // CheckPoint management:
+    static Mutex* s_sharedLock;
+    static CheckPoint* s_topCheckPoint;
+    static LayoutCheckPoint* s_firstLayoutCheckPoint;
+    static LayoutCheckPoint* s_topLayoutCheckPoint;
+
+    // High watermark stats:
+    static int s_maxCheckPointDiff;
+    static int s_maxStackHeight;
+    static int s_maxReentryDepth;
+
+    static int s_maxLayoutCheckPointDiff;
+    static int s_maxTotalLayoutCheckPointDiff;
+    static int s_maxLayoutReentryDepth;
+
+    friend class CheckPoint;
+    friend class LayoutCheckPoint;
+};
+
+#endif // ENABLE(STACK_STATS) 
+
+} // namespace WTF
+
+using WTF::StackStats;
+
+#endif // StackStats_h
index b70ccdd..1dd84f0 100644 (file)
@@ -39,6 +39,7 @@
 #include "dtoa/cached-powers.h"
 #include "HashMap.h"
 #include "RandomNumberSeed.h"
+#include "StackStats.h"
 #include "StdLibExtras.h"
 #include "ThreadFunctionInvocation.h"
 #include "ThreadIdentifierDataPthreads.h"
@@ -138,6 +139,7 @@ void initializeThreading()
     threadMapMutex();
     initializeRandomNumberGenerator();
     ThreadIdentifierData::initializeOnce();
+    StackStats::initialize();
     wtfThreadData();
     s_dtoaP5Mutex = new Mutex;
     initializeDates();
index 3a903f8..7d90748 100644 (file)
@@ -38,7 +38,10 @@ WTFThreadData::WTFThreadData()
     , m_defaultIdentifierTable(new JSC::IdentifierTable())
     , m_currentIdentifierTable(m_defaultIdentifierTable)
     , m_stackBounds(StackBounds::currentThreadStackBounds())
+#if ENABLE(STACK_STATS)
+    , m_stackStats()
 #endif
+#endif // USE(JSC)
 {
 }
 
index dbc5ba6..9c2a5db 100644 (file)
@@ -31,6 +31,7 @@
 #include <wtf/HashSet.h>
 #include <wtf/Noncopyable.h>
 #include <wtf/StackBounds.h>
+#include <wtf/StackStats.h>
 #include <wtf/text/StringHash.h>
 #include <wtf/ThreadSpecific.h>
 #include <wtf/Threading.h>
@@ -108,7 +109,14 @@ public:
     {
         return m_stackBounds;
     }
+
+#if ENABLE(STACK_STATS)
+    StackStats::PerThreadStats& stackStats()
+    {
+        return m_stackStats;
+    }
 #endif
+#endif // USE(JSC)
 
 private:
     AtomicStringTable* m_atomicStringTable;
@@ -118,7 +126,10 @@ private:
     JSC::IdentifierTable* m_defaultIdentifierTable;
     JSC::IdentifierTable* m_currentIdentifierTable;
     StackBounds m_stackBounds;
+#if ENABLE(STACK_STATS)
+    StackStats::PerThreadStats m_stackStats;
 #endif
+#endif // USE(JSC)
 
     static WTF_EXPORTDATA ThreadSpecific<WTFThreadData>* staticData;
     friend WTFThreadData& wtfThreadData();
index e36045d..fc9a6ca 100644 (file)
@@ -1,3 +1,92 @@
+2012-10-19  Mark Lam  <mark.lam@apple.com>
+
+        Added WTF::StackStats mechanism.
+        https://bugs.webkit.org/show_bug.cgi?id=99805.
+
+        Reviewed by Geoffrey Garen.
+
+        Added StackStats probes in layout methods.
+
+        * dom/Document.cpp:
+        (WebCore::Document::updateLayout):
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::layout):
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::layout):
+        * rendering/RenderDialog.cpp:
+        (WebCore::RenderDialog::layout):
+        * rendering/RenderEmbeddedObject.cpp:
+        (WebCore::RenderEmbeddedObject::layout):
+        * rendering/RenderFlowThread.cpp:
+        (WebCore::RenderFlowThread::layout):
+        * rendering/RenderFrameSet.cpp:
+        (WebCore::RenderFrameSet::layout):
+        * rendering/RenderIFrame.cpp:
+        (WebCore::RenderIFrame::layout):
+        * rendering/RenderImage.cpp:
+        (WebCore::RenderImage::layout):
+        * rendering/RenderListBox.cpp:
+        (WebCore::RenderListBox::layout):
+        * rendering/RenderListItem.cpp:
+        (WebCore::RenderListItem::layout):
+        * rendering/RenderListMarker.cpp:
+        (WebCore::RenderListMarker::layout):
+        * rendering/RenderMedia.cpp:
+        (WebCore::RenderMedia::layout):
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::layout):
+        * rendering/RenderObject.h:
+        * rendering/RenderRegion.cpp:
+        (WebCore::RenderRegion::layout):
+        * rendering/RenderReplaced.cpp:
+        (WebCore::RenderReplaced::layout):
+        * rendering/RenderReplica.cpp:
+        (WebCore::RenderReplica::layout):
+        * rendering/RenderRubyRun.cpp:
+        (WebCore::RenderRubyRun::layoutSpecialExcludedChild):
+        * rendering/RenderScrollbarPart.cpp:
+        (WebCore::RenderScrollbarPart::layout):
+        * rendering/RenderSlider.cpp:
+        (WebCore::RenderSlider::layout):
+        * rendering/RenderTable.cpp:
+        (WebCore::RenderTable::layout):
+        * rendering/RenderTableCell.cpp:
+        (WebCore::RenderTableCell::layout):
+        * rendering/RenderTableRow.cpp:
+        (WebCore::RenderTableRow::layout):
+        * rendering/RenderTableSection.cpp:
+        (WebCore::RenderTableSection::layout):
+        * rendering/RenderTextControlSingleLine.cpp:
+        (WebCore::RenderTextControlSingleLine::layout):
+        * rendering/RenderTextTrackCue.cpp:
+        (WebCore::RenderTextTrackCue::layout):
+        * rendering/RenderVideo.cpp:
+        (WebCore::RenderVideo::layout):
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::layout):
+        * rendering/RenderWidget.cpp:
+        (WebCore::RenderWidget::layout):
+        * rendering/svg/RenderSVGContainer.cpp:
+        (WebCore::RenderSVGContainer::layout):
+        * rendering/svg/RenderSVGForeignObject.cpp:
+        (WebCore::RenderSVGForeignObject::layout):
+        * rendering/svg/RenderSVGGradientStop.cpp:
+        (WebCore::RenderSVGGradientStop::layout):
+        * rendering/svg/RenderSVGHiddenContainer.cpp:
+        (WebCore::RenderSVGHiddenContainer::layout):
+        * rendering/svg/RenderSVGImage.cpp:
+        (WebCore::RenderSVGImage::layout):
+        * rendering/svg/RenderSVGResourceContainer.cpp:
+        (WebCore::RenderSVGResourceContainer::layout):
+        * rendering/svg/RenderSVGResourceMarker.cpp:
+        (WebCore::RenderSVGResourceMarker::layout):
+        * rendering/svg/RenderSVGRoot.cpp:
+        (WebCore::RenderSVGRoot::layout):
+        * rendering/svg/RenderSVGShape.cpp:
+        (WebCore::RenderSVGShape::layout):
+        * rendering/svg/RenderSVGText.cpp:
+        (WebCore::RenderSVGText::layout):
+
 2012-10-19  Pavel Feldman  <pfeldman@chromium.org>
 
         Web Inspector: merge "docked" state into the "dock side" enum.
index 42dd041..e85c8f1 100644 (file)
@@ -1926,6 +1926,7 @@ void Document::updateLayout()
 
     updateStyleIfNeeded();
 
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     // Only do a layout if changes have occurred that make it necessary.      
     FrameView* v = view();
     if (v && renderer() && (v->layoutPending() || renderer()->needsLayout()))
index 796156a..f5ec449 100644 (file)
@@ -1373,6 +1373,7 @@ void RenderBlock::updateScrollInfoAfterLayout()
 
 void RenderBlock::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     OverflowEventDispatcher dispatcher(this);
 
     // Update our first letter info now.
index c56d7a9..78960dc 100644 (file)
@@ -314,6 +314,7 @@ void RenderBox::updateFromStyle()
 
 void RenderBox::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
 
     RenderObject* child = firstChild();
index 4fb9409..b2498ae 100644 (file)
@@ -36,6 +36,7 @@ namespace WebCore {
 
 void RenderDialog::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     LayoutRepainter repainter(*this, true);
     LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
 
index 1007dfb..1e12c7c 100644 (file)
@@ -228,6 +228,7 @@ bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumul
 
 void RenderEmbeddedObject::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
 
     updateLogicalWidth();
index 94f8ba6..d054d24 100644 (file)
@@ -132,6 +132,7 @@ private:
 
 void RenderFlowThread::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     m_pageLogicalHeightChanged = m_regionsInvalidated && everHadLayout();
     if (m_regionsInvalidated) {
         m_regionsInvalidated = false;
index 4086cdc..543c2d3 100644 (file)
@@ -459,6 +459,7 @@ FrameEdgeInfo RenderFrameSet::edgeInfo() const
 
 void RenderFrameSet::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
 
     bool doFullRepaint = selfNeedsLayout() && checkForRepaintDuringLayout();
index 6649d56..2fcd58a 100644 (file)
@@ -147,6 +147,7 @@ void RenderIFrame::layoutSeamlessly()
 
 void RenderIFrame::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
 
     if (isSeamless()) {
index e94fa3e..25a62f5 100644 (file)
@@ -533,6 +533,7 @@ void RenderImage::updateAltText()
 
 void RenderImage::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     RenderReplaced::layout();
 
     // Propagate container size to image resource.
index f67ae82..2af9635 100644 (file)
@@ -172,6 +172,7 @@ void RenderListBox::selectionChanged()
 
 void RenderListBox::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     RenderBlock::layout();
 
     if (m_vBar) {
index 89d99b3..84a5794 100644 (file)
@@ -286,6 +286,7 @@ void RenderListItem::computePreferredLogicalWidths()
 
 void RenderListItem::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout()); 
 
     updateMarkerLocation();    
index a5b0e4c..b7cbaa0 100644 (file)
@@ -1302,6 +1302,7 @@ void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffse
 
 void RenderListMarker::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
  
     if (isImage()) {
index 9af648b..385fb50 100644 (file)
@@ -57,6 +57,7 @@ HTMLMediaElement* RenderMedia::mediaElement() const
 
 void RenderMedia::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     LayoutSize oldSize = contentBoxRect().size();
 
     RenderImage::layout();
index e3aa404..318a149 100644 (file)
@@ -2582,6 +2582,7 @@ void RenderObject::scheduleRelayout()
 
 void RenderObject::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
     RenderObject* child = firstChild();
     while (child) {
index d1994fc..1d5e767 100644 (file)
@@ -39,6 +39,7 @@
 #include "TextAffinity.h"
 #include "TransformationMatrix.h"
 #include <wtf/HashSet.h>
+#include <wtf/StackStats.h>
 #include <wtf/UnusedParam.h>
 
 namespace WebCore {
index 11d5aff..6f3f2e9 100644 (file)
@@ -208,6 +208,7 @@ void RenderRegion::styleDidChange(StyleDifference diff, const RenderStyle* oldSt
 
 void RenderRegion::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     RenderReplaced::layout();
     if (m_flowThread && isValid()) {
         LayoutRect oldRegionRect(flowThreadPortionRect());
index de87251..2cc5493 100644 (file)
@@ -79,6 +79,7 @@ void RenderReplaced::styleDidChange(StyleDifference diff, const RenderStyle* old
 
 void RenderReplaced::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
     
     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
index 0879282..ad3acf0 100644 (file)
@@ -48,6 +48,7 @@ RenderReplica::~RenderReplica()
     
 void RenderReplica::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     setFrameRect(parentBox()->borderBoxRect());
     updateLayerTransform();
     setNeedsLayout(false);
index 65d764a..8481546 100644 (file)
@@ -217,6 +217,7 @@ RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby
 
 RenderObject* RenderRubyRun::layoutSpecialExcludedChild(bool relayoutChildren)
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     // Don't bother positioning the RenderRubyRun yet.
     RenderRubyText* rt = rubyText();
     if (!rt)
index f2ca8c6..3eeb1d8 100644 (file)
@@ -48,6 +48,7 @@ RenderScrollbarPart::~RenderScrollbarPart()
 
 void RenderScrollbarPart::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     setLocation(LayoutPoint()); // We don't worry about positioning ourselves. We're just determining our minimum width/height.
     if (m_scrollbar->orientation() == HorizontalScrollbar)
         layoutHorizontalPart();
index 2691106..87c4b74 100644 (file)
@@ -102,6 +102,7 @@ void RenderSlider::computePreferredLogicalWidths()
 
 void RenderSlider::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     // FIXME: Find a way to cascade appearance.
     // http://webkit.org/b/62535
     RenderBox* thumbBox = sliderThumbElementOf(node())->renderBox();
index ee7c8b8..f9bf446 100644 (file)
@@ -341,6 +341,7 @@ void RenderTable::distributeExtraLogicalHeight(int extraLogicalHeight)
 
 void RenderTable::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
 
     if (simplifiedLayout())
index b3a0457..683321a 100644 (file)
@@ -241,6 +241,7 @@ void RenderTableCell::setCellLogicalWidth(int tableLayoutLogicalWidth)
 
 void RenderTableCell::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     updateFirstLetter();
     layoutBlock(cellWidthChanged());
     setCellWidthChanged(false);
index c86f14c..c3aaf85 100644 (file)
@@ -151,6 +151,7 @@ void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
 
 void RenderTableRow::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
 
     // Table rows do not add translation.
index 7dce602..341c905 100644 (file)
@@ -354,6 +354,7 @@ int RenderTableSection::calcRowLogicalHeight()
 
 void RenderTableSection::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
     ASSERT(!needsCellRecalc());
     ASSERT(!table()->needsSectionRecalc());
index 1484a27..967fb2a 100644 (file)
@@ -96,6 +96,8 @@ LayoutUnit RenderTextControlSingleLine::computeHeightLimit() const
 
 void RenderTextControlSingleLine::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+
     // FIXME: We should remove the height-related hacks in layout() and
     // styleDidChange(). We need them because
     // - Center the inner elements vertically if the input height is taller than
index ef8edda..4e9dc15 100644 (file)
@@ -41,6 +41,7 @@ RenderTextTrackCue::RenderTextTrackCue(TextTrackCueBox* node)
 
 void RenderTextTrackCue::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     RenderBlock::layout();
 
     LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
index 37f2f08..02c313b 100644 (file)
@@ -225,6 +225,7 @@ void RenderVideo::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOf
 
 void RenderVideo::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     RenderMedia::layout();
     updatePlayer();
 }
index ef27b37..d40e53d 100644 (file)
@@ -156,6 +156,7 @@ void RenderView::checkLayoutState(const LayoutState& state)
 
 void RenderView::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     if (!document()->paginated())
         setPageLogicalHeight(0);
 
index 402bac4..977751a 100644 (file)
@@ -211,6 +211,7 @@ void RenderWidget::setWidget(PassRefPtr<Widget> widget)
 
 void RenderWidget::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
 
     setNeedsLayout(false);
index 3802753..d5e5d0c 100644 (file)
@@ -51,6 +51,7 @@ RenderSVGContainer::~RenderSVGContainer()
 
 void RenderSVGContainer::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
 
     // RenderSVGRoot disables layoutState for the SVG rendering tree.
index 3b39a83..2915ede 100644 (file)
@@ -123,6 +123,7 @@ void RenderSVGForeignObject::computeLogicalHeight(LayoutUnit, LayoutUnit logical
 
 void RenderSVGForeignObject::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
     ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
 
index 46c3e2b..31d5da5 100644 (file)
@@ -64,6 +64,7 @@ void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderSty
 
 void RenderSVGGradientStop::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     setNeedsLayout(false);
 }
 
index 895b254..4d37e13 100644 (file)
@@ -34,6 +34,7 @@ RenderSVGHiddenContainer::RenderSVGHiddenContainer(SVGStyledElement* element)
 
 void RenderSVGHiddenContainer::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
     SVGRenderSupport::layoutChildren(this, selfNeedsLayout()); 
     setNeedsLayout(false);    
index 56be5cd..5487b5e 100644 (file)
@@ -79,6 +79,7 @@ bool RenderSVGImage::updateImageViewport()
 
 void RenderSVGImage::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
 
     LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout());
index 51858e5..310e586 100644 (file)
@@ -54,6 +54,7 @@ RenderSVGResourceContainer::~RenderSVGResourceContainer()
 
 void RenderSVGResourceContainer::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     // Invalidate all resources if our layout changed.
     if (everHadLayout() && selfNeedsLayout())
         RenderSVGRoot::addResourceForClientInvalidation(this);
index 784559e..7aaef0e 100644 (file)
@@ -48,6 +48,7 @@ RenderSVGResourceMarker::~RenderSVGResourceMarker()
 
 void RenderSVGResourceMarker::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     // Invalidate all resources if our layout changed.
     if (everHadLayout() && selfNeedsLayout())
         RenderSVGRoot::addResourceForClientInvalidation(this);
index c47a7bb..797b70e 100644 (file)
@@ -218,6 +218,7 @@ LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const
 
 void RenderSVGRoot::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
 
     m_resourcesNeedingToInvalidateClients.clear();
index 62a8c99..5dceac3 100644 (file)
@@ -144,6 +144,7 @@ bool RenderSVGShape::strokeContains(const FloatPoint& point, bool requiresStroke
 
 void RenderSVGShape::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && selfNeedsLayout());
     SVGStyledTransformableElement* element = static_cast<SVGStyledTransformableElement*>(node());
 
index fd8bea0..200cd49 100644 (file)
@@ -347,6 +347,7 @@ static inline void updateFontInAllDescendants(RenderObject* start, SVGTextLayout
 
 void RenderSVGText::layout()
 {
+    StackStats::LayoutCheckPoint layoutCheckPoint;
     ASSERT(needsLayout());
     LayoutRepainter repainter(*this, checkForRepaintDuringLayout());