• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, strTrace.c_str());
104         return;
105     }
106 
107     JsFrameInfo jsFrameInfo = jsStackInfo.front();
108     size_t pos = jsFrameInfo.pos.find(':', 0);
109     if (pos != CString::npos) {
110         int64_t tmp = std::strtoll(jsFrameInfo.pos.substr(0, pos).c_str(), nullptr, 10);
111         if (tmp < INT_MIN || tmp > INT_MAX) {
112             LOG_ECMA(ERROR) << "MicroJobTrace: Invalid line number: " << jsFrameInfo.pos.substr(0, pos);
113             return;
114         }
115 
116         int64_t val = std::strtoll(jsFrameInfo.pos.substr(pos + 1).c_str(), nullptr, 10);
117         if (val < INT_MIN || val > INT_MAX) {
118             LOG_ECMA(ERROR) << "MicroJobTrace: Invalid column number: " << jsFrameInfo.pos.substr(pos + 1);
119             return;
120         }
121         int lineNumber = static_cast<int>(tmp);
122         int columnNumber = static_cast<int>(val);
123         auto sourceMapcb = thread->GetEcmaVM()->GetSourceMapTranslateCallback();
124         if (sourceMapcb != nullptr && !jsFrameInfo.fileName.empty()) {
125             sourceMapcb(jsFrameInfo.fileName, lineNumber, columnNumber, jsFrameInfo.packageName);
126         }
127     }
128 
129     strTrace += ", funcName: " + jsFrameInfo.functionName + ", url: " + jsFrameInfo.fileName + ":" + jsFrameInfo.pos;
130     ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, strTrace.c_str());
131 }
132 
~EnqueueJobTrace()133 EnqueueJobTrace::~EnqueueJobTrace()
134 {
135     if (isMicroJobTraceEnable_) {
136         ECMA_BYTRACE_FINISH_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK);
137     }
138 }
139 
ExecuteJobTrace(JSThread * thread,const JSHandle<PendingJob> & pendingJob)140 ExecuteJobTrace::ExecuteJobTrace(JSThread *thread, const JSHandle<PendingJob> &pendingJob)
141 {
142     isMicroJobTraceEnable_ = thread->GetEcmaVM()->GetJSOptions().EnableMicroJobTrace();
143     if (isMicroJobTraceEnable_) {
144         uint64_t jobId = pendingJob->GetJobId();
145         std::string strTrace = "PendingJob::ExecutePendingJob: jobId: " + std::to_string(jobId);
146         strTrace += ", threadId: " + std::to_string(thread->GetThreadId());
147         ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, strTrace.c_str());
148     }
149 }
150 
~ExecuteJobTrace()151 ExecuteJobTrace::~ExecuteJobTrace()
152 {
153     if (isMicroJobTraceEnable_) {
154         ECMA_BYTRACE_FINISH_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK);
155     }
156 }
157 }  // namespace panda::ecmascript::job