| 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 |