Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: third_party/WebKit/Source/platform/heap/HeapPage.h

Issue 1477023003: Refactor the Heap into ThreadHeap to prepare for per thread heaps Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 #endif 118 #endif
119 119
120 #if !ENABLE(ASSERT) && CPU(64BIT) 120 #if !ENABLE(ASSERT) && CPU(64BIT)
121 #define USE_4BYTE_HEADER_PADDING 1 121 #define USE_4BYTE_HEADER_PADDING 1
122 #else 122 #else
123 #define USE_4BYTE_HEADER_PADDING 0 123 #define USE_4BYTE_HEADER_PADDING 0
124 #endif 124 #endif
125 125
126 class CallbackStack; 126 class CallbackStack;
127 class FreePagePool; 127 class FreePagePool;
128 class NormalPageHeap; 128 class NormalPageArena;
129 class OrphanedPagePool; 129 class OrphanedPagePool;
130 class PageMemory; 130 class PageMemory;
131 class PageMemoryRegion; 131 class PageMemoryRegion;
132 class WebMemoryAllocatorDump; 132 class WebMemoryAllocatorDump;
133 133
134 // HeapObjectHeader is 4 byte (32 bit) that has the following layout: 134 // HeapObjectHeader is 4 byte (32 bit) that has the following layout:
135 // 135 //
136 // | gcInfoIndex (14 bit) | DOM mark bit (1 bit) | size (14 bit) | dead bit (1 b it) | freed bit (1 bit) | mark bit (1 bit) | 136 // | gcInfoIndex (14 bit) | DOM mark bit (1 bit) | size (14 bit) | dead bit (1 b it) | freed bit (1 bit) | mark bit (1 bit) |
137 // 137 //
138 // - For non-large objects, 14 bit is enough for |size| because the blink 138 // - For non-large objects, 14 bit is enough for |size| because the blink
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 // 345 //
346 // - LargeObjectPage is a page that contains only one object. The object size 346 // - LargeObjectPage is a page that contains only one object. The object size
347 // is arbitrary. An object whose size is larger than |blinkPageSize| is stored 347 // is arbitrary. An object whose size is larger than |blinkPageSize| is stored
348 // as a single project in LargeObjectPage. 348 // as a single project in LargeObjectPage.
349 // 349 //
350 // Note: An object whose size is between |largeObjectSizeThreshold| and 350 // Note: An object whose size is between |largeObjectSizeThreshold| and
351 // |blinkPageSize| can go to either of NormalPage or LargeObjectPage. 351 // |blinkPageSize| can go to either of NormalPage or LargeObjectPage.
352 class BasePage { 352 class BasePage {
353 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); 353 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
354 public: 354 public:
355 BasePage(PageMemory*, BaseHeap*); 355 BasePage(PageMemory*, BaseArena*);
356 virtual ~BasePage() { } 356 virtual ~BasePage() { }
357 357
358 void link(BasePage** previousNext) 358 void link(BasePage** previousNext)
359 { 359 {
360 m_next = *previousNext; 360 m_next = *previousNext;
361 *previousNext = this; 361 *previousNext = this;
362 } 362 }
363 void unlink(BasePage** previousNext) 363 void unlink(BasePage** previousNext)
364 { 364 {
365 *previousNext = m_next; 365 *previousNext = m_next;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 401
402 virtual void takeSnapshot(WebMemoryAllocatorDump*, ThreadState::GCSnapshotIn fo&, HeapSnapshotInfo&) = 0; 402 virtual void takeSnapshot(WebMemoryAllocatorDump*, ThreadState::GCSnapshotIn fo&, HeapSnapshotInfo&) = 0;
403 #if ENABLE(ASSERT) 403 #if ENABLE(ASSERT)
404 virtual bool contains(Address) = 0; 404 virtual bool contains(Address) = 0;
405 #endif 405 #endif
406 virtual size_t size() = 0; 406 virtual size_t size() = 0;
407 virtual bool isLargeObjectPage() { return false; } 407 virtual bool isLargeObjectPage() { return false; }
408 408
409 Address address() { return reinterpret_cast<Address>(this); } 409 Address address() { return reinterpret_cast<Address>(this); }
410 PageMemory* storage() const { return m_storage; } 410 PageMemory* storage() const { return m_storage; }
411 BaseHeap* heap() const { return m_heap; } 411 BaseArena* arena() const { return m_arena; }
412 bool orphaned() { return !m_heap; } 412 bool orphaned() { return !m_arena; }
413 bool terminating() { return m_terminating; } 413 bool terminating() { return m_terminating; }
414 void setTerminating() { m_terminating = true; } 414 void setTerminating() { m_terminating = true; }
415 415
416 // Returns true if this page has been swept by the ongoing lazy sweep. 416 // Returns true if this page has been swept by the ongoing lazy sweep.
417 bool hasBeenSwept() const { return m_swept; } 417 bool hasBeenSwept() const { return m_swept; }
418 418
419 void markAsSwept() 419 void markAsSwept()
420 { 420 {
421 ASSERT(!m_swept); 421 ASSERT(!m_swept);
422 m_swept = true; 422 m_swept = true;
423 } 423 }
424 424
425 void markAsUnswept() 425 void markAsUnswept()
426 { 426 {
427 ASSERT(m_swept); 427 ASSERT(m_swept);
428 m_swept = false; 428 m_swept = false;
429 } 429 }
430 430
431 private: 431 private:
432 PageMemory* m_storage; 432 PageMemory* m_storage;
433 BaseHeap* m_heap; 433 BaseArena* m_arena;
434 BasePage* m_next; 434 BasePage* m_next;
435 // Whether the page is part of a terminating thread or not. 435 // Whether the page is part of a terminating thread or not.
436 bool m_terminating; 436 bool m_terminating;
437 437
438 // Track the sweeping state of a page. Set to true once 438 // Track the sweeping state of a page. Set to true once
439 // the lazy sweep completes has processed it. 439 // the lazy sweep completes has processed it.
440 // 440 //
441 // Set to false at the start of a sweep, true upon completion 441 // Set to false at the start of a sweep, true upon completion
442 // of lazy sweeping. 442 // of lazy sweeping.
443 bool m_swept; 443 bool m_swept;
444 friend class BaseHeap; 444 friend class BaseArena;
445 }; 445 };
446 446
447 class NormalPage final : public BasePage { 447 class NormalPage final : public BasePage {
448 public: 448 public:
449 NormalPage(PageMemory*, BaseHeap*); 449 NormalPage(PageMemory*, BaseArena*);
450 450
451 Address payload() 451 Address payload()
452 { 452 {
453 return address() + pageHeaderSize(); 453 return address() + pageHeaderSize();
454 } 454 }
455 size_t payloadSize() 455 size_t payloadSize()
456 { 456 {
457 return (blinkPagePayloadSize() - pageHeaderSize()) & ~allocationMask; 457 return (blinkPagePayloadSize() - pageHeaderSize()) & ~allocationMask;
458 } 458 }
459 Address payloadEnd() { return payload() + payloadSize(); } 459 Address payloadEnd() { return payload() + payloadSize(); }
(...skipping 25 matching lines...) Expand all
485 size_t size() override { return blinkPageSize; } 485 size_t size() override { return blinkPageSize; }
486 static size_t pageHeaderSize() 486 static size_t pageHeaderSize()
487 { 487 {
488 // Compute the amount of padding we have to add to a header to make 488 // Compute the amount of padding we have to add to a header to make
489 // the size of the header plus the padding a multiple of 8 bytes. 489 // the size of the header plus the padding a multiple of 8 bytes.
490 size_t paddingSize = (sizeof(NormalPage) + allocationGranularity - (size of(HeapObjectHeader) % allocationGranularity)) % allocationGranularity; 490 size_t paddingSize = (sizeof(NormalPage) + allocationGranularity - (size of(HeapObjectHeader) % allocationGranularity)) % allocationGranularity;
491 return sizeof(NormalPage) + paddingSize; 491 return sizeof(NormalPage) + paddingSize;
492 } 492 }
493 493
494 494
495 NormalPageHeap* heapForNormalPage(); 495 NormalPageArena* heapForNormalPage();
496 496
497 private: 497 private:
498 HeapObjectHeader* findHeaderFromAddress(Address); 498 HeapObjectHeader* findHeaderFromAddress(Address);
499 void populateObjectStartBitMap(); 499 void populateObjectStartBitMap();
500 500
501 bool m_objectStartBitMapComputed; 501 bool m_objectStartBitMapComputed;
502 uint8_t m_objectStartBitMap[reservedForObjectBitMap]; 502 uint8_t m_objectStartBitMap[reservedForObjectBitMap];
503 }; 503 };
504 504
505 // Large allocations are allocated as separate objects and linked in a list. 505 // Large allocations are allocated as separate objects and linked in a list.
506 // 506 //
507 // In order to use the same memory allocation routines for everything allocated 507 // In order to use the same memory allocation routines for everything allocated
508 // in the heap, large objects are considered heap pages containing only one 508 // in the heap, large objects are considered heap pages containing only one
509 // object. 509 // object.
510 class LargeObjectPage final : public BasePage { 510 class LargeObjectPage final : public BasePage {
511 public: 511 public:
512 LargeObjectPage(PageMemory*, BaseHeap*, size_t); 512 LargeObjectPage(PageMemory*, BaseArena*, size_t);
513 513
514 Address payload() { return heapObjectHeader()->payload(); } 514 Address payload() { return heapObjectHeader()->payload(); }
515 size_t payloadSize() { return m_payloadSize; } 515 size_t payloadSize() { return m_payloadSize; }
516 Address payloadEnd() { return payload() + payloadSize(); } 516 Address payloadEnd() { return payload() + payloadSize(); }
517 bool containedInObjectPayload(Address address) 517 bool containedInObjectPayload(Address address)
518 { 518 {
519 return payload() <= address && address < payloadEnd(); 519 return payload() <= address && address < payloadEnd();
520 } 520 }
521 521
522 size_t objectPayloadSizeForTesting() override; 522 size_t objectPayloadSizeForTesting() override;
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 static void zapFreedMemory(Address, size_t); 639 static void zapFreedMemory(Address, size_t);
640 static void checkFreedMemoryIsZapped(Address, size_t); 640 static void checkFreedMemoryIsZapped(Address, size_t);
641 #endif 641 #endif
642 642
643 private: 643 private:
644 int m_biggestFreeListIndex; 644 int m_biggestFreeListIndex;
645 645
646 // All FreeListEntries in the nth list have size >= 2^n. 646 // All FreeListEntries in the nth list have size >= 2^n.
647 FreeListEntry* m_freeLists[blinkPageSizeLog2]; 647 FreeListEntry* m_freeLists[blinkPageSizeLog2];
648 648
649 friend class NormalPageHeap; 649 friend class NormalPageArena;
650 }; 650 };
651 651
652 // Each thread has a number of thread heaps (e.g., Generic heaps, 652 // Each thread has a number of thread heaps (e.g., Generic heaps,
653 // typed heaps for Node, heaps for collection backings etc) 653 // typed heaps for Node, heaps for collection backings etc)
654 // and BaseHeap represents each thread heap. 654 // and BaseArena represents each thread heap.
655 // 655 //
656 // BaseHeap is a parent class of NormalPageHeap and LargeObjectHeap. 656 // BaseArena is a parent class of NormalPageArena and LargeObjectArena.
657 // NormalPageHeap represents a heap that contains NormalPages 657 // NormalPageArena represents a heap that contains NormalPages
658 // and LargeObjectHeap represents a heap that contains LargeObjectPages. 658 // and LargeObjectArena represents a heap that contains LargeObjectPages.
659 class PLATFORM_EXPORT BaseHeap { 659 class PLATFORM_EXPORT BaseArena {
660 USING_FAST_MALLOC(BaseHeap); 660 USING_FAST_MALLOC(BaseArena);
661 public: 661 public:
662 BaseHeap(ThreadState*, int); 662 BaseArena(ThreadState*, int);
663 virtual ~BaseHeap(); 663 virtual ~BaseArena();
664 void cleanupPages(); 664 void cleanupPages();
665 665
666 void takeSnapshot(const String& dumpBaseName, ThreadState::GCSnapshotInfo&); 666 void takeSnapshot(const String& dumpBaseName, ThreadState::GCSnapshotInfo&);
667 #if ENABLE(ASSERT) 667 #if ENABLE(ASSERT)
668 BasePage* findPageFromAddress(Address); 668 BasePage* findPageFromAddress(Address);
669 #endif 669 #endif
670 virtual void takeFreelistSnapshot(const String& dumpBaseName) { } 670 virtual void takeFreelistSnapshot(const String& dumpBaseName) { }
671 virtual void clearFreeLists() { } 671 virtual void clearFreeLists() { }
672 void makeConsistentForGC(); 672 void makeConsistentForGC();
673 void makeConsistentForMutator(); 673 void makeConsistentForMutator();
674 #if ENABLE(ASSERT) 674 #if ENABLE(ASSERT)
675 virtual bool isConsistentForGC() = 0; 675 virtual bool isConsistentForGC() = 0;
676 #endif 676 #endif
677 size_t objectPayloadSizeForTesting(); 677 size_t objectPayloadSizeForTesting();
678 void prepareHeapForTermination(); 678 void prepareHeapForTermination();
679 void prepareForSweep(); 679 void prepareForSweep();
680 #if defined(ADDRESS_SANITIZER) 680 #if defined(ADDRESS_SANITIZER)
681 void poisonHeap(BlinkGC::ObjectsToPoison, BlinkGC::Poisoning); 681 void poisonHeap(BlinkGC::ObjectsToPoison, BlinkGC::Poisoning);
682 #endif 682 #endif
683 Address lazySweep(size_t, size_t gcInfoIndex); 683 Address lazySweep(size_t, size_t gcInfoIndex);
684 void sweepUnsweptPage(); 684 void sweepUnsweptPage();
685 // Returns true if we have swept all pages within the deadline. 685 // Returns true if we have swept all pages within the deadline.
686 // Returns false otherwise. 686 // Returns false otherwise.
687 bool lazySweepWithDeadline(double deadlineSeconds); 687 bool lazySweepWithDeadline(double deadlineSeconds);
688 void completeSweep(); 688 void completeSweep();
689 689
690 ThreadState* threadState() { return m_threadState; } 690 ThreadState* threadState() { return m_threadState; }
691 int heapIndex() const { return m_index; } 691 int arenaIndex() const { return m_index; }
692 692
693 protected: 693 protected:
694 BasePage* m_firstPage; 694 BasePage* m_firstPage;
695 BasePage* m_firstUnsweptPage; 695 BasePage* m_firstUnsweptPage;
696 696
697 private: 697 private:
698 virtual Address lazySweepPages(size_t, size_t gcInfoIndex) = 0; 698 virtual Address lazySweepPages(size_t, size_t gcInfoIndex) = 0;
699 699
700 ThreadState* m_threadState; 700 ThreadState* m_threadState;
701 701
702 // Index into the page pools. This is used to ensure that the pages of the 702 // Index into the page pools. This is used to ensure that the pages of the
703 // same type go into the correct page pool and thus avoid type confusion. 703 // same type go into the correct page pool and thus avoid type confusion.
704 int m_index; 704 int m_index;
705 }; 705 };
706 706
707 class PLATFORM_EXPORT NormalPageHeap final : public BaseHeap { 707 class PLATFORM_EXPORT NormalPageArena final : public BaseArena {
708 public: 708 public:
709 NormalPageHeap(ThreadState*, int); 709 NormalPageArena(ThreadState*, int);
710 void addToFreeList(Address address, size_t size) 710 void addToFreeList(Address address, size_t size)
711 { 711 {
712 ASSERT(findPageFromAddress(address)); 712 ASSERT(findPageFromAddress(address));
713 ASSERT(findPageFromAddress(address + size - 1)); 713 ASSERT(findPageFromAddress(address + size - 1));
714 m_freeList.addToFreeList(address, size); 714 m_freeList.addToFreeList(address, size);
715 } 715 }
716 void clearFreeLists() override; 716 void clearFreeLists() override;
717 #if ENABLE(ASSERT) 717 #if ENABLE(ASSERT)
718 bool isConsistentForGC() override; 718 bool isConsistentForGC() override;
719 bool pagesToBeSweptContains(Address); 719 bool pagesToBeSweptContains(Address);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 752
753 FreeList m_freeList; 753 FreeList m_freeList;
754 Address m_currentAllocationPoint; 754 Address m_currentAllocationPoint;
755 size_t m_remainingAllocationSize; 755 size_t m_remainingAllocationSize;
756 size_t m_lastRemainingAllocationSize; 756 size_t m_lastRemainingAllocationSize;
757 757
758 // The size of promptly freed objects in the heap. 758 // The size of promptly freed objects in the heap.
759 size_t m_promptlyFreedSize; 759 size_t m_promptlyFreedSize;
760 }; 760 };
761 761
762 class LargeObjectHeap final : public BaseHeap { 762 class LargeObjectArena final : public BaseArena {
763 public: 763 public:
764 LargeObjectHeap(ThreadState*, int); 764 LargeObjectArena(ThreadState*, int);
765 Address allocateLargeObjectPage(size_t, size_t gcInfoIndex); 765 Address allocateLargeObjectPage(size_t, size_t gcInfoIndex);
766 void freeLargeObjectPage(LargeObjectPage*); 766 void freeLargeObjectPage(LargeObjectPage*);
767 #if ENABLE(ASSERT) 767 #if ENABLE(ASSERT)
768 bool isConsistentForGC() override { return true; } 768 bool isConsistentForGC() override { return true; }
769 #endif 769 #endif
770 private: 770 private:
771 Address doAllocateLargeObjectPage(size_t, size_t gcInfoIndex); 771 Address doAllocateLargeObjectPage(size_t, size_t gcInfoIndex);
772 Address lazySweepPages(size_t, size_t gcInfoIndex) override; 772 Address lazySweepPages(size_t, size_t gcInfoIndex) override;
773 }; 773 };
774 774
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 } 865 }
866 866
867 NO_SANITIZE_ADDRESS inline 867 NO_SANITIZE_ADDRESS inline
868 void HeapObjectHeader::markDead() 868 void HeapObjectHeader::markDead()
869 { 869 {
870 ASSERT(checkHeader()); 870 ASSERT(checkHeader());
871 ASSERT(!isMarked()); 871 ASSERT(!isMarked());
872 m_encoded |= headerDeadBitMask; 872 m_encoded |= headerDeadBitMask;
873 } 873 }
874 874
875 inline Address NormalPageHeap::allocateObject(size_t allocationSize, size_t gcIn foIndex) 875 inline Address NormalPageArena::allocateObject(size_t allocationSize, size_t gcI nfoIndex)
876 { 876 {
877 if (LIKELY(allocationSize <= m_remainingAllocationSize)) { 877 if (LIKELY(allocationSize <= m_remainingAllocationSize)) {
878 Address headerAddress = m_currentAllocationPoint; 878 Address headerAddress = m_currentAllocationPoint;
879 m_currentAllocationPoint += allocationSize; 879 m_currentAllocationPoint += allocationSize;
880 m_remainingAllocationSize -= allocationSize; 880 m_remainingAllocationSize -= allocationSize;
881 ASSERT(gcInfoIndex > 0); 881 ASSERT(gcInfoIndex > 0);
882 new (NotNull, headerAddress) HeapObjectHeader(allocationSize, gcInfoInde x); 882 new (NotNull, headerAddress) HeapObjectHeader(allocationSize, gcInfoInde x);
883 Address result = headerAddress + sizeof(HeapObjectHeader); 883 Address result = headerAddress + sizeof(HeapObjectHeader);
884 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); 884 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask));
885 885
886 SET_MEMORY_ACCESSIBLE(result, allocationSize - sizeof(HeapObjectHeader)) ; 886 SET_MEMORY_ACCESSIBLE(result, allocationSize - sizeof(HeapObjectHeader)) ;
887 ASSERT(findPageFromAddress(headerAddress + allocationSize - 1)); 887 ASSERT(findPageFromAddress(headerAddress + allocationSize - 1));
888 return result; 888 return result;
889 } 889 }
890 return outOfLineAllocate(allocationSize, gcInfoIndex); 890 return outOfLineAllocate(allocationSize, gcInfoIndex);
891 } 891 }
892 892
893 } // namespace blink 893 } // namespace blink
894 894
895 #endif // HeapPage_h 895 #endif // HeapPage_h
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698