11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors. 21cb0ef41Sopenharmony_ci// 31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a 41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the 51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including 61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish, 71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit 81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the 91cb0ef41Sopenharmony_ci// following conditions: 101cb0ef41Sopenharmony_ci// 111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included 121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software. 131cb0ef41Sopenharmony_ci// 141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE. 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci#include "node_v8.h" 231cb0ef41Sopenharmony_ci#include "aliased_buffer-inl.h" 241cb0ef41Sopenharmony_ci#include "base_object-inl.h" 251cb0ef41Sopenharmony_ci#include "env-inl.h" 261cb0ef41Sopenharmony_ci#include "memory_tracker-inl.h" 271cb0ef41Sopenharmony_ci#include "node.h" 281cb0ef41Sopenharmony_ci#include "node_external_reference.h" 291cb0ef41Sopenharmony_ci#include "util-inl.h" 301cb0ef41Sopenharmony_ci#include "v8.h" 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_cinamespace node { 331cb0ef41Sopenharmony_cinamespace v8_utils { 341cb0ef41Sopenharmony_ciusing v8::Array; 351cb0ef41Sopenharmony_ciusing v8::Context; 361cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo; 371cb0ef41Sopenharmony_ciusing v8::FunctionTemplate; 381cb0ef41Sopenharmony_ciusing v8::HandleScope; 391cb0ef41Sopenharmony_ciusing v8::HeapCodeStatistics; 401cb0ef41Sopenharmony_ciusing v8::HeapSpaceStatistics; 411cb0ef41Sopenharmony_ciusing v8::HeapStatistics; 421cb0ef41Sopenharmony_ciusing v8::Integer; 431cb0ef41Sopenharmony_ciusing v8::Isolate; 441cb0ef41Sopenharmony_ciusing v8::Local; 451cb0ef41Sopenharmony_ciusing v8::Object; 461cb0ef41Sopenharmony_ciusing v8::ScriptCompiler; 471cb0ef41Sopenharmony_ciusing v8::String; 481cb0ef41Sopenharmony_ciusing v8::Uint32; 491cb0ef41Sopenharmony_ciusing v8::V8; 501cb0ef41Sopenharmony_ciusing v8::Value; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci#define HEAP_STATISTICS_PROPERTIES(V) \ 531cb0ef41Sopenharmony_ci V(0, total_heap_size, kTotalHeapSizeIndex) \ 541cb0ef41Sopenharmony_ci V(1, total_heap_size_executable, kTotalHeapSizeExecutableIndex) \ 551cb0ef41Sopenharmony_ci V(2, total_physical_size, kTotalPhysicalSizeIndex) \ 561cb0ef41Sopenharmony_ci V(3, total_available_size, kTotalAvailableSize) \ 571cb0ef41Sopenharmony_ci V(4, used_heap_size, kUsedHeapSizeIndex) \ 581cb0ef41Sopenharmony_ci V(5, heap_size_limit, kHeapSizeLimitIndex) \ 591cb0ef41Sopenharmony_ci V(6, malloced_memory, kMallocedMemoryIndex) \ 601cb0ef41Sopenharmony_ci V(7, peak_malloced_memory, kPeakMallocedMemoryIndex) \ 611cb0ef41Sopenharmony_ci V(8, does_zap_garbage, kDoesZapGarbageIndex) \ 621cb0ef41Sopenharmony_ci V(9, number_of_native_contexts, kNumberOfNativeContextsIndex) \ 631cb0ef41Sopenharmony_ci V(10, number_of_detached_contexts, kNumberOfDetachedContextsIndex) \ 641cb0ef41Sopenharmony_ci V(11, total_global_handles_size, kTotalGlobalHandlesSizeIndex) \ 651cb0ef41Sopenharmony_ci V(12, used_global_handles_size, kUsedGlobalHandlesSizeIndex) \ 661cb0ef41Sopenharmony_ci V(13, external_memory, kExternalMemoryIndex) 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci#define V(a, b, c) +1 691cb0ef41Sopenharmony_cistatic constexpr size_t kHeapStatisticsPropertiesCount = 701cb0ef41Sopenharmony_ci HEAP_STATISTICS_PROPERTIES(V); 711cb0ef41Sopenharmony_ci#undef V 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci#define HEAP_SPACE_STATISTICS_PROPERTIES(V) \ 741cb0ef41Sopenharmony_ci V(0, space_size, kSpaceSizeIndex) \ 751cb0ef41Sopenharmony_ci V(1, space_used_size, kSpaceUsedSizeIndex) \ 761cb0ef41Sopenharmony_ci V(2, space_available_size, kSpaceAvailableSizeIndex) \ 771cb0ef41Sopenharmony_ci V(3, physical_space_size, kPhysicalSpaceSizeIndex) 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci#define V(a, b, c) +1 801cb0ef41Sopenharmony_cistatic constexpr size_t kHeapSpaceStatisticsPropertiesCount = 811cb0ef41Sopenharmony_ci HEAP_SPACE_STATISTICS_PROPERTIES(V); 821cb0ef41Sopenharmony_ci#undef V 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci#define HEAP_CODE_STATISTICS_PROPERTIES(V) \ 851cb0ef41Sopenharmony_ci V(0, code_and_metadata_size, kCodeAndMetadataSizeIndex) \ 861cb0ef41Sopenharmony_ci V(1, bytecode_and_metadata_size, kBytecodeAndMetadataSizeIndex) \ 871cb0ef41Sopenharmony_ci V(2, external_script_source_size, kExternalScriptSourceSizeIndex) \ 881cb0ef41Sopenharmony_ci V(3, cpu_profiler_metadata_size, kCPUProfilerMetaDataSizeIndex) 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci#define V(a, b, c) +1 911cb0ef41Sopenharmony_cistatic const size_t kHeapCodeStatisticsPropertiesCount = 921cb0ef41Sopenharmony_ci HEAP_CODE_STATISTICS_PROPERTIES(V); 931cb0ef41Sopenharmony_ci#undef V 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ciBindingData::BindingData(Realm* realm, Local<Object> obj) 961cb0ef41Sopenharmony_ci : SnapshotableObject(realm, obj, type_int), 971cb0ef41Sopenharmony_ci heap_statistics_buffer(realm->isolate(), kHeapStatisticsPropertiesCount), 981cb0ef41Sopenharmony_ci heap_space_statistics_buffer(realm->isolate(), 991cb0ef41Sopenharmony_ci kHeapSpaceStatisticsPropertiesCount), 1001cb0ef41Sopenharmony_ci heap_code_statistics_buffer(realm->isolate(), 1011cb0ef41Sopenharmony_ci kHeapCodeStatisticsPropertiesCount) { 1021cb0ef41Sopenharmony_ci Local<Context> context = realm->context(); 1031cb0ef41Sopenharmony_ci obj->Set(context, 1041cb0ef41Sopenharmony_ci FIXED_ONE_BYTE_STRING(realm->isolate(), "heapStatisticsBuffer"), 1051cb0ef41Sopenharmony_ci heap_statistics_buffer.GetJSArray()) 1061cb0ef41Sopenharmony_ci .Check(); 1071cb0ef41Sopenharmony_ci obj->Set(context, 1081cb0ef41Sopenharmony_ci FIXED_ONE_BYTE_STRING(realm->isolate(), "heapCodeStatisticsBuffer"), 1091cb0ef41Sopenharmony_ci heap_code_statistics_buffer.GetJSArray()) 1101cb0ef41Sopenharmony_ci .Check(); 1111cb0ef41Sopenharmony_ci obj->Set(context, 1121cb0ef41Sopenharmony_ci FIXED_ONE_BYTE_STRING(realm->isolate(), "heapSpaceStatisticsBuffer"), 1131cb0ef41Sopenharmony_ci heap_space_statistics_buffer.GetJSArray()) 1141cb0ef41Sopenharmony_ci .Check(); 1151cb0ef41Sopenharmony_ci} 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_cibool BindingData::PrepareForSerialization(Local<Context> context, 1181cb0ef41Sopenharmony_ci v8::SnapshotCreator* creator) { 1191cb0ef41Sopenharmony_ci // We'll just re-initialize the buffers in the constructor since their 1201cb0ef41Sopenharmony_ci // contents can be thrown away once consumed in the previous call. 1211cb0ef41Sopenharmony_ci heap_statistics_buffer.Release(); 1221cb0ef41Sopenharmony_ci heap_space_statistics_buffer.Release(); 1231cb0ef41Sopenharmony_ci heap_code_statistics_buffer.Release(); 1241cb0ef41Sopenharmony_ci // Return true because we need to maintain the reference to the binding from 1251cb0ef41Sopenharmony_ci // JS land. 1261cb0ef41Sopenharmony_ci return true; 1271cb0ef41Sopenharmony_ci} 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_civoid BindingData::Deserialize(Local<Context> context, 1301cb0ef41Sopenharmony_ci Local<Object> holder, 1311cb0ef41Sopenharmony_ci int index, 1321cb0ef41Sopenharmony_ci InternalFieldInfoBase* info) { 1331cb0ef41Sopenharmony_ci DCHECK_EQ(index, BaseObject::kEmbedderType); 1341cb0ef41Sopenharmony_ci HandleScope scope(context->GetIsolate()); 1351cb0ef41Sopenharmony_ci Realm* realm = Realm::GetCurrent(context); 1361cb0ef41Sopenharmony_ci BindingData* binding = realm->AddBindingData<BindingData>(context, holder); 1371cb0ef41Sopenharmony_ci CHECK_NOT_NULL(binding); 1381cb0ef41Sopenharmony_ci} 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ciInternalFieldInfoBase* BindingData::Serialize(int index) { 1411cb0ef41Sopenharmony_ci DCHECK_EQ(index, BaseObject::kEmbedderType); 1421cb0ef41Sopenharmony_ci InternalFieldInfo* info = 1431cb0ef41Sopenharmony_ci InternalFieldInfoBase::New<InternalFieldInfo>(type()); 1441cb0ef41Sopenharmony_ci return info; 1451cb0ef41Sopenharmony_ci} 1461cb0ef41Sopenharmony_ci 1471cb0ef41Sopenharmony_civoid BindingData::MemoryInfo(MemoryTracker* tracker) const { 1481cb0ef41Sopenharmony_ci tracker->TrackField("heap_statistics_buffer", heap_statistics_buffer); 1491cb0ef41Sopenharmony_ci tracker->TrackField("heap_space_statistics_buffer", 1501cb0ef41Sopenharmony_ci heap_space_statistics_buffer); 1511cb0ef41Sopenharmony_ci tracker->TrackField("heap_code_statistics_buffer", 1521cb0ef41Sopenharmony_ci heap_code_statistics_buffer); 1531cb0ef41Sopenharmony_ci} 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_civoid CachedDataVersionTag(const FunctionCallbackInfo<Value>& args) { 1561cb0ef41Sopenharmony_ci Environment* env = Environment::GetCurrent(args); 1571cb0ef41Sopenharmony_ci Local<Integer> result = 1581cb0ef41Sopenharmony_ci Integer::NewFromUnsigned(env->isolate(), 1591cb0ef41Sopenharmony_ci ScriptCompiler::CachedDataVersionTag()); 1601cb0ef41Sopenharmony_ci args.GetReturnValue().Set(result); 1611cb0ef41Sopenharmony_ci} 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_civoid SetHeapSnapshotNearHeapLimit(const FunctionCallbackInfo<Value>& args) { 1641cb0ef41Sopenharmony_ci CHECK(args[0]->IsUint32()); 1651cb0ef41Sopenharmony_ci Environment* env = Environment::GetCurrent(args); 1661cb0ef41Sopenharmony_ci uint32_t limit = args[0].As<v8::Uint32>()->Value(); 1671cb0ef41Sopenharmony_ci CHECK_GT(limit, 0); 1681cb0ef41Sopenharmony_ci env->AddHeapSnapshotNearHeapLimitCallback(); 1691cb0ef41Sopenharmony_ci env->set_heap_snapshot_near_heap_limit(limit); 1701cb0ef41Sopenharmony_ci} 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_civoid UpdateHeapStatisticsBuffer(const FunctionCallbackInfo<Value>& args) { 1731cb0ef41Sopenharmony_ci BindingData* data = Realm::GetBindingData<BindingData>(args); 1741cb0ef41Sopenharmony_ci HeapStatistics s; 1751cb0ef41Sopenharmony_ci args.GetIsolate()->GetHeapStatistics(&s); 1761cb0ef41Sopenharmony_ci AliasedFloat64Array& buffer = data->heap_statistics_buffer; 1771cb0ef41Sopenharmony_ci#define V(index, name, _) buffer[index] = static_cast<double>(s.name()); 1781cb0ef41Sopenharmony_ci HEAP_STATISTICS_PROPERTIES(V) 1791cb0ef41Sopenharmony_ci#undef V 1801cb0ef41Sopenharmony_ci} 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_civoid UpdateHeapSpaceStatisticsBuffer(const FunctionCallbackInfo<Value>& args) { 1841cb0ef41Sopenharmony_ci BindingData* data = Realm::GetBindingData<BindingData>(args); 1851cb0ef41Sopenharmony_ci HeapSpaceStatistics s; 1861cb0ef41Sopenharmony_ci Isolate* const isolate = args.GetIsolate(); 1871cb0ef41Sopenharmony_ci CHECK(args[0]->IsUint32()); 1881cb0ef41Sopenharmony_ci size_t space_index = static_cast<size_t>(args[0].As<v8::Uint32>()->Value()); 1891cb0ef41Sopenharmony_ci isolate->GetHeapSpaceStatistics(&s, space_index); 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_ci AliasedFloat64Array& buffer = data->heap_space_statistics_buffer; 1921cb0ef41Sopenharmony_ci 1931cb0ef41Sopenharmony_ci#define V(index, name, _) buffer[index] = static_cast<double>(s.name()); 1941cb0ef41Sopenharmony_ci HEAP_SPACE_STATISTICS_PROPERTIES(V) 1951cb0ef41Sopenharmony_ci#undef V 1961cb0ef41Sopenharmony_ci} 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_civoid UpdateHeapCodeStatisticsBuffer(const FunctionCallbackInfo<Value>& args) { 1991cb0ef41Sopenharmony_ci BindingData* data = Realm::GetBindingData<BindingData>(args); 2001cb0ef41Sopenharmony_ci HeapCodeStatistics s; 2011cb0ef41Sopenharmony_ci args.GetIsolate()->GetHeapCodeAndMetadataStatistics(&s); 2021cb0ef41Sopenharmony_ci AliasedFloat64Array& buffer = data->heap_code_statistics_buffer; 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci#define V(index, name, _) buffer[index] = static_cast<double>(s.name()); 2051cb0ef41Sopenharmony_ci HEAP_CODE_STATISTICS_PROPERTIES(V) 2061cb0ef41Sopenharmony_ci#undef V 2071cb0ef41Sopenharmony_ci} 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_civoid SetFlagsFromString(const FunctionCallbackInfo<Value>& args) { 2111cb0ef41Sopenharmony_ci CHECK(args[0]->IsString()); 2121cb0ef41Sopenharmony_ci String::Utf8Value flags(args.GetIsolate(), args[0]); 2131cb0ef41Sopenharmony_ci V8::SetFlagsFromString(*flags, static_cast<size_t>(flags.length())); 2141cb0ef41Sopenharmony_ci} 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_cistatic const char* GetGCTypeName(v8::GCType gc_type) { 2171cb0ef41Sopenharmony_ci switch (gc_type) { 2181cb0ef41Sopenharmony_ci case v8::GCType::kGCTypeScavenge: 2191cb0ef41Sopenharmony_ci return "Scavenge"; 2201cb0ef41Sopenharmony_ci case v8::GCType::kGCTypeMarkSweepCompact: 2211cb0ef41Sopenharmony_ci return "MarkSweepCompact"; 2221cb0ef41Sopenharmony_ci case v8::GCType::kGCTypeIncrementalMarking: 2231cb0ef41Sopenharmony_ci return "IncrementalMarking"; 2241cb0ef41Sopenharmony_ci case v8::GCType::kGCTypeProcessWeakCallbacks: 2251cb0ef41Sopenharmony_ci return "ProcessWeakCallbacks"; 2261cb0ef41Sopenharmony_ci default: 2271cb0ef41Sopenharmony_ci return "Unknown"; 2281cb0ef41Sopenharmony_ci } 2291cb0ef41Sopenharmony_ci} 2301cb0ef41Sopenharmony_ci 2311cb0ef41Sopenharmony_cistatic void SetHeapStatistics(JSONWriter* writer, Isolate* isolate) { 2321cb0ef41Sopenharmony_ci HeapStatistics heap_statistics; 2331cb0ef41Sopenharmony_ci isolate->GetHeapStatistics(&heap_statistics); 2341cb0ef41Sopenharmony_ci writer->json_objectstart("heapStatistics"); 2351cb0ef41Sopenharmony_ci writer->json_keyvalue("totalHeapSize", heap_statistics.total_heap_size()); 2361cb0ef41Sopenharmony_ci writer->json_keyvalue("totalHeapSizeExecutable", 2371cb0ef41Sopenharmony_ci heap_statistics.total_heap_size_executable()); 2381cb0ef41Sopenharmony_ci writer->json_keyvalue("totalPhysicalSize", 2391cb0ef41Sopenharmony_ci heap_statistics.total_physical_size()); 2401cb0ef41Sopenharmony_ci writer->json_keyvalue("totalAvailableSize", 2411cb0ef41Sopenharmony_ci heap_statistics.total_available_size()); 2421cb0ef41Sopenharmony_ci writer->json_keyvalue("totalGlobalHandlesSize", 2431cb0ef41Sopenharmony_ci heap_statistics.total_global_handles_size()); 2441cb0ef41Sopenharmony_ci writer->json_keyvalue("usedGlobalHandlesSize", 2451cb0ef41Sopenharmony_ci heap_statistics.used_global_handles_size()); 2461cb0ef41Sopenharmony_ci writer->json_keyvalue("usedHeapSize", heap_statistics.used_heap_size()); 2471cb0ef41Sopenharmony_ci writer->json_keyvalue("heapSizeLimit", heap_statistics.heap_size_limit()); 2481cb0ef41Sopenharmony_ci writer->json_keyvalue("mallocedMemory", heap_statistics.malloced_memory()); 2491cb0ef41Sopenharmony_ci writer->json_keyvalue("externalMemory", heap_statistics.external_memory()); 2501cb0ef41Sopenharmony_ci writer->json_keyvalue("peakMallocedMemory", 2511cb0ef41Sopenharmony_ci heap_statistics.peak_malloced_memory()); 2521cb0ef41Sopenharmony_ci writer->json_objectend(); 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ci int space_count = isolate->NumberOfHeapSpaces(); 2551cb0ef41Sopenharmony_ci writer->json_arraystart("heapSpaceStatistics"); 2561cb0ef41Sopenharmony_ci for (int i = 0; i < space_count; i++) { 2571cb0ef41Sopenharmony_ci HeapSpaceStatistics heap_space_statistics; 2581cb0ef41Sopenharmony_ci isolate->GetHeapSpaceStatistics(&heap_space_statistics, i); 2591cb0ef41Sopenharmony_ci writer->json_start(); 2601cb0ef41Sopenharmony_ci writer->json_keyvalue("spaceName", heap_space_statistics.space_name()); 2611cb0ef41Sopenharmony_ci writer->json_keyvalue("spaceSize", heap_space_statistics.space_size()); 2621cb0ef41Sopenharmony_ci writer->json_keyvalue("spaceUsedSize", 2631cb0ef41Sopenharmony_ci heap_space_statistics.space_used_size()); 2641cb0ef41Sopenharmony_ci writer->json_keyvalue("spaceAvailableSize", 2651cb0ef41Sopenharmony_ci heap_space_statistics.space_available_size()); 2661cb0ef41Sopenharmony_ci writer->json_keyvalue("physicalSpaceSize", 2671cb0ef41Sopenharmony_ci heap_space_statistics.physical_space_size()); 2681cb0ef41Sopenharmony_ci writer->json_end(); 2691cb0ef41Sopenharmony_ci } 2701cb0ef41Sopenharmony_ci writer->json_arrayend(); 2711cb0ef41Sopenharmony_ci} 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_cistatic void BeforeGCCallback(Isolate* isolate, 2741cb0ef41Sopenharmony_ci v8::GCType gc_type, 2751cb0ef41Sopenharmony_ci v8::GCCallbackFlags flags, 2761cb0ef41Sopenharmony_ci void* data) { 2771cb0ef41Sopenharmony_ci GCProfiler* profiler = static_cast<GCProfiler*>(data); 2781cb0ef41Sopenharmony_ci if (profiler->current_gc_type != 0) { 2791cb0ef41Sopenharmony_ci return; 2801cb0ef41Sopenharmony_ci } 2811cb0ef41Sopenharmony_ci JSONWriter* writer = profiler->writer(); 2821cb0ef41Sopenharmony_ci writer->json_start(); 2831cb0ef41Sopenharmony_ci writer->json_keyvalue("gcType", GetGCTypeName(gc_type)); 2841cb0ef41Sopenharmony_ci writer->json_objectstart("beforeGC"); 2851cb0ef41Sopenharmony_ci SetHeapStatistics(writer, isolate); 2861cb0ef41Sopenharmony_ci writer->json_objectend(); 2871cb0ef41Sopenharmony_ci profiler->current_gc_type = gc_type; 2881cb0ef41Sopenharmony_ci profiler->start_time = uv_hrtime(); 2891cb0ef41Sopenharmony_ci} 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_cistatic void AfterGCCallback(Isolate* isolate, 2921cb0ef41Sopenharmony_ci v8::GCType gc_type, 2931cb0ef41Sopenharmony_ci v8::GCCallbackFlags flags, 2941cb0ef41Sopenharmony_ci void* data) { 2951cb0ef41Sopenharmony_ci GCProfiler* profiler = static_cast<GCProfiler*>(data); 2961cb0ef41Sopenharmony_ci if (profiler->current_gc_type != gc_type) { 2971cb0ef41Sopenharmony_ci return; 2981cb0ef41Sopenharmony_ci } 2991cb0ef41Sopenharmony_ci JSONWriter* writer = profiler->writer(); 3001cb0ef41Sopenharmony_ci profiler->current_gc_type = 0; 3011cb0ef41Sopenharmony_ci writer->json_keyvalue("cost", (uv_hrtime() - profiler->start_time) / 1e3); 3021cb0ef41Sopenharmony_ci profiler->start_time = 0; 3031cb0ef41Sopenharmony_ci writer->json_objectstart("afterGC"); 3041cb0ef41Sopenharmony_ci SetHeapStatistics(writer, isolate); 3051cb0ef41Sopenharmony_ci writer->json_objectend(); 3061cb0ef41Sopenharmony_ci writer->json_end(); 3071cb0ef41Sopenharmony_ci} 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ciGCProfiler::GCProfiler(Environment* env, Local<Object> object) 3101cb0ef41Sopenharmony_ci : BaseObject(env, object), 3111cb0ef41Sopenharmony_ci start_time(0), 3121cb0ef41Sopenharmony_ci current_gc_type(0), 3131cb0ef41Sopenharmony_ci state(GCProfilerState::kInitialized), 3141cb0ef41Sopenharmony_ci writer_(out_stream_, false) { 3151cb0ef41Sopenharmony_ci MakeWeak(); 3161cb0ef41Sopenharmony_ci} 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci// This function will be called when 3191cb0ef41Sopenharmony_ci// 1. StartGCProfile and StopGCProfile are called and 3201cb0ef41Sopenharmony_ci// JS land does not keep the object anymore. 3211cb0ef41Sopenharmony_ci// 2. StartGCProfile is called then the env exits before 3221cb0ef41Sopenharmony_ci// StopGCProfile is called. 3231cb0ef41Sopenharmony_ciGCProfiler::~GCProfiler() { 3241cb0ef41Sopenharmony_ci if (state != GCProfiler::GCProfilerState::kInitialized) { 3251cb0ef41Sopenharmony_ci env()->isolate()->RemoveGCPrologueCallback(BeforeGCCallback, this); 3261cb0ef41Sopenharmony_ci env()->isolate()->RemoveGCEpilogueCallback(AfterGCCallback, this); 3271cb0ef41Sopenharmony_ci } 3281cb0ef41Sopenharmony_ci} 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_ciJSONWriter* GCProfiler::writer() { 3311cb0ef41Sopenharmony_ci return &writer_; 3321cb0ef41Sopenharmony_ci} 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_cistd::ostringstream* GCProfiler::out_stream() { 3351cb0ef41Sopenharmony_ci return &out_stream_; 3361cb0ef41Sopenharmony_ci} 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_civoid GCProfiler::New(const FunctionCallbackInfo<Value>& args) { 3391cb0ef41Sopenharmony_ci CHECK(args.IsConstructCall()); 3401cb0ef41Sopenharmony_ci Environment* env = Environment::GetCurrent(args); 3411cb0ef41Sopenharmony_ci new GCProfiler(env, args.This()); 3421cb0ef41Sopenharmony_ci} 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_civoid GCProfiler::Start(const FunctionCallbackInfo<Value>& args) { 3451cb0ef41Sopenharmony_ci Environment* env = Environment::GetCurrent(args); 3461cb0ef41Sopenharmony_ci GCProfiler* profiler; 3471cb0ef41Sopenharmony_ci ASSIGN_OR_RETURN_UNWRAP(&profiler, args.Holder()); 3481cb0ef41Sopenharmony_ci if (profiler->state != GCProfiler::GCProfilerState::kInitialized) { 3491cb0ef41Sopenharmony_ci return; 3501cb0ef41Sopenharmony_ci } 3511cb0ef41Sopenharmony_ci profiler->writer()->json_start(); 3521cb0ef41Sopenharmony_ci profiler->writer()->json_keyvalue("version", 1); 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ci uv_timeval64_t ts; 3551cb0ef41Sopenharmony_ci if (uv_gettimeofday(&ts) == 0) { 3561cb0ef41Sopenharmony_ci profiler->writer()->json_keyvalue("startTime", 3571cb0ef41Sopenharmony_ci ts.tv_sec * 1000 + ts.tv_usec / 1000); 3581cb0ef41Sopenharmony_ci } else { 3591cb0ef41Sopenharmony_ci profiler->writer()->json_keyvalue("startTime", 0); 3601cb0ef41Sopenharmony_ci } 3611cb0ef41Sopenharmony_ci profiler->writer()->json_arraystart("statistics"); 3621cb0ef41Sopenharmony_ci env->isolate()->AddGCPrologueCallback(BeforeGCCallback, 3631cb0ef41Sopenharmony_ci static_cast<void*>(profiler)); 3641cb0ef41Sopenharmony_ci env->isolate()->AddGCEpilogueCallback(AfterGCCallback, 3651cb0ef41Sopenharmony_ci static_cast<void*>(profiler)); 3661cb0ef41Sopenharmony_ci profiler->state = GCProfiler::GCProfilerState::kStarted; 3671cb0ef41Sopenharmony_ci} 3681cb0ef41Sopenharmony_ci 3691cb0ef41Sopenharmony_civoid GCProfiler::Stop(const FunctionCallbackInfo<v8::Value>& args) { 3701cb0ef41Sopenharmony_ci Environment* env = Environment::GetCurrent(args); 3711cb0ef41Sopenharmony_ci GCProfiler* profiler; 3721cb0ef41Sopenharmony_ci ASSIGN_OR_RETURN_UNWRAP(&profiler, args.Holder()); 3731cb0ef41Sopenharmony_ci if (profiler->state != GCProfiler::GCProfilerState::kStarted) { 3741cb0ef41Sopenharmony_ci return; 3751cb0ef41Sopenharmony_ci } 3761cb0ef41Sopenharmony_ci profiler->writer()->json_arrayend(); 3771cb0ef41Sopenharmony_ci uv_timeval64_t ts; 3781cb0ef41Sopenharmony_ci if (uv_gettimeofday(&ts) == 0) { 3791cb0ef41Sopenharmony_ci profiler->writer()->json_keyvalue("endTime", 3801cb0ef41Sopenharmony_ci ts.tv_sec * 1000 + ts.tv_usec / 1000); 3811cb0ef41Sopenharmony_ci } else { 3821cb0ef41Sopenharmony_ci profiler->writer()->json_keyvalue("endTime", 0); 3831cb0ef41Sopenharmony_ci } 3841cb0ef41Sopenharmony_ci profiler->writer()->json_end(); 3851cb0ef41Sopenharmony_ci profiler->state = GCProfiler::GCProfilerState::kStopped; 3861cb0ef41Sopenharmony_ci auto string = profiler->out_stream()->str(); 3871cb0ef41Sopenharmony_ci args.GetReturnValue().Set(String::NewFromUtf8(env->isolate(), 3881cb0ef41Sopenharmony_ci string.data(), 3891cb0ef41Sopenharmony_ci v8::NewStringType::kNormal, 3901cb0ef41Sopenharmony_ci string.size()) 3911cb0ef41Sopenharmony_ci .ToLocalChecked()); 3921cb0ef41Sopenharmony_ci} 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_civoid Initialize(Local<Object> target, 3951cb0ef41Sopenharmony_ci Local<Value> unused, 3961cb0ef41Sopenharmony_ci Local<Context> context, 3971cb0ef41Sopenharmony_ci void* priv) { 3981cb0ef41Sopenharmony_ci Realm* realm = Realm::GetCurrent(context); 3991cb0ef41Sopenharmony_ci Environment* env = realm->env(); 4001cb0ef41Sopenharmony_ci BindingData* const binding_data = 4011cb0ef41Sopenharmony_ci realm->AddBindingData<BindingData>(context, target); 4021cb0ef41Sopenharmony_ci if (binding_data == nullptr) return; 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci SetMethodNoSideEffect( 4051cb0ef41Sopenharmony_ci context, target, "cachedDataVersionTag", CachedDataVersionTag); 4061cb0ef41Sopenharmony_ci SetMethodNoSideEffect(context, 4071cb0ef41Sopenharmony_ci target, 4081cb0ef41Sopenharmony_ci "setHeapSnapshotNearHeapLimit", 4091cb0ef41Sopenharmony_ci SetHeapSnapshotNearHeapLimit); 4101cb0ef41Sopenharmony_ci SetMethod(context, 4111cb0ef41Sopenharmony_ci target, 4121cb0ef41Sopenharmony_ci "updateHeapStatisticsBuffer", 4131cb0ef41Sopenharmony_ci UpdateHeapStatisticsBuffer); 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_ci SetMethod(context, 4161cb0ef41Sopenharmony_ci target, 4171cb0ef41Sopenharmony_ci "updateHeapCodeStatisticsBuffer", 4181cb0ef41Sopenharmony_ci UpdateHeapCodeStatisticsBuffer); 4191cb0ef41Sopenharmony_ci 4201cb0ef41Sopenharmony_ci size_t number_of_heap_spaces = env->isolate()->NumberOfHeapSpaces(); 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci // Heap space names are extracted once and exposed to JavaScript to 4231cb0ef41Sopenharmony_ci // avoid excessive creation of heap space name Strings. 4241cb0ef41Sopenharmony_ci HeapSpaceStatistics s; 4251cb0ef41Sopenharmony_ci MaybeStackBuffer<Local<Value>, 16> heap_spaces(number_of_heap_spaces); 4261cb0ef41Sopenharmony_ci for (size_t i = 0; i < number_of_heap_spaces; i++) { 4271cb0ef41Sopenharmony_ci env->isolate()->GetHeapSpaceStatistics(&s, i); 4281cb0ef41Sopenharmony_ci heap_spaces[i] = String::NewFromUtf8(env->isolate(), s.space_name()) 4291cb0ef41Sopenharmony_ci .ToLocalChecked(); 4301cb0ef41Sopenharmony_ci } 4311cb0ef41Sopenharmony_ci target 4321cb0ef41Sopenharmony_ci ->Set( 4331cb0ef41Sopenharmony_ci context, 4341cb0ef41Sopenharmony_ci FIXED_ONE_BYTE_STRING(env->isolate(), "kHeapSpaces"), 4351cb0ef41Sopenharmony_ci Array::New(env->isolate(), heap_spaces.out(), number_of_heap_spaces)) 4361cb0ef41Sopenharmony_ci .Check(); 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_ci SetMethod(context, 4391cb0ef41Sopenharmony_ci target, 4401cb0ef41Sopenharmony_ci "updateHeapSpaceStatisticsBuffer", 4411cb0ef41Sopenharmony_ci UpdateHeapSpaceStatisticsBuffer); 4421cb0ef41Sopenharmony_ci 4431cb0ef41Sopenharmony_ci#define V(i, _, name) \ 4441cb0ef41Sopenharmony_ci target \ 4451cb0ef41Sopenharmony_ci ->Set(context, \ 4461cb0ef41Sopenharmony_ci FIXED_ONE_BYTE_STRING(env->isolate(), #name), \ 4471cb0ef41Sopenharmony_ci Uint32::NewFromUnsigned(env->isolate(), i)) \ 4481cb0ef41Sopenharmony_ci .Check(); 4491cb0ef41Sopenharmony_ci 4501cb0ef41Sopenharmony_ci HEAP_STATISTICS_PROPERTIES(V) 4511cb0ef41Sopenharmony_ci HEAP_CODE_STATISTICS_PROPERTIES(V) 4521cb0ef41Sopenharmony_ci HEAP_SPACE_STATISTICS_PROPERTIES(V) 4531cb0ef41Sopenharmony_ci#undef V 4541cb0ef41Sopenharmony_ci 4551cb0ef41Sopenharmony_ci // Export symbols used by v8.setFlagsFromString() 4561cb0ef41Sopenharmony_ci SetMethod(context, target, "setFlagsFromString", SetFlagsFromString); 4571cb0ef41Sopenharmony_ci 4581cb0ef41Sopenharmony_ci // GCProfiler 4591cb0ef41Sopenharmony_ci Local<FunctionTemplate> t = 4601cb0ef41Sopenharmony_ci NewFunctionTemplate(env->isolate(), GCProfiler::New); 4611cb0ef41Sopenharmony_ci t->InstanceTemplate()->SetInternalFieldCount(BaseObject::kInternalFieldCount); 4621cb0ef41Sopenharmony_ci SetProtoMethod(env->isolate(), t, "start", GCProfiler::Start); 4631cb0ef41Sopenharmony_ci SetProtoMethod(env->isolate(), t, "stop", GCProfiler::Stop); 4641cb0ef41Sopenharmony_ci SetConstructorFunction(context, target, "GCProfiler", t); 4651cb0ef41Sopenharmony_ci} 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_civoid RegisterExternalReferences(ExternalReferenceRegistry* registry) { 4681cb0ef41Sopenharmony_ci registry->Register(CachedDataVersionTag); 4691cb0ef41Sopenharmony_ci registry->Register(UpdateHeapStatisticsBuffer); 4701cb0ef41Sopenharmony_ci registry->Register(UpdateHeapCodeStatisticsBuffer); 4711cb0ef41Sopenharmony_ci registry->Register(UpdateHeapSpaceStatisticsBuffer); 4721cb0ef41Sopenharmony_ci registry->Register(SetFlagsFromString); 4731cb0ef41Sopenharmony_ci registry->Register(SetHeapSnapshotNearHeapLimit); 4741cb0ef41Sopenharmony_ci registry->Register(GCProfiler::New); 4751cb0ef41Sopenharmony_ci registry->Register(GCProfiler::Start); 4761cb0ef41Sopenharmony_ci registry->Register(GCProfiler::Stop); 4771cb0ef41Sopenharmony_ci} 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci} // namespace v8_utils 4801cb0ef41Sopenharmony_ci} // namespace node 4811cb0ef41Sopenharmony_ci 4821cb0ef41Sopenharmony_ciNODE_BINDING_CONTEXT_AWARE_INTERNAL(v8, node::v8_utils::Initialize) 4831cb0ef41Sopenharmony_ciNODE_BINDING_EXTERNAL_REFERENCE(v8, node::v8_utils::RegisterExternalReferences) 484