statistics-extension.cc 5.74 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5
#include "src/extensions/statistics-extension.h"
6

7
#include "src/common/assert-scope.h"
8
#include "src/execution/isolate.h"
9
#include "src/heap/heap-inl.h"  // crbug.com/v8/8499
10
#include "src/logging/counters.h"
11
#include "src/roots/roots.h"
12

13 14 15 16 17 18 19
namespace v8 {
namespace internal {

const char* const StatisticsExtension::kSource =
    "native function getV8Statistics();";


20 21
v8::Local<v8::FunctionTemplate> StatisticsExtension::GetNativeFunctionTemplate(
    v8::Isolate* isolate, v8::Local<v8::String> str) {
22
  DCHECK_EQ(strcmp(*v8::String::Utf8Value(isolate, str), "getV8Statistics"), 0);
23
  return v8::FunctionTemplate::New(isolate, StatisticsExtension::GetCounters);
24 25 26
}


27 28
static void AddCounter(v8::Isolate* isolate,
                       v8::Local<v8::Object> object,
29 30
                       StatsCounter* counter,
                       const char* name) {
31
  if (counter->Enabled()) {
32 33 34 35
    object
        ->Set(isolate->GetCurrentContext(),
              v8::String::NewFromUtf8(isolate, name).ToLocalChecked(),
              v8::Number::New(isolate, *counter->GetInternalPointer()))
36
        .FromJust();
37 38 39
  }
}

40 41 42 43
static void AddNumber(v8::Isolate* isolate, v8::Local<v8::Object> object,
                      double value, const char* name) {
  object
      ->Set(isolate->GetCurrentContext(),
44
            v8::String::NewFromUtf8(isolate, name).ToLocalChecked(),
45 46
            v8::Number::New(isolate, value))
      .FromJust();
47 48
}

49

50 51
static void AddNumber64(v8::Isolate* isolate,
                        v8::Local<v8::Object> object,
52 53
                        int64_t value,
                        const char* name) {
54 55 56 57 58
  object
      ->Set(isolate->GetCurrentContext(),
            v8::String::NewFromUtf8(isolate, name).ToLocalChecked(),
            v8::Number::New(isolate, static_cast<double>(value)))
      .FromJust();
59 60 61
}


62 63
void StatisticsExtension::GetCounters(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
64
  Isolate* isolate = reinterpret_cast<Isolate*>(args.GetIsolate());
65
  Heap* heap = isolate->heap();
66

67
  if (args.Length() > 0) {  // GC if first argument evaluates to true.
68
    if (args[0]->IsBoolean() && args[0]->BooleanValue(args.GetIsolate())) {
69 70
      heap->CollectAllGarbage(Heap::kNoGCFlags,
                              GarbageCollectionReason::kCountersExtension);
71 72 73 74
    }
  }

  Counters* counters = isolate->counters();
75
  v8::Local<v8::Object> result = v8::Object::New(args.GetIsolate());
76

77 78 79 80
  struct StatisticsCounter {
    v8::internal::StatsCounter* counter;
    const char* name;
  };
81
  // clang-format off
82
  const StatisticsCounter counter_list[] = {
83 84 85 86
#define ADD_COUNTER(name, caption) {counters->name(), #name},
      STATS_COUNTER_LIST_1(ADD_COUNTER)
      STATS_COUNTER_LIST_2(ADD_COUNTER)
      STATS_COUNTER_NATIVE_CODE_LIST(ADD_COUNTER)
87
#undef ADD_COUNTER
88
  };  // End counter_list array.
89
  // clang-format on
90 91 92 93 94 95 96

  for (size_t i = 0; i < arraysize(counter_list); i++) {
    AddCounter(args.GetIsolate(), result, counter_list[i].counter,
               counter_list[i].name);
  }

  struct StatisticNumber {
97
    size_t number;
98 99 100 101
    const char* name;
  };

  const StatisticNumber numbers[] = {
102
      {heap->memory_allocator()->Size(), "total_committed_bytes"},
103 104
      {heap->new_space()->Size(), "new_space_live_bytes"},
      {heap->new_space()->Available(), "new_space_available_bytes"},
105
      {heap->new_space()->CommittedMemory(), "new_space_commited_bytes"},
106 107
      {heap->old_space()->Size(), "old_space_live_bytes"},
      {heap->old_space()->Available(), "old_space_available_bytes"},
108
      {heap->old_space()->CommittedMemory(), "old_space_commited_bytes"},
109 110
      {heap->code_space()->Size(), "code_space_live_bytes"},
      {heap->code_space()->Available(), "code_space_available_bytes"},
111
      {heap->code_space()->CommittedMemory(), "code_space_commited_bytes"},
112 113
      {heap->lo_space()->Size(), "lo_space_live_bytes"},
      {heap->lo_space()->Available(), "lo_space_available_bytes"},
114
      {heap->lo_space()->CommittedMemory(), "lo_space_commited_bytes"},
115 116 117 118
      {heap->code_lo_space()->Size(), "code_lo_space_live_bytes"},
      {heap->code_lo_space()->Available(), "code_lo_space_available_bytes"},
      {heap->code_lo_space()->CommittedMemory(),
       "code_lo_space_commited_bytes"},
119 120 121 122 123
  };

  for (size_t i = 0; i < arraysize(numbers); i++) {
    AddNumber(args.GetIsolate(), result, numbers[i].number, numbers[i].name);
  }
124

125
  AddNumber64(args.GetIsolate(), result, heap->external_memory(),
126
              "amount_of_external_allocated_memory");
127
  args.GetReturnValue().Set(result);
128

129
  DisallowGarbageCollection no_gc;
130 131
  HeapObjectIterator iterator(
      reinterpret_cast<Isolate*>(args.GetIsolate())->heap());
132 133
  int reloc_info_total = 0;
  int source_position_table_total = 0;
134 135
  for (HeapObject obj = iterator.Next(); !obj.is_null();
       obj = iterator.Next()) {
136
    Object maybe_source_positions;
137
    if (obj.IsCode()) {
138
      Code code = Code::cast(obj);
139
      reloc_info_total += code.relocation_info().Size();
140
      maybe_source_positions = code.source_position_table();
141
    } else if (obj.IsBytecodeArray()) {
142 143 144 145
      maybe_source_positions =
          BytecodeArray::cast(obj).source_position_table(kAcquireLoad);
    } else {
      continue;
146
    }
147 148 149 150
    if (!maybe_source_positions.IsByteArray()) continue;
    ByteArray source_positions = ByteArray::cast(maybe_source_positions);
    if (source_positions.length() == 0) continue;
    source_position_table_total += source_positions.Size();
151 152 153 154 155 156
  }

  AddNumber(args.GetIsolate(), result, reloc_info_total,
            "reloc_info_total_size");
  AddNumber(args.GetIsolate(), result, source_position_table_total,
            "source_position_table_total_size");
157 158
}

159 160
}  // namespace internal
}  // namespace v8