Title: [127829] trunk/Source/_javascript_Core
Revision
127829
Author
[email protected]
Date
2012-09-06 22:53:25 -0700 (Thu, 06 Sep 2012)

Log Message

JSC should have a zombie mode
https://bugs.webkit.org/show_bug.cgi?id=96047

Reviewed by Geoffrey Garen.

To aid clients of JSC while they are debugging memory issues, we should add a zombie
mode that scribbles into objects in the MarkedSpace after they are found to be dead
to prevent a sort of "use after free" situation. As a first cut we should support a
mode that just scribbles on objects prior to their being reused (i.e. while they are
"zombies") and a mode in which, in addition to scribbling on zombies, once an object
has been marked its mark bit will never be cleared, thus giving us "immortal" zombies.

These two modes will be enabled through the use of environment variables. For now these
will be "JSZombieEnabled" and "JSImmortalZombieEnabled". Setting them to any value will
result in the use of the appropriate mode.

* heap/Heap.cpp:
(JSC::Heap::collect): Zombifies dead objects at the end of collection if zombie mode is enabled.
(ZombifyCellFunctor):
(JSC::ZombifyCellFunctor::ZombifyCellFunctor): Sets marked bits for dead objects if in immortal mode and writes 0xbbadbeef into them.
(JSC::ZombifyCellFunctor::operator()):
(JSC):
(ZombifyBlockFunctor):
(JSC::ZombifyBlockFunctor::operator()):
(JSC::Heap::zombifyDeadObjects): Eagerly sweeps so that we don't write garbage into an object before it
is finalized/destroyed.
* heap/Heap.h:
(Heap):
* heap/MarkedBlock.h:
(MarkedBlock):
(JSC::MarkedBlock::forEachDeadCell): Used to iterate over dead cells at the end of collection if zombie mode is enabled.
(JSC):
* runtime/Options.cpp:
(JSC::Options::initialize):
* runtime/Options.h:
(JSC):

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (127828 => 127829)


--- trunk/Source/_javascript_Core/ChangeLog	2012-09-07 05:34:33 UTC (rev 127828)
+++ trunk/Source/_javascript_Core/ChangeLog	2012-09-07 05:53:25 UTC (rev 127829)
@@ -1,3 +1,42 @@
+2012-09-06  Mark Hahnenberg  <[email protected]>
+
+        JSC should have a zombie mode
+        https://bugs.webkit.org/show_bug.cgi?id=96047
+
+        Reviewed by Geoffrey Garen.
+
+        To aid clients of JSC while they are debugging memory issues, we should add a zombie 
+        mode that scribbles into objects in the MarkedSpace after they are found to be dead 
+        to prevent a sort of "use after free" situation. As a first cut we should support a 
+        mode that just scribbles on objects prior to their being reused (i.e. while they are 
+        "zombies") and a mode in which, in addition to scribbling on zombies, once an object 
+        has been marked its mark bit will never be cleared, thus giving us "immortal" zombies.
+
+        These two modes will be enabled through the use of environment variables. For now these 
+        will be "JSZombieEnabled" and "JSImmortalZombieEnabled". Setting them to any value will 
+        result in the use of the appropriate mode.
+
+        * heap/Heap.cpp:
+        (JSC::Heap::collect): Zombifies dead objects at the end of collection if zombie mode is enabled.
+        (ZombifyCellFunctor):
+        (JSC::ZombifyCellFunctor::ZombifyCellFunctor): Sets marked bits for dead objects if in immortal mode and writes 0xbbadbeef into them.
+        (JSC::ZombifyCellFunctor::operator()):
+        (JSC):
+        (ZombifyBlockFunctor):
+        (JSC::ZombifyBlockFunctor::operator()):
+        (JSC::Heap::zombifyDeadObjects): Eagerly sweeps so that we don't write garbage into an object before it 
+        is finalized/destroyed.
+        * heap/Heap.h:
+        (Heap):
+        * heap/MarkedBlock.h:
+        (MarkedBlock):
+        (JSC::MarkedBlock::forEachDeadCell): Used to iterate over dead cells at the end of collection if zombie mode is enabled.
+        (JSC):
+        * runtime/Options.cpp:
+        (JSC::Options::initialize):
+        * runtime/Options.h:
+        (JSC):
+
 2012-09-05  Geoffrey Garen  <[email protected]>
 
         Rolled back in <http://trac.webkit.org/changeset/127698> with a fix for

Modified: trunk/Source/_javascript_Core/heap/Heap.cpp (127828 => 127829)


--- trunk/Source/_javascript_Core/heap/Heap.cpp	2012-09-07 05:34:33 UTC (rev 127828)
+++ trunk/Source/_javascript_Core/heap/Heap.cpp	2012-09-07 05:53:25 UTC (rev 127829)
@@ -753,6 +753,9 @@
         m_objectSpace.resetAllocators();
     }
     
+    if (Options::useZombieMode())
+        zombifyDeadObjects();
+
     size_t currentHeapSize = size();
     if (fullGC) {
         m_sizeAfterLastCollect = currentHeapSize;
@@ -844,4 +847,49 @@
     lastChanceToFinalize();
 }
 
