Changeset 247886 in webkit


Ignore:
Timestamp:
Jul 26, 2019 5:43:54 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, Saam Barati, and Michael Saboff.

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.
  • 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/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:
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r247854 r247886  
     12019-07-26  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, Saam Barati, and Michael Saboff.
     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
     27        * heap/FreeList.h:
     28        (JSC::FreeCell::offsetOfScrambledNext):
     29        * heap/HeapCell.h:
     30        (JSC::HeapCell::zap):
     31        (JSC::HeapCell::isZapped const):
     32        * heap/MarkedBlock.cpp:
     33        (JSC::MarkedBlock::Handle::stopAllocating):
     34        * heap/MarkedBlock.h:
     35        (JSC::MarkedBlock::Handle::start const):
     36        (JSC::MarkedBlock::Handle::end const):
     37        (JSC::MarkedBlock::Handle::contains const):
     38        * heap/MarkedBlockInlines.h:
     39        (JSC::MarkedBlock::Handle::specializedSweep):
     40        * heap/MarkedSpace.h:
     41        (JSC::MarkedSpace::forEachSubspace):
     42        * heap/SlotVisitor.cpp:
     43        (JSC::SlotVisitor::appendToMarkStack):
     44        (JSC::SlotVisitor::visitChildren):
     45        (JSC::SlotVisitor::reportZappedCellAndCrash):
     46        * heap/SlotVisitor.h:
     47        * jit/AssemblyHelpers.cpp:
     48        (JSC::AssemblyHelpers::emitAllocateWithNonNullAllocator):
     49        * runtime/VM.cpp:
     50        (JSC::VM::VM):
     51        * tools/JSDollarVM.cpp:
     52        (JSC::functionDumpSubspaceHashes):
     53        (JSC::JSDollarVM::finishCreation):
     54        * tools/VMInspector.cpp:
     55        (JSC::VMInspector::dumpSubspaceHashes):
     56        * tools/VMInspector.h:
     57
    1582019-07-25  Yusuke Suzuki  <ysuzuki@apple.com>
    259
  • trunk/Source/JavaScriptCore/heap/FreeList.h

    r240216 r247886  
    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

    r243667 r247886  
    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

    r247801 r247886  
    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

    r247854 r247886  
    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

    r233346 r247886  
    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

    r240216 r247886  
    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

    r247801 r247886  
    287287{
    288288    ASSERT(m_heap.isMarked(cell));
     289#if CPU(X86_64)
     290    if (UNLIKELY(cell->isZapped()))
     291        reportZappedCellAndCrash(cell);
     292#else
    289293    ASSERT(!cell->isZapped());
    290    
     294#endif
     295
    291296    container.noteMarked();
    292297   
     
    386391        // FIXME: This could be so much better.
    387392        // https://bugs.webkit.org/show_bug.cgi?id=162462
     393#if CPU(X86_64)
     394        Structure* structure = cell->structure(vm());
     395        if (LIKELY(structure)) {
     396            const MethodTable* methodTable = &structure->classInfo()->methodTable;
     397            methodTable->visitChildren(const_cast<JSCell*>(cell), *this);
     398            break;
     399        }
     400        reportZappedCellAndCrash(const_cast<JSCell*>(cell));
     401#else
    388402        cell->methodTable(vm())->visitChildren(const_cast<JSCell*>(cell), *this);
     403#endif
    389404        break;
    390405    }
     
    805820}
    806821
     822#if CPU(X86_64)
     823NEVER_INLINE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void SlotVisitor::reportZappedCellAndCrash(JSCell* cell)
     824{
     825    MarkedBlock::Handle* foundBlock = nullptr;
     826    uint32_t* cellWords = reinterpret_cast_ptr<uint32_t*>(this);
     827
     828    uintptr_t cellAddress = bitwise_cast<uintptr_t>(cell);
     829    uintptr_t headerWord = cellWords[1];
     830    uintptr_t zapReason = cellWords[2];
     831    unsigned subspaceHash = 0;
     832    size_t cellSize = 0;
     833
     834    // FIXME: This iteration may crash because the mutator may race against us
     835    // to add / remove blocks. That said, this should be rare and is not too
     836    // detrimental to the purpose of this function. We will crash imminently
     837    // anyway, and the most profitable crash info comes from the crash trace.
     838    // If the race does not crash this iteration (which should be the common
     839    // case), then we'll get additional info to debug the crash with. If the
     840    // race does crash this iteration, then we still have the crash trace to
     841    // work with.
     842    // https://bugs.webkit.org/show_bug.cgi?id=200183
     843    m_heap.objectSpace().forEachBlock([&] (MarkedBlock::Handle* block) {
     844        if (block->contains(cell)) {
     845            foundBlock = block;
     846            return IterationStatus::Done;
     847        }
     848        return IterationStatus::Continue;
     849    });
     850
     851    if (foundBlock) {
     852        subspaceHash = StringHasher::computeHash(foundBlock->subspace()->name());
     853        cellSize = foundBlock->cellSize();
     854    }
     855
     856    CRASH_WITH_INFO(cellAddress, headerWord, zapReason, subspaceHash, cellSize);
     857}
     858#endif // CPU(X86_64)
     859
    807860} // namespace JSC
  • trunk/Source/JavaScriptCore/heap/SlotVisitor.h

    r247801 r247886  
    226226    bool didReachTermination(const AbstractLocker&);
    227227
     228#if CPU(X86_64)
     229    NEVER_INLINE NO_RETURN_DUE_TO_CRASH NOT_TAIL_CALLED void reportZappedCellAndCrash(JSCell*);
     230#endif
     231
    228232    template<typename Func>
    229233    IterationStatus forEachMarkStack(const Func&);
  • trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp

    r243232 r247886  
    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/VM.cpp

    r246565 r247886  
    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

    r247832 r247886  
    11/*
    2  * Copyright (C) 2015-2018 Apple Inc. All rights reserved.
     2 * Copyright (C) 2015-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    13941394}
    13951395
     1396// Dumps the hashes of all subspaces currently registered with the VM.
     1397// Usage: $vm.dumpSubspaceHashes()
     1398static EncodedJSValue JSC_HOST_CALL functionDumpSubspaceHashes(ExecState* exec)
     1399{
     1400    VM& vm = exec->vm();
     1401    VMInspector::dumpSubspaceHashes(&vm);
     1402    return JSValue::encode(jsUndefined());
     1403}
     1404
    13961405// Gets a JSDollarVMCallFrame for a specified frame index.
    13971406// Usage: var callFrame = $vm.callFrame(0) // frame 0 is the top frame.
     
    22202229    addFunction(vm, "gc", functionGC, 0);
    22212230    addFunction(vm, "edenGC", functionEdenGC, 0);
     2231    addFunction(vm, "dumpSubspaceHashes", functionDumpSubspaceHashes, 0);
    22222232
    22232233    addFunction(vm, "callFrame", functionCallFrame, 1);
  • trunk/Source/JavaScriptCore/tools/VMInspector.cpp

    r235450 r247886  
    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

    r241923 r247886  
    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

    r247881 r247886  
     12019-07-26  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, Saam Barati, and Michael Saboff.
     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-07-26  Ryosuke Niwa  <rniwa@webkit.org>
    218
  • trunk/Source/WebCore/bindings/js/WebCoreJSClientData.cpp

    r243279 r247886  
    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.