• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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