• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright Joyent, Inc. and other Node contributors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a
4 // copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to permit
8 // persons to whom the Software is furnished to do so, subject to the
9 // following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included
12 // in all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 // USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 #include "node_v8.h"
23 #include "base_object-inl.h"
24 #include "env-inl.h"
25 #include "memory_tracker-inl.h"
26 #include "node.h"
27 #include "util-inl.h"
28 #include "v8.h"
29 
30 namespace node {
31 namespace v8_utils {
32 using v8::Array;
33 using v8::Context;
34 using v8::FunctionCallbackInfo;
35 using v8::HeapCodeStatistics;
36 using v8::HeapSpaceStatistics;
37 using v8::HeapStatistics;
38 using v8::Integer;
39 using v8::Isolate;
40 using v8::Local;
41 using v8::Object;
42 using v8::ScriptCompiler;
43 using v8::String;
44 using v8::Uint32;
45 using v8::V8;
46 using v8::Value;
47 
48 #define HEAP_STATISTICS_PROPERTIES(V)                                         \
49   V(0, total_heap_size, kTotalHeapSizeIndex)                                  \
50   V(1, total_heap_size_executable, kTotalHeapSizeExecutableIndex)             \
51   V(2, total_physical_size, kTotalPhysicalSizeIndex)                          \
52   V(3, total_available_size, kTotalAvailableSize)                             \
53   V(4, used_heap_size, kUsedHeapSizeIndex)                                    \
54   V(5, heap_size_limit, kHeapSizeLimitIndex)                                  \
55   V(6, malloced_memory, kMallocedMemoryIndex)                                 \
56   V(7, peak_malloced_memory, kPeakMallocedMemoryIndex)                        \
57   V(8, does_zap_garbage, kDoesZapGarbageIndex)                                \
58   V(9, number_of_native_contexts, kNumberOfNativeContextsIndex)               \
59   V(10, number_of_detached_contexts, kNumberOfDetachedContextsIndex)
60 
61 #define V(a, b, c) +1
62 static constexpr size_t kHeapStatisticsPropertiesCount =
63     HEAP_STATISTICS_PROPERTIES(V);
64 #undef V
65 
66 #define HEAP_SPACE_STATISTICS_PROPERTIES(V)                                   \
67   V(0, space_size, kSpaceSizeIndex)                                           \
68   V(1, space_used_size, kSpaceUsedSizeIndex)                                  \
69   V(2, space_available_size, kSpaceAvailableSizeIndex)                        \
70   V(3, physical_space_size, kPhysicalSpaceSizeIndex)
71 
72 #define V(a, b, c) +1
73 static constexpr size_t kHeapSpaceStatisticsPropertiesCount =
74     HEAP_SPACE_STATISTICS_PROPERTIES(V);
75 #undef V
76 
77 #define HEAP_CODE_STATISTICS_PROPERTIES(V)                                     \
78   V(0, code_and_metadata_size, kCodeAndMetadataSizeIndex)                      \
79   V(1, bytecode_and_metadata_size, kBytecodeAndMetadataSizeIndex)              \
80   V(2, external_script_source_size, kExternalScriptSourceSizeIndex)
81 
82 #define V(a, b, c) +1
83 static const size_t kHeapCodeStatisticsPropertiesCount =
84     HEAP_CODE_STATISTICS_PROPERTIES(V);
85 #undef V
86 
BindingData(Environment * env,Local<Object> obj)87 BindingData::BindingData(Environment* env, Local<Object> obj)
88     : BaseObject(env, obj),
89       heap_statistics_buffer(env->isolate(), kHeapStatisticsPropertiesCount),
90       heap_space_statistics_buffer(env->isolate(),
91                                    kHeapSpaceStatisticsPropertiesCount),
92       heap_code_statistics_buffer(env->isolate(),
93                                   kHeapCodeStatisticsPropertiesCount) {
94   obj->Set(env->context(),
95            FIXED_ONE_BYTE_STRING(env->isolate(), "heapStatisticsBuffer"),
96            heap_statistics_buffer.GetJSArray())
97       .Check();
98   obj->Set(env->context(),
99            FIXED_ONE_BYTE_STRING(env->isolate(), "heapCodeStatisticsBuffer"),
100            heap_code_statistics_buffer.GetJSArray())
101       .Check();
102   obj->Set(env->context(),
103            FIXED_ONE_BYTE_STRING(env->isolate(), "heapSpaceStatisticsBuffer"),
104            heap_space_statistics_buffer.GetJSArray())
105       .Check();
106 }
107 
MemoryInfo(MemoryTracker * tracker) const108 void BindingData::MemoryInfo(MemoryTracker* tracker) const {
109   tracker->TrackField("heap_statistics_buffer", heap_statistics_buffer);
110   tracker->TrackField("heap_space_statistics_buffer",
111                       heap_space_statistics_buffer);
112   tracker->TrackField("heap_code_statistics_buffer",
113                       heap_code_statistics_buffer);
114 }
115 
116 // TODO(addaleax): Remove once we're on C++17.
117 constexpr FastStringKey BindingData::type_name;
118 
CachedDataVersionTag(const FunctionCallbackInfo<Value> & args)119 void CachedDataVersionTag(const FunctionCallbackInfo<Value>& args) {
120   Environment* env = Environment::GetCurrent(args);
121   Local<Integer> result =
122       Integer::NewFromUnsigned(env->isolate(),
123                                ScriptCompiler::CachedDataVersionTag());
124   args.GetReturnValue().Set(result);
125 }
126 
UpdateHeapStatisticsBuffer(const FunctionCallbackInfo<Value> & args)127 void UpdateHeapStatisticsBuffer(const FunctionCallbackInfo<Value>& args) {
128   BindingData* data = Environment::GetBindingData<BindingData>(args);
129   HeapStatistics s;
130   args.GetIsolate()->GetHeapStatistics(&s);
131   AliasedFloat64Array& buffer = data->heap_statistics_buffer;
132 #define V(index, name, _) buffer[index] = static_cast<double>(s.name());
133   HEAP_STATISTICS_PROPERTIES(V)
134 #undef V
135 }
136 
137 
UpdateHeapSpaceStatisticsBuffer(const FunctionCallbackInfo<Value> & args)138 void UpdateHeapSpaceStatisticsBuffer(const FunctionCallbackInfo<Value>& args) {
139   BindingData* data = Environment::GetBindingData<BindingData>(args);
140   HeapSpaceStatistics s;
141   Isolate* const isolate = args.GetIsolate();
142   CHECK(args[0]->IsUint32());
143   size_t space_index = static_cast<size_t>(args[0].As<v8::Uint32>()->Value());
144   isolate->GetHeapSpaceStatistics(&s, space_index);
145 
146   AliasedFloat64Array& buffer = data->heap_space_statistics_buffer;
147 
148 #define V(index, name, _) buffer[index] = static_cast<double>(s.name());
149   HEAP_SPACE_STATISTICS_PROPERTIES(V)
150 #undef V
151 }
152 
UpdateHeapCodeStatisticsBuffer(const FunctionCallbackInfo<Value> & args)153 void UpdateHeapCodeStatisticsBuffer(const FunctionCallbackInfo<Value>& args) {
154   BindingData* data = Environment::GetBindingData<BindingData>(args);
155   HeapCodeStatistics s;
156   args.GetIsolate()->GetHeapCodeAndMetadataStatistics(&s);
157   AliasedFloat64Array& buffer = data->heap_code_statistics_buffer;
158 
159 #define V(index, name, _) buffer[index] = static_cast<double>(s.name());
160   HEAP_CODE_STATISTICS_PROPERTIES(V)
161 #undef V
162 }
163 
164 
SetFlagsFromString(const FunctionCallbackInfo<Value> & args)165 void SetFlagsFromString(const FunctionCallbackInfo<Value>& args) {
166   CHECK(args[0]->IsString());
167   String::Utf8Value flags(args.GetIsolate(), args[0]);
168   V8::SetFlagsFromString(*flags, static_cast<size_t>(flags.length()));
169 }
170 
171 
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)172 void Initialize(Local<Object> target,
173                 Local<Value> unused,
174                 Local<Context> context,
175                 void* priv) {
176   Environment* env = Environment::GetCurrent(context);
177   BindingData* const binding_data =
178       env->AddBindingData<BindingData>(context, target);
179   if (binding_data == nullptr) return;
180 
181   env->SetMethodNoSideEffect(target, "cachedDataVersionTag",
182                              CachedDataVersionTag);
183   env->SetMethod(
184       target, "updateHeapStatisticsBuffer", UpdateHeapStatisticsBuffer);
185 
186   env->SetMethod(
187       target, "updateHeapCodeStatisticsBuffer", UpdateHeapCodeStatisticsBuffer);
188 
189   size_t number_of_heap_spaces = env->isolate()->NumberOfHeapSpaces();
190 
191   // Heap space names are extracted once and exposed to JavaScript to
192   // avoid excessive creation of heap space name Strings.
193   HeapSpaceStatistics s;
194   MaybeStackBuffer<Local<Value>, 16> heap_spaces(number_of_heap_spaces);
195   for (size_t i = 0; i < number_of_heap_spaces; i++) {
196     env->isolate()->GetHeapSpaceStatistics(&s, i);
197     heap_spaces[i] = String::NewFromUtf8(env->isolate(), s.space_name())
198                                              .ToLocalChecked();
199   }
200   target->Set(env->context(),
201               FIXED_ONE_BYTE_STRING(env->isolate(), "kHeapSpaces"),
202               Array::New(env->isolate(),
203                          heap_spaces.out(),
204                          number_of_heap_spaces)).Check();
205 
206   env->SetMethod(target,
207                  "updateHeapSpaceStatisticsBuffer",
208                  UpdateHeapSpaceStatisticsBuffer);
209 
210 #define V(i, _, name)                                                          \
211   target                                                                       \
212       ->Set(env->context(),                                                    \
213             FIXED_ONE_BYTE_STRING(env->isolate(), #name),                      \
214             Uint32::NewFromUnsigned(env->isolate(), i))                        \
215       .Check();
216 
217   HEAP_STATISTICS_PROPERTIES(V)
218   HEAP_CODE_STATISTICS_PROPERTIES(V)
219   HEAP_SPACE_STATISTICS_PROPERTIES(V)
220 #undef V
221 
222   // Export symbols used by v8.setFlagsFromString()
223   env->SetMethod(target, "setFlagsFromString", SetFlagsFromString);
224 }
225 
226 }  // namespace v8_utils
227 }  // namespace node
228 
229 NODE_MODULE_CONTEXT_AWARE_INTERNAL(v8, node::v8_utils::Initialize)
230