Chromium Code Reviews| Index: src/heap.cc |
| diff --git a/src/heap.cc b/src/heap.cc |
| index 679ef9d8e1901914daeb642b5b1091d63fa3c8cf..9f09acbd97a1faffad5adde2e64083b9e8d24670 100644 |
| --- a/src/heap.cc |
| +++ b/src/heap.cc |
| @@ -107,7 +107,6 @@ Heap::Heap() |
| cell_space_(NULL), |
| lo_space_(NULL), |
| gc_state_(NOT_IN_GC), |
| - mc_count_(0), |
| ms_count_(0), |
| gc_count_(0), |
| unflattened_strings_length_(0), |
| @@ -774,9 +773,7 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector, |
| amount_of_external_allocated_memory_; |
| } |
| - GCCallbackFlags callback_flags = tracer->is_compacting() |
| - ? kGCCallbackFlagCompacted |
| - : kNoGCCallbackFlags; |
| + GCCallbackFlags callback_flags = kNoGCCallbackFlags; |
| for (int i = 0; i < gc_epilogue_callbacks_.length(); ++i) { |
| if (gc_type & gc_epilogue_callbacks_[i].gc_type) { |
| gc_epilogue_callbacks_[i].callback(gc_type, callback_flags); |
| @@ -800,16 +797,10 @@ void Heap::MarkCompact(GCTracer* tracer) { |
| mark_compact_collector_.Prepare(tracer); |
| - bool is_compacting = mark_compact_collector_.IsCompacting(); |
| + ms_count_++; |
| + tracer->set_full_gc_count(ms_count_); |
| - if (is_compacting) { |
| - mc_count_++; |
| - } else { |
| - ms_count_++; |
| - } |
| - tracer->set_full_gc_count(mc_count_ + ms_count_); |
| - |
| - MarkCompactPrologue(is_compacting); |
| + MarkCompactPrologue(); |
| mark_compact_collector_.CollectGarbage(); |
| @@ -825,7 +816,7 @@ void Heap::MarkCompact(GCTracer* tracer) { |
| } |
| -void Heap::MarkCompactPrologue(bool is_compacting) { |
| +void Heap::MarkCompactPrologue() { |
| // At any old GC clear the keyed lookup cache to enable collection of unused |
| // maps. |
| isolate_->keyed_lookup_cache()->Clear(); |
| @@ -836,7 +827,8 @@ void Heap::MarkCompactPrologue(bool is_compacting) { |
| CompletelyClearInstanceofCache(); |
| - if (is_compacting) FlushNumberStringCache(); |
| + // TODO(gc) select heuristic for flushing NumberString cache with |
| + // FlushNumberStringCache |
| ClearNormalizedMapCaches(); |
| } |
| @@ -1051,7 +1043,8 @@ void Heap::Scavenge() { |
| StoreBufferRebuildScope scope(this, |
| store_buffer(), |
| &ScavengeStoreBufferCallback); |
| - store_buffer()->IteratePointersToNewSpace(&ScavengeObject); |
| + store_buffer()->IteratePointersToNewSpace(&ScavengeObject, |
| + StoreBuffer::VISIT_ALL_SLOTS); |
| } |
| // Copy objects reachable from cells by scavenging cell values directly. |
| @@ -1149,64 +1142,91 @@ void Heap::UpdateNewSpaceReferencesInExternalStringTable( |
| } |
| +void Heap::UpdateReferencesInExternalStringTable( |
| + ExternalStringTableUpdaterCallback updater_func) { |
| + |
| + // Update old space string references. |
| + if (external_string_table_.old_space_strings_.length() > 0) { |
| + Object** start = &external_string_table_.old_space_strings_[0]; |
| + Object** end = start + external_string_table_.old_space_strings_.length(); |
| + for (Object** p = start; p < end; ++p) *p = updater_func(this, p); |
| + } |
| + |
| + UpdateNewSpaceReferencesInExternalStringTable(updater_func); |
| +} |
| + |
| + |
| static Object* ProcessFunctionWeakReferences(Heap* heap, |
| Object* function, |
| WeakObjectRetainer* retainer) { |
| - Object* head = heap->undefined_value(); |
| + Object* undefined = heap->undefined_value(); |
| + Object* head = undefined; |
| JSFunction* tail = NULL; |
| Object* candidate = function; |
| - while (candidate != heap->undefined_value()) { |
| + while (candidate != undefined) { |
| // Check whether to keep the candidate in the list. |
| JSFunction* candidate_function = reinterpret_cast<JSFunction*>(candidate); |
| Object* retain = retainer->RetainAs(candidate); |
| if (retain != NULL) { |
| - if (head == heap->undefined_value()) { |
| + if (head == undefined) { |
| // First element in the list. |
| - head = candidate_function; |
| + head = retain; |
| } else { |
| // Subsequent elements in the list. |
| ASSERT(tail != NULL); |
| - tail->set_next_function_link(candidate_function); |
| + tail->set_next_function_link(retain); |
| } |
| // Retained function is new tail. |
| + candidate_function = reinterpret_cast<JSFunction*>(retain); |
| tail = candidate_function; |
| + |
| + ASSERT(retain->IsUndefined() || retain->IsJSFunction()); |
| + |
| + if (retain == undefined) break; |
| } |
| + |
| // Move to next element in the list. |
| candidate = candidate_function->next_function_link(); |
| } |
| // Terminate the list if there is one or more elements. |
| if (tail != NULL) { |
| - tail->set_next_function_link(heap->undefined_value()); |
| + tail->set_next_function_link(undefined); |
| } |
| + head->Verify(); |
| + |
| return head; |
| } |
| void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) { |
| - Object* head = undefined_value(); |
| + Object* undefined = undefined_value(); |
| + Object* head = undefined; |
| Context* tail = NULL; |
| Object* candidate = global_contexts_list_; |
| - while (candidate != undefined_value()) { |
| + while (candidate != undefined) { |
| // Check whether to keep the candidate in the list. |
| Context* candidate_context = reinterpret_cast<Context*>(candidate); |
| Object* retain = retainer->RetainAs(candidate); |
| if (retain != NULL) { |
| - if (head == undefined_value()) { |
| + if (head == undefined) { |
| // First element in the list. |
| - head = candidate_context; |
| + head = retain; |
| } else { |
| // Subsequent elements in the list. |
| ASSERT(tail != NULL); |
| tail->set_unchecked(this, |
| Context::NEXT_CONTEXT_LINK, |
| - candidate_context, |
| + retain, |
| UPDATE_WRITE_BARRIER); |
| } |
| // Retained context is new tail. |
| + candidate_context = reinterpret_cast<Context*>(retain); |
| tail = candidate_context; |
| + if (retain == undefined) break; |
| + |
| // Process the weak list of optimized functions for the context. |
| Object* function_list_head = |
| ProcessFunctionWeakReferences( |
| @@ -1218,6 +1238,7 @@ void Heap::ProcessWeakReferences(WeakObjectRetainer* retainer) { |
| function_list_head, |
| UPDATE_WRITE_BARRIER); |
| } |
| + |
| // Move to next element in the list. |
| candidate = candidate_context->get(Context::NEXT_CONTEXT_LINK); |
| } |
| @@ -4060,7 +4081,6 @@ void Heap::ReportHeapStatistics(const char* title) { |
| USE(title); |
| PrintF(">>>>>> =============== %s (%d) =============== >>>>>>\n", |
| title, gc_count_); |
| - PrintF("mark-compact GC : %d\n", mc_count_); |
| PrintF("old_gen_promotion_limit_ %" V8_PTR_PREFIX "d\n", |
| old_gen_promotion_limit_); |
| PrintF("old_gen_allocation_limit_ %" V8_PTR_PREFIX "d\n", |
| @@ -4956,7 +4976,6 @@ void Heap::TearDown() { |
| PrintF("\n\n"); |
| PrintF("gc_count=%d ", gc_count_); |
| PrintF("mark_sweep_count=%d ", ms_count_); |
| - PrintF("mark_compact_count=%d ", mc_count_); |
| PrintF("max_gc_pause=%d ", get_max_gc_pause()); |
| PrintF("min_in_mutator=%d ", get_min_in_mutator()); |
| PrintF("max_alive_after_gc=%" V8_PTR_PREFIX "d ", |
| @@ -5431,6 +5450,10 @@ void PathTracer::TracePathFrom(Object** root) { |
| } |
| +static bool SafeIsGlobalContext(HeapObject* obj) { |
| + return obj->map() == obj->GetHeap()->raw_unchecked_global_context_map(); |
| +} |
| + |
|
Erik Corry
2011/06/20 20:41:26
missing blank line
Vyacheslav Egorov (Chromium)
2011/06/21 11:44:48
Done.
|
| void PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) { |
| if (!(*p)->IsHeapObject()) return; |
| @@ -5449,7 +5472,7 @@ void PathTracer::MarkRecursively(Object** p, MarkVisitor* mark_visitor) { |
| return; |
| } |
| - bool is_global_context = obj->IsGlobalContext(); |
| + bool is_global_context = SafeIsGlobalContext(obj); |
| // not visited yet |
| Map* map_p = reinterpret_cast<Map*>(HeapObject::cast(map)); |
| @@ -5494,7 +5517,7 @@ void PathTracer::UnmarkRecursively(Object** p, UnmarkVisitor* unmark_visitor) { |
| map_addr -= kMarkTag; |
| - ASSERT_TAG_ALIGNED(map_addr); |
| + // ASSERT_TAG_ALIGNED(map_addr); |
|
Erik Corry
2011/06/20 20:41:26
commented code
Vyacheslav Egorov (Chromium)
2011/06/21 11:44:48
Done.
|
| HeapObject* map_p = HeapObject::FromAddress(map_addr); |
| @@ -5568,8 +5591,6 @@ GCTracer::GCTracer(Heap* heap) |
| start_size_(0), |
| gc_count_(0), |
| full_gc_count_(0), |
| - is_compacting_(false), |
| - marked_count_(0), |
| allocated_since_last_gc_(0), |
| spent_in_mutator_(0), |
| promoted_objects_size_(0), |
| @@ -5645,8 +5666,7 @@ GCTracer::~GCTracer() { |
| PrintF("s"); |
| break; |
| case MARK_COMPACTOR: |
| - PrintF("%s", |
| - heap_->mark_compact_collector_.HasCompacted() ? "mc" : "ms"); |
| + PrintF("%s", "ms"); |
| break; |
| default: |
| UNREACHABLE(); |
| @@ -5684,8 +5704,7 @@ const char* GCTracer::CollectorString() { |
| case SCAVENGER: |
| return "Scavenge"; |
| case MARK_COMPACTOR: |
| - return heap_->mark_compact_collector_.HasCompacted() ? "Mark-compact" |
| - : "Mark-sweep"; |
| + return "Mark-sweep"; |
| } |
| return "Unknown GC"; |
| } |