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

Unified Diff: src/heap.cc

Issue 8055029: Add experimental support for tracing the state of the VM heap to a file Base URL: http://v8.googlecode.com/svn/branches/experimental/heap-visualization/
Patch Set: Created 9 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/heap.h ('k') | src/incremental-marking.cc » ('j') | src/spaces.h » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap.cc
===================================================================
--- src/heap.cc (revision 9457)
+++ src/heap.cc (working copy)
@@ -92,6 +92,7 @@
sweep_generation_(0),
always_allocate_scope_depth_(0),
linear_allocation_scope_depth_(0),
+ visualizer_(NULL),
contexts_disposed_(0),
scan_on_scavenge_pages_(0),
new_space_(this),
@@ -359,7 +360,10 @@
}
-void Heap::GarbageCollectionPrologue() {
+void Heap::GarbageCollectionPrologue(GarbageCollector collector) {
+ VisualizerTimeStamp(collector == SCAVENGER ?
+ HeapVisualizer::kScavenging :
+ HeapVisualizer::kMarking);
isolate_->transcendental_cache()->Clear();
ClearJSFunctionResultCaches();
gc_count_++;
@@ -383,6 +387,7 @@
store_buffer()->GCPrologue();
}
+
intptr_t Heap::SizeOfObjects() {
intptr_t total = 0;
AllSpaces spaces;
@@ -422,6 +427,10 @@
#ifdef ENABLE_DEBUGGER_SUPPORT
isolate_->debug()->AfterGarbageCollection();
#endif // ENABLE_DEBUGGER_SUPPORT
+ VisualizerTimeStamp(HeapVisualizer::kRunning);
+ for (HeapVisualizer* vis = visualizer(); vis != NULL; vis = vis->next()) {
+ UpdateHeapVisualizer(vis, new_space());
+ }
}
@@ -491,7 +500,7 @@
bool next_gc_likely_to_collect_more = false;
{ GCTracer tracer(this);
- GarbageCollectionPrologue();
+ GarbageCollectionPrologue(collector);
// The GC count was incremented in the prologue. Tell the tracer about
// it.
tracer.set_gc_count(gc_count_);
@@ -6393,6 +6402,248 @@
}
+static void HandleRange(uintptr_t* allocated_bytes,
+ int pixel_size_log_2,
+ uintptr_t page_address,
+ uintptr_t object_start,
+ uintptr_t object_size) {
+ uintptr_t pixel_size = 1 << pixel_size_log_2;
+ int start_pixel = (object_start - page_address) >> pixel_size_log_2;
+ int end_pixel =
+ (object_start + object_size - page_address) >> pixel_size_log_2;
+ if (start_pixel != end_pixel) {
+ int on_first_page = pixel_size - (object_start & (pixel_size - 1));
+ allocated_bytes[start_pixel++] += on_first_page;
+ object_size -= on_first_page;
+ object_start += on_first_page;
+ while (start_pixel != end_pixel) {
+ allocated_bytes[start_pixel++] += pixel_size;
+ object_size -= pixel_size;
+ object_start += pixel_size;
+ }
+ }
+ allocated_bytes[start_pixel] += object_size;
+}
+
+
+void Heap::UpdateHeapVisualizer(HeapVisualizer* visualizer, NewSpace* space) {
+ SemiSpace* semi_space = space->active_space();
+
+ Address top = space->top();
+ NewSpacePage* top_page = NewSpacePage::FromLimit(top);
+ bool allocated = true;
+ for (NewSpacePage* page = semi_space->first_page();
+ !page->is_anchor();
+ page = page->next_page()) {
+ uintptr_t page_address = reinterpret_cast<uintptr_t>(page->address());
+ uintptr_t address = reinterpret_cast<uintptr_t>(page->ObjectAreaStart());
+ uintptr_t end = reinterpret_cast<uintptr_t>(page->ObjectAreaEnd());
+ int overhead_size = address - page_address;
+ visualizer->Name(HeapVisualizer::kHeapOverheadPseudoSpaceIdentity,
+ page_address,
+ overhead_size);
+ visualizer->ConstantAllocation(page_address, overhead_size, 0);
+ Address age_mark = space->to_space_age_mark();
+ if (page->ObjectAreaStart() <= age_mark &&
+ page->ObjectAreaEnd() > age_mark) {
+ visualizer->Name(HeapVisualizer::kSurvivingNewSpacePseudoSpaceIdentity,
+ address,
+ age_mark - page->ObjectAreaStart());
+ visualizer->Name(space->identity(),
+ reinterpret_cast<uintptr_t>(age_mark),
+ page->ObjectAreaEnd() - age_mark);
+ } else {
+ bool below_mark = page->IsFlagSet(MemoryChunk::NEW_SPACE_BELOW_AGE_MARK);
+ int space_id = below_mark ?
+ HeapVisualizer::kSurvivingNewSpacePseudoSpaceIdentity :
+ space->identity();
+ visualizer->Name(space_id, address, end - address);
+ }
+ if (page == top_page) {
+ int allocated_size = reinterpret_cast<uintptr_t>(top) - address;
+ allocated = false;
+ if (allocated_size != 0) {
+ uintptr_t size =
+ Max(allocated_size, 1 << visualizer->pixel_size_log_2());
+ visualizer->ConstantAllocation(address, size, 0);
+ }
+ }
+ if (allocated) {
+ visualizer->ConstantAllocation(address, end - address, 0);
+ }
+ }
+}
+
+
+static void UpdateAllocation(HeapVisualizer* visualizer, Page* page) {
+ int pixel_size_log_2 = visualizer->pixel_size_log_2();
+ uint32_t page_address = reinterpret_cast<uintptr_t>(page->address());
+ uint32_t address = reinterpret_cast<uintptr_t>(page->ObjectAreaStart());
+ uintptr_t end = reinterpret_cast<uintptr_t>(page->ObjectAreaEnd());
+ int overhead_size = address - page_address;
+ visualizer->Name(HeapVisualizer::kHeapOverheadPseudoSpaceIdentity,
+ page_address,
+ overhead_size);
+ visualizer->ConstantAllocation(page_address, overhead_size, 0);
+
+ visualizer->Name(page->owner()->identity(), address, end - address);
+ if (page->WasSwept()) {
+ uintptr_t pixel_size = 1 << pixel_size_log_2;
+ int pixels = ((end - address) >> pixel_size_log_2) + 1;
+ uintptr_t* allocated_bytes = new uintptr_t[pixels];
+ for (int i = 0; i < pixels; i++) {
+ allocated_bytes[i] = 0;
+ }
+ if (page->WasSweptPrecisely()) {
+ HeapObjectIterator iterator(page, NULL);
+ for (HeapObject* object = iterator.Next();
+ object != NULL; object = iterator.Next()) {
+ HandleRange(allocated_bytes,
+ pixel_size_log_2,
+ address,
+ reinterpret_cast<intptr_t>(object->address()),
+ object->Size());
+ }
+ } else {
+ FreeList* free_list =
+ reinterpret_cast<PagedSpace*>(page->owner())->free_list();
+ if (free_list->IsVeryLong()) {
+ // Make checker board pattern to indicate fragmentation.
+ for (int i = 0; i < pixels; i += 8) {
+ allocated_bytes[i] = pixel_size;
+ allocated_bytes[i + 1] = pixel_size;
+ allocated_bytes[i + 4] = pixel_size;
+ allocated_bytes[i + 5] = pixel_size;
+ }
+ } else {
+ FreeListNode* node;
+ for (int i = 0; i < FreeList::kNumberOfChains; i++) {
+ for (node = free_list->get_chain(i);
+ node != NULL;
+ node = node->next()) {
+ if (node->address() >= page->ObjectAreaStart() &&
+ node->address() < page->ObjectAreaEnd()) {
+ HandleRange(allocated_bytes,
+ pixel_size_log_2,
+ address,
+ reinterpret_cast<intptr_t>(node->address()),
+ node->Size());
+ }
+ }
+ }
+ }
+ for (int i = 0; i < pixels; i++) {
+ allocated_bytes[i] = pixel_size - allocated_bytes[i];
+ }
+ }
+ unsigned char* freeness = new unsigned char[pixels];
+ for (int i = 0; i < pixels; i++) {
+ if (allocated_bytes[i] == pixel_size) {
+ freeness[i] = 0;
+ } else {
+ freeness[i] = 255 - (allocated_bytes[i] >> (8 - pixel_size_log_2));
+ }
+ }
+ visualizer->Allocate(address, pixels, freeness);
+ delete[] allocated_bytes;
+ delete[] freeness;
+ }
+}
+
+
+void Heap::UpdateVisualizers(Page* page) {
+ for (HeapVisualizer* vis = visualizer(); vis != NULL; vis = vis->next()) {
+ UpdateAllocation(vis, page);
+ }
+}
+
+
+void Heap::VisualizeCrankshaft() {
+ VisualizerTimeStamp(HeapVisualizer::kCrankshafting);
+}
+
+
+static void VisualizeAllocationTop(PagedSpace* space) {
+ space->SetTop(space->top(), space->limit());
+}
+
+
+void Heap::VisualizeCrankshaftDone() {
+ VisualizeAllocationTop(old_data_space());
+ VisualizeAllocationTop(old_pointer_space());
+ VisualizeAllocationTop(map_space());
+ VisualizeAllocationTop(cell_space());
+ VisualizeAllocationTop(code_space());
+ new_space()->VisualizeTop();
+ VisualizerTimeStamp(HeapVisualizer::kRunning);
+}
+
+
+void Heap::VisualizerTimeStamp(HeapVisualizer::ProfileState state) {
+ uint32_t secs, usecs;
+ OS::GetUserTime(&secs, &usecs);
+ for (HeapVisualizer* vis = visualizer(); vis != NULL; vis = vis->next()) {
+ if (vis->secs_zero() == 0) {
+ vis->set_time_zero(secs, usecs);
+ }
+ if (usecs < vis->usecs_zero()) {
+ usecs += 1000000;
+ secs -= 1;
+ }
+ vis->TimeStamp(state, secs - vis->secs_zero(), usecs - vis->usecs_zero());
+ vis->Flush();
+ }
+}
+
+
+
+void Heap::UpdateHeapVisualizer(HeapVisualizer* visualizer, PagedSpace* space) {
+ // Update the other visualizers (not the new one) with the latest allocation
+ // events.
+ space->SetTop(space->top(), space->limit());
+
+ PageIterator pages(space);
+ while (pages.has_next()) {
+ Page* page = pages.next();
+ UpdateAllocation(visualizer, page);
+ }
+}
+
+
+void Heap::UpdateHeapVisualizer(
+ HeapVisualizer* visualizer, LargeObjectSpace* space) {
+ LargeObjectIterator it(space);
+ for (HeapObject* object = it.Next(); object != NULL; object = it.Next()) {
+ MemoryChunk* chunk = MemoryChunk::FromAddress(object->address());
+ int space_id = OLD_DATA_SPACE;
+ if (object->IsCode()) space_id = CODE_SPACE;
+ if (object->IsFixedArray()) space_id = OLD_POINTER_SPACE;
+ visualizer->Name(HeapVisualizer::kHeapOverheadPseudoSpaceIdentity,
+ reinterpret_cast<uint32_t>(chunk->address()),
+ object->address() - chunk->address());
+ visualizer->Name(space_id,
+ reinterpret_cast<intptr_t>(object->address()),
+ object->Size());
+ visualizer->ConstantAllocation(
+ reinterpret_cast<uint32_t>(chunk->address()),
+ object->address() - chunk->address() + object->Size(),
+ 0);
+ }
+}
+
+
+void Heap::UpdateVisualizer(HeapVisualizer* visualizer) {
+ UpdateHeapVisualizer(visualizer, old_data_space());
+ UpdateHeapVisualizer(visualizer, old_pointer_space());
+ UpdateHeapVisualizer(visualizer, map_space());
+ UpdateHeapVisualizer(visualizer, cell_space());
+ UpdateHeapVisualizer(visualizer, code_space());
+ UpdateHeapVisualizer(visualizer, lo_space());
+ UpdateHeapVisualizer(visualizer, new_space());
+ visualizer->Flush();
+}
+
+
void TranscendentalCache::Clear() {
for (int i = 0; i < kNumberOfCaches; i++) {
if (caches_[i] != NULL) {
@@ -6473,6 +6724,13 @@
isolate_->heap()->store_buffer()->Filter(MemoryChunk::ABOUT_TO_BE_FREED);
for (chunk = chunks_queued_for_free_; chunk != NULL; chunk = next) {
next = chunk->next_chunk();
+ for (HeapVisualizer* vis = isolate_->heap()->visualizer();
+ vis != NULL;
+ vis = vis->next()) {
+ vis->ConstantAllocation(reinterpret_cast<uintptr_t>(chunk->address()),
+ chunk->size(),
+ 255);
+ }
isolate_->memory_allocator()->Free(chunk);
}
chunks_queued_for_free_ = NULL;
« no previous file with comments | « src/heap.h ('k') | src/incremental-marking.cc » ('j') | src/spaces.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698