Changeset 234363 in webkit
- Timestamp:
- Jul 30, 2018 7:46:25 AM (6 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r234335 r234363 1 2018-07-30 Mark Lam <mark.lam@apple.com> 2 3 Add a debugging utility to dump the memory layout of a JSCell. 4 https://bugs.webkit.org/show_bug.cgi?id=188157 5 6 Reviewed by Yusuke Suzuki. 7 8 This patch adds $vm.dumpCell() and VMInspector::dumpCellMemory() to allow us to 9 dump the memory contents of a cell and if present, its butterfly for debugging 10 purposes. 11 12 Example usage for JS code when JSC_useDollarVM=true: 13 14 $vm.dumpCell(obj); 15 16 Example usage from C++ code or from lldb: 17 18 (lldb) p JSC::VMInspector::dumpCellMemory(obj) 19 20 Some examples of dumps: 21 22 <0x104bc8260, Object> 23 [0] 0x104bc8260 : 0x010016000000016c header 24 structureID 364 0x16c structure 0x104b721b0 25 indexingTypeAndMisc 0 0x0 NonArray 26 type 22 0x16 27 flags 0 0x0 28 cellState 1 29 [1] 0x104bc8268 : 0x0000000000000000 butterfly 30 [2] 0x104bc8270 : 0xffff000000000007 31 [3] 0x104bc8278 : 0xffff000000000008 32 33 <0x104bb4360, Array> 34 [0] 0x104bb4360 : 0x0108210b00000171 header 35 structureID 369 0x171 structure 0x104b723e0 36 indexingTypeAndMisc 11 0xb ArrayWithArrayStorage 37 type 33 0x21 38 flags 8 0x8 39 cellState 1 40 [1] 0x104bb4368 : 0x00000008000f4718 butterfly 41 base 0x8000f46e0 42 hasIndexingHeader YES hasAnyArrayStorage YES 43 publicLength 4 vectorLength 7 indexBias 2 44 preCapacity 2 propertyCapacity 4 45 <--- preCapacity 46 [0] 0x8000f46e0 : 0x0000000000000000 47 [1] 0x8000f46e8 : 0x0000000000000000 48 <--- propertyCapacity 49 [2] 0x8000f46f0 : 0x0000000000000000 50 [3] 0x8000f46f8 : 0x0000000000000000 51 [4] 0x8000f4700 : 0xffff00000000000d 52 [5] 0x8000f4708 : 0xffff00000000000c 53 <--- indexingHeader 54 [6] 0x8000f4710 : 0x0000000700000004 55 <--- butterfly 56 <--- arrayStorage 57 [7] 0x8000f4718 : 0x0000000000000000 58 [8] 0x8000f4720 : 0x0000000400000002 59 <--- indexedProperties 60 [9] 0x8000f4728 : 0xffff000000000008 61 [10] 0x8000f4730 : 0xffff000000000009 62 [11] 0x8000f4738 : 0xffff000000000005 63 [12] 0x8000f4740 : 0xffff000000000006 64 [13] 0x8000f4748 : 0x0000000000000000 65 [14] 0x8000f4750 : 0x0000000000000000 66 [15] 0x8000f4758 : 0x0000000000000000 67 <--- unallocated capacity 68 [16] 0x8000f4760 : 0x0000000000000000 69 [17] 0x8000f4768 : 0x0000000000000000 70 [18] 0x8000f4770 : 0x0000000000000000 71 [19] 0x8000f4778 : 0x0000000000000000 72 73 * runtime/JSObject.h: 74 * tools/JSDollarVM.cpp: 75 (JSC::functionDumpCell): 76 (JSC::JSDollarVM::finishCreation): 77 * tools/VMInspector.cpp: 78 (JSC::VMInspector::dumpCellMemory): 79 (JSC::IndentationScope::IndentationScope): 80 (JSC::IndentationScope::~IndentationScope): 81 (JSC::VMInspector::dumpCellMemoryToStream): 82 * tools/VMInspector.h: 83 1 84 2018-07-27 Mark Lam <mark.lam@apple.com> 2 85 -
trunk/Source/JavaScriptCore/runtime/JSObject.h
r234089 r234363 1015 1015 private: 1016 1016 friend class LLIntOffsetsExtractor; 1017 1017 friend class VMInspector; 1018 1018 1019 // Nobody should ever ask any of these questions on something already known to be a JSObject. 1019 1020 using JSCell::isAPIValueWrapper; -
trunk/Source/JavaScriptCore/tools/JSDollarVM.cpp
r233285 r234363 1489 1489 } 1490 1490 1491 // Dumps the internal memory layout of a JSCell. 1492 // Usage: $vm.dumpCell(cell) 1493 static EncodedJSValue JSC_HOST_CALL functionDumpCell(ExecState* exec) 1494 { 1495 JSValue value = exec->argument(0); 1496 if (!value.isCell()) 1497 return encodedJSUndefined(); 1498 1499 VMInspector::dumpCellMemory(value.asCell()); 1500 return encodedJSUndefined(); 1501 } 1502 1491 1503 // Gets the dataLog dump of the indexingMode of the passed value. 1492 1504 // Usage: $vm.print("indexingMode = " + $vm.indexingMode(jsValue)) … … 1990 2002 addFunction(vm, "dumpStack", functionDumpStack, 0); 1991 2003 2004 addFunction(vm, "dumpCell", functionDumpCell, 1); 2005 1992 2006 addFunction(vm, "indexingMode", functionIndexingMode, 1); 1993 2007 addFunction(vm, "inlineCapacity", functionInlineCapacity, 1); -
trunk/Source/JavaScriptCore/tools/VMInspector.cpp
r233285 r234363 31 31 #include "HeapInlines.h" 32 32 #include "HeapIterationScope.h" 33 #include "JSCInlines.h" 33 34 #include "MachineContext.h" 34 35 #include "MarkedSpaceInlines.h" … … 382 383 } 383 384 385 void VMInspector::dumpCellMemory(JSCell* cell) 386 { 387 dumpCellMemoryToStream(cell, WTF::dataFile()); 388 } 389 390 class IndentationScope { 391 public: 392 IndentationScope(unsigned& indentation) 393 : m_indentation(indentation) 394 { 395 ++m_indentation; 396 } 397 398 ~IndentationScope() 399 { 400 --m_indentation; 401 } 402 403 private: 404 unsigned& m_indentation; 405 }; 406 407 void VMInspector::dumpCellMemoryToStream(JSCell* cell, PrintStream& out) 408 { 409 VM& vm = *cell->vm(); 410 StructureID structureID = cell->structureID(); 411 Structure* structure = cell->structure(vm); 412 IndexingType indexingTypeAndMisc = cell->indexingTypeAndMisc(); 413 IndexingType indexingType = structure->indexingType(); 414 IndexingType indexingMode = structure->indexingMode(); 415 JSType type = cell->type(); 416 TypeInfo::InlineTypeFlags inlineTypeFlags = cell->inlineTypeFlags(); 417 CellState cellState = cell->cellState(); 418 size_t cellSize = cell->cellSize(); 419 size_t slotCount = cellSize / sizeof(EncodedJSValue); 420 421 EncodedJSValue* slots = bitwise_cast<EncodedJSValue*>(cell); 422 unsigned indentation = 0; 423 424 auto indent = [&] { 425 for (unsigned i = 0 ; i < indentation; ++i) 426 out.print(" "); 427 }; 428 429 #define INDENT indent(), 430 431 auto dumpSlot = [&] (EncodedJSValue* slots, unsigned index, const char* label = nullptr) { 432 out.print("[", index, "] ", format("%p : 0x%016" PRIx64, &slots[index], slots[index])); 433 if (label) 434 out.print(" ", label); 435 out.print("\n"); 436 }; 437 438 out.printf("<%p, %s>\n", cell, cell->className(vm)); 439 IndentationScope scope(indentation); 440 441 INDENT dumpSlot(slots, 0, "header"); 442 { 443 IndentationScope scope(indentation); 444 INDENT out.println("structureID ", format("%d 0x%" PRIx32, structureID, structureID), " structure ", RawPointer(structure)); 445 INDENT out.println("indexingTypeAndMisc ", format("%d 0x%" PRIx8, indexingTypeAndMisc, indexingTypeAndMisc), " ", IndexingTypeDump(indexingMode)); 446 INDENT out.println("type ", format("%d 0x%" PRIx8, type, type)); 447 INDENT out.println("flags ", format("%d 0x%" PRIx8, inlineTypeFlags, inlineTypeFlags)); 448 INDENT out.println("cellState ", format("%d", cellState)); 449 } 450 451 unsigned slotIndex = 1; 452 if (cell->isObject()) { 453 JSObject* obj = static_cast<JSObject*>(const_cast<JSCell*>(cell)); 454 Butterfly* butterfly = obj->butterfly(); 455 size_t butterflySize = obj->butterflyTotalSize(); 456 457 INDENT dumpSlot(slots, slotIndex, "butterfly"); 458 slotIndex++; 459 460 if (butterfly) { 461 IndentationScope scope(indentation); 462 463 bool hasIndexingHeader = structure->hasIndexingHeader(cell); 464 bool hasAnyArrayStorage = JSC::hasAnyArrayStorage(indexingType); 465 466 size_t preCapacity = obj->butterflyPreCapacity(); 467 size_t propertyCapacity = structure->outOfLineCapacity(); 468 469 void* base = hasIndexingHeader 470 ? butterfly->base(preCapacity, propertyCapacity) 471 : butterfly->base(structure); 472 473 unsigned publicLength = butterfly->publicLength(); 474 unsigned vectorLength = butterfly->vectorLength(); 475 size_t butterflyCellSize = MarkedSpace::optimalSizeFor(butterflySize); 476 477 size_t endOfIndexedPropertiesIndex = butterflySize / sizeof(EncodedJSValue); 478 size_t endOfButterflyIndex = butterflyCellSize / sizeof(EncodedJSValue); 479 480 INDENT out.println("base ", RawPointer(base)); 481 INDENT out.println("hasIndexingHeader ", (hasIndexingHeader ? "YES" : "NO"), " hasAnyArrayStorage ", (hasAnyArrayStorage ? "YES" : "NO")); 482 if (hasIndexingHeader) { 483 INDENT out.print("publicLength ", publicLength, " vectorLength ", vectorLength); 484 if (hasAnyArrayStorage) 485 out.print(" indexBias ", butterfly->arrayStorage()->m_indexBias); 486 out.print("\n"); 487 } 488 INDENT out.println("preCapacity ", preCapacity, " propertyCapacity ", propertyCapacity); 489 490 unsigned index = 0; 491 EncodedJSValue* slots = reinterpret_cast<EncodedJSValue*>(base); 492 493 auto asVoidPtr = [] (void* p) { 494 return p; 495 }; 496 497 auto dumpSectionHeader = [&] (const char* name) { 498 out.println("<--- ", name); 499 }; 500 501 auto dumpSection = [&] (unsigned startIndex, unsigned endIndex, const char* name) -> unsigned { 502 for (unsigned index = startIndex; index < endIndex; ++index) { 503 if (name && index == startIndex) 504 INDENT dumpSectionHeader(name); 505 INDENT dumpSlot(slots, index); 506 } 507 return endIndex; 508 }; 509 510 { 511 IndentationScope scope(indentation); 512 513 index = dumpSection(index, preCapacity, "preCapacity"); 514 index = dumpSection(index, preCapacity + propertyCapacity, "propertyCapacity"); 515 516 if (hasIndexingHeader) 517 index = dumpSection(index, index + 1, "indexingHeader"); 518 519 INDENT dumpSectionHeader("butterfly"); 520 if (hasAnyArrayStorage) { 521 RELEASE_ASSERT(asVoidPtr(butterfly->arrayStorage()) == asVoidPtr(&slots[index])); 522 RELEASE_ASSERT(ArrayStorage::vectorOffset() == 2 * sizeof(EncodedJSValue)); 523 index = dumpSection(index, index + 2, "arrayStorage"); 524 } 525 526 index = dumpSection(index, endOfIndexedPropertiesIndex, "indexedProperties"); 527 index = dumpSection(index, endOfButterflyIndex, "unallocated capacity"); 528 } 529 } 530 } 531 532 for (; slotIndex < slotCount; ++slotIndex) 533 INDENT dumpSlot(slots, slotIndex); 534 535 #undef INDENT 536 } 537 384 538 } // namespace JSC -
trunk/Source/JavaScriptCore/tools/VMInspector.h
r233285 r234363 73 73 JS_EXPORT_PRIVATE static void dumpStack(CallFrame* topCallFrame, unsigned framesToSkip = 0); 74 74 JS_EXPORT_PRIVATE static void dumpValue(JSValue); 75 JS_EXPORT_PRIVATE static void dumpCellMemory(JSCell*); 76 JS_EXPORT_PRIVATE static void dumpCellMemoryToStream(JSCell*, PrintStream&); 75 77 76 78 private:
Note: See TracChangeset
for help on using the changeset viewer.