// 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) {
+void i::V8::FatalProcessOutOfMemory(const char* location, bool take_snapshot) {
i::HeapStats heap_stats;
int start_marker;
heap_stats.start_marker = &start_marker;
heap_stats.near_death_global_handle_count = &near_death_global_handle_count;
int destroyed_global_handle_count;
heap_stats.destroyed_global_handle_count = &destroyed_global_handle_count;
+ int memory_allocator_size;
+ heap_stats.memory_allocator_size = &memory_allocator_size;
+ int memory_allocator_capacity;
+ heap_stats.memory_allocator_capacity = &memory_allocator_capacity;
+ int objects_per_type[LAST_TYPE + 1] = {0};
+ heap_stats.objects_per_type = objects_per_type;
+ int size_per_type[LAST_TYPE + 1] = {0};
+ heap_stats.size_per_type = size_per_type;
int end_marker;
heap_stats.end_marker = &end_marker;
- i::Heap::RecordStats(&heap_stats);
+ i::Heap::RecordStats(&heap_stats, take_snapshot);
i::V8::SetFatalError();
FatalErrorCallback callback = GetFatalErrorHandler();
{
Object* __object__ = FUNCTION_CALL; \
if (!__object__->IsFailure()) RETURN_VALUE; \
if (__object__->IsOutOfMemoryFailure()) { \
- v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_0"); \
+ v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_0", true);\
} \
if (!__object__->IsRetryAfterGC()) RETURN_EMPTY; \
Heap::CollectGarbage(Failure::cast(__object__)->requested(), \
__object__ = FUNCTION_CALL; \
if (!__object__->IsFailure()) RETURN_VALUE; \
if (__object__->IsOutOfMemoryFailure()) { \
- v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_1"); \
+ v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_1", true);\
} \
if (!__object__->IsRetryAfterGC()) RETURN_EMPTY; \
Counters::gc_last_resort_from_handles.Increment(); \
if (__object__->IsOutOfMemoryFailure() || \
__object__->IsRetryAfterGC()) { \
/* TODO(1181417): Fix this. */ \
- v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_2"); \
+ v8::internal::V8::FatalProcessOutOfMemory("CALL_AND_RETRY_2", true);\
} \
RETURN_EMPTY; \
} while (false)
}
-void Heap::RecordStats(HeapStats* stats) {
+void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
*stats->start_marker = 0xDECADE00;
*stats->end_marker = 0xDECADE01;
*stats->new_space_size = new_space_.Size();
*stats->cell_space_capacity = cell_space_->Capacity();
*stats->lo_space_size = lo_space_->Size();
GlobalHandles::RecordStats(stats);
+ *stats->memory_allocator_size = MemoryAllocator::Size();
+ *stats->memory_allocator_capacity =
+ MemoryAllocator::Size() + MemoryAllocator::Available();
+ if (take_snapshot) {
+ HeapIterator iterator;
+ for (HeapObject* obj = iterator.next();
+ obj != NULL;
+ obj = iterator.next()) {
+ // Note: snapshot won't be precise because IsFreeListNode returns true
+ // for any bytearray.
+ if (FreeListNode::IsFreeListNode(obj)) continue;
+ InstanceType type = obj->map()->instance_type();
+ ASSERT(0 <= type && type <= LAST_TYPE);
+ stats->objects_per_type[type]++;
+ stats->size_per_type[type] += obj->Size();
+ }
+ }
}
static RootListIndex RootIndexForExternalArrayType(
ExternalArrayType array_type);
- static void RecordStats(HeapStats* stats);
+ static void RecordStats(HeapStats* stats, bool take_snapshot = false);
static Scavenger GetScavenger(int instance_type, int instance_size);
class HeapStats {
public:
- int* start_marker;
- 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;
- int* end_marker;
+ int* start_marker; // 0
+ int* new_space_size; // 1
+ int* new_space_capacity; // 2
+ int* old_pointer_space_size; // 3
+ int* old_pointer_space_capacity; // 4
+ int* old_data_space_size; // 5
+ int* old_data_space_capacity; // 6
+ int* code_space_size; // 7
+ int* code_space_capacity; // 8
+ int* map_space_size; // 9
+ int* map_space_capacity; // 10
+ int* cell_space_size; // 11
+ int* cell_space_capacity; // 12
+ int* lo_space_size; // 13
+ int* global_handle_count; // 14
+ int* weak_global_handle_count; // 15
+ int* pending_global_handle_count; // 16
+ int* near_death_global_handle_count; // 17
+ int* destroyed_global_handle_count; // 18
+ int* memory_allocator_size; // 19
+ int* memory_allocator_capacity; // 20
+ int* objects_per_type; // 21
+ int* size_per_type; // 22
+ int* end_marker; // 23
};
static void SetFatalError();
// Report process out of memory. Implementation found in api.cc.
- static void FatalProcessOutOfMemory(const char* location);
+ static void FatalProcessOutOfMemory(const char* location,
+ bool take_snapshot = false);
// Random number generation support. Not cryptographically safe.
static uint32_t Random();