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 #include "bytecode_analysis_results.h"
17
18 #include <mutex>
19
20 namespace panda::bytecodeopt {
21
22 std::mutex BytecodeAnalysisResults::mutex_;
23 BytecodeAnalysisResultMap BytecodeAnalysisResults::analysis_results_;
24 BytecodeMapsMap BytecodeAnalysisResults::bytecode_maps_;
25
SetModuleConstantAnalysisResult(const ModuleConstantAnalysisResult & result)26 void BytecodeAnalysisResult::SetModuleConstantAnalysisResult(const ModuleConstantAnalysisResult &result)
27 {
28 for (auto &iter : result) {
29 uint32_t slot = iter.first;
30 if (slot < local_export_slot_external_names_.size()) {
31 const auto &external_names = local_export_slot_external_names_[slot];
32 for (const auto &external_name_iter : external_names) {
33 constant_local_export_values_.emplace(external_name_iter, *iter.second);
34 }
35 }
36 }
37 }
38
SetConstantLocalExportSlots(const std::unordered_set<uint32_t> & slots)39 void BytecodeAnalysisResult::SetConstantLocalExportSlots(const std::unordered_set<uint32_t> &slots)
40 {
41 constant_local_export_slots_ = slots;
42 }
43
SetLocalExportInfo(uint32_t slot,const std::string & external_name)44 void BytecodeAnalysisResult::SetLocalExportInfo(uint32_t slot, const std::string &external_name)
45 {
46 if (slot == local_export_slot_external_names_.size()) {
47 auto &vec = local_export_slot_external_names_.emplace_back();
48 vec.push_back(external_name);
49 } else {
50 ASSERT(slot < local_export_slot_external_names_.size());
51 local_export_slot_external_names_[slot].push_back(external_name);
52 }
53 }
54
SetRegularImportInfo(uint32_t slot,const std::string & import_name,const std::string & source_record)55 void BytecodeAnalysisResult::SetRegularImportInfo(uint32_t slot,
56 const std::string &import_name,
57 const std::string &source_record)
58 {
59 [[maybe_unused]] auto iter = regular_import_slot_infos_.find(slot);
60 ASSERT(iter == regular_import_slot_infos_.end());
61 RegularImportInfo info {import_name, source_record};
62 regular_import_slot_infos_.emplace(slot, info);
63 }
64
SetNamespaceImportInfo(uint32_t slot,const std::string & source_record)65 void BytecodeAnalysisResult::SetNamespaceImportInfo(uint32_t slot, const std::string &source_record)
66 {
67 namespace_import_slot_source_record_names_.emplace(slot, source_record);
68 }
69
GetLocalExportInfo(uint32_t slot,uint32_t name_idx,std::string & external_name) const70 bool BytecodeAnalysisResult::GetLocalExportInfo(uint32_t slot, uint32_t name_idx, std::string &external_name) const
71 {
72 if (slot >= local_export_slot_external_names_.size()) {
73 return false;
74 }
75 const auto &names = local_export_slot_external_names_[slot];
76 if (name_idx > names.size()) {
77 return false;
78 }
79 external_name = names[name_idx];
80 return true;
81 }
82
GetRegularImportInfo(uint32_t slot,std::string & import_name,std::string & source_record) const83 bool BytecodeAnalysisResult::GetRegularImportInfo(uint32_t slot,
84 std::string &import_name,
85 std::string &source_record) const
86 {
87 auto iter = regular_import_slot_infos_.find(slot);
88 if (iter == regular_import_slot_infos_.end()) {
89 return false;
90 }
91 import_name = iter->second.import_name;
92 source_record = iter->second.source_record_name;
93 return true;
94 }
95
GetNamespaceImportInfo(uint32_t slot,std::string & source_record) const96 bool BytecodeAnalysisResult::GetNamespaceImportInfo(uint32_t slot, std::string &source_record) const
97 {
98 auto iter = namespace_import_slot_source_record_names_.find(slot);
99 if (iter == namespace_import_slot_source_record_names_.end()) {
100 return false;
101 }
102 source_record = iter->second;
103 return true;
104 }
105
GetExportedConstantValue(const std::string & name,ConstantValue & value) const106 bool BytecodeAnalysisResult::GetExportedConstantValue(const std::string &name, ConstantValue &value) const
107 {
108 auto iter = constant_local_export_values_.find(name);
109 if (iter != constant_local_export_values_.end()) {
110 value = iter->second;
111 return true;
112 }
113 return false;
114 }
115
Dump(std::ostream & os)116 void BytecodeAnalysisResult::Dump(std::ostream &os)
117 {
118 os << "------------------------------------" << std::endl;
119 os << "Constant local export values: " << std::endl;
120 for (auto iter : constant_local_export_values_) {
121 os << iter.first << ": " << iter.second.ToString() << std::endl;
122 }
123 os << "Constant local export slots: " << std::endl;
124 for (auto iter : constant_local_export_slots_) {
125 os << iter << ", ";
126 }
127 os << std::endl;
128 os << "Local export slot external names: " << std::endl;
129 for (size_t i = 0; i < local_export_slot_external_names_.size(); i++) {
130 os << i << ": ";
131 for (auto iter : local_export_slot_external_names_[i]) {
132 os << iter << ", ";
133 }
134 os << std::endl;
135 }
136 os << "Regular import slot infos: " << std::endl;
137 for (auto iter : regular_import_slot_infos_) {
138 os << iter.first << ": import_name: " << iter.second.import_name
139 << ", source_record_name: " << iter.second.source_record_name << std::endl;
140 }
141 os << "Namespace import slot source record names: " << std::endl;
142 for (auto iter : namespace_import_slot_source_record_names_) {
143 os << iter.first << ": " << iter.second << std::endl;
144 }
145 os << "------------------------------------" << std::endl;
146 }
147
GetOrCreateBytecodeMaps(const std::string & filename,bool & exists)148 pandasm::AsmEmitter::PandaFileToPandaAsmMaps &BytecodeAnalysisResults::GetOrCreateBytecodeMaps(
149 const std::string &filename, bool &exists)
150 {
151 return GetOrCreateElementInMap<pandasm::AsmEmitter::PandaFileToPandaAsmMaps>(bytecode_maps_, filename, exists);
152 }
153
DeleteBytecodeMaps(const std::string & filename)154 void BytecodeAnalysisResults::DeleteBytecodeMaps(const std::string &filename)
155 {
156 std::unique_lock<std::mutex> lock(mutex_);
157 bytecode_maps_.erase(filename);
158 }
159
GetOrCreateBytecodeAnalysisResult(const std::string & recordname,bool & exists)160 BytecodeAnalysisResult &BytecodeAnalysisResults::GetOrCreateBytecodeAnalysisResult(const std::string &recordname,
161 bool &exists)
162 {
163 return GetOrCreateElementInMap<BytecodeAnalysisResult>(analysis_results_, recordname, exists);
164 }
165
GetLocalExportConstForRecord(const std::string & recordname,uint32_t local_export_slot,ConstantValue & value)166 bool BytecodeAnalysisResults::GetLocalExportConstForRecord(const std::string &recordname,
167 uint32_t local_export_slot,
168 ConstantValue &value)
169 {
170 constexpr uint32_t DEFAULT_EXTERNAL_NAME_IDX = 0;
171 auto iter = analysis_results_.find(recordname);
172 if (iter == analysis_results_.end()) {
173 return false;
174 }
175 auto &analysis_resut = iter->second;
176 std::string external_name;
177 if (!analysis_resut->GetLocalExportInfo(local_export_slot, DEFAULT_EXTERNAL_NAME_IDX, external_name)) {
178 return false;
179 }
180 return analysis_resut->GetExportedConstantValue(external_name, value);
181 }
182
GetRegularImportConstForRecord(const std::string & recordname,uint32_t regular_import_slot,ConstantValue & value)183 bool BytecodeAnalysisResults::GetRegularImportConstForRecord(const std::string &recordname,
184 uint32_t regular_import_slot,
185 ConstantValue &value)
186 {
187 auto iter = analysis_results_.find(recordname);
188 if (iter == analysis_results_.end()) {
189 return false;
190 }
191 std::string import_name;
192 std::string source_record;
193 if (!iter->second->GetRegularImportInfo(regular_import_slot, import_name, source_record)) {
194 return false;
195 }
196
197 iter = analysis_results_.find(source_record);
198 if (iter == analysis_results_.end()) {
199 return false;
200 }
201 return iter->second->GetExportedConstantValue(import_name, value);
202 }
203
GetModuleNamespaceConstForRecord(const std::string & recordname,uint32_t module_namespace_slot,const std::string & property_name,ConstantValue & value)204 bool BytecodeAnalysisResults::GetModuleNamespaceConstForRecord(const std::string &recordname,
205 uint32_t module_namespace_slot,
206 const std::string &property_name,
207 ConstantValue &value)
208 {
209 auto iter = analysis_results_.find(recordname);
210 if (iter == analysis_results_.end()) {
211 return false;
212 }
213 std::string source_record;
214 if (!iter->second->GetNamespaceImportInfo(module_namespace_slot, source_record)) {
215 return false;
216 }
217 iter = analysis_results_.find(source_record);
218 if (iter == analysis_results_.end()) {
219 return false;
220 }
221 return iter->second->GetExportedConstantValue(property_name, value);
222 }
223
Clear()224 void BytecodeAnalysisResults::Clear()
225 {
226 std::unique_lock<std::mutex> lock(mutex_);
227 bytecode_maps_.clear();
228 analysis_results_.clear();
229 }
230
231 } // namespace panda::bytecodeopt