Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 MarkBit mark_bit = Marking::MarkBitFrom(HeapObject::cast(obj)); | 181 MarkBit mark_bit = Marking::MarkBitFrom(HeapObject::cast(obj)); |
| 182 if (Marking::IsBlack(mark_bit)) { | 182 if (Marking::IsBlack(mark_bit)) { |
| 183 MemoryChunk::IncrementLiveBytesFromGC(heap_obj->address(), | 183 MemoryChunk::IncrementLiveBytesFromGC(heap_obj->address(), |
| 184 -heap_obj->Size()); | 184 -heap_obj->Size()); |
| 185 } | 185 } |
| 186 Marking::AnyToGrey(mark_bit); | 186 Marking::AnyToGrey(mark_bit); |
| 187 } | 187 } |
| 188 } | 188 } |
| 189 | 189 |
| 190 | 190 |
| 191 static inline void MarkBlackOrKeepGrey(HeapObject* heap_object, | |
| 192 MarkBit mark_bit, | |
| 193 int size) { | |
| 194 ASSERT(!Marking::IsImpossible(mark_bit)); | |
| 195 if (mark_bit.Get()) return; | |
| 196 mark_bit.Set(); | |
| 197 MemoryChunk::IncrementLiveBytesFromGC(heap_object->address(), size); | |
| 198 ASSERT(Marking::IsBlack(mark_bit)); | |
| 199 } | |
| 200 | |
| 201 | |
| 202 static inline void MarkBlackOrKeepBlack(HeapObject* heap_object, | |
| 203 MarkBit mark_bit, | |
| 204 int size) { | |
| 205 ASSERT(!Marking::IsImpossible(mark_bit)); | |
| 206 if (Marking::IsBlack(mark_bit)) return; | |
| 207 Marking::MarkBlack(mark_bit); | |
| 208 MemoryChunk::IncrementLiveBytesFromGC(heap_object->address(), size); | |
| 209 ASSERT(Marking::IsBlack(mark_bit)); | |
| 210 } | |
| 211 | |
| 212 | |
| 191 class IncrementalMarkingMarkingVisitor | 213 class IncrementalMarkingMarkingVisitor |
| 192 : public StaticMarkingVisitor<IncrementalMarkingMarkingVisitor> { | 214 : public StaticMarkingVisitor<IncrementalMarkingMarkingVisitor> { |
| 193 public: | 215 public: |
| 194 static void Initialize() { | 216 static void Initialize() { |
| 195 StaticMarkingVisitor<IncrementalMarkingMarkingVisitor>::Initialize(); | 217 StaticMarkingVisitor<IncrementalMarkingMarkingVisitor>::Initialize(); |
| 196 | 218 table_.Register(kVisitFixedArray, &VisitFixedArrayIncremental); |
| 197 table_.Register(kVisitNativeContext, &VisitNativeContextIncremental); | 219 table_.Register(kVisitNativeContext, &VisitNativeContextIncremental); |
| 198 table_.Register(kVisitJSRegExp, &VisitJSRegExp); | 220 table_.Register(kVisitJSRegExp, &VisitJSRegExp); |
| 199 } | 221 } |
| 200 | 222 |
| 223 static const int kProgressBarScanningChunk = 32 * 1024; | |
| 224 | |
| 225 static void VisitFixedArrayIncremental(Map* map, HeapObject* object) { | |
| 226 MemoryChunk* chunk = MemoryChunk::FromAddress(object->address()); | |
| 227 if (FLAG_use_progress_bar && chunk->owner()->identity() == LO_SPACE) { | |
| 228 Heap* heap = map->GetHeap(); | |
|
Hannes Payer (out of office)
2012/11/14 12:21:04
can you set that flag earlier e.g. at allocation t
Michael Starzinger
2012/11/15 15:12:50
Yes, that would be cleaner. I just couldn't find a
Michael Starzinger
2012/11/15 17:54:51
Left a TODO in the code about that. Currently ther
| |
| 229 chunk->SetFlag(MemoryChunk::HAS_PROGRESS_BAR); | |
| 230 // When using a progress bar for large fixed arrays, scan only a chunk of | |
| 231 // the array and try to push it onto the marking deque again until it is | |
| 232 // fully scanned. Fall back to scanning it through to the end in case this | |
| 233 // fails because of a full deque. | |
| 234 bool scan_until_end = false; | |
| 235 int object_size = FixedArray::BodyDescriptor::SizeOf(map, object); | |
| 236 do { | |
| 237 int start_offset = Max(FixedArray::BodyDescriptor::kStartOffset, | |
|
ulan
2012/11/15 09:54:23
Not sure if worthwhile as the loop rarely executes
Michael Starzinger
2012/11/15 15:12:50
Done.
| |
| 238 chunk->progress_bar()); | |
| 239 int end_offset = Min(object_size, | |
| 240 chunk->progress_bar() + kProgressBarScanningChunk); | |
|
ulan
2012/11/15 09:54:23
Shouldn't this be start_offset + kProgressBarScann
Michael Starzinger
2012/11/15 15:12:50
Done.
| |
| 241 chunk->set_progress_bar(end_offset); | |
| 242 VisitPointersWithAnchor(heap, | |
| 243 HeapObject::RawField(object, 0), | |
| 244 HeapObject::RawField(object, start_offset), | |
| 245 HeapObject::RawField(object, end_offset)); | |
| 246 scan_until_end = heap->incremental_marking()->marking_deque()->IsFull(); | |
| 247 if (end_offset < object_size) { | |
|
Hannes Payer (out of office)
2012/11/14 12:21:04
why is this method called UnshiftGrey and not Unsh
ulan
2012/11/15 09:54:23
(end_offset < object_size && !scan_until_end) woul
Michael Starzinger
2012/11/15 15:12:50
Done.
Michael Starzinger
2012/11/15 15:12:50
The method is called UnshiftGrey because at the ti
Hannes Payer (out of office)
2012/11/15 16:25:54
There is probably no performance difference, I jus
| |
| 248 heap->incremental_marking()->marking_deque()->UnshiftGrey(object); | |
| 249 } | |
| 250 } while (scan_until_end && chunk->progress_bar() < object_size); | |
| 251 } else { | |
| 252 FixedArrayVisitor::Visit(map, object); | |
| 253 } | |
| 254 } | |
| 255 | |
| 201 static void VisitNativeContextIncremental(Map* map, HeapObject* object) { | 256 static void VisitNativeContextIncremental(Map* map, HeapObject* object) { |
| 202 Context* context = Context::cast(object); | 257 Context* context = Context::cast(object); |
| 203 | 258 |
| 204 // We will mark cache black with a separate pass | 259 // We will mark cache black with a separate pass |
| 205 // when we finish marking. | 260 // when we finish marking. |
| 206 MarkObjectGreyDoNotEnqueue(context->normalized_map_cache()); | 261 MarkObjectGreyDoNotEnqueue(context->normalized_map_cache()); |
| 207 VisitNativeContext(map, context); | 262 VisitNativeContext(map, context); |
| 208 } | 263 } |
| 209 | 264 |
| 210 static void VisitJSWeakMap(Map* map, HeapObject* object) { | 265 static void VisitJSWeakMap(Map* map, HeapObject* object) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 227 INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) { | 282 INLINE(static void VisitPointers(Heap* heap, Object** start, Object** end)) { |
| 228 for (Object** p = start; p < end; p++) { | 283 for (Object** p = start; p < end; p++) { |
| 229 Object* obj = *p; | 284 Object* obj = *p; |
| 230 if (obj->NonFailureIsHeapObject()) { | 285 if (obj->NonFailureIsHeapObject()) { |
| 231 heap->mark_compact_collector()->RecordSlot(start, p, obj); | 286 heap->mark_compact_collector()->RecordSlot(start, p, obj); |
| 232 MarkObject(heap, obj); | 287 MarkObject(heap, obj); |
| 233 } | 288 } |
| 234 } | 289 } |
| 235 } | 290 } |
| 236 | 291 |
| 292 INLINE(static void VisitPointersWithAnchor(Heap* heap, | |
| 293 Object** anchor, | |
| 294 Object** start, | |
| 295 Object** end)) { | |
| 296 for (Object** p = start; p < end; p++) { | |
| 297 Object* obj = *p; | |
| 298 if (obj->NonFailureIsHeapObject()) { | |
| 299 heap->mark_compact_collector()->RecordSlot(anchor, p, obj); | |
| 300 MarkObject(heap, obj); | |
| 301 } | |
| 302 } | |
| 303 } | |
| 304 | |
| 237 // Marks the object grey and pushes it on the marking stack. | 305 // Marks the object grey and pushes it on the marking stack. |
|
Hannes Payer (out of office)
2012/11/14 12:21:04
update comment
Michael Starzinger
2012/11/15 15:12:50
I think the comment still applies. I didn't change
| |
| 238 INLINE(static void MarkObject(Heap* heap, Object* obj)) { | 306 INLINE(static void MarkObject(Heap* heap, Object* obj)) { |
| 239 HeapObject* heap_object = HeapObject::cast(obj); | 307 HeapObject* heap_object = HeapObject::cast(obj); |
| 240 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); | 308 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); |
| 241 if (mark_bit.data_only()) { | 309 if (mark_bit.data_only()) { |
| 242 if (heap->incremental_marking()->MarkBlackOrKeepGrey(mark_bit)) { | 310 MarkBlackOrKeepGrey(heap_object, mark_bit, heap_object->Size()); |
| 243 MemoryChunk::IncrementLiveBytesFromGC(heap_object->address(), | |
| 244 heap_object->Size()); | |
| 245 } | |
| 246 } else if (Marking::IsWhite(mark_bit)) { | 311 } else if (Marking::IsWhite(mark_bit)) { |
| 247 heap->incremental_marking()->WhiteToGreyAndPush(heap_object, mark_bit); | 312 heap->incremental_marking()->WhiteToGreyAndPush(heap_object, mark_bit); |
| 248 } | 313 } |
| 249 } | 314 } |
| 250 | 315 |
| 251 // Marks the object black without pushing it on the marking stack. | 316 // Marks the object black without pushing it on the marking stack. |
| 252 // Returns true if object needed marking and false otherwise. | 317 // Returns true if object needed marking and false otherwise. |
| 253 INLINE(static bool MarkObjectWithoutPush(Heap* heap, Object* obj)) { | 318 INLINE(static bool MarkObjectWithoutPush(Heap* heap, Object* obj)) { |
| 254 HeapObject* heap_object = HeapObject::cast(obj); | 319 HeapObject* heap_object = HeapObject::cast(obj); |
| 255 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); | 320 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 281 } | 346 } |
| 282 | 347 |
| 283 private: | 348 private: |
| 284 void MarkObjectByPointer(Object** p) { | 349 void MarkObjectByPointer(Object** p) { |
| 285 Object* obj = *p; | 350 Object* obj = *p; |
| 286 if (!obj->IsHeapObject()) return; | 351 if (!obj->IsHeapObject()) return; |
| 287 | 352 |
| 288 HeapObject* heap_object = HeapObject::cast(obj); | 353 HeapObject* heap_object = HeapObject::cast(obj); |
| 289 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); | 354 MarkBit mark_bit = Marking::MarkBitFrom(heap_object); |
| 290 if (mark_bit.data_only()) { | 355 if (mark_bit.data_only()) { |
| 291 if (incremental_marking_->MarkBlackOrKeepGrey(mark_bit)) { | 356 MarkBlackOrKeepGrey(heap_object, mark_bit, heap_object->Size()); |
| 292 MemoryChunk::IncrementLiveBytesFromGC(heap_object->address(), | |
| 293 heap_object->Size()); | |
| 294 } | |
| 295 } else { | 357 } else { |
| 296 if (Marking::IsWhite(mark_bit)) { | 358 if (Marking::IsWhite(mark_bit)) { |
| 297 incremental_marking_->WhiteToGreyAndPush(heap_object, mark_bit); | 359 incremental_marking_->WhiteToGreyAndPush(heap_object, mark_bit); |
| 298 } | 360 } |
| 299 } | 361 } |
| 300 } | 362 } |
| 301 | 363 |
| 302 Heap* heap_; | 364 Heap* heap_; |
| 303 IncrementalMarking* incremental_marking_; | 365 IncrementalMarking* incremental_marking_; |
| 304 }; | 366 }; |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 609 #endif | 671 #endif |
| 610 } | 672 } |
| 611 } else if (obj->map() != filler_map) { | 673 } else if (obj->map() != filler_map) { |
| 612 // Skip one word filler objects that appear on the | 674 // Skip one word filler objects that appear on the |
| 613 // stack when we perform in place array shift. | 675 // stack when we perform in place array shift. |
| 614 array[new_top] = obj; | 676 array[new_top] = obj; |
| 615 new_top = ((new_top + 1) & mask); | 677 new_top = ((new_top + 1) & mask); |
| 616 ASSERT(new_top != marking_deque_.bottom()); | 678 ASSERT(new_top != marking_deque_.bottom()); |
| 617 #ifdef DEBUG | 679 #ifdef DEBUG |
| 618 MarkBit mark_bit = Marking::MarkBitFrom(obj); | 680 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
| 681 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); | |
| 619 ASSERT(Marking::IsGrey(mark_bit) || | 682 ASSERT(Marking::IsGrey(mark_bit) || |
| 620 (obj->IsFiller() && Marking::IsWhite(mark_bit))); | 683 (obj->IsFiller() && Marking::IsWhite(mark_bit)) || |
| 684 (chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR) && | |
| 685 Marking::IsBlack(mark_bit))); | |
| 621 #endif | 686 #endif |
| 622 } | 687 } |
| 623 } | 688 } |
| 624 marking_deque_.set_top(new_top); | 689 marking_deque_.set_top(new_top); |
| 625 | 690 |
| 626 steps_took_since_last_gc_ = 0; | 691 steps_took_since_last_gc_ = 0; |
| 627 steps_count_since_last_gc_ = 0; | 692 steps_count_since_last_gc_ = 0; |
| 628 longest_step_ = 0.0; | 693 longest_step_ = 0.0; |
| 629 } | 694 } |
| 630 | 695 |
| 631 | 696 |
| 632 void IncrementalMarking::VisitObject(Map* map, HeapObject* obj, int size) { | 697 void IncrementalMarking::VisitObject(Map* map, HeapObject* obj, int size) { |
| 633 MarkBit map_mark_bit = Marking::MarkBitFrom(map); | 698 MarkBit map_mark_bit = Marking::MarkBitFrom(map); |
| 634 if (Marking::IsWhite(map_mark_bit)) { | 699 if (Marking::IsWhite(map_mark_bit)) { |
| 635 WhiteToGreyAndPush(map, map_mark_bit); | 700 WhiteToGreyAndPush(map, map_mark_bit); |
| 636 } | 701 } |
| 637 | 702 |
| 638 IncrementalMarkingMarkingVisitor::IterateBody(map, obj); | 703 IncrementalMarkingMarkingVisitor::IterateBody(map, obj); |
| 639 | 704 |
| 640 MarkBit obj_mark_bit = Marking::MarkBitFrom(obj); | 705 MarkBit mark_bit = Marking::MarkBitFrom(obj); |
| 641 SLOW_ASSERT(Marking::IsGrey(obj_mark_bit) || | 706 #ifdef DEBUG |
| 642 (obj->IsFiller() && Marking::IsWhite(obj_mark_bit))); | 707 MemoryChunk* chunk = MemoryChunk::FromAddress(obj->address()); |
| 643 Marking::MarkBlack(obj_mark_bit); | 708 SLOW_ASSERT(Marking::IsGrey(mark_bit) || |
| 644 MemoryChunk::IncrementLiveBytesFromGC(obj->address(), size); | 709 (obj->IsFiller() && Marking::IsWhite(mark_bit)) || |
| 710 (chunk->IsFlagSet(MemoryChunk::HAS_PROGRESS_BAR) && | |
| 711 Marking::IsBlack(mark_bit))); | |
| 712 #endif | |
| 713 MarkBlackOrKeepBlack(obj, mark_bit, size); | |
| 645 } | 714 } |
| 646 | 715 |
| 647 | 716 |
| 648 void IncrementalMarking::ProcessMarkingDeque(intptr_t bytes_to_process) { | 717 void IncrementalMarking::ProcessMarkingDeque(intptr_t bytes_to_process) { |
| 649 Map* filler_map = heap_->one_pointer_filler_map(); | 718 Map* filler_map = heap_->one_pointer_filler_map(); |
| 650 while (!marking_deque_.IsEmpty() && bytes_to_process > 0) { | 719 while (!marking_deque_.IsEmpty() && bytes_to_process > 0) { |
| 651 HeapObject* obj = marking_deque_.Pop(); | 720 HeapObject* obj = marking_deque_.Pop(); |
| 652 | 721 |
| 653 // Explicitly skip one word fillers. Incremental markbit patterns are | 722 // Explicitly skip one word fillers. Incremental markbit patterns are |
| 654 // correct only for objects that occupy at least two words. | 723 // correct only for objects that occupy at least two words. |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 920 bytes_scanned_ = 0; | 989 bytes_scanned_ = 0; |
| 921 write_barriers_invoked_since_last_step_ = 0; | 990 write_barriers_invoked_since_last_step_ = 0; |
| 922 } | 991 } |
| 923 | 992 |
| 924 | 993 |
| 925 int64_t IncrementalMarking::SpaceLeftInOldSpace() { | 994 int64_t IncrementalMarking::SpaceLeftInOldSpace() { |
| 926 return heap_->MaxOldGenerationSize() - heap_->PromotedSpaceSizeOfObjects(); | 995 return heap_->MaxOldGenerationSize() - heap_->PromotedSpaceSizeOfObjects(); |
| 927 } | 996 } |
| 928 | 997 |
| 929 } } // namespace v8::internal | 998 } } // namespace v8::internal |
| OLD | NEW |