1 /*
2 * Copyright (c) 2021 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/micro_job_queue.h"
17
18 #include "ecmascript/global_env.h"
19 #include "ecmascript/jobs/pending_job.h"
20 #include "ecmascript/js_arguments.h"
21 #include "ecmascript/js_handle.h"
22 #include "ecmascript/js_tagged_value.h"
23 #include "ecmascript/js_thread.h"
24 #include "ecmascript/object_factory.h"
25 #include "ecmascript/tagged_queue-inl.h"
26 #include "ecmascript/tagged_queue.h"
27 #ifndef PANDA_TARGET_LINUX
28 #include "hitrace/hitrace.h"
29 #include "hitrace/hitraceid.h"
30 #endif
31 #include "utils/expected.h"
32
33 namespace panda::ecmascript::job {
34 #ifndef PANDA_TARGET_LINUX
35 using namespace OHOS::HiviewDFX;
36 #endif
EnqueueJob(JSThread * thread,JSHandle<MicroJobQueue> jobQueue,QueueType queueType,const JSHandle<JSFunction> & job,const JSHandle<TaggedArray> & argv)37 void MicroJobQueue::EnqueueJob(JSThread *thread, JSHandle<MicroJobQueue> jobQueue, QueueType queueType,
38 const JSHandle<JSFunction> &job, const JSHandle<TaggedArray> &argv)
39 {
40 // 1. Assert: Type(queueName) is String and its value is the name of a Job Queue recognized by this implementation.
41 // 2. Assert: job is the name of a Job.
42 // 3. Assert: arguments is a List that has the same number of elements as the number of parameters required by job.
43 // 4. Let callerContext be the running execution context.
44 // 5. Let callerRealm be callerContext’s Realm.
45 ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
46 [[maybe_unused]] EcmaHandleScope handleScope(thread);
47 JSHandle<PendingJob> pendingJob(factory->NewPendingJob(job, argv));
48 #ifndef PANDA_TARGET_LINUX
49 HiTraceId id = HiTrace::GetId();
50 if (id.IsValid() && id.IsFlagEnabled(HITRACE_FLAG_INCLUDE_ASYNC)) {
51 HiTraceId childId = HiTrace::CreateSpan();
52
53 pendingJob->SetChainId(childId.GetChainId());
54 pendingJob->SetSpanId(childId.GetSpanId());
55 pendingJob->SetParentSpanId(childId.GetParentSpanId());
56 pendingJob->SetFlags(childId.GetFlags());
57
58 if (id.IsFlagEnabled(HITRACE_FLAG_TP_INFO)) {
59 if (queueType == QueueType::QUEUE_PROMISE) {
60 HiTrace::Tracepoint(HITRACE_CM_THREAD, HITRACE_TP_CS,
61 childId, "Queue type:%s", "Promise queue");
62 } else if (queueType == QueueType::QUEUE_SCRIPT) {
63 HiTrace::Tracepoint(HITRACE_CM_THREAD, HITRACE_TP_CS,
64 childId, "Queue type:%s", "Script queue");
65 } else {
66 HiTrace::Tracepoint(HITRACE_CM_THREAD, HITRACE_TP_CS,
67 childId, "Queue type:%s", "Other queue");
68 }
69 }
70 }
71 #endif
72 if (queueType == QueueType::QUEUE_PROMISE) {
73 JSHandle<TaggedQueue> promiseQueue(thread, jobQueue->GetPromiseJobQueue());
74 LOG_ECMA(DEBUG) << "promiseQueue start length: " << promiseQueue->Size();
75 TaggedQueue *newPromiseQueue = TaggedQueue::Push(thread, promiseQueue, JSHandle<JSTaggedValue>(pendingJob));
76 jobQueue->SetPromiseJobQueue(thread, JSTaggedValue(newPromiseQueue));
77 LOG_ECMA(DEBUG) << "promiseQueue end length: " << newPromiseQueue->Size();
78 } else if (queueType == QueueType::QUEUE_SCRIPT) {
79 JSHandle<TaggedQueue> scriptQueue(thread, jobQueue->GetScriptJobQueue());
80 TaggedQueue *newScriptQueue = TaggedQueue::Push(thread, scriptQueue, JSHandle<JSTaggedValue>(pendingJob));
81 jobQueue->SetScriptJobQueue(thread, JSTaggedValue(newScriptQueue));
82 }
83 }
84
ExecutePendingJob(JSThread * thread,JSHandle<MicroJobQueue> jobQueue)85 void MicroJobQueue::ExecutePendingJob(JSThread *thread, JSHandle<MicroJobQueue> jobQueue)
86 {
87 [[maybe_unused]] EcmaHandleScope handleScope(thread);
88 JSMutableHandle<TaggedQueue> promiseQueue(thread, jobQueue->GetPromiseJobQueue());
89 JSMutableHandle<PendingJob> pendingJob(thread, JSTaggedValue::Undefined());
90 while (!promiseQueue->Empty()) {
91 LOG_ECMA(DEBUG) << "promiseQueue start length: " << promiseQueue->Size();
92 pendingJob.Update(promiseQueue->Pop(thread));
93 LOG_ECMA(DEBUG) << "promiseQueue end length: " << promiseQueue->Size();
94 #ifndef PANDA_TARGET_LINUX
95 HiTraceId hitraceId;
96 if (pendingJob->GetChainId() != 0) {
97 hitraceId.SetChainId(pendingJob->GetChainId());
98 hitraceId.SetSpanId(pendingJob->GetSpanId());
99 hitraceId.SetParentSpanId(pendingJob->GetParentSpanId());
100 hitraceId.SetFlags(pendingJob->GetFlags());
101
102 if (hitraceId.IsValid()) {
103 HiTrace::SetId(hitraceId);
104 if (hitraceId.IsFlagEnabled(HITRACE_FLAG_TP_INFO)) {
105 HiTrace::Tracepoint(HITRACE_CM_THREAD, HITRACE_TP_SR, hitraceId,
106 "Before %s queue job execute", "Promise");
107 }
108 }
109 }
110 #endif
111 PendingJob::ExecutePendingJob(pendingJob, thread);
112 #ifndef PANDA_TARGET_LINUX
113 if (pendingJob->GetChainId() != 0) {
114 if (hitraceId.IsValid()) {
115 if (hitraceId.IsFlagEnabled(HITRACE_FLAG_TP_INFO)) {
116 HiTrace::Tracepoint(HITRACE_CM_THREAD, HITRACE_TP_SS, hitraceId,
117 "After %s queue job execute", "Promise");
118 }
119 HiTrace::ClearId();
120 }
121 }
122 #endif
123 if (thread->HasPendingException()) {
124 return;
125 }
126 promiseQueue.Update(jobQueue->GetPromiseJobQueue());
127 }
128
129 JSHandle<TaggedQueue> scriptQueue(thread, jobQueue->GetScriptJobQueue());
130 while (!scriptQueue->Empty()) {
131 pendingJob.Update(scriptQueue->Pop(thread));
132 #ifndef PANDA_TARGET_LINUX
133 HiTraceId hitraceId;
134 if (pendingJob->GetChainId() != 0) {
135 hitraceId.SetChainId(pendingJob->GetChainId());
136 hitraceId.SetSpanId(pendingJob->GetSpanId());
137 hitraceId.SetParentSpanId(pendingJob->GetParentSpanId());
138 hitraceId.SetFlags(pendingJob->GetFlags());
139
140 if (hitraceId.IsValid()) {
141 HiTrace::SetId(hitraceId);
142 if (hitraceId.IsFlagEnabled(HITRACE_FLAG_TP_INFO)) {
143 HiTrace::Tracepoint(HITRACE_CM_THREAD, HITRACE_TP_SR, hitraceId,
144 "Before %s queue job execute", "Script");
145 }
146 }
147 }
148 #endif
149 PendingJob::ExecutePendingJob(pendingJob, thread);
150 #ifndef PANDA_TARGET_LINUX
151 if (pendingJob->GetChainId() != 0) {
152 if (hitraceId.IsValid()) {
153 if (hitraceId.IsFlagEnabled(HITRACE_FLAG_TP_INFO)) {
154 HiTrace::Tracepoint(HITRACE_CM_THREAD, HITRACE_TP_SS, hitraceId,
155 "After %s queue job execute", "Script");
156 }
157 HiTrace::ClearId();
158 }
159 }
160 #endif
161 if (thread->HasPendingException()) {
162 return;
163 }
164 }
165 }
166 } // namespace panda::ecmascript::job
167