Changeset 176424 in webkit


Ignore:
Timestamp:
Nov 20, 2014 3:28:41 PM (9 years ago)
Author:
mark.lam@apple.com
Message:

Add Heap verification infrastructure.
<https://webkit.org/b/138851>

Reviewed by Geoffrey Garen.

The verification infrastructure code is always built in but disabled by
default. When disabled, the cost is minimal:

  1. Heap has a m_verifier field.
  2. GC does a few "if (m_verifier)" checks that should fail.
  3. HeapVerifier takes up code space though not used.

When enabled:

  1. The HeapVerifier will keep N number of GC cycle data. Each GC cycle will contain a "before marking" and "after marking" live object list. The GC cycles is a circular buffer. Only data for the last N GC cycles will be retained.
  2. During GC, the current GC cycle's live objects lists will be populated before and after marking.
  3. The current GC cycle's live object lists will be validated before GC, after marking, and after GC.

Currently, the only validation being done is to verify that object
butterflies are allocated from valid blocks in the Storage (aka Copied)
space.

(JSC::Heap::Heap):
(JSC::Heap::collect):

  • heap/Heap.h:
  • heap/HeapVerifier.cpp: Added.

(JSC::LiveObjectList::findObject):
(JSC::HeapVerifier::HeapVerifier):
(JSC::HeapVerifier::collectionTypeName):
(JSC::HeapVerifier::phaseName):
(JSC::getButterflyDetails):
(JSC::HeapVerifier::initializeGCCycle):
(JSC::GatherLiveObjFunctor::GatherLiveObjFunctor):
(JSC::GatherLiveObjFunctor::operator()):
(JSC::HeapVerifier::gatherLiveObjects):
(JSC::HeapVerifier::liveObjectListForGathering):
(JSC::trimDeadObjectsFromList):
(JSC::HeapVerifier::trimDeadObjects):
(JSC::HeapVerifier::verifyButterflyIsInStorageSpace):
(JSC::HeapVerifier::verify):
(JSC::HeapVerifier::reportObject):
(JSC::HeapVerifier::checkIfRecorded):

  • heap/HeapVerifier.h: Added.

(JSC::LiveObjectData::LiveObjectData):
(JSC::LiveObjectList::LiveObjectList):
(JSC::LiveObjectList::reset):
(JSC::HeapVerifier::GCCycle::GCCycle):
(JSC::HeapVerifier::GCCycle::collectionTypeName):
(JSC::HeapVerifier::incrementCycle):
(JSC::HeapVerifier::currentCycle):
(JSC::HeapVerifier::cycleForIndex):

  • runtime/Options.h:
