Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(453)

Side by Side Diff: src/heap/heap.cc

Issue 890663005: Introduce a flag for tracing retaining path in GC. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/heap/heap.h ('k') | src/heap/mark-compact.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/api.h" 8 #include "src/api.h"
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/base/once.h" 10 #include "src/base/once.h"
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 set_native_contexts_list(NULL); 159 set_native_contexts_list(NULL);
160 set_array_buffers_list(Smi::FromInt(0)); 160 set_array_buffers_list(Smi::FromInt(0));
161 set_allocation_sites_list(Smi::FromInt(0)); 161 set_allocation_sites_list(Smi::FromInt(0));
162 set_encountered_weak_collections(Smi::FromInt(0)); 162 set_encountered_weak_collections(Smi::FromInt(0));
163 set_encountered_weak_cells(Smi::FromInt(0)); 163 set_encountered_weak_cells(Smi::FromInt(0));
164 // Put a dummy entry in the remembered pages so we can find the list the 164 // Put a dummy entry in the remembered pages so we can find the list the
165 // minidump even if there are no real unmapped pages. 165 // minidump even if there are no real unmapped pages.
166 RememberUnmappedPage(NULL, false); 166 RememberUnmappedPage(NULL, false);
167 167
168 ClearObjectStats(true); 168 ClearObjectStats(true);
169
170 #ifdef TRACE_RETAINING_PATH
171 ClearRetainingInfo();
172 #endif
169 } 173 }
170 174
171 175
172 intptr_t Heap::Capacity() { 176 intptr_t Heap::Capacity() {
173 if (!HasBeenSetUp()) return 0; 177 if (!HasBeenSetUp()) return 0;
174 178
175 return new_space_.Capacity() + old_pointer_space_->Capacity() + 179 return new_space_.Capacity() + old_pointer_space_->Capacity() +
176 old_data_space_->Capacity() + code_space_->Capacity() + 180 old_data_space_->Capacity() + code_space_->Capacity() +
177 map_space_->Capacity() + cell_space_->Capacity() + 181 map_space_->Capacity() + cell_space_->Capacity() +
178 property_cell_space_->Capacity(); 182 property_cell_space_->Capacity();
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
607 611
608 // Process pretenuring feedback and update allocation sites. 612 // Process pretenuring feedback and update allocation sites.
609 ProcessPretenuringFeedback(); 613 ProcessPretenuringFeedback();
610 614
611 #ifdef VERIFY_HEAP 615 #ifdef VERIFY_HEAP
612 if (FLAG_verify_heap) { 616 if (FLAG_verify_heap) {
613 Verify(); 617 Verify();
614 } 618 }
615 #endif 619 #endif
616 620
621 #ifdef TRACE_RETAINING_PATH
622 ClearRetainingInfo();
623 #endif
624
617 AllowHeapAllocation for_the_rest_of_the_epilogue; 625 AllowHeapAllocation for_the_rest_of_the_epilogue;
618 626
619 #ifdef DEBUG 627 #ifdef DEBUG
620 if (FLAG_print_global_handles) isolate_->global_handles()->Print(); 628 if (FLAG_print_global_handles) isolate_->global_handles()->Print();
621 if (FLAG_print_handles) PrintHandles(); 629 if (FLAG_print_handles) PrintHandles();
622 if (FLAG_gc_verbose) Print(); 630 if (FLAG_gc_verbose) Print();
623 if (FLAG_code_stats) ReportCodeStatistics("After GC"); 631 if (FLAG_code_stats) ReportCodeStatistics("After GC");
624 #endif 632 #endif
625 if (FLAG_deopt_every_n_garbage_collections > 0) { 633 if (FLAG_deopt_every_n_garbage_collections > 0) {
626 // TODO(jkummerow/ulan/jarin): This is not safe! We can't assume that 634 // TODO(jkummerow/ulan/jarin): This is not safe! We can't assume that
(...skipping 4410 matching lines...) Expand 10 before | Expand all | Expand 10 after
5037 5045
5038 5046
5039 void Heap::IterateSmiRoots(ObjectVisitor* v) { 5047 void Heap::IterateSmiRoots(ObjectVisitor* v) {
5040 // Acquire execution access since we are going to read stack limit values. 5048 // Acquire execution access since we are going to read stack limit values.
5041 ExecutionAccess access(isolate()); 5049 ExecutionAccess access(isolate());
5042 v->VisitPointers(&roots_[kSmiRootsStart], &roots_[kRootListLength]); 5050 v->VisitPointers(&roots_[kSmiRootsStart], &roots_[kRootListLength]);
5043 v->Synchronize(VisitorSynchronization::kSmiRootList); 5051 v->Synchronize(VisitorSynchronization::kSmiRootList);
5044 } 5052 }
5045 5053
5046 5054
5055 #ifdef TRACE_RETAINING_PATH
5056 #define TRACE_ROOT(root) SetCurrentRootRetainer(std::string(root))
5057 #else
5058 #define TRACE_ROOT(root)
5059 #endif
5060
5061
5047 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) { 5062 void Heap::IterateStrongRoots(ObjectVisitor* v, VisitMode mode) {
5063 TRACE_ROOT("[strong root list]");
5048 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]); 5064 v->VisitPointers(&roots_[0], &roots_[kStrongRootListLength]);
5049 v->Synchronize(VisitorSynchronization::kStrongRootList); 5065 v->Synchronize(VisitorSynchronization::kStrongRootList);
5050 5066
5067 TRACE_ROOT("[internalized string]");
5051 v->VisitPointer(bit_cast<Object**>(&hidden_string_)); 5068 v->VisitPointer(bit_cast<Object**>(&hidden_string_));
5052 v->Synchronize(VisitorSynchronization::kInternalizedString); 5069 v->Synchronize(VisitorSynchronization::kInternalizedString);
5053 5070
5071 TRACE_ROOT("[bootstrapper]");
5054 isolate_->bootstrapper()->Iterate(v); 5072 isolate_->bootstrapper()->Iterate(v);
5055 v->Synchronize(VisitorSynchronization::kBootstrapper); 5073 v->Synchronize(VisitorSynchronization::kBootstrapper);
5074
5075 TRACE_ROOT("[isolate threads]");
5056 isolate_->Iterate(v); 5076 isolate_->Iterate(v);
5057 v->Synchronize(VisitorSynchronization::kTop); 5077 v->Synchronize(VisitorSynchronization::kTop);
5078
5079 TRACE_ROOT("[isolate relocatable]");
5058 Relocatable::Iterate(isolate_, v); 5080 Relocatable::Iterate(isolate_, v);
5059 v->Synchronize(VisitorSynchronization::kRelocatable); 5081 v->Synchronize(VisitorSynchronization::kRelocatable);
5060 5082
5083 TRACE_ROOT("[deoptimizer data]");
5061 if (isolate_->deoptimizer_data() != NULL) { 5084 if (isolate_->deoptimizer_data() != NULL) {
5062 isolate_->deoptimizer_data()->Iterate(v); 5085 isolate_->deoptimizer_data()->Iterate(v);
5063 } 5086 }
5064 v->Synchronize(VisitorSynchronization::kDebug); 5087 v->Synchronize(VisitorSynchronization::kDebug);
5088
5089 TRACE_ROOT("[compilation cache]");
5065 isolate_->compilation_cache()->Iterate(v); 5090 isolate_->compilation_cache()->Iterate(v);
5066 v->Synchronize(VisitorSynchronization::kCompilationCache); 5091 v->Synchronize(VisitorSynchronization::kCompilationCache);
5067 5092
5068 // Iterate over local handles in handle scopes. 5093 // Iterate over local handles in handle scopes.
5094 TRACE_ROOT("[internal handles]");
5069 isolate_->handle_scope_implementer()->Iterate(v); 5095 isolate_->handle_scope_implementer()->Iterate(v);
5096 TRACE_ROOT("[internal deferred handles]");
5070 isolate_->IterateDeferredHandles(v); 5097 isolate_->IterateDeferredHandles(v);
5071 v->Synchronize(VisitorSynchronization::kHandleScope); 5098 v->Synchronize(VisitorSynchronization::kHandleScope);
5072 5099
5073 // Iterate over the builtin code objects and code stubs in the 5100 // Iterate over the builtin code objects and code stubs in the
5074 // heap. Note that it is not necessary to iterate over code objects 5101 // heap. Note that it is not necessary to iterate over code objects
5075 // on scavenge collections. 5102 // on scavenge collections.
5103 TRACE_ROOT("[builtins]");
5076 if (mode != VISIT_ALL_IN_SCAVENGE) { 5104 if (mode != VISIT_ALL_IN_SCAVENGE) {
5077 isolate_->builtins()->IterateBuiltins(v); 5105 isolate_->builtins()->IterateBuiltins(v);
5078 } 5106 }
5079 v->Synchronize(VisitorSynchronization::kBuiltins); 5107 v->Synchronize(VisitorSynchronization::kBuiltins);
5080 5108
5081 // Iterate over global handles. 5109 // Iterate over global handles.
5110 TRACE_ROOT("[global handles]");
5082 switch (mode) { 5111 switch (mode) {
5083 case VISIT_ONLY_STRONG: 5112 case VISIT_ONLY_STRONG:
5084 isolate_->global_handles()->IterateStrongRoots(v); 5113 isolate_->global_handles()->IterateStrongRoots(v);
5085 break; 5114 break;
5086 case VISIT_ALL_IN_SCAVENGE: 5115 case VISIT_ALL_IN_SCAVENGE:
5087 isolate_->global_handles()->IterateNewSpaceStrongAndDependentRoots(v); 5116 isolate_->global_handles()->IterateNewSpaceStrongAndDependentRoots(v);
5088 break; 5117 break;
5089 case VISIT_ALL_IN_SWEEP_NEWSPACE: 5118 case VISIT_ALL_IN_SWEEP_NEWSPACE:
5090 case VISIT_ALL: 5119 case VISIT_ALL:
5091 isolate_->global_handles()->IterateAllRoots(v); 5120 isolate_->global_handles()->IterateAllRoots(v);
5092 break; 5121 break;
5093 } 5122 }
5094 v->Synchronize(VisitorSynchronization::kGlobalHandles); 5123 v->Synchronize(VisitorSynchronization::kGlobalHandles);
5095 5124
5096 // Iterate over eternal handles. 5125 // Iterate over eternal handles.
5126 TRACE_ROOT("[eternal handles]");
5097 if (mode == VISIT_ALL_IN_SCAVENGE) { 5127 if (mode == VISIT_ALL_IN_SCAVENGE) {
5098 isolate_->eternal_handles()->IterateNewSpaceRoots(v); 5128 isolate_->eternal_handles()->IterateNewSpaceRoots(v);
5099 } else { 5129 } else {
5100 isolate_->eternal_handles()->IterateAllRoots(v); 5130 isolate_->eternal_handles()->IterateAllRoots(v);
5101 } 5131 }
5102 v->Synchronize(VisitorSynchronization::kEternalHandles); 5132 v->Synchronize(VisitorSynchronization::kEternalHandles);
5103 5133
5134 TRACE_ROOT("[isolate inactive threads]");
5104 // Iterate over pointers being held by inactive threads. 5135 // Iterate over pointers being held by inactive threads.
5105 isolate_->thread_manager()->Iterate(v); 5136 isolate_->thread_manager()->Iterate(v);
5106 v->Synchronize(VisitorSynchronization::kThreadManager); 5137 v->Synchronize(VisitorSynchronization::kThreadManager);
5107 5138
5108 // Iterate over the pointers the Serialization/Deserialization code is 5139 // Iterate over the pointers the Serialization/Deserialization code is
5109 // holding. 5140 // holding.
5110 // During garbage collection this keeps the partial snapshot cache alive. 5141 // During garbage collection this keeps the partial snapshot cache alive.
5111 // During deserialization of the startup snapshot this creates the partial 5142 // During deserialization of the startup snapshot this creates the partial
5112 // snapshot cache and deserializes the objects it refers to. During 5143 // snapshot cache and deserializes the objects it refers to. During
5113 // serialization this does nothing, since the partial snapshot cache is 5144 // serialization this does nothing, since the partial snapshot cache is
5114 // empty. However the next thing we do is create the partial snapshot, 5145 // empty. However the next thing we do is create the partial snapshot,
5115 // filling up the partial snapshot cache with objects it needs as we go. 5146 // filling up the partial snapshot cache with objects it needs as we go.
5147 TRACE_ROOT("[serializer/deserializer]");
5116 SerializerDeserializer::Iterate(isolate_, v); 5148 SerializerDeserializer::Iterate(isolate_, v);
5117 // We don't do a v->Synchronize call here, because in debug mode that will 5149 // We don't do a v->Synchronize call here, because in debug mode that will
5118 // output a flag to the snapshot. However at this point the serializer and 5150 // output a flag to the snapshot. However at this point the serializer and
5119 // deserializer are deliberately a little unsynchronized (see above) so the 5151 // deserializer are deliberately a little unsynchronized (see above) so the
5120 // checking of the sync flag in the snapshot would fail. 5152 // checking of the sync flag in the snapshot would fail.
5153 TRACE_ROOT("[]");
5121 } 5154 }
5122 5155
5123 5156
5124 // TODO(1236194): Since the heap size is configurable on the command line 5157 // TODO(1236194): Since the heap size is configurable on the command line
5125 // and through the API, we should gracefully handle the case that the heap 5158 // and through the API, we should gracefully handle the case that the heap
5126 // size is not big enough to fit all the initial objects. 5159 // size is not big enough to fit all the initial objects.
5127 bool Heap::ConfigureHeap(int max_semi_space_size, int max_old_space_size, 5160 bool Heap::ConfigureHeap(int max_semi_space_size, int max_old_space_size,
5128 int max_executable_size, size_t code_range_size) { 5161 int max_executable_size, size_t code_range_size) {
5129 if (HasBeenSetUp()) return false; 5162 if (HasBeenSetUp()) return false;
5130 5163
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
5517 roots_[kStackLimitRootIndex] = reinterpret_cast<Object*>( 5550 roots_[kStackLimitRootIndex] = reinterpret_cast<Object*>(
5518 (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag); 5551 (isolate_->stack_guard()->jslimit() & ~kSmiTagMask) | kSmiTag);
5519 roots_[kRealStackLimitRootIndex] = reinterpret_cast<Object*>( 5552 roots_[kRealStackLimitRootIndex] = reinterpret_cast<Object*>(
5520 (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag); 5553 (isolate_->stack_guard()->real_jslimit() & ~kSmiTagMask) | kSmiTag);
5521 } 5554 }
5522 5555
5523 5556
5524 void Heap::NotifyDeserializationComplete() { deserialization_complete_ = true; } 5557 void Heap::NotifyDeserializationComplete() { deserialization_complete_ = true; }
5525 5558
5526 5559
5560 #ifdef TRACE_RETAINING_PATH
5561 void Heap::SetCurrentRetainer(HeapObject* obj) { current_retainer_ = obj; }
5562
5563
5564 void Heap::SetCurrentRootRetainer(std::string root) {
5565 current_root_retainer_ = root;
5566 }
5567
5568
5569 void Heap::PrintRetainingPath(HeapObject* obj, const char* comment) {
5570 PrintF("Retaining path for %s [%p]:\n", comment, static_cast<void*>(obj));
5571 obj->ShortPrint();
5572 PrintF("\n");
5573 while (retainer_.count(obj) && retainer_[obj] != NULL) {
5574 PrintF("^^^^^^^^\n");
5575 obj = retainer_[obj];
5576 #ifdef OBJECT_PRINT
5577 obj->Print();
5578 #else
5579 obj->ShortPrint();
5580 #endif
5581 PrintF("\n");
5582 }
5583 if (root_retainer_.count(obj)) {
5584 PrintF("^^^^^^^^\n");
5585 PrintF("%s\n", root_retainer_[obj].c_str());
5586 }
5587 PrintF("End of retaining path.\n");
5588 }
5589
5590
5591 void Heap::AddRetainedObject(HeapObject* obj) {
5592 if (retainer_.count(obj)) return;
5593 retainer_[obj] = current_retainer_;
5594 if (current_retainer_ == NULL) {
5595 root_retainer_[obj] = current_root_retainer_;
5596 }
5597 const char* filter = FLAG_trace_retaining_path_for;
5598 if (obj->IsJSObject() && *filter != 0) {
5599 JSObject* jsobj = JSObject::cast(obj);
5600 String* name = jsobj->constructor_name();
5601 if (!strcmp(filter, name->ToCString().get())) {
5602 PrintRetainingPath(obj, filter);
5603 }
5604 }
5605 if (FLAG_track_detached_contexts && obj->IsNativeContext()) {
5606 FixedArray* dc = detached_contexts();
5607 int length = dc->length();
5608 for (int i = 0; i < length; i += 2) {
5609 int mark_sweeps = Smi::cast(dc->get(i))->value();
5610 if (mark_sweeps > 5 && WeakCell::cast(dc->get(i + 1))->value() == obj) {
Hannes Payer (out of office) 2015/02/06 13:31:31 make 5 a constant
5611 PrintRetainingPath(obj, "detached context");
5612 }
5613 }
5614 }
5615 }
5616
5617
5618 void Heap::ClearRetainingInfo() {
5619 retainer_.clear();
5620 root_retainer_.clear();
5621 current_retainer_ = NULL;
5622 current_root_retainer_ = "";
5623 }
5624 #endif
5625
Hannes Payer (out of office) 2015/02/06 13:31:32 +1 newline
5527 void Heap::TearDown() { 5626 void Heap::TearDown() {
5528 #ifdef VERIFY_HEAP 5627 #ifdef VERIFY_HEAP
5529 if (FLAG_verify_heap) { 5628 if (FLAG_verify_heap) {
5530 Verify(); 5629 Verify();
5531 } 5630 }
5532 #endif 5631 #endif
5533 5632
5534 UpdateMaximumCommitted(); 5633 UpdateMaximumCommitted();
5535 5634
5536 if (FLAG_print_cumulative_gc_stat) { 5635 if (FLAG_print_cumulative_gc_stat) {
(...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after
6488 static_cast<int>(object_sizes_last_time_[index])); 6587 static_cast<int>(object_sizes_last_time_[index]));
6489 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT) 6588 CODE_AGE_LIST_COMPLETE(ADJUST_LAST_TIME_OBJECT_COUNT)
6490 #undef ADJUST_LAST_TIME_OBJECT_COUNT 6589 #undef ADJUST_LAST_TIME_OBJECT_COUNT
6491 6590
6492 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_)); 6591 MemCopy(object_counts_last_time_, object_counts_, sizeof(object_counts_));
6493 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_)); 6592 MemCopy(object_sizes_last_time_, object_sizes_, sizeof(object_sizes_));
6494 ClearObjectStats(); 6593 ClearObjectStats();
6495 } 6594 }
6496 } 6595 }
6497 } // namespace v8::internal 6596 } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/heap/heap.h ('k') | src/heap/mark-compact.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698