+class ZombifyCellFunctor : public MarkedBlock::VoidFunctor {
+public:
+    ZombifyCellFunctor(size_t cellSize)
+        : m_cellSize(cellSize)
+    {
+    }
+
+    void operator()(JSCell* cell)
+    {
+        if (Options::zombiesAreImmortal())
+            MarkedBlock::blockFor(cell)->setMarked(cell);
+
+        void** current = reinterpret_cast<void**>(cell);
+
+        // We want to maintain zapped-ness because that's how we know if we've called 
+        // the destructor.
+        if (cell->isZapped())
+            current++;
+
+        void* limit = static_cast<void*>(reinterpret_cast<char*>(cell) + m_cellSize);
+        for (; current < limit; current++)
+            *current = reinterpret_cast<void*>(0xbbadbeef);
+    }
+
+private:
+    size_t m_cellSize;
+};
+
+class ZombifyBlockFunctor : public MarkedBlock::VoidFunctor {
+public:
+    void operator()(MarkedBlock* block)
+    {
+        ZombifyCellFunctor functor(block->cellSize());
+        block->forEachDeadCell(functor);
+    }
+};
+
+void Heap::zombifyDeadObjects()
+{
+    m_objectSpace.sweep();
+
+    ZombifyBlockFunctor functor;
+    m_objectSpace.forEachBlock(functor);
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/heap/Heap.h (127828 => 127829)


--- trunk/Source/_javascript_Core/heap/Heap.h	2012-09-07 05:34:33 UTC (rev 127828)
+++ trunk/Source/_javascript_Core/heap/Heap.h	2012-09-07 05:53:25 UTC (rev 127829)
@@ -203,7 +203,8 @@
         void harvestWeakReferences();
         void finalizeUnconditionalFinalizers();
         void deleteUnmarkedCompiledCode();
-        
+        void zombifyDeadObjects();
+ 
         RegisterFile& registerFile();
         BlockAllocator& blockAllocator();
 

Modified: trunk/Source/_javascript_Core/heap/MarkedBlock.h (127828 => 127829)


--- trunk/Source/_javascript_Core/heap/MarkedBlock.h	2012-09-07 05:34:33 UTC (rev 127828)
+++ trunk/Source/_javascript_Core/heap/MarkedBlock.h	2012-09-07 05:53:25 UTC (rev 127829)
@@ -186,6 +186,7 @@
 #endif
 
         template <typename Functor> void forEachCell(Functor&);
+        template <typename Functor> void forEachDeadCell(Functor&);
 
     private:
         static const size_t atomAlignmentMask = atomSize - 1; // atomSize must be a power of two.
@@ -417,6 +418,17 @@
         }
     }
 
+    template <typename Functor> inline void MarkedBlock::forEachDeadCell(Functor& functor)
+    {
+        for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
+            JSCell* cell = reinterpret_cast_ptr<JSCell*>(&atoms()[i]);
+            if (isLive(cell))
+                continue;
+
+            functor(cell);
+        }
+    }
+
     inline bool MarkedBlock::needsSweeping()
     {
         return m_state == Marked || m_state == Zapped;

Modified: trunk/Source/_javascript_Core/runtime/Options.cpp (127828 => 127829)


--- trunk/Source/_javascript_Core/runtime/Options.cpp	2012-09-07 05:34:33 UTC (rev 127828)
+++ trunk/Source/_javascript_Core/runtime/Options.cpp	2012-09-07 05:53:25 UTC (rev 127829)
@@ -146,6 +146,11 @@
     useRegExpJIT() = false;
 #endif
 
+#if USE(CF) || OS(UNIX)
+    zombiesAreImmortal() = !!getenv("JSImmortalZombieEnabled");
+    useZombieMode() = zombiesAreImmortal() || !!getenv("JSZombieEnabled");
+#endif
+
     // Do range checks where needed and make corrections to the options:
     ASSERT(thresholdForOptimizeAfterLongWarmUp() >= thresholdForOptimizeAfterWarmUp());
     ASSERT(thresholdForOptimizeAfterWarmUp() >= thresholdForOptimizeSoon());

Modified: trunk/Source/_javascript_Core/runtime/Options.h (127828 => 127829)


--- trunk/Source/_javascript_Core/runtime/Options.h	2012-09-07 05:34:33 UTC (rev 127828)
+++ trunk/Source/_javascript_Core/runtime/Options.h	2012-09-07 05:53:25 UTC (rev 127829)
@@ -118,7 +118,10 @@
     v(unsigned, opaqueRootMergeThreshold, 1000) \
     \
     v(bool, forceWeakRandomSeed, false) \
-    v(unsigned, forcedWeakRandomSeed, 0)
+    v(unsigned, forcedWeakRandomSeed, 0) \
+    \
+    v(bool, useZombieMode, false) \
+    v(bool, zombiesAreImmortal, false) 
 
 
 class Options {
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to