Changeset 248143 in webkit


Ignore:
Timestamp:
Aug 1, 2019 6:58:11 PM (5 years ago)
Author:
mark.lam@apple.com
Message:

Add crash diagnostics for debugging unexpected zapped cells.
https://bugs.webkit.org/show_bug.cgi?id=200149
<rdar://problem/53570112>

Reviewed by Yusuke Suzuki.

Source/JavaScriptCore:

Add a check for zapped cells in SlotVisitor::appendToMarkStack() and
SlotVisitor::visitChildren(). If a zapped cell is detected, we will crash with
some diagnostic info.

To facilitate this, we've made the following changes:

  1. Changed FreeCell to preserve the 1st 8 bytes. This is fine to do because all cells are at least 16 bytes long.
  2. Changed HeapCell::zap() to only zap the structureID. Leave the rest of the cell header info intact (including the cell JSType).
  3. Changed HeapCell::zap() to record the reason for zapping the cell. We stash the reason immediately after the first 8 bytes. This is the same location as FreeCell::scrambledNext. However, since a cell is not expected to be zapped and on the free list at the same time, it is also fine to do this.
  4. Added a few utility functions to MarkedBlock for checking if a cell points into the block.
  5. Added VMInspector and JSDollarVM utilities to dump in-use subspace hashes.
  6. Added some comments to document the hashes of known subspaces.
  7. Added Options::dumpZappedCellCrashData() to make this check conditional. We use this option to disable this check for slower machines so that their PLT5 performance is not impacted.
  • assembler/CPU.cpp:

(JSC::hwL3CacheSize):
(JSC::hwPhysicalCPUMax):

  • assembler/CPU.h:

(JSC::hwL3CacheSize):
(JSC::hwPhysicalCPUMax):

  • heap/FreeList.h:

(JSC::FreeCell::offsetOfScrambledNext):

  • heap/HeapCell.h:

(JSC::HeapCell::zap):
(JSC::HeapCell::isZapped const):

  • heap/MarkedBlock.cpp:

(JSC::MarkedBlock::Handle::stopAllocating):

  • heap/MarkedBlock.h:

(JSC::MarkedBlock::Handle::start const):
(JSC::MarkedBlock::Handle::end const):
(JSC::MarkedBlock::Handle::contains const):

  • heap/MarkedBlockInlines.h:

(JSC::MarkedBlock::Handle::specializedSweep):

  • heap/MarkedSpace.h:

(JSC::MarkedSpace::forEachSubspace):

  • heap/SlotVisitor.cpp:

(JSC::SlotVisitor::appendToMarkStack):
(JSC::SlotVisitor::visitChildren):
(JSC::SlotVisitor::reportZappedCellAndCrash):

  • heap/SlotVisitor.h:
  • jit/AssemblyHelpers.cpp:

(JSC::AssemblyHelpers::emitAllocateWithNonNullAllocator):

  • runtime/Options.cpp:

(JSC::Options::initialize):

  • runtime/Options.h:
  • runtime/VM.cpp:

(JSC::VM::VM):

  • tools/JSDollarVM.cpp:

(JSC::functionDumpSubspaceHashes):
(JSC::JSDollarVM::finishCreation):

  • tools/VMInspector.cpp:

(JSC::VMInspector::dumpSubspaceHashes):

  • tools/VMInspector.h:

Source/WebCore:

No new tests because this is a feature for debugging crashes. It has been tested
manually by modifying the code to force a crash at the point of interest.

Added some comments to document the hashes of known subspaces.

  • bindings/js/WebCoreJSClientData.cpp:

(WebCore::JSVMClientData::JSVMClientData):

