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