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.h"
23 #include "env-inl.h"
24 #include "util-inl.h"
25 #include "v8.h"
26
27 namespace node {
28
29 using v8::Array;
30 using v8::ArrayBuffer;
31 using v8::Context;
32 using v8::FunctionCallbackInfo;
33 using v8::HeapCodeStatistics;
34 using v8::HeapSpaceStatistics;
35 using v8::HeapStatistics;
36 using v8::Integer;
37 using v8::Isolate;
38 using v8::Local;
39 using v8::NewStringType;
40 using v8::Object;
41 using v8::ScriptCompiler;
42 using v8::String;
43 using v8::Uint32;
44 using v8::V8;
45 using v8::Value;
46
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 const size_t kHeapStatisticsPropertiesCount =
63 HEAP_STATISTICS_PROPERTIES(V);
64 #undef V
65
66
67 #define HEAP_SPACE_STATISTICS_PROPERTIES(V) \
68 V(0, space_size, kSpaceSizeIndex) \
69 V(1, space_used_size, kSpaceUsedSizeIndex) \
70 V(2, space_available_size, kSpaceAvailableSizeIndex) \
71 V(3, physical_space_size, kPhysicalSpaceSizeIndex)
72
73 #define V(a, b, c) +1
74 static const size_t kHeapSpaceStatisticsPropertiesCount =
75 HEAP_SPACE_STATISTICS_PROPERTIES(V);
76 #undef V
77
78
79 #define HEAP_CODE_STATISTICS_PROPERTIES(V) \
80 V(0, code_and_metadata_size, kCodeAndMetadataSizeIndex) \
81 V(1, bytecode_and_metadata_size, kBytecodeAndMetadataSizeIndex) \
82 V(2, external_script_source_size, kExternalScriptSourceSizeIndex)
83
84 #define V(a, b, c) +1
85 static const size_t kHeapCodeStatisticsPropertiesCount =
86 HEAP_CODE_STATISTICS_PROPERTIES(V);
87 #undef V
88
CachedDataVersionTag(const FunctionCallbackInfo<Value> & args)89 void CachedDataVersionTag(const FunctionCallbackInfo<Value>& args) {
90 Environment* env = Environment::GetCurrent(args);
91 Local<Integer> result =
92 Integer::NewFromUnsigned(env->isolate(),
93 ScriptCompiler::CachedDataVersionTag());
94 args.GetReturnValue().Set(result);
95 }
96
97
UpdateHeapStatisticsArrayBuffer(const FunctionCallbackInfo<Value> & args)98 void UpdateHeapStatisticsArrayBuffer(const FunctionCallbackInfo<Value>& args) {
99 Environment* env = Environment::GetCurrent(args);
100 HeapStatistics s;
101 env->isolate()->GetHeapStatistics(&s);
102 double* const buffer = env->heap_statistics_buffer();
103 #define V(index, name, _) buffer[index] = static_cast<double>(s.name());
104 HEAP_STATISTICS_PROPERTIES(V)
105 #undef V
106 }
107
108
UpdateHeapSpaceStatisticsBuffer(const FunctionCallbackInfo<Value> & args)109 void UpdateHeapSpaceStatisticsBuffer(const FunctionCallbackInfo<Value>& args) {
110 Environment* env = Environment::GetCurrent(args);
111 HeapSpaceStatistics s;
112 Isolate* const isolate = env->isolate();
113 double* buffer = env->heap_space_statistics_buffer();
114 size_t number_of_heap_spaces = env->isolate()->NumberOfHeapSpaces();
115
116 for (size_t i = 0; i < number_of_heap_spaces; i++) {
117 isolate->GetHeapSpaceStatistics(&s, i);
118 size_t const property_offset = i * kHeapSpaceStatisticsPropertiesCount;
119 #define V(index, name, _) buffer[property_offset + index] = \
120 static_cast<double>(s.name());
121 HEAP_SPACE_STATISTICS_PROPERTIES(V)
122 #undef V
123 }
124 }
125
126
UpdateHeapCodeStatisticsArrayBuffer(const FunctionCallbackInfo<Value> & args)127 void UpdateHeapCodeStatisticsArrayBuffer(
128 const FunctionCallbackInfo<Value>& args) {
129 Environment* env = Environment::GetCurrent(args);
130 HeapCodeStatistics s;
131 env->isolate()->GetHeapCodeAndMetadataStatistics(&s);
132 double* const buffer = env->heap_code_statistics_buffer();
133 #define V(index, name, _) buffer[index] = static_cast<double>(s.name());
134 HEAP_CODE_STATISTICS_PROPERTIES(V)
135 #undef V
136 }
137
138
SetFlagsFromString(const FunctionCallbackInfo<Value> & args)139 void SetFlagsFromString(const FunctionCallbackInfo<Value>& args) {
140 CHECK(args[0]->IsString());
141 String::Utf8Value flags(args.GetIsolate(), args[0]);
142 V8::SetFlagsFromString(*flags, flags.length());
143 }
144
145
Initialize(Local<Object> target,Local<Value> unused,Local<Context> context,void * priv)146 void Initialize(Local<Object> target,
147 Local<Value> unused,
148 Local<Context> context,
149 void* priv) {
150 Environment* env = Environment::GetCurrent(context);
151
152 env->SetMethodNoSideEffect(target, "cachedDataVersionTag",
153 CachedDataVersionTag);
154
155 // Export symbols used by v8.getHeapStatistics()
156 env->SetMethod(target,
157 "updateHeapStatisticsArrayBuffer",
158 UpdateHeapStatisticsArrayBuffer);
159
160 env->set_heap_statistics_buffer(new double[kHeapStatisticsPropertiesCount]);
161
162 const size_t heap_statistics_buffer_byte_length =
163 sizeof(*env->heap_statistics_buffer()) * kHeapStatisticsPropertiesCount;
164
165 target->Set(env->context(),
166 FIXED_ONE_BYTE_STRING(env->isolate(),
167 "heapStatisticsArrayBuffer"),
168 ArrayBuffer::New(env->isolate(),
169 env->heap_statistics_buffer(),
170 heap_statistics_buffer_byte_length)).Check();
171
172 #define V(i, _, name) \
173 target->Set(env->context(), \
174 FIXED_ONE_BYTE_STRING(env->isolate(), #name), \
175 Uint32::NewFromUnsigned(env->isolate(), i)).Check();
176
177 HEAP_STATISTICS_PROPERTIES(V)
178 #undef V
179
180 // Export symbols used by v8.getHeapCodeStatistics()
181 env->SetMethod(target,
182 "updateHeapCodeStatisticsArrayBuffer",
183 UpdateHeapCodeStatisticsArrayBuffer);
184
185 env->set_heap_code_statistics_buffer(
186 new double[kHeapCodeStatisticsPropertiesCount]);
187
188 const size_t heap_code_statistics_buffer_byte_length =
189 sizeof(*env->heap_code_statistics_buffer())
190 * kHeapCodeStatisticsPropertiesCount;
191
192 target->Set(env->context(),
193 FIXED_ONE_BYTE_STRING(env->isolate(),
194 "heapCodeStatisticsArrayBuffer"),
195 ArrayBuffer::New(env->isolate(),
196 env->heap_code_statistics_buffer(),
197 heap_code_statistics_buffer_byte_length))
198 .Check();
199
200 #define V(i, _, name) \
201 target->Set(env->context(), \
202 FIXED_ONE_BYTE_STRING(env->isolate(), #name), \
203 Uint32::NewFromUnsigned(env->isolate(), i)).Check();
204
205 HEAP_CODE_STATISTICS_PROPERTIES(V)
206 #undef V
207
208 // Export symbols used by v8.getHeapSpaceStatistics()
209 target->Set(env->context(),
210 FIXED_ONE_BYTE_STRING(env->isolate(),
211 "kHeapSpaceStatisticsPropertiesCount"),
212 Uint32::NewFromUnsigned(env->isolate(),
213 kHeapSpaceStatisticsPropertiesCount))
214 .Check();
215
216 size_t number_of_heap_spaces = env->isolate()->NumberOfHeapSpaces();
217
218 // Heap space names are extracted once and exposed to JavaScript to
219 // avoid excessive creation of heap space name Strings.
220 HeapSpaceStatistics s;
221 MaybeStackBuffer<Local<Value>, 16> heap_spaces(number_of_heap_spaces);
222 for (size_t i = 0; i < number_of_heap_spaces; i++) {
223 env->isolate()->GetHeapSpaceStatistics(&s, i);
224 heap_spaces[i] = String::NewFromUtf8(env->isolate(),
225 s.space_name(),
226 NewStringType::kNormal)
227 .ToLocalChecked();
228 }
229 target->Set(env->context(),
230 FIXED_ONE_BYTE_STRING(env->isolate(), "kHeapSpaces"),
231 Array::New(env->isolate(),
232 heap_spaces.out(),
233 number_of_heap_spaces)).Check();
234
235 env->SetMethod(target,
236 "updateHeapSpaceStatisticsArrayBuffer",
237 UpdateHeapSpaceStatisticsBuffer);
238
239 env->set_heap_space_statistics_buffer(
240 new double[kHeapSpaceStatisticsPropertiesCount * number_of_heap_spaces]);
241
242 const size_t heap_space_statistics_buffer_byte_length =
243 sizeof(*env->heap_space_statistics_buffer()) *
244 kHeapSpaceStatisticsPropertiesCount *
245 number_of_heap_spaces;
246
247 target->Set(env->context(),
248 FIXED_ONE_BYTE_STRING(env->isolate(),
249 "heapSpaceStatisticsArrayBuffer"),
250 ArrayBuffer::New(env->isolate(),
251 env->heap_space_statistics_buffer(),
252 heap_space_statistics_buffer_byte_length))
253 .Check();
254
255 #define V(i, _, name) \
256 target->Set(env->context(), \
257 FIXED_ONE_BYTE_STRING(env->isolate(), #name), \
258 Uint32::NewFromUnsigned(env->isolate(), i)).Check();
259
260 HEAP_SPACE_STATISTICS_PROPERTIES(V)
261 #undef V
262
263 // Export symbols used by v8.setFlagsFromString()
264 env->SetMethod(target, "setFlagsFromString", SetFlagsFromString);
265 }
266
267 } // namespace node
268
269 NODE_MODULE_CONTEXT_AWARE_INTERNAL(v8, node::Initialize)
270