Changeset 96738 in webkit for trunk/Source/JavaScriptCore/heap
- Timestamp:
- Oct 5, 2011, 12:07:18 PM (14 years ago)
- Location:
- trunk/Source/JavaScriptCore/heap
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/heap/Heap.cpp
r96432 r96738 44 44 static const size_t largeHeapSize = 16 * 1024 * 1024; 45 45 static const size_t smallHeapSize = 512 * 1024; 46 47 #if ENABLE(GC_LOGGING) 48 49 struct GCTimer { 50 GCTimer(const char* name) 51 : m_time(0) 52 , m_min(100000000) 53 , m_max(0) 54 , m_count(0) 55 , m_name(name) 56 { 57 } 58 ~GCTimer() 59 { 60 printf("%s: %.2lfms (avg. %.2lf, min. %.2lf, max. %.2lf)\n", m_name, m_time * 1000, m_time * 1000 / m_count, m_min*1000, m_max*1000); 61 } 62 double m_time; 63 double m_min; 64 double m_max; 65 size_t m_count; 66 const char* m_name; 67 }; 68 69 struct GCTimerScope { 70 GCTimerScope(GCTimer* timer) 71 : m_timer(timer) 72 , m_start(WTF::currentTime()) 73 { 74 } 75 ~GCTimerScope() 76 { 77 double delta = WTF::currentTime() - m_start; 78 if (delta < m_timer->m_min) 79 m_timer->m_min = delta; 80 if (delta > m_timer->m_max) 81 m_timer->m_max = delta; 82 m_timer->m_count++; 83 m_timer->m_time += delta; 84 } 85 GCTimer* m_timer; 86 double m_start; 87 }; 88 89 #define GCPHASE(name) static GCTimer name##Timer(#name); GCTimerScope name##TimerScope(&name##Timer) 90 #define COND_GCPHASE(cond, name1, name2) static GCTimer name1##Timer(#name1); static GCTimer name2##Timer(#name2); GCTimerScope name1##CondTimerScope(cond ? &name1##Timer : &name2##Timer) 91 92 #else 93 94 #define GCPHASE(name) do { } while (false) 95 #define COND_GCPHASE(cond, name1, name2) do { } while (false) 96 97 #endif 46 98 47 99 static size_t heapSizeForHint(HeapSize heapSize) … … 457 509 void Heap::markRoots(bool fullGC) 458 510 { 511 COND_GCPHASE(fullGC, MarkFullRoots, MarkYoungRoots); 459 512 UNUSED_PARAM(fullGC); 460 513 ASSERT(isValidThreadState(m_globalData)); … … 468 521 // gathering uses the mark bits to determine whether a reference is valid. 469 522 ConservativeRoots machineThreadRoots(&m_objectSpace.blocks()); 470 m_machineThreads.gatherConservativeRoots(machineThreadRoots, &dummy); 523 { 524 GCPHASE(GatherConservativeRoots); 525 m_machineThreads.gatherConservativeRoots(machineThreadRoots, &dummy); 526 } 471 527 472 528 ConservativeRoots registerFileRoots(&m_objectSpace.blocks()); 473 529 m_jettisonedCodeBlocks.clearMarks(); 474 registerFile().gatherConservativeRoots(registerFileRoots, m_jettisonedCodeBlocks); 530 { 531 GCPHASE(GatherRegisterFileRoots); 532 registerFile().gatherConservativeRoots(registerFileRoots, m_jettisonedCodeBlocks); 533 } 475 534 m_jettisonedCodeBlocks.deleteUnmarkedCodeBlocks(); 476 535 #if ENABLE(GGC) 477 536 MarkedBlock::DirtyCellVector dirtyCells; 478 if (!fullGC) 537 if (!fullGC) { 538 GCPHASE(GatheringDirtyCells); 479 539 m_objectSpace.gatherDirtyCells(dirtyCells); 480 else540 } else 481 541 #endif 542 { 543 GCPHASE(clearMarks); 482 544 clearMarks(); 483 545 } 484 546 485 547 SlotVisitor& visitor = m_slotVisitor; … … 487 549 488 550 #if ENABLE(GGC) 489 size_t dirtyCellCount = dirtyCells.size(); 490 for (size_t i = 0; i < dirtyCellCount; i++) { 491 heapRootVisitor.visitChildren(dirtyCells[i]); 551 if (size_t dirtyCellCount = dirtyCells.size()) { 552 GCPHASE(VisitDirtyCells); 553 for (size_t i = 0; i < dirtyCellCount; i++) { 554 heapRootVisitor.visitChildren(dirtyCells[i]); 555 visitor.drain(); 556 } 557 } 558 #endif 559 560 { 561 GCPHASE(VisitMachineRoots); 562 visitor.append(machineThreadRoots); 492 563 visitor.drain(); 493 564 } 494 #endif 495 496 visitor.append(machineThreadRoots); 497 visitor.drain(); 498 499 visitor.append(registerFileRoots); 500 visitor.drain(); 501 502 markProtectedObjects(heapRootVisitor); 503 visitor.drain(); 504 505 markTempSortVectors(heapRootVisitor); 506 visitor.drain(); 507 508 if (m_markListSet && m_markListSet->size()) 509 MarkedArgumentBuffer::markLists(heapRootVisitor, *m_markListSet); 510 if (m_globalData->exception) 565 { 566 GCPHASE(VisitRegisterFileRoots); 567 visitor.append(registerFileRoots); 568 visitor.drain(); 569 } 570 { 571 GCPHASE(VisitProtectedObjects); 572 markProtectedObjects(heapRootVisitor); 573 visitor.drain(); 574 } 575 { 576 GCPHASE(VisitTempSortVectors); 577 markTempSortVectors(heapRootVisitor); 578 visitor.drain(); 579 } 580 581 { 582 GCPHASE(MarkingArgumentBuffers); 583 if (m_markListSet && m_markListSet->size()) { 584 MarkedArgumentBuffer::markLists(heapRootVisitor, *m_markListSet); 585 visitor.drain(); 586 } 587 } 588 if (m_globalData->exception) { 589 GCPHASE(MarkingException); 511 590 heapRootVisitor.visit(&m_globalData->exception); 512 visitor.drain(); 513 514 m_handleHeap.visitStrongHandles(heapRootVisitor); 515 visitor.drain(); 516 517 m_handleStack.visit(heapRootVisitor); 518 visitor.drain(); 519 520 m_jettisonedCodeBlocks.traceCodeBlocks(visitor); 521 visitor.drain(); 591 visitor.drain(); 592 } 593 594 { 595 GCPHASE(VisitStrongHandles); 596 m_handleHeap.visitStrongHandles(heapRootVisitor); 597 visitor.drain(); 598 } 599 600 { 601 GCPHASE(HandleStack); 602 m_handleStack.visit(heapRootVisitor); 603 visitor.drain(); 604 } 605 606 { 607 GCPHASE(TraceCodeBlocks); 608 m_jettisonedCodeBlocks.traceCodeBlocks(visitor); 609 visitor.drain(); 610 } 522 611 523 612 // Weak handles must be marked last, because their owners use the set of 524 613 // opaque roots to determine reachability. 525 int lastOpaqueRootCount; 526 do { 527 lastOpaqueRootCount = visitor.opaqueRootCount(); 528 m_handleHeap.visitWeakHandles(heapRootVisitor); 529 visitor.drain(); 530 // If the set of opaque roots has grown, more weak handles may have become reachable. 531 } while (lastOpaqueRootCount != visitor.opaqueRootCount()); 532 614 { 615 GCPHASE(VisitingWeakHandles); 616 int lastOpaqueRootCount; 617 do { 618 lastOpaqueRootCount = visitor.opaqueRootCount(); 619 m_handleHeap.visitWeakHandles(heapRootVisitor); 620 visitor.drain(); 621 // If the set of opaque roots has grown, more weak handles may have become reachable. 622 } while (lastOpaqueRootCount != visitor.opaqueRootCount()); 623 } 533 624 visitor.reset(); 534 625 … … 598 689 void Heap::collect(SweepToggle sweepToggle) 599 690 { 691 GCPHASE(Collect); 600 692 ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); 601 693 ASSERT(m_isSafeToCollect); 602 694 JAVASCRIPTCORE_GC_BEGIN(); 695 #if ENABLE(GGC) 603 696 bool fullGC = sweepToggle == DoSweep; 604 697 if (!fullGC) 605 698 fullGC = (capacity() > 4 * m_lastFullGCSize); 606 canonicalizeCellLivenessData(); 699 #else 700 bool fullGC = true; 701 #endif 702 { 703 GCPHASE(Canonicalize); 704 canonicalizeCellLivenessData(); 705 } 607 706 608 707 markRoots(fullGC); 609 708 610 harvestWeakReferences(); 611 m_handleHeap.finalizeWeakHandles(); 612 m_globalData->smallStrings.finalizeSmallStrings(); 709 { 710 GCPHASE(HarvestWeakReferences); 711 harvestWeakReferences(); 712 m_handleHeap.finalizeWeakHandles(); 713 m_globalData->smallStrings.finalizeSmallStrings(); 714 } 613 715 614 716 JAVASCRIPTCORE_GC_MARKED(); 615 616 resetAllocator(); 717 718 { 719 GCPHASE(ResetAllocator); 720 resetAllocator(); 721 } 617 722 618 723 if (sweepToggle == DoSweep) { 724 GCPHASE(Sweeping); 619 725 sweep(); 620 726 shrink(); … … 625 731 // proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size : 626 732 // new bytes allocated) proportion, and seems to work well in benchmarks. 627 size_t proportionalBytes = 2 * size(); 628 if (fullGC) 629 m_lastFullGCSize = proportionalBytes / 2; 630 631 m_objectSpace.setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle)); 733 size_t newSize = size(); 734 size_t proportionalBytes = 2 * newSize; 735 if (fullGC) { 736 m_lastFullGCSize = newSize; 737 m_objectSpace.setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle)); 738 } 632 739 JAVASCRIPTCORE_GC_END(); 633 740 -
trunk/Source/JavaScriptCore/heap/MarkedBlock.h
r96372 r96738 70 70 // object the heap will commonly allocate is four words. 71 71 static const size_t atomSize = 4 * sizeof(void*); 72 static const size_t atomShift = 5; 72 73 static const size_t blockSize = 16 * KB; 73 74 static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two. 74 75 75 76 static const size_t atomsPerBlock = blockSize / atomSize; // ~0.4% overhead 77 static const size_t atomMask = atomsPerBlock - 1; 76 78 static const int cardShift = 10; // This is log2 of bytes per card. 77 79 static const size_t bytesPerCard = 1 << cardShift; … … 140 142 { 141 143 return OBJECT_OFFSETOF(MarkedBlock, m_cards); 144 } 145 146 static inline size_t offsetOfMarks() 147 { 148 return OBJECT_OFFSETOF(MarkedBlock, m_marks); 142 149 } 143 150 … … 312 319 void MarkedBlock::gatherDirtyCells(DirtyCellVector& dirtyCells) 313 320 { 314 COMPILE_ASSERT( m_cards.cardCount ==cardCount, MarkedBlockCardCountsMatch);321 COMPILE_ASSERT((int)m_cards.cardCount == (int)cardCount, MarkedBlockCardCountsMatch); 315 322 316 323 ASSERT(m_state != New && m_state != FreeListed);
Note:
See TracChangeset
for help on using the changeset viewer.