OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 #ifdef DEBUG | 148 #ifdef DEBUG |
149 ASSERT(state_ == SWEEP_SPACES || state_ == REBUILD_RSETS); | 149 ASSERT(state_ == SWEEP_SPACES || state_ == REBUILD_RSETS); |
150 state_ = IDLE; | 150 state_ = IDLE; |
151 #endif | 151 #endif |
152 // The stub cache is not traversed during GC; clear the cache to | 152 // The stub cache is not traversed during GC; clear the cache to |
153 // force lazy re-initialization of it. This must be done after the | 153 // force lazy re-initialization of it. This must be done after the |
154 // GC, because it relies on the new address of certain old space | 154 // GC, because it relies on the new address of certain old space |
155 // objects (empty string, illegal builtin). | 155 // objects (empty string, illegal builtin). |
156 StubCache::Clear(); | 156 StubCache::Clear(); |
157 | 157 |
| 158 ExternalStringTable::CleanUp(); |
| 159 |
158 // If we've just compacted old space there's no reason to check the | 160 // If we've just compacted old space there's no reason to check the |
159 // fragmentation limit. Just return. | 161 // fragmentation limit. Just return. |
160 if (HasCompacted()) return; | 162 if (HasCompacted()) return; |
161 | 163 |
162 // We compact the old generation on the next GC if it has gotten too | 164 // We compact the old generation on the next GC if it has gotten too |
163 // fragmented (ie, we could recover an expected amount of space by | 165 // fragmented (ie, we could recover an expected amount of space by |
164 // reclaiming the waste and free list blocks). | 166 // reclaiming the waste and free list blocks). |
165 static const int kFragmentationLimit = 15; // Percent. | 167 static const int kFragmentationLimit = 15; // Percent. |
166 static const int kFragmentationAllowed = 1 * MB; // Absolute. | 168 static const int kFragmentationAllowed = 1 * MB; // Absolute. |
167 int old_gen_recoverable = 0; | 169 int old_gen_recoverable = 0; |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 // overflowed objects in the heap. | 364 // overflowed objects in the heap. |
363 MarkCompactCollector::EmptyMarkingStack(&stack_visitor_); | 365 MarkCompactCollector::EmptyMarkingStack(&stack_visitor_); |
364 } | 366 } |
365 }; | 367 }; |
366 | 368 |
367 | 369 |
368 // Helper class for pruning the symbol table. | 370 // Helper class for pruning the symbol table. |
369 class SymbolTableCleaner : public ObjectVisitor { | 371 class SymbolTableCleaner : public ObjectVisitor { |
370 public: | 372 public: |
371 SymbolTableCleaner() : pointers_removed_(0) { } | 373 SymbolTableCleaner() : pointers_removed_(0) { } |
372 void VisitPointers(Object** start, Object** end) { | 374 |
| 375 virtual void VisitPointers(Object** start, Object** end) { |
373 // Visit all HeapObject pointers in [start, end). | 376 // Visit all HeapObject pointers in [start, end). |
374 for (Object** p = start; p < end; p++) { | 377 for (Object** p = start; p < end; p++) { |
375 if ((*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked()) { | 378 if ((*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked()) { |
376 // Check if the symbol being pruned is an external symbol. We need to | 379 // Check if the symbol being pruned is an external symbol. We need to |
377 // delete the associated external data as this symbol is going away. | 380 // delete the associated external data as this symbol is going away. |
378 | 381 |
379 // Since the object is not marked we can access its map word safely | |
380 // without having to worry about marking bits in the object header. | |
381 Map* map = HeapObject::cast(*p)->map(); | |
382 // Since no objects have yet been moved we can safely access the map of | 382 // Since no objects have yet been moved we can safely access the map of |
383 // the object. | 383 // the object. |
384 uint32_t type = map->instance_type(); | 384 if ((*p)->IsExternalString()) { |
385 bool is_external = (type & kStringRepresentationMask) == | 385 Heap::FinalizeExternalString(String::cast(*p)); |
386 kExternalStringTag; | |
387 if (is_external) { | |
388 bool is_two_byte = (type & kStringEncodingMask) == kTwoByteStringTag; | |
389 byte* resource_addr = reinterpret_cast<byte*>(*p) + | |
390 ExternalString::kResourceOffset - | |
391 kHeapObjectTag; | |
392 if (is_two_byte) { | |
393 v8::String::ExternalStringResource** resource = | |
394 reinterpret_cast<v8::String::ExternalStringResource**> | |
395 (resource_addr); | |
396 delete *resource; | |
397 // Clear the resource pointer in the symbol. | |
398 *resource = NULL; | |
399 } else { | |
400 v8::String::ExternalAsciiStringResource** resource = | |
401 reinterpret_cast<v8::String::ExternalAsciiStringResource**> | |
402 (resource_addr); | |
403 delete *resource; | |
404 // Clear the resource pointer in the symbol. | |
405 *resource = NULL; | |
406 } | |
407 } | 386 } |
408 // Set the entry to null_value (as deleted). | 387 // Set the entry to null_value (as deleted). |
409 *p = Heap::raw_unchecked_null_value(); | 388 *p = Heap::raw_unchecked_null_value(); |
410 pointers_removed_++; | 389 pointers_removed_++; |
411 } | 390 } |
412 } | 391 } |
413 } | 392 } |
414 | 393 |
415 int PointersRemoved() { | 394 int PointersRemoved() { |
416 return pointers_removed_; | 395 return pointers_removed_; |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 } | 518 } |
540 } | 519 } |
541 } | 520 } |
542 | 521 |
543 | 522 |
544 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { | 523 bool MarkCompactCollector::IsUnmarkedHeapObject(Object** p) { |
545 return (*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked(); | 524 return (*p)->IsHeapObject() && !HeapObject::cast(*p)->IsMarked(); |
546 } | 525 } |
547 | 526 |
548 | 527 |
549 class SymbolMarkingVisitor : public ObjectVisitor { | |
550 public: | |
551 void VisitPointers(Object** start, Object** end) { | |
552 MarkingVisitor marker; | |
553 for (Object** p = start; p < end; p++) { | |
554 if (!(*p)->IsHeapObject()) continue; | |
555 | |
556 HeapObject* object = HeapObject::cast(*p); | |
557 // If the object is marked, we have marked or are in the process | |
558 // of marking subparts. | |
559 if (object->IsMarked()) continue; | |
560 | |
561 // The object is unmarked, we do not need to unmark to use its | |
562 // map. | |
563 Map* map = object->map(); | |
564 object->IterateBody(map->instance_type(), | |
565 object->SizeFromMap(map), | |
566 &marker); | |
567 } | |
568 } | |
569 }; | |
570 | |
571 | |
572 void MarkCompactCollector::MarkSymbolTable() { | 528 void MarkCompactCollector::MarkSymbolTable() { |
573 // Objects reachable from symbols are marked as live so as to ensure | |
574 // that if the symbol itself remains alive after GC for any reason, | |
575 // and if it is a cons string backed by an external string (even indirectly), | |
576 // then the external string does not receive a weak reference callback. | |
577 SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table(); | 529 SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table(); |
578 // Mark the symbol table itself. | 530 // Mark the symbol table itself. |
579 SetMark(symbol_table); | 531 SetMark(symbol_table); |
580 // Explicitly mark the prefix. | 532 // Explicitly mark the prefix. |
581 MarkingVisitor marker; | 533 MarkingVisitor marker; |
582 symbol_table->IteratePrefix(&marker); | 534 symbol_table->IteratePrefix(&marker); |
583 ProcessMarkingStack(&marker); | 535 ProcessMarkingStack(&marker); |
584 // Mark subparts of the symbols but not the symbols themselves | |
585 // (unless reachable from another symbol). | |
586 SymbolMarkingVisitor symbol_marker; | |
587 symbol_table->IterateElements(&symbol_marker); | |
588 ProcessMarkingStack(&marker); | |
589 } | 536 } |
590 | 537 |
591 | 538 |
592 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { | 539 void MarkCompactCollector::MarkRoots(RootMarkingVisitor* visitor) { |
593 // Mark the heap roots including global variables, stack variables, | 540 // Mark the heap roots including global variables, stack variables, |
594 // etc., and all objects reachable from them. | 541 // etc., and all objects reachable from them. |
595 Heap::IterateStrongRoots(visitor, VISIT_ONLY_STRONG); | 542 Heap::IterateStrongRoots(visitor, VISIT_ONLY_STRONG); |
596 | 543 |
597 // Handle the symbol table specially. | 544 // Handle the symbol table specially. |
598 MarkSymbolTable(); | 545 MarkSymbolTable(); |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
767 // weak roots. | 714 // weak roots. |
768 ProcessObjectGroups(root_visitor.stack_visitor()); | 715 ProcessObjectGroups(root_visitor.stack_visitor()); |
769 | 716 |
770 // Prune the symbol table removing all symbols only pointed to by the | 717 // Prune the symbol table removing all symbols only pointed to by the |
771 // symbol table. Cannot use symbol_table() here because the symbol | 718 // symbol table. Cannot use symbol_table() here because the symbol |
772 // table is marked. | 719 // table is marked. |
773 SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table(); | 720 SymbolTable* symbol_table = Heap::raw_unchecked_symbol_table(); |
774 SymbolTableCleaner v; | 721 SymbolTableCleaner v; |
775 symbol_table->IterateElements(&v); | 722 symbol_table->IterateElements(&v); |
776 symbol_table->ElementsRemoved(v.PointersRemoved()); | 723 symbol_table->ElementsRemoved(v.PointersRemoved()); |
| 724 ExternalStringTable::Iterate(&v); |
| 725 ExternalStringTable::CleanUp(); |
777 | 726 |
778 // Remove object groups after marking phase. | 727 // Remove object groups after marking phase. |
779 GlobalHandles::RemoveObjectGroups(); | 728 GlobalHandles::RemoveObjectGroups(); |
780 } | 729 } |
781 | 730 |
782 | 731 |
783 static int CountMarkedCallback(HeapObject* obj) { | 732 static int CountMarkedCallback(HeapObject* obj) { |
784 MapWord map_word = obj->map_word(); | 733 MapWord map_word = obj->map_word(); |
785 map_word.ClearMark(); | 734 map_word.ClearMark(); |
786 return obj->SizeFromMap(map_word.ToMap()); | 735 return obj->SizeFromMap(map_word.ToMap()); |
(...skipping 1021 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1808 | 1757 |
1809 void MarkCompactCollector::RebuildRSets() { | 1758 void MarkCompactCollector::RebuildRSets() { |
1810 #ifdef DEBUG | 1759 #ifdef DEBUG |
1811 ASSERT(state_ == RELOCATE_OBJECTS); | 1760 ASSERT(state_ == RELOCATE_OBJECTS); |
1812 state_ = REBUILD_RSETS; | 1761 state_ = REBUILD_RSETS; |
1813 #endif | 1762 #endif |
1814 Heap::RebuildRSets(); | 1763 Heap::RebuildRSets(); |
1815 } | 1764 } |
1816 | 1765 |
1817 } } // namespace v8::internal | 1766 } } // namespace v8::internal |
OLD | NEW |