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