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 |