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 #include "src/heap/heap.h" | 5 #include "src/heap/heap.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/api.h" | 8 #include "src/api.h" |
9 #include "src/assembler-inl.h" | 9 #include "src/assembler-inl.h" |
10 #include "src/ast/context-slot-cache.h" | 10 #include "src/ast/context-slot-cache.h" |
(...skipping 4761 matching lines...) Loading... | |
4772 VerifyPointersVisitor no_dirty_regions_visitor; | 4772 VerifyPointersVisitor no_dirty_regions_visitor; |
4773 code_space_->Verify(&no_dirty_regions_visitor); | 4773 code_space_->Verify(&no_dirty_regions_visitor); |
4774 | 4774 |
4775 lo_space_->Verify(); | 4775 lo_space_->Verify(); |
4776 | 4776 |
4777 mark_compact_collector()->VerifyWeakEmbeddedObjectsInCode(); | 4777 mark_compact_collector()->VerifyWeakEmbeddedObjectsInCode(); |
4778 if (FLAG_omit_map_checks_for_leaf_maps) { | 4778 if (FLAG_omit_map_checks_for_leaf_maps) { |
4779 mark_compact_collector()->VerifyOmittedMapChecks(); | 4779 mark_compact_collector()->VerifyOmittedMapChecks(); |
4780 } | 4780 } |
4781 } | 4781 } |
4782 | |
4783 class SlotVerifyingVisitor : public ObjectVisitor { | |
4784 public: | |
4785 SlotVerifyingVisitor(std::set<Address>* untyped, | |
4786 std::set<std::pair<SlotType, Address> >* typed) | |
4787 : untyped_(untyped), typed_(typed) {} | |
4788 | |
4789 virtual bool ShouldHaveBeenRecorded(HeapObject* host, Object* target) = 0; | |
4790 | |
4791 void VisitPointers(HeapObject* host, Object** start, Object** end) override { | |
4792 for (Object** slot = start; slot < end; slot++) { | |
4793 if (ShouldHaveBeenRecorded(host, *slot)) { | |
4794 CHECK_GT(untyped_->count(reinterpret_cast<Address>(slot)), 0); | |
4795 } | |
4796 } | |
4797 } | |
4798 | |
4799 void VisitCodeTarget(Code* host, RelocInfo* rinfo) override { | |
4800 Object* target = Code::GetCodeFromTargetAddress(rinfo->target_address()); | |
4801 if (ShouldHaveBeenRecorded(host, target)) { | |
4802 CHECK(InTypedSet(CODE_TARGET_SLOT, rinfo->pc()) || | |
4803 (rinfo->IsInConstantPool() && | |
4804 InTypedSet(CODE_ENTRY_SLOT, rinfo->pc()))); | |
4805 } | |
4806 } | |
4807 | |
4808 void VisitCodeAgeSequence(Code* host, RelocInfo* rinfo) override { | |
4809 Object* target = rinfo->code_age_stub(); | |
4810 if (ShouldHaveBeenRecorded(host, target)) { | |
4811 CHECK(InTypedSet(CODE_TARGET_SLOT, rinfo->pc()) || | |
4812 (rinfo->IsInConstantPool() && | |
4813 InTypedSet(CODE_ENTRY_SLOT, rinfo->pc()))); | |
4814 } | |
4815 } | |
4816 | |
4817 void VisitCodeEntry(JSFunction* host, Address entry_address) override { | |
4818 Object* target = Code::GetObjectFromEntryAddress(entry_address); | |
4819 if (ShouldHaveBeenRecorded(host, target)) { | |
4820 CHECK(InTypedSet(CODE_ENTRY_SLOT, entry_address)); | |
4821 } | |
4822 } | |
4823 | |
4824 void VisitCellPointer(Code* host, RelocInfo* rinfo) override { | |
4825 Object* target = rinfo->target_cell(); | |
4826 if (ShouldHaveBeenRecorded(host, target)) { | |
4827 CHECK( | |
4828 InTypedSet(CELL_TARGET_SLOT, rinfo->pc()) || | |
4829 (rinfo->IsInConstantPool() && InTypedSet(OBJECT_SLOT, rinfo->pc()))); | |
4830 } | |
4831 } | |
4832 | |
4833 void VisitDebugTarget(Code* host, RelocInfo* rinfo) override { | |
4834 Object* target = | |
4835 Code::GetCodeFromTargetAddress(rinfo->debug_call_address()); | |
4836 if (ShouldHaveBeenRecorded(host, target)) { | |
4837 CHECK(InTypedSet(DEBUG_TARGET_SLOT, rinfo->pc()) || | |
4838 (rinfo->IsInConstantPool() && | |
4839 InTypedSet(CODE_ENTRY_SLOT, rinfo->pc()))); | |
4840 } | |
4841 } | |
4842 | |
4843 void VisitEmbeddedPointer(Code* host, RelocInfo* rinfo) override { | |
4844 Object* target = rinfo->target_object(); | |
4845 if (ShouldHaveBeenRecorded(host, target)) { | |
4846 CHECK( | |
4847 InTypedSet(EMBEDDED_OBJECT_SLOT, rinfo->pc()) || | |
4848 (rinfo->IsInConstantPool() && InTypedSet(OBJECT_SLOT, rinfo->pc()))); | |
4849 } | |
4850 } | |
4851 | |
4852 private: | |
4853 bool InTypedSet(SlotType type, Address slot) { | |
4854 return typed_->count(std::make_pair(type, slot)) > 0; | |
4855 } | |
4856 std::set<Address>* untyped_; | |
4857 std::set<std::pair<SlotType, Address> >* typed_; | |
4858 }; | |
4859 | |
4860 class OldToNewSlotVerifyingVisitor : public SlotVerifyingVisitor { | |
4861 public: | |
4862 OldToNewSlotVerifyingVisitor(Heap* heap, std::set<Address>* untyped, | |
4863 std::set<std::pair<SlotType, Address> >* typed) | |
4864 : SlotVerifyingVisitor(untyped, typed), heap_(heap) {} | |
4865 | |
4866 bool ShouldHaveBeenRecorded(HeapObject* host, Object* target) override { | |
4867 return target->IsHeapObject() && heap_->InNewSpace(target) && | |
4868 !heap_->InNewSpace(host); | |
4869 } | |
4870 | |
4871 private: | |
4872 Heap* heap_; | |
4873 }; | |
4874 | |
4875 class OldToOldSlotVerifyingVisitor : public SlotVerifyingVisitor { | |
4876 public: | |
4877 OldToOldSlotVerifyingVisitor(std::set<Address>* untyped, | |
4878 std::set<std::pair<SlotType, Address> >* typed) | |
4879 : SlotVerifyingVisitor(untyped, typed) {} | |
4880 | |
4881 bool ShouldHaveBeenRecorded(HeapObject* host, Object* target) override { | |
4882 if (!target->IsHeapObject()) return false; | |
4883 Page* target_page = Page::FromAddress(reinterpret_cast<Address>(target)); | |
4884 Page* source_page = Page::FromAddress(reinterpret_cast<Address>(host)); | |
4885 return target_page->IsEvacuationCandidate() && | |
4886 !source_page->ShouldSkipEvacuationSlotRecording() && | |
4887 ObjectMarking::IsBlack(host, MarkingState::Internal(host)); | |
4888 } | |
4889 }; | |
4890 | |
4891 template <RememberedSetType direction> | |
4892 void CollectSlots(MemoryChunk* chunk, Address start, Address end, | |
4893 std::set<Address>* untyped, | |
4894 std::set<std::pair<SlotType, Address> >* typed) { | |
4895 RememberedSet<direction>::Iterate(chunk, [start, end, untyped](Address slot) { | |
4896 if (start <= slot && slot < end) { | |
4897 untyped->insert(slot); | |
4898 } | |
4899 return KEEP_SLOT; | |
4900 }); | |
4901 RememberedSet<direction>::IterateTyped( | |
4902 chunk, [start, end, typed](SlotType type, Address host, Address slot) { | |
4903 if (start <= slot && slot < end) { | |
4904 typed->insert(std::make_pair(type, slot)); | |
4905 } | |
4906 return KEEP_SLOT; | |
4907 }); | |
4908 } | |
4909 | |
4910 void Heap::VerifyRememberedSetFor(HeapObject* object) { | |
4911 MemoryChunk* chunk = MemoryChunk::FromAddress(object->address()); | |
4912 base::LockGuard<base::RecursiveMutex> lock_guard(chunk->mutex()); | |
4913 Address start = object->address(); | |
4914 Address end = start + object->Size(); | |
4915 std::set<Address> old_to_new, old_to_old; | |
4916 std::set<std::pair<SlotType, Address> > typed_old_to_new, typed_old_to_old; | |
4917 if (!InNewSpace(object)) { | |
4918 store_buffer()->MoveAllEntriesToRememberedSet(); | |
4919 CollectSlots<OLD_TO_NEW>(chunk, start, end, &old_to_new, &typed_old_to_new); | |
4920 OldToNewSlotVerifyingVisitor visitor(this, &old_to_new, &typed_old_to_new); | |
4921 object->IterateBody(&visitor); | |
4922 } | |
4923 // For some weak objects the slots are recorded in during the finalization | |
4924 // of mark-compactor. Since there is precise check for DescriptorArray and | |
Michael Lippautz
2017/05/09 17:44:05
/is/is no/
That is unfortunate :/
| |
4925 // the backing store of a weak JS collection we have to ignore all fixed | |
4926 // arrays and all hash tables. | |
4927 // TODO(ulan): record slots for all weak objects. | |
4928 if (ObjectMarking::IsBlack(object, MarkingState::Internal(object)) && | |
4929 !object->IsWeakCell() && !object->IsTransitionArray() && | |
4930 !object->IsFixedArray() && !object->IsHashTable()) { | |
4931 CollectSlots<OLD_TO_OLD>(chunk, start, end, &old_to_old, &typed_old_to_old); | |
4932 OldToOldSlotVerifyingVisitor visitor(&old_to_old, &typed_old_to_old); | |
4933 object->IterateBody(&visitor); | |
4934 } | |
4935 } | |
4782 #endif | 4936 #endif |
4783 | 4937 |
4784 | 4938 |
4785 void Heap::ZapFromSpace() { | 4939 void Heap::ZapFromSpace() { |
4786 if (!new_space_->IsFromSpaceCommitted()) return; | 4940 if (!new_space_->IsFromSpaceCommitted()) return; |
4787 for (Page* page : | 4941 for (Page* page : |
4788 PageRange(new_space_->FromSpaceStart(), new_space_->FromSpaceEnd())) { | 4942 PageRange(new_space_->FromSpaceStart(), new_space_->FromSpaceEnd())) { |
4789 for (Address cursor = page->area_start(), limit = page->area_end(); | 4943 for (Address cursor = page->area_start(), limit = page->area_end(); |
4790 cursor < limit; cursor += kPointerSize) { | 4944 cursor < limit; cursor += kPointerSize) { |
4791 Memory::Address_at(cursor) = kFromSpaceZapValue; | 4945 Memory::Address_at(cursor) = kFromSpaceZapValue; |
(...skipping 1599 matching lines...) Loading... | |
6391 case LO_SPACE: | 6545 case LO_SPACE: |
6392 return "LO_SPACE"; | 6546 return "LO_SPACE"; |
6393 default: | 6547 default: |
6394 UNREACHABLE(); | 6548 UNREACHABLE(); |
6395 } | 6549 } |
6396 return NULL; | 6550 return NULL; |
6397 } | 6551 } |
6398 | 6552 |
6399 } // namespace internal | 6553 } // namespace internal |
6400 } // namespace v8 | 6554 } // namespace v8 |
OLD | NEW |