1 /*
2 * Copyright (c) 2023 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 "tooling/client/manager/variable_manager.h"
17
18 #include <iomanip>
19
20 #include "common/log_wrapper.h"
21
22 using PtJson = panda::ecmascript::tooling::PtJson;
23 namespace OHOS::ArkCompiler::Toolchain {
AddChild(std::unique_ptr<PropertyDescriptor> descriptor)24 void TreeNode::AddChild(std::unique_ptr<PropertyDescriptor> descriptor)
25 {
26 children.push_back(std::make_unique<TreeNode>(std::move(descriptor)));
27 }
28
AddChild(DescriptorMap descriptorMap)29 void TreeNode::AddChild(DescriptorMap descriptorMap)
30 {
31 children.push_back(std::make_unique<TreeNode>(std::move(descriptorMap)));
32 }
33
AddChild(std::unique_ptr<TreeNode> child)34 void TreeNode::AddChild(std::unique_ptr<TreeNode> child)
35 {
36 children.push_back(std::move(child));
37 }
38
Print(int depth) const39 void TreeNode::Print(int depth) const
40 {
41 int actualIndent = 0;
42 if (depth > 1) {
43 actualIndent = (depth - 1) * 4; // 4: four spaces
44 }
45 std::string indent(actualIndent, ' ');
46
47 if (std::holds_alternative<int32_t>(data)) {
48 std::cout << indent << "CallFrameId: " << std::get<int32_t>(data) << std::endl;
49 } else if (std::holds_alternative<std::map<int32_t, std::map<int32_t, std::string>>>(data)) {
50 const auto& outerMap = std::get<std::map<int32_t, std::map<int32_t, std::string>>>(data);
51 for (const auto& [key, innerMap] : outerMap) {
52 for (const auto& [innerKey, value] : innerMap) {
53 std::cout << key << ". " << value << std::endl;
54 }
55 }
56 } else if (std::holds_alternative<std::unique_ptr<PropertyDescriptor>>(data)) {
57 const auto &descriptor = std::get<std::unique_ptr<PropertyDescriptor>>(data);
58 if (descriptor) {
59 if (descriptor->GetValue()->HasDescription()) {
60 std::cout << indent << " " << descriptor->GetName() << " = "
61 << descriptor->GetValue()->GetDescription() << std::endl;
62 } else {
63 std::cout << indent << " " << descriptor->GetName() << " = "
64 << descriptor->GetValue()->GetType() << std::endl;
65 }
66 }
67 } else if (std::holds_alternative<DescriptorMap>(data)) {
68 const auto &descriptorMap = std::get<DescriptorMap>(data);
69 for (const auto& [key, descriptor] : descriptorMap) {
70 std::cout << indent << key << ". ";
71 if (descriptor) {
72 std::cout << descriptor->GetName() << " = " << descriptor->GetValue()->GetDescription() << std::endl;
73 }
74 }
75 }
76
77 for (const auto &child : children) {
78 child->Print(depth + 1);
79 }
80 }
81
Tree(const std::map<int32_t,std::map<int32_t,std::string>> & dataMap,int32_t index)82 Tree::Tree(const std::map<int32_t, std::map<int32_t, std::string>>& dataMap, int32_t index)
83 {
84 root_ = std::make_unique<TreeNode>(index);
85
86 auto it = dataMap.find(index);
87 if (it != dataMap.end()) {
88 for (const auto& [key, value] : it->second) {
89 std::map<int32_t, std::map<int32_t, std::string>> childData;
90 childData[index_] = {{key, value}};
91 root_->children.push_back(std::make_unique<TreeNode>(childData));
92 index_++;
93 }
94 }
95 }
96
PrintRootAndImmediateChildren() const97 void Tree::PrintRootAndImmediateChildren() const
98 {
99 if (std::holds_alternative<int32_t>(root_->data)) {
100 std::cout << "CallFrame ID: " << std::get<int32_t>(root_->data) << std::endl;
101 }
102
103 for (const auto& child : root_->children) {
104 if (std::holds_alternative<std::map<int32_t, std::map<int32_t, std::string>>>(child->data)) {
105 const auto& outerMap = std::get<std::map<int32_t, std::map<int32_t, std::string>>>(child->data);
106 for (const auto& [index, innerMap] : outerMap) {
107 std::cout << " Index: " << index << std::endl;
108 for (const auto& [objectId, type] : innerMap) {
109 std::cout << " Object ID: " << objectId << ", Type: " << type << std::endl;
110 }
111 }
112 }
113 }
114 }
115
Clear()116 void Tree::Clear()
117 {
118 if (root_ != nullptr) {
119 root_.reset();
120 }
121 }
122
Print() const123 void Tree::Print() const
124 {
125 if (root_) {
126 root_->Print();
127 }
128 }
129
FindNodeWithObjectId(int32_t objectId) const130 TreeNode* Tree::FindNodeWithObjectId(int32_t objectId) const
131 {
132 return FindNodeWithObjectIdRecursive(root_.get(), objectId);
133 }
134
AddVariableNode(TreeNode * parentNode,std::unique_ptr<PropertyDescriptor> descriptor)135 void Tree::AddVariableNode(TreeNode* parentNode, std::unique_ptr<PropertyDescriptor> descriptor)
136 {
137 if (!parentNode) {
138 return;
139 }
140 parentNode->AddChild(std::move(descriptor));
141 }
142
AddObjectNode(TreeNode * parentNode,std::unique_ptr<PropertyDescriptor> descriptor)143 void Tree::AddObjectNode(TreeNode* parentNode, std::unique_ptr<PropertyDescriptor> descriptor)
144 {
145 if (!parentNode) {
146 return;
147 }
148 DescriptorMap descriptorMap;
149 descriptorMap[index_] = std::move(descriptor);
150 parentNode->AddChild(std::move(descriptorMap));
151 index_++;
152 }
153
GetRoot() const154 TreeNode* Tree::GetRoot() const
155 {
156 return root_.get();
157 }
158
FindNodeWithObjectIdRecursive(TreeNode * node,int32_t objectId) const159 TreeNode* Tree::FindNodeWithObjectIdRecursive(TreeNode* node, int32_t objectId) const
160 {
161 if (!node) {
162 return nullptr;
163 }
164
165 if (std::holds_alternative<std::map<int32_t, std::map<int32_t, std::string>>>(node->data)) {
166 const auto& outerMap = std::get<std::map<int32_t, std::map<int32_t, std::string>>>(node->data);
167 for (const auto& [key, innerMap] : outerMap) {
168 if (innerMap.find(objectId) != innerMap.end()) {
169 return node;
170 }
171 }
172 } else if (std::holds_alternative<DescriptorMap>(node->data)) {
173 const auto& descriptorMap = std::get<DescriptorMap>(node->data);
174 for (const auto& [key, descriptor] : descriptorMap) {
175 if (descriptor && descriptor->GetValue()->GetObjectId() == objectId) {
176 return node;
177 }
178 }
179 }
180
181 for (const auto& child : node->children) {
182 TreeNode* foundNode = FindNodeWithObjectIdRecursive(child.get(), objectId);
183 if (foundNode) {
184 return foundNode;
185 }
186 }
187
188 return nullptr;
189 }
190
FindNodeWithInnerKeyZero(TreeNode * node) const191 TreeNode* Tree::FindNodeWithInnerKeyZero(TreeNode* node) const
192 {
193 if (!node) {
194 return nullptr;
195 }
196
197 if (std::holds_alternative<std::map<int32_t, std::map<int32_t, std::string>>>(node->data)) {
198 const auto &outerMap = std::get<std::map<int32_t, std::map<int32_t, std::string>>>(node->data);
199 for (const auto &innerMapPair : outerMap) {
200 if (innerMapPair.second.find(0) != innerMapPair.second.end()) {
201 return node;
202 }
203 }
204 }
205
206 for (const auto &child : node->children) {
207 TreeNode* foundNode = FindNodeWithInnerKeyZero(child.get());
208 if (foundNode) {
209 return foundNode;
210 }
211 }
212
213 return nullptr;
214 }
FindNodeWithCondition() const215 TreeNode* Tree::FindNodeWithCondition() const
216 {
217 return FindNodeWithInnerKeyZero(root_.get());
218 }
219
FindObjectByIndex(int32_t index) const220 int32_t Tree::FindObjectByIndex(int32_t index) const
221 {
222 return FindObjectByIndexRecursive(root_.get(), index);
223 }
224
FindObjectByIndexRecursive(const TreeNode * node,int32_t index) const225 int32_t Tree::FindObjectByIndexRecursive(const TreeNode* node, int32_t index) const
226 {
227 if (!node) {
228 return 0;
229 }
230
231 if (std::holds_alternative<std::map<int32_t, std::map<int32_t, std::string>>>(node->data)) {
232 const auto &outerMap = std::get<std::map<int32_t, std::map<int32_t, std::string>>>(node->data);
233 auto it = outerMap.find(index);
234 if (it != outerMap.end() && !it->second.empty()) {
235 return it->second.begin()->first;
236 }
237 } else if (std::holds_alternative<DescriptorMap>(node->data)) {
238 const auto &descriptorMap = std::get<DescriptorMap>(node->data);
239 auto it = descriptorMap.find(index);
240 if (it != descriptorMap.end() && it->second) {
241 return it->second->GetValue()->GetObjectId();
242 }
243 }
244
245 for (const auto& child : node->children) {
246 int32_t result = FindObjectByIndexRecursive(child.get(), index);
247 if (result != 0) {
248 return result;
249 }
250 }
251
252 return 0;
253 }
254
SetHeapUsageInfo(std::unique_ptr<GetHeapUsageReturns> heapUsageReturns)255 void VariableManager::SetHeapUsageInfo(std::unique_ptr<GetHeapUsageReturns> heapUsageReturns)
256 {
257 heapUsageInfo_.SetUsedSize(heapUsageReturns->GetUsedSize());
258 heapUsageInfo_.SetTotalSize(heapUsageReturns->GetTotalSize());
259 }
260
ShowHeapUsageInfo() const261 void VariableManager::ShowHeapUsageInfo() const
262 {
263 std::cout << std::endl;
264 std::cout << "UsedSize is: " << heapUsageInfo_.GetUsedSize() << std::endl;
265 std::cout << "TotalSize is: " << std::fixed << std::setprecision(0) << heapUsageInfo_.GetTotalSize() << std::endl;
266 }
267
ShowVariableInfos() const268 void VariableManager::ShowVariableInfos() const
269 {
270 variableInfo_.Print();
271 }
272
ClearVariableInfo()273 void VariableManager::ClearVariableInfo()
274 {
275 variableInfo_.Clear();
276 }
InitializeTree(std::map<int32_t,std::map<int32_t,std::string>> dataMap,int index)277 void VariableManager::InitializeTree(std::map<int32_t, std::map<int32_t, std::string>> dataMap, int index)
278 {
279 variableInfo_ = Tree(dataMap, index);
280 }
281
PrintVariableInfo()282 void VariableManager::PrintVariableInfo()
283 {
284 variableInfo_.Print();
285 }
286
FindNodeWithObjectId(int32_t objectId)287 TreeNode* VariableManager::FindNodeWithObjectId(int32_t objectId)
288 {
289 return variableInfo_.FindNodeWithObjectId(objectId);
290 }
291
AddVariableInfo(TreeNode * parentNode,std::unique_ptr<PropertyDescriptor> variableInfo)292 void VariableManager::AddVariableInfo(TreeNode *parentNode, std::unique_ptr<PropertyDescriptor> variableInfo)
293 {
294 if (variableInfo->GetValue()->HasObjectId()) {
295 variableInfo_.AddObjectNode(parentNode, std::move(variableInfo));
296 } else {
297 variableInfo_.AddVariableNode(parentNode, std::move(variableInfo));
298 }
299 }
300
FindNodeObjectZero()301 TreeNode* VariableManager::FindNodeObjectZero()
302 {
303 return variableInfo_.FindNodeWithCondition();
304 }
305
FindObjectIdWithIndex(int index)306 int32_t VariableManager::FindObjectIdWithIndex(int index)
307 {
308 return variableInfo_.FindObjectByIndex(index);
309 }
310
Printinfo() const311 void VariableManager::Printinfo() const
312 {
313 variableInfo_.PrintRootAndImmediateChildren();
314 }
315 }