Location:
trunk/Source
Files:
20 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r248133 r248143  
     12019-08-01  Mark Lam  <mark.lam@apple.com>
     2
     3        Add crash diagnostics for debugging unexpected zapped cells.
     4        https://bugs.webkit.org/show_bug.cgi?id=200149
     5        <rdar://problem/53570112>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        Add a check for zapped cells in SlotVisitor::appendToMarkStack() and
     10        SlotVisitor::visitChildren().  If a zapped cell is detected, we will crash with
     11        some diagnostic info.
     12
     13        To facilitate this, we've made the following changes:
     14        1. Changed FreeCell to preserve the 1st 8 bytes.  This is fine to do because all
     15           cells are at least 16 bytes long.
     16        2. Changed HeapCell::zap() to only zap the structureID.  Leave the rest of the
     17           cell header info intact (including the cell JSType).
     18        3. Changed HeapCell::zap() to record the reason for zapping the cell.  We stash
     19           the reason immediately after the first 8 bytes.  This is the same location as
     20           FreeCell::scrambledNext.  However, since a cell is not expected to be zapped
     21           and on the free list at the same time, it is also fine to do this.
     22        4. Added a few utility functions to MarkedBlock for checking if a cell points
     23           into the block.
     24        5. Added VMInspector and JSDollarVM utilities to dump in-use subspace hashes.
     25        6. Added some comments to document the hashes of known subspaces.
     26        7. Added Options::dumpZappedCellCrashData() to make this check conditional.
     27           We use this option to disable this check for slower machines so that their
     28           PLT5 performance is not impacted.
     29
     30        * assembler/CPU.cpp:
     31        (JSC::hwL3CacheSize):
     32        (JSC::hwPhysicalCPUMax):
     33        * assembler/CPU.h:
     34        (JSC::hwL3CacheSize):
     35        (JSC::hwPhysicalCPUMax):
     36        * heap/FreeList.h:
     37        (JSC::FreeCell::offsetOfScrambledNext):
     38        * heap/HeapCell.h:
     39        (JSC::HeapCell::zap):
     40        (JSC::HeapCell::isZapped const):
     41        * heap/MarkedBlock.cpp:
     42        (JSC::MarkedBlock::Handle::stopAllocating):
     43        * heap/MarkedBlock.h:
     44        (JSC::MarkedBlock::Handle::start const):
     45        (JSC::MarkedBlock::Handle::end const):
     46        (JSC::MarkedBlock::Handle::contains const):
     47        * heap/MarkedBlockInlines.h:
     48        (JSC::MarkedBlock::Handle::specializedSweep):
     49        * heap/MarkedSpace.h:
     50        (JSC::MarkedSpace::forEachSubspace):
     51        * heap/SlotVisitor.cpp:
     52        (JSC::SlotVisitor::appendToMarkStack):
     53        (JSC::SlotVisitor::visitChildren):
     54        (JSC::SlotVisitor::reportZappedCellAndCrash):
     55        * heap/SlotVisitor.h:
     56        * jit/AssemblyHelpers.cpp:
     57        (JSC::AssemblyHelpers::emitAllocateWithNonNullAllocator):
     58        * runtime/Options.cpp:
     59        (JSC::Options::initialize):
     60        * runtime/Options.h:
     61        * runtime/VM.cpp:
     62        (JSC::VM::VM):
     63        * tools/JSDollarVM.cpp:
     64        (JSC::functionDumpSubspaceHashes):
     65        (JSC::JSDollarVM::finishCreation):
     66        * tools/VMInspector.cpp:
     67        (JSC::VMInspector::dumpSubspaceHashes):
     68        * tools/VMInspector.h:
     69
    1702019-08-01  Keith Miller  <keith_miller@apple.com>
    271
  • trunk/Source/JavaScriptCore/assembler/CPU.cpp

    r244237 r248143  
    6767    return result;
    6868}
     69
     70int64_t hwL3CacheSize()
     71{
     72    int64_t val = 0;
     73    size_t valSize = sizeof(val);
     74    int rc = sysctlbyname("hw.l3cachesize", &val, &valSize, nullptr, 0);
     75    if (rc < 0)
     76        return 0;
     77    return val;
     78}
     79
     80int32_t hwPhysicalCPUMax()
     81{
     82    int64_t val = 0;
     83    size_t valSize = sizeof(val);
     84    int rc = sysctlbyname("hw.physicalcpu_max", &val, &valSize, nullptr, 0);
     85    if (rc < 0)
     86        return 0;
     87    return val;
     88}
     89
    6990#endif // #if (CPU(X86) || CPU(X86_64)) && OS(DARWIN)
    7091
  • trunk/Source/JavaScriptCore/assembler/CPU.h

    r246368 r248143  
    11/*
    2  * Copyright (C) 2008-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    146146bool enableKernTCSM();
    147147int kernTCSMAwareNumberOfProcessorCores();
     148int64_t hwL3CacheSize();
     149int32_t hwPhysicalCPUMax();
    148150#else
    149151ALWAYS_INLINE bool isKernTCSMAvailable() { return false; }
    150152ALWAYS_INLINE bool enableKernTCSM() { return false; }
    151153ALWAYS_INLINE int kernTCSMAwareNumberOfProcessorCores() { return WTF::numberOfProcessorCores(); }
     154ALWAYS_INLINE int64_t hwL3CacheSize() { return 0; }
     155ALWAYS_INLINE int32_t hwPhysicalCPUMax() { return kernTCSMAwareNumberOfProcessorCores(); }
    152156#endif
    153157
  • trunk/Source/JavaScriptCore/heap/FreeList.h

    r247900 r248143  
    11/*
    2  * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2016-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5454    }
    5555   
     56    static ptrdiff_t offsetOfScrambledNext() { return OBJECT_OFFSETOF(FreeCell, scrambledNext); }
     57
     58    uint64_t preservedBitsForCrashAnalysis;
    5659    uintptr_t scrambledNext;
    5760};
  • trunk/Source/JavaScriptCore/heap/HeapCell.h

    r247900 r248143  
    11/*
    2  * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2016-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4848    HeapCell() { }
    4949   
    50     void zap() { *reinterpret_cast_ptr<uintptr_t**>(this) = 0; }
    51     bool isZapped() const { return !*reinterpret_cast_ptr<uintptr_t* const*>(this); }
     50    // We're intentionally only zapping the bits for the structureID and leaving
     51    // the rest of the cell header bits intact for crash analysis uses.
     52    enum ZapReason : int8_t { Unspecified, Destruction, StopAllocating };
     53    void zap(ZapReason reason)
     54    {
     55        uint32_t* cellWords = bitwise_cast<uint32_t*>(this);
     56        cellWords[0] = 0;
     57        // Leaving cellWords[1] alone for crash analysis if needed.
     58        cellWords[2] = reason;
     59    }
     60    bool isZapped() const { return !*bitwise_cast<const uint32_t*>(this); }
    5261
    5362    bool isLive();
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp

    r247900 r248143  
    162162                dataLog("Free cell: ", RawPointer(cell), "\n");
    163163            if (m_attributes.destruction == NeedsDestruction)
    164                 cell->zap();
     164                cell->zap(HeapCell::StopAllocating);
    165165            block().clearNewlyAllocated(cell);
    166166        });
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.h

    r247900 r248143  
    199199        void didRemoveFromDirectory();
    200200       
     201        void* start() const { return &m_block->atoms()[0]; }
     202        void* end() const { return &m_block->atoms()[m_endAtom]; }
     203        bool contains(void* p) const { return start() <= p && p < end(); }
     204
    201205        void dumpState(PrintStream&);
    202206       
  • trunk/Source/JavaScriptCore/heap/MarkedBlockInlines.h

    r247900 r248143  
    11/*
    2  * Copyright (C) 2016-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2016-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    259259        if (!jsCell->isZapped()) {
    260260            destroyFunc(vm, jsCell);
    261             jsCell->zap();
     261            jsCell->zap(HeapCell::Destruction);
    262262        }
    263263    };
  • trunk/Source/JavaScriptCore/heap/MarkedSpace.h

    r247900 r248143  
    125125    template<typename Functor> void forEachDeadCell(HeapIterationScope&, const Functor&);
    126126    template<typename Functor> void forEachBlock(const Functor&);
     127    template<typename Functor> void forEachSubspace(const Functor&);
    127128
    128129    void shrink();
     
    241242}
    242243
     244template<typename Functor>
     245void MarkedSpace::forEachSubspace(const Functor& functor)
     246{
     247    for (auto subspace : m_subspaces) {
     248        if (functor(*subspace) == IterationStatus::Done)
     249            return;
     250    }
     251}
     252
     253
    243254ALWAYS_INLINE size_t MarkedSpace::optimalSizeFor(size_t bytes)
    244255{
  • trunk/Source/JavaScriptCore/heap/SlotVisitor.cpp

    r247900 r248143  
    287287{
    288288    ASSERT(m_heap.isMarked(cell));
     289#if CPU(X86_64)
     290    if (Options::dumpZappedCellCrashData()) {
     291        if (UNLIKELY(cell->isZapped()))
     292            reportZappedCellAndCrash(cell);
     293    }
     294#endif
    289295    ASSERT(!cell->isZapped());
    290    
     296
    291297    container.noteMarked();
    292298   
     
    386392        // FIXME: This could be so much better.
    387393        // https://bugs.webkit.org/show_bug.cgi?id=162462
     394#if CPU(X86_64)
     395        if (Options::dumpZappedCellCrashData()) {
     396            Structure* structure = cell->structure(vm());
     397            if (LIKELY(structure)) {
     398                const MethodTable* methodTable = &structure->classInfo()->methodTable;
     399                methodTable->visitChildren(const_cast<JSCell*>(cell), *this);
     400                break;
     401            }
     402            reportZappedCellAndCrash(const_cast<JSCell*>(cell));
     403        }
     404#endif
    388405        cell->methodTable(vm())->visitChildren(const_cast<JSCell*>(cell), *this);
    389406        break;
     
    805822}
    806823
     824#if CPU(X86_64)
     825NEVER_INLINE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void SlotVisitor::reportZappedCellAndCrash(JSCell* cell)
     826{
     827    MarkedBlock::Handle* foundBlock = nullptr;
     828    uint32_t* cellWords = reinterpret_cast_ptr<uint32_t*>(this);
     829
     830    uintptr_t cellAddress = bitwise_cast<uintptr_t>(cell);
     831    uintptr_t headerWord = cellWords[1];
     832    uintptr_t zapReason = cellWords[2];
     833    unsigned subspaceHash = 0;
     834    size_t cellSize = 0;
     835
     836    m_heap.objectSpace().forEachBlock([&] (MarkedBlock::Handle* block) {
     837        if (block->contains(cell)) {
     838            foundBlock = block;
     839            return IterationStatus::Done;
     840        }
     841        return IterationStatus::Continue;
     842    });
     843
     844    if (foundBlock) {
     845        subspaceHash = StringHasher::computeHash(foundBlock->subspace()->name());
     846        cellSize = foundBlock->cellSize();
     847    }
     848
     849    CRASH_WITH_INFO(cellAddress, headerWord, zapReason, subspaceHash, cellSize);
     850}
     851#endif // PLATFORM(MAC)
     852
    807853} // namespace JSC
  • trunk/Source/JavaScriptCore/heap/SlotVisitor.h

    r247925 r248143  
    228228    bool didReachTermination(const AbstractLocker&);
    229229
     230#if CPU(X86_64)
     231    NEVER_INLINE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void reportZappedCellAndCrash(JSCell*);
     232#endif
     233
    230234    template<typename Func>
    231235    IterationStatus forEachMarkStack(const Func&);
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp

    r247900 r248143  
    547547    // The object is half-allocated: we have what we know is a fresh object, but
    548548    // it's still on the GC's free list.
    549     loadPtr(Address(resultGPR), scratchGPR);
     549    loadPtr(Address(resultGPR, FreeCell::offsetOfScrambledNext()), scratchGPR);
    550550    storePtr(scratchGPR, Address(allocatorGPR, LocalAllocator::offsetOfFreeList() + FreeList::offsetOfScrambledHead()));
    551551       
  • trunk/Source/JavaScriptCore/runtime/Options.cpp

    r247543 r248143  
    604604                }
    605605            }
     606#endif
     607
     608#if CPU(X86_64) && OS(DARWIN)
     609            Options::dumpZappedCellCrashData() =
     610                (hwPhysicalCPUMax() >= 4) && (hwL3CacheSize() >= static_cast<int64_t>(6 * MB));
    606611#endif
    607612        });
  • trunk/Source/JavaScriptCore/runtime/Options.h

    r247925 r248143  
    242242    v(bool, stealEmptyBlocksFromOtherAllocators, true, Normal, nullptr) \
    243243    v(bool, eagerlyUpdateTopCallFrame, false, Normal, nullptr) \
     244    v(bool, dumpZappedCellCrashData, false, Normal, nullptr) \
    244245    \
    245246    v(bool, useOSREntryToDFG, true, Normal, nullptr) \
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r247900 r248143  
    266266    , webAssemblyFunctionHeapCellType(std::make_unique<WebAssemblyFunctionHeapCellType>())
    267267#endif
    268     , primitiveGigacageAuxiliarySpace("Primitive Gigacage Auxiliary", heap, auxiliaryHeapCellType.get(), primitiveGigacageAllocator.get())
    269     , jsValueGigacageAuxiliarySpace("JSValue Gigacage Auxiliary", heap, auxiliaryHeapCellType.get(), jsValueGigacageAllocator.get())
    270     , immutableButterflyJSValueGigacageAuxiliarySpace("ImmutableButterfly Gigacage JSCellWithInteriorPointers", heap, immutableButterflyHeapCellType.get(), jsValueGigacageAllocator.get())
    271     , cellSpace("JSCell", heap, cellHeapCellType.get(), fastMallocAllocator.get())
    272     , jsValueGigacageCellSpace("JSValue Gigacage JSCell", heap, cellHeapCellType.get(), jsValueGigacageAllocator.get())
    273     , destructibleCellSpace("Destructible JSCell", heap, destructibleCellHeapCellType.get(), fastMallocAllocator.get())
    274     , stringSpace("JSString", heap, stringHeapCellType.get(), fastMallocAllocator.get())
    275     , destructibleObjectSpace("JSDestructibleObject", heap, destructibleObjectHeapCellType.get(), fastMallocAllocator.get())
    276     , eagerlySweptDestructibleObjectSpace("Eagerly Swept JSDestructibleObject", heap, destructibleObjectHeapCellType.get(), fastMallocAllocator.get())
    277     , executableToCodeBlockEdgeSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), ExecutableToCodeBlockEdge)
    278     , functionSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), JSFunction)
    279     , internalFunctionSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), InternalFunction)
    280     , nativeExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), NativeExecutable)
    281     , propertyTableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), PropertyTable)
    282     , structureRareDataSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), StructureRareData)
    283     , structureSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), Structure)
    284     , symbolTableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), SymbolTable)
     268    , primitiveGigacageAuxiliarySpace("Primitive Gigacage Auxiliary", heap, auxiliaryHeapCellType.get(), primitiveGigacageAllocator.get()) // Hash:0x3e7cd762
     269    , jsValueGigacageAuxiliarySpace("JSValue Gigacage Auxiliary", heap, auxiliaryHeapCellType.get(), jsValueGigacageAllocator.get()) // Hash:0x241e946
     270    , immutableButterflyJSValueGigacageAuxiliarySpace("ImmutableButterfly Gigacage JSCellWithInteriorPointers", heap, immutableButterflyHeapCellType.get(), jsValueGigacageAllocator.get()) // Hash:0x7a945300
     271    , cellSpace("JSCell", heap, cellHeapCellType.get(), fastMallocAllocator.get()) // Hash:0xadfb5a79
     272    , jsValueGigacageCellSpace("JSValue Gigacage JSCell", heap, cellHeapCellType.get(), jsValueGigacageAllocator.get()) // Hash:0x2f5b102b
     273    , destructibleCellSpace("Destructible JSCell", heap, destructibleCellHeapCellType.get(), fastMallocAllocator.get()) // Hash:0xbfff3d73
     274    , stringSpace("JSString", heap, stringHeapCellType.get(), fastMallocAllocator.get()) // Hash:0x90cf758f
     275    , destructibleObjectSpace("JSDestructibleObject", heap, destructibleObjectHeapCellType.get(), fastMallocAllocator.get()) // Hash:0x4f5ed7a9
     276    , eagerlySweptDestructibleObjectSpace("Eagerly Swept JSDestructibleObject", heap, destructibleObjectHeapCellType.get(), fastMallocAllocator.get()) // Hash:0x6ebf28e2
     277    , executableToCodeBlockEdgeSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), ExecutableToCodeBlockEdge) // Hash:0x7b730b20
     278    , functionSpace ISO_SUBSPACE_INIT(heap, cellHeapCellType.get(), JSFunction) // Hash:0x800fca72
     279    , internalFunctionSpace ISO_SUBSPACE_INIT(heap, destructibleObjectHeapCellType.get(), InternalFunction) // Hash:0xf845c464
     280    , nativeExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), NativeExecutable) // Hash:0x67567f95
     281    , propertyTableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), PropertyTable) // Hash:0xc6bc9f12
     282    , structureRareDataSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), StructureRareData) // Hash:0xaca4e62d
     283    , structureSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), Structure) // Hash:0x1f1bcdca
     284    , symbolTableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), SymbolTable) // Hash:0xc5215afd
    285285    , executableToCodeBlockEdgesWithConstraints(executableToCodeBlockEdgeSpace)
    286286    , executableToCodeBlockEdgesWithFinalizers(executableToCodeBlockEdgeSpace)
    287     , codeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), CodeBlock)
    288     , functionExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), FunctionExecutable)
    289     , programExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ProgramExecutable)
    290     , unlinkedFunctionExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), UnlinkedFunctionExecutable)
     287    , codeBlockSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), CodeBlock) // Hash:0x77e66ec9
     288    , functionExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), FunctionExecutable) // Hash:0x5d158f3
     289    , programExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), ProgramExecutable) // Hash:0x527c77e7
     290    , unlinkedFunctionExecutableSpace ISO_SUBSPACE_INIT(heap, destructibleCellHeapCellType.get(), UnlinkedFunctionExecutable) // Hash:0xf6b828d9
    291291    , vmType(vmType)
    292292    , clientData(0)
     
    12441244
    12451245
    1246 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(boundFunctionSpace, cellHeapCellType.get(), JSBoundFunction)
    1247 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(callbackFunctionSpace, destructibleObjectHeapCellType.get(), JSCallbackFunction)
    1248 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(customGetterSetterFunctionSpace, cellHeapCellType.get(), JSCustomGetterSetterFunction)
    1249 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(errorInstanceSpace, destructibleObjectHeapCellType.get(), ErrorInstance)
    1250 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(nativeStdFunctionSpace, cellHeapCellType.get(), JSNativeStdFunction)
    1251 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(proxyRevokeSpace, destructibleObjectHeapCellType.get(), ProxyRevoke)
    1252 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(weakMapSpace, destructibleObjectHeapCellType.get(), JSWeakMap)
    1253 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(weakSetSpace, destructibleObjectHeapCellType.get(), JSWeakSet)
    1254 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(weakObjectRefSpace, cellHeapCellType.get(), JSWeakObjectRef)
     1246DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(boundFunctionSpace, cellHeapCellType.get(), JSBoundFunction) // Hash:0xd7916d41
     1247DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(callbackFunctionSpace, destructibleObjectHeapCellType.get(), JSCallbackFunction) // Hash:0xe7648ebc
     1248DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(customGetterSetterFunctionSpace, cellHeapCellType.get(), JSCustomGetterSetterFunction) // Hash:0x18091000
     1249DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(errorInstanceSpace, destructibleObjectHeapCellType.get(), ErrorInstance) // Hash:0x3f40d4a
     1250DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(nativeStdFunctionSpace, cellHeapCellType.get(), JSNativeStdFunction) // Hash:0x70ed61e4
     1251DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(proxyRevokeSpace, destructibleObjectHeapCellType.get(), ProxyRevoke) // Hash:0xb506a939
     1252DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(weakMapSpace, destructibleObjectHeapCellType.get(), JSWeakMap) // Hash:0x662b12a3
     1253DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(weakSetSpace, destructibleObjectHeapCellType.get(), JSWeakSet) // Hash:0x4c781b30
     1254DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(weakObjectRefSpace, cellHeapCellType.get(), JSWeakObjectRef) // Hash:0x8ec68f1f
    12551255#if JSC_OBJC_API_ENABLED
    1256 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(objCCallbackFunctionSpace, destructibleObjectHeapCellType.get(), ObjCCallbackFunction)
     1256DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(objCCallbackFunctionSpace, destructibleObjectHeapCellType.get(), ObjCCallbackFunction) // Hash:0x10f610b8
    12571257#endif
    12581258#if ENABLE(WEBASSEMBLY)
    1259 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyCodeBlockSpace, webAssemblyCodeBlockHeapCellType.get(), JSWebAssemblyCodeBlock)
    1260 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyFunctionSpace, webAssemblyFunctionHeapCellType.get(), WebAssemblyFunction)
    1261 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyWrapperFunctionSpace, cellHeapCellType.get(), WebAssemblyWrapperFunction)
     1259DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyCodeBlockSpace, webAssemblyCodeBlockHeapCellType.get(), JSWebAssemblyCodeBlock) // Hash:0x9ad995cd
     1260DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyFunctionSpace, webAssemblyFunctionHeapCellType.get(), WebAssemblyFunction) // Hash:0x8b7c32db
     1261DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(webAssemblyWrapperFunctionSpace, cellHeapCellType.get(), WebAssemblyWrapperFunction) // Hash:0xd4a5ff01
    12621262#endif
    12631263
     
    12741274    }
    12751275
    1276 DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(evalExecutableSpace, destructibleCellHeapCellType.get(), EvalExecutable)
    1277 DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(moduleProgramExecutableSpace, destructibleCellHeapCellType.get(), ModuleProgramExecutable)
     1276DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(evalExecutableSpace, destructibleCellHeapCellType.get(), EvalExecutable) // Hash:0x958e3e9d
     1277DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW(moduleProgramExecutableSpace, destructibleCellHeapCellType.get(), ModuleProgramExecutable) // Hash:0x6506fa3c
    12781278
    12791279#undef DYNAMIC_SPACE_AND_SET_DEFINE_MEMBER_SLOW
  • trunk/Source/JavaScriptCore/tools/JSDollarVM.cpp

    r248105 r248143  
    13951395}
    13961396
     1397// Dumps the hashes of all subspaces currently registered with the VM.
     1398// Usage: $vm.dumpSubspaceHashes()
     1399static EncodedJSValue JSC_HOST_CALL functionDumpSubspaceHashes(ExecState* exec)
     1400{
     1401    VM& vm = exec->vm();
     1402    VMInspector::dumpSubspaceHashes(&vm);
     1403    return JSValue::encode(jsUndefined());
     1404}
     1405
    13971406// Gets a JSDollarVMCallFrame for a specified frame index.
    13981407// Usage: var callFrame = $vm.callFrame(0) // frame 0 is the top frame.
     
    22262235    addFunction(vm, "gc", functionGC, 0);
    22272236    addFunction(vm, "edenGC", functionEdenGC, 0);
     2237    addFunction(vm, "dumpSubspaceHashes", functionDumpSubspaceHashes, 0);
    22282238
    22292239    addFunction(vm, "callFrame", functionCallFrame, 1);
  • trunk/Source/JavaScriptCore/tools/VMInspector.cpp

    r247900 r248143  
    11/*
    2  * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    627627}
    628628
     629void VMInspector::dumpSubspaceHashes(VM* vm)
     630{
     631    unsigned count = 0;
     632    vm->heap.objectSpace().forEachSubspace([&] (const Subspace& subspace) -> IterationStatus {
     633        const char* name = subspace.name();
     634        unsigned hash = StringHasher::computeHash(name);
     635        void* hashAsPtr = reinterpret_cast<void*>(static_cast<uintptr_t>(hash));
     636        dataLogLn("    [", count++, "] ", name, " Hash:", RawPointer(hashAsPtr));
     637        return IterationStatus::Continue;
     638    });
     639    dataLogLn();
     640}
     641
    629642} // namespace JSC
  • trunk/Source/JavaScriptCore/tools/VMInspector.h

    r247900 r248143  
    11/*
    2  * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    7979    JS_EXPORT_PRIVATE static void dumpCellMemory(JSCell*);
    8080    JS_EXPORT_PRIVATE static void dumpCellMemoryToStream(JSCell*, PrintStream&);
     81    JS_EXPORT_PRIVATE static void dumpSubspaceHashes(VM*);
    8182
    8283private:
  • trunk/Source/WebCore/ChangeLog

    r248141 r248143  
     12019-08-01  Mark Lam  <mark.lam@apple.com>
     2
     3        Add crash diagnostics for debugging unexpected zapped cells.
     4        https://bugs.webkit.org/show_bug.cgi?id=200149
     5        <rdar://problem/53570112>
     6
     7        Reviewed by Yusuke Suzuki.
     8
     9        No new tests because this is a feature for debugging crashes.  It has been tested
     10        manually by modifying the code to force a crash at the point of interest.
     11
     12        Added some comments to document the hashes of known subspaces.
     13
     14        * bindings/js/WebCoreJSClientData.cpp:
     15        (WebCore::JSVMClientData::JSVMClientData):
     16
    1172019-08-01  Saam Barati  <sbarati@apple.com>
    218
  • trunk/Source/WebCore/bindings/js/WebCoreJSClientData.cpp

    r247900 r248143  
    4444    : m_builtinFunctions(vm)
    4545    , m_builtinNames(&vm)
    46     , m_runtimeMethodSpace ISO_SUBSPACE_INIT(vm.heap, vm.destructibleObjectHeapCellType.get(), RuntimeMethod)
    47     , m_outputConstraintSpace("WebCore Wrapper w/ Output Constraint", vm.heap, vm.destructibleObjectHeapCellType.get(), vm.fastMallocAllocator.get())
    48     , m_globalObjectOutputConstraintSpace("WebCore Global Object w/ Output Constraint", vm.heap, vm.cellHeapCellType.get(), vm.fastMallocAllocator.get())
     46    , m_runtimeMethodSpace ISO_SUBSPACE_INIT(vm.heap, vm.destructibleObjectHeapCellType.get(), RuntimeMethod) // Hash:0xf70c4a85
     47    , m_outputConstraintSpace("WebCore Wrapper w/ Output Constraint", vm.heap, vm.destructibleObjectHeapCellType.get(), vm.fastMallocAllocator.get()) // Hash:0x7724c2e4
     48    , m_globalObjectOutputConstraintSpace("WebCore Global Object w/ Output Constraint", vm.heap, vm.cellHeapCellType.get(), vm.fastMallocAllocator.get()) // Hash:0x522d6ec9
    4949{
    5050}
Note: See TracChangeset for help on using the changeset viewer.