From 1d9eac1b7c5796c5693b5ab9051c2cbaf9b0508f Mon Sep 17 00:00:00 2001 From: "christian.plesner.hansen@gmail.com" Date: Thu, 3 Dec 2009 10:16:37 +0000 Subject: [PATCH] Added recording of heap and global handle stats in a stack-allocated struct on fatal out of memory. This should cause the information to be included in minidumps so we can get a better idea of the state of v8 on OOMs. Review URL: http://codereview.chromium.org/462019 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3406 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/api.cc | 10 +++++++++- src/global-handles.cc | 20 ++++++++++++++++++++ src/global-handles.h | 2 ++ src/heap.cc | 18 ++++++++++++++++++ src/heap.h | 25 +++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/api.cc b/src/api.cc index 3a2f8ab745..eaff86255f 100644 --- a/src/api.cc +++ b/src/api.cc @@ -125,7 +125,8 @@ static FatalErrorCallback& GetFatalErrorHandler() { // When V8 cannot allocated memory FatalProcessOutOfMemory is called. // The default fatal error handler is called and execution is stopped. -void i::V8::FatalProcessOutOfMemory(const char* location) { +static void ExecuteFatalProcessOutOfMemory(const char* location, + i::HeapStats* heap_stats) { i::V8::SetFatalError(); FatalErrorCallback callback = GetFatalErrorHandler(); { @@ -137,6 +138,13 @@ void i::V8::FatalProcessOutOfMemory(const char* location) { } +void i::V8::FatalProcessOutOfMemory(const char* location) { + i::HeapStats heap_stats; + i::Heap::RecordStats(&heap_stats); + ExecuteFatalProcessOutOfMemory(location, &heap_stats); +} + + void V8::SetFatalErrorHandler(FatalErrorCallback that) { exception_behavior = that; } diff --git a/src/global-handles.cc b/src/global-handles.cc index e519d7077f..5b01f61f3a 100644 --- a/src/global-handles.cc +++ b/src/global-handles.cc @@ -429,6 +429,26 @@ GlobalHandles::Node* GlobalHandles::head_ = NULL; GlobalHandles::Node* GlobalHandles::first_free_ = NULL; GlobalHandles::Node* GlobalHandles::first_deallocated_ = NULL; +void GlobalHandles::RecordStats(HeapStats* stats) { + stats->global_handle_count = 0; + stats->weak_global_handle_count = 0; + stats->pending_global_handle_count = 0; + stats->near_death_global_handle_count = 0; + stats->destroyed_global_handle_count = 0; + for (Node* current = head_; current != NULL; current = current->next()) { + stats->global_handle_count++; + if (current->state_ == Node::WEAK) { + stats->weak_global_handle_count++; + } else if (current->state_ == Node::PENDING) { + stats->pending_global_handle_count++; + } else if (current->state_ == Node::NEAR_DEATH) { + stats->near_death_global_handle_count++; + } else if (current->state_ == Node::DESTROYED) { + stats->destroyed_global_handle_count++; + } + } +} + #ifdef DEBUG void GlobalHandles::PrintStats() { diff --git a/src/global-handles.h b/src/global-handles.h index b9cac5c2a1..659f86eca7 100644 --- a/src/global-handles.h +++ b/src/global-handles.h @@ -78,6 +78,8 @@ class GlobalHandles : public AllStatic { // Returns the current number of weak handles. static int NumberOfWeakHandles() { return number_of_weak_handles_; } + static void RecordStats(HeapStats* stats); + // Returns the current number of weak handles to global objects. // These handles are also included in NumberOfWeakHandles(). static int NumberOfGlobalObjectWeakHandles() { diff --git a/src/heap.cc b/src/heap.cc index 79a91cfc00..39f00d3b43 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -3273,6 +3273,24 @@ bool Heap::ConfigureHeapDefault() { } +void Heap::RecordStats(HeapStats* stats) { + stats->new_space_size = new_space_.Size(); + stats->new_space_capacity = new_space_.Capacity(); + stats->old_pointer_space_size = old_pointer_space_->Size(); + stats->old_pointer_space_capacity = old_pointer_space_->Capacity(); + stats->old_data_space_size = old_data_space_->Size(); + stats->old_data_space_capacity = old_data_space_->Capacity(); + stats->code_space_size = code_space_->Size(); + stats->code_space_capacity = code_space_->Capacity(); + stats->map_space_size = map_space_->Size(); + stats->map_space_capacity = map_space_->Capacity(); + stats->cell_space_size = cell_space_->Size(); + stats->cell_space_capacity = cell_space_->Capacity(); + stats->lo_space_size = lo_space_->Size(); + GlobalHandles::RecordStats(stats); +} + + int Heap::PromotedSpaceSize() { return old_pointer_space_->Size() + old_data_space_->Size() diff --git a/src/heap.h b/src/heap.h index 80cc885a80..8bc55e8031 100644 --- a/src/heap.h +++ b/src/heap.h @@ -189,6 +189,7 @@ namespace internal { // Forward declaration of the GCTracer class. class GCTracer; +class HeapStats; // The all static Heap captures the interface to the global object heap. @@ -865,6 +866,8 @@ class Heap : public AllStatic { static RootListIndex RootIndexForExternalArrayType( ExternalArrayType array_type); + static void RecordStats(HeapStats* stats); + private: static int reserved_semispace_size_; static int max_semispace_size_; @@ -1100,6 +1103,28 @@ class Heap : public AllStatic { }; +struct HeapStats { + int new_space_size; + int new_space_capacity; + int old_pointer_space_size; + int old_pointer_space_capacity; + int old_data_space_size; + int old_data_space_capacity; + int code_space_size; + int code_space_capacity; + int map_space_size; + int map_space_capacity; + int cell_space_size; + int cell_space_capacity; + int lo_space_size; + int global_handle_count; + int weak_global_handle_count; + int pending_global_handle_count; + int near_death_global_handle_count; + int destroyed_global_handle_count; +}; + + class AlwaysAllocateScope { public: AlwaysAllocateScope() {