|
28 | 28 |
|
29 | 29 | #include <node.h> |
30 | 30 | #include <v8-profiler.h> |
| 31 | +#include "allocation-profile-node.hh" |
31 | 32 |
|
32 | 33 | namespace dd { |
33 | 34 |
|
@@ -55,17 +56,6 @@ static size_t NearHeapLimit(void* data, |
55 | 56 | static void InterruptCallback(v8::Isolate* isolate, void* data); |
56 | 57 | static void AsyncCallback(uv_async_t* handle); |
57 | 58 |
|
58 | | -struct Node { |
59 | | - using Allocation = v8::AllocationProfile::Allocation; |
60 | | - std::string name; |
61 | | - std::string script_name; |
62 | | - int line_number; |
63 | | - int column_number; |
64 | | - int script_id; |
65 | | - std::vector<std::shared_ptr<Node>> children; |
66 | | - std::vector<Allocation> allocations; |
67 | | -}; |
68 | | - |
69 | 59 | enum CallbackMode { |
70 | 60 | kNoCallback = 0, |
71 | 61 | kAsyncCallback = 1, |
@@ -139,73 +129,6 @@ struct HeapProfilerState { |
139 | 129 | bool insideCallback = false; |
140 | 130 | }; |
141 | 131 |
|
142 | | -std::shared_ptr<Node> TranslateAllocationProfileToCpp( |
143 | | - v8::AllocationProfile::Node* node) { |
144 | | - auto new_node = std::make_shared<Node>(); |
145 | | - new_node->line_number = node->line_number; |
146 | | - new_node->column_number = node->column_number; |
147 | | - new_node->script_id = node->script_id; |
148 | | - Nan::Utf8String name(node->name); |
149 | | - new_node->name.assign(*name, name.length()); |
150 | | - Nan::Utf8String script_name(node->script_name); |
151 | | - new_node->script_name.assign(*script_name, script_name.length()); |
152 | | - |
153 | | - new_node->children.reserve(node->children.size()); |
154 | | - for (auto& child : node->children) { |
155 | | - new_node->children.push_back(TranslateAllocationProfileToCpp(child)); |
156 | | - } |
157 | | - |
158 | | - new_node->allocations.reserve(node->allocations.size()); |
159 | | - for (auto& allocation : node->allocations) { |
160 | | - new_node->allocations.push_back(allocation); |
161 | | - } |
162 | | - return new_node; |
163 | | -} |
164 | | - |
165 | | -v8::Local<v8::Value> TranslateAllocationProfile(Node* node) { |
166 | | - v8::Local<v8::Object> js_node = Nan::New<v8::Object>(); |
167 | | - |
168 | | - Nan::Set(js_node, |
169 | | - Nan::New<v8::String>("name").ToLocalChecked(), |
170 | | - Nan::New(node->name).ToLocalChecked()); |
171 | | - Nan::Set(js_node, |
172 | | - Nan::New<v8::String>("scriptName").ToLocalChecked(), |
173 | | - Nan::New(node->script_name).ToLocalChecked()); |
174 | | - Nan::Set(js_node, |
175 | | - Nan::New<v8::String>("scriptId").ToLocalChecked(), |
176 | | - Nan::New<v8::Integer>(node->script_id)); |
177 | | - Nan::Set(js_node, |
178 | | - Nan::New<v8::String>("lineNumber").ToLocalChecked(), |
179 | | - Nan::New<v8::Integer>(node->line_number)); |
180 | | - Nan::Set(js_node, |
181 | | - Nan::New<v8::String>("columnNumber").ToLocalChecked(), |
182 | | - Nan::New<v8::Integer>(node->column_number)); |
183 | | - |
184 | | - v8::Local<v8::Array> children = Nan::New<v8::Array>(node->children.size()); |
185 | | - for (size_t i = 0; i < node->children.size(); i++) { |
186 | | - Nan::Set(children, i, TranslateAllocationProfile(node->children[i].get())); |
187 | | - } |
188 | | - Nan::Set( |
189 | | - js_node, Nan::New<v8::String>("children").ToLocalChecked(), children); |
190 | | - v8::Local<v8::Array> allocations = |
191 | | - Nan::New<v8::Array>(node->allocations.size()); |
192 | | - for (size_t i = 0; i < node->allocations.size(); i++) { |
193 | | - v8::AllocationProfile::Allocation alloc = node->allocations[i]; |
194 | | - v8::Local<v8::Object> js_alloc = Nan::New<v8::Object>(); |
195 | | - Nan::Set(js_alloc, |
196 | | - Nan::New<v8::String>("sizeBytes").ToLocalChecked(), |
197 | | - Nan::New<v8::Number>(alloc.size)); |
198 | | - Nan::Set(js_alloc, |
199 | | - Nan::New<v8::String>("count").ToLocalChecked(), |
200 | | - Nan::New<v8::Number>(alloc.count)); |
201 | | - Nan::Set(allocations, i, js_alloc); |
202 | | - } |
203 | | - Nan::Set(js_node, |
204 | | - Nan::New<v8::String>("allocations").ToLocalChecked(), |
205 | | - allocations); |
206 | | - return js_node; |
207 | | -} |
208 | | - |
209 | 132 | static void dumpAllocationProfile(FILE* file, |
210 | 133 | Node* node, |
211 | 134 | std::string& cur_stack) { |
@@ -582,6 +505,35 @@ NAN_METHOD(HeapProfiler::GetAllocationProfile) { |
582 | 505 | info.GetReturnValue().Set(TranslateAllocationProfile(root)); |
583 | 506 | } |
584 | 507 |
|
| 508 | +// mapAllocationProfile(callback): callback result |
| 509 | +NAN_METHOD(HeapProfiler::MapAllocationProfile) { |
| 510 | + if (info.Length() < 1 || !info[0]->IsFunction()) { |
| 511 | + return Nan::ThrowTypeError("mapAllocationProfile requires a callback"); |
| 512 | + } |
| 513 | + auto isolate = info.GetIsolate(); |
| 514 | + auto callback = info[0].As<v8::Function>(); |
| 515 | + |
| 516 | + std::unique_ptr<v8::AllocationProfile> profile( |
| 517 | + isolate->GetHeapProfiler()->GetAllocationProfile()); |
| 518 | + |
| 519 | + if (!profile) { |
| 520 | + return Nan::ThrowError("Heap profiler is not enabled."); |
| 521 | + } |
| 522 | + |
| 523 | + auto state = PerIsolateData::For(isolate)->GetHeapProfilerState(); |
| 524 | + if (state) { |
| 525 | + state->OnNewProfile(); |
| 526 | + } |
| 527 | + |
| 528 | + auto root = AllocationProfileNodeView::New(profile->GetRootNode()); |
| 529 | + v8::Local<v8::Value> argv[] = {root}; |
| 530 | + auto result = |
| 531 | + Nan::Call(callback, isolate->GetCurrentContext()->Global(), 1, argv); |
| 532 | + if (!result.IsEmpty()) { |
| 533 | + info.GetReturnValue().Set(result.ToLocalChecked()); |
| 534 | + } |
| 535 | +} |
| 536 | + |
585 | 537 | NAN_METHOD(HeapProfiler::MonitorOutOfMemory) { |
586 | 538 | if (info.Length() != 7) { |
587 | 539 | return Nan::ThrowTypeError("MonitorOOMCondition must have 7 arguments."); |
@@ -645,6 +597,7 @@ NAN_MODULE_INIT(HeapProfiler::Init) { |
645 | 597 | Nan::SetMethod( |
646 | 598 | heapProfiler, "stopSamplingHeapProfiler", StopSamplingHeapProfiler); |
647 | 599 | Nan::SetMethod(heapProfiler, "getAllocationProfile", GetAllocationProfile); |
| 600 | + Nan::SetMethod(heapProfiler, "mapAllocationProfile", MapAllocationProfile); |
648 | 601 | Nan::SetMethod(heapProfiler, "monitorOutOfMemory", MonitorOutOfMemory); |
649 | 602 | Nan::Set(target, |
650 | 603 | Nan::New<v8::String>("heapProfiler").ToLocalChecked(), |
|
0 commit comments