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
11 namespace v8 {
12 namespace internal {
13
14 const char* const StatisticsExtension::kSource =
15 "native function getV8Statistics();";
16
17
GetNativeFunctionTemplate(v8::Isolate * isolate,v8::Local<v8::String> str)18 v8::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
AddCounter(v8::Isolate * isolate,v8::Local<v8::Object> object,StatsCounter * counter,const char * name)25 static 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
AddNumber(v8::Isolate * isolate,v8::Local<v8::Object> object,double value,const char * name)38 static void AddNumber(v8::Isolate* isolate, v8::Local<v8::Object> object,
39 double value, const char* name) {
40 object
41 ->Set(isolate->GetCurrentContext(),
42 v8::String::NewFromUtf8(isolate, name, NewStringType::kNormal)
43 .ToLocalChecked(),
44 v8::Number::New(isolate, value))
45 .FromJust();
46 }
47
48
AddNumber64(v8::Isolate * isolate,v8::Local<v8::Object> object,int64_t value,const char * name)49 static 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
GetCounters(const v8::FunctionCallbackInfo<v8::Value> & args)60 void 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,
71 GarbageCollectionReason::kCountersExtension);
72 }
73 }
74
75 Counters* counters = isolate->counters();
76 v8::Local<v8::Object> result = v8::Object::New(args.GetIsolate());
77
78 struct StatisticsCounter {
79 v8::internal::StatsCounter* counter;
80 const char* name;
81 };
82 const StatisticsCounter counter_list[] = {
83 #define ADD_COUNTER(name, caption) \
84 { counters->name(), #name } \
85 ,
86
87 STATS_COUNTER_LIST_1(ADD_COUNTER) STATS_COUNTER_LIST_2(ADD_COUNTER)
88 #undef ADD_COUNTER
89 #define ADD_COUNTER(name) \
90 { counters->count_of_##name(), "count_of_" #name } \
91 , {counters->size_of_##name(), "size_of_" #name},
92
93 INSTANCE_TYPE_LIST(ADD_COUNTER)
94 #undef ADD_COUNTER
95 #define ADD_COUNTER(name) \
96 { counters->count_of_CODE_TYPE_##name(), "count_of_CODE_TYPE_" #name } \
97 , {counters->size_of_CODE_TYPE_##name(), "size_of_CODE_TYPE_" #name},
98
99 CODE_KIND_LIST(ADD_COUNTER)
100 #undef ADD_COUNTER
101 #define ADD_COUNTER(name) \
102 { counters->count_of_FIXED_ARRAY_##name(), "count_of_FIXED_ARRAY_" #name } \
103 , {counters->size_of_FIXED_ARRAY_##name(), "size_of_FIXED_ARRAY_" #name},
104
105 FIXED_ARRAY_SUB_INSTANCE_TYPE_LIST(ADD_COUNTER)
106 #undef ADD_COUNTER
107 }; // End counter_list array.
108
109 for (size_t i = 0; i < arraysize(counter_list); i++) {
110 AddCounter(args.GetIsolate(), result, counter_list[i].counter,
111 counter_list[i].name);
112 }
113
114 struct StatisticNumber {
115 size_t number;
116 const char* name;
117 };
118
119 const StatisticNumber numbers[] = {
120 {heap->memory_allocator()->Size(), "total_committed_bytes"},
121 {heap->new_space()->Size(), "new_space_live_bytes"},
122 {heap->new_space()->Available(), "new_space_available_bytes"},
123 {heap->new_space()->CommittedMemory(), "new_space_commited_bytes"},
124 {heap->old_space()->Size(), "old_space_live_bytes"},
125 {heap->old_space()->Available(), "old_space_available_bytes"},
126 {heap->old_space()->CommittedMemory(), "old_space_commited_bytes"},
127 {heap->code_space()->Size(), "code_space_live_bytes"},
128 {heap->code_space()->Available(), "code_space_available_bytes"},
129 {heap->code_space()->CommittedMemory(), "code_space_commited_bytes"},
130 {heap->lo_space()->Size(), "lo_space_live_bytes"},
131 {heap->lo_space()->Available(), "lo_space_available_bytes"},
132 {heap->lo_space()->CommittedMemory(), "lo_space_commited_bytes"},
133 };
134
135 for (size_t i = 0; i < arraysize(numbers); i++) {
136 AddNumber(args.GetIsolate(), result, numbers[i].number, numbers[i].name);
137 }
138
139 AddNumber64(args.GetIsolate(), result, heap->external_memory(),
140 "amount_of_external_allocated_memory");
141 args.GetReturnValue().Set(result);
142
143 HeapIterator iterator(reinterpret_cast<Isolate*>(args.GetIsolate())->heap());
144 HeapObject* obj;
145 int reloc_info_total = 0;
146 int source_position_table_total = 0;
147 while ((obj = iterator.next())) {
148 if (obj->IsCode()) {
149 Code* code = Code::cast(obj);
150 reloc_info_total += code->relocation_info()->Size();
151 ByteArray* source_position_table = code->source_position_table();
152 if (source_position_table->length() > 0) {
153 source_position_table_total += code->source_position_table()->Size();
154 }
155 } else if (obj->IsBytecodeArray()) {
156 source_position_table_total +=
157 BytecodeArray::cast(obj)->source_position_table()->Size();
158 }
159 }
160
161 AddNumber(args.GetIsolate(), result, reloc_info_total,
162 "reloc_info_total_size");
163 AddNumber(args.GetIsolate(), result, source_position_table_total,
164 "source_position_table_total_size");
165 }
166
167 } // namespace internal
168 } // namespace v8
169