1 /*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/jobs/hitrace_scope.h"
17
18 #include "ecmascript/jobs/pending_job.h"
19 #include "hitrace/trace.h"
20 #include "ecmascript/dfx/stackinfo/js_stackinfo.h"
21
22 namespace panda::ecmascript::job {
EnqueueJobScope(const JSHandle<PendingJob> &pendingJob, QueueType queueType)23 EnqueueJobScope::EnqueueJobScope(const JSHandle<PendingJob> &pendingJob, QueueType queueType)
24 {
25 HiTraceId id = HiTraceChain::GetId();
26 if (id.IsValid() && id.IsFlagEnabled(HITRACE_FLAG_INCLUDE_ASYNC)) {
27 HiTraceId childId = HiTraceChain::CreateSpan();
28
29 pendingJob->SetChainId(childId.GetChainId());
30 pendingJob->SetSpanId(childId.GetSpanId());
31 pendingJob->SetParentSpanId(childId.GetParentSpanId());
32 pendingJob->SetFlags(childId.GetFlags());
33
34 if (id.IsFlagEnabled(HITRACE_FLAG_TP_INFO)) {
35 if (queueType == QueueType::QUEUE_PROMISE) {
36 HiTraceChain::Tracepoint(HITRACE_CM_THREAD, HITRACE_TP_CS,
37 childId, "Queue type:%s", "Promise queue");
38 } else if (queueType == QueueType::QUEUE_SCRIPT) {
39 HiTraceChain::Tracepoint(HITRACE_CM_THREAD, HITRACE_TP_CS,
40 childId, "Queue type:%s", "Script queue");
41 } else {
42 HiTraceChain::Tracepoint(HITRACE_CM_THREAD, HITRACE_TP_CS,
43 childId, "Queue type:%s", "Other queue");
44 }
45 }
46 }
47 }
48
~EnqueueJobScope()49 EnqueueJobScope::~EnqueueJobScope()
50 {
51 }
52
ExecuteJobScope(const JSHandle<PendingJob> &pendingJob)53 ExecuteJobScope::ExecuteJobScope(const JSHandle<PendingJob> &pendingJob)
54 {
55 saveId_ = HiTraceChain::GetId();
56 if (saveId_.IsValid()) {
57 HiTraceChain::ClearId();
58 }
59 if (pendingJob->GetChainId() != 0) {
60 hitraceId_.SetChainId(pendingJob->GetChainId());
61 hitraceId_.SetSpanId(pendingJob->GetSpanId());
62 hitraceId_.SetParentSpanId(pendingJob->GetParentSpanId());
63 hitraceId_.SetFlags(pendingJob->GetFlags());
64
65 if (hitraceId_.IsValid()) {
66 HiTraceChain::SetId(hitraceId_);
67 if (hitraceId_.IsFlagEnabled(HITRACE_FLAG_TP_INFO)) {
68 HiTraceChain::Tracepoint(HITRACE_CM_THREAD, HITRACE_TP_SR,
69 hitraceId_, "Before %s pending job execute", "Promise");
70 }
71 }
72 }
73 }
74
~ExecuteJobScope()75 ExecuteJobScope::~ExecuteJobScope()
76 {
77 if (hitraceId_.IsValid()) {
78 if (hitraceId_.IsFlagEnabled(HITRACE_FLAG_TP_INFO)) {
79 HiTraceChain::Tracepoint(HITRACE_CM_THREAD, HITRACE_TP_SS,
80 hitraceId_, "After %s pending job execute", "Promise");
81 }
82 HiTraceChain::ClearId();
83 }
84 if (saveId_.IsValid()) {
85 HiTraceChain::SetId(saveId_);
86 }
87 }
88
EnqueueJobTrace(JSThread *thread, const JSHandle<PendingJob> &pendingJob)89 EnqueueJobTrace::EnqueueJobTrace(JSThread *thread, const JSHandle<PendingJob> &pendingJob)
90 {
91 isMicroJobTraceEnable_ = thread->GetEcmaVM()->GetJSOptions().EnableMicroJobTrace();
92 if (!isMicroJobTraceEnable_) {
93 return;
94 }
95
96 uint64_t jobId = thread->GetJobId();
97 pendingJob->SetJobId(jobId);
98 std::string strTrace = "MicroJobQueue::EnqueueJob: jobId: " + std::to_string(jobId);
99 strTrace += ", threadId: " + std::to_string(thread->GetThreadId());
100
101 std::vector<JsFrameInfo> jsStackInfo = JsStackInfo::BuildJsStackInfo(thread, true);
102 if (jsStackInfo.empty()) {
103 ECMA_BYTRACE_START_TRACE(HITRACE_TAG_ARK, strTrace);
104 return;
105 }
106
107 JsFrameInfo jsFrameInfo = jsStackInfo.front();
108 size_t pos = jsFrameInfo.pos.find(':', 0);
109 if (pos != CString::npos) {
110 int lineNumber = std::stoi(jsFrameInfo.pos.substr(0, pos));
111 int columnNumber = std::stoi(jsFrameInfo.pos.substr(pos + 1));
112 auto sourceMapcb = thread->GetEcmaVM()->GetSourceMapTranslateCallback();
113 if (sourceMapcb != nullptr && !jsFrameInfo.fileName.empty()) {
114 sourceMapcb(jsFrameInfo.fileName, lineNumber, columnNumber);
115 }
116 }
117
118 strTrace += ", funcName: " + jsFrameInfo.functionName + ", url: " + jsFrameInfo.fileName + ":" + jsFrameInfo.pos;
119 ECMA_BYTRACE_START_TRACE(HITRACE_TAG_ARK, strTrace);
120 }
121
~EnqueueJobTrace()122 EnqueueJobTrace::~EnqueueJobTrace()
123 {
124 if (isMicroJobTraceEnable_) {
125 ECMA_BYTRACE_FINISH_TRACE(HITRACE_TAG_ARK);
126 }
127 }
128
ExecuteJobTrace(JSThread *thread, const JSHandle<PendingJob> &pendingJob)129 ExecuteJobTrace::ExecuteJobTrace(JSThread *thread, const JSHandle<PendingJob> &pendingJob)
130 {
131 isMicroJobTraceEnable_ = thread->GetEcmaVM()->GetJSOptions().EnableMicroJobTrace();
132 if (isMicroJobTraceEnable_) {
133 uint64_t jobId = pendingJob->GetJobId();
134 std::string strTrace = "PendingJob::ExecutePendingJob: jobId: " + std::to_string(jobId);
135 strTrace += ", threadId: " + std::to_string(thread->GetThreadId());
136 ECMA_BYTRACE_START_TRACE(HITRACE_TAG_ARK, strTrace);
137 }
138 }
139
~ExecuteJobTrace()140 ExecuteJobTrace::~ExecuteJobTrace()
141 {
142 if (isMicroJobTraceEnable_) {
143 ECMA_BYTRACE_FINISH_TRACE(HITRACE_TAG_ARK);
144 }
145 }
146 } // namespace panda::ecmascript::job