WebKit Bugzilla
Attachment 346053 Details for
Bug 188157
: Add a debugging utility to dump the memory layout of a JSCell.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
proposed patch.
bug-188157.patch (text/plain), 12.77 KB, created by
Mark Lam
on 2018-07-30 00:34:33 PDT
(
hide
)
Description:
proposed patch.
Filename:
MIME Type:
Creator:
Mark Lam
Created:
2018-07-30 00:34:33 PDT
Size:
12.77 KB
patch
obsolete
>Index: Source/JavaScriptCore/ChangeLog >=================================================================== >--- Source/JavaScriptCore/ChangeLog (revision 234359) >+++ Source/JavaScriptCore/ChangeLog (working copy) >@@ -1,3 +1,86 @@ >+2018-07-30 Mark Lam <mark.lam@apple.com> >+ >+ Add a debugging utility to dump the memory layout of a JSCell. >+ https://bugs.webkit.org/show_bug.cgi?id=188157 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ This patch adds $vm.dumpCell() and VMInspector::dumpCellMemory() to allow us to >+ dump the memory contents of a cell and if present, its butterfly for debugging >+ purposes. >+ >+ Example usage for JS code when JSC_useDollarVM=true: >+ >+ $vm.dumpCell(obj); >+ >+ Example usage from C++ code or from lldb: >+ >+ (lldb) p JSC::VMInspector::dumpCellMemory(obj) >+ >+ Some examples of dumps: >+ >+ <0x104bc8260, Object> >+ [0] 0x104bc8260 : 0x010016000000016c header >+ structureID 364 0x16c structure 0x104b721b0 >+ indexingTypeAndMisc 0 0x0 NonArray >+ type 22 0x16 >+ flags 0 0x0 >+ cellState 1 >+ [1] 0x104bc8268 : 0x0000000000000000 butterfly >+ [2] 0x104bc8270 : 0xffff000000000007 >+ [3] 0x104bc8278 : 0xffff000000000008 >+ >+ <0x104bb4360, Array> >+ [0] 0x104bb4360 : 0x0108210b00000171 header >+ structureID 369 0x171 structure 0x104b723e0 >+ indexingTypeAndMisc 11 0xb ArrayWithArrayStorage >+ type 33 0x21 >+ flags 8 0x8 >+ cellState 1 >+ [1] 0x104bb4368 : 0x00000008000f4718 butterfly >+ base 0x8000f46e0 >+ hasIndexingHeader YES hasAnyArrayStorage YES >+ publicLength 4 vectorLength 7 indexBias 2 >+ preCapacity 2 propertyCapacity 4 >+ <--- preCapacity >+ [0] 0x8000f46e0 : 0x0000000000000000 >+ [1] 0x8000f46e8 : 0x0000000000000000 >+ <--- propertyCapacity >+ [2] 0x8000f46f0 : 0x0000000000000000 >+ [3] 0x8000f46f8 : 0x0000000000000000 >+ [4] 0x8000f4700 : 0xffff00000000000d >+ [5] 0x8000f4708 : 0xffff00000000000c >+ <--- indexingHeader >+ [6] 0x8000f4710 : 0x0000000700000004 >+ <--- butterfly >+ <--- arrayStorage >+ [7] 0x8000f4718 : 0x0000000000000000 >+ [8] 0x8000f4720 : 0x0000000400000002 >+ <--- indexedProperties >+ [9] 0x8000f4728 : 0xffff000000000008 >+ [10] 0x8000f4730 : 0xffff000000000009 >+ [11] 0x8000f4738 : 0xffff000000000005 >+ [12] 0x8000f4740 : 0xffff000000000006 >+ [13] 0x8000f4748 : 0x0000000000000000 >+ [14] 0x8000f4750 : 0x0000000000000000 >+ [15] 0x8000f4758 : 0x0000000000000000 >+ <--- unallocated capacity >+ [16] 0x8000f4760 : 0x0000000000000000 >+ [17] 0x8000f4768 : 0x0000000000000000 >+ [18] 0x8000f4770 : 0x0000000000000000 >+ [19] 0x8000f4778 : 0x0000000000000000 >+ >+ * runtime/JSObject.h: >+ * tools/JSDollarVM.cpp: >+ (JSC::functionDumpCell): >+ (JSC::JSDollarVM::finishCreation): >+ * tools/VMInspector.cpp: >+ (JSC::VMInspector::dumpCellMemory): >+ (JSC::IndentationScope::IndentationScope): >+ (JSC::IndentationScope::~IndentationScope): >+ (JSC::VMInspector::dumpCellMemoryToStream): >+ * tools/VMInspector.h: >+ > 2018-07-27 Mark Lam <mark.lam@apple.com> > > Add some crash info to Heap::checkConn() RELEASE_ASSERTs. >Index: Source/JavaScriptCore/runtime/JSObject.h >=================================================================== >--- Source/JavaScriptCore/runtime/JSObject.h (revision 234345) >+++ Source/JavaScriptCore/runtime/JSObject.h (working copy) >@@ -1014,7 +1014,8 @@ protected: > > private: > friend class LLIntOffsetsExtractor; >- >+ friend class VMInspector; >+ > // Nobody should ever ask any of these questions on something already known to be a JSObject. > using JSCell::isAPIValueWrapper; > using JSCell::isGetterSetter; >Index: Source/JavaScriptCore/tools/JSDollarVM.cpp >=================================================================== >--- Source/JavaScriptCore/tools/JSDollarVM.cpp (revision 234345) >+++ Source/JavaScriptCore/tools/JSDollarVM.cpp (working copy) >@@ -1488,6 +1488,18 @@ static EncodedJSValue JSC_HOST_CALL func > return JSValue::encode(jsUndefined()); > } > >+// Dumps the internal memory layout of a JSCell. >+// Usage: $vm.dumpCell(cell) >+static EncodedJSValue JSC_HOST_CALL functionDumpCell(ExecState* exec) >+{ >+ JSValue value = exec->argument(0); >+ if (!value.isCell()) >+ return encodedJSUndefined(); >+ >+ VMInspector::dumpCellMemory(value.asCell()); >+ return encodedJSUndefined(); >+} >+ > // Gets the dataLog dump of the indexingMode of the passed value. > // Usage: $vm.print("indexingMode = " + $vm.indexingMode(jsValue)) > static EncodedJSValue JSC_HOST_CALL functionIndexingMode(ExecState* exec) >@@ -1989,6 +2001,8 @@ void JSDollarVM::finishCreation(VM& vm) > addFunction(vm, "dumpCallFrame", functionDumpCallFrame, 0); > addFunction(vm, "dumpStack", functionDumpStack, 0); > >+ addFunction(vm, "dumpCell", functionDumpCell, 1); >+ > addFunction(vm, "indexingMode", functionIndexingMode, 1); > addFunction(vm, "inlineCapacity", functionInlineCapacity, 1); > addFunction(vm, "value", functionValue, 1); >Index: Source/JavaScriptCore/tools/VMInspector.cpp >=================================================================== >--- Source/JavaScriptCore/tools/VMInspector.cpp (revision 234345) >+++ Source/JavaScriptCore/tools/VMInspector.cpp (working copy) >@@ -30,6 +30,7 @@ > #include "CodeBlockSet.h" > #include "HeapInlines.h" > #include "HeapIterationScope.h" >+#include "JSCInlines.h" > #include "MachineContext.h" > #include "MarkedSpaceInlines.h" > #include "StackVisitor.h" >@@ -381,4 +382,157 @@ void VMInspector::dumpValue(JSValue valu > dataLog(value); > } > >+void VMInspector::dumpCellMemory(JSCell* cell) >+{ >+ dumpCellMemoryToStream(cell, WTF::dataFile()); >+} >+ >+class IndentationScope { >+public: >+ IndentationScope(unsigned& indentation) >+ : m_indentation(indentation) >+ { >+ ++m_indentation; >+ } >+ >+ ~IndentationScope() >+ { >+ --m_indentation; >+ } >+ >+private: >+ unsigned& m_indentation; >+}; >+ >+void VMInspector::dumpCellMemoryToStream(JSCell* cell, PrintStream& out) >+{ >+ VM& vm = *cell->vm(); >+ StructureID structureID = cell->structureID(); >+ Structure* structure = cell->structure(vm); >+ IndexingType indexingTypeAndMisc = cell->indexingTypeAndMisc(); >+ IndexingType indexingType = structure->indexingType(); >+ IndexingType indexingMode = structure->indexingMode(); >+ JSType type = cell->type(); >+ TypeInfo::InlineTypeFlags inlineTypeFlags = cell->inlineTypeFlags(); >+ CellState cellState = cell->cellState(); >+ size_t cellSize = cell->cellSize(); >+ size_t slotCount = cellSize / sizeof(EncodedJSValue); >+ >+ EncodedJSValue* slots = bitwise_cast<EncodedJSValue*>(cell); >+ unsigned indentation = 0; >+ >+ auto indent = [&] { >+ for (unsigned i = 0 ; i < indentation; ++i) >+ out.print(" "); >+ }; >+ >+#define INDENT indent(), >+ >+ auto dumpSlot = [&] (EncodedJSValue* slots, unsigned index, const char* label = nullptr) { >+ out.print("[", index, "] ", format("%p : 0x%016" PRIx64, &slots[index], slots[index])); >+ if (label) >+ out.print(" ", label); >+ out.print("\n"); >+ }; >+ >+ out.printf("<%p, %s>\n", cell, cell->className(vm)); >+ IndentationScope scope(indentation); >+ >+ INDENT dumpSlot(slots, 0, "header"); >+ { >+ IndentationScope scope(indentation); >+ INDENT out.println("structureID ", format("%d 0x%" PRIx32, structureID, structureID), " structure ", RawPointer(structure)); >+ INDENT out.println("indexingTypeAndMisc ", format("%d 0x%" PRIx8, indexingTypeAndMisc, indexingTypeAndMisc), " ", IndexingTypeDump(indexingMode)); >+ INDENT out.println("type ", format("%d 0x%" PRIx8, type, type)); >+ INDENT out.println("flags ", format("%d 0x%" PRIx8, inlineTypeFlags, inlineTypeFlags)); >+ INDENT out.println("cellState ", format("%d", cellState)); >+ } >+ >+ unsigned slotIndex = 1; >+ if (cell->isObject()) { >+ JSObject* obj = static_cast<JSObject*>(const_cast<JSCell*>(cell)); >+ Butterfly* butterfly = obj->butterfly(); >+ size_t butterflySize = obj->butterflyTotalSize(); >+ >+ INDENT dumpSlot(slots, slotIndex, "butterfly"); >+ slotIndex++; >+ >+ if (butterfly) { >+ IndentationScope scope(indentation); >+ >+ bool hasIndexingHeader = structure->hasIndexingHeader(cell); >+ bool hasAnyArrayStorage = JSC::hasAnyArrayStorage(indexingType); >+ >+ size_t preCapacity = obj->butterflyPreCapacity(); >+ size_t propertyCapacity = structure->outOfLineCapacity(); >+ >+ void* base = hasIndexingHeader >+ ? butterfly->base(preCapacity, propertyCapacity) >+ : butterfly->base(structure); >+ >+ unsigned publicLength = butterfly->publicLength(); >+ unsigned vectorLength = butterfly->vectorLength(); >+ size_t butterflyCellSize = MarkedSpace::optimalSizeFor(butterflySize); >+ >+ size_t endOfIndexedPropertiesIndex = butterflySize / sizeof(EncodedJSValue); >+ size_t endOfButterflyIndex = butterflyCellSize / sizeof(EncodedJSValue); >+ >+ INDENT out.println("base ", RawPointer(base)); >+ INDENT out.println("hasIndexingHeader ", (hasIndexingHeader ? "YES" : "NO"), " hasAnyArrayStorage ", (hasAnyArrayStorage ? "YES" : "NO")); >+ if (hasIndexingHeader) { >+ INDENT out.print("publicLength ", publicLength, " vectorLength ", vectorLength); >+ if (hasAnyArrayStorage) >+ out.print(" indexBias ", butterfly->arrayStorage()->m_indexBias); >+ out.print("\n"); >+ } >+ INDENT out.println("preCapacity ", preCapacity, " propertyCapacity ", propertyCapacity); >+ >+ unsigned index = 0; >+ EncodedJSValue* slots = reinterpret_cast<EncodedJSValue*>(base); >+ >+ auto asVoidPtr = [] (void* p) { >+ return p; >+ }; >+ >+ auto dumpSectionHeader = [&] (const char* name) { >+ out.println("<--- ", name); >+ }; >+ >+ auto dumpSection = [&] (unsigned startIndex, unsigned endIndex, const char* name) -> unsigned { >+ for (unsigned index = startIndex; index < endIndex; ++index) { >+ if (name && index == startIndex) >+ INDENT dumpSectionHeader(name); >+ INDENT dumpSlot(slots, index); >+ } >+ return endIndex; >+ }; >+ >+ { >+ IndentationScope scope(indentation); >+ >+ index = dumpSection(index, preCapacity, "preCapacity"); >+ index = dumpSection(index, preCapacity + propertyCapacity, "propertyCapacity"); >+ >+ if (hasIndexingHeader) >+ index = dumpSection(index, index + 1, "indexingHeader"); >+ >+ INDENT dumpSectionHeader("butterfly"); >+ if (hasAnyArrayStorage) { >+ RELEASE_ASSERT(asVoidPtr(butterfly->arrayStorage()) == asVoidPtr(&slots[index])); >+ RELEASE_ASSERT(ArrayStorage::vectorOffset() == 2 * sizeof(EncodedJSValue)); >+ index = dumpSection(index, index + 2, "arrayStorage"); >+ } >+ >+ index = dumpSection(index, endOfIndexedPropertiesIndex, "indexedProperties"); >+ index = dumpSection(index, endOfButterflyIndex, "unallocated capacity"); >+ } >+ } >+ } >+ >+ for (; slotIndex < slotCount; ++slotIndex) >+ INDENT dumpSlot(slots, slotIndex); >+ >+#undef INDENT >+} >+ > } // namespace JSC >Index: Source/JavaScriptCore/tools/VMInspector.h >=================================================================== >--- Source/JavaScriptCore/tools/VMInspector.h (revision 234345) >+++ Source/JavaScriptCore/tools/VMInspector.h (working copy) >@@ -72,6 +72,8 @@ public: > JS_EXPORT_PRIVATE static void dumpCallFrame(CallFrame*, unsigned framesToSkip = 0); > JS_EXPORT_PRIVATE static void dumpStack(CallFrame* topCallFrame, unsigned framesToSkip = 0); > JS_EXPORT_PRIVATE static void dumpValue(JSValue); >+ JS_EXPORT_PRIVATE static void dumpCellMemory(JSCell*); >+ JS_EXPORT_PRIVATE static void dumpCellMemoryToStream(JSCell*, PrintStream&); > > private: > template <typename Functor> void iterate(const Functor& functor)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
ysuzuki
:
review+
ews-watchlist
:
commit-queue-
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188157
: 346053