11cb0ef41Sopenharmony_ci// Copyright 2016 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/inspector/v8-heap-profiler-agent-impl.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "include/v8-context.h" 81cb0ef41Sopenharmony_ci#include "include/v8-inspector.h" 91cb0ef41Sopenharmony_ci#include "include/v8-platform.h" 101cb0ef41Sopenharmony_ci#include "include/v8-profiler.h" 111cb0ef41Sopenharmony_ci#include "include/v8-version.h" 121cb0ef41Sopenharmony_ci#include "src/base/platform/mutex.h" 131cb0ef41Sopenharmony_ci#include "src/inspector/injected-script.h" 141cb0ef41Sopenharmony_ci#include "src/inspector/inspected-context.h" 151cb0ef41Sopenharmony_ci#include "src/inspector/protocol/Protocol.h" 161cb0ef41Sopenharmony_ci#include "src/inspector/string-util.h" 171cb0ef41Sopenharmony_ci#include "src/inspector/v8-debugger.h" 181cb0ef41Sopenharmony_ci#include "src/inspector/v8-inspector-impl.h" 191cb0ef41Sopenharmony_ci#include "src/inspector/v8-inspector-session-impl.h" 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_cinamespace v8_inspector { 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_cinamespace { 241cb0ef41Sopenharmony_ci 251cb0ef41Sopenharmony_cinamespace HeapProfilerAgentState { 261cb0ef41Sopenharmony_cistatic const char heapProfilerEnabled[] = "heapProfilerEnabled"; 271cb0ef41Sopenharmony_cistatic const char heapObjectsTrackingEnabled[] = "heapObjectsTrackingEnabled"; 281cb0ef41Sopenharmony_cistatic const char allocationTrackingEnabled[] = "allocationTrackingEnabled"; 291cb0ef41Sopenharmony_cistatic const char samplingHeapProfilerEnabled[] = "samplingHeapProfilerEnabled"; 301cb0ef41Sopenharmony_cistatic const char samplingHeapProfilerInterval[] = 311cb0ef41Sopenharmony_ci "samplingHeapProfilerInterval"; 321cb0ef41Sopenharmony_ci} // namespace HeapProfilerAgentState 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ciclass HeapSnapshotProgress final : public v8::ActivityControl { 351cb0ef41Sopenharmony_ci public: 361cb0ef41Sopenharmony_ci explicit HeapSnapshotProgress(protocol::HeapProfiler::Frontend* frontend) 371cb0ef41Sopenharmony_ci : m_frontend(frontend) {} 381cb0ef41Sopenharmony_ci ControlOption ReportProgressValue(uint32_t done, uint32_t total) override { 391cb0ef41Sopenharmony_ci m_frontend->reportHeapSnapshotProgress(done, total, 401cb0ef41Sopenharmony_ci protocol::Maybe<bool>()); 411cb0ef41Sopenharmony_ci if (done >= total) { 421cb0ef41Sopenharmony_ci m_frontend->reportHeapSnapshotProgress(total, total, true); 431cb0ef41Sopenharmony_ci } 441cb0ef41Sopenharmony_ci m_frontend->flush(); 451cb0ef41Sopenharmony_ci return kContinue; 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci private: 491cb0ef41Sopenharmony_ci protocol::HeapProfiler::Frontend* m_frontend; 501cb0ef41Sopenharmony_ci}; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ciclass GlobalObjectNameResolver final 531cb0ef41Sopenharmony_ci : public v8::HeapProfiler::ObjectNameResolver { 541cb0ef41Sopenharmony_ci public: 551cb0ef41Sopenharmony_ci explicit GlobalObjectNameResolver(V8InspectorSessionImpl* session) 561cb0ef41Sopenharmony_ci : m_offset(0), m_strings(10000), m_session(session) {} 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci const char* GetName(v8::Local<v8::Object> object) override { 591cb0ef41Sopenharmony_ci v8::Local<v8::Context> creationContext; 601cb0ef41Sopenharmony_ci if (!object->GetCreationContext().ToLocal(&creationContext)) { 611cb0ef41Sopenharmony_ci return ""; 621cb0ef41Sopenharmony_ci } 631cb0ef41Sopenharmony_ci InspectedContext* context = m_session->inspector()->getContext( 641cb0ef41Sopenharmony_ci m_session->contextGroupId(), 651cb0ef41Sopenharmony_ci InspectedContext::contextId(creationContext)); 661cb0ef41Sopenharmony_ci if (!context) return ""; 671cb0ef41Sopenharmony_ci String16 name = context->origin(); 681cb0ef41Sopenharmony_ci size_t length = name.length(); 691cb0ef41Sopenharmony_ci if (m_offset + length + 1 >= m_strings.size()) return ""; 701cb0ef41Sopenharmony_ci for (size_t i = 0; i < length; ++i) { 711cb0ef41Sopenharmony_ci UChar ch = name[i]; 721cb0ef41Sopenharmony_ci m_strings[m_offset + i] = ch > 0xFF ? '?' : static_cast<char>(ch); 731cb0ef41Sopenharmony_ci } 741cb0ef41Sopenharmony_ci m_strings[m_offset + length] = '\0'; 751cb0ef41Sopenharmony_ci char* result = &*m_strings.begin() + m_offset; 761cb0ef41Sopenharmony_ci m_offset += length + 1; 771cb0ef41Sopenharmony_ci return result; 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci private: 811cb0ef41Sopenharmony_ci size_t m_offset; 821cb0ef41Sopenharmony_ci std::vector<char> m_strings; 831cb0ef41Sopenharmony_ci V8InspectorSessionImpl* m_session; 841cb0ef41Sopenharmony_ci}; 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_ciclass HeapSnapshotOutputStream final : public v8::OutputStream { 871cb0ef41Sopenharmony_ci public: 881cb0ef41Sopenharmony_ci explicit HeapSnapshotOutputStream(protocol::HeapProfiler::Frontend* frontend) 891cb0ef41Sopenharmony_ci : m_frontend(frontend) {} 901cb0ef41Sopenharmony_ci void EndOfStream() override {} 911cb0ef41Sopenharmony_ci int GetChunkSize() override { return 102400; } 921cb0ef41Sopenharmony_ci WriteResult WriteAsciiChunk(char* data, int size) override { 931cb0ef41Sopenharmony_ci m_frontend->addHeapSnapshotChunk(String16(data, size)); 941cb0ef41Sopenharmony_ci m_frontend->flush(); 951cb0ef41Sopenharmony_ci return kContinue; 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci private: 991cb0ef41Sopenharmony_ci protocol::HeapProfiler::Frontend* m_frontend; 1001cb0ef41Sopenharmony_ci}; 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_civ8::Local<v8::Object> objectByHeapObjectId(v8::Isolate* isolate, int id) { 1031cb0ef41Sopenharmony_ci v8::HeapProfiler* profiler = isolate->GetHeapProfiler(); 1041cb0ef41Sopenharmony_ci v8::Local<v8::Value> value = profiler->FindObjectById(id); 1051cb0ef41Sopenharmony_ci if (value.IsEmpty() || !value->IsObject()) return v8::Local<v8::Object>(); 1061cb0ef41Sopenharmony_ci return value.As<v8::Object>(); 1071cb0ef41Sopenharmony_ci} 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ciclass InspectableHeapObject final : public V8InspectorSession::Inspectable { 1101cb0ef41Sopenharmony_ci public: 1111cb0ef41Sopenharmony_ci explicit InspectableHeapObject(int heapObjectId) 1121cb0ef41Sopenharmony_ci : m_heapObjectId(heapObjectId) {} 1131cb0ef41Sopenharmony_ci v8::Local<v8::Value> get(v8::Local<v8::Context> context) override { 1141cb0ef41Sopenharmony_ci return objectByHeapObjectId(context->GetIsolate(), m_heapObjectId); 1151cb0ef41Sopenharmony_ci } 1161cb0ef41Sopenharmony_ci 1171cb0ef41Sopenharmony_ci private: 1181cb0ef41Sopenharmony_ci int m_heapObjectId; 1191cb0ef41Sopenharmony_ci}; 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ciclass HeapStatsStream final : public v8::OutputStream { 1221cb0ef41Sopenharmony_ci public: 1231cb0ef41Sopenharmony_ci explicit HeapStatsStream(protocol::HeapProfiler::Frontend* frontend) 1241cb0ef41Sopenharmony_ci : m_frontend(frontend) {} 1251cb0ef41Sopenharmony_ci 1261cb0ef41Sopenharmony_ci void EndOfStream() override {} 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci WriteResult WriteAsciiChunk(char* data, int size) override { 1291cb0ef41Sopenharmony_ci DCHECK(false); 1301cb0ef41Sopenharmony_ci return kAbort; 1311cb0ef41Sopenharmony_ci } 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci WriteResult WriteHeapStatsChunk(v8::HeapStatsUpdate* updateData, 1341cb0ef41Sopenharmony_ci int count) override { 1351cb0ef41Sopenharmony_ci DCHECK_GT(count, 0); 1361cb0ef41Sopenharmony_ci auto statsDiff = std::make_unique<protocol::Array<int>>(); 1371cb0ef41Sopenharmony_ci for (int i = 0; i < count; ++i) { 1381cb0ef41Sopenharmony_ci statsDiff->emplace_back(updateData[i].index); 1391cb0ef41Sopenharmony_ci statsDiff->emplace_back(updateData[i].count); 1401cb0ef41Sopenharmony_ci statsDiff->emplace_back(updateData[i].size); 1411cb0ef41Sopenharmony_ci } 1421cb0ef41Sopenharmony_ci m_frontend->heapStatsUpdate(std::move(statsDiff)); 1431cb0ef41Sopenharmony_ci return kContinue; 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci private: 1471cb0ef41Sopenharmony_ci protocol::HeapProfiler::Frontend* m_frontend; 1481cb0ef41Sopenharmony_ci}; 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci} // namespace 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_cistruct V8HeapProfilerAgentImpl::AsyncGC { 1531cb0ef41Sopenharmony_ci v8::base::Mutex m_mutex; 1541cb0ef41Sopenharmony_ci bool m_canceled = false; 1551cb0ef41Sopenharmony_ci bool m_pending = false; 1561cb0ef41Sopenharmony_ci std::vector<std::unique_ptr<CollectGarbageCallback>> m_pending_callbacks; 1571cb0ef41Sopenharmony_ci}; 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ciclass V8HeapProfilerAgentImpl::GCTask : public v8::Task { 1601cb0ef41Sopenharmony_ci public: 1611cb0ef41Sopenharmony_ci GCTask(v8::Isolate* isolate, std::shared_ptr<AsyncGC> async_gc) 1621cb0ef41Sopenharmony_ci : m_isolate(isolate), m_async_gc(async_gc) {} 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci void Run() override { 1651cb0ef41Sopenharmony_ci std::shared_ptr<AsyncGC> async_gc = m_async_gc.lock(); 1661cb0ef41Sopenharmony_ci if (!async_gc) return; 1671cb0ef41Sopenharmony_ci v8::base::MutexGuard lock(&async_gc->m_mutex); 1681cb0ef41Sopenharmony_ci if (async_gc->m_canceled) return; 1691cb0ef41Sopenharmony_ci v8::debug::ForceGarbageCollection( 1701cb0ef41Sopenharmony_ci m_isolate, v8::EmbedderHeapTracer::EmbedderStackState::kNoHeapPointers); 1711cb0ef41Sopenharmony_ci for (auto& callback : async_gc->m_pending_callbacks) { 1721cb0ef41Sopenharmony_ci callback->sendSuccess(); 1731cb0ef41Sopenharmony_ci } 1741cb0ef41Sopenharmony_ci async_gc->m_pending_callbacks.clear(); 1751cb0ef41Sopenharmony_ci } 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci private: 1781cb0ef41Sopenharmony_ci v8::Isolate* m_isolate; 1791cb0ef41Sopenharmony_ci std::weak_ptr<AsyncGC> m_async_gc; 1801cb0ef41Sopenharmony_ci}; 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ciV8HeapProfilerAgentImpl::V8HeapProfilerAgentImpl( 1831cb0ef41Sopenharmony_ci V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, 1841cb0ef41Sopenharmony_ci protocol::DictionaryValue* state) 1851cb0ef41Sopenharmony_ci : m_session(session), 1861cb0ef41Sopenharmony_ci m_isolate(session->inspector()->isolate()), 1871cb0ef41Sopenharmony_ci m_frontend(frontendChannel), 1881cb0ef41Sopenharmony_ci m_state(state), 1891cb0ef41Sopenharmony_ci m_hasTimer(false), 1901cb0ef41Sopenharmony_ci m_async_gc(std::make_shared<AsyncGC>()) {} 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ciV8HeapProfilerAgentImpl::~V8HeapProfilerAgentImpl() { 1931cb0ef41Sopenharmony_ci v8::base::MutexGuard lock(&m_async_gc->m_mutex); 1941cb0ef41Sopenharmony_ci m_async_gc->m_canceled = true; 1951cb0ef41Sopenharmony_ci m_async_gc->m_pending_callbacks.clear(); 1961cb0ef41Sopenharmony_ci} 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_civoid V8HeapProfilerAgentImpl::restore() { 1991cb0ef41Sopenharmony_ci if (m_state->booleanProperty(HeapProfilerAgentState::heapProfilerEnabled, 2001cb0ef41Sopenharmony_ci false)) 2011cb0ef41Sopenharmony_ci m_frontend.resetProfiles(); 2021cb0ef41Sopenharmony_ci if (m_state->booleanProperty( 2031cb0ef41Sopenharmony_ci HeapProfilerAgentState::heapObjectsTrackingEnabled, false)) 2041cb0ef41Sopenharmony_ci startTrackingHeapObjectsInternal(m_state->booleanProperty( 2051cb0ef41Sopenharmony_ci HeapProfilerAgentState::allocationTrackingEnabled, false)); 2061cb0ef41Sopenharmony_ci if (m_state->booleanProperty( 2071cb0ef41Sopenharmony_ci HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) { 2081cb0ef41Sopenharmony_ci double samplingInterval = m_state->doubleProperty( 2091cb0ef41Sopenharmony_ci HeapProfilerAgentState::samplingHeapProfilerInterval, -1); 2101cb0ef41Sopenharmony_ci DCHECK_GE(samplingInterval, 0); 2111cb0ef41Sopenharmony_ci startSampling(Maybe<double>(samplingInterval)); 2121cb0ef41Sopenharmony_ci } 2131cb0ef41Sopenharmony_ci} 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_civoid V8HeapProfilerAgentImpl::collectGarbage( 2161cb0ef41Sopenharmony_ci std::unique_ptr<CollectGarbageCallback> callback) { 2171cb0ef41Sopenharmony_ci v8::base::MutexGuard lock(&m_async_gc->m_mutex); 2181cb0ef41Sopenharmony_ci m_async_gc->m_pending_callbacks.push_back(std::move(callback)); 2191cb0ef41Sopenharmony_ci if (!m_async_gc->m_pending) { 2201cb0ef41Sopenharmony_ci v8::debug::GetCurrentPlatform() 2211cb0ef41Sopenharmony_ci ->GetForegroundTaskRunner(m_isolate) 2221cb0ef41Sopenharmony_ci ->PostNonNestableTask(std::make_unique<GCTask>(m_isolate, m_async_gc)); 2231cb0ef41Sopenharmony_ci } 2241cb0ef41Sopenharmony_ci} 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ciResponse V8HeapProfilerAgentImpl::startTrackingHeapObjects( 2271cb0ef41Sopenharmony_ci Maybe<bool> trackAllocations) { 2281cb0ef41Sopenharmony_ci m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, true); 2291cb0ef41Sopenharmony_ci bool allocationTrackingEnabled = trackAllocations.fromMaybe(false); 2301cb0ef41Sopenharmony_ci m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, 2311cb0ef41Sopenharmony_ci allocationTrackingEnabled); 2321cb0ef41Sopenharmony_ci startTrackingHeapObjectsInternal(allocationTrackingEnabled); 2331cb0ef41Sopenharmony_ci return Response::Success(); 2341cb0ef41Sopenharmony_ci} 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ciResponse V8HeapProfilerAgentImpl::stopTrackingHeapObjects( 2371cb0ef41Sopenharmony_ci Maybe<bool> reportProgress, Maybe<bool> treatGlobalObjectsAsRoots, 2381cb0ef41Sopenharmony_ci Maybe<bool> captureNumericValue) { 2391cb0ef41Sopenharmony_ci requestHeapStatsUpdate(); 2401cb0ef41Sopenharmony_ci takeHeapSnapshot(std::move(reportProgress), 2411cb0ef41Sopenharmony_ci std::move(treatGlobalObjectsAsRoots), 2421cb0ef41Sopenharmony_ci std::move(captureNumericValue)); 2431cb0ef41Sopenharmony_ci stopTrackingHeapObjectsInternal(); 2441cb0ef41Sopenharmony_ci return Response::Success(); 2451cb0ef41Sopenharmony_ci} 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ciResponse V8HeapProfilerAgentImpl::enable() { 2481cb0ef41Sopenharmony_ci m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, true); 2491cb0ef41Sopenharmony_ci return Response::Success(); 2501cb0ef41Sopenharmony_ci} 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ciResponse V8HeapProfilerAgentImpl::disable() { 2531cb0ef41Sopenharmony_ci stopTrackingHeapObjectsInternal(); 2541cb0ef41Sopenharmony_ci if (m_state->booleanProperty( 2551cb0ef41Sopenharmony_ci HeapProfilerAgentState::samplingHeapProfilerEnabled, false)) { 2561cb0ef41Sopenharmony_ci v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); 2571cb0ef41Sopenharmony_ci if (profiler) profiler->StopSamplingHeapProfiler(); 2581cb0ef41Sopenharmony_ci } 2591cb0ef41Sopenharmony_ci m_isolate->GetHeapProfiler()->ClearObjectIds(); 2601cb0ef41Sopenharmony_ci m_state->setBoolean(HeapProfilerAgentState::heapProfilerEnabled, false); 2611cb0ef41Sopenharmony_ci return Response::Success(); 2621cb0ef41Sopenharmony_ci} 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ciResponse V8HeapProfilerAgentImpl::takeHeapSnapshot( 2651cb0ef41Sopenharmony_ci Maybe<bool> reportProgress, Maybe<bool> treatGlobalObjectsAsRoots, 2661cb0ef41Sopenharmony_ci Maybe<bool> captureNumericValue) { 2671cb0ef41Sopenharmony_ci v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); 2681cb0ef41Sopenharmony_ci if (!profiler) return Response::ServerError("Cannot access v8 heap profiler"); 2691cb0ef41Sopenharmony_ci std::unique_ptr<HeapSnapshotProgress> progress; 2701cb0ef41Sopenharmony_ci if (reportProgress.fromMaybe(false)) 2711cb0ef41Sopenharmony_ci progress.reset(new HeapSnapshotProgress(&m_frontend)); 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ci GlobalObjectNameResolver resolver(m_session); 2741cb0ef41Sopenharmony_ci const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot( 2751cb0ef41Sopenharmony_ci progress.get(), &resolver, treatGlobalObjectsAsRoots.fromMaybe(true), 2761cb0ef41Sopenharmony_ci captureNumericValue.fromMaybe(false)); 2771cb0ef41Sopenharmony_ci if (!snapshot) return Response::ServerError("Failed to take heap snapshot"); 2781cb0ef41Sopenharmony_ci HeapSnapshotOutputStream stream(&m_frontend); 2791cb0ef41Sopenharmony_ci snapshot->Serialize(&stream); 2801cb0ef41Sopenharmony_ci const_cast<v8::HeapSnapshot*>(snapshot)->Delete(); 2811cb0ef41Sopenharmony_ci return Response::Success(); 2821cb0ef41Sopenharmony_ci} 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ciResponse V8HeapProfilerAgentImpl::getObjectByHeapObjectId( 2851cb0ef41Sopenharmony_ci const String16& heapSnapshotObjectId, Maybe<String16> objectGroup, 2861cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Runtime::RemoteObject>* result) { 2871cb0ef41Sopenharmony_ci bool ok; 2881cb0ef41Sopenharmony_ci int id = heapSnapshotObjectId.toInteger(&ok); 2891cb0ef41Sopenharmony_ci if (!ok) return Response::ServerError("Invalid heap snapshot object id"); 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_ci v8::HandleScope handles(m_isolate); 2921cb0ef41Sopenharmony_ci v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id); 2931cb0ef41Sopenharmony_ci if (heapObject.IsEmpty()) 2941cb0ef41Sopenharmony_ci return Response::ServerError("Object is not available"); 2951cb0ef41Sopenharmony_ci 2961cb0ef41Sopenharmony_ci if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) 2971cb0ef41Sopenharmony_ci return Response::ServerError("Object is not available"); 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci v8::Local<v8::Context> creationContext; 3001cb0ef41Sopenharmony_ci if (!heapObject->GetCreationContext().ToLocal(&creationContext)) { 3011cb0ef41Sopenharmony_ci return Response::ServerError("Object is not available"); 3021cb0ef41Sopenharmony_ci } 3031cb0ef41Sopenharmony_ci *result = m_session->wrapObject(creationContext, heapObject, 3041cb0ef41Sopenharmony_ci objectGroup.fromMaybe(""), false); 3051cb0ef41Sopenharmony_ci if (!*result) return Response::ServerError("Object is not available"); 3061cb0ef41Sopenharmony_ci return Response::Success(); 3071cb0ef41Sopenharmony_ci} 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ciResponse V8HeapProfilerAgentImpl::addInspectedHeapObject( 3101cb0ef41Sopenharmony_ci const String16& inspectedHeapObjectId) { 3111cb0ef41Sopenharmony_ci bool ok; 3121cb0ef41Sopenharmony_ci int id = inspectedHeapObjectId.toInteger(&ok); 3131cb0ef41Sopenharmony_ci if (!ok) return Response::ServerError("Invalid heap snapshot object id"); 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ci v8::HandleScope handles(m_isolate); 3161cb0ef41Sopenharmony_ci v8::Local<v8::Object> heapObject = objectByHeapObjectId(m_isolate, id); 3171cb0ef41Sopenharmony_ci if (heapObject.IsEmpty()) 3181cb0ef41Sopenharmony_ci return Response::ServerError("Object is not available"); 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci if (!m_session->inspector()->client()->isInspectableHeapObject(heapObject)) 3211cb0ef41Sopenharmony_ci return Response::ServerError("Object is not available"); 3221cb0ef41Sopenharmony_ci m_session->addInspectedObject( 3231cb0ef41Sopenharmony_ci std::unique_ptr<InspectableHeapObject>(new InspectableHeapObject(id))); 3241cb0ef41Sopenharmony_ci return Response::Success(); 3251cb0ef41Sopenharmony_ci} 3261cb0ef41Sopenharmony_ci 3271cb0ef41Sopenharmony_ciResponse V8HeapProfilerAgentImpl::getHeapObjectId( 3281cb0ef41Sopenharmony_ci const String16& objectId, String16* heapSnapshotObjectId) { 3291cb0ef41Sopenharmony_ci v8::HandleScope handles(m_isolate); 3301cb0ef41Sopenharmony_ci v8::Local<v8::Value> value; 3311cb0ef41Sopenharmony_ci v8::Local<v8::Context> context; 3321cb0ef41Sopenharmony_ci Response response = 3331cb0ef41Sopenharmony_ci m_session->unwrapObject(objectId, &value, &context, nullptr); 3341cb0ef41Sopenharmony_ci if (!response.IsSuccess()) return response; 3351cb0ef41Sopenharmony_ci if (value->IsUndefined()) return Response::InternalError(); 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci v8::SnapshotObjectId id = m_isolate->GetHeapProfiler()->GetObjectId(value); 3381cb0ef41Sopenharmony_ci *heapSnapshotObjectId = String16::fromInteger(static_cast<size_t>(id)); 3391cb0ef41Sopenharmony_ci return Response::Success(); 3401cb0ef41Sopenharmony_ci} 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_civoid V8HeapProfilerAgentImpl::requestHeapStatsUpdate() { 3431cb0ef41Sopenharmony_ci HeapStatsStream stream(&m_frontend); 3441cb0ef41Sopenharmony_ci v8::SnapshotObjectId lastSeenObjectId = 3451cb0ef41Sopenharmony_ci m_isolate->GetHeapProfiler()->GetHeapStats(&stream); 3461cb0ef41Sopenharmony_ci m_frontend.lastSeenObjectId( 3471cb0ef41Sopenharmony_ci lastSeenObjectId, m_session->inspector()->client()->currentTimeMS()); 3481cb0ef41Sopenharmony_ci} 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ci// static 3511cb0ef41Sopenharmony_civoid V8HeapProfilerAgentImpl::onTimer(void* data) { 3521cb0ef41Sopenharmony_ci reinterpret_cast<V8HeapProfilerAgentImpl*>(data)->requestHeapStatsUpdate(); 3531cb0ef41Sopenharmony_ci} 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_civoid V8HeapProfilerAgentImpl::startTrackingHeapObjectsInternal( 3561cb0ef41Sopenharmony_ci bool trackAllocations) { 3571cb0ef41Sopenharmony_ci m_isolate->GetHeapProfiler()->StartTrackingHeapObjects(trackAllocations); 3581cb0ef41Sopenharmony_ci if (!m_hasTimer) { 3591cb0ef41Sopenharmony_ci m_hasTimer = true; 3601cb0ef41Sopenharmony_ci m_session->inspector()->client()->startRepeatingTimer( 3611cb0ef41Sopenharmony_ci 0.05, &V8HeapProfilerAgentImpl::onTimer, reinterpret_cast<void*>(this)); 3621cb0ef41Sopenharmony_ci } 3631cb0ef41Sopenharmony_ci} 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_civoid V8HeapProfilerAgentImpl::stopTrackingHeapObjectsInternal() { 3661cb0ef41Sopenharmony_ci if (m_hasTimer) { 3671cb0ef41Sopenharmony_ci m_session->inspector()->client()->cancelTimer( 3681cb0ef41Sopenharmony_ci reinterpret_cast<void*>(this)); 3691cb0ef41Sopenharmony_ci m_hasTimer = false; 3701cb0ef41Sopenharmony_ci } 3711cb0ef41Sopenharmony_ci m_isolate->GetHeapProfiler()->StopTrackingHeapObjects(); 3721cb0ef41Sopenharmony_ci m_state->setBoolean(HeapProfilerAgentState::heapObjectsTrackingEnabled, 3731cb0ef41Sopenharmony_ci false); 3741cb0ef41Sopenharmony_ci m_state->setBoolean(HeapProfilerAgentState::allocationTrackingEnabled, false); 3751cb0ef41Sopenharmony_ci} 3761cb0ef41Sopenharmony_ci 3771cb0ef41Sopenharmony_ciResponse V8HeapProfilerAgentImpl::startSampling( 3781cb0ef41Sopenharmony_ci Maybe<double> samplingInterval) { 3791cb0ef41Sopenharmony_ci v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); 3801cb0ef41Sopenharmony_ci if (!profiler) return Response::ServerError("Cannot access v8 heap profiler"); 3811cb0ef41Sopenharmony_ci const unsigned defaultSamplingInterval = 1 << 15; 3821cb0ef41Sopenharmony_ci double samplingIntervalValue = 3831cb0ef41Sopenharmony_ci samplingInterval.fromMaybe(defaultSamplingInterval); 3841cb0ef41Sopenharmony_ci if (samplingIntervalValue <= 0.0) { 3851cb0ef41Sopenharmony_ci return Response::ServerError("Invalid sampling interval"); 3861cb0ef41Sopenharmony_ci } 3871cb0ef41Sopenharmony_ci m_state->setDouble(HeapProfilerAgentState::samplingHeapProfilerInterval, 3881cb0ef41Sopenharmony_ci samplingIntervalValue); 3891cb0ef41Sopenharmony_ci m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, 3901cb0ef41Sopenharmony_ci true); 3911cb0ef41Sopenharmony_ci profiler->StartSamplingHeapProfiler( 3921cb0ef41Sopenharmony_ci static_cast<uint64_t>(samplingIntervalValue), 128, 3931cb0ef41Sopenharmony_ci v8::HeapProfiler::kSamplingForceGC); 3941cb0ef41Sopenharmony_ci return Response::Success(); 3951cb0ef41Sopenharmony_ci} 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_cinamespace { 3981cb0ef41Sopenharmony_cistd::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode> 3991cb0ef41Sopenharmony_cibuildSampingHeapProfileNode(v8::Isolate* isolate, 4001cb0ef41Sopenharmony_ci const v8::AllocationProfile::Node* node) { 4011cb0ef41Sopenharmony_ci auto children = std::make_unique< 4021cb0ef41Sopenharmony_ci protocol::Array<protocol::HeapProfiler::SamplingHeapProfileNode>>(); 4031cb0ef41Sopenharmony_ci for (const auto* child : node->children) 4041cb0ef41Sopenharmony_ci children->emplace_back(buildSampingHeapProfileNode(isolate, child)); 4051cb0ef41Sopenharmony_ci size_t selfSize = 0; 4061cb0ef41Sopenharmony_ci for (const auto& allocation : node->allocations) 4071cb0ef41Sopenharmony_ci selfSize += allocation.size * allocation.count; 4081cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Runtime::CallFrame> callFrame = 4091cb0ef41Sopenharmony_ci protocol::Runtime::CallFrame::create() 4101cb0ef41Sopenharmony_ci .setFunctionName(toProtocolString(isolate, node->name)) 4111cb0ef41Sopenharmony_ci .setScriptId(String16::fromInteger(node->script_id)) 4121cb0ef41Sopenharmony_ci .setUrl(toProtocolString(isolate, node->script_name)) 4131cb0ef41Sopenharmony_ci .setLineNumber(node->line_number - 1) 4141cb0ef41Sopenharmony_ci .setColumnNumber(node->column_number - 1) 4151cb0ef41Sopenharmony_ci .build(); 4161cb0ef41Sopenharmony_ci std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfileNode> result = 4171cb0ef41Sopenharmony_ci protocol::HeapProfiler::SamplingHeapProfileNode::create() 4181cb0ef41Sopenharmony_ci .setCallFrame(std::move(callFrame)) 4191cb0ef41Sopenharmony_ci .setSelfSize(selfSize) 4201cb0ef41Sopenharmony_ci .setChildren(std::move(children)) 4211cb0ef41Sopenharmony_ci .setId(node->node_id) 4221cb0ef41Sopenharmony_ci .build(); 4231cb0ef41Sopenharmony_ci return result; 4241cb0ef41Sopenharmony_ci} 4251cb0ef41Sopenharmony_ci} // namespace 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ciResponse V8HeapProfilerAgentImpl::stopSampling( 4281cb0ef41Sopenharmony_ci std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile) { 4291cb0ef41Sopenharmony_ci Response result = getSamplingProfile(profile); 4301cb0ef41Sopenharmony_ci if (result.IsSuccess()) { 4311cb0ef41Sopenharmony_ci m_isolate->GetHeapProfiler()->StopSamplingHeapProfiler(); 4321cb0ef41Sopenharmony_ci m_state->setBoolean(HeapProfilerAgentState::samplingHeapProfilerEnabled, 4331cb0ef41Sopenharmony_ci false); 4341cb0ef41Sopenharmony_ci } 4351cb0ef41Sopenharmony_ci return result; 4361cb0ef41Sopenharmony_ci} 4371cb0ef41Sopenharmony_ci 4381cb0ef41Sopenharmony_ciResponse V8HeapProfilerAgentImpl::getSamplingProfile( 4391cb0ef41Sopenharmony_ci std::unique_ptr<protocol::HeapProfiler::SamplingHeapProfile>* profile) { 4401cb0ef41Sopenharmony_ci v8::HeapProfiler* profiler = m_isolate->GetHeapProfiler(); 4411cb0ef41Sopenharmony_ci // Need a scope as v8::AllocationProfile contains Local handles. 4421cb0ef41Sopenharmony_ci v8::HandleScope scope(m_isolate); 4431cb0ef41Sopenharmony_ci std::unique_ptr<v8::AllocationProfile> v8Profile( 4441cb0ef41Sopenharmony_ci profiler->GetAllocationProfile()); 4451cb0ef41Sopenharmony_ci if (!v8Profile) 4461cb0ef41Sopenharmony_ci return Response::ServerError("V8 sampling heap profiler was not started."); 4471cb0ef41Sopenharmony_ci v8::AllocationProfile::Node* root = v8Profile->GetRootNode(); 4481cb0ef41Sopenharmony_ci auto samples = std::make_unique< 4491cb0ef41Sopenharmony_ci protocol::Array<protocol::HeapProfiler::SamplingHeapProfileSample>>(); 4501cb0ef41Sopenharmony_ci for (const auto& sample : v8Profile->GetSamples()) { 4511cb0ef41Sopenharmony_ci samples->emplace_back( 4521cb0ef41Sopenharmony_ci protocol::HeapProfiler::SamplingHeapProfileSample::create() 4531cb0ef41Sopenharmony_ci .setSize(sample.size * sample.count) 4541cb0ef41Sopenharmony_ci .setNodeId(sample.node_id) 4551cb0ef41Sopenharmony_ci .setOrdinal(static_cast<double>(sample.sample_id)) 4561cb0ef41Sopenharmony_ci .build()); 4571cb0ef41Sopenharmony_ci } 4581cb0ef41Sopenharmony_ci *profile = protocol::HeapProfiler::SamplingHeapProfile::create() 4591cb0ef41Sopenharmony_ci .setHead(buildSampingHeapProfileNode(m_isolate, root)) 4601cb0ef41Sopenharmony_ci .setSamples(std::move(samples)) 4611cb0ef41Sopenharmony_ci .build(); 4621cb0ef41Sopenharmony_ci return Response::Success(); 4631cb0ef41Sopenharmony_ci} 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci} // namespace v8_inspector 466