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