Location:
trunk/Source/JavaScriptCore
Files:
2 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r176329 r176424  
    266266    heap/HeapStatistics.cpp
    267267    heap/HeapTimer.cpp
     268    heap/HeapVerifier.cpp
    268269    heap/IncrementalSweeper.cpp
    269270    heap/JITStubRoutineSet.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r176404 r176424  
     12014-11-20  Mark Lam  <mark.lam@apple.com>
     2
     3        Add Heap verification infrastructure.
     4        <https://webkit.org/b/138851>
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        The verification infrastructure code is always built in but disabled by
     9        default.  When disabled, the cost is minimal:
     10        1. Heap has a m_verifier field.
     11        2. GC does a few "if (m_verifier)" checks that should fail.
     12        3. HeapVerifier takes up code space though not used.
     13
     14        When enabled:
     15        1. The HeapVerifier will keep N number of GC cycle data.
     16           Each GC cycle will contain a "before marking" and "after marking" live
     17           object list.
     18           The GC cycles is a circular buffer.  Only data for the last N GC cycles
     19           will be retained.
     20        2. During GC, the current GC cycle's live objects lists will be populated
     21           before and after marking.
     22        3. The current GC cycle's live object lists will be validated before GC,
     23           after marking, and after GC.
     24
     25        Currently, the only validation being done is to verify that object
     26        butterflies are allocated from valid blocks in the Storage (aka Copied)
     27        space.
     28
     29        * CMakeLists.txt:
     30        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     31        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
     32        * JavaScriptCore.xcodeproj/project.pbxproj:
     33        * heap/Heap.cpp:
     34        (JSC::Heap::Heap):
     35        (JSC::Heap::collect):
     36        * heap/Heap.h:
     37        * heap/HeapVerifier.cpp: Added.
     38        (JSC::LiveObjectList::findObject):
     39        (JSC::HeapVerifier::HeapVerifier):
     40        (JSC::HeapVerifier::collectionTypeName):
     41        (JSC::HeapVerifier::phaseName):
     42        (JSC::getButterflyDetails):
     43        (JSC::HeapVerifier::initializeGCCycle):
     44        (JSC::GatherLiveObjFunctor::GatherLiveObjFunctor):
     45        (JSC::GatherLiveObjFunctor::operator()):
     46        (JSC::HeapVerifier::gatherLiveObjects):
     47        (JSC::HeapVerifier::liveObjectListForGathering):
     48        (JSC::trimDeadObjectsFromList):
     49        (JSC::HeapVerifier::trimDeadObjects):
     50        (JSC::HeapVerifier::verifyButterflyIsInStorageSpace):
     51        (JSC::HeapVerifier::verify):
     52        (JSC::HeapVerifier::reportObject):
     53        (JSC::HeapVerifier::checkIfRecorded):
     54        * heap/HeapVerifier.h: Added.
     55        (JSC::LiveObjectData::LiveObjectData):
     56        (JSC::LiveObjectList::LiveObjectList):
     57        (JSC::LiveObjectList::reset):
     58        (JSC::HeapVerifier::GCCycle::GCCycle):
     59        (JSC::HeapVerifier::GCCycle::collectionTypeName):
     60        (JSC::HeapVerifier::incrementCycle):
     61        (JSC::HeapVerifier::currentCycle):
     62        (JSC::HeapVerifier::cycleForIndex):
     63        * runtime/Options.h:
     64
    1652014-11-20  Yusuke Suzuki  <utatane.tea@gmail.com>
    266
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r176329 r176424  
    548548    <ClCompile Include="..\heap\HeapStatistics.cpp" />
    549549    <ClCompile Include="..\heap\HeapTimer.cpp" />
     550    <ClCompile Include="..\heap\HeapVerifier.cpp" />
    550551    <ClCompile Include="..\heap\IncrementalSweeper.cpp" />
    551552    <ClCompile Include="..\heap\JITStubRoutineSet.cpp" />
     
    12511252    <ClInclude Include="..\heap\HeapStatistics.h" />
    12521253    <ClInclude Include="..\heap\HeapTimer.h" />
     1254    <ClInclude Include="..\heap\HeapVerifier.h" />
    12531255    <ClInclude Include="..\heap\IncrementalSweeper.h" />
    12541256    <ClInclude Include="..\heap\JITStubRoutineSet.h" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters

    r176329 r176424  
    283283      <Filter>heap</Filter>
    284284    </ClCompile>
     285    <ClCompile Include="..\heap\HeapVerifier.cpp">
     286      <Filter>heap</Filter>
     287    </ClCompile>
    285288    <ClCompile Include="..\heap\IncrementalSweeper.cpp">
    286289      <Filter>heap</Filter>
     
    21342137    </ClInclude>
    21352138    <ClInclude Include="..\heap\HeapTimer.h">
     2139      <Filter>heap</Filter>
     2140    </ClInclude>
     2141    <ClInclude Include="..\heap\HeapVerifier.h">
    21362142      <Filter>heap</Filter>
    21372143    </ClInclude>
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r176335 r176424  
    15961596                FE5932A7183C5A2600A1ECCC /* VMEntryScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */; };
    15971597                FE5932A8183C5A2600A1ECCC /* VMEntryScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1598                FE7BA60F1A1A7CEC00F1F7B4 /* HeapVerifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE7BA60D1A1A7CEC00F1F7B4 /* HeapVerifier.cpp */; };
     1599                FE7BA6101A1A7CEC00F1F7B4 /* HeapVerifier.h in Headers */ = {isa = PBXBuildFile; fileRef = FE7BA60E1A1A7CEC00F1F7B4 /* HeapVerifier.h */; settings = {ATTRIBUTES = (Private, ); }; };
    15981600                FEA08620182B7A0400F6D851 /* Breakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861E182B7A0400F6D851 /* Breakpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
    15991601                FEA08621182B7A0400F6D851 /* DebuggerPrimitives.h in Headers */ = {isa = PBXBuildFile; fileRef = FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    33123314                FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VMEntryScope.cpp; sourceTree = "<group>"; };
    33133315                FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMEntryScope.h; sourceTree = "<group>"; };
     3316                FE7BA60D1A1A7CEC00F1F7B4 /* HeapVerifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HeapVerifier.cpp; sourceTree = "<group>"; };
     3317                FE7BA60E1A1A7CEC00F1F7B4 /* HeapVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapVerifier.h; sourceTree = "<group>"; };
    33143318                FEA0861E182B7A0400F6D851 /* Breakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Breakpoint.h; sourceTree = "<group>"; };
    33153319                FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerPrimitives.h; sourceTree = "<group>"; };
     
    38033807                        isa = PBXGroup;
    38043808                        children = (
     3809                                FE7BA60D1A1A7CEC00F1F7B4 /* HeapVerifier.cpp */,
     3810                                FE7BA60E1A1A7CEC00F1F7B4 /* HeapVerifier.h */,
    38053811                                C2DA778218E259990066FCB6 /* HeapInlines.h */,
    38063812                                ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */,
     
    53805386                                2AABCDE718EF294200002096 /* GCLogging.h in Headers */,
    53815387                                FE5248F9191442D900B7FDE4 /* VariableWatchpointSetInlines.h in Headers */,
     5388                                FE7BA6101A1A7CEC00F1F7B4 /* HeapVerifier.h in Headers */,
    53825389                                A5EF9B141A1D43F600702E90 /* generate_cpp_backend_dispatcher_header.py in Headers */,
    53835390                                C2DA778318E259990066FCB6 /* HeapInlines.h in Headers */,
     
    69876994                                A5840E20187B7B8600843B10 /* InjectedScriptModule.cpp in Sources */,
    69886995                                0F24E55517F0B71C00ABB217 /* InlineCallFrameSet.cpp in Sources */,
     6996                                FE7BA60F1A1A7CEC00F1F7B4 /* HeapVerifier.cpp in Sources */,
    69896997                                A5CEEE14187F3BAD00E55C99 /* InspectorAgent.cpp in Sources */,
    69906998                                A593CF86184038CA00BFCE27 /* InspectorAgentRegistry.cpp in Sources */,
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r176219 r176424  
    3636#include "HeapRootVisitor.h"
    3737#include "HeapStatistics.h"
     38#include "HeapVerifier.h"
    3839#include "IncrementalSweeper.h"
    3940#include "Interpreter.h"
     
    340341{
    341342    m_storageSpace.init();
     343    if (Options::verifyHeap())
     344        m_verifier = std::make_unique<HeapVerifier>(this, Options::numberOfGCCyclesToRecordForVerification());
    342345}
    343346
     
    10051008
    10061009    double gcStartTime = WTF::monotonicallyIncreasingTime();
     1010    if (m_verifier) {
     1011        // Verify that live objects from the last GC cycle haven't been corrupted by
     1012        // mutators before we begin this new GC cycle.
     1013        m_verifier->verify(HeapVerifier::Phase::BeforeGC);
     1014
     1015        m_verifier->initializeGCCycle();
     1016        m_verifier->gatherLiveObjects(HeapVerifier::Phase::BeforeMarking);
     1017    }
    10071018
    10081019    deleteOldCode(gcStartTime);
     
    10131024    markRoots(gcStartTime);
    10141025
     1026    if (m_verifier) {
     1027        m_verifier->gatherLiveObjects(HeapVerifier::Phase::AfterMarking);
     1028        m_verifier->verify(HeapVerifier::Phase::AfterMarking);
     1029    }
    10151030    JAVASCRIPTCORE_GC_MARKED();
    10161031
     
    10351050    didFinishCollection(gcStartTime);
    10361051    resumeCompilerThreads();
     1052
     1053    if (m_verifier) {
     1054        m_verifier->trimDeadObjects();
     1055        m_verifier->verify(HeapVerifier::Phase::AfterGC);
     1056    }
    10371057
    10381058    if (Options::logGC()) {
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r176000 r176424  
    5858class Heap;
    5959class HeapRootVisitor;
     60class HeapVerifier;
    6061class IncrementalSweeper;
    6162class JITStubRoutine;
     
    235236    friend class GCLogging;
    236237    friend class HandleSet;
     238    friend class HeapVerifier;
    237239    friend class JITStubRoutine;
    238240    friend class LLIntOffsetsExtractor;
     
    384386    unsigned m_deferralDepth;
    385387    Vector<DFG::Worklist*> m_suspendedCompilerWorklists;
     388
     389    std::unique_ptr<HeapVerifier> m_verifier;
    386390};
    387391
  • trunk/Source/JavaScriptCore/runtime/Options.h

    r174224 r176424  
    288288    v(bool, enableTypeProfiler, false) \
    289289    \
     290    v(bool, verifyHeap, true) \
     291    v(unsigned, numberOfGCCyclesToRecordForVerification, 3) \
     292    \
    290293    v(bool, enableExceptionFuzz, false) \
    291294    v(unsigned, fireExceptionFuzzAt, 0)
Note: See TracChangeset for help on using the changeset viewer.