• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #ifndef ECMASCRIPT_STACKINFO_STACK_TRACE_H
17 #define ECMASCRIPT_STACKINFO_STACK_TRACE_H
18 
19 #include <memory>
20 #include <string>
21 
22 #include "ecmascript/js_promise.h"
23 #include "ecmascript/mem/c_containers.h"
24 
25 namespace panda::ecmascript {
26 class JSPromise;
27 class EcmaVM;
28 class JSTaggedValue;
29 
30 // for async stack trace
31 static constexpr int32_t MAX_CALL_STACK_SIZE_TO_CAPTURE = 200;
32 class PUBLIC_API StackFrame {
33 public:
34     StackFrame() = default;
35     ~StackFrame() = default;
36 
GetFunctionName()37     const std::string &GetFunctionName() const
38     {
39         return functionName_;
40     }
41 
SetFunctionName(std::string & functionName)42     void SetFunctionName(std::string &functionName)
43     {
44         functionName_ = functionName;
45     }
46 
GetUrl()47     const std::string &GetUrl() const
48     {
49         return url_;
50     }
51 
SetUrl(std::string & url)52     void SetUrl(std::string &url)
53     {
54         url_ = url;
55     }
56 
GetLineNumber()57     int32_t GetLineNumber() const
58     {
59         return lineNumber_;
60     }
61 
SetLineNumber(int32_t lineNumber)62     void SetLineNumber(int32_t lineNumber)
63     {
64         lineNumber_ = lineNumber;
65     }
66 
GetColumnNumber()67     int32_t GetColumnNumber() const
68     {
69         return columnNumber_;
70     }
71 
SetColumnNumber(int32_t columnNumber)72     void SetColumnNumber(int32_t columnNumber)
73     {
74         columnNumber_ = columnNumber;
75     }
76 
GetScriptId()77     int32_t GetScriptId() const
78     {
79         return scriptId_;
80     }
81 
SetScriptId(int32_t scriptId)82     void SetScriptId(int32_t scriptId)
83     {
84         scriptId_ = scriptId;
85     }
86 
87 private:
88     std::string functionName_;
89     std::string url_;
90     int32_t lineNumber_;
91     int32_t columnNumber_;
92     // For debugger
93     int32_t scriptId_;
94 };
95 
96 class AsyncStack {
97 public:
98     AsyncStack() = default;
99 
GetDescription()100     const std::string &GetDescription() const
101     {
102         return description_;
103     }
104 
SetDescription(const std::string & description)105     void SetDescription(const std::string &description)
106     {
107         description_ = description;
108     }
109 
GetAsyncParent()110     const std::weak_ptr<AsyncStack> &GetAsyncParent() const
111     {
112         return asyncParent_;
113     }
114 
SetAsyncParent(const std::shared_ptr<AsyncStack> & asyncParent)115     void SetAsyncParent(const std::shared_ptr<AsyncStack> &asyncParent)
116     {
117         asyncParent_ = asyncParent;
118     }
119 
GetFrames()120     const std::vector<std::shared_ptr<StackFrame>> &GetFrames() const
121     {
122         return frames_;
123     }
124 
SetFrames(const std::vector<std::shared_ptr<StackFrame>> & frames)125     void SetFrames(const std::vector<std::shared_ptr<StackFrame>> &frames)
126     {
127         frames_ = frames;
128     }
129 private:
130     std::string description_;
131     std::vector<std::shared_ptr<StackFrame>> frames_;
132     std::weak_ptr<AsyncStack> asyncParent_;
133 };
134 
135 class AsyncStackTrace {
136 public:
137     explicit AsyncStackTrace(EcmaVM *vm);
138 
139     ~AsyncStackTrace() = default;
140 
141     void RegisterAsyncDetectCallBack();
142 
143     bool InsertAsyncStackTrace(const JSHandle<JSPromise> &promise);
144 
145     bool RemoveAsyncStackTrace(const JSHandle<JSPromise> &promise);
146 
147     bool InsertAsyncTaskStacks(const JSHandle<JSPromise> &promise, const std::string &description);
148 
149     bool InsertCurrentAsyncTaskStack(const JSTaggedValue &PromiseReaction);
150 
151     bool RemoveAsyncTaskStack(const JSTaggedValue &PromiseReaction);
152 
153     std::shared_ptr<AsyncStack> GetCurrentAsyncParent();
154 
GetAsyncStackTrace()155     CMap<uint32_t, std::pair<std::string, int64_t>> GetAsyncStackTrace()
156     {
157         return asyncStackTrace_;
158     }
159 
GetAsyncTaskId()160     uint32_t GetAsyncTaskId()
161     {
162         if (asyncTaskId_ == MAX_ASYNC_TASK_ID) {
163             asyncTaskId_ = 0;
164         }
165         return ++asyncTaskId_;
166     }
167 
168     static constexpr uint32_t PROMISE_PENDING_TIME_MS = 5000;
169 
170     NO_COPY_SEMANTIC(AsyncStackTrace);
171     NO_MOVE_SEMANTIC(AsyncStackTrace);
172 private:
173     static constexpr uint32_t MAX_ASYNC_TASK_ID = (1u << JSPromise::ASYNC_TASK_ID_BITS) - 1;
174 
175     EcmaVM *vm_ {nullptr};
176     JSThread *jsThread_ {nullptr};
177     uint32_t asyncTaskId_ {0};
178 
179     // { promiseid , (jsStack, time) }
180     CMap<uint32_t, std::pair<std::string, int64_t>> asyncStackTrace_;
181 
182     std::vector<std::shared_ptr<AsyncStack>> currentAsyncParent_;
183     CMap<uint32_t, std::shared_ptr<AsyncStack>> asyncTaskStacks_;
184 };
185 } // namespace panda::ecmascript
186 #endif  // ECMASCRIPT_STACKINFO_STACK_TRACE_H