Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 208 bool Heap::HasBeenSetup() { | 208 bool Heap::HasBeenSetup() { |
| 209 return old_pointer_space_ != NULL && | 209 return old_pointer_space_ != NULL && |
| 210 old_data_space_ != NULL && | 210 old_data_space_ != NULL && |
| 211 code_space_ != NULL && | 211 code_space_ != NULL && |
| 212 map_space_ != NULL && | 212 map_space_ != NULL && |
| 213 cell_space_ != NULL && | 213 cell_space_ != NULL && |
| 214 lo_space_ != NULL; | 214 lo_space_ != NULL; |
| 215 } | 215 } |
| 216 | 216 |
| 217 | 217 |
| 218 int Heap::GcSafeSizeOfOldObject(HeapObject* object) { | 218 int Heap::GcSafeSizeOfOldObject(HeapObject* object) { |
|
Erik Corry
2011/01/07 12:13:21
Shouldn't we just get rid of this alltogether?
| |
| 219 ASSERT(!Heap::InNewSpace(object)); // Code only works for old objects. | 219 return object->Size(); |
| 220 ASSERT(!MarkCompactCollector::are_map_pointers_encoded()); | |
| 221 MapWord map_word = object->map_word(); | |
| 222 map_word.ClearMark(); | |
| 223 map_word.ClearOverflow(); | |
| 224 return object->SizeFromMap(map_word.ToMap()); | |
| 225 } | 220 } |
| 226 | 221 |
| 227 | 222 |
| 228 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space) { | 223 GarbageCollector Heap::SelectGarbageCollector(AllocationSpace space) { |
| 229 // Is global GC requested? | 224 // Is global GC requested? |
| 230 if (space != NEW_SPACE || FLAG_gc_global) { | 225 if (space != NEW_SPACE || FLAG_gc_global) { |
| 231 Counters::gc_compactor_caused_by_request.Increment(); | 226 Counters::gc_compactor_caused_by_request.Increment(); |
| 232 return MARK_COMPACTOR; | 227 return MARK_COMPACTOR; |
| 233 } | 228 } |
| 234 | 229 |
| (...skipping 4356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4591 } | 4586 } |
| 4592 | 4587 |
| 4593 LOG(IntPtrTEvent("heap-capacity", Capacity())); | 4588 LOG(IntPtrTEvent("heap-capacity", Capacity())); |
| 4594 LOG(IntPtrTEvent("heap-available", Available())); | 4589 LOG(IntPtrTEvent("heap-available", Available())); |
| 4595 | 4590 |
| 4596 #ifdef ENABLE_LOGGING_AND_PROFILING | 4591 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 4597 // This should be called only after initial objects have been created. | 4592 // This should be called only after initial objects have been created. |
| 4598 ProducerHeapProfile::Setup(); | 4593 ProducerHeapProfile::Setup(); |
| 4599 #endif | 4594 #endif |
| 4600 | 4595 |
| 4596 if (!Marking::Setup()) return false; | |
| 4597 | |
| 4601 return true; | 4598 return true; |
| 4602 } | 4599 } |
| 4603 | 4600 |
| 4604 | 4601 |
| 4605 void Heap::SetStackLimits() { | 4602 void Heap::SetStackLimits() { |
| 4606 // On 64 bit machines, pointers are generally out of range of Smis. We write | 4603 // On 64 bit machines, pointers are generally out of range of Smis. We write |
| 4607 // something that looks like an out of range Smi to the GC. | 4604 // something that looks like an out of range Smi to the GC. |
| 4608 | 4605 |
| 4609 // Set up the special root array entries containing the stack limits. | 4606 // Set up the special root array entries containing the stack limits. |
| 4610 // These are actually addresses, but the tag makes the GC ignore it. | 4607 // These are actually addresses, but the tag makes the GC ignore it. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4665 delete cell_space_; | 4662 delete cell_space_; |
| 4666 cell_space_ = NULL; | 4663 cell_space_ = NULL; |
| 4667 } | 4664 } |
| 4668 | 4665 |
| 4669 if (lo_space_ != NULL) { | 4666 if (lo_space_ != NULL) { |
| 4670 lo_space_->TearDown(); | 4667 lo_space_->TearDown(); |
| 4671 delete lo_space_; | 4668 delete lo_space_; |
| 4672 lo_space_ = NULL; | 4669 lo_space_ = NULL; |
| 4673 } | 4670 } |
| 4674 | 4671 |
| 4672 Marking::TearDown(); | |
| 4673 | |
| 4675 MemoryAllocator::TearDown(); | 4674 MemoryAllocator::TearDown(); |
| 4676 } | 4675 } |
| 4677 | 4676 |
| 4678 | 4677 |
| 4679 void Heap::Shrink() { | 4678 void Heap::Shrink() { |
| 4680 // Try to shrink all paged spaces. | 4679 // Try to shrink all paged spaces. |
| 4681 PagedSpaces spaces; | 4680 PagedSpaces spaces; |
| 4682 for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next()) | 4681 for (PagedSpace* space = spaces.next(); space != NULL; space = spaces.next()) |
| 4683 space->Shrink(); | 4682 space->Shrink(); |
| 4684 } | 4683 } |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4898 } | 4897 } |
| 4899 | 4898 |
| 4900 | 4899 |
| 4901 class HeapObjectsFilter { | 4900 class HeapObjectsFilter { |
| 4902 public: | 4901 public: |
| 4903 virtual ~HeapObjectsFilter() {} | 4902 virtual ~HeapObjectsFilter() {} |
| 4904 virtual bool SkipObject(HeapObject* object) = 0; | 4903 virtual bool SkipObject(HeapObject* object) = 0; |
| 4905 }; | 4904 }; |
| 4906 | 4905 |
| 4907 | 4906 |
| 4907 // Intrusive object marking uses least significant bit of | |
| 4908 // heap object's map word to mark objects. | |
| 4909 // Normally all map words have least significant bit set | |
| 4910 // because they contain tagged map pointer. | |
| 4911 // If the bit is not set object is marked. | |
| 4912 // All objects should be unmarked before resuming | |
| 4913 // JavaScript execution. | |
| 4914 class IntrusiveMarking { | |
| 4915 public: | |
| 4916 static bool IsMarked(HeapObject* object) { | |
| 4917 return (object->map_word().ToRawValue() & kNotMarkedBit) == 0; | |
| 4918 } | |
| 4919 | |
| 4920 static void ClearMark(HeapObject* object) { | |
| 4921 uintptr_t map_word = object->map_word().ToRawValue(); | |
| 4922 object->set_map_word(MapWord::FromRawValue(map_word | kNotMarkedBit)); | |
| 4923 } | |
| 4924 | |
| 4925 static void SetMark(HeapObject* object) { | |
| 4926 uintptr_t map_word = object->map_word().ToRawValue(); | |
| 4927 object->set_map_word(MapWord::FromRawValue(map_word & ~kNotMarkedBit)); | |
| 4928 } | |
| 4929 | |
| 4930 private: | |
| 4931 static const uintptr_t kNotMarkedBit = 0x1; | |
| 4932 STATIC_ASSERT((kHeapObjectTag & kNotMarkedBit) != 0); | |
| 4933 }; | |
| 4934 | |
| 4908 class FreeListNodesFilter : public HeapObjectsFilter { | 4935 class FreeListNodesFilter : public HeapObjectsFilter { |
| 4909 public: | 4936 public: |
| 4910 FreeListNodesFilter() { | 4937 FreeListNodesFilter() { |
| 4911 MarkFreeListNodes(); | 4938 MarkFreeListNodes(); |
| 4912 } | 4939 } |
| 4913 | 4940 |
| 4914 bool SkipObject(HeapObject* object) { | 4941 bool SkipObject(HeapObject* object) { |
| 4915 if (object->IsMarked()) { | 4942 if (IntrusiveMarking::IsMarked(object)) { |
| 4916 object->ClearMark(); | 4943 IntrusiveMarking::ClearMark(object); |
| 4917 return true; | 4944 return true; |
| 4918 } else { | 4945 } else { |
| 4919 return false; | 4946 return false; |
| 4920 } | 4947 } |
| 4921 } | 4948 } |
| 4922 | 4949 |
| 4923 private: | 4950 private: |
| 4924 void MarkFreeListNodes() { | 4951 void MarkFreeListNodes() { |
| 4925 Heap::old_pointer_space()->MarkFreeListNodes(); | 4952 Heap::old_pointer_space()->MarkFreeListNodes(); |
| 4926 Heap::old_data_space()->MarkFreeListNodes(); | 4953 Heap::old_data_space()->MarkFreeListNodes(); |
| 4927 MarkCodeSpaceFreeListNodes(); | 4954 MarkCodeSpaceFreeListNodes(); |
| 4928 Heap::map_space()->MarkFreeListNodes(); | 4955 Heap::map_space()->MarkFreeListNodes(); |
| 4929 Heap::cell_space()->MarkFreeListNodes(); | 4956 Heap::cell_space()->MarkFreeListNodes(); |
| 4930 } | 4957 } |
| 4931 | 4958 |
| 4932 void MarkCodeSpaceFreeListNodes() { | 4959 void MarkCodeSpaceFreeListNodes() { |
| 4933 // For code space, using FreeListNode::IsFreeListNode is OK. | 4960 // For code space, using FreeListNode::IsFreeListNode is OK. |
| 4934 HeapObjectIterator iter(Heap::code_space()); | 4961 HeapObjectIterator iter(Heap::code_space()); |
| 4935 for (HeapObject* obj = iter.next_object(); | 4962 for (HeapObject* obj = iter.next_object(); |
| 4936 obj != NULL; | 4963 obj != NULL; |
| 4937 obj = iter.next_object()) { | 4964 obj = iter.next_object()) { |
| 4938 if (FreeListNode::IsFreeListNode(obj)) obj->SetMark(); | 4965 if (FreeListNode::IsFreeListNode(obj)) { |
| 4966 IntrusiveMarking::SetMark(obj); | |
| 4967 } | |
| 4939 } | 4968 } |
| 4940 } | 4969 } |
| 4941 | 4970 |
| 4942 AssertNoAllocation no_alloc; | 4971 AssertNoAllocation no_alloc; |
| 4943 }; | 4972 }; |
| 4944 | 4973 |
| 4945 | 4974 |
| 4946 class UnreachableObjectsFilter : public HeapObjectsFilter { | 4975 class UnreachableObjectsFilter : public HeapObjectsFilter { |
| 4947 public: | 4976 public: |
| 4948 UnreachableObjectsFilter() { | 4977 UnreachableObjectsFilter() { |
| 4949 MarkUnreachableObjects(); | 4978 MarkUnreachableObjects(); |
| 4950 } | 4979 } |
| 4951 | 4980 |
| 4952 bool SkipObject(HeapObject* object) { | 4981 bool SkipObject(HeapObject* object) { |
| 4953 if (object->IsMarked()) { | 4982 if (IntrusiveMarking::IsMarked(object)) { |
| 4954 object->ClearMark(); | 4983 IntrusiveMarking::ClearMark(object); |
| 4955 return true; | 4984 return true; |
| 4956 } else { | 4985 } else { |
| 4957 return false; | 4986 return false; |
| 4958 } | 4987 } |
| 4959 } | 4988 } |
| 4960 | 4989 |
| 4961 private: | 4990 private: |
| 4962 class UnmarkingVisitor : public ObjectVisitor { | 4991 class UnmarkingVisitor : public ObjectVisitor { |
| 4963 public: | 4992 public: |
| 4964 UnmarkingVisitor() : list_(10) {} | 4993 UnmarkingVisitor() : list_(10) {} |
| 4965 | 4994 |
| 4966 void VisitPointers(Object** start, Object** end) { | 4995 void VisitPointers(Object** start, Object** end) { |
| 4967 for (Object** p = start; p < end; p++) { | 4996 for (Object** p = start; p < end; p++) { |
| 4968 if (!(*p)->IsHeapObject()) continue; | 4997 if (!(*p)->IsHeapObject()) continue; |
| 4969 HeapObject* obj = HeapObject::cast(*p); | 4998 HeapObject* obj = HeapObject::cast(*p); |
| 4970 if (obj->IsMarked()) { | 4999 if (IntrusiveMarking::IsMarked(obj)) { |
| 4971 obj->ClearMark(); | 5000 IntrusiveMarking::ClearMark(obj); |
| 4972 list_.Add(obj); | 5001 list_.Add(obj); |
| 4973 } | 5002 } |
| 4974 } | 5003 } |
| 4975 } | 5004 } |
| 4976 | 5005 |
| 4977 bool can_process() { return !list_.is_empty(); } | 5006 bool can_process() { return !list_.is_empty(); } |
| 4978 | 5007 |
| 4979 void ProcessNext() { | 5008 void ProcessNext() { |
| 4980 HeapObject* obj = list_.RemoveLast(); | 5009 HeapObject* obj = list_.RemoveLast(); |
| 4981 obj->Iterate(this); | 5010 obj->Iterate(this); |
| 4982 } | 5011 } |
| 4983 | 5012 |
| 4984 private: | 5013 private: |
| 4985 List<HeapObject*> list_; | 5014 List<HeapObject*> list_; |
| 4986 }; | 5015 }; |
| 4987 | 5016 |
| 4988 void MarkUnreachableObjects() { | 5017 void MarkUnreachableObjects() { |
| 4989 HeapIterator iterator; | 5018 HeapIterator iterator; |
| 4990 for (HeapObject* obj = iterator.next(); | 5019 for (HeapObject* obj = iterator.next(); |
| 4991 obj != NULL; | 5020 obj != NULL; |
| 4992 obj = iterator.next()) { | 5021 obj = iterator.next()) { |
| 4993 obj->SetMark(); | 5022 IntrusiveMarking::SetMark(obj); |
| 4994 } | 5023 } |
| 4995 UnmarkingVisitor visitor; | 5024 UnmarkingVisitor visitor; |
| 4996 Heap::IterateRoots(&visitor, VISIT_ONLY_STRONG); | 5025 Heap::IterateRoots(&visitor, VISIT_ONLY_STRONG); |
| 4997 while (visitor.can_process()) | 5026 while (visitor.can_process()) |
| 4998 visitor.ProcessNext(); | 5027 visitor.ProcessNext(); |
| 4999 } | 5028 } |
| 5000 | 5029 |
| 5001 AssertNoAllocation no_alloc; | 5030 AssertNoAllocation no_alloc; |
| 5002 }; | 5031 }; |
| 5003 | 5032 |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5277 gc_count_(0), | 5306 gc_count_(0), |
| 5278 full_gc_count_(0), | 5307 full_gc_count_(0), |
| 5279 is_compacting_(false), | 5308 is_compacting_(false), |
| 5280 marked_count_(0), | 5309 marked_count_(0), |
| 5281 allocated_since_last_gc_(0), | 5310 allocated_since_last_gc_(0), |
| 5282 spent_in_mutator_(0), | 5311 spent_in_mutator_(0), |
| 5283 promoted_objects_size_(0) { | 5312 promoted_objects_size_(0) { |
| 5284 // These two fields reflect the state of the previous full collection. | 5313 // These two fields reflect the state of the previous full collection. |
| 5285 // Set them before they are changed by the collector. | 5314 // Set them before they are changed by the collector. |
| 5286 previous_has_compacted_ = MarkCompactCollector::HasCompacted(); | 5315 previous_has_compacted_ = MarkCompactCollector::HasCompacted(); |
| 5287 previous_marked_count_ = MarkCompactCollector::previous_marked_count(); | |
| 5288 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; | 5316 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; |
| 5289 start_time_ = OS::TimeCurrentMillis(); | 5317 start_time_ = OS::TimeCurrentMillis(); |
| 5290 start_size_ = Heap::SizeOfObjects(); | 5318 start_size_ = Heap::SizeOfObjects(); |
| 5291 | 5319 |
| 5292 for (int i = 0; i < Scope::kNumberOfScopes; i++) { | 5320 for (int i = 0; i < Scope::kNumberOfScopes; i++) { |
| 5293 scopes_[i] = 0; | 5321 scopes_[i] = 0; |
| 5294 } | 5322 } |
| 5295 | 5323 |
| 5296 in_free_list_or_wasted_before_gc_ = CountTotalHolesSize(); | 5324 in_free_list_or_wasted_before_gc_ = CountTotalHolesSize(); |
| 5297 | 5325 |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5500 void ExternalStringTable::TearDown() { | 5528 void ExternalStringTable::TearDown() { |
| 5501 new_space_strings_.Free(); | 5529 new_space_strings_.Free(); |
| 5502 old_space_strings_.Free(); | 5530 old_space_strings_.Free(); |
| 5503 } | 5531 } |
| 5504 | 5532 |
| 5505 | 5533 |
| 5506 List<Object*> ExternalStringTable::new_space_strings_; | 5534 List<Object*> ExternalStringTable::new_space_strings_; |
| 5507 List<Object*> ExternalStringTable::old_space_strings_; | 5535 List<Object*> ExternalStringTable::old_space_strings_; |
| 5508 | 5536 |
| 5509 } } // namespace v8::internal | 5537 } } // namespace v8::internal |
| OLD | NEW |