@@ -42,6 +42,8 @@ using v8::HeapStatistics;
42
42
using v8::Integer;
43
43
using v8::Isolate;
44
44
using v8::Local;
45
+ using v8::LocalVector;
46
+ using v8::Name;
45
47
using v8::Object;
46
48
using v8::ScriptCompiler;
47
49
using v8::String;
@@ -295,6 +297,164 @@ static void SetHeapStatistics(JSONWriter* writer, Isolate* isolate) {
295
297
writer->json_arrayend ();
296
298
}
297
299
300
+ static Local<Object> ConvertHeapStatsToJSObject (
301
+ Isolate* isolate, const cppgc::HeapStatistics& stats) {
302
+ Local<Context> context = isolate->GetCurrentContext ();
303
+ // Space Statistics
304
+ LocalVector<Value> space_statistics_array (isolate);
305
+ for (size_t i = 0 ; i < stats.space_stats .size (); i++) {
306
+ const cppgc::HeapStatistics::SpaceStatistics& space_stats =
307
+ stats.space_stats [i];
308
+ // Page Statistics
309
+ LocalVector<Value> page_statistics_array (isolate);
310
+ for (size_t j = 0 ; j < space_stats.page_stats .size (); j++) {
311
+ const cppgc::HeapStatistics::PageStatistics& page_stats =
312
+ space_stats.page_stats [j];
313
+ // Object Statistics
314
+ LocalVector<Value> object_statistics_array (isolate);
315
+ for (size_t k = 0 ; k < page_stats.object_statistics .size (); k++) {
316
+ const cppgc::HeapStatistics::ObjectStatsEntry& object_stats =
317
+ page_stats.object_statistics [k];
318
+ Local<Name> object_stats_names[] = {
319
+ FIXED_ONE_BYTE_STRING (isolate, " allocated_bytes" ),
320
+ FIXED_ONE_BYTE_STRING (isolate, " object_count" )};
321
+ Local<Value> object_stats_values[] = {
322
+ Uint32::NewFromUnsigned (
323
+ isolate, static_cast <uint32_t >(object_stats.allocated_bytes )),
324
+ Uint32::NewFromUnsigned (
325
+ isolate, static_cast <uint32_t >(object_stats.object_count ))};
326
+ Local<Object> object_stats_object =
327
+ Object::New (isolate,
328
+ Null (isolate),
329
+ object_stats_names,
330
+ object_stats_values,
331
+ arraysize (object_stats_names));
332
+ object_statistics_array.emplace_back (object_stats_object);
333
+ }
334
+
335
+ // Set page statistics
336
+ Local<Name> page_stats_names[] = {
337
+ FIXED_ONE_BYTE_STRING (isolate, " committed_size_bytes" ),
338
+ FIXED_ONE_BYTE_STRING (isolate, " resident_size_bytes" ),
339
+ FIXED_ONE_BYTE_STRING (isolate, " used_size_bytes" ),
340
+ FIXED_ONE_BYTE_STRING (isolate, " object_statistics" )};
341
+ Local<Value> page_stats_values[] = {
342
+ Uint32::NewFromUnsigned (
343
+ isolate, static_cast <uint32_t >(page_stats.committed_size_bytes )),
344
+ Uint32::NewFromUnsigned (
345
+ isolate, static_cast <uint32_t >(page_stats.resident_size_bytes )),
346
+ Uint32::NewFromUnsigned (
347
+ isolate, static_cast <uint32_t >(page_stats.used_size_bytes )),
348
+ Array::New (isolate,
349
+ object_statistics_array.data (),
350
+ object_statistics_array.size ())};
351
+ Local<Object> page_stats_object =
352
+ Object::New (isolate,
353
+ Null (isolate),
354
+ page_stats_names,
355
+ page_stats_values,
356
+ arraysize (page_stats_names));
357
+ page_statistics_array.emplace_back (page_stats_object);
358
+ }
359
+
360
+ // Free List Statistics
361
+ Local<Name> free_list_statistics_names[] = {
362
+ FIXED_ONE_BYTE_STRING (isolate, " bucket_size" ),
363
+ FIXED_ONE_BYTE_STRING (isolate, " free_count" ),
364
+ FIXED_ONE_BYTE_STRING (isolate, " free_size" )};
365
+ Local<Value> free_list_statistics_values[] = {
366
+ ToV8Value (context, space_stats.free_list_stats .bucket_size , isolate)
367
+ .ToLocalChecked (),
368
+ ToV8Value (context, space_stats.free_list_stats .free_count , isolate)
369
+ .ToLocalChecked (),
370
+ ToV8Value (context, space_stats.free_list_stats .free_size , isolate)
371
+ .ToLocalChecked ()};
372
+ Local<Object> free_list_statistics_obj =
373
+ Object::New (isolate,
374
+ Null (isolate),
375
+ free_list_statistics_names,
376
+ free_list_statistics_values,
377
+ arraysize (free_list_statistics_names));
378
+
379
+ // Set Space Statistics
380
+ Local<Name> space_stats_names[] = {
381
+ FIXED_ONE_BYTE_STRING (isolate, " name" ),
382
+ FIXED_ONE_BYTE_STRING (isolate, " committed_size_bytes" ),
383
+ FIXED_ONE_BYTE_STRING (isolate, " resident_size_bytes" ),
384
+ FIXED_ONE_BYTE_STRING (isolate, " used_size_bytes" ),
385
+ FIXED_ONE_BYTE_STRING (isolate, " page_stats" ),
386
+ FIXED_ONE_BYTE_STRING (isolate, " free_list_stats" )};
387
+ Local<Value> space_stats_values[] = {
388
+ ToV8Value (context, stats.space_stats [i].name .c_str (), isolate)
389
+ .ToLocalChecked (),
390
+ Uint32::NewFromUnsigned (
391
+ isolate,
392
+ static_cast <uint32_t >(stats.space_stats [i].committed_size_bytes )),
393
+ Uint32::NewFromUnsigned (
394
+ isolate,
395
+ static_cast <uint32_t >(stats.space_stats [i].resident_size_bytes )),
396
+ Uint32::NewFromUnsigned (
397
+ isolate,
398
+ static_cast <uint32_t >(stats.space_stats [i].used_size_bytes )),
399
+ Array::New (isolate,
400
+ page_statistics_array.data (),
401
+ page_statistics_array.size ()),
402
+ free_list_statistics_obj,
403
+ };
404
+ Local<Object> space_stats_object =
405
+ Object::New (isolate,
406
+ Null (isolate),
407
+ space_stats_names,
408
+ space_stats_values,
409
+ arraysize (space_stats_names));
410
+ space_statistics_array.emplace_back (space_stats_object);
411
+ }
412
+
413
+ // Set heap statistics
414
+ Local<Name> heap_statistics_names[] = {
415
+ FIXED_ONE_BYTE_STRING (isolate, " committed_size_bytes" ),
416
+ FIXED_ONE_BYTE_STRING (isolate, " resident_size_bytes" ),
417
+ FIXED_ONE_BYTE_STRING (isolate, " used_size_bytes" ),
418
+ FIXED_ONE_BYTE_STRING (isolate, " space_statistics" ),
419
+ FIXED_ONE_BYTE_STRING (isolate, " type_names" )};
420
+
421
+ Local<Value> heap_statistics_values[] = {
422
+ Uint32::NewFromUnsigned (
423
+ isolate, static_cast <uint32_t >(stats.committed_size_bytes )),
424
+ Uint32::NewFromUnsigned (isolate,
425
+ static_cast <uint32_t >(stats.resident_size_bytes )),
426
+ Uint32::NewFromUnsigned (isolate,
427
+ static_cast <uint32_t >(stats.used_size_bytes )),
428
+ Array::New (isolate,
429
+ space_statistics_array.data (),
430
+ space_statistics_array.size ()),
431
+ ToV8Value (context, stats.type_names , isolate).ToLocalChecked ()};
432
+
433
+ Local<Object> heap_statistics_object =
434
+ Object::New (isolate,
435
+ Null (isolate),
436
+ heap_statistics_names,
437
+ heap_statistics_values,
438
+ arraysize (heap_statistics_names));
439
+
440
+ return heap_statistics_object;
441
+ }
442
+
443
+ static void getCppHeapStatistics (const FunctionCallbackInfo<Value>& args) {
444
+ Isolate* isolate = args.GetIsolate ();
445
+ HandleScope handle_scope (isolate);
446
+
447
+ CHECK_EQ (args.Length (), 1 );
448
+ CHECK (args[0 ]->IsInt32 ());
449
+
450
+ cppgc::HeapStatistics stats = isolate->GetCppHeap ()->CollectStatistics (
451
+ static_cast <cppgc::HeapStatistics::DetailLevel>(
452
+ args[0 ].As <v8::Int32>()->Value ()));
453
+
454
+ Local<Object> result = ConvertHeapStatsToJSObject (isolate, stats);
455
+ args.GetReturnValue ().Set (result);
456
+ }
457
+
298
458
static void BeforeGCCallback (Isolate* isolate,
299
459
v8::GCType gc_type,
300
460
v8::GCCallbackFlags flags,
@@ -440,6 +600,7 @@ void Initialize(Local<Object> target,
440
600
target,
441
601
" updateHeapCodeStatisticsBuffer" ,
442
602
UpdateHeapCodeStatisticsBuffer);
603
+ SetMethod (context, target, " getCppHeapStatistics" , getCppHeapStatistics);
443
604
444
605
size_t number_of_heap_spaces = env->isolate ()->NumberOfHeapSpaces ();
445
606
@@ -486,6 +647,18 @@ void Initialize(Local<Object> target,
486
647
SetProtoMethod (env->isolate (), t, " start" , GCProfiler::Start);
487
648
SetProtoMethod (env->isolate (), t, " stop" , GCProfiler::Stop);
488
649
SetConstructorFunction (context, target, " GCProfiler" , t);
650
+
651
+ {
652
+ Isolate* isolate = env->isolate ();
653
+ Local<Object> detail_level = Object::New (isolate);
654
+ cppgc::HeapStatistics::DetailLevel DETAILED =
655
+ cppgc::HeapStatistics::DetailLevel::kDetailed ;
656
+ cppgc::HeapStatistics::DetailLevel BRIEF =
657
+ cppgc::HeapStatistics::DetailLevel::kBrief ;
658
+ NODE_DEFINE_CONSTANT (detail_level, DETAILED);
659
+ NODE_DEFINE_CONSTANT (detail_level, BRIEF);
660
+ READONLY_PROPERTY (target, " detailLevel" , detail_level);
661
+ }
489
662
}
490
663
491
664
void RegisterExternalReferences (ExternalReferenceRegistry* registry) {
@@ -498,6 +671,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
498
671
registry->Register (GCProfiler::New);
499
672
registry->Register (GCProfiler::Start);
500
673
registry->Register (GCProfiler::Stop);
674
+ registry->Register (getCppHeapStatistics);
501
675
}
502
676
503
677
} // namespace v8_utils
0 commit comments