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

Side by Side Diff: Source/platform/heap/Heap.h

Issue 840223002: Oilpan: Remove duplicated code between HeapPage and LargeObject (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | Source/platform/heap/Heap.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 #if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) 82 #if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER)
83 #define FILL_ZERO_IF_PRODUCTION(address, size) do { } while (false) 83 #define FILL_ZERO_IF_PRODUCTION(address, size) do { } while (false)
84 #define FILL_ZERO_IF_NOT_PRODUCTION(address, size) memset((address), 0, (size)) 84 #define FILL_ZERO_IF_NOT_PRODUCTION(address, size) memset((address), 0, (size))
85 #else 85 #else
86 #define FILL_ZERO_IF_PRODUCTION(address, size) memset((address), 0, (size)) 86 #define FILL_ZERO_IF_PRODUCTION(address, size) memset((address), 0, (size))
87 #define FILL_ZERO_IF_NOT_PRODUCTION(address, size) do { } while (false) 87 #define FILL_ZERO_IF_NOT_PRODUCTION(address, size) do { } while (false)
88 #endif 88 #endif
89 89
90 class CallbackStack; 90 class CallbackStack;
91 class PageMemory; 91 class PageMemory;
92 class ThreadHeapForHeapPage;
92 template<ThreadAffinity affinity> class ThreadLocalPersistents; 93 template<ThreadAffinity affinity> class ThreadLocalPersistents;
93 template<typename T, typename RootsAccessor = ThreadLocalPersistents<ThreadingTr ait<T>::Affinity>> class Persistent; 94 template<typename T, typename RootsAccessor = ThreadLocalPersistents<ThreadingTr ait<T>::Affinity>> class Persistent;
94 95
95 #if ENABLE(GC_PROFILING) 96 #if ENABLE(GC_PROFILING)
96 class TracedValue; 97 class TracedValue;
97 #endif 98 #endif
98 99
99 // HeapObjectHeader is 4 byte (32 bit) that has the following layout: 100 // HeapObjectHeader is 4 byte (32 bit) that has the following layout:
100 // 101 //
101 // | gcInfoIndex (15 bit) | size (14 bit) | dead bit (1 bit) | freed bit (1 bit) | mark bit (1 bit) | 102 // | gcInfoIndex (15 bit) | size (14 bit) | dead bit (1 bit) | freed bit (1 bit) | mark bit (1 bit) |
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 inline Address roundToBlinkPageStart(Address address) 324 inline Address roundToBlinkPageStart(Address address)
324 { 325 {
325 return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address) & blin kPageBaseMask); 326 return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address) & blin kPageBaseMask);
326 } 327 }
327 328
328 inline Address roundToBlinkPageEnd(Address address) 329 inline Address roundToBlinkPageEnd(Address address)
329 { 330 {
330 return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address - 1) & blinkPageBaseMask) + blinkPageSize; 331 return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address - 1) & blinkPageBaseMask) + blinkPageSize;
331 } 332 }
332 333
333 // Compute the amount of padding we have to add to a header to make
334 // the size of the header plus the padding a multiple of 8 bytes.
335 inline size_t headerPadding()
336 {
337 return (allocationGranularity - (sizeof(HeapObjectHeader) % allocationGranul arity)) % allocationGranularity;
338 }
339
340 // Masks an address down to the enclosing blink page base address. 334 // Masks an address down to the enclosing blink page base address.
341 inline Address blinkPageAddress(Address address) 335 inline Address blinkPageAddress(Address address)
342 { 336 {
343 return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address) & blin kPageBaseMask); 337 return reinterpret_cast<Address>(reinterpret_cast<uintptr_t>(address) & blin kPageBaseMask);
344 } 338 }
345 339
346 #if ENABLE(ASSERT) 340 #if ENABLE(ASSERT)
347 341
348 // Sanity check for a page header address: the address of the page 342 // Sanity check for a page header address: the address of the page
349 // header should be OS page size away from being Blink page size 343 // header should be OS page size away from being Blink page size
350 // aligned. 344 // aligned.
351 inline bool isPageHeaderAddress(Address address) 345 inline bool isPageHeaderAddress(Address address)
352 { 346 {
353 return !((reinterpret_cast<uintptr_t>(address) & blinkPageOffsetMask) - WTF: :kSystemPageSize); 347 return !((reinterpret_cast<uintptr_t>(address) & blinkPageOffsetMask) - WTF: :kSystemPageSize);
354 } 348 }
355 #endif 349 #endif
356 350
357 // FIXME: Add a good comment about the heap layout once heap relayout work 351 // FIXME: Add a good comment about the heap layout once heap relayout work
358 // is done. 352 // is done.
359 class BaseHeapPage { 353 class BaseHeapPage {
360 public: 354 public:
361 BaseHeapPage(PageMemory*, ThreadHeap*); 355 BaseHeapPage(PageMemory*, ThreadHeap*);
362 virtual ~BaseHeapPage() { } 356 virtual ~BaseHeapPage() { }
363 357
358 void link(BaseHeapPage** previousNext)
359 {
360 m_next = *previousNext;
361 *previousNext = this;
362 }
363 void unlink(BaseHeapPage** previousNext)
364 {
365 *previousNext = m_next;
366 m_next = nullptr;
367 }
368 BaseHeapPage* next() const { return m_next; }
369
364 // virtual methods are slow. So performance-sensitive methods 370 // virtual methods are slow. So performance-sensitive methods
365 // should be defined as non-virtual methods on HeapPage and LargeObject. 371 // should be defined as non-virtual methods on HeapPage and LargeObject.
366 // The following methods are not performance-sensitive. 372 // The following methods are not performance-sensitive.
367 virtual size_t objectPayloadSizeForTesting() = 0; 373 virtual size_t objectPayloadSizeForTesting() = 0;
368 virtual bool isEmpty() = 0; 374 virtual bool isEmpty() = 0;
369 virtual void removeFromHeap(ThreadHeap*) = 0; 375 virtual void removeFromHeap() = 0;
370 virtual void sweep() = 0; 376 virtual void sweep() = 0;
371 virtual void markUnmarkedObjectsDead() = 0; 377 virtual void markUnmarkedObjectsDead() = 0;
372 // Check if the given address points to an object in this 378 // Check if the given address points to an object in this
373 // heap page. If so, find the start of that object and mark it 379 // heap page. If so, find the start of that object and mark it
374 // using the given Visitor. Otherwise do nothing. The pointer must 380 // using the given Visitor. Otherwise do nothing. The pointer must
375 // be within the same aligned blinkPageSize as the this-pointer. 381 // be within the same aligned blinkPageSize as the this-pointer.
376 // 382 //
377 // This is used during conservative stack scanning to 383 // This is used during conservative stack scanning to
378 // conservatively mark all objects that could be referenced from 384 // conservatively mark all objects that could be referenced from
379 // the stack. 385 // the stack.
(...skipping 27 matching lines...) Expand all
407 413
408 void markAsUnswept() 414 void markAsUnswept()
409 { 415 {
410 ASSERT(m_swept); 416 ASSERT(m_swept);
411 m_swept = false; 417 m_swept = false;
412 } 418 }
413 419
414 private: 420 private:
415 PageMemory* m_storage; 421 PageMemory* m_storage;
416 ThreadHeap* m_heap; 422 ThreadHeap* m_heap;
423 BaseHeapPage* m_next;
417 // Whether the page is part of a terminating thread or not. 424 // Whether the page is part of a terminating thread or not.
418 bool m_terminating; 425 bool m_terminating;
419 426
420 // Track the sweeping state of a page. Set to true once 427 // Track the sweeping state of a page. Set to true once
421 // the lazy sweep completes has processed it. 428 // the lazy sweep completes has processed it.
422 // 429 //
423 // Set to false at the start of a sweep, true upon completion 430 // Set to false at the start of a sweep, true upon completion
424 // of lazy sweeping. 431 // of lazy sweeping.
425 bool m_swept; 432 bool m_swept;
433 friend class ThreadHeap;
426 }; 434 };
427 435
428 class HeapPage final : public BaseHeapPage { 436 class HeapPage final : public BaseHeapPage {
429 public: 437 public:
430 HeapPage(PageMemory*, ThreadHeap*); 438 HeapPage(PageMemory*, ThreadHeap*);
431 439
432 Address payload() 440 Address payload()
433 { 441 {
434 return address() + sizeof(HeapPage) + headerPadding(); 442 return address() + sizeof(HeapPage) + headerPadding();
435 } 443 }
436 size_t payloadSize() 444 size_t payloadSize()
437 { 445 {
438 return (blinkPagePayloadSize() - sizeof(HeapPage) - headerPadding()) & ~ allocationMask; 446 return (blinkPagePayloadSize() - sizeof(HeapPage) - headerPadding()) & ~ allocationMask;
439 } 447 }
440 Address payloadEnd() { return payload() + payloadSize(); } 448 Address payloadEnd() { return payload() + payloadSize(); }
441 bool containedInObjectPayload(Address address) { return payload() <= address && address < payloadEnd(); } 449 bool containedInObjectPayload(Address address) { return payload() <= address && address < payloadEnd(); }
442 450
443 void link(HeapPage** previousNext)
444 {
445 m_next = *previousNext;
446 *previousNext = this;
447 }
448
449 void unlink(HeapPage** previousNext)
450 {
451 *previousNext = m_next;
452 m_next = nullptr;
453 }
454
455 virtual size_t objectPayloadSizeForTesting() override; 451 virtual size_t objectPayloadSizeForTesting() override;
456 virtual bool isEmpty() override; 452 virtual bool isEmpty() override;
457 virtual void removeFromHeap(ThreadHeap*) override; 453 virtual void removeFromHeap() override;
458 virtual void sweep() override; 454 virtual void sweep() override;
459 virtual void markUnmarkedObjectsDead() override; 455 virtual void markUnmarkedObjectsDead() override;
460 virtual void checkAndMarkPointer(Visitor*, Address) override; 456 virtual void checkAndMarkPointer(Visitor*, Address) override;
461 virtual void markOrphaned() override 457 virtual void markOrphaned() override
462 { 458 {
463 // Zap the payload with a recognizable value to detect any incorrect 459 // Zap the payload with a recognizable value to detect any incorrect
464 // cross thread pointer usage. 460 // cross thread pointer usage.
465 #if defined(ADDRESS_SANITIZER) 461 #if defined(ADDRESS_SANITIZER)
466 // This needs to zap poisoned memory as well. 462 // This needs to zap poisoned memory as well.
467 // Force unpoison memory before memset. 463 // Force unpoison memory before memset.
(...skipping 14 matching lines...) Expand all
482 // for the header, and the unmapped guard page at the start. That ensures 478 // for the header, and the unmapped guard page at the start. That ensures
483 // the result can be used to populate the negative page cache. 479 // the result can be used to populate the negative page cache.
484 virtual bool contains(Address addr) override 480 virtual bool contains(Address addr) override
485 { 481 {
486 Address blinkPageStart = roundToBlinkPageStart(address()); 482 Address blinkPageStart = roundToBlinkPageStart(address());
487 ASSERT(blinkPageStart == address() - WTF::kSystemPageSize); // Page is a t aligned address plus guard page size. 483 ASSERT(blinkPageStart == address() - WTF::kSystemPageSize); // Page is a t aligned address plus guard page size.
488 return blinkPageStart <= addr && addr < blinkPageStart + blinkPageSize; 484 return blinkPageStart <= addr && addr < blinkPageStart + blinkPageSize;
489 } 485 }
490 #endif 486 #endif
491 virtual size_t size() override { return blinkPageSize; } 487 virtual size_t size() override { return blinkPageSize; }
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.
490 static size_t headerPadding()
491 {
492 return (sizeof(HeapPage) + allocationGranularity - (sizeof(HeapObjectHea der) % allocationGranularity)) % allocationGranularity;
493 }
492 494
493 HeapPage* next() { return m_next; }
494 495
496 ThreadHeapForHeapPage* heapForHeapPage();
495 void clearObjectStartBitMap(); 497 void clearObjectStartBitMap();
496 498
497 #if defined(ADDRESS_SANITIZER) 499 #if defined(ADDRESS_SANITIZER)
498 void poisonUnmarkedObjects(); 500 void poisonUnmarkedObjects();
499 #endif 501 #endif
500 502
501 // This method is needed just to avoid compilers from removing m_padding.
502 uint64_t unusedMethod() const { return m_padding; }
503
504 private: 503 private:
505 HeapObjectHeader* findHeaderFromAddress(Address); 504 HeapObjectHeader* findHeaderFromAddress(Address);
506 void populateObjectStartBitMap(); 505 void populateObjectStartBitMap();
507 bool isObjectStartBitMapComputed() { return m_objectStartBitMapComputed; } 506 bool isObjectStartBitMapComputed() { return m_objectStartBitMapComputed; }
508 507
509 HeapPage* m_next;
510 bool m_objectStartBitMapComputed; 508 bool m_objectStartBitMapComputed;
511 uint8_t m_objectStartBitMap[reservedForObjectBitMap]; 509 uint8_t m_objectStartBitMap[reservedForObjectBitMap];
512 uint64_t m_padding; // Preserve 8-byte alignment on 32-bit systems.
513
514 friend class ThreadHeap;
515 }; 510 };
516 511
517 // Large allocations are allocated as separate objects and linked in a list. 512 // Large allocations are allocated as separate objects and linked in a list.
518 // 513 //
519 // In order to use the same memory allocation routines for everything allocated 514 // In order to use the same memory allocation routines for everything allocated
520 // in the heap, large objects are considered heap pages containing only one 515 // in the heap, large objects are considered heap pages containing only one
521 // object. 516 // object.
522 class LargeObject final : public BaseHeapPage { 517 class LargeObject final : public BaseHeapPage {
523 public: 518 public:
524 LargeObject(PageMemory* storage, ThreadHeap* heap, size_t payloadSize) 519 LargeObject(PageMemory* storage, ThreadHeap* heap, size_t payloadSize)
525 : BaseHeapPage(storage, heap) 520 : BaseHeapPage(storage, heap)
526 , m_payloadSize(payloadSize) 521 , m_payloadSize(payloadSize)
527 { 522 {
528 } 523 }
529 524
530 Address payload() { return heapObjectHeader()->payload(); } 525 Address payload() { return heapObjectHeader()->payload(); }
531 size_t payloadSize() { return m_payloadSize; } 526 size_t payloadSize() { return m_payloadSize; }
532 Address payloadEnd() { return payload() + payloadSize(); } 527 Address payloadEnd() { return payload() + payloadSize(); }
533 bool containedInObjectPayload(Address address) { return payload() <= address && address < payloadEnd(); } 528 bool containedInObjectPayload(Address address) { return payload() <= address && address < payloadEnd(); }
534 529
535 virtual size_t objectPayloadSizeForTesting() override; 530 virtual size_t objectPayloadSizeForTesting() override;
536 virtual bool isEmpty() override; 531 virtual bool isEmpty() override;
537 virtual void removeFromHeap(ThreadHeap*) override; 532 virtual void removeFromHeap() override;
538 virtual void sweep() override; 533 virtual void sweep() override;
539 virtual void markUnmarkedObjectsDead() override; 534 virtual void markUnmarkedObjectsDead() override;
540 virtual void checkAndMarkPointer(Visitor*, Address) override; 535 virtual void checkAndMarkPointer(Visitor*, Address) override;
541 virtual void markOrphaned() override 536 virtual void markOrphaned() override
542 { 537 {
543 // Zap the payload with a recognizable value to detect any incorrect 538 // Zap the payload with a recognizable value to detect any incorrect
544 // cross thread pointer usage. 539 // cross thread pointer usage.
545 memset(payload(), orphanedZapValue, payloadSize()); 540 memset(payload(), orphanedZapValue, payloadSize());
546 BaseHeapPage::markOrphaned(); 541 BaseHeapPage::markOrphaned();
547 } 542 }
(...skipping 12 matching lines...) Expand all
560 // populate the negative page cache. 555 // populate the negative page cache.
561 virtual bool contains(Address object) override 556 virtual bool contains(Address object) override
562 { 557 {
563 return roundToBlinkPageStart(address()) <= object && object < roundToBli nkPageEnd(address() + size()); 558 return roundToBlinkPageStart(address()) <= object && object < roundToBli nkPageEnd(address() + size());
564 } 559 }
565 #endif 560 #endif
566 virtual size_t size() 561 virtual size_t size()
567 { 562 {
568 return sizeof(LargeObject) + headerPadding() + sizeof(HeapObjectHeader) + m_payloadSize; 563 return sizeof(LargeObject) + headerPadding() + sizeof(HeapObjectHeader) + m_payloadSize;
569 } 564 }
565 // Compute the amount of padding we have to add to a header to make
566 // the size of the header plus the padding a multiple of 8 bytes.
567 static size_t headerPadding()
568 {
569 return (sizeof(LargeObject) + allocationGranularity - (sizeof(HeapObject Header) % allocationGranularity)) % allocationGranularity;
570 }
570 virtual bool isLargeObject() override { return true; } 571 virtual bool isLargeObject() override { return true; }
571 572
572 void link(LargeObject** previousNext)
573 {
574 m_next = *previousNext;
575 *previousNext = this;
576 }
577
578 void unlink(LargeObject** previousNext)
579 {
580 *previousNext = m_next;
581 m_next = nullptr;
582 }
583
584 LargeObject* next()
585 {
586 return m_next;
587 }
588
589 HeapObjectHeader* heapObjectHeader() 573 HeapObjectHeader* heapObjectHeader()
590 { 574 {
591 Address headerAddress = address() + sizeof(LargeObject) + headerPadding( ); 575 Address headerAddress = address() + sizeof(LargeObject) + headerPadding( );
592 return reinterpret_cast<HeapObjectHeader*>(headerAddress); 576 return reinterpret_cast<HeapObjectHeader*>(headerAddress);
593 } 577 }
594 578
595 // This method is needed just to avoid compilers from removing m_padding. 579 private:
596 uint64_t unusedMethod() const { return m_padding; }
597 580
598 private:
599 friend class ThreadHeap;
600 LargeObject* m_next;
601 size_t m_payloadSize; 581 size_t m_payloadSize;
602 uint64_t m_padding; // Preserve 8-byte alignment on 32-bit systems.
603 }; 582 };
604 583
605 // A HeapDoesNotContainCache provides a fast way of taking an arbitrary 584 // A HeapDoesNotContainCache provides a fast way of taking an arbitrary
606 // pointer-sized word, and determining whether it cannot be interpreted as a 585 // pointer-sized word, and determining whether it cannot be interpreted as a
607 // pointer to an area that is managed by the garbage collected Blink heap. This 586 // pointer to an area that is managed by the garbage collected Blink heap. This
608 // is a cache of 'pages' that have previously been determined to be wholly 587 // is a cache of 'pages' that have previously been determined to be wholly
609 // outside of the heap. The size of these pages must be smaller than the 588 // outside of the heap. The size of these pages must be smaller than the
610 // allocation alignment of the heap pages. We determine off-heap-ness by 589 // allocation alignment of the heap pages. We determine off-heap-ness by
611 // rounding down the pointer to the nearest page and looking up the page in the 590 // rounding down the pointer to the nearest page and looking up the page in the
612 // cache. If there is a miss in the cache we can determine the status of the 591 // cache. If there is a miss in the cache we can determine the status of the
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 700
722 void getFreeSizeStats(PerBucketFreeListStats bucketStats[], size_t& totalSiz e) const; 701 void getFreeSizeStats(PerBucketFreeListStats bucketStats[], size_t& totalSiz e) const;
723 #endif 702 #endif
724 703
725 private: 704 private:
726 int m_biggestFreeListIndex; 705 int m_biggestFreeListIndex;
727 706
728 // All FreeListEntries in the nth list have size >= 2^n. 707 // All FreeListEntries in the nth list have size >= 2^n.
729 FreeListEntry* m_freeLists[blinkPageSizeLog2]; 708 FreeListEntry* m_freeLists[blinkPageSizeLog2];
730 709
731 friend class ThreadHeap; 710 friend class ThreadHeapForHeapPage;
732 }; 711 };
733 712
734 // Thread heaps represent a part of the per-thread Blink heap. 713 // Thread heaps represent a part of the per-thread Blink heap.
735 // 714 //
736 // Each Blink thread has a number of thread heaps: one general heap 715 // Each Blink thread has a number of thread heaps: one general heap
737 // that contains any type of object and a number of heaps specialized 716 // that contains any type of object and a number of heaps specialized
738 // for specific object types (such as Node). 717 // for specific object types (such as Node).
739 // 718 //
740 // Each thread heap contains the functionality to allocate new objects 719 // Each thread heap contains the functionality to allocate new objects
741 // (potentially adding new pages to the heap), to find and mark 720 // (potentially adding new pages to the heap), to find and mark
742 // objects during conservative stack scanning and to sweep the set of 721 // objects during conservative stack scanning and to sweep the set of
743 // pages after a GC. 722 // pages after a GC.
744 class PLATFORM_EXPORT ThreadHeap final { 723 class PLATFORM_EXPORT ThreadHeap {
745 public: 724 public:
746 ThreadHeap(ThreadState*, int); 725 ThreadHeap(ThreadState*, int);
747 ~ThreadHeap(); 726 virtual ~ThreadHeap();
748 void cleanupPages(); 727 void cleanupPages();
749 728
750 #if ENABLE(ASSERT) || ENABLE(GC_PROFILING) 729 #if ENABLE(ASSERT) || ENABLE(GC_PROFILING)
751 BaseHeapPage* findPageFromAddress(Address); 730 BaseHeapPage* findPageFromAddress(Address);
752 #endif 731 #endif
753 #if ENABLE(GC_PROFILING) 732 #if ENABLE(GC_PROFILING)
754 void snapshot(TracedValue*, ThreadState::SnapshotInfo*); 733 void snapshot(TracedValue*, ThreadState::SnapshotInfo*);
755 void incrementMarkedObjectsAge(); 734 void incrementMarkedObjectsAge();
756 #endif 735 #endif
757 736
758 void clearFreeLists(); 737 virtual void clearFreeLists() { }
759 void makeConsistentForSweeping(); 738 void makeConsistentForSweeping();
760 #if ENABLE(ASSERT) 739 #if ENABLE(ASSERT)
761 bool isConsistentForSweeping(); 740 virtual bool isConsistentForSweeping() = 0;
762 #endif 741 #endif
763 size_t objectPayloadSizeForTesting(); 742 size_t objectPayloadSizeForTesting();
743 void prepareHeapForTermination();
744 void prepareForSweep();
745 Address lazySweep(size_t, size_t gcInfoIndex);
746 void completeSweep();
764 747
765 ThreadState* threadState() { return m_threadState; } 748 ThreadState* threadState() { return m_threadState; }
749 int heapIndex() const { return m_index; }
750 inline static size_t allocationSizeFromSize(size_t);
751 inline static size_t roundedAllocationSize(size_t size)
752 {
753 return allocationSizeFromSize(size) - sizeof(HeapObjectHeader);
754 }
766 755
756 protected:
757 BaseHeapPage* m_firstPage;
758 BaseHeapPage* m_firstUnsweptPage;
759
760 private:
761 virtual Address lazySweepPages(size_t, size_t gcInfoIndex) = 0;
762
763 ThreadState* m_threadState;
764
765 // Index into the page pools. This is used to ensure that the pages of the
766 // same type go into the correct page pool and thus avoid type confusion.
767 int m_index;
768 };
769
770 class PLATFORM_EXPORT ThreadHeapForHeapPage final : public ThreadHeap {
771 public:
772 ThreadHeapForHeapPage(ThreadState*, int);
767 void addToFreeList(Address address, size_t size) 773 void addToFreeList(Address address, size_t size)
768 { 774 {
769 ASSERT(findPageFromAddress(address)); 775 ASSERT(findPageFromAddress(address));
770 ASSERT(findPageFromAddress(address + size - 1)); 776 ASSERT(findPageFromAddress(address + size - 1));
771 m_freeList.addToFreeList(address, size); 777 m_freeList.addToFreeList(address, size);
772 } 778 }
779 virtual void clearFreeLists() override;
780 #if ENABLE(ASSERT)
781 virtual bool isConsistentForSweeping() override;
782 bool pagesToBeSweptContains(Address);
783 #endif
773 784
774 inline Address allocate(size_t payloadSize, size_t gcInfoIndex); 785 inline Address allocate(size_t payloadSize, size_t gcInfoIndex);
775 inline static size_t roundedAllocationSize(size_t size) 786 inline Address allocateObject(size_t allocationSize, size_t gcInfoIndex);
776 {
777 return allocationSizeFromSize(size) - sizeof(HeapObjectHeader);
778 }
779 inline static size_t allocationSizeFromSize(size_t);
780
781 void prepareHeapForTermination();
782 void prepareForSweep();
783 void completeSweep();
784 787
785 void freePage(HeapPage*); 788 void freePage(HeapPage*);
786 void freeLargeObject(LargeObject*);
787 789
790 bool coalesce();
788 void promptlyFreeObject(HeapObjectHeader*); 791 void promptlyFreeObject(HeapObjectHeader*);
789 bool expandObject(HeapObjectHeader*, size_t); 792 bool expandObject(HeapObjectHeader*, size_t);
790 void shrinkObject(HeapObjectHeader*, size_t); 793 void shrinkObject(HeapObjectHeader*, size_t);
791 void decreasePromptlyFreedSize(size_t size) { m_promptlyFreedSize -= size; } 794 void decreasePromptlyFreedSize(size_t size) { m_promptlyFreedSize -= size; }
792 795
793 #if ENABLE(GC_PROFILING) 796 #if ENABLE(GC_PROFILING)
794 void snapshotFreeList(TracedValue&); 797 void snapshotFreeList(TracedValue&);
795 798
796 void countMarkedObjects(ClassAgeCountsMap&) const; 799 void countMarkedObjects(ClassAgeCountsMap&) const;
797 void countObjectsToSweep(ClassAgeCountsMap&) const; 800 void countObjectsToSweep(ClassAgeCountsMap&) const;
798 #endif 801 #endif
799 802
800 private: 803 private:
804 void allocatePage();
805 virtual Address lazySweepPages(size_t, size_t gcInfoIndex) override;
801 Address outOfLineAllocate(size_t allocationSize, size_t gcInfoIndex); 806 Address outOfLineAllocate(size_t allocationSize, size_t gcInfoIndex);
802 Address currentAllocationPoint() const { return m_currentAllocationPoint; } 807 Address currentAllocationPoint() const { return m_currentAllocationPoint; }
803 size_t remainingAllocationSize() const { return m_remainingAllocationSize; } 808 size_t remainingAllocationSize() const { return m_remainingAllocationSize; }
804 bool hasCurrentAllocationArea() const { return currentAllocationPoint() && r emainingAllocationSize(); } 809 bool hasCurrentAllocationArea() const { return currentAllocationPoint() && r emainingAllocationSize(); }
805 inline void setAllocationPoint(Address, size_t); 810 inline void setAllocationPoint(Address, size_t);
806 void updateRemainingAllocationSize(); 811 void updateRemainingAllocationSize();
807 Address allocateFromFreeList(size_t, size_t gcInfoIndex); 812 Address allocateFromFreeList(size_t, size_t gcInfoIndex);
808 Address lazySweepPages(size_t, size_t gcInfoIndex);
809 bool lazySweepLargeObjects(size_t);
810 813
811 void allocatePage(); 814 FreeList m_freeList;
812 Address allocateLargeObject(size_t, size_t gcInfoIndex);
813
814 inline Address allocateObject(size_t allocationSize, size_t gcInfoIndex);
815
816 #if ENABLE(ASSERT)
817 bool pagesToBeSweptContains(Address);
818 #endif
819
820 bool coalesce();
821 void preparePagesForSweeping();
822
823 Address m_currentAllocationPoint; 815 Address m_currentAllocationPoint;
824 size_t m_remainingAllocationSize; 816 size_t m_remainingAllocationSize;
825 size_t m_lastRemainingAllocationSize; 817 size_t m_lastRemainingAllocationSize;
826 818
827 HeapPage* m_firstPage;
828 LargeObject* m_firstLargeObject;
829 HeapPage* m_firstUnsweptPage;
830 LargeObject* m_firstUnsweptLargeObject;
831
832 ThreadState* m_threadState;
833
834 FreeList m_freeList;
835
836 // Index into the page pools. This is used to ensure that the pages of the
837 // same type go into the correct page pool and thus avoid type confusion.
838 int m_index;
839
840 // The size of promptly freed objects in the heap. 819 // The size of promptly freed objects in the heap.
841 size_t m_promptlyFreedSize; 820 size_t m_promptlyFreedSize;
842 821
843 #if ENABLE(GC_PROFILING) 822 #if ENABLE(GC_PROFILING)
844 size_t m_cumulativeAllocationSize; 823 size_t m_cumulativeAllocationSize;
845 size_t m_allocationCount; 824 size_t m_allocationCount;
846 size_t m_inlineAllocationCount; 825 size_t m_inlineAllocationCount;
847 #endif 826 #endif
848 }; 827 };
849 828
829 class ThreadHeapForLargeObject final : public ThreadHeap {
830 public:
831 ThreadHeapForLargeObject(ThreadState*, int);
832 Address allocateLargeObject(size_t, size_t gcInfoIndex);
833 void freeLargeObject(LargeObject*);
834 #if ENABLE(ASSERT)
835 virtual bool isConsistentForSweeping() override { return true; }
836 #endif
837 private:
838 Address doAllocateLargeObject(size_t, size_t gcInfoIndex);
839 virtual Address lazySweepPages(size_t, size_t gcInfoIndex) override;
840 };
841
850 // Mask an address down to the enclosing oilpan heap base page. All oilpan heap 842 // Mask an address down to the enclosing oilpan heap base page. All oilpan heap
851 // pages are aligned at blinkPageBase plus an OS page size. 843 // pages are aligned at blinkPageBase plus an OS page size.
852 // FIXME: Remove PLATFORM_EXPORT once we get a proper public interface to our 844 // FIXME: Remove PLATFORM_EXPORT once we get a proper public interface to our
853 // typed heaps. This is only exported to enable tests in HeapTest.cpp. 845 // typed heaps. This is only exported to enable tests in HeapTest.cpp.
854 PLATFORM_EXPORT inline BaseHeapPage* pageFromObject(const void* object) 846 PLATFORM_EXPORT inline BaseHeapPage* pageFromObject(const void* object)
855 { 847 {
856 Address address = reinterpret_cast<Address>(const_cast<void*>(object)); 848 Address address = reinterpret_cast<Address>(const_cast<void*>(object));
857 BaseHeapPage* page = reinterpret_cast<BaseHeapPage*>(blinkPageAddress(addres s) + WTF::kSystemPageSize); 849 BaseHeapPage* page = reinterpret_cast<BaseHeapPage*>(blinkPageAddress(addres s) + WTF::kSystemPageSize);
858 ASSERT(page->contains(address)); 850 ASSERT(page->contains(address));
859 return page; 851 return page;
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
1355 // therefore has to happen before any calculation on the size. 1347 // therefore has to happen before any calculation on the size.
1356 RELEASE_ASSERT(size < maxHeapObjectSize); 1348 RELEASE_ASSERT(size < maxHeapObjectSize);
1357 1349
1358 // Add space for header. 1350 // Add space for header.
1359 size_t allocationSize = size + sizeof(HeapObjectHeader); 1351 size_t allocationSize = size + sizeof(HeapObjectHeader);
1360 // Align size with allocation granularity. 1352 // Align size with allocation granularity.
1361 allocationSize = (allocationSize + allocationMask) & ~allocationMask; 1353 allocationSize = (allocationSize + allocationMask) & ~allocationMask;
1362 return allocationSize; 1354 return allocationSize;
1363 } 1355 }
1364 1356
1365 Address ThreadHeap::allocateObject(size_t allocationSize, size_t gcInfoIndex) 1357 Address ThreadHeapForHeapPage::allocateObject(size_t allocationSize, size_t gcIn foIndex)
1366 { 1358 {
1367 #if ENABLE(GC_PROFILING) 1359 #if ENABLE(GC_PROFILING)
1368 m_cumulativeAllocationSize += allocationSize; 1360 m_cumulativeAllocationSize += allocationSize;
1369 ++m_allocationCount; 1361 ++m_allocationCount;
1370 #endif 1362 #endif
1371 1363
1372 if (LIKELY(allocationSize <= m_remainingAllocationSize)) { 1364 if (LIKELY(allocationSize <= m_remainingAllocationSize)) {
1373 #if ENABLE(GC_PROFILING) 1365 #if ENABLE(GC_PROFILING)
1374 ++m_inlineAllocationCount; 1366 ++m_inlineAllocationCount;
1375 #endif 1367 #endif
1376 Address headerAddress = m_currentAllocationPoint; 1368 Address headerAddress = m_currentAllocationPoint;
1377 m_currentAllocationPoint += allocationSize; 1369 m_currentAllocationPoint += allocationSize;
1378 m_remainingAllocationSize -= allocationSize; 1370 m_remainingAllocationSize -= allocationSize;
1379 ASSERT(gcInfoIndex > 0); 1371 ASSERT(gcInfoIndex > 0);
1380 new (NotNull, headerAddress) HeapObjectHeader(allocationSize, gcInfoInde x); 1372 new (NotNull, headerAddress) HeapObjectHeader(allocationSize, gcInfoInde x);
1381 Address result = headerAddress + sizeof(HeapObjectHeader); 1373 Address result = headerAddress + sizeof(HeapObjectHeader);
1382 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); 1374 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask));
1383 1375
1384 // Unpoison the memory used for the object (payload). 1376 // Unpoison the memory used for the object (payload).
1385 ASAN_UNPOISON_MEMORY_REGION(result, allocationSize - sizeof(HeapObjectHe ader)); 1377 ASAN_UNPOISON_MEMORY_REGION(result, allocationSize - sizeof(HeapObjectHe ader));
1386 FILL_ZERO_IF_NOT_PRODUCTION(result, allocationSize - sizeof(HeapObjectHe ader)); 1378 FILL_ZERO_IF_NOT_PRODUCTION(result, allocationSize - sizeof(HeapObjectHe ader));
1387 ASSERT(findPageFromAddress(headerAddress + allocationSize - 1)); 1379 ASSERT(findPageFromAddress(headerAddress + allocationSize - 1));
1388 return result; 1380 return result;
1389 } 1381 }
1390 return outOfLineAllocate(allocationSize, gcInfoIndex); 1382 return outOfLineAllocate(allocationSize, gcInfoIndex);
1391 } 1383 }
1392 1384
1393 Address ThreadHeap::allocate(size_t size, size_t gcInfoIndex) 1385 Address ThreadHeapForHeapPage::allocate(size_t size, size_t gcInfoIndex)
1394 { 1386 {
1395 return allocateObject(allocationSizeFromSize(size), gcInfoIndex); 1387 return allocateObject(allocationSizeFromSize(size), gcInfoIndex);
1396 } 1388 }
1397 1389
1398 template<typename T> 1390 template<typename T>
1399 struct HeapIndexTrait { 1391 struct HeapIndexTrait {
1400 static int index() { return GeneralHeap; }; 1392 static int index() { return GeneralHeap; };
1401 }; 1393 };
1402 1394
1403 // FIXME: The forward declaration is layering violation. 1395 // FIXME: The forward declaration is layering violation.
1404 #define DEFINE_TYPED_HEAP_TRAIT(Type) \ 1396 #define DEFINE_TYPED_HEAP_TRAIT(Type) \
1405 class Type; \ 1397 class Type; \
1406 template<> \ 1398 template<> \
1407 struct HeapIndexTrait<class Type> { \ 1399 struct HeapIndexTrait<class Type> { \
1408 static int index() { return Type##Heap; }; \ 1400 static int index() { return Type##Heap; }; \
1409 }; 1401 };
1410 FOR_EACH_TYPED_HEAP(DEFINE_TYPED_HEAP_TRAIT) 1402 FOR_EACH_TYPED_HEAP(DEFINE_TYPED_HEAP_TRAIT)
1411 #undef DEFINE_TYPED_HEAP_TRAIT 1403 #undef DEFINE_TYPED_HEAP_TRAIT
1412 1404
1413 template<typename T> 1405 template<typename T>
1414 Address Heap::allocateOnHeapIndex(size_t size, int heapIndex, size_t gcInfoIndex ) 1406 Address Heap::allocateOnHeapIndex(size_t size, int heapIndex, size_t gcInfoIndex )
1415 { 1407 {
1416 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); 1408 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state();
1417 ASSERT(state->isAllocationAllowed()); 1409 ASSERT(state->isAllocationAllowed());
1418 return state->heap(heapIndex)->allocate(size, gcInfoIndex); 1410 return static_cast<ThreadHeapForHeapPage*>(state->heap(heapIndex))->allocate (size, gcInfoIndex);
1419 } 1411 }
1420 1412
1421 template<typename T> 1413 template<typename T>
1422 Address Heap::allocate(size_t size) 1414 Address Heap::allocate(size_t size)
1423 { 1415 {
1424 return allocateOnHeapIndex<T>(size, HeapIndexTrait<T>::index(), GCInfoTrait< T>::index()); 1416 return allocateOnHeapIndex<T>(size, HeapIndexTrait<T>::index(), GCInfoTrait< T>::index());
1425 } 1417 }
1426 1418
1427 template<typename T> 1419 template<typename T>
1428 Address Heap::reallocate(void* previous, size_t size) 1420 Address Heap::reallocate(void* previous, size_t size)
(...skipping 1033 matching lines...) Expand 10 before | Expand all | Expand 10 after
2462 template<typename T, size_t inlineCapacity> 2454 template<typename T, size_t inlineCapacity>
2463 struct GCInfoTrait<HeapVector<T, inlineCapacity>> : public GCInfoTrait<Vector<T, inlineCapacity, HeapAllocator>> { }; 2455 struct GCInfoTrait<HeapVector<T, inlineCapacity>> : public GCInfoTrait<Vector<T, inlineCapacity, HeapAllocator>> { };
2464 template<typename T, size_t inlineCapacity> 2456 template<typename T, size_t inlineCapacity>
2465 struct GCInfoTrait<HeapDeque<T, inlineCapacity>> : public GCInfoTrait<Deque<T, i nlineCapacity, HeapAllocator>> { }; 2457 struct GCInfoTrait<HeapDeque<T, inlineCapacity>> : public GCInfoTrait<Deque<T, i nlineCapacity, HeapAllocator>> { };
2466 template<typename T, typename U, typename V> 2458 template<typename T, typename U, typename V>
2467 struct GCInfoTrait<HeapHashCountedSet<T, U, V>> : public GCInfoTrait<HashCounted Set<T, U, V, HeapAllocator>> { }; 2459 struct GCInfoTrait<HeapHashCountedSet<T, U, V>> : public GCInfoTrait<HashCounted Set<T, U, V, HeapAllocator>> { };
2468 2460
2469 } // namespace blink 2461 } // namespace blink
2470 2462
2471 #endif // Heap_h 2463 #endif // Heap_h
OLDNEW
« no previous file with comments | « no previous file | Source/platform/heap/Heap.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698