| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 live_young_objects_size_(0), | 66 live_young_objects_size_(0), |
| 67 live_old_pointer_objects_size_(0), | 67 live_old_pointer_objects_size_(0), |
| 68 live_old_data_objects_size_(0), | 68 live_old_data_objects_size_(0), |
| 69 live_code_objects_size_(0), | 69 live_code_objects_size_(0), |
| 70 live_map_objects_size_(0), | 70 live_map_objects_size_(0), |
| 71 live_cell_objects_size_(0), | 71 live_cell_objects_size_(0), |
| 72 live_lo_objects_size_(0), | 72 live_lo_objects_size_(0), |
| 73 live_bytes_(0), | 73 live_bytes_(0), |
| 74 #endif | 74 #endif |
| 75 heap_(NULL), | 75 heap_(NULL), |
| 76 code_flusher_(NULL) { } | 76 code_flusher_(NULL), |
| 77 encountered_weak_maps_(NULL) { } |
| 77 | 78 |
| 78 | 79 |
| 79 #ifdef DEBUG | 80 #ifdef DEBUG |
| 80 class VerifyMarkingVisitor: public ObjectVisitor { | 81 class VerifyMarkingVisitor: public ObjectVisitor { |
| 81 public: | 82 public: |
| 82 void VisitPointers(Object** start, Object** end) { | 83 void VisitPointers(Object** start, Object** end) { |
| 83 for (Object** current = start; current < end; current++) { | 84 for (Object** current = start; current < end; current++) { |
| 84 if ((*current)->IsHeapObject()) { | 85 if ((*current)->IsHeapObject()) { |
| 85 HeapObject* object = HeapObject::cast(*current); | 86 HeapObject* object = HeapObject::cast(*current); |
| 86 ASSERT(HEAP->mark_compact_collector()->IsMarked(object)); | 87 ASSERT(HEAP->mark_compact_collector()->IsMarked(object)); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 } | 245 } |
| 245 | 246 |
| 246 return compacting_; | 247 return compacting_; |
| 247 } | 248 } |
| 248 | 249 |
| 249 | 250 |
| 250 void MarkCompactCollector::CollectGarbage() { | 251 void MarkCompactCollector::CollectGarbage() { |
| 251 // Make sure that Prepare() has been called. The individual steps below will | 252 // Make sure that Prepare() has been called. The individual steps below will |
| 252 // update the state as they proceed. | 253 // update the state as they proceed. |
| 253 ASSERT(state_ == PREPARE_GC); | 254 ASSERT(state_ == PREPARE_GC); |
| 255 ASSERT(encountered_weak_maps_ == Smi::FromInt(0)); |
| 254 | 256 |
| 255 MarkLiveObjects(); | 257 MarkLiveObjects(); |
| 256 ASSERT(heap_->incremental_marking()->IsStopped()); | 258 ASSERT(heap_->incremental_marking()->IsStopped()); |
| 257 | 259 |
| 258 if (collect_maps_) ClearNonLiveTransitions(); | 260 if (collect_maps_) ClearNonLiveTransitions(); |
| 259 | 261 |
| 262 ClearWeakMaps(); |
| 263 |
| 260 #ifdef DEBUG | 264 #ifdef DEBUG |
| 261 if (FLAG_verify_heap) { | 265 if (FLAG_verify_heap) { |
| 262 VerifyMarking(heap_); | 266 VerifyMarking(heap_); |
| 263 } | 267 } |
| 264 #endif | 268 #endif |
| 265 | 269 |
| 266 SweepSpaces(); | 270 SweepSpaces(); |
| 267 | 271 |
| 268 if (!collect_maps_) ReattachInitialMaps(); | 272 if (!collect_maps_) ReattachInitialMaps(); |
| 269 | 273 |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 | 688 |
| 685 table_.Register(kVisitGlobalContext, &VisitGlobalContext); | 689 table_.Register(kVisitGlobalContext, &VisitGlobalContext); |
| 686 | 690 |
| 687 table_.Register(kVisitFixedDoubleArray, DataObjectVisitor::Visit); | 691 table_.Register(kVisitFixedDoubleArray, DataObjectVisitor::Visit); |
| 688 | 692 |
| 689 table_.Register(kVisitByteArray, &DataObjectVisitor::Visit); | 693 table_.Register(kVisitByteArray, &DataObjectVisitor::Visit); |
| 690 table_.Register(kVisitFreeSpace, &DataObjectVisitor::Visit); | 694 table_.Register(kVisitFreeSpace, &DataObjectVisitor::Visit); |
| 691 table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit); | 695 table_.Register(kVisitSeqAsciiString, &DataObjectVisitor::Visit); |
| 692 table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit); | 696 table_.Register(kVisitSeqTwoByteString, &DataObjectVisitor::Visit); |
| 693 | 697 |
| 698 table_.Register(kVisitJSWeakMap, &VisitJSWeakMap); |
| 699 |
| 694 table_.Register(kVisitOddball, | 700 table_.Register(kVisitOddball, |
| 695 &FixedBodyVisitor<StaticMarkingVisitor, | 701 &FixedBodyVisitor<StaticMarkingVisitor, |
| 696 Oddball::BodyDescriptor, | 702 Oddball::BodyDescriptor, |
| 697 void>::Visit); | 703 void>::Visit); |
| 698 table_.Register(kVisitMap, | 704 table_.Register(kVisitMap, |
| 699 &FixedBodyVisitor<StaticMarkingVisitor, | 705 &FixedBodyVisitor<StaticMarkingVisitor, |
| 700 Map::BodyDescriptor, | 706 Map::BodyDescriptor, |
| 701 void>::Visit); | 707 void>::Visit); |
| 702 | 708 |
| 703 table_.Register(kVisitCode, &VisitCode); | 709 table_.Register(kVisitCode, &VisitCode); |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 847 }; | 853 }; |
| 848 | 854 |
| 849 typedef FlexibleBodyVisitor<StaticMarkingVisitor, | 855 typedef FlexibleBodyVisitor<StaticMarkingVisitor, |
| 850 JSObject::BodyDescriptor, | 856 JSObject::BodyDescriptor, |
| 851 void> JSObjectVisitor; | 857 void> JSObjectVisitor; |
| 852 | 858 |
| 853 typedef FlexibleBodyVisitor<StaticMarkingVisitor, | 859 typedef FlexibleBodyVisitor<StaticMarkingVisitor, |
| 854 StructBodyDescriptor, | 860 StructBodyDescriptor, |
| 855 void> StructObjectVisitor; | 861 void> StructObjectVisitor; |
| 856 | 862 |
| 863 static void VisitJSWeakMap(Map* map, HeapObject* object) { |
| 864 MarkCompactCollector* collector = map->GetHeap()->mark_compact_collector(); |
| 865 JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(object); |
| 866 |
| 867 // Enqueue weak map in linked list of encountered weak maps. |
| 868 ASSERT(weak_map->next() == Smi::FromInt(0)); |
| 869 weak_map->set_next(collector->encountered_weak_maps()); |
| 870 collector->set_encountered_weak_maps(weak_map); |
| 871 |
| 872 // Skip visiting the backing hash table containing the mappings. |
| 873 int object_size = JSWeakMap::BodyDescriptor::SizeOf(map, object); |
| 874 BodyVisitorBase<StaticMarkingVisitor>::IteratePointers( |
| 875 map->GetHeap(), |
| 876 object, |
| 877 JSWeakMap::BodyDescriptor::kStartOffset, |
| 878 JSWeakMap::kTableOffset); |
| 879 BodyVisitorBase<StaticMarkingVisitor>::IteratePointers( |
| 880 map->GetHeap(), |
| 881 object, |
| 882 JSWeakMap::kTableOffset + kPointerSize, |
| 883 object_size); |
| 884 |
| 885 // Mark the backing hash table without pushing it on the marking stack. |
| 886 ASSERT(!MarkCompactCollector::IsMarked(weak_map->unchecked_table())); |
| 887 ASSERT(MarkCompactCollector::IsMarked(weak_map->unchecked_table()->map())); |
| 888 |
| 889 HeapObject* unchecked_table = weak_map->unchecked_table(); |
| 890 MarkBit mark_bit = Marking::MarkBitFrom(unchecked_table); |
| 891 collector->SetMark(unchecked_table, mark_bit); |
| 892 } |
| 893 |
| 857 static void VisitCode(Map* map, HeapObject* object) { | 894 static void VisitCode(Map* map, HeapObject* object) { |
| 858 reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>( | 895 reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>( |
| 859 map->GetHeap()); | 896 map->GetHeap()); |
| 860 } | 897 } |
| 861 | 898 |
| 862 // Code flushing support. | 899 // Code flushing support. |
| 863 | 900 |
| 864 // How many collections newly compiled code object will survive before being | 901 // How many collections newly compiled code object will survive before being |
| 865 // flushed. | 902 // flushed. |
| 866 static const int kCodeAgeThreshold = 5; | 903 static const int kCodeAgeThreshold = 5; |
| (...skipping 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1760 ref_groups->Rewind(last); | 1797 ref_groups->Rewind(last); |
| 1761 } | 1798 } |
| 1762 | 1799 |
| 1763 | 1800 |
| 1764 // Mark all objects reachable from the objects on the marking stack. | 1801 // Mark all objects reachable from the objects on the marking stack. |
| 1765 // Before: the marking stack contains zero or more heap object pointers. | 1802 // Before: the marking stack contains zero or more heap object pointers. |
| 1766 // After: the marking stack is empty, and all objects reachable from the | 1803 // After: the marking stack is empty, and all objects reachable from the |
| 1767 // marking stack have been marked, or are overflowed in the heap. | 1804 // marking stack have been marked, or are overflowed in the heap. |
| 1768 void MarkCompactCollector::EmptyMarkingDeque() { | 1805 void MarkCompactCollector::EmptyMarkingDeque() { |
| 1769 while (!marking_deque_.IsEmpty()) { | 1806 while (!marking_deque_.IsEmpty()) { |
| 1770 HeapObject* object = marking_deque_.Pop(); | 1807 while (!marking_deque_.IsEmpty()) { |
| 1771 ASSERT(object->IsHeapObject()); | 1808 HeapObject* object = marking_deque_.Pop(); |
| 1772 ASSERT(heap()->Contains(object)); | 1809 ASSERT(object->IsHeapObject()); |
| 1773 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(object))); | 1810 ASSERT(heap()->Contains(object)); |
| 1811 ASSERT(Marking::IsBlack(Marking::MarkBitFrom(object))); |
| 1774 | 1812 |
| 1775 Map* map = object->map(); | 1813 Map* map = object->map(); |
| 1776 MarkBit map_mark = Marking::MarkBitFrom(map); | 1814 MarkBit map_mark = Marking::MarkBitFrom(map); |
| 1777 MarkObject(map, map_mark); | 1815 MarkObject(map, map_mark); |
| 1778 | 1816 |
| 1779 StaticMarkingVisitor::IterateBody(map, object); | 1817 StaticMarkingVisitor::IterateBody(map, object); |
| 1818 } |
| 1819 |
| 1820 // Process encountered weak maps, mark objects only reachable by those |
| 1821 // weak maps and repeat until fix-point is reached. |
| 1822 ProcessWeakMaps(); |
| 1780 } | 1823 } |
| 1781 } | 1824 } |
| 1782 | 1825 |
| 1783 | 1826 |
| 1784 // Sweep the heap for overflowed objects, clear their overflow bits, and | 1827 // Sweep the heap for overflowed objects, clear their overflow bits, and |
| 1785 // push them on the marking stack. Stop early if the marking stack fills | 1828 // push them on the marking stack. Stop early if the marking stack fills |
| 1786 // before sweeping completes. If sweeping completes, there are no remaining | 1829 // before sweeping completes. If sweeping completes, there are no remaining |
| 1787 // overflowed objects in the heap so the overflow flag on the markings stack | 1830 // overflowed objects in the heap so the overflow flag on the markings stack |
| 1788 // is cleared. | 1831 // is cleared. |
| 1789 void MarkCompactCollector::RefillMarkingDeque() { | 1832 void MarkCompactCollector::RefillMarkingDeque() { |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2171 if (is_alive) { | 2214 if (is_alive) { |
| 2172 Object** slot = HeapObject::RawField(current, Map::kPrototypeOffset); | 2215 Object** slot = HeapObject::RawField(current, Map::kPrototypeOffset); |
| 2173 RecordSlot(slot, slot, real_prototype); | 2216 RecordSlot(slot, slot, real_prototype); |
| 2174 } | 2217 } |
| 2175 current = reinterpret_cast<Map*>(next); | 2218 current = reinterpret_cast<Map*>(next); |
| 2176 } | 2219 } |
| 2177 } | 2220 } |
| 2178 } | 2221 } |
| 2179 | 2222 |
| 2180 | 2223 |
| 2224 void MarkCompactCollector::ProcessWeakMaps() { |
| 2225 Object* weak_map_obj = encountered_weak_maps(); |
| 2226 while (weak_map_obj != Smi::FromInt(0)) { |
| 2227 ASSERT(MarkCompactCollector::IsMarked(HeapObject::cast(weak_map_obj))); |
| 2228 JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(weak_map_obj); |
| 2229 ObjectHashTable* table = weak_map->unchecked_table(); |
| 2230 for (int i = 0; i < table->Capacity(); i++) { |
| 2231 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { |
| 2232 Object* value = table->get(table->EntryToValueIndex(i)); |
| 2233 StaticMarkingVisitor::VisitPointer(heap(), &value); |
| 2234 table->set_unchecked(heap(), |
| 2235 table->EntryToValueIndex(i), |
| 2236 value, |
| 2237 UPDATE_WRITE_BARRIER); |
| 2238 } |
| 2239 } |
| 2240 weak_map_obj = weak_map->next(); |
| 2241 } |
| 2242 } |
| 2243 |
| 2244 |
| 2245 void MarkCompactCollector::ClearWeakMaps() { |
| 2246 Object* weak_map_obj = encountered_weak_maps(); |
| 2247 while (weak_map_obj != Smi::FromInt(0)) { |
| 2248 ASSERT(MarkCompactCollector::IsMarked(HeapObject::cast(weak_map_obj))); |
| 2249 JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(weak_map_obj); |
| 2250 ObjectHashTable* table = weak_map->unchecked_table(); |
| 2251 for (int i = 0; i < table->Capacity(); i++) { |
| 2252 if (!MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { |
| 2253 table->RemoveEntry(i, heap()); |
| 2254 } |
| 2255 } |
| 2256 weak_map_obj = weak_map->next(); |
| 2257 weak_map->set_next(Smi::FromInt(0)); |
| 2258 } |
| 2259 set_encountered_weak_maps(Smi::FromInt(0)); |
| 2260 } |
| 2261 |
| 2262 |
| 2181 // We scavange new space simultaneously with sweeping. This is done in two | 2263 // We scavange new space simultaneously with sweeping. This is done in two |
| 2182 // passes. | 2264 // passes. |
| 2183 // | 2265 // |
| 2184 // The first pass migrates all alive objects from one semispace to another or | 2266 // The first pass migrates all alive objects from one semispace to another or |
| 2185 // promotes them to old space. Forwarding address is written directly into | 2267 // promotes them to old space. Forwarding address is written directly into |
| 2186 // first word of object without any encoding. If object is dead we write | 2268 // first word of object without any encoding. If object is dead we write |
| 2187 // NULL as a forwarding address. | 2269 // NULL as a forwarding address. |
| 2188 // | 2270 // |
| 2189 // The second pass updates pointers to new space in all spaces. It is possible | 2271 // The second pass updates pointers to new space in all spaces. It is possible |
| 2190 // to encounter pointers to dead new space objects during traversal of pointers | 2272 // to encounter pointers to dead new space objects during traversal of pointers |
| (...skipping 1154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3345 while (buffer != NULL) { | 3427 while (buffer != NULL) { |
| 3346 SlotsBuffer* next_buffer = buffer->next(); | 3428 SlotsBuffer* next_buffer = buffer->next(); |
| 3347 DeallocateBuffer(buffer); | 3429 DeallocateBuffer(buffer); |
| 3348 buffer = next_buffer; | 3430 buffer = next_buffer; |
| 3349 } | 3431 } |
| 3350 *buffer_address = NULL; | 3432 *buffer_address = NULL; |
| 3351 } | 3433 } |
| 3352 | 3434 |
| 3353 | 3435 |
| 3354 } } // namespace v8::internal | 3436 } } // namespace v8::internal |
| OLD | NEW |