Chromium Code Reviews| Index: src/heap.cc |
| diff --git a/src/heap.cc b/src/heap.cc |
| index 4e4cd1c051e570621916663aa5a88cc342b41682..17cb8a1cb177ace7355c84388bfc58ac8d592bd2 100644 |
| --- a/src/heap.cc |
| +++ b/src/heap.cc |
| @@ -733,7 +733,7 @@ void Heap::Scavenge() { |
| ScavengeVisitor scavenge_visitor; |
| // Copy roots. |
| - IterateRoots(&scavenge_visitor, VISIT_ALL); |
| + IterateRoots(&scavenge_visitor, VISIT_ALL_IN_SCAVENGE); |
| // Copy objects reachable from the old generation. By definition, |
| // there are no intergenerational pointers in code or data spaces. |
| @@ -753,6 +753,63 @@ void Heap::Scavenge() { |
| } |
| } |
| + new_space_front = DoScavenge(&scavenge_visitor, new_space_front); |
| + |
| + ScavengeExternalStringTable(); |
| + ASSERT(new_space_front == new_space_.top()); |
| + |
| + // Set age mark. |
| + new_space_.set_age_mark(new_space_.top()); |
| + |
| + // Update how much has survived scavenge. |
| + survived_since_last_expansion_ += |
| + (PromotedSpaceSize() - survived_watermark) + new_space_.Size(); |
| + |
| + LOG(ResourceEvent("scavenge", "end")); |
| + |
| + gc_state_ = NOT_IN_GC; |
| +} |
| + |
| + |
| +void Heap::ScavengeExternalStringTable() { |
| + ExternalStringTable::Verify(); |
| + |
| + if (ExternalStringTable::new_space_strings_.is_empty()) return; |
| + |
| + Object** start = &ExternalStringTable::new_space_strings_[0]; |
| + Object** end = start + ExternalStringTable::new_space_strings_.length(); |
| + Object** last = start; |
| + |
| + for (Object** p = start; p < end; ++p) { |
| + ASSERT(Heap::InFromSpace(*p)); |
| + MapWord first_word = HeapObject::cast(*p)->map_word(); |
| + |
| + if (!first_word.IsForwardingAddress()) { |
| + // Unreachable external string can be finalized. |
| + FinalizeExternalString(String::cast(*p)); |
| + continue; |
| + } |
| + |
| + // String is still reachable. |
| + String* target = String::cast(first_word.ToForwardingAddress()); |
| + ASSERT(target->IsExternalString()); |
| + |
| + if (Heap::InNewSpace(target)) { |
| + // String is still in new space. Update the table entry. |
| + *last = target; |
| + ++last; |
| + } else { |
| + // String got promoted. Move it to the old string list. |
| + ExternalStringTable::AddOldString(target); |
| + } |
| + } |
| + |
| + ExternalStringTable::ShrinkNewStrings(last - start); |
| +} |
| + |
| + |
| +Address Heap::DoScavenge(ObjectVisitor* scavenge_visitor, |
| + Address new_space_front) { |
| do { |
| ASSERT(new_space_front <= new_space_.top()); |
| @@ -761,7 +818,7 @@ void Heap::Scavenge() { |
| // queue is empty. |
| while (new_space_front < new_space_.top()) { |
| HeapObject* object = HeapObject::FromAddress(new_space_front); |
| - object->Iterate(&scavenge_visitor); |
| + object->Iterate(scavenge_visitor); |
| new_space_front += object->Size(); |
| } |
| @@ -783,7 +840,7 @@ void Heap::Scavenge() { |
| RecordCopiedObject(target); |
| #endif |
| // Visit the newly copied object for pointers to new space. |
| - target->Iterate(&scavenge_visitor); |
| + target->Iterate(scavenge_visitor); |
| UpdateRSet(target); |
| } |
| @@ -791,16 +848,7 @@ void Heap::Scavenge() { |
| // (there are currently no more unswept promoted objects). |
| } while (new_space_front < new_space_.top()); |
| - // Set age mark. |
| - new_space_.set_age_mark(new_space_.top()); |
| - |
| - // Update how much has survived scavenge. |
| - survived_since_last_expansion_ += |
| - (PromotedSpaceSize() - survived_watermark) + new_space_.Size(); |
| - |
| - LOG(ResourceEvent("scavenge", "end")); |
| - |
| - gc_state_ = NOT_IN_GC; |
| + return new_space_front; |
| } |
| @@ -3175,6 +3223,11 @@ void Heap::IterateRoots(ObjectVisitor* v, VisitMode mode) { |
| IterateStrongRoots(v, mode); |
| v->VisitPointer(reinterpret_cast<Object**>(&roots_[kSymbolTableRootIndex])); |
| v->Synchronize("symbol_table"); |
| + if (mode != VISIT_ALL_IN_SCAVENGE) { |
| + // Scavenge collections have special processing for this. |
| + ExternalStringTable::Iterate(v); |
| + } |
| + v->Synchronize("external_string_table"); |
| } |
| @@ -3203,11 +3256,12 @@ void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { |
| HandleScopeImplementer::Iterate(v); |
| v->Synchronize("handlescope"); |
| - // Iterate over the builtin code objects and code stubs in the heap. Note |
| - // that it is not strictly necessary to iterate over code objects on |
| - // scavenge collections. We still do it here because this same function |
| - // is used by the mark-sweep collector and the deserializer. |
| - Builtins::IterateBuiltins(v); |
| + // Iterate over the builtin code objects and code stubs in the |
| + // heap. Note that it is not necessary to iterate over code objects |
| + // on scavenge collections. |
| + if (mode != VISIT_ALL_IN_SCAVENGE) { |
| + Builtins::IterateBuiltins(v); |
| + } |
| v->Synchronize("builtins"); |
| // Iterate over global handles. |
| @@ -3424,6 +3478,8 @@ void Heap::SetStackLimits() { |
| void Heap::TearDown() { |
| GlobalHandles::TearDown(); |
| + ExternalStringTable::TearDown(); |
| + |
| new_space_.TearDown(); |
| if (old_pointer_space_ != NULL) { |
| @@ -3839,8 +3895,8 @@ class MarkRootVisitor: public ObjectVisitor { |
| // Triggers a depth-first traversal of reachable objects from roots |
| // and finds a path to a specific heap object and prints it. |
| -void Heap::TracePathToObject() { |
| - search_target = NULL; |
| +void Heap::TracePathToObject(Object* target) { |
| + search_target = target; |
| search_for_any_global = false; |
| MarkRootVisitor root_visitor; |
| @@ -3991,4 +4047,37 @@ void TranscendentalCache::Clear() { |
| } |
| +void ExternalStringTable::CleanUp() { |
| + CleanUpList(true); |
| + CleanUpList(false); |
| + Verify(); |
| +} |
| + |
| + |
| +void ExternalStringTable::CleanUpList(bool new_to_old) { |
| + List<Object*>& source = new_to_old ? new_space_strings_ : old_space_strings_; |
| + if (source.is_empty()) return; |
| + List<Object*>& target = new_to_old ? old_space_strings_ : new_space_strings_; |
|
Mads Ager (chromium)
2009/12/08 16:18:40
Use old_space_strings_ as the target always? It s
Vitaly Repeshko
2009/12/09 14:33:23
Makes sense. Done.
|
| + int last = 0; |
| + for (int i = 0; i < source.length(); ++i) { |
| + if (source[i] == Heap::raw_unchecked_null_value()) continue; |
| + if (Heap::InNewSpace(source[i]) == new_to_old) { |
| + source[last++] = source[i]; |
| + } else { |
| + target.Add(source[i]); |
| + } |
| + } |
| + source.Rewind(last); |
| +} |
| + |
| + |
| +void ExternalStringTable::TearDown() { |
| + new_space_strings_.Free(); |
| + old_space_strings_.Free(); |
| +} |
| + |
| + |
| +List<Object*> ExternalStringTable::new_space_strings_; |
| +List<Object*> ExternalStringTable::old_space_strings_; |
| + |
| } } // namespace v8::internal |