OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_HEAP_HEAP_H_ | 5 #ifndef V8_HEAP_HEAP_H_ |
6 #define V8_HEAP_HEAP_H_ | 6 #define V8_HEAP_HEAP_H_ |
7 | 7 |
8 #include <cmath> | 8 #include <cmath> |
9 #include <map> | 9 #include <map> |
10 | 10 |
(...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 | 570 |
571 | 571 |
572 enum ArrayStorageAllocationMode { | 572 enum ArrayStorageAllocationMode { |
573 DONT_INITIALIZE_ARRAY_ELEMENTS, | 573 DONT_INITIALIZE_ARRAY_ELEMENTS, |
574 INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE | 574 INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE |
575 }; | 575 }; |
576 | 576 |
577 | 577 |
578 class Heap { | 578 class Heap { |
579 public: | 579 public: |
580 // Configure heap size in MB before setup. Return false if the heap has been | 580 // Declare all the root indices. This defines the root list order. |
581 // set up already. | 581 enum RootListIndex { |
582 bool ConfigureHeap(int max_semi_space_size, int max_old_space_size, | 582 #define ROOT_INDEX_DECLARATION(type, name, camel_name) k##camel_name##RootIndex, |
583 int max_executable_size, size_t code_range_size); | 583 STRONG_ROOT_LIST(ROOT_INDEX_DECLARATION) |
584 bool ConfigureHeapDefault(); | 584 #undef ROOT_INDEX_DECLARATION |
585 | 585 |
586 // Prepares the heap, setting up memory areas that are needed in the isolate | 586 #define STRING_INDEX_DECLARATION(name, str) k##name##RootIndex, |
587 // without actually creating any objects. | 587 INTERNALIZED_STRING_LIST(STRING_INDEX_DECLARATION) |
588 bool SetUp(); | 588 #undef STRING_DECLARATION |
589 | 589 |
590 // Bootstraps the object heap with the core set of objects required to run. | 590 #define SYMBOL_INDEX_DECLARATION(name) k##name##RootIndex, |
591 // Returns whether it succeeded. | 591 PRIVATE_SYMBOL_LIST(SYMBOL_INDEX_DECLARATION) |
592 bool CreateHeapObjects(); | 592 #undef SYMBOL_INDEX_DECLARATION |
593 | 593 |
594 // Destroys all memory allocated by the heap. | 594 #define SYMBOL_INDEX_DECLARATION(name, varname, description) k##name##RootIndex, |
595 void TearDown(); | 595 PUBLIC_SYMBOL_LIST(SYMBOL_INDEX_DECLARATION) |
| 596 #undef SYMBOL_INDEX_DECLARATION |
| 597 |
| 598 // Utility type maps |
| 599 #define DECLARE_STRUCT_MAP(NAME, Name, name) k##Name##MapRootIndex, |
| 600 STRUCT_LIST(DECLARE_STRUCT_MAP) |
| 601 #undef DECLARE_STRUCT_MAP |
| 602 kStringTableRootIndex, |
| 603 |
| 604 #define ROOT_INDEX_DECLARATION(type, name, camel_name) k##camel_name##RootIndex, |
| 605 SMI_ROOT_LIST(ROOT_INDEX_DECLARATION) |
| 606 #undef ROOT_INDEX_DECLARATION |
| 607 kRootListLength, |
| 608 kStrongRootListLength = kStringTableRootIndex, |
| 609 kSmiRootsStart = kStringTableRootIndex + 1 |
| 610 }; |
| 611 |
| 612 // Indicates whether live bytes adjustment is triggered |
| 613 // - from within the GC code before sweeping started (SEQUENTIAL_TO_SWEEPER), |
| 614 // - or from within GC (CONCURRENT_TO_SWEEPER), |
| 615 // - or mutator code (CONCURRENT_TO_SWEEPER). |
| 616 enum InvocationMode { SEQUENTIAL_TO_SWEEPER, CONCURRENT_TO_SWEEPER }; |
| 617 |
| 618 enum ScratchpadSlotMode { IGNORE_SCRATCHPAD_SLOT, RECORD_SCRATCHPAD_SLOT }; |
| 619 |
| 620 enum HeapState { NOT_IN_GC, SCAVENGE, MARK_COMPACT }; |
| 621 |
| 622 // ObjectStats are kept in two arrays, counts and sizes. Related stats are |
| 623 // stored in a contiguous linear buffer. Stats groups are stored one after |
| 624 // another. |
| 625 enum { |
| 626 FIRST_CODE_KIND_SUB_TYPE = LAST_TYPE + 1, |
| 627 FIRST_FIXED_ARRAY_SUB_TYPE = |
| 628 FIRST_CODE_KIND_SUB_TYPE + Code::NUMBER_OF_KINDS, |
| 629 FIRST_CODE_AGE_SUB_TYPE = |
| 630 FIRST_FIXED_ARRAY_SUB_TYPE + LAST_FIXED_ARRAY_SUB_TYPE + 1, |
| 631 OBJECT_STATS_COUNT = FIRST_CODE_AGE_SUB_TYPE + Code::kCodeAgeCount + 1 |
| 632 }; |
| 633 |
| 634 // Taking this lock prevents the GC from entering a phase that relocates |
| 635 // object references. |
| 636 class RelocationLock { |
| 637 public: |
| 638 explicit RelocationLock(Heap* heap) : heap_(heap) { |
| 639 heap_->relocation_mutex_.Lock(); |
| 640 } |
| 641 |
| 642 ~RelocationLock() { heap_->relocation_mutex_.Unlock(); } |
| 643 |
| 644 private: |
| 645 Heap* heap_; |
| 646 }; |
| 647 |
| 648 // An optional version of the above lock that can be used for some critical |
| 649 // sections on the mutator thread; only safe since the GC currently does not |
| 650 // do concurrent compaction. |
| 651 class OptionalRelocationLock { |
| 652 public: |
| 653 OptionalRelocationLock(Heap* heap, bool concurrent) |
| 654 : heap_(heap), concurrent_(concurrent) { |
| 655 if (concurrent_) heap_->relocation_mutex_.Lock(); |
| 656 } |
| 657 |
| 658 ~OptionalRelocationLock() { |
| 659 if (concurrent_) heap_->relocation_mutex_.Unlock(); |
| 660 } |
| 661 |
| 662 private: |
| 663 Heap* heap_; |
| 664 bool concurrent_; |
| 665 }; |
| 666 |
| 667 // Support for partial snapshots. After calling this we have a linear |
| 668 // space to write objects in each space. |
| 669 struct Chunk { |
| 670 uint32_t size; |
| 671 Address start; |
| 672 Address end; |
| 673 }; |
| 674 typedef List<Chunk> Reservation; |
| 675 |
| 676 static const intptr_t kMinimumOldGenerationAllocationLimit = |
| 677 8 * (Page::kPageSize > MB ? Page::kPageSize : MB); |
| 678 |
| 679 static const int kInitalOldGenerationLimitFactor = 2; |
| 680 |
| 681 #if V8_OS_ANDROID |
| 682 // Don't apply pointer multiplier on Android since it has no swap space and |
| 683 // should instead adapt it's heap size based on available physical memory. |
| 684 static const int kPointerMultiplier = 1; |
| 685 #else |
| 686 static const int kPointerMultiplier = i::kPointerSize / 4; |
| 687 #endif |
| 688 |
| 689 // The new space size has to be a power of 2. Sizes are in MB. |
| 690 static const int kMaxSemiSpaceSizeLowMemoryDevice = 1 * kPointerMultiplier; |
| 691 static const int kMaxSemiSpaceSizeMediumMemoryDevice = 4 * kPointerMultiplier; |
| 692 static const int kMaxSemiSpaceSizeHighMemoryDevice = 8 * kPointerMultiplier; |
| 693 static const int kMaxSemiSpaceSizeHugeMemoryDevice = 8 * kPointerMultiplier; |
| 694 |
| 695 // The old space size has to be a multiple of Page::kPageSize. |
| 696 // Sizes are in MB. |
| 697 static const int kMaxOldSpaceSizeLowMemoryDevice = 128 * kPointerMultiplier; |
| 698 static const int kMaxOldSpaceSizeMediumMemoryDevice = |
| 699 256 * kPointerMultiplier; |
| 700 static const int kMaxOldSpaceSizeHighMemoryDevice = 512 * kPointerMultiplier; |
| 701 static const int kMaxOldSpaceSizeHugeMemoryDevice = 700 * kPointerMultiplier; |
| 702 |
| 703 // The executable size has to be a multiple of Page::kPageSize. |
| 704 // Sizes are in MB. |
| 705 static const int kMaxExecutableSizeLowMemoryDevice = 96 * kPointerMultiplier; |
| 706 static const int kMaxExecutableSizeMediumMemoryDevice = |
| 707 192 * kPointerMultiplier; |
| 708 static const int kMaxExecutableSizeHighMemoryDevice = |
| 709 256 * kPointerMultiplier; |
| 710 static const int kMaxExecutableSizeHugeMemoryDevice = |
| 711 256 * kPointerMultiplier; |
| 712 |
| 713 static const int kTraceRingBufferSize = 512; |
| 714 static const int kStacktraceBufferSize = 512; |
| 715 |
| 716 static const double kMinHeapGrowingFactor; |
| 717 static const double kMaxHeapGrowingFactor; |
| 718 static const double kMaxHeapGrowingFactorMemoryConstrained; |
| 719 static const double kMaxHeapGrowingFactorIdle; |
| 720 static const double kTargetMutatorUtilization; |
| 721 |
| 722 // Sloppy mode arguments object size. |
| 723 static const int kSloppyArgumentsObjectSize = |
| 724 JSObject::kHeaderSize + 2 * kPointerSize; |
| 725 |
| 726 // Strict mode arguments has no callee so it is smaller. |
| 727 static const int kStrictArgumentsObjectSize = |
| 728 JSObject::kHeaderSize + 1 * kPointerSize; |
| 729 |
| 730 // Indicies for direct access into argument objects. |
| 731 static const int kArgumentsLengthIndex = 0; |
| 732 |
| 733 // callee is only valid in sloppy mode. |
| 734 static const int kArgumentsCalleeIndex = 1; |
| 735 |
| 736 static const int kNoGCFlags = 0; |
| 737 static const int kReduceMemoryFootprintMask = 1; |
| 738 static const int kAbortIncrementalMarkingMask = 2; |
| 739 static const int kFinalizeIncrementalMarkingMask = 4; |
| 740 |
| 741 // Making the heap iterable requires us to abort incremental marking. |
| 742 static const int kMakeHeapIterableMask = kAbortIncrementalMarkingMask; |
| 743 |
| 744 // The roots that have an index less than this are always in old space. |
| 745 static const int kOldSpaceRoots = 0x20; |
| 746 |
| 747 STATIC_ASSERT(kUndefinedValueRootIndex == |
| 748 Internals::kUndefinedValueRootIndex); |
| 749 STATIC_ASSERT(kNullValueRootIndex == Internals::kNullValueRootIndex); |
| 750 STATIC_ASSERT(kTrueValueRootIndex == Internals::kTrueValueRootIndex); |
| 751 STATIC_ASSERT(kFalseValueRootIndex == Internals::kFalseValueRootIndex); |
| 752 STATIC_ASSERT(kempty_stringRootIndex == Internals::kEmptyStringRootIndex); |
| 753 |
| 754 // Calculates the maximum amount of filler that could be required by the |
| 755 // given alignment. |
| 756 static int GetMaximumFillToAlign(AllocationAlignment alignment); |
| 757 // Calculates the actual amount of filler required for a given address at the |
| 758 // given alignment. |
| 759 static int GetFillToAlign(Address address, AllocationAlignment alignment); |
| 760 |
| 761 template <typename T> |
| 762 static inline bool IsOneByte(T t, int chars); |
| 763 |
| 764 // Callback function passed to Heap::Iterate etc. Copies an object if |
| 765 // necessary, the object might be promoted to an old space. The caller must |
| 766 // ensure the precondition that the object is (a) a heap object and (b) in |
| 767 // the heap's from space. |
| 768 static inline void ScavengePointer(HeapObject** p); |
| 769 static inline void ScavengeObject(HeapObject** p, HeapObject* object); |
| 770 |
| 771 // Slow part of scavenge object. |
| 772 static void ScavengeObjectSlow(HeapObject** p, HeapObject* object); |
| 773 |
| 774 static void FatalProcessOutOfMemory(const char* location, |
| 775 bool take_snapshot = false); |
| 776 |
| 777 static bool RootIsImmortalImmovable(int root_index); |
| 778 |
| 779 // Checks whether the space is valid. |
| 780 static bool IsValidAllocationSpace(AllocationSpace space); |
| 781 |
| 782 // An object may have an AllocationSite associated with it through a trailing |
| 783 // AllocationMemento. Its feedback should be updated when objects are found |
| 784 // in the heap. |
| 785 static inline void UpdateAllocationSiteFeedback(HeapObject* object, |
| 786 ScratchpadSlotMode mode); |
| 787 |
| 788 // Generated code can embed direct references to non-writable roots if |
| 789 // they are in new space. |
| 790 static bool RootCanBeWrittenAfterInitialization(RootListIndex root_index); |
| 791 |
| 792 // Zapping is needed for verify heap, and always done in debug builds. |
| 793 static inline bool ShouldZapGarbage() { |
| 794 #ifdef DEBUG |
| 795 return true; |
| 796 #else |
| 797 #ifdef VERIFY_HEAP |
| 798 return FLAG_verify_heap; |
| 799 #else |
| 800 return false; |
| 801 #endif |
| 802 #endif |
| 803 } |
| 804 |
| 805 static double HeapGrowingFactor(double gc_speed, double mutator_speed); |
| 806 |
| 807 // Copy block of memory from src to dst. Size of block should be aligned |
| 808 // by pointer size. |
| 809 static inline void CopyBlock(Address dst, Address src, int byte_size); |
| 810 |
| 811 // Optimized version of memmove for blocks with pointer size aligned sizes and |
| 812 // pointer size aligned addresses. |
| 813 static inline void MoveBlock(Address dst, Address src, int byte_size); |
596 | 814 |
597 // Set the stack limit in the roots_ array. Some architectures generate | 815 // Set the stack limit in the roots_ array. Some architectures generate |
598 // code that looks here, because it is faster than loading from the static | 816 // code that looks here, because it is faster than loading from the static |
599 // jslimit_/real_jslimit_ variable in the StackGuard. | 817 // jslimit_/real_jslimit_ variable in the StackGuard. |
600 void SetStackLimits(); | 818 void SetStackLimits(); |
601 | 819 |
602 // Notifies the heap that is ok to start marking or other activities that | 820 // Notifies the heap that is ok to start marking or other activities that |
603 // should not happen during deserialization. | 821 // should not happen during deserialization. |
604 void NotifyDeserializationComplete(); | 822 void NotifyDeserializationComplete(); |
605 | 823 |
606 // Returns whether SetUp has been called. | 824 // Returns whether SetUp has been called. |
607 bool HasBeenSetUp(); | 825 bool HasBeenSetUp(); |
608 | 826 |
609 // Returns the maximum amount of memory reserved for the heap. For | |
610 // the young generation, we reserve 4 times the amount needed for a | |
611 // semi space. The young generation consists of two semi spaces and | |
612 // we reserve twice the amount needed for those in order to ensure | |
613 // that new space can be aligned to its size. | |
614 intptr_t MaxReserved() { | |
615 return 4 * reserved_semispace_size_ + max_old_generation_size_; | |
616 } | |
617 int MaxSemiSpaceSize() { return max_semi_space_size_; } | |
618 int ReservedSemiSpaceSize() { return reserved_semispace_size_; } | |
619 int InitialSemiSpaceSize() { return initial_semispace_size_; } | |
620 int TargetSemiSpaceSize() { return target_semispace_size_; } | |
621 intptr_t MaxOldGenerationSize() { return max_old_generation_size_; } | |
622 intptr_t MaxExecutableSize() { return max_executable_size_; } | |
623 | |
624 // Returns the capacity of the heap in bytes w/o growing. Heap grows when | |
625 // more spaces are needed until it reaches the limit. | |
626 intptr_t Capacity(); | |
627 | |
628 // Returns the amount of memory currently committed for the heap. | |
629 intptr_t CommittedMemory(); | |
630 | |
631 // Returns the amount of memory currently committed for the old space. | |
632 intptr_t CommittedOldGenerationMemory(); | |
633 | |
634 // Returns the amount of executable memory currently committed for the heap. | |
635 intptr_t CommittedMemoryExecutable(); | |
636 | |
637 // Returns the amount of phyical memory currently committed for the heap. | |
638 size_t CommittedPhysicalMemory(); | |
639 | |
640 // Returns the maximum amount of memory ever committed for the heap. | |
641 intptr_t MaximumCommittedMemory() { return maximum_committed_; } | |
642 | |
643 // Updates the maximum committed memory for the heap. Should be called | |
644 // whenever a space grows. | |
645 void UpdateMaximumCommitted(); | |
646 | |
647 // Returns the available bytes in space w/o growing. | |
648 // Heap doesn't guarantee that it can allocate an object that requires | |
649 // all available bytes. Check MaxHeapObjectSize() instead. | |
650 intptr_t Available(); | |
651 | |
652 // Returns of size of all objects residing in the heap. | |
653 intptr_t SizeOfObjects(); | |
654 | |
655 intptr_t old_generation_allocation_limit() const { | 827 intptr_t old_generation_allocation_limit() const { |
656 return old_generation_allocation_limit_; | 828 return old_generation_allocation_limit_; |
657 } | 829 } |
658 | 830 |
659 // Return the starting address and a mask for the new space. And-masking an | |
660 // address with the mask will result in the start address of the new space | |
661 // for all addresses in either semispace. | |
662 Address NewSpaceStart() { return new_space_.start(); } | |
663 uintptr_t NewSpaceMask() { return new_space_.mask(); } | |
664 Address NewSpaceTop() { return new_space_.top(); } | |
665 | |
666 NewSpace* new_space() { return &new_space_; } | |
667 OldSpace* old_space() { return old_space_; } | |
668 OldSpace* code_space() { return code_space_; } | |
669 MapSpace* map_space() { return map_space_; } | |
670 LargeObjectSpace* lo_space() { return lo_space_; } | |
671 PagedSpace* paged_space(int idx) { | |
672 switch (idx) { | |
673 case OLD_SPACE: | |
674 return old_space(); | |
675 case MAP_SPACE: | |
676 return map_space(); | |
677 case CODE_SPACE: | |
678 return code_space(); | |
679 case NEW_SPACE: | |
680 case LO_SPACE: | |
681 UNREACHABLE(); | |
682 } | |
683 return NULL; | |
684 } | |
685 Space* space(int idx) { | |
686 switch (idx) { | |
687 case NEW_SPACE: | |
688 return new_space(); | |
689 case LO_SPACE: | |
690 return lo_space(); | |
691 default: | |
692 return paged_space(idx); | |
693 } | |
694 } | |
695 | |
696 // Returns name of the space. | |
697 const char* GetSpaceName(int idx); | |
698 | |
699 bool always_allocate() { return always_allocate_scope_depth_ != 0; } | 831 bool always_allocate() { return always_allocate_scope_depth_ != 0; } |
700 Address always_allocate_scope_depth_address() { | 832 Address always_allocate_scope_depth_address() { |
701 return reinterpret_cast<Address>(&always_allocate_scope_depth_); | 833 return reinterpret_cast<Address>(&always_allocate_scope_depth_); |
702 } | 834 } |
703 | 835 |
704 Address* NewSpaceAllocationTopAddress() { | 836 Address* NewSpaceAllocationTopAddress() { |
705 return new_space_.allocation_top_address(); | 837 return new_space_.allocation_top_address(); |
706 } | 838 } |
707 Address* NewSpaceAllocationLimitAddress() { | 839 Address* NewSpaceAllocationLimitAddress() { |
708 return new_space_.allocation_limit_address(); | 840 return new_space_.allocation_limit_address(); |
709 } | 841 } |
710 | 842 |
711 Address* OldSpaceAllocationTopAddress() { | 843 Address* OldSpaceAllocationTopAddress() { |
712 return old_space_->allocation_top_address(); | 844 return old_space_->allocation_top_address(); |
713 } | 845 } |
714 Address* OldSpaceAllocationLimitAddress() { | 846 Address* OldSpaceAllocationLimitAddress() { |
715 return old_space_->allocation_limit_address(); | 847 return old_space_->allocation_limit_address(); |
716 } | 848 } |
717 | 849 |
718 // TODO(hpayer): There is still a missmatch between capacity and actual | 850 // TODO(hpayer): There is still a missmatch between capacity and actual |
719 // committed memory size. | 851 // committed memory size. |
720 bool CanExpandOldGeneration(int size) { | 852 bool CanExpandOldGeneration(int size) { |
721 return (CommittedOldGenerationMemory() + size) < MaxOldGenerationSize(); | 853 return (CommittedOldGenerationMemory() + size) < MaxOldGenerationSize(); |
722 } | 854 } |
723 | 855 |
724 // Returns a deep copy of the JavaScript object. | |
725 // Properties and elements are copied too. | |
726 // Optionally takes an AllocationSite to be appended in an AllocationMemento. | |
727 MUST_USE_RESULT AllocationResult | |
728 CopyJSObject(JSObject* source, AllocationSite* site = NULL); | |
729 | |
730 // Calculates the maximum amount of filler that could be required by the | |
731 // given alignment. | |
732 static int GetMaximumFillToAlign(AllocationAlignment alignment); | |
733 // Calculates the actual amount of filler required for a given address at the | |
734 // given alignment. | |
735 static int GetFillToAlign(Address address, AllocationAlignment alignment); | |
736 | |
737 // Creates a filler object and returns a heap object immediately after it. | |
738 MUST_USE_RESULT HeapObject* PrecedeWithFiller(HeapObject* object, | |
739 int filler_size); | |
740 // Creates a filler object if needed for alignment and returns a heap object | |
741 // immediately after it. If any space is left after the returned object, | |
742 // another filler object is created so the over allocated memory is iterable. | |
743 MUST_USE_RESULT HeapObject* AlignWithFiller(HeapObject* object, | |
744 int object_size, | |
745 int allocation_size, | |
746 AllocationAlignment alignment); | |
747 | |
748 // Clear the Instanceof cache (used when a prototype changes). | 856 // Clear the Instanceof cache (used when a prototype changes). |
749 inline void ClearInstanceofCache(); | 857 inline void ClearInstanceofCache(); |
750 | 858 |
751 // Iterates the whole code space to clear all ICs of the given kind. | 859 // Iterates the whole code space to clear all ICs of the given kind. |
752 void ClearAllICsByKind(Code::Kind kind); | 860 void ClearAllICsByKind(Code::Kind kind); |
753 | 861 |
754 // FreeSpace objects have a null map after deserialization. Update the map. | 862 // FreeSpace objects have a null map after deserialization. Update the map. |
755 void RepairFreeListsAfterDeserialization(); | 863 void RepairFreeListsAfterDeserialization(); |
756 | 864 |
757 template <typename T> | |
758 static inline bool IsOneByte(T t, int chars); | |
759 | |
760 // Move len elements within a given array from src_index index to dst_index | 865 // Move len elements within a given array from src_index index to dst_index |
761 // index. | 866 // index. |
762 void MoveElements(FixedArray* array, int dst_index, int src_index, int len); | 867 void MoveElements(FixedArray* array, int dst_index, int src_index, int len); |
763 | 868 |
764 // Sloppy mode arguments object size. | |
765 static const int kSloppyArgumentsObjectSize = | |
766 JSObject::kHeaderSize + 2 * kPointerSize; | |
767 // Strict mode arguments has no callee so it is smaller. | |
768 static const int kStrictArgumentsObjectSize = | |
769 JSObject::kHeaderSize + 1 * kPointerSize; | |
770 // Indicies for direct access into argument objects. | |
771 static const int kArgumentsLengthIndex = 0; | |
772 // callee is only valid in sloppy mode. | |
773 static const int kArgumentsCalleeIndex = 1; | |
774 | |
775 // Finalizes an external string by deleting the associated external | 869 // Finalizes an external string by deleting the associated external |
776 // data and clearing the resource pointer. | 870 // data and clearing the resource pointer. |
777 inline void FinalizeExternalString(String* string); | 871 inline void FinalizeExternalString(String* string); |
778 | 872 |
779 // Initialize a filler object to keep the ability to iterate over the heap | 873 // Initialize a filler object to keep the ability to iterate over the heap |
780 // when introducing gaps within pages. | 874 // when introducing gaps within pages. |
781 void CreateFillerObjectAt(Address addr, int size); | 875 void CreateFillerObjectAt(Address addr, int size); |
782 | 876 |
783 bool CanMoveObjectStart(HeapObject* object); | 877 bool CanMoveObjectStart(HeapObject* object); |
784 | 878 |
785 // Indicates whether live bytes adjustment is triggered | |
786 // - from within the GC code before sweeping started (SEQUENTIAL_TO_SWEEPER), | |
787 // - or from within GC (CONCURRENT_TO_SWEEPER), | |
788 // - or mutator code (CONCURRENT_TO_SWEEPER). | |
789 enum InvocationMode { SEQUENTIAL_TO_SWEEPER, CONCURRENT_TO_SWEEPER }; | |
790 | |
791 // Maintain consistency of live bytes during incremental marking. | 879 // Maintain consistency of live bytes during incremental marking. |
792 void AdjustLiveBytes(HeapObject* object, int by, InvocationMode mode); | 880 void AdjustLiveBytes(HeapObject* object, int by, InvocationMode mode); |
793 | 881 |
794 // Trim the given array from the left. Note that this relocates the object | 882 // Trim the given array from the left. Note that this relocates the object |
795 // start and hence is only valid if there is only a single reference to it. | 883 // start and hence is only valid if there is only a single reference to it. |
796 FixedArrayBase* LeftTrimFixedArray(FixedArrayBase* obj, int elements_to_trim); | 884 FixedArrayBase* LeftTrimFixedArray(FixedArrayBase* obj, int elements_to_trim); |
797 | 885 |
798 // Trim the given array from the right. | 886 // Trim the given array from the right. |
799 template<Heap::InvocationMode mode> | 887 template<Heap::InvocationMode mode> |
800 void RightTrimFixedArray(FixedArrayBase* obj, int elements_to_trim); | 888 void RightTrimFixedArray(FixedArrayBase* obj, int elements_to_trim); |
801 | 889 |
802 // Converts the given boolean condition to JavaScript boolean value. | 890 // Converts the given boolean condition to JavaScript boolean value. |
803 inline Object* ToBoolean(bool condition); | 891 inline Object* ToBoolean(bool condition); |
804 | 892 |
805 // Performs garbage collection operation. | |
806 // Returns whether there is a chance that another major GC could | |
807 // collect more garbage. | |
808 inline bool CollectGarbage( | |
809 AllocationSpace space, const char* gc_reason = NULL, | |
810 const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags); | |
811 | |
812 static const int kNoGCFlags = 0; | |
813 static const int kReduceMemoryFootprintMask = 1; | |
814 static const int kAbortIncrementalMarkingMask = 2; | |
815 static const int kFinalizeIncrementalMarkingMask = 4; | |
816 | |
817 // Making the heap iterable requires us to abort incremental marking. | |
818 static const int kMakeHeapIterableMask = kAbortIncrementalMarkingMask; | |
819 | |
820 // Invoked when GC was requested via the stack guard. | |
821 void HandleGCRequest(); | |
822 | |
823 // Attempt to over-approximate the weak closure by marking object groups and | 893 // Attempt to over-approximate the weak closure by marking object groups and |
824 // implicit references from global handles, but don't atomically complete | 894 // implicit references from global handles, but don't atomically complete |
825 // marking. If we continue to mark incrementally, we might have marked | 895 // marking. If we continue to mark incrementally, we might have marked |
826 // objects that die later. | 896 // objects that die later. |
827 void OverApproximateWeakClosure(const char* gc_reason); | 897 void OverApproximateWeakClosure(const char* gc_reason); |
828 | 898 |
829 // Performs a full garbage collection. If (flags & kMakeHeapIterableMask) is | |
830 // non-zero, then the slower precise sweeper is used, which leaves the heap | |
831 // in a state where we can iterate over the heap visiting all objects. | |
832 void CollectAllGarbage( | |
833 int flags = kFinalizeIncrementalMarkingMask, const char* gc_reason = NULL, | |
834 const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags); | |
835 | |
836 // Last hope GC, should try to squeeze as much as possible. | |
837 void CollectAllAvailableGarbage(const char* gc_reason = NULL); | |
838 | |
839 // Check whether the heap is currently iterable. | 899 // Check whether the heap is currently iterable. |
840 bool IsHeapIterable(); | 900 bool IsHeapIterable(); |
841 | 901 |
842 // Notify the heap that a context has been disposed. | 902 // Notify the heap that a context has been disposed. |
843 int NotifyContextDisposed(bool dependant_context); | 903 int NotifyContextDisposed(bool dependant_context); |
844 | 904 |
845 // Start incremental marking and ensure that idle time handler can perform | |
846 // incremental steps. | |
847 void StartIdleIncrementalMarking(); | |
848 | |
849 // Starts incremental marking assuming incremental marking is currently | |
850 // stopped. | |
851 void StartIncrementalMarking(int gc_flags, | |
852 const GCCallbackFlags gc_callback_flags, | |
853 const char* reason = nullptr); | |
854 | |
855 // Performs incremental marking steps of step_size_in_bytes as long as | |
856 // deadline_ins_ms is not reached. step_size_in_bytes can be 0 to compute | |
857 // an estimate increment. Returns the remaining time that cannot be used | |
858 // for incremental marking anymore because a single step would exceed the | |
859 // deadline. | |
860 double AdvanceIncrementalMarking( | |
861 intptr_t step_size_in_bytes, double deadline_in_ms, | |
862 IncrementalMarking::StepActions step_actions); | |
863 | |
864 void FinalizeIncrementalMarkingIfComplete(const char* comment); | 905 void FinalizeIncrementalMarkingIfComplete(const char* comment); |
865 | 906 |
866 inline void increment_scan_on_scavenge_pages() { | 907 inline void increment_scan_on_scavenge_pages() { |
867 scan_on_scavenge_pages_++; | 908 scan_on_scavenge_pages_++; |
868 if (FLAG_gc_verbose) { | 909 if (FLAG_gc_verbose) { |
869 PrintF("Scan-on-scavenge pages: %d\n", scan_on_scavenge_pages_); | 910 PrintF("Scan-on-scavenge pages: %d\n", scan_on_scavenge_pages_); |
870 } | 911 } |
871 } | 912 } |
872 | 913 |
873 inline void decrement_scan_on_scavenge_pages() { | 914 inline void decrement_scan_on_scavenge_pages() { |
874 scan_on_scavenge_pages_--; | 915 scan_on_scavenge_pages_--; |
875 if (FLAG_gc_verbose) { | 916 if (FLAG_gc_verbose) { |
876 PrintF("Scan-on-scavenge pages: %d\n", scan_on_scavenge_pages_); | 917 PrintF("Scan-on-scavenge pages: %d\n", scan_on_scavenge_pages_); |
877 } | 918 } |
878 } | 919 } |
879 | 920 |
880 PromotionQueue* promotion_queue() { return &promotion_queue_; } | |
881 | |
882 void AddGCPrologueCallback(v8::Isolate::GCCallback callback, | |
883 GCType gc_type_filter, bool pass_isolate = true); | |
884 void RemoveGCPrologueCallback(v8::Isolate::GCCallback callback); | |
885 | |
886 void AddGCEpilogueCallback(v8::Isolate::GCCallback callback, | |
887 GCType gc_type_filter, bool pass_isolate = true); | |
888 void RemoveGCEpilogueCallback(v8::Isolate::GCCallback callback); | |
889 | |
890 // Heap root getters. We have versions with and without type::cast() here. | 921 // Heap root getters. We have versions with and without type::cast() here. |
891 // You can't use type::cast during GC because the assert fails. | 922 // You can't use type::cast during GC because the assert fails. |
892 // TODO(1490): Try removing the unchecked accessors, now that GC marking does | 923 // TODO(1490): Try removing the unchecked accessors, now that GC marking does |
893 // not corrupt the map. | 924 // not corrupt the map. |
894 #define ROOT_ACCESSOR(type, name, camel_name) \ | 925 #define ROOT_ACCESSOR(type, name, camel_name) \ |
895 inline type* name(); \ | 926 inline type* name(); \ |
896 type* raw_unchecked_##name() { \ | 927 type* raw_unchecked_##name() { \ |
897 return reinterpret_cast<type*>(roots_[k##camel_name##RootIndex]); \ | 928 return reinterpret_cast<type*>(roots_[k##camel_name##RootIndex]); \ |
898 } | 929 } |
899 ROOT_LIST(ROOT_ACCESSOR) | 930 ROOT_LIST(ROOT_ACCESSOR) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 } | 968 } |
938 | 969 |
939 void set_encountered_weak_cells(Object* weak_cell) { | 970 void set_encountered_weak_cells(Object* weak_cell) { |
940 encountered_weak_cells_ = weak_cell; | 971 encountered_weak_cells_ = weak_cell; |
941 } | 972 } |
942 Object* encountered_weak_cells() const { return encountered_weak_cells_; } | 973 Object* encountered_weak_cells() const { return encountered_weak_cells_; } |
943 | 974 |
944 // Number of mark-sweeps. | 975 // Number of mark-sweeps. |
945 int ms_count() const { return ms_count_; } | 976 int ms_count() const { return ms_count_; } |
946 | 977 |
947 // Iterates over all roots in the heap. | |
948 void IterateRoots(ObjectVisitor* v, VisitMode mode); | |
949 // Iterates over all strong roots in the heap. | |
950 void IterateStrongRoots(ObjectVisitor* v, VisitMode mode); | |
951 // Iterates over entries in the smi roots list. Only interesting to the | |
952 // serializer/deserializer, since GC does not care about smis. | |
953 void IterateSmiRoots(ObjectVisitor* v); | |
954 // Iterates over all the other roots in the heap. | |
955 void IterateWeakRoots(ObjectVisitor* v, VisitMode mode); | |
956 | |
957 // Iterate pointers to from semispace of new space found in memory interval | |
958 // from start to end within |object|. | |
959 void IterateAndMarkPointersToFromSpace(HeapObject* object, Address start, | |
960 Address end, bool record_slots, | |
961 ObjectSlotCallback callback); | |
962 | |
963 // Returns whether the object resides in new space. | |
964 inline bool InNewSpace(Object* object); | |
965 inline bool InNewSpace(Address address); | |
966 inline bool InNewSpacePage(Address address); | |
967 inline bool InFromSpace(Object* object); | |
968 inline bool InToSpace(Object* object); | |
969 | |
970 // Returns whether the object resides in old space. | |
971 inline bool InOldSpace(Address address); | |
972 inline bool InOldSpace(Object* object); | |
973 | |
974 // Checks whether an address/object in the heap (including auxiliary | |
975 // area and unused area). | |
976 bool Contains(Address addr); | |
977 bool Contains(HeapObject* value); | |
978 | |
979 // Checks whether an address/object in a space. | |
980 // Currently used by tests, serialization and heap verification only. | |
981 bool InSpace(Address addr, AllocationSpace space); | |
982 bool InSpace(HeapObject* value, AllocationSpace space); | |
983 | |
984 // Checks whether the space is valid. | |
985 static bool IsValidAllocationSpace(AllocationSpace space); | |
986 | |
987 // Checks whether the given object is allowed to be migrated from it's | 978 // Checks whether the given object is allowed to be migrated from it's |
988 // current space into the given destination space. Used for debugging. | 979 // current space into the given destination space. Used for debugging. |
989 inline bool AllowedToBeMigrated(HeapObject* object, AllocationSpace dest); | 980 inline bool AllowedToBeMigrated(HeapObject* object, AllocationSpace dest); |
990 | 981 |
991 // Sets the stub_cache_ (only used when expanding the dictionary). | 982 // Sets the stub_cache_ (only used when expanding the dictionary). |
992 void public_set_code_stubs(UnseededNumberDictionary* value) { | 983 void public_set_code_stubs(UnseededNumberDictionary* value) { |
993 roots_[kCodeStubsRootIndex] = value; | 984 roots_[kCodeStubsRootIndex] = value; |
994 } | 985 } |
995 | 986 |
996 // Sets the non_monomorphic_cache_ (only used when expanding the dictionary). | 987 // Sets the non_monomorphic_cache_ (only used when expanding the dictionary). |
(...skipping 13 matching lines...) Expand all Loading... |
1010 roots_[kMaterializedObjectsRootIndex] = objects; | 1001 roots_[kMaterializedObjectsRootIndex] = objects; |
1011 } | 1002 } |
1012 | 1003 |
1013 // Generated code can embed this address to get access to the roots. | 1004 // Generated code can embed this address to get access to the roots. |
1014 Object** roots_array_start() { return roots_; } | 1005 Object** roots_array_start() { return roots_; } |
1015 | 1006 |
1016 Address* store_buffer_top_address() { | 1007 Address* store_buffer_top_address() { |
1017 return reinterpret_cast<Address*>(&roots_[kStoreBufferTopRootIndex]); | 1008 return reinterpret_cast<Address*>(&roots_[kStoreBufferTopRootIndex]); |
1018 } | 1009 } |
1019 | 1010 |
1020 static bool RootIsImmortalImmovable(int root_index); | |
1021 void CheckHandleCount(); | 1011 void CheckHandleCount(); |
1022 | 1012 |
1023 #ifdef VERIFY_HEAP | |
1024 // Verify the heap is in its normal state before or after a GC. | |
1025 void Verify(); | |
1026 #endif | |
1027 | |
1028 #ifdef DEBUG | |
1029 void Print(); | |
1030 void PrintHandles(); | |
1031 | |
1032 // Report heap statistics. | |
1033 void ReportHeapStatistics(const char* title); | |
1034 void ReportCodeStatistics(const char* title); | |
1035 #endif | |
1036 | |
1037 // Zapping is needed for verify heap, and always done in debug builds. | |
1038 static inline bool ShouldZapGarbage() { | |
1039 #ifdef DEBUG | |
1040 return true; | |
1041 #else | |
1042 #ifdef VERIFY_HEAP | |
1043 return FLAG_verify_heap; | |
1044 #else | |
1045 return false; | |
1046 #endif | |
1047 #endif | |
1048 } | |
1049 | |
1050 // Number of "runtime allocations" done so far. | 1013 // Number of "runtime allocations" done so far. |
1051 uint32_t allocations_count() { return allocations_count_; } | 1014 uint32_t allocations_count() { return allocations_count_; } |
1052 | 1015 |
1053 // Returns deterministic "time" value in ms. Works only with | 1016 // Returns deterministic "time" value in ms. Works only with |
1054 // FLAG_verify_predictable. | 1017 // FLAG_verify_predictable. |
1055 double synthetic_time() { return allocations_count_ / 2.0; } | 1018 double synthetic_time() { return allocations_count_ / 2.0; } |
1056 | 1019 |
1057 // Print short heap statistics. | 1020 // Print short heap statistics. |
1058 void PrintShortHeapStatistics(); | 1021 void PrintShortHeapStatistics(); |
1059 | 1022 |
1060 size_t object_count_last_gc(size_t index) { | 1023 size_t object_count_last_gc(size_t index) { |
1061 return index < OBJECT_STATS_COUNT ? object_counts_last_time_[index] : 0; | 1024 return index < OBJECT_STATS_COUNT ? object_counts_last_time_[index] : 0; |
1062 } | 1025 } |
| 1026 |
1063 size_t object_size_last_gc(size_t index) { | 1027 size_t object_size_last_gc(size_t index) { |
1064 return index < OBJECT_STATS_COUNT ? object_sizes_last_time_[index] : 0; | 1028 return index < OBJECT_STATS_COUNT ? object_sizes_last_time_[index] : 0; |
1065 } | 1029 } |
1066 | 1030 |
1067 // Write barrier support for address[offset] = o. | 1031 // Write barrier support for address[offset] = o. |
1068 INLINE(void RecordWrite(Address address, int offset)); | 1032 INLINE(void RecordWrite(Address address, int offset)); |
1069 | 1033 |
1070 // Write barrier support for address[start : start + len[ = o. | 1034 // Write barrier support for address[start : start + len[ = o. |
1071 INLINE(void RecordWrites(Address address, int start, int len)); | 1035 INLINE(void RecordWrites(Address address, int start, int len)); |
1072 | 1036 |
1073 enum HeapState { NOT_IN_GC, SCAVENGE, MARK_COMPACT }; | |
1074 inline HeapState gc_state() { return gc_state_; } | 1037 inline HeapState gc_state() { return gc_state_; } |
1075 | 1038 |
1076 inline bool IsInGCPostProcessing() { return gc_post_processing_depth_ > 0; } | 1039 inline bool IsInGCPostProcessing() { return gc_post_processing_depth_ > 0; } |
1077 | 1040 |
1078 #ifdef DEBUG | |
1079 void set_allocation_timeout(int timeout) { allocation_timeout_ = timeout; } | |
1080 | |
1081 void TracePathToObjectFrom(Object* target, Object* root); | |
1082 void TracePathToObject(Object* target); | |
1083 void TracePathToGlobal(); | |
1084 #endif | |
1085 | |
1086 // Callback function passed to Heap::Iterate etc. Copies an object if | |
1087 // necessary, the object might be promoted to an old space. The caller must | |
1088 // ensure the precondition that the object is (a) a heap object and (b) in | |
1089 // the heap's from space. | |
1090 static inline void ScavengePointer(HeapObject** p); | |
1091 static inline void ScavengeObject(HeapObject** p, HeapObject* object); | |
1092 | |
1093 // Slow part of scavenge object. | |
1094 static void ScavengeObjectSlow(HeapObject** p, HeapObject* object); | |
1095 | |
1096 enum ScratchpadSlotMode { IGNORE_SCRATCHPAD_SLOT, RECORD_SCRATCHPAD_SLOT }; | |
1097 | |
1098 // If an object has an AllocationMemento trailing it, return it, otherwise | 1041 // If an object has an AllocationMemento trailing it, return it, otherwise |
1099 // return NULL; | 1042 // return NULL; |
1100 inline AllocationMemento* FindAllocationMemento(HeapObject* object); | 1043 inline AllocationMemento* FindAllocationMemento(HeapObject* object); |
1101 | 1044 |
1102 // An object may have an AllocationSite associated with it through a trailing | |
1103 // AllocationMemento. Its feedback should be updated when objects are found | |
1104 // in the heap. | |
1105 static inline void UpdateAllocationSiteFeedback(HeapObject* object, | |
1106 ScratchpadSlotMode mode); | |
1107 | |
1108 // Support for partial snapshots. After calling this we have a linear | |
1109 // space to write objects in each space. | |
1110 struct Chunk { | |
1111 uint32_t size; | |
1112 Address start; | |
1113 Address end; | |
1114 }; | |
1115 | |
1116 typedef List<Chunk> Reservation; | |
1117 | |
1118 // Returns false if not able to reserve. | 1045 // Returns false if not able to reserve. |
1119 bool ReserveSpace(Reservation* reservations); | 1046 bool ReserveSpace(Reservation* reservations); |
1120 | 1047 |
1121 // | 1048 // |
1122 // Support for the API. | 1049 // Support for the API. |
1123 // | 1050 // |
1124 | 1051 |
1125 void CreateApiObjects(); | 1052 void CreateApiObjects(); |
1126 | 1053 |
1127 inline intptr_t PromotedTotalSize() { | |
1128 int64_t total = PromotedSpaceSizeOfObjects() + PromotedExternalMemorySize(); | |
1129 if (total > std::numeric_limits<intptr_t>::max()) { | |
1130 // TODO(erikcorry): Use uintptr_t everywhere we do heap size calculations. | |
1131 return std::numeric_limits<intptr_t>::max(); | |
1132 } | |
1133 if (total < 0) return 0; | |
1134 return static_cast<intptr_t>(total); | |
1135 } | |
1136 | |
1137 inline intptr_t OldGenerationSpaceAvailable() { | |
1138 return old_generation_allocation_limit_ - PromotedTotalSize(); | |
1139 } | |
1140 | |
1141 inline intptr_t OldGenerationCapacityAvailable() { | |
1142 return max_old_generation_size_ - PromotedTotalSize(); | |
1143 } | |
1144 | |
1145 static const intptr_t kMinimumOldGenerationAllocationLimit = | |
1146 8 * (Page::kPageSize > MB ? Page::kPageSize : MB); | |
1147 | |
1148 static const int kInitalOldGenerationLimitFactor = 2; | |
1149 | |
1150 #if V8_OS_ANDROID | |
1151 // Don't apply pointer multiplier on Android since it has no swap space and | |
1152 // should instead adapt it's heap size based on available physical memory. | |
1153 static const int kPointerMultiplier = 1; | |
1154 #else | |
1155 static const int kPointerMultiplier = i::kPointerSize / 4; | |
1156 #endif | |
1157 | |
1158 // The new space size has to be a power of 2. Sizes are in MB. | |
1159 static const int kMaxSemiSpaceSizeLowMemoryDevice = 1 * kPointerMultiplier; | |
1160 static const int kMaxSemiSpaceSizeMediumMemoryDevice = 4 * kPointerMultiplier; | |
1161 static const int kMaxSemiSpaceSizeHighMemoryDevice = 8 * kPointerMultiplier; | |
1162 static const int kMaxSemiSpaceSizeHugeMemoryDevice = 8 * kPointerMultiplier; | |
1163 | |
1164 // The old space size has to be a multiple of Page::kPageSize. | |
1165 // Sizes are in MB. | |
1166 static const int kMaxOldSpaceSizeLowMemoryDevice = 128 * kPointerMultiplier; | |
1167 static const int kMaxOldSpaceSizeMediumMemoryDevice = | |
1168 256 * kPointerMultiplier; | |
1169 static const int kMaxOldSpaceSizeHighMemoryDevice = 512 * kPointerMultiplier; | |
1170 static const int kMaxOldSpaceSizeHugeMemoryDevice = 700 * kPointerMultiplier; | |
1171 | |
1172 // The executable size has to be a multiple of Page::kPageSize. | |
1173 // Sizes are in MB. | |
1174 static const int kMaxExecutableSizeLowMemoryDevice = 96 * kPointerMultiplier; | |
1175 static const int kMaxExecutableSizeMediumMemoryDevice = | |
1176 192 * kPointerMultiplier; | |
1177 static const int kMaxExecutableSizeHighMemoryDevice = | |
1178 256 * kPointerMultiplier; | |
1179 static const int kMaxExecutableSizeHugeMemoryDevice = | |
1180 256 * kPointerMultiplier; | |
1181 | |
1182 static const int kTraceRingBufferSize = 512; | |
1183 static const int kStacktraceBufferSize = 512; | |
1184 | |
1185 static const double kMinHeapGrowingFactor; | |
1186 static const double kMaxHeapGrowingFactor; | |
1187 static const double kMaxHeapGrowingFactorMemoryConstrained; | |
1188 static const double kMaxHeapGrowingFactorIdle; | |
1189 static const double kTargetMutatorUtilization; | |
1190 | |
1191 static double HeapGrowingFactor(double gc_speed, double mutator_speed); | |
1192 | |
1193 // Calculates the allocation limit based on a given growing factor and a | 1054 // Calculates the allocation limit based on a given growing factor and a |
1194 // given old generation size. | 1055 // given old generation size. |
1195 intptr_t CalculateOldGenerationAllocationLimit(double factor, | 1056 intptr_t CalculateOldGenerationAllocationLimit(double factor, |
1196 intptr_t old_gen_size); | 1057 intptr_t old_gen_size); |
1197 | 1058 |
1198 // Sets the allocation limit to trigger the next full garbage collection. | 1059 // Sets the allocation limit to trigger the next full garbage collection. |
1199 void SetOldGenerationAllocationLimit(intptr_t old_gen_size, double gc_speed, | 1060 void SetOldGenerationAllocationLimit(intptr_t old_gen_size, double gc_speed, |
1200 double mutator_speed); | 1061 double mutator_speed); |
1201 | 1062 |
1202 // Decrease the allocation limit if the new limit based on the given | 1063 // Decrease the allocation limit if the new limit based on the given |
1203 // parameters is lower than the current limit. | 1064 // parameters is lower than the current limit. |
1204 void DampenOldGenerationAllocationLimit(intptr_t old_gen_size, | 1065 void DampenOldGenerationAllocationLimit(intptr_t old_gen_size, |
1205 double gc_speed, | 1066 double gc_speed, |
1206 double mutator_speed); | 1067 double mutator_speed); |
1207 | 1068 |
1208 // Indicates whether inline bump-pointer allocation has been disabled. | |
1209 bool inline_allocation_disabled() { return inline_allocation_disabled_; } | |
1210 | |
1211 // Switch whether inline bump-pointer allocation should be used. | |
1212 void EnableInlineAllocation(); | |
1213 void DisableInlineAllocation(); | |
1214 | |
1215 // Implements the corresponding V8 API function. | 1069 // Implements the corresponding V8 API function. |
1216 bool IdleNotification(double deadline_in_seconds); | 1070 bool IdleNotification(double deadline_in_seconds); |
1217 bool IdleNotification(int idle_time_in_ms); | 1071 bool IdleNotification(int idle_time_in_ms); |
1218 | 1072 |
1219 double MonotonicallyIncreasingTimeInMs(); | 1073 double MonotonicallyIncreasingTimeInMs(); |
1220 | 1074 |
1221 // Declare all the root indices. This defines the root list order. | |
1222 enum RootListIndex { | |
1223 #define ROOT_INDEX_DECLARATION(type, name, camel_name) k##camel_name##RootIndex, | |
1224 STRONG_ROOT_LIST(ROOT_INDEX_DECLARATION) | |
1225 #undef ROOT_INDEX_DECLARATION | |
1226 | |
1227 #define STRING_INDEX_DECLARATION(name, str) k##name##RootIndex, | |
1228 INTERNALIZED_STRING_LIST(STRING_INDEX_DECLARATION) | |
1229 #undef STRING_DECLARATION | |
1230 | |
1231 #define SYMBOL_INDEX_DECLARATION(name) k##name##RootIndex, | |
1232 PRIVATE_SYMBOL_LIST(SYMBOL_INDEX_DECLARATION) | |
1233 #undef SYMBOL_INDEX_DECLARATION | |
1234 | |
1235 #define SYMBOL_INDEX_DECLARATION(name, varname, description) k##name##RootIndex, | |
1236 PUBLIC_SYMBOL_LIST(SYMBOL_INDEX_DECLARATION) | |
1237 #undef SYMBOL_INDEX_DECLARATION | |
1238 | |
1239 // Utility type maps | |
1240 #define DECLARE_STRUCT_MAP(NAME, Name, name) k##Name##MapRootIndex, | |
1241 STRUCT_LIST(DECLARE_STRUCT_MAP) | |
1242 #undef DECLARE_STRUCT_MAP | |
1243 kStringTableRootIndex, | |
1244 | |
1245 #define ROOT_INDEX_DECLARATION(type, name, camel_name) k##camel_name##RootIndex, | |
1246 SMI_ROOT_LIST(ROOT_INDEX_DECLARATION) | |
1247 #undef ROOT_INDEX_DECLARATION | |
1248 kRootListLength, | |
1249 kStrongRootListLength = kStringTableRootIndex, | |
1250 kSmiRootsStart = kStringTableRootIndex + 1 | |
1251 }; | |
1252 | |
1253 Object* root(RootListIndex index) { return roots_[index]; } | 1075 Object* root(RootListIndex index) { return roots_[index]; } |
1254 | 1076 |
1255 STATIC_ASSERT(kUndefinedValueRootIndex == | |
1256 Internals::kUndefinedValueRootIndex); | |
1257 STATIC_ASSERT(kNullValueRootIndex == Internals::kNullValueRootIndex); | |
1258 STATIC_ASSERT(kTrueValueRootIndex == Internals::kTrueValueRootIndex); | |
1259 STATIC_ASSERT(kFalseValueRootIndex == Internals::kFalseValueRootIndex); | |
1260 STATIC_ASSERT(kempty_stringRootIndex == Internals::kEmptyStringRootIndex); | |
1261 | |
1262 // Generated code can embed direct references to non-writable roots if | |
1263 // they are in new space. | |
1264 static bool RootCanBeWrittenAfterInitialization(RootListIndex root_index); | |
1265 // Generated code can treat direct references to this root as constant. | 1077 // Generated code can treat direct references to this root as constant. |
1266 bool RootCanBeTreatedAsConstant(RootListIndex root_index); | 1078 bool RootCanBeTreatedAsConstant(RootListIndex root_index); |
1267 | 1079 |
1268 Map* MapForFixedTypedArray(ExternalArrayType array_type); | 1080 Map* MapForFixedTypedArray(ExternalArrayType array_type); |
1269 RootListIndex RootIndexForFixedTypedArray(ExternalArrayType array_type); | 1081 RootListIndex RootIndexForFixedTypedArray(ExternalArrayType array_type); |
1270 | 1082 |
1271 RootListIndex RootIndexForEmptyFixedTypedArray(ElementsKind kind); | 1083 RootListIndex RootIndexForEmptyFixedTypedArray(ElementsKind kind); |
1272 FixedTypedArrayBase* EmptyFixedTypedArrayForMap(Map* map); | 1084 FixedTypedArrayBase* EmptyFixedTypedArrayForMap(Map* map); |
1273 | 1085 |
1274 void RecordStats(HeapStats* stats, bool take_snapshot = false); | 1086 void RecordStats(HeapStats* stats, bool take_snapshot = false); |
1275 | 1087 |
1276 // Copy block of memory from src to dst. Size of block should be aligned | |
1277 // by pointer size. | |
1278 static inline void CopyBlock(Address dst, Address src, int byte_size); | |
1279 | |
1280 // Optimized version of memmove for blocks with pointer size aligned sizes and | |
1281 // pointer size aligned addresses. | |
1282 static inline void MoveBlock(Address dst, Address src, int byte_size); | |
1283 | |
1284 // Check new space expansion criteria and expand semispaces if it was hit. | 1088 // Check new space expansion criteria and expand semispaces if it was hit. |
1285 void CheckNewSpaceExpansionCriteria(); | 1089 void CheckNewSpaceExpansionCriteria(); |
1286 | 1090 |
1287 inline void IncrementPromotedObjectsSize(int object_size) { | |
1288 DCHECK(object_size > 0); | |
1289 promoted_objects_size_ += object_size; | |
1290 } | |
1291 | |
1292 inline void IncrementSemiSpaceCopiedObjectSize(int object_size) { | |
1293 DCHECK(object_size > 0); | |
1294 semi_space_copied_object_size_ += object_size; | |
1295 } | |
1296 | |
1297 inline intptr_t SurvivedNewSpaceObjectSize() { | |
1298 return promoted_objects_size_ + semi_space_copied_object_size_; | |
1299 } | |
1300 | |
1301 inline void IncrementNodesDiedInNewSpace() { nodes_died_in_new_space_++; } | |
1302 | |
1303 inline void IncrementNodesCopiedInNewSpace() { nodes_copied_in_new_space_++; } | |
1304 | |
1305 inline void IncrementNodesPromoted() { nodes_promoted_++; } | |
1306 | |
1307 inline void IncrementYoungSurvivorsCounter(int survived) { | |
1308 DCHECK(survived >= 0); | |
1309 survived_last_scavenge_ = survived; | |
1310 survived_since_last_expansion_ += survived; | |
1311 } | |
1312 | |
1313 inline bool HeapIsFullEnoughToStartIncrementalMarking(intptr_t limit) { | 1091 inline bool HeapIsFullEnoughToStartIncrementalMarking(intptr_t limit) { |
1314 if (FLAG_stress_compaction && (gc_count_ & 1) != 0) return true; | 1092 if (FLAG_stress_compaction && (gc_count_ & 1) != 0) return true; |
1315 | 1093 |
1316 intptr_t adjusted_allocation_limit = limit - new_space_.Capacity(); | 1094 intptr_t adjusted_allocation_limit = limit - new_space_.Capacity(); |
1317 | 1095 |
1318 if (PromotedTotalSize() >= adjusted_allocation_limit) return true; | 1096 if (PromotedTotalSize() >= adjusted_allocation_limit) return true; |
1319 | 1097 |
1320 return false; | 1098 return false; |
1321 } | 1099 } |
1322 | 1100 |
1323 void UpdateNewSpaceReferencesInExternalStringTable( | 1101 void UpdateNewSpaceReferencesInExternalStringTable( |
1324 ExternalStringTableUpdaterCallback updater_func); | 1102 ExternalStringTableUpdaterCallback updater_func); |
1325 | 1103 |
1326 void UpdateReferencesInExternalStringTable( | 1104 void UpdateReferencesInExternalStringTable( |
1327 ExternalStringTableUpdaterCallback updater_func); | 1105 ExternalStringTableUpdaterCallback updater_func); |
1328 | 1106 |
1329 void ProcessAllWeakReferences(WeakObjectRetainer* retainer); | 1107 void ProcessAllWeakReferences(WeakObjectRetainer* retainer); |
1330 void ProcessYoungWeakReferences(WeakObjectRetainer* retainer); | 1108 void ProcessYoungWeakReferences(WeakObjectRetainer* retainer); |
1331 | 1109 |
1332 void VisitExternalResources(v8::ExternalResourceVisitor* visitor); | 1110 void VisitExternalResources(v8::ExternalResourceVisitor* visitor); |
1333 | 1111 |
1334 // An object should be promoted if the object has survived a | 1112 // An object should be promoted if the object has survived a |
1335 // scavenge operation. | 1113 // scavenge operation. |
1336 inline bool ShouldBePromoted(Address old_address, int object_size); | 1114 inline bool ShouldBePromoted(Address old_address, int object_size); |
1337 | 1115 |
1338 void ClearNormalizedMapCaches(); | 1116 void ClearNormalizedMapCaches(); |
1339 | 1117 |
1340 GCTracer* tracer() { return tracer_; } | |
1341 | |
1342 // Returns the size of objects residing in non new spaces. | |
1343 intptr_t PromotedSpaceSizeOfObjects(); | |
1344 | |
1345 double total_regexp_code_generated() { return total_regexp_code_generated_; } | |
1346 void IncreaseTotalRegexpCodeGenerated(int size) { | |
1347 total_regexp_code_generated_ += size; | |
1348 } | |
1349 | |
1350 void IncrementCodeGeneratedBytes(bool is_crankshafted, int size) { | |
1351 if (is_crankshafted) { | |
1352 crankshaft_codegen_bytes_generated_ += size; | |
1353 } else { | |
1354 full_codegen_bytes_generated_ += size; | |
1355 } | |
1356 } | |
1357 | |
1358 void UpdateNewSpaceAllocationCounter() { | |
1359 new_space_allocation_counter_ = NewSpaceAllocationCounter(); | |
1360 } | |
1361 | |
1362 size_t NewSpaceAllocationCounter() { | |
1363 return new_space_allocation_counter_ + new_space()->AllocatedSinceLastGC(); | |
1364 } | |
1365 | |
1366 // This should be used only for testing. | |
1367 void set_new_space_allocation_counter(size_t new_value) { | |
1368 new_space_allocation_counter_ = new_value; | |
1369 } | |
1370 | |
1371 void UpdateOldGenerationAllocationCounter() { | |
1372 old_generation_allocation_counter_ = OldGenerationAllocationCounter(); | |
1373 } | |
1374 | |
1375 size_t OldGenerationAllocationCounter() { | |
1376 return old_generation_allocation_counter_ + PromotedSinceLastGC(); | |
1377 } | |
1378 | |
1379 // This should be used only for testing. | |
1380 void set_old_generation_allocation_counter(size_t new_value) { | |
1381 old_generation_allocation_counter_ = new_value; | |
1382 } | |
1383 | |
1384 size_t PromotedSinceLastGC() { | |
1385 return PromotedSpaceSizeOfObjects() - old_generation_size_at_last_gc_; | |
1386 } | |
1387 | |
1388 // Update GC statistics that are tracked on the Heap. | |
1389 void UpdateCumulativeGCStatistics(double duration, double spent_in_mutator, | |
1390 double marking_time); | |
1391 | |
1392 // Returns maximum GC pause. | |
1393 double get_max_gc_pause() { return max_gc_pause_; } | |
1394 | |
1395 // Returns maximum size of objects alive after GC. | |
1396 intptr_t get_max_alive_after_gc() { return max_alive_after_gc_; } | |
1397 | |
1398 // Returns minimal interval between two subsequent collections. | |
1399 double get_min_in_mutator() { return min_in_mutator_; } | |
1400 | |
1401 void IncrementDeferredCount(v8::Isolate::UseCounterFeature feature); | 1118 void IncrementDeferredCount(v8::Isolate::UseCounterFeature feature); |
1402 | 1119 |
1403 MarkCompactCollector* mark_compact_collector() { | |
1404 return &mark_compact_collector_; | |
1405 } | |
1406 | |
1407 StoreBuffer* store_buffer() { return &store_buffer_; } | |
1408 | |
1409 IncrementalMarking* incremental_marking() { return &incremental_marking_; } | |
1410 | |
1411 ExternalStringTable* external_string_table() { | 1120 ExternalStringTable* external_string_table() { |
1412 return &external_string_table_; | 1121 return &external_string_table_; |
1413 } | 1122 } |
1414 | 1123 |
1415 bool concurrent_sweeping_enabled() { return concurrent_sweeping_enabled_; } | 1124 bool concurrent_sweeping_enabled() { return concurrent_sweeping_enabled_; } |
1416 | 1125 |
1417 inline Isolate* isolate(); | |
1418 | |
1419 void CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags); | |
1420 void CallGCEpilogueCallbacks(GCType gc_type, GCCallbackFlags flags); | |
1421 | |
1422 inline bool OldGenerationAllocationLimitReached(); | 1126 inline bool OldGenerationAllocationLimitReached(); |
1423 | 1127 |
1424 void QueueMemoryChunkForFree(MemoryChunk* chunk); | 1128 void QueueMemoryChunkForFree(MemoryChunk* chunk); |
1425 void FilterStoreBufferEntriesOnAboutToBeFreedPages(); | 1129 void FilterStoreBufferEntriesOnAboutToBeFreedPages(); |
1426 void FreeQueuedChunks(); | 1130 void FreeQueuedChunks(); |
1427 | 1131 |
1428 int gc_count() const { return gc_count_; } | |
1429 | |
1430 bool RecentIdleNotificationHappened(); | 1132 bool RecentIdleNotificationHappened(); |
1431 | 1133 |
1432 // Completely clear the Instanceof cache (to stop it keeping objects alive | 1134 // Completely clear the Instanceof cache (to stop it keeping objects alive |
1433 // around a GC). | 1135 // around a GC). |
1434 inline void CompletelyClearInstanceofCache(); | 1136 inline void CompletelyClearInstanceofCache(); |
1435 | 1137 |
1436 // The roots that have an index less than this are always in old space. | |
1437 static const int kOldSpaceRoots = 0x20; | |
1438 | |
1439 inline uint32_t HashSeed(); | 1138 inline uint32_t HashSeed(); |
1440 | 1139 |
1441 inline Smi* NextScriptId(); | 1140 inline Smi* NextScriptId(); |
1442 | 1141 |
1443 inline void SetArgumentsAdaptorDeoptPCOffset(int pc_offset); | 1142 inline void SetArgumentsAdaptorDeoptPCOffset(int pc_offset); |
1444 inline void SetConstructStubDeoptPCOffset(int pc_offset); | 1143 inline void SetConstructStubDeoptPCOffset(int pc_offset); |
1445 inline void SetGetterStubDeoptPCOffset(int pc_offset); | 1144 inline void SetGetterStubDeoptPCOffset(int pc_offset); |
1446 inline void SetSetterStubDeoptPCOffset(int pc_offset); | 1145 inline void SetSetterStubDeoptPCOffset(int pc_offset); |
1447 | 1146 |
1448 // For post mortem debugging. | 1147 // For post mortem debugging. |
(...skipping 12 matching lines...) Expand all Loading... |
1461 } | 1160 } |
1462 | 1161 |
1463 void DeoptMarkedAllocationSites(); | 1162 void DeoptMarkedAllocationSites(); |
1464 | 1163 |
1465 bool MaximumSizeScavenge() { return maximum_size_scavenges_ > 0; } | 1164 bool MaximumSizeScavenge() { return maximum_size_scavenges_ > 0; } |
1466 | 1165 |
1467 bool DeoptMaybeTenuredAllocationSites() { | 1166 bool DeoptMaybeTenuredAllocationSites() { |
1468 return new_space_.IsAtMaximumCapacity() && maximum_size_scavenges_ == 0; | 1167 return new_space_.IsAtMaximumCapacity() && maximum_size_scavenges_ == 0; |
1469 } | 1168 } |
1470 | 1169 |
1471 // ObjectStats are kept in two arrays, counts and sizes. Related stats are | |
1472 // stored in a contiguous linear buffer. Stats groups are stored one after | |
1473 // another. | |
1474 enum { | |
1475 FIRST_CODE_KIND_SUB_TYPE = LAST_TYPE + 1, | |
1476 FIRST_FIXED_ARRAY_SUB_TYPE = | |
1477 FIRST_CODE_KIND_SUB_TYPE + Code::NUMBER_OF_KINDS, | |
1478 FIRST_CODE_AGE_SUB_TYPE = | |
1479 FIRST_FIXED_ARRAY_SUB_TYPE + LAST_FIXED_ARRAY_SUB_TYPE + 1, | |
1480 OBJECT_STATS_COUNT = FIRST_CODE_AGE_SUB_TYPE + Code::kCodeAgeCount + 1 | |
1481 }; | |
1482 | |
1483 void RecordObjectStats(InstanceType type, size_t size) { | 1170 void RecordObjectStats(InstanceType type, size_t size) { |
1484 DCHECK(type <= LAST_TYPE); | 1171 DCHECK(type <= LAST_TYPE); |
1485 object_counts_[type]++; | 1172 object_counts_[type]++; |
1486 object_sizes_[type] += size; | 1173 object_sizes_[type] += size; |
1487 } | 1174 } |
1488 | 1175 |
1489 void RecordCodeSubTypeStats(int code_sub_type, int code_age, size_t size) { | 1176 void RecordCodeSubTypeStats(int code_sub_type, int code_age, size_t size) { |
1490 int code_sub_type_index = FIRST_CODE_KIND_SUB_TYPE + code_sub_type; | 1177 int code_sub_type_index = FIRST_CODE_KIND_SUB_TYPE + code_sub_type; |
1491 int code_age_index = | 1178 int code_age_index = |
1492 FIRST_CODE_AGE_SUB_TYPE + code_age - Code::kFirstCodeAge; | 1179 FIRST_CODE_AGE_SUB_TYPE + code_age - Code::kFirstCodeAge; |
(...skipping 15 matching lines...) Expand all Loading... |
1508 | 1195 |
1509 void TraceObjectStats(); | 1196 void TraceObjectStats(); |
1510 void TraceObjectStat(const char* name, int count, int size, double time); | 1197 void TraceObjectStat(const char* name, int count, int size, double time); |
1511 void CheckpointObjectStats(); | 1198 void CheckpointObjectStats(); |
1512 bool GetObjectTypeName(size_t index, const char** object_type, | 1199 bool GetObjectTypeName(size_t index, const char** object_type, |
1513 const char** object_sub_type); | 1200 const char** object_sub_type); |
1514 | 1201 |
1515 void RegisterStrongRoots(Object** start, Object** end); | 1202 void RegisterStrongRoots(Object** start, Object** end); |
1516 void UnregisterStrongRoots(Object** start); | 1203 void UnregisterStrongRoots(Object** start); |
1517 | 1204 |
1518 // Taking this lock prevents the GC from entering a phase that relocates | |
1519 // object references. | |
1520 class RelocationLock { | |
1521 public: | |
1522 explicit RelocationLock(Heap* heap) : heap_(heap) { | |
1523 heap_->relocation_mutex_.Lock(); | |
1524 } | |
1525 | |
1526 ~RelocationLock() { heap_->relocation_mutex_.Unlock(); } | |
1527 | |
1528 private: | |
1529 Heap* heap_; | |
1530 }; | |
1531 | |
1532 // An optional version of the above lock that can be used for some critical | |
1533 // sections on the mutator thread; only safe since the GC currently does not | |
1534 // do concurrent compaction. | |
1535 class OptionalRelocationLock { | |
1536 public: | |
1537 OptionalRelocationLock(Heap* heap, bool concurrent) | |
1538 : heap_(heap), concurrent_(concurrent) { | |
1539 if (concurrent_) heap_->relocation_mutex_.Lock(); | |
1540 } | |
1541 | |
1542 ~OptionalRelocationLock() { | |
1543 if (concurrent_) heap_->relocation_mutex_.Unlock(); | |
1544 } | |
1545 | |
1546 private: | |
1547 Heap* heap_; | |
1548 bool concurrent_; | |
1549 }; | |
1550 | |
1551 void AddWeakObjectToCodeDependency(Handle<HeapObject> obj, | 1205 void AddWeakObjectToCodeDependency(Handle<HeapObject> obj, |
1552 Handle<DependentCode> dep); | 1206 Handle<DependentCode> dep); |
1553 | 1207 |
1554 DependentCode* LookupWeakObjectToCodeDependency(Handle<HeapObject> obj); | 1208 DependentCode* LookupWeakObjectToCodeDependency(Handle<HeapObject> obj); |
1555 | 1209 |
1556 void AddRetainedMap(Handle<Map> map); | 1210 void AddRetainedMap(Handle<Map> map); |
1557 | 1211 |
1558 static void FatalProcessOutOfMemory(const char* location, | |
1559 bool take_snapshot = false); | |
1560 | |
1561 // This event is triggered after successful allocation of a new object made | 1212 // This event is triggered after successful allocation of a new object made |
1562 // by runtime. Allocations of target space for object evacuation do not | 1213 // by runtime. Allocations of target space for object evacuation do not |
1563 // trigger the event. In order to track ALL allocations one must turn off | 1214 // trigger the event. In order to track ALL allocations one must turn off |
1564 // FLAG_inline_new and FLAG_use_allocation_folding. | 1215 // FLAG_inline_new and FLAG_use_allocation_folding. |
1565 inline void OnAllocationEvent(HeapObject* object, int size_in_bytes); | 1216 inline void OnAllocationEvent(HeapObject* object, int size_in_bytes); |
1566 | 1217 |
1567 // This event is triggered after object is moved to a new place. | 1218 // This event is triggered after object is moved to a new place. |
1568 inline void OnMoveEvent(HeapObject* target, HeapObject* source, | 1219 inline void OnMoveEvent(HeapObject* target, HeapObject* source, |
1569 int size_in_bytes); | 1220 int size_in_bytes); |
1570 | 1221 |
(...skipping 21 matching lines...) Expand all Loading... |
1592 | 1243 |
1593 // An ArrayBuffer moved from new space to old space. | 1244 // An ArrayBuffer moved from new space to old space. |
1594 void PromoteArrayBuffer(Object* buffer); | 1245 void PromoteArrayBuffer(Object* buffer); |
1595 | 1246 |
1596 bool HasLowAllocationRate(); | 1247 bool HasLowAllocationRate(); |
1597 bool HasHighFragmentation(); | 1248 bool HasHighFragmentation(); |
1598 bool HasHighFragmentation(intptr_t used, intptr_t committed); | 1249 bool HasHighFragmentation(intptr_t used, intptr_t committed); |
1599 | 1250 |
1600 bool ShouldOptimizeForMemoryUsage() { return optimize_for_memory_usage_; } | 1251 bool ShouldOptimizeForMemoryUsage() { return optimize_for_memory_usage_; } |
1601 | 1252 |
| 1253 // =========================================================================== |
| 1254 // Initialization. =========================================================== |
| 1255 // =========================================================================== |
| 1256 |
| 1257 // Configure heap size in MB before setup. Return false if the heap has been |
| 1258 // set up already. |
| 1259 bool ConfigureHeap(int max_semi_space_size, int max_old_space_size, |
| 1260 int max_executable_size, size_t code_range_size); |
| 1261 bool ConfigureHeapDefault(); |
| 1262 |
| 1263 // Prepares the heap, setting up memory areas that are needed in the isolate |
| 1264 // without actually creating any objects. |
| 1265 bool SetUp(); |
| 1266 |
| 1267 // Bootstraps the object heap with the core set of objects required to run. |
| 1268 // Returns whether it succeeded. |
| 1269 bool CreateHeapObjects(); |
| 1270 |
| 1271 // Destroys all memory allocated by the heap. |
| 1272 void TearDown(); |
| 1273 |
| 1274 // =========================================================================== |
| 1275 // Getters for spaces. ======================================================= |
| 1276 // =========================================================================== |
| 1277 |
| 1278 // Return the starting address and a mask for the new space. And-masking an |
| 1279 // address with the mask will result in the start address of the new space |
| 1280 // for all addresses in either semispace. |
| 1281 Address NewSpaceStart() { return new_space_.start(); } |
| 1282 uintptr_t NewSpaceMask() { return new_space_.mask(); } |
| 1283 Address NewSpaceTop() { return new_space_.top(); } |
| 1284 |
| 1285 NewSpace* new_space() { return &new_space_; } |
| 1286 OldSpace* old_space() { return old_space_; } |
| 1287 OldSpace* code_space() { return code_space_; } |
| 1288 MapSpace* map_space() { return map_space_; } |
| 1289 LargeObjectSpace* lo_space() { return lo_space_; } |
| 1290 |
| 1291 PagedSpace* paged_space(int idx) { |
| 1292 switch (idx) { |
| 1293 case OLD_SPACE: |
| 1294 return old_space(); |
| 1295 case MAP_SPACE: |
| 1296 return map_space(); |
| 1297 case CODE_SPACE: |
| 1298 return code_space(); |
| 1299 case NEW_SPACE: |
| 1300 case LO_SPACE: |
| 1301 UNREACHABLE(); |
| 1302 } |
| 1303 return NULL; |
| 1304 } |
| 1305 |
| 1306 Space* space(int idx) { |
| 1307 switch (idx) { |
| 1308 case NEW_SPACE: |
| 1309 return new_space(); |
| 1310 case LO_SPACE: |
| 1311 return lo_space(); |
| 1312 default: |
| 1313 return paged_space(idx); |
| 1314 } |
| 1315 } |
| 1316 |
| 1317 // Returns name of the space. |
| 1318 const char* GetSpaceName(int idx); |
| 1319 |
| 1320 // =========================================================================== |
| 1321 // Getters to other components. ============================================== |
| 1322 // =========================================================================== |
| 1323 |
| 1324 GCTracer* tracer() { return tracer_; } |
| 1325 |
| 1326 PromotionQueue* promotion_queue() { return &promotion_queue_; } |
| 1327 |
| 1328 inline Isolate* isolate(); |
| 1329 |
| 1330 MarkCompactCollector* mark_compact_collector() { |
| 1331 return &mark_compact_collector_; |
| 1332 } |
| 1333 |
| 1334 StoreBuffer* store_buffer() { return &store_buffer_; } |
| 1335 |
| 1336 // =========================================================================== |
| 1337 // Inline allocation. ======================================================== |
| 1338 // =========================================================================== |
| 1339 |
| 1340 // Indicates whether inline bump-pointer allocation has been disabled. |
| 1341 bool inline_allocation_disabled() { return inline_allocation_disabled_; } |
| 1342 |
| 1343 // Switch whether inline bump-pointer allocation should be used. |
| 1344 void EnableInlineAllocation(); |
| 1345 void DisableInlineAllocation(); |
| 1346 |
| 1347 // =========================================================================== |
| 1348 // Methods triggering GCs. =================================================== |
| 1349 // =========================================================================== |
| 1350 |
| 1351 // Performs garbage collection operation. |
| 1352 // Returns whether there is a chance that another major GC could |
| 1353 // collect more garbage. |
| 1354 inline bool CollectGarbage( |
| 1355 AllocationSpace space, const char* gc_reason = NULL, |
| 1356 const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags); |
| 1357 |
| 1358 // Performs a full garbage collection. If (flags & kMakeHeapIterableMask) is |
| 1359 // non-zero, then the slower precise sweeper is used, which leaves the heap |
| 1360 // in a state where we can iterate over the heap visiting all objects. |
| 1361 void CollectAllGarbage( |
| 1362 int flags = kFinalizeIncrementalMarkingMask, const char* gc_reason = NULL, |
| 1363 const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags); |
| 1364 |
| 1365 // Last hope GC, should try to squeeze as much as possible. |
| 1366 void CollectAllAvailableGarbage(const char* gc_reason = NULL); |
| 1367 |
| 1368 // Invoked when GC was requested via the stack guard. |
| 1369 void HandleGCRequest(); |
| 1370 |
| 1371 // =========================================================================== |
| 1372 // Iterators. ================================================================ |
| 1373 // =========================================================================== |
| 1374 |
| 1375 // Iterates over all roots in the heap. |
| 1376 void IterateRoots(ObjectVisitor* v, VisitMode mode); |
| 1377 // Iterates over all strong roots in the heap. |
| 1378 void IterateStrongRoots(ObjectVisitor* v, VisitMode mode); |
| 1379 // Iterates over entries in the smi roots list. Only interesting to the |
| 1380 // serializer/deserializer, since GC does not care about smis. |
| 1381 void IterateSmiRoots(ObjectVisitor* v); |
| 1382 // Iterates over all the other roots in the heap. |
| 1383 void IterateWeakRoots(ObjectVisitor* v, VisitMode mode); |
| 1384 |
| 1385 // Iterate pointers to from semispace of new space found in memory interval |
| 1386 // from start to end within |object|. |
| 1387 void IterateAndMarkPointersToFromSpace(HeapObject* object, Address start, |
| 1388 Address end, bool record_slots, |
| 1389 ObjectSlotCallback callback); |
| 1390 |
| 1391 // =========================================================================== |
| 1392 // Incremental marking API. ================================================== |
| 1393 // =========================================================================== |
| 1394 |
| 1395 // Start incremental marking and ensure that idle time handler can perform |
| 1396 // incremental steps. |
| 1397 void StartIdleIncrementalMarking(); |
| 1398 |
| 1399 // Starts incremental marking assuming incremental marking is currently |
| 1400 // stopped. |
| 1401 void StartIncrementalMarking(int gc_flags, |
| 1402 const GCCallbackFlags gc_callback_flags, |
| 1403 const char* reason = nullptr); |
| 1404 |
| 1405 // Performs incremental marking steps of step_size_in_bytes as long as |
| 1406 // deadline_ins_ms is not reached. step_size_in_bytes can be 0 to compute |
| 1407 // an estimate increment. Returns the remaining time that cannot be used |
| 1408 // for incremental marking anymore because a single step would exceed the |
| 1409 // deadline. |
| 1410 double AdvanceIncrementalMarking( |
| 1411 intptr_t step_size_in_bytes, double deadline_in_ms, |
| 1412 IncrementalMarking::StepActions step_actions); |
| 1413 |
| 1414 IncrementalMarking* incremental_marking() { return &incremental_marking_; } |
| 1415 |
| 1416 // =========================================================================== |
| 1417 // Methods checking/returning the space of a given object/address. =========== |
| 1418 // =========================================================================== |
| 1419 |
| 1420 // Returns whether the object resides in new space. |
| 1421 inline bool InNewSpace(Object* object); |
| 1422 inline bool InNewSpace(Address address); |
| 1423 inline bool InNewSpacePage(Address address); |
| 1424 inline bool InFromSpace(Object* object); |
| 1425 inline bool InToSpace(Object* object); |
| 1426 |
| 1427 // Returns whether the object resides in old space. |
| 1428 inline bool InOldSpace(Address address); |
| 1429 inline bool InOldSpace(Object* object); |
| 1430 |
| 1431 // Checks whether an address/object in the heap (including auxiliary |
| 1432 // area and unused area). |
| 1433 bool Contains(Address addr); |
| 1434 bool Contains(HeapObject* value); |
| 1435 |
| 1436 // Checks whether an address/object in a space. |
| 1437 // Currently used by tests, serialization and heap verification only. |
| 1438 bool InSpace(Address addr, AllocationSpace space); |
| 1439 bool InSpace(HeapObject* value, AllocationSpace space); |
| 1440 |
| 1441 // =========================================================================== |
| 1442 // GC statistics. ============================================================ |
| 1443 // =========================================================================== |
| 1444 |
| 1445 // Returns the maximum amount of memory reserved for the heap. For |
| 1446 // the young generation, we reserve 4 times the amount needed for a |
| 1447 // semi space. The young generation consists of two semi spaces and |
| 1448 // we reserve twice the amount needed for those in order to ensure |
| 1449 // that new space can be aligned to its size. |
| 1450 intptr_t MaxReserved() { |
| 1451 return 4 * reserved_semispace_size_ + max_old_generation_size_; |
| 1452 } |
| 1453 int MaxSemiSpaceSize() { return max_semi_space_size_; } |
| 1454 int ReservedSemiSpaceSize() { return reserved_semispace_size_; } |
| 1455 int InitialSemiSpaceSize() { return initial_semispace_size_; } |
| 1456 int TargetSemiSpaceSize() { return target_semispace_size_; } |
| 1457 intptr_t MaxOldGenerationSize() { return max_old_generation_size_; } |
| 1458 intptr_t MaxExecutableSize() { return max_executable_size_; } |
| 1459 |
| 1460 // Returns the capacity of the heap in bytes w/o growing. Heap grows when |
| 1461 // more spaces are needed until it reaches the limit. |
| 1462 intptr_t Capacity(); |
| 1463 |
| 1464 // Returns the amount of memory currently committed for the heap. |
| 1465 intptr_t CommittedMemory(); |
| 1466 |
| 1467 // Returns the amount of memory currently committed for the old space. |
| 1468 intptr_t CommittedOldGenerationMemory(); |
| 1469 |
| 1470 // Returns the amount of executable memory currently committed for the heap. |
| 1471 intptr_t CommittedMemoryExecutable(); |
| 1472 |
| 1473 // Returns the amount of phyical memory currently committed for the heap. |
| 1474 size_t CommittedPhysicalMemory(); |
| 1475 |
| 1476 // Returns the maximum amount of memory ever committed for the heap. |
| 1477 intptr_t MaximumCommittedMemory() { return maximum_committed_; } |
| 1478 |
| 1479 // Updates the maximum committed memory for the heap. Should be called |
| 1480 // whenever a space grows. |
| 1481 void UpdateMaximumCommitted(); |
| 1482 |
| 1483 // Returns the available bytes in space w/o growing. |
| 1484 // Heap doesn't guarantee that it can allocate an object that requires |
| 1485 // all available bytes. Check MaxHeapObjectSize() instead. |
| 1486 intptr_t Available(); |
| 1487 |
| 1488 // Returns of size of all objects residing in the heap. |
| 1489 intptr_t SizeOfObjects(); |
| 1490 |
| 1491 void UpdateSurvivalStatistics(int start_new_space_size); |
| 1492 |
| 1493 inline void IncrementPromotedObjectsSize(int object_size) { |
| 1494 DCHECK(object_size > 0); |
| 1495 promoted_objects_size_ += object_size; |
| 1496 } |
| 1497 inline intptr_t promoted_objects_size() { return promoted_objects_size_; } |
| 1498 |
| 1499 inline void IncrementSemiSpaceCopiedObjectSize(int object_size) { |
| 1500 DCHECK(object_size > 0); |
| 1501 semi_space_copied_object_size_ += object_size; |
| 1502 } |
| 1503 inline intptr_t semi_space_copied_object_size() { |
| 1504 return semi_space_copied_object_size_; |
| 1505 } |
| 1506 |
| 1507 |
| 1508 inline intptr_t SurvivedNewSpaceObjectSize() { |
| 1509 return promoted_objects_size_ + semi_space_copied_object_size_; |
| 1510 } |
| 1511 |
| 1512 inline void IncrementNodesDiedInNewSpace() { nodes_died_in_new_space_++; } |
| 1513 |
| 1514 inline void IncrementNodesCopiedInNewSpace() { nodes_copied_in_new_space_++; } |
| 1515 |
| 1516 inline void IncrementNodesPromoted() { nodes_promoted_++; } |
| 1517 |
| 1518 inline void IncrementYoungSurvivorsCounter(int survived) { |
| 1519 DCHECK(survived >= 0); |
| 1520 survived_last_scavenge_ = survived; |
| 1521 survived_since_last_expansion_ += survived; |
| 1522 } |
| 1523 |
| 1524 inline intptr_t PromotedTotalSize() { |
| 1525 int64_t total = PromotedSpaceSizeOfObjects() + PromotedExternalMemorySize(); |
| 1526 if (total > std::numeric_limits<intptr_t>::max()) { |
| 1527 // TODO(erikcorry): Use uintptr_t everywhere we do heap size calculations. |
| 1528 return std::numeric_limits<intptr_t>::max(); |
| 1529 } |
| 1530 if (total < 0) return 0; |
| 1531 return static_cast<intptr_t>(total); |
| 1532 } |
| 1533 |
| 1534 inline intptr_t OldGenerationSpaceAvailable() { |
| 1535 return old_generation_allocation_limit_ - PromotedTotalSize(); |
| 1536 } |
| 1537 |
| 1538 inline intptr_t OldGenerationCapacityAvailable() { |
| 1539 return max_old_generation_size_ - PromotedTotalSize(); |
| 1540 } |
| 1541 |
| 1542 |
| 1543 void UpdateNewSpaceAllocationCounter() { |
| 1544 new_space_allocation_counter_ = NewSpaceAllocationCounter(); |
| 1545 } |
| 1546 |
| 1547 size_t NewSpaceAllocationCounter() { |
| 1548 return new_space_allocation_counter_ + new_space()->AllocatedSinceLastGC(); |
| 1549 } |
| 1550 |
| 1551 // This should be used only for testing. |
| 1552 void set_new_space_allocation_counter(size_t new_value) { |
| 1553 new_space_allocation_counter_ = new_value; |
| 1554 } |
| 1555 |
| 1556 void UpdateOldGenerationAllocationCounter() { |
| 1557 old_generation_allocation_counter_ = OldGenerationAllocationCounter(); |
| 1558 } |
| 1559 |
| 1560 size_t OldGenerationAllocationCounter() { |
| 1561 return old_generation_allocation_counter_ + PromotedSinceLastGC(); |
| 1562 } |
| 1563 |
| 1564 // This should be used only for testing. |
| 1565 void set_old_generation_allocation_counter(size_t new_value) { |
| 1566 old_generation_allocation_counter_ = new_value; |
| 1567 } |
| 1568 |
| 1569 size_t PromotedSinceLastGC() { |
| 1570 return PromotedSpaceSizeOfObjects() - old_generation_size_at_last_gc_; |
| 1571 } |
| 1572 |
| 1573 // Update GC statistics that are tracked on the Heap. |
| 1574 void UpdateCumulativeGCStatistics(double duration, double spent_in_mutator, |
| 1575 double marking_time); |
| 1576 |
| 1577 // Returns maximum GC pause. |
| 1578 double get_max_gc_pause() { return max_gc_pause_; } |
| 1579 |
| 1580 // Returns maximum size of objects alive after GC. |
| 1581 intptr_t get_max_alive_after_gc() { return max_alive_after_gc_; } |
| 1582 |
| 1583 // Returns minimal interval between two subsequent collections. |
| 1584 double get_min_in_mutator() { return min_in_mutator_; } |
| 1585 |
| 1586 int gc_count() const { return gc_count_; } |
| 1587 |
| 1588 // Returns the size of objects residing in non new spaces. |
| 1589 intptr_t PromotedSpaceSizeOfObjects(); |
| 1590 |
| 1591 double total_regexp_code_generated() { return total_regexp_code_generated_; } |
| 1592 void IncreaseTotalRegexpCodeGenerated(int size) { |
| 1593 total_regexp_code_generated_ += size; |
| 1594 } |
| 1595 |
| 1596 void IncrementCodeGeneratedBytes(bool is_crankshafted, int size) { |
| 1597 if (is_crankshafted) { |
| 1598 crankshaft_codegen_bytes_generated_ += size; |
| 1599 } else { |
| 1600 full_codegen_bytes_generated_ += size; |
| 1601 } |
| 1602 } |
| 1603 |
| 1604 // =========================================================================== |
| 1605 // Prologue/epilogue callback methods.======================================== |
| 1606 // =========================================================================== |
| 1607 |
| 1608 void AddGCPrologueCallback(v8::Isolate::GCCallback callback, |
| 1609 GCType gc_type_filter, bool pass_isolate = true); |
| 1610 void RemoveGCPrologueCallback(v8::Isolate::GCCallback callback); |
| 1611 |
| 1612 void AddGCEpilogueCallback(v8::Isolate::GCCallback callback, |
| 1613 GCType gc_type_filter, bool pass_isolate = true); |
| 1614 void RemoveGCEpilogueCallback(v8::Isolate::GCCallback callback); |
| 1615 |
| 1616 void CallGCPrologueCallbacks(GCType gc_type, GCCallbackFlags flags); |
| 1617 void CallGCEpilogueCallbacks(GCType gc_type, GCCallbackFlags flags); |
| 1618 |
| 1619 // =========================================================================== |
| 1620 // Allocation methods. ======================================================= |
| 1621 // =========================================================================== |
| 1622 |
| 1623 // Returns a deep copy of the JavaScript object. |
| 1624 // Properties and elements are copied too. |
| 1625 // Optionally takes an AllocationSite to be appended in an AllocationMemento. |
| 1626 MUST_USE_RESULT AllocationResult CopyJSObject(JSObject* source, |
| 1627 AllocationSite* site = NULL); |
| 1628 |
| 1629 // Creates a filler object and returns a heap object immediately after it. |
| 1630 MUST_USE_RESULT HeapObject* PrecedeWithFiller(HeapObject* object, |
| 1631 int filler_size); |
| 1632 // Creates a filler object if needed for alignment and returns a heap object |
| 1633 // immediately after it. If any space is left after the returned object, |
| 1634 // another filler object is created so the over allocated memory is iterable. |
| 1635 MUST_USE_RESULT HeapObject* AlignWithFiller(HeapObject* object, |
| 1636 int object_size, |
| 1637 int allocation_size, |
| 1638 AllocationAlignment alignment); |
| 1639 |
| 1640 // ============================================================================= |
| 1641 |
| 1642 #ifdef VERIFY_HEAP |
| 1643 // Verify the heap is in its normal state before or after a GC. |
| 1644 void Verify(); |
| 1645 #endif |
| 1646 |
| 1647 #ifdef DEBUG |
| 1648 void set_allocation_timeout(int timeout) { allocation_timeout_ = timeout; } |
| 1649 |
| 1650 void TracePathToObjectFrom(Object* target, Object* root); |
| 1651 void TracePathToObject(Object* target); |
| 1652 void TracePathToGlobal(); |
| 1653 |
| 1654 void Print(); |
| 1655 void PrintHandles(); |
| 1656 |
| 1657 // Report heap statistics. |
| 1658 void ReportHeapStatistics(const char* title); |
| 1659 void ReportCodeStatistics(const char* title); |
| 1660 #endif |
| 1661 |
1602 private: | 1662 private: |
1603 static const int kInitialStringTableSize = 2048; | 1663 struct StrongRootsList; |
1604 static const int kInitialEvalCacheSize = 64; | |
1605 static const int kInitialNumberStringCacheSize = 256; | |
1606 | |
1607 Heap(); | |
1608 | |
1609 int current_gc_flags() { return current_gc_flags_; } | |
1610 void set_current_gc_flags(int flags) { | |
1611 current_gc_flags_ = flags; | |
1612 DCHECK(!ShouldFinalizeIncrementalMarking() || | |
1613 !ShouldAbortIncrementalMarking()); | |
1614 } | |
1615 | |
1616 inline bool ShouldReduceMemory() const { | |
1617 return current_gc_flags_ & kReduceMemoryFootprintMask; | |
1618 } | |
1619 | |
1620 inline bool ShouldAbortIncrementalMarking() const { | |
1621 return current_gc_flags_ & kAbortIncrementalMarkingMask; | |
1622 } | |
1623 | |
1624 inline bool ShouldFinalizeIncrementalMarking() const { | |
1625 return current_gc_flags_ & kFinalizeIncrementalMarkingMask; | |
1626 } | |
1627 | |
1628 // Allocates a JS Map in the heap. | |
1629 MUST_USE_RESULT AllocationResult | |
1630 AllocateMap(InstanceType instance_type, int instance_size, | |
1631 ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND); | |
1632 | |
1633 // Allocates and initializes a new JavaScript object based on a | |
1634 // constructor. | |
1635 // If allocation_site is non-null, then a memento is emitted after the object | |
1636 // that points to the site. | |
1637 MUST_USE_RESULT AllocationResult | |
1638 AllocateJSObject(JSFunction* constructor, | |
1639 PretenureFlag pretenure = NOT_TENURED, | |
1640 AllocationSite* allocation_site = NULL); | |
1641 | |
1642 // Allocates and initializes a new JavaScript object based on a map. | |
1643 // Passing an allocation site means that a memento will be created that | |
1644 // points to the site. | |
1645 MUST_USE_RESULT AllocationResult | |
1646 AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure = NOT_TENURED, | |
1647 AllocationSite* allocation_site = NULL); | |
1648 | |
1649 // Allocates a HeapNumber from value. | |
1650 MUST_USE_RESULT AllocationResult | |
1651 AllocateHeapNumber(double value, MutableMode mode = IMMUTABLE, | |
1652 PretenureFlag pretenure = NOT_TENURED); | |
1653 | |
1654 // Allocates SIMD values from the given lane values. | |
1655 #define SIMD_ALLOCATE_DECLARATION(TYPE, Type, type, lane_count, lane_type) \ | |
1656 AllocationResult Allocate##Type(lane_type lanes[lane_count], \ | |
1657 PretenureFlag pretenure = NOT_TENURED); | |
1658 SIMD128_TYPES(SIMD_ALLOCATE_DECLARATION) | |
1659 #undef SIMD_ALLOCATE_DECLARATION | |
1660 | |
1661 // Allocates a byte array of the specified length | |
1662 MUST_USE_RESULT AllocationResult | |
1663 AllocateByteArray(int length, PretenureFlag pretenure = NOT_TENURED); | |
1664 | |
1665 // Allocates a bytecode array with given contents. | |
1666 MUST_USE_RESULT AllocationResult | |
1667 AllocateBytecodeArray(int length, const byte* raw_bytecodes, | |
1668 int frame_size); | |
1669 | |
1670 // Copy the code and scope info part of the code object, but insert | |
1671 // the provided data as the relocation information. | |
1672 MUST_USE_RESULT AllocationResult | |
1673 CopyCode(Code* code, Vector<byte> reloc_info); | |
1674 | |
1675 MUST_USE_RESULT AllocationResult CopyCode(Code* code); | |
1676 | |
1677 // Allocates a fixed array initialized with undefined values | |
1678 MUST_USE_RESULT AllocationResult | |
1679 AllocateFixedArray(int length, PretenureFlag pretenure = NOT_TENURED); | |
1680 | |
1681 // The amount of external memory registered through the API kept alive | |
1682 // by global handles | |
1683 int64_t amount_of_external_allocated_memory_; | |
1684 | |
1685 // Caches the amount of external memory registered at the last global gc. | |
1686 int64_t amount_of_external_allocated_memory_at_last_global_gc_; | |
1687 | |
1688 // This can be calculated directly from a pointer to the heap; however, it is | |
1689 // more expedient to get at the isolate directly from within Heap methods. | |
1690 Isolate* isolate_; | |
1691 | |
1692 Object* roots_[kRootListLength]; | |
1693 | |
1694 size_t code_range_size_; | |
1695 int reserved_semispace_size_; | |
1696 int max_semi_space_size_; | |
1697 int initial_semispace_size_; | |
1698 int target_semispace_size_; | |
1699 intptr_t max_old_generation_size_; | |
1700 intptr_t initial_old_generation_size_; | |
1701 bool old_generation_size_configured_; | |
1702 intptr_t max_executable_size_; | |
1703 intptr_t maximum_committed_; | |
1704 | |
1705 // For keeping track of how much data has survived | |
1706 // scavenge since last new space expansion. | |
1707 int survived_since_last_expansion_; | |
1708 | |
1709 // ... and since the last scavenge. | |
1710 int survived_last_scavenge_; | |
1711 | |
1712 int always_allocate_scope_depth_; | |
1713 | |
1714 // For keeping track of context disposals. | |
1715 int contexts_disposed_; | |
1716 | |
1717 int global_ic_age_; | |
1718 | |
1719 int scan_on_scavenge_pages_; | |
1720 | |
1721 NewSpace new_space_; | |
1722 OldSpace* old_space_; | |
1723 OldSpace* code_space_; | |
1724 MapSpace* map_space_; | |
1725 LargeObjectSpace* lo_space_; | |
1726 HeapState gc_state_; | |
1727 int gc_post_processing_depth_; | |
1728 Address new_space_top_after_last_gc_; | |
1729 | |
1730 // Returns the amount of external memory registered since last global gc. | |
1731 int64_t PromotedExternalMemorySize(); | |
1732 | |
1733 // How many "runtime allocations" happened. | |
1734 uint32_t allocations_count_; | |
1735 | |
1736 // Running hash over allocations performed. | |
1737 uint32_t raw_allocations_hash_; | |
1738 | |
1739 // Countdown counter, dumps allocation hash when 0. | |
1740 uint32_t dump_allocations_hash_countdown_; | |
1741 | |
1742 // How many mark-sweep collections happened. | |
1743 unsigned int ms_count_; | |
1744 | |
1745 // How many gc happened. | |
1746 unsigned int gc_count_; | |
1747 | |
1748 // For post mortem debugging. | |
1749 static const int kRememberedUnmappedPages = 128; | |
1750 int remembered_unmapped_pages_index_; | |
1751 Address remembered_unmapped_pages_[kRememberedUnmappedPages]; | |
1752 | |
1753 #define ROOT_ACCESSOR(type, name, camel_name) \ | |
1754 inline void set_##name(type* value); | |
1755 ROOT_LIST(ROOT_ACCESSOR) | |
1756 #undef ROOT_ACCESSOR | |
1757 | |
1758 #ifdef DEBUG | |
1759 // If the --gc-interval flag is set to a positive value, this | |
1760 // variable holds the value indicating the number of allocations | |
1761 // remain until the next failure and garbage collection. | |
1762 int allocation_timeout_; | |
1763 #endif // DEBUG | |
1764 | |
1765 // Limit that triggers a global GC on the next (normally caused) GC. This | |
1766 // is checked when we have already decided to do a GC to help determine | |
1767 // which collector to invoke, before expanding a paged space in the old | |
1768 // generation and on every allocation in large object space. | |
1769 intptr_t old_generation_allocation_limit_; | |
1770 | |
1771 // Indicates that an allocation has failed in the old generation since the | |
1772 // last GC. | |
1773 bool old_gen_exhausted_; | |
1774 | |
1775 // Indicates that memory usage is more important than latency. | |
1776 // TODO(ulan): Merge it with memory reducer once chromium:490559 is fixed. | |
1777 bool optimize_for_memory_usage_; | |
1778 | |
1779 // Indicates that inline bump-pointer allocation has been globally disabled | |
1780 // for all spaces. This is used to disable allocations in generated code. | |
1781 bool inline_allocation_disabled_; | |
1782 | |
1783 // Weak list heads, threaded through the objects. | |
1784 // List heads are initialized lazily and contain the undefined_value at start. | |
1785 Object* native_contexts_list_; | |
1786 Object* allocation_sites_list_; | |
1787 | |
1788 // List of encountered weak collections (JSWeakMap and JSWeakSet) during | |
1789 // marking. It is initialized during marking, destroyed after marking and | |
1790 // contains Smi(0) while marking is not active. | |
1791 Object* encountered_weak_collections_; | |
1792 | |
1793 Object* encountered_weak_cells_; | |
1794 | |
1795 StoreBufferRebuilder store_buffer_rebuilder_; | |
1796 | 1664 |
1797 struct StringTypeTable { | 1665 struct StringTypeTable { |
1798 InstanceType type; | 1666 InstanceType type; |
1799 int size; | 1667 int size; |
1800 RootListIndex index; | 1668 RootListIndex index; |
1801 }; | 1669 }; |
1802 | 1670 |
1803 struct ConstantStringTable { | 1671 struct ConstantStringTable { |
1804 const char* contents; | 1672 const char* contents; |
1805 RootListIndex index; | 1673 RootListIndex index; |
1806 }; | 1674 }; |
1807 | 1675 |
1808 struct StructTable { | 1676 struct StructTable { |
1809 InstanceType type; | 1677 InstanceType type; |
1810 int size; | 1678 int size; |
1811 RootListIndex index; | 1679 RootListIndex index; |
1812 }; | 1680 }; |
1813 | 1681 |
1814 static const StringTypeTable string_type_table[]; | |
1815 static const ConstantStringTable constant_string_table[]; | |
1816 static const StructTable struct_table[]; | |
1817 | |
1818 struct GCCallbackPair { | 1682 struct GCCallbackPair { |
1819 GCCallbackPair(v8::Isolate::GCCallback callback, GCType gc_type, | 1683 GCCallbackPair(v8::Isolate::GCCallback callback, GCType gc_type, |
1820 bool pass_isolate) | 1684 bool pass_isolate) |
1821 : callback(callback), gc_type(gc_type), pass_isolate(pass_isolate) {} | 1685 : callback(callback), gc_type(gc_type), pass_isolate(pass_isolate) {} |
1822 | 1686 |
1823 bool operator==(const GCCallbackPair& other) const { | 1687 bool operator==(const GCCallbackPair& other) const { |
1824 return other.callback == callback; | 1688 return other.callback == callback; |
1825 } | 1689 } |
1826 | 1690 |
1827 v8::Isolate::GCCallback callback; | 1691 v8::Isolate::GCCallback callback; |
1828 GCType gc_type; | 1692 GCType gc_type; |
1829 bool pass_isolate; | 1693 bool pass_isolate; |
1830 }; | 1694 }; |
1831 | 1695 |
1832 List<GCCallbackPair> gc_epilogue_callbacks_; | 1696 static const int kInitialStringTableSize = 2048; |
1833 List<GCCallbackPair> gc_prologue_callbacks_; | 1697 static const int kInitialEvalCacheSize = 64; |
| 1698 static const int kInitialNumberStringCacheSize = 256; |
| 1699 |
| 1700 static const int kRememberedUnmappedPages = 128; |
| 1701 |
| 1702 static const StringTypeTable string_type_table[]; |
| 1703 static const ConstantStringTable constant_string_table[]; |
| 1704 static const StructTable struct_table[]; |
| 1705 |
| 1706 static const int kYoungSurvivalRateHighThreshold = 90; |
| 1707 static const int kYoungSurvivalRateAllowedDeviation = 15; |
| 1708 static const int kOldSurvivalRateLowThreshold = 10; |
| 1709 |
| 1710 static const int kMaxMarkCompactsInIdleRound = 7; |
| 1711 static const int kIdleScavengeThreshold = 5; |
| 1712 |
| 1713 static const int kAllocationSiteScratchpadSize = 256; |
| 1714 |
| 1715 Heap(); |
| 1716 |
| 1717 static String* UpdateNewSpaceReferenceInExternalStringTableEntry( |
| 1718 Heap* heap, Object** pointer); |
| 1719 |
| 1720 static void ScavengeStoreBufferCallback(Heap* heap, MemoryChunk* page, |
| 1721 StoreBufferEvent event); |
| 1722 |
| 1723 // Selects the proper allocation space depending on the given object |
| 1724 // size and pretenuring decision. |
| 1725 static AllocationSpace SelectSpace(int object_size, PretenureFlag pretenure) { |
| 1726 if (object_size > Page::kMaxRegularHeapObjectSize) return LO_SPACE; |
| 1727 return (pretenure == TENURED) ? OLD_SPACE : NEW_SPACE; |
| 1728 } |
| 1729 |
| 1730 int current_gc_flags() { return current_gc_flags_; } |
| 1731 |
| 1732 void set_current_gc_flags(int flags) { |
| 1733 current_gc_flags_ = flags; |
| 1734 DCHECK(!ShouldFinalizeIncrementalMarking() || |
| 1735 !ShouldAbortIncrementalMarking()); |
| 1736 } |
| 1737 |
| 1738 inline bool ShouldReduceMemory() const { |
| 1739 return current_gc_flags_ & kReduceMemoryFootprintMask; |
| 1740 } |
| 1741 |
| 1742 inline bool ShouldAbortIncrementalMarking() const { |
| 1743 return current_gc_flags_ & kAbortIncrementalMarkingMask; |
| 1744 } |
| 1745 |
| 1746 inline bool ShouldFinalizeIncrementalMarking() const { |
| 1747 return current_gc_flags_ & kFinalizeIncrementalMarkingMask; |
| 1748 } |
| 1749 |
| 1750 #define ROOT_ACCESSOR(type, name, camel_name) \ |
| 1751 inline void set_##name(type* value); |
| 1752 ROOT_LIST(ROOT_ACCESSOR) |
| 1753 #undef ROOT_ACCESSOR |
1834 | 1754 |
1835 // Code that should be run before and after each GC. Includes some | 1755 // Code that should be run before and after each GC. Includes some |
1836 // reporting/verification activities when compiled with DEBUG set. | 1756 // reporting/verification activities when compiled with DEBUG set. |
1837 void GarbageCollectionPrologue(); | 1757 void GarbageCollectionPrologue(); |
1838 void GarbageCollectionEpilogue(); | 1758 void GarbageCollectionEpilogue(); |
1839 | 1759 |
1840 void PreprocessStackTraces(); | 1760 void PreprocessStackTraces(); |
1841 | 1761 |
1842 // Pretenuring decisions are made based on feedback collected during new | 1762 // Pretenuring decisions are made based on feedback collected during new |
1843 // space evacuation. Note that between feedback collection and calling this | 1763 // space evacuation. Note that between feedback collection and calling this |
(...skipping 24 matching lines...) Expand all Loading... |
1868 | 1788 |
1869 // Performs garbage collection | 1789 // Performs garbage collection |
1870 // Returns whether there is a chance another major GC could | 1790 // Returns whether there is a chance another major GC could |
1871 // collect more garbage. | 1791 // collect more garbage. |
1872 bool PerformGarbageCollection( | 1792 bool PerformGarbageCollection( |
1873 GarbageCollector collector, | 1793 GarbageCollector collector, |
1874 const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags); | 1794 const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags); |
1875 | 1795 |
1876 inline void UpdateOldSpaceLimits(); | 1796 inline void UpdateOldSpaceLimits(); |
1877 | 1797 |
1878 // Selects the proper allocation space depending on the given object | 1798 // Initializes a JSObject based on its map. |
1879 // size and pretenuring decision. | 1799 void InitializeJSObjectFromMap(JSObject* obj, FixedArray* properties, |
1880 static AllocationSpace SelectSpace(int object_size, | 1800 Map* map); |
1881 PretenureFlag pretenure) { | 1801 void InitializeAllocationMemento(AllocationMemento* memento, |
1882 if (object_size > Page::kMaxRegularHeapObjectSize) return LO_SPACE; | 1802 AllocationSite* allocation_site); |
1883 return (pretenure == TENURED) ? OLD_SPACE : NEW_SPACE; | 1803 |
1884 } | 1804 bool CreateInitialMaps(); |
| 1805 void CreateInitialObjects(); |
| 1806 |
| 1807 // These five Create*EntryStub functions are here and forced to not be inlined |
| 1808 // because of a gcc-4.4 bug that assigns wrong vtable entries. |
| 1809 NO_INLINE(void CreateJSEntryStub()); |
| 1810 NO_INLINE(void CreateJSConstructEntryStub()); |
| 1811 |
| 1812 void CreateFixedStubs(); |
1885 | 1813 |
1886 HeapObject* DoubleAlignForDeserialization(HeapObject* object, int size); | 1814 HeapObject* DoubleAlignForDeserialization(HeapObject* object, int size); |
1887 | 1815 |
| 1816 // Performs a minor collection in new generation. |
| 1817 void Scavenge(); |
| 1818 |
| 1819 // Commits from space if it is uncommitted. |
| 1820 void EnsureFromSpaceIsCommitted(); |
| 1821 |
| 1822 // Uncommit unused semi space. |
| 1823 bool UncommitFromSpace() { return new_space_.UncommitFromSpace(); } |
| 1824 |
| 1825 // Fill in bogus values in from space |
| 1826 void ZapFromSpace(); |
| 1827 |
| 1828 Address DoScavenge(ObjectVisitor* scavenge_visitor, Address new_space_front); |
| 1829 |
| 1830 // Performs a major collection in the whole heap. |
| 1831 void MarkCompact(); |
| 1832 |
| 1833 // Code to be run before and after mark-compact. |
| 1834 void MarkCompactPrologue(); |
| 1835 void MarkCompactEpilogue(); |
| 1836 |
| 1837 void ProcessNativeContexts(WeakObjectRetainer* retainer); |
| 1838 void ProcessAllocationSites(WeakObjectRetainer* retainer); |
| 1839 |
| 1840 // Deopts all code that contains allocation instruction which are tenured or |
| 1841 // not tenured. Moreover it clears the pretenuring allocation site statistics. |
| 1842 void ResetAllAllocationSitesDependentCode(PretenureFlag flag); |
| 1843 |
| 1844 // Evaluates local pretenuring for the old space and calls |
| 1845 // ResetAllTenuredAllocationSitesDependentCode if too many objects died in |
| 1846 // the old space. |
| 1847 void EvaluateOldSpaceLocalPretenuring(uint64_t size_of_objects_before_gc); |
| 1848 |
| 1849 // Called on heap tear-down. Frees all remaining ArrayBuffer backing stores. |
| 1850 void TearDownArrayBuffers(); |
| 1851 |
| 1852 // These correspond to the non-Helper versions. |
| 1853 void RegisterNewArrayBufferHelper(std::map<void*, size_t>& live_buffers, |
| 1854 void* data, size_t length); |
| 1855 void UnregisterArrayBufferHelper( |
| 1856 std::map<void*, size_t>& live_buffers, |
| 1857 std::map<void*, size_t>& not_yet_discovered_buffers, void* data); |
| 1858 void RegisterLiveArrayBufferHelper( |
| 1859 std::map<void*, size_t>& not_yet_discovered_buffers, void* data); |
| 1860 size_t FreeDeadArrayBuffersHelper( |
| 1861 Isolate* isolate, std::map<void*, size_t>& live_buffers, |
| 1862 std::map<void*, size_t>& not_yet_discovered_buffers); |
| 1863 void TearDownArrayBuffersHelper( |
| 1864 Isolate* isolate, std::map<void*, size_t>& live_buffers, |
| 1865 std::map<void*, size_t>& not_yet_discovered_buffers); |
| 1866 |
| 1867 // Record statistics before and after garbage collection. |
| 1868 void ReportStatisticsBeforeGC(); |
| 1869 void ReportStatisticsAfterGC(); |
| 1870 |
| 1871 // Creates and installs the full-sized number string cache. |
| 1872 int FullSizeNumberStringCacheLength(); |
| 1873 // Flush the number to string cache. |
| 1874 void FlushNumberStringCache(); |
| 1875 |
| 1876 // Sets used allocation sites entries to undefined. |
| 1877 void FlushAllocationSitesScratchpad(); |
| 1878 |
| 1879 // Initializes the allocation sites scratchpad with undefined values. |
| 1880 void InitializeAllocationSitesScratchpad(); |
| 1881 |
| 1882 // Adds an allocation site to the scratchpad if there is space left. |
| 1883 void AddAllocationSiteToScratchpad(AllocationSite* site, |
| 1884 ScratchpadSlotMode mode); |
| 1885 |
| 1886 // TODO(hpayer): Allocation site pretenuring may make this method obsolete. |
| 1887 // Re-visit incremental marking heuristics. |
| 1888 bool IsHighSurvivalRate() { return high_survival_rate_period_length_ > 0; } |
| 1889 |
| 1890 void ConfigureInitialOldGenerationSize(); |
| 1891 |
| 1892 void SelectScavengingVisitorsTable(); |
| 1893 |
| 1894 bool HasLowYoungGenerationAllocationRate(); |
| 1895 bool HasLowOldGenerationAllocationRate(); |
| 1896 double YoungGenerationMutatorUtilization(); |
| 1897 double OldGenerationMutatorUtilization(); |
| 1898 |
| 1899 void ReduceNewSpaceSize(); |
| 1900 |
| 1901 bool TryFinalizeIdleIncrementalMarking( |
| 1902 double idle_time_in_ms, size_t size_of_objects, |
| 1903 size_t mark_compact_speed_in_bytes_per_ms); |
| 1904 |
| 1905 GCIdleTimeHandler::HeapState ComputeHeapState(); |
| 1906 |
| 1907 bool PerformIdleTimeAction(GCIdleTimeAction action, |
| 1908 GCIdleTimeHandler::HeapState heap_state, |
| 1909 double deadline_in_ms); |
| 1910 |
| 1911 void IdleNotificationEpilogue(GCIdleTimeAction action, |
| 1912 GCIdleTimeHandler::HeapState heap_state, |
| 1913 double start_ms, double deadline_in_ms); |
| 1914 void CheckAndNotifyBackgroundIdleNotification(double idle_time_in_ms, |
| 1915 double now_ms); |
| 1916 |
| 1917 void ClearObjectStats(bool clear_last_time_stats = false); |
| 1918 |
| 1919 inline void UpdateAllocationsHash(HeapObject* object); |
| 1920 inline void UpdateAllocationsHash(uint32_t value); |
| 1921 inline void PrintAlloctionsHash(); |
| 1922 |
| 1923 void AddToRingBuffer(const char* string); |
| 1924 void GetFromRingBuffer(char* buffer); |
| 1925 |
| 1926 // =========================================================================== |
| 1927 // Allocation methods. ======================================================= |
| 1928 // =========================================================================== |
| 1929 |
| 1930 // Allocates a JS Map in the heap. |
| 1931 MUST_USE_RESULT AllocationResult |
| 1932 AllocateMap(InstanceType instance_type, int instance_size, |
| 1933 ElementsKind elements_kind = TERMINAL_FAST_ELEMENTS_KIND); |
| 1934 |
| 1935 // Allocates and initializes a new JavaScript object based on a |
| 1936 // constructor. |
| 1937 // If allocation_site is non-null, then a memento is emitted after the object |
| 1938 // that points to the site. |
| 1939 MUST_USE_RESULT AllocationResult AllocateJSObject( |
| 1940 JSFunction* constructor, PretenureFlag pretenure = NOT_TENURED, |
| 1941 AllocationSite* allocation_site = NULL); |
| 1942 |
| 1943 // Allocates and initializes a new JavaScript object based on a map. |
| 1944 // Passing an allocation site means that a memento will be created that |
| 1945 // points to the site. |
| 1946 MUST_USE_RESULT AllocationResult |
| 1947 AllocateJSObjectFromMap(Map* map, PretenureFlag pretenure = NOT_TENURED, |
| 1948 AllocationSite* allocation_site = NULL); |
| 1949 |
| 1950 // Allocates a HeapNumber from value. |
| 1951 MUST_USE_RESULT AllocationResult |
| 1952 AllocateHeapNumber(double value, MutableMode mode = IMMUTABLE, |
| 1953 PretenureFlag pretenure = NOT_TENURED); |
| 1954 |
| 1955 // Allocates SIMD values from the given lane values. |
| 1956 #define SIMD_ALLOCATE_DECLARATION(TYPE, Type, type, lane_count, lane_type) \ |
| 1957 AllocationResult Allocate##Type(lane_type lanes[lane_count], \ |
| 1958 PretenureFlag pretenure = NOT_TENURED); |
| 1959 SIMD128_TYPES(SIMD_ALLOCATE_DECLARATION) |
| 1960 #undef SIMD_ALLOCATE_DECLARATION |
| 1961 |
| 1962 // Allocates a byte array of the specified length |
| 1963 MUST_USE_RESULT AllocationResult |
| 1964 AllocateByteArray(int length, PretenureFlag pretenure = NOT_TENURED); |
| 1965 |
| 1966 // Allocates a bytecode array with given contents. |
| 1967 MUST_USE_RESULT AllocationResult |
| 1968 AllocateBytecodeArray(int length, const byte* raw_bytecodes, int frame_size); |
| 1969 |
| 1970 // Copy the code and scope info part of the code object, but insert |
| 1971 // the provided data as the relocation information. |
| 1972 MUST_USE_RESULT AllocationResult CopyCode(Code* code, |
| 1973 Vector<byte> reloc_info); |
| 1974 |
| 1975 MUST_USE_RESULT AllocationResult CopyCode(Code* code); |
| 1976 |
| 1977 // Allocates a fixed array initialized with undefined values |
| 1978 MUST_USE_RESULT AllocationResult |
| 1979 AllocateFixedArray(int length, PretenureFlag pretenure = NOT_TENURED); |
| 1980 |
1888 // Allocate an uninitialized object. The memory is non-executable if the | 1981 // Allocate an uninitialized object. The memory is non-executable if the |
1889 // hardware and OS allow. This is the single choke-point for allocations | 1982 // hardware and OS allow. This is the single choke-point for allocations |
1890 // performed by the runtime and should not be bypassed (to extend this to | 1983 // performed by the runtime and should not be bypassed (to extend this to |
1891 // inlined allocations, use the Heap::DisableInlineAllocation() support). | 1984 // inlined allocations, use the Heap::DisableInlineAllocation() support). |
1892 MUST_USE_RESULT inline AllocationResult AllocateRaw( | 1985 MUST_USE_RESULT inline AllocationResult AllocateRaw( |
1893 int size_in_bytes, AllocationSpace space, AllocationSpace retry_space, | 1986 int size_in_bytes, AllocationSpace space, AllocationSpace retry_space, |
1894 AllocationAlignment aligment = kWordAligned); | 1987 AllocationAlignment aligment = kWordAligned); |
1895 | 1988 |
1896 // Allocates a heap object based on the map. | 1989 // Allocates a heap object based on the map. |
1897 MUST_USE_RESULT AllocationResult | 1990 MUST_USE_RESULT AllocationResult |
1898 Allocate(Map* map, AllocationSpace space, | 1991 Allocate(Map* map, AllocationSpace space, |
1899 AllocationSite* allocation_site = NULL); | 1992 AllocationSite* allocation_site = NULL); |
1900 | 1993 |
1901 // Allocates a partial map for bootstrapping. | 1994 // Allocates a partial map for bootstrapping. |
1902 MUST_USE_RESULT AllocationResult | 1995 MUST_USE_RESULT AllocationResult |
1903 AllocatePartialMap(InstanceType instance_type, int instance_size); | 1996 AllocatePartialMap(InstanceType instance_type, int instance_size); |
1904 | 1997 |
1905 // Initializes a JSObject based on its map. | |
1906 void InitializeJSObjectFromMap(JSObject* obj, FixedArray* properties, | |
1907 Map* map); | |
1908 void InitializeAllocationMemento(AllocationMemento* memento, | |
1909 AllocationSite* allocation_site); | |
1910 | |
1911 // Allocate a block of memory in the given space (filled with a filler). | 1998 // Allocate a block of memory in the given space (filled with a filler). |
1912 // Used as a fall-back for generated code when the space is full. | 1999 // Used as a fall-back for generated code when the space is full. |
1913 MUST_USE_RESULT AllocationResult | 2000 MUST_USE_RESULT AllocationResult |
1914 AllocateFillerObject(int size, bool double_align, AllocationSpace space); | 2001 AllocateFillerObject(int size, bool double_align, AllocationSpace space); |
1915 | 2002 |
1916 // Allocate an uninitialized fixed array. | 2003 // Allocate an uninitialized fixed array. |
1917 MUST_USE_RESULT AllocationResult | 2004 MUST_USE_RESULT AllocationResult |
1918 AllocateRawFixedArray(int length, PretenureFlag pretenure); | 2005 AllocateRawFixedArray(int length, PretenureFlag pretenure); |
1919 | 2006 |
1920 // Allocate an uninitialized fixed double array. | 2007 // Allocate an uninitialized fixed double array. |
1921 MUST_USE_RESULT AllocationResult | 2008 MUST_USE_RESULT AllocationResult |
1922 AllocateRawFixedDoubleArray(int length, PretenureFlag pretenure); | 2009 AllocateRawFixedDoubleArray(int length, PretenureFlag pretenure); |
1923 | 2010 |
1924 // Allocate an initialized fixed array with the given filler value. | 2011 // Allocate an initialized fixed array with the given filler value. |
1925 MUST_USE_RESULT AllocationResult | 2012 MUST_USE_RESULT AllocationResult |
1926 AllocateFixedArrayWithFiller(int length, PretenureFlag pretenure, | 2013 AllocateFixedArrayWithFiller(int length, PretenureFlag pretenure, |
1927 Object* filler); | 2014 Object* filler); |
1928 | 2015 |
1929 // Allocate and partially initializes a String. There are two String | 2016 // Allocate and partially initializes a String. There are two String |
1930 // encodings: one-byte and two-byte. These functions allocate a string of | 2017 // encodings: one-byte and two-byte. These functions allocate a string of |
1931 // the given length and set its map and length fields. The characters of | 2018 // the given length and set its map and length fields. The characters of |
1932 // the string are uninitialized. | 2019 // the string are uninitialized. |
1933 MUST_USE_RESULT AllocationResult | 2020 MUST_USE_RESULT AllocationResult |
1934 AllocateRawOneByteString(int length, PretenureFlag pretenure); | 2021 AllocateRawOneByteString(int length, PretenureFlag pretenure); |
1935 MUST_USE_RESULT AllocationResult | 2022 MUST_USE_RESULT AllocationResult |
1936 AllocateRawTwoByteString(int length, PretenureFlag pretenure); | 2023 AllocateRawTwoByteString(int length, PretenureFlag pretenure); |
1937 | 2024 |
1938 bool CreateInitialMaps(); | |
1939 void CreateInitialObjects(); | |
1940 | |
1941 // Allocates an internalized string in old space based on the character | 2025 // Allocates an internalized string in old space based on the character |
1942 // stream. | 2026 // stream. |
1943 MUST_USE_RESULT inline AllocationResult AllocateInternalizedStringFromUtf8( | 2027 MUST_USE_RESULT inline AllocationResult AllocateInternalizedStringFromUtf8( |
1944 Vector<const char> str, int chars, uint32_t hash_field); | 2028 Vector<const char> str, int chars, uint32_t hash_field); |
1945 | 2029 |
1946 MUST_USE_RESULT inline AllocationResult AllocateOneByteInternalizedString( | 2030 MUST_USE_RESULT inline AllocationResult AllocateOneByteInternalizedString( |
1947 Vector<const uint8_t> str, uint32_t hash_field); | 2031 Vector<const uint8_t> str, uint32_t hash_field); |
1948 | 2032 |
1949 MUST_USE_RESULT inline AllocationResult AllocateTwoByteInternalizedString( | 2033 MUST_USE_RESULT inline AllocationResult AllocateTwoByteInternalizedString( |
1950 Vector<const uc16> str, uint32_t hash_field); | 2034 Vector<const uc16> str, uint32_t hash_field); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1997 MUST_USE_RESULT AllocationResult CopyAndTenureFixedCOWArray(FixedArray* src); | 2081 MUST_USE_RESULT AllocationResult CopyAndTenureFixedCOWArray(FixedArray* src); |
1998 | 2082 |
1999 // Make a copy of src, set the map, and return the copy. | 2083 // Make a copy of src, set the map, and return the copy. |
2000 MUST_USE_RESULT AllocationResult | 2084 MUST_USE_RESULT AllocationResult |
2001 CopyFixedDoubleArrayWithMap(FixedDoubleArray* src, Map* map); | 2085 CopyFixedDoubleArrayWithMap(FixedDoubleArray* src, Map* map); |
2002 | 2086 |
2003 // Allocates a fixed double array with uninitialized values. Returns | 2087 // Allocates a fixed double array with uninitialized values. Returns |
2004 MUST_USE_RESULT AllocationResult AllocateUninitializedFixedDoubleArray( | 2088 MUST_USE_RESULT AllocationResult AllocateUninitializedFixedDoubleArray( |
2005 int length, PretenureFlag pretenure = NOT_TENURED); | 2089 int length, PretenureFlag pretenure = NOT_TENURED); |
2006 | 2090 |
2007 // These five Create*EntryStub functions are here and forced to not be inlined | |
2008 // because of a gcc-4.4 bug that assigns wrong vtable entries. | |
2009 NO_INLINE(void CreateJSEntryStub()); | |
2010 NO_INLINE(void CreateJSConstructEntryStub()); | |
2011 | |
2012 void CreateFixedStubs(); | |
2013 | |
2014 // Allocate empty fixed array. | 2091 // Allocate empty fixed array. |
2015 MUST_USE_RESULT AllocationResult AllocateEmptyFixedArray(); | 2092 MUST_USE_RESULT AllocationResult AllocateEmptyFixedArray(); |
2016 | 2093 |
2017 // Allocate empty fixed typed array of given type. | 2094 // Allocate empty fixed typed array of given type. |
2018 MUST_USE_RESULT AllocationResult | 2095 MUST_USE_RESULT AllocationResult |
2019 AllocateEmptyFixedTypedArray(ExternalArrayType array_type); | 2096 AllocateEmptyFixedTypedArray(ExternalArrayType array_type); |
2020 | 2097 |
2021 // Allocate a tenured simple cell. | 2098 // Allocate a tenured simple cell. |
2022 MUST_USE_RESULT AllocationResult AllocateCell(Object* value); | 2099 MUST_USE_RESULT AllocationResult AllocateCell(Object* value); |
2023 | 2100 |
2024 // Allocate a tenured JS global property cell initialized with the hole. | 2101 // Allocate a tenured JS global property cell initialized with the hole. |
2025 MUST_USE_RESULT AllocationResult AllocatePropertyCell(); | 2102 MUST_USE_RESULT AllocationResult AllocatePropertyCell(); |
2026 | 2103 |
2027 MUST_USE_RESULT AllocationResult AllocateWeakCell(HeapObject* value); | 2104 MUST_USE_RESULT AllocationResult AllocateWeakCell(HeapObject* value); |
2028 | 2105 |
2029 // Allocates a new utility object in the old generation. | 2106 // Allocates a new utility object in the old generation. |
2030 MUST_USE_RESULT AllocationResult AllocateStruct(InstanceType type); | 2107 MUST_USE_RESULT AllocationResult AllocateStruct(InstanceType type); |
2031 | 2108 |
2032 // Allocates a new foreign object. | 2109 // Allocates a new foreign object. |
2033 MUST_USE_RESULT AllocationResult | 2110 MUST_USE_RESULT AllocationResult |
2034 AllocateForeign(Address address, PretenureFlag pretenure = NOT_TENURED); | 2111 AllocateForeign(Address address, PretenureFlag pretenure = NOT_TENURED); |
2035 | 2112 |
2036 MUST_USE_RESULT AllocationResult | 2113 MUST_USE_RESULT AllocationResult |
2037 AllocateCode(int object_size, bool immovable); | 2114 AllocateCode(int object_size, bool immovable); |
2038 | 2115 |
2039 MUST_USE_RESULT AllocationResult InternalizeStringWithKey(HashTableKey* key); | 2116 MUST_USE_RESULT AllocationResult InternalizeStringWithKey(HashTableKey* key); |
2040 | 2117 |
2041 MUST_USE_RESULT AllocationResult InternalizeString(String* str); | 2118 MUST_USE_RESULT AllocationResult InternalizeString(String* str); |
2042 | 2119 |
2043 // Performs a minor collection in new generation. | 2120 // The amount of external memory registered through the API kept alive |
2044 void Scavenge(); | 2121 // by global handles |
| 2122 int64_t amount_of_external_allocated_memory_; |
2045 | 2123 |
2046 // Commits from space if it is uncommitted. | 2124 // Caches the amount of external memory registered at the last global gc. |
2047 void EnsureFromSpaceIsCommitted(); | 2125 int64_t amount_of_external_allocated_memory_at_last_global_gc_; |
2048 | 2126 |
2049 // Uncommit unused semi space. | 2127 // This can be calculated directly from a pointer to the heap; however, it is |
2050 bool UncommitFromSpace() { return new_space_.UncommitFromSpace(); } | 2128 // more expedient to get at the isolate directly from within Heap methods. |
| 2129 Isolate* isolate_; |
2051 | 2130 |
2052 // Fill in bogus values in from space | 2131 Object* roots_[kRootListLength]; |
2053 void ZapFromSpace(); | |
2054 | 2132 |
2055 static String* UpdateNewSpaceReferenceInExternalStringTableEntry( | 2133 size_t code_range_size_; |
2056 Heap* heap, Object** pointer); | 2134 int reserved_semispace_size_; |
| 2135 int max_semi_space_size_; |
| 2136 int initial_semispace_size_; |
| 2137 int target_semispace_size_; |
| 2138 intptr_t max_old_generation_size_; |
| 2139 intptr_t initial_old_generation_size_; |
| 2140 bool old_generation_size_configured_; |
| 2141 intptr_t max_executable_size_; |
| 2142 intptr_t maximum_committed_; |
2057 | 2143 |
2058 Address DoScavenge(ObjectVisitor* scavenge_visitor, Address new_space_front); | 2144 // For keeping track of how much data has survived |
2059 static void ScavengeStoreBufferCallback(Heap* heap, MemoryChunk* page, | 2145 // scavenge since last new space expansion. |
2060 StoreBufferEvent event); | 2146 int survived_since_last_expansion_; |
2061 | 2147 |
2062 // Performs a major collection in the whole heap. | 2148 // ... and since the last scavenge. |
2063 void MarkCompact(); | 2149 int survived_last_scavenge_; |
2064 | 2150 |
2065 // Code to be run before and after mark-compact. | 2151 int always_allocate_scope_depth_; |
2066 void MarkCompactPrologue(); | |
2067 void MarkCompactEpilogue(); | |
2068 | 2152 |
2069 void ProcessNativeContexts(WeakObjectRetainer* retainer); | 2153 // For keeping track of context disposals. |
2070 void ProcessAllocationSites(WeakObjectRetainer* retainer); | 2154 int contexts_disposed_; |
2071 | 2155 |
2072 // Deopts all code that contains allocation instruction which are tenured or | 2156 int global_ic_age_; |
2073 // not tenured. Moreover it clears the pretenuring allocation site statistics. | |
2074 void ResetAllAllocationSitesDependentCode(PretenureFlag flag); | |
2075 | 2157 |
2076 // Evaluates local pretenuring for the old space and calls | 2158 int scan_on_scavenge_pages_; |
2077 // ResetAllTenuredAllocationSitesDependentCode if too many objects died in | |
2078 // the old space. | |
2079 void EvaluateOldSpaceLocalPretenuring(uint64_t size_of_objects_before_gc); | |
2080 | 2159 |
2081 // Called on heap tear-down. Frees all remaining ArrayBuffer backing stores. | 2160 NewSpace new_space_; |
2082 void TearDownArrayBuffers(); | 2161 OldSpace* old_space_; |
| 2162 OldSpace* code_space_; |
| 2163 MapSpace* map_space_; |
| 2164 LargeObjectSpace* lo_space_; |
| 2165 HeapState gc_state_; |
| 2166 int gc_post_processing_depth_; |
| 2167 Address new_space_top_after_last_gc_; |
2083 | 2168 |
2084 // These correspond to the non-Helper versions. | 2169 // Returns the amount of external memory registered since last global gc. |
2085 void RegisterNewArrayBufferHelper(std::map<void*, size_t>& live_buffers, | 2170 int64_t PromotedExternalMemorySize(); |
2086 void* data, size_t length); | |
2087 void UnregisterArrayBufferHelper( | |
2088 std::map<void*, size_t>& live_buffers, | |
2089 std::map<void*, size_t>& not_yet_discovered_buffers, void* data); | |
2090 void RegisterLiveArrayBufferHelper( | |
2091 std::map<void*, size_t>& not_yet_discovered_buffers, void* data); | |
2092 size_t FreeDeadArrayBuffersHelper( | |
2093 Isolate* isolate, std::map<void*, size_t>& live_buffers, | |
2094 std::map<void*, size_t>& not_yet_discovered_buffers); | |
2095 void TearDownArrayBuffersHelper( | |
2096 Isolate* isolate, std::map<void*, size_t>& live_buffers, | |
2097 std::map<void*, size_t>& not_yet_discovered_buffers); | |
2098 | 2171 |
2099 // Record statistics before and after garbage collection. | 2172 // How many "runtime allocations" happened. |
2100 void ReportStatisticsBeforeGC(); | 2173 uint32_t allocations_count_; |
2101 void ReportStatisticsAfterGC(); | 2174 |
| 2175 // Running hash over allocations performed. |
| 2176 uint32_t raw_allocations_hash_; |
| 2177 |
| 2178 // Countdown counter, dumps allocation hash when 0. |
| 2179 uint32_t dump_allocations_hash_countdown_; |
| 2180 |
| 2181 // How many mark-sweep collections happened. |
| 2182 unsigned int ms_count_; |
| 2183 |
| 2184 // How many gc happened. |
| 2185 unsigned int gc_count_; |
| 2186 |
| 2187 // For post mortem debugging. |
| 2188 int remembered_unmapped_pages_index_; |
| 2189 Address remembered_unmapped_pages_[kRememberedUnmappedPages]; |
| 2190 |
| 2191 #ifdef DEBUG |
| 2192 // If the --gc-interval flag is set to a positive value, this |
| 2193 // variable holds the value indicating the number of allocations |
| 2194 // remain until the next failure and garbage collection. |
| 2195 int allocation_timeout_; |
| 2196 #endif // DEBUG |
| 2197 |
| 2198 // Limit that triggers a global GC on the next (normally caused) GC. This |
| 2199 // is checked when we have already decided to do a GC to help determine |
| 2200 // which collector to invoke, before expanding a paged space in the old |
| 2201 // generation and on every allocation in large object space. |
| 2202 intptr_t old_generation_allocation_limit_; |
| 2203 |
| 2204 // Indicates that an allocation has failed in the old generation since the |
| 2205 // last GC. |
| 2206 bool old_gen_exhausted_; |
| 2207 |
| 2208 // Indicates that memory usage is more important than latency. |
| 2209 // TODO(ulan): Merge it with memory reducer once chromium:490559 is fixed. |
| 2210 bool optimize_for_memory_usage_; |
| 2211 |
| 2212 // Indicates that inline bump-pointer allocation has been globally disabled |
| 2213 // for all spaces. This is used to disable allocations in generated code. |
| 2214 bool inline_allocation_disabled_; |
| 2215 |
| 2216 // Weak list heads, threaded through the objects. |
| 2217 // List heads are initialized lazily and contain the undefined_value at start. |
| 2218 Object* native_contexts_list_; |
| 2219 Object* allocation_sites_list_; |
| 2220 |
| 2221 // List of encountered weak collections (JSWeakMap and JSWeakSet) during |
| 2222 // marking. It is initialized during marking, destroyed after marking and |
| 2223 // contains Smi(0) while marking is not active. |
| 2224 Object* encountered_weak_collections_; |
| 2225 |
| 2226 Object* encountered_weak_cells_; |
| 2227 |
| 2228 StoreBufferRebuilder store_buffer_rebuilder_; |
| 2229 |
| 2230 List<GCCallbackPair> gc_epilogue_callbacks_; |
| 2231 List<GCCallbackPair> gc_prologue_callbacks_; |
2102 | 2232 |
2103 // Total RegExp code ever generated | 2233 // Total RegExp code ever generated |
2104 double total_regexp_code_generated_; | 2234 double total_regexp_code_generated_; |
2105 | 2235 |
2106 int deferred_counters_[v8::Isolate::kUseCounterFeatureCount]; | 2236 int deferred_counters_[v8::Isolate::kUseCounterFeatureCount]; |
2107 | 2237 |
2108 GCTracer* tracer_; | 2238 GCTracer* tracer_; |
2109 | 2239 |
2110 // Creates and installs the full-sized number string cache. | |
2111 int FullSizeNumberStringCacheLength(); | |
2112 // Flush the number to string cache. | |
2113 void FlushNumberStringCache(); | |
2114 | |
2115 // Sets used allocation sites entries to undefined. | |
2116 void FlushAllocationSitesScratchpad(); | |
2117 | |
2118 // Initializes the allocation sites scratchpad with undefined values. | |
2119 void InitializeAllocationSitesScratchpad(); | |
2120 | |
2121 // Adds an allocation site to the scratchpad if there is space left. | |
2122 void AddAllocationSiteToScratchpad(AllocationSite* site, | |
2123 ScratchpadSlotMode mode); | |
2124 | |
2125 void UpdateSurvivalStatistics(int start_new_space_size); | |
2126 | |
2127 static const int kYoungSurvivalRateHighThreshold = 90; | |
2128 static const int kYoungSurvivalRateAllowedDeviation = 15; | |
2129 | |
2130 static const int kOldSurvivalRateLowThreshold = 10; | |
2131 | |
2132 int high_survival_rate_period_length_; | 2240 int high_survival_rate_period_length_; |
2133 intptr_t promoted_objects_size_; | 2241 intptr_t promoted_objects_size_; |
2134 double promotion_ratio_; | 2242 double promotion_ratio_; |
2135 double promotion_rate_; | 2243 double promotion_rate_; |
2136 intptr_t semi_space_copied_object_size_; | 2244 intptr_t semi_space_copied_object_size_; |
2137 intptr_t previous_semi_space_copied_object_size_; | 2245 intptr_t previous_semi_space_copied_object_size_; |
2138 double semi_space_copied_rate_; | 2246 double semi_space_copied_rate_; |
2139 int nodes_died_in_new_space_; | 2247 int nodes_died_in_new_space_; |
2140 int nodes_copied_in_new_space_; | 2248 int nodes_copied_in_new_space_; |
2141 int nodes_promoted_; | 2249 int nodes_promoted_; |
2142 | 2250 |
2143 // This is the pretenuring trigger for allocation sites that are in maybe | 2251 // This is the pretenuring trigger for allocation sites that are in maybe |
2144 // tenure state. When we switched to the maximum new space size we deoptimize | 2252 // tenure state. When we switched to the maximum new space size we deoptimize |
2145 // the code that belongs to the allocation site and derive the lifetime | 2253 // the code that belongs to the allocation site and derive the lifetime |
2146 // of the allocation site. | 2254 // of the allocation site. |
2147 unsigned int maximum_size_scavenges_; | 2255 unsigned int maximum_size_scavenges_; |
2148 | 2256 |
2149 // TODO(hpayer): Allocation site pretenuring may make this method obsolete. | |
2150 // Re-visit incremental marking heuristics. | |
2151 bool IsHighSurvivalRate() { return high_survival_rate_period_length_ > 0; } | |
2152 | |
2153 void ConfigureInitialOldGenerationSize(); | |
2154 | |
2155 void SelectScavengingVisitorsTable(); | |
2156 | |
2157 bool HasLowYoungGenerationAllocationRate(); | |
2158 bool HasLowOldGenerationAllocationRate(); | |
2159 double YoungGenerationMutatorUtilization(); | |
2160 double OldGenerationMutatorUtilization(); | |
2161 | |
2162 void ReduceNewSpaceSize(); | |
2163 | |
2164 bool TryFinalizeIdleIncrementalMarking( | |
2165 double idle_time_in_ms, size_t size_of_objects, | |
2166 size_t mark_compact_speed_in_bytes_per_ms); | |
2167 | |
2168 GCIdleTimeHandler::HeapState ComputeHeapState(); | |
2169 | |
2170 bool PerformIdleTimeAction(GCIdleTimeAction action, | |
2171 GCIdleTimeHandler::HeapState heap_state, | |
2172 double deadline_in_ms); | |
2173 | |
2174 void IdleNotificationEpilogue(GCIdleTimeAction action, | |
2175 GCIdleTimeHandler::HeapState heap_state, | |
2176 double start_ms, double deadline_in_ms); | |
2177 void CheckAndNotifyBackgroundIdleNotification(double idle_time_in_ms, | |
2178 double now_ms); | |
2179 | |
2180 void ClearObjectStats(bool clear_last_time_stats = false); | |
2181 | |
2182 inline void UpdateAllocationsHash(HeapObject* object); | |
2183 inline void UpdateAllocationsHash(uint32_t value); | |
2184 inline void PrintAlloctionsHash(); | |
2185 | |
2186 void AddToRingBuffer(const char* string); | |
2187 void GetFromRingBuffer(char* buffer); | |
2188 | |
2189 // Object counts and used memory by InstanceType | 2257 // Object counts and used memory by InstanceType |
2190 size_t object_counts_[OBJECT_STATS_COUNT]; | 2258 size_t object_counts_[OBJECT_STATS_COUNT]; |
2191 size_t object_counts_last_time_[OBJECT_STATS_COUNT]; | 2259 size_t object_counts_last_time_[OBJECT_STATS_COUNT]; |
2192 size_t object_sizes_[OBJECT_STATS_COUNT]; | 2260 size_t object_sizes_[OBJECT_STATS_COUNT]; |
2193 size_t object_sizes_last_time_[OBJECT_STATS_COUNT]; | 2261 size_t object_sizes_last_time_[OBJECT_STATS_COUNT]; |
2194 | 2262 |
2195 // Maximum GC pause. | 2263 // Maximum GC pause. |
2196 double max_gc_pause_; | 2264 double max_gc_pause_; |
2197 | 2265 |
2198 // Total time spent in GC. | 2266 // Total time spent in GC. |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2241 size_t old_generation_allocation_counter_; | 2309 size_t old_generation_allocation_counter_; |
2242 | 2310 |
2243 // The size of objects in old generation after the last MarkCompact GC. | 2311 // The size of objects in old generation after the last MarkCompact GC. |
2244 size_t old_generation_size_at_last_gc_; | 2312 size_t old_generation_size_at_last_gc_; |
2245 | 2313 |
2246 // If the --deopt_every_n_garbage_collections flag is set to a positive value, | 2314 // If the --deopt_every_n_garbage_collections flag is set to a positive value, |
2247 // this variable holds the number of garbage collections since the last | 2315 // this variable holds the number of garbage collections since the last |
2248 // deoptimization triggered by garbage collection. | 2316 // deoptimization triggered by garbage collection. |
2249 int gcs_since_last_deopt_; | 2317 int gcs_since_last_deopt_; |
2250 | 2318 |
2251 static const int kAllocationSiteScratchpadSize = 256; | |
2252 int allocation_sites_scratchpad_length_; | 2319 int allocation_sites_scratchpad_length_; |
2253 | 2320 |
2254 char trace_ring_buffer_[kTraceRingBufferSize]; | 2321 char trace_ring_buffer_[kTraceRingBufferSize]; |
2255 // If it's not full then the data is from 0 to ring_buffer_end_. If it's | 2322 // If it's not full then the data is from 0 to ring_buffer_end_. If it's |
2256 // full then the data is from ring_buffer_end_ to the end of the buffer and | 2323 // full then the data is from ring_buffer_end_ to the end of the buffer and |
2257 // from 0 to ring_buffer_end_. | 2324 // from 0 to ring_buffer_end_. |
2258 bool ring_buffer_full_; | 2325 bool ring_buffer_full_; |
2259 size_t ring_buffer_end_; | 2326 size_t ring_buffer_end_; |
2260 | 2327 |
2261 static const int kMaxMarkCompactsInIdleRound = 7; | |
2262 static const int kIdleScavengeThreshold = 5; | |
2263 | |
2264 // Shared state read by the scavenge collector and set by ScavengeObject. | 2328 // Shared state read by the scavenge collector and set by ScavengeObject. |
2265 PromotionQueue promotion_queue_; | 2329 PromotionQueue promotion_queue_; |
2266 | 2330 |
2267 // Flag is set when the heap has been configured. The heap can be repeatedly | 2331 // Flag is set when the heap has been configured. The heap can be repeatedly |
2268 // configured through the API until it is set up. | 2332 // configured through the API until it is set up. |
2269 bool configured_; | 2333 bool configured_; |
2270 | 2334 |
2271 // Currently set GC flags that are respected by all GC components. | 2335 // Currently set GC flags that are respected by all GC components. |
2272 int current_gc_flags_; | 2336 int current_gc_flags_; |
2273 | 2337 |
(...skipping 23 matching lines...) Expand all Loading... |
2297 | 2361 |
2298 // To be able to free memory held by ArrayBuffers during scavenge as well, we | 2362 // To be able to free memory held by ArrayBuffers during scavenge as well, we |
2299 // have a separate list of allocated memory held by ArrayBuffers in new space. | 2363 // have a separate list of allocated memory held by ArrayBuffers in new space. |
2300 // | 2364 // |
2301 // Since mark/compact also evacuates the new space, all pointers in the | 2365 // Since mark/compact also evacuates the new space, all pointers in the |
2302 // |live_array_buffers_for_scavenge_| list are also in the | 2366 // |live_array_buffers_for_scavenge_| list are also in the |
2303 // |live_array_buffers_| list. | 2367 // |live_array_buffers_| list. |
2304 std::map<void*, size_t> live_array_buffers_for_scavenge_; | 2368 std::map<void*, size_t> live_array_buffers_for_scavenge_; |
2305 std::map<void*, size_t> not_yet_discovered_array_buffers_for_scavenge_; | 2369 std::map<void*, size_t> not_yet_discovered_array_buffers_for_scavenge_; |
2306 | 2370 |
2307 struct StrongRootsList; | |
2308 StrongRootsList* strong_roots_list_; | 2371 StrongRootsList* strong_roots_list_; |
2309 | 2372 |
2310 friend class AlwaysAllocateScope; | 2373 friend class AlwaysAllocateScope; |
2311 friend class Bootstrapper; | 2374 friend class Bootstrapper; |
2312 friend class Deserializer; | 2375 friend class Deserializer; |
2313 friend class Factory; | 2376 friend class Factory; |
2314 friend class GCCallbacksScope; | 2377 friend class GCCallbacksScope; |
2315 friend class GCTracer; | 2378 friend class GCTracer; |
2316 friend class HeapIterator; | 2379 friend class HeapIterator; |
2317 friend class IncrementalMarking; | 2380 friend class IncrementalMarking; |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2687 DisallowHeapAllocation no_allocation; // i.e. no gc allowed. | 2750 DisallowHeapAllocation no_allocation; // i.e. no gc allowed. |
2688 | 2751 |
2689 private: | 2752 private: |
2690 DISALLOW_IMPLICIT_CONSTRUCTORS(PathTracer); | 2753 DISALLOW_IMPLICIT_CONSTRUCTORS(PathTracer); |
2691 }; | 2754 }; |
2692 #endif // DEBUG | 2755 #endif // DEBUG |
2693 } | 2756 } |
2694 } // namespace v8::internal | 2757 } // namespace v8::internal |
2695 | 2758 |
2696 #endif // V8_HEAP_HEAP_H_ | 2759 #endif // V8_HEAP_HEAP_H_ |
OLD | NEW |