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 3// found in the LICENSE file. 4 5#include "src/extensions/statistics-extension.h" 6 7#include "src/counters.h" 8#include "src/heap/heap-inl.h" 9#include "src/isolate.h" 10 11namespace v8 { 12namespace internal { 13 14const char* const StatisticsExtension::kSource = 15 "native function getV8Statistics();"; 16 17 18v8::Local<v8::FunctionTemplate> StatisticsExtension::GetNativeFunctionTemplate( 19 v8::Isolate* isolate, v8::Local<v8::String> str) { 20 DCHECK(strcmp(*v8::String::Utf8Value(str), "getV8Statistics") == 0); 21 return v8::FunctionTemplate::New(isolate, StatisticsExtension::GetCounters); 22} 23 24 25static void AddCounter(v8::Isolate* isolate, 26 v8::Local<v8::Object> object, 27 StatsCounter* counter, 28 const char* name) { 29 if (counter->Enabled()) { 30 object->Set(isolate->GetCurrentContext(), 31 v8::String::NewFromUtf8(isolate, name, NewStringType::kNormal) 32 .ToLocalChecked(), 33 v8::Number::New(isolate, *counter->GetInternalPointer())) 34 .FromJust(); 35 } 36} 37 38static void AddNumber(v8::Isolate* isolate, 39 v8::Local<v8::Object> object, 40 intptr_t value, 41 const char* name) { 42 object->Set(isolate->GetCurrentContext(), 43 v8::String::NewFromUtf8(isolate, name, NewStringType::kNormal) 44 .ToLocalChecked(), 45 v8::Number::New(isolate, static_cast<double>(value))).FromJust(); 46} 47 48 49static void AddNumber64(v8::Isolate* isolate, 50 v8::Local<v8::Object> object, 51 int64_t value, 52 const char* name) { 53 object->Set(isolate->GetCurrentContext(), 54 v8::String::NewFromUtf8(isolate, name, NewStringType::kNormal) 55 .ToLocalChecked(), 56 v8::Number::New(isolate, static_cast<double>(value))).FromJust(); 57} 58 59 60void StatisticsExtension::GetCounters( 61 const v8::FunctionCallbackInfo<v8::Value>& args) { 62 Isolate* isolate = reinterpret_cast<Isolate*>(args.GetIsolate()); 63 Heap* heap = isolate->heap(); 64 65 if (args.Length() > 0) { // GC if first argument evaluates to true. 66 if (args[0]->IsBoolean() && 67 args[0] 68 ->BooleanValue(args.GetIsolate()->GetCurrentContext()) 69 .FromMaybe(false)) { 70 heap->CollectAllGarbage(Heap::kNoGCFlags, "counters extension"); 71 } 72 } 73 74 Counters* counters = isolate->counters(); 75 v8::Local<v8::Object> result = v8::Object::New(args.GetIsolate()); 76 77 struct StatisticsCounter { 78 v8::internal::StatsCounter* counter; 79 const char* name; 80 }; 81 const StatisticsCounter counter_list[] = { 82#define ADD_COUNTER(name, caption) \ 83 { counters->name(), #name } \ 84 , 85 86 STATS_COUNTER_LIST_1(ADD_COUNTER) STATS_COUNTER_LIST_2(ADD_COUNTER) 87#undef ADD_COUNTER 88#define ADD_COUNTER(name) \ 89 { counters->count_of_##name(), "count_of_" #name } \ 90 , {counters->size_of_##name(), "size_of_" #name}, 91 92 INSTANCE_TYPE_LIST(ADD_COUNTER) 93#undef ADD_COUNTER 94#define ADD_COUNTER(name) \ 95 { counters->count_of_CODE_TYPE_##name(), "count_of_CODE_TYPE_" #name } \ 96 , {counters->size_of_CODE_TYPE_##name(), "size_of_CODE_TYPE_" #name}, 97 98 CODE_KIND_LIST(ADD_COUNTER) 99#undef ADD_COUNTER 100#define ADD_COUNTER(name) \ 101 { counters->count_of_FIXED_ARRAY_##name(), "count_of_FIXED_ARRAY_" #name } \ 102 , {counters->size_of_FIXED_ARRAY_##name(), "size_of_FIXED_ARRAY_" #name}, 103 104 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADD_COUNTER) 105#undef ADD_COUNTER 106 }; // End counter_list array. 107 108 for (size_t i = 0; i < arraysize(counter_list); i++) { 109 AddCounter(args.GetIsolate(), result, counter_list[i].counter, 110 counter_list[i].name); 111 } 112 113 struct StatisticNumber { 114 intptr_t number; 115 const char* name; 116 }; 117 118 const StatisticNumber numbers[] = { 119 {heap->memory_allocator()->Size(), "total_committed_bytes"}, 120 {heap->new_space()->Size(), "new_space_live_bytes"}, 121 {heap->new_space()->Available(), "new_space_available_bytes"}, 122 {heap->new_space()->CommittedMemory(), "new_space_commited_bytes"}, 123 {heap->old_space()->Size(), "old_space_live_bytes"}, 124 {heap->old_space()->Available(), "old_space_available_bytes"}, 125 {heap->old_space()->CommittedMemory(), "old_space_commited_bytes"}, 126 {heap->code_space()->Size(), "code_space_live_bytes"}, 127 {heap->code_space()->Available(), "code_space_available_bytes"}, 128 {heap->code_space()->CommittedMemory(), "code_space_commited_bytes"}, 129 {heap->lo_space()->Size(), "lo_space_live_bytes"}, 130 {heap->lo_space()->Available(), "lo_space_available_bytes"}, 131 {heap->lo_space()->CommittedMemory(), "lo_space_commited_bytes"}, 132 }; 133 134 for (size_t i = 0; i < arraysize(numbers); i++) { 135 AddNumber(args.GetIsolate(), result, numbers[i].number, numbers[i].name); 136 } 137 138 AddNumber64(args.GetIsolate(), result, heap->external_memory(), 139 "amount_of_external_allocated_memory"); 140 args.GetReturnValue().Set(result); 141} 142 143} // namespace internal 144} // namespace v8 145