• 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 #include "ecmascript/stackmap/llvm_stackmap_parser.h"
16 
17 #include "ecmascript/compiler/aot_file/aot_file_manager.h"
18 #include "ecmascript/compiler/assembler/assembler.h"
19 #include "ecmascript/frames.h"
20 #include "ecmascript/mem/slots.h"
21 #include "ecmascript/mem/visitor.h"
22 
23 using namespace panda::ecmascript;
24 
25 namespace panda::ecmascript::kungfu {
TypeToString(Kind loc) const26 std::string LocationTy::TypeToString(Kind loc) const
27 {
28     switch (loc) {
29         case Kind::REGISTER:
30             return "Register	Reg	Value in a register";
31         case Kind::DIRECT:
32             return "Direct	Reg + Offset	Frame index value";
33         case Kind::INDIRECT:
34             return "Indirect	[Reg + Offset]	Spilled value";
35         case Kind::CONSTANT:
36             return "Constant	Offset	Small constant";
37         case Kind::CONSTANTNDEX:
38             return "ConstIndex	constants[Offset]	Large constant";
39         default:
40             return "no know location";
41     }
42 }
43 
FilterCallSiteInfo(LLVMStackMapType::CallSiteInfo & info)44 void LLVMStackMapParser::FilterCallSiteInfo(LLVMStackMapType::CallSiteInfo &info)
45 {
46     ASSERT(GC_PAIR_SIZE == 2);
47     ASSERT(info.size() % GC_PAIR_SIZE == 0);
48     for (auto it = info.begin(); it != info.end();) {
49         auto base = it;
50         auto deri = ++it;
51         bool baseIsConst = (base->first == LLVMStackMapType::INVALID_DWARF_REG);
52         bool deriIsConst = (deri->first == LLVMStackMapType::INVALID_DWARF_REG);
53         if (baseIsConst && deriIsConst) {
54             it = info.erase(base, base + GC_PAIR_SIZE);
55         } else if (baseIsConst && !deriIsConst) {
56             base->first = deri->first;
57             base->second = deri->second;
58             it++;
59         } else if (!baseIsConst && deriIsConst) {
60             deri->first = base->first;
61             deri->second = base->second;
62             it++;
63         } else {
64             it++;
65         }
66     }
67     ASSERT(info.size() % GC_PAIR_SIZE == 0);
68 }
69 
CalcCallSite()70 void LLVMStackMapParser::CalcCallSite()
71 {
72     uint64_t recordNum = 0;
73     LLVMStackMapType::Pc2CallSiteInfo pc2CallSiteInfo;
74     LLVMStackMapType::Pc2Deopt deoptbundles;
75 
76     auto calStkMapRecordFunc = [this, &recordNum, &pc2CallSiteInfo, &deoptbundles](uintptr_t address,
77                                                                                    uint32_t recordId) {
78         struct StkMapRecordTy &record = llvmStackMap_.stkMapRecord[recordNum + recordId];
79         struct StkMapRecordHeadTy &recordHead = record.head;
80         uint32_t instructionOffset = recordHead.instructionOffset;
81         uintptr_t pc = address + instructionOffset;
82         uint64_t pID = recordHead.patchPointID;
83 
84         if (pc2CallSiteInfo.find(pc) == pc2CallSiteInfo.end()) {
85             auto p = std::pair<uintptr_t, LLVMStackMapType::CallSiteInfo>(pc, {});
86             pc2CallSiteInfo.insert(p);
87         }
88         LLVMStackMapType::CallSiteInfo& callSiteInfo = pc2CallSiteInfo.find(pc)->second;
89 
90         ASSERT(recordHead.numLocations > LocationTy::CONSTANT_DEOPT_CNT_INDEX);
91         const int lastDeoptIndex = record.locations[LocationTy::CONSTANT_DEOPT_CNT_INDEX].offsetOrSmallConstant +
92                                    LocationTy::CONSTANT_DEOPT_CNT_INDEX;
93 
94         for (int j = LocationTy::CONSTANT_FIRST_ELEMENT_INDEX; j < recordHead.numLocations; j++) {
95             const struct LocationTy &loc = record.locations[j];
96             if (j <= lastDeoptIndex) {
97                 switch (loc.location) {
98                     case LocationTy::Kind::REGISTER:
99                     case LocationTy::Kind::DIRECT: {
100                         LOG_ECMA(FATAL) << "this branch is unreachable";
101                         UNREACHABLE();
102                         break;
103                     }
104                     case LocationTy::Kind::INDIRECT: {
105                         OPTIONAL_LOG_COMPILER(DEBUG) << "DwarfRegNum:" << loc.dwarfRegNum
106                                                      << " loc.OffsetOrSmallConstant:" << loc.offsetOrSmallConstant
107                                                      << " address:" << address
108                                                      << " instructionOffset:" << instructionOffset
109                                                      << " callsite:" << "  patchPointID :" << std::hex
110                                                      << pID << pc;
111                         LLVMStackMapType::DwarfRegAndOffsetType info(loc.dwarfRegNum, loc.offsetOrSmallConstant);
112                         deoptbundles[pc].push_back(info);
113                         break;
114                     }
115                     case LocationTy::Kind::CONSTANT: {
116                         deoptbundles[pc].push_back(loc.offsetOrSmallConstant);
117                         break;
118                     }
119                     case LocationTy::Kind::CONSTANTNDEX: {
120                         auto v = llvmStackMap_.constants[loc.offsetOrSmallConstant].largeConstant;
121                         deoptbundles[pc].push_back(static_cast<LLVMStackMapType::LargeInt>(v));
122                         break;
123                     }
124                     default: {
125                         LOG_ECMA(FATAL) << "this branch is unreachable";
126                         UNREACHABLE();
127                         break;
128                     }
129                 }
130             } else {
131                 switch (loc.location) {
132                     case LocationTy::Kind::REGISTER:
133                     case LocationTy::Kind::DIRECT: {
134                         LOG_ECMA(FATAL) << "this branch is unreachable";
135                         UNREACHABLE();
136                         break;
137                     }
138                     case LocationTy::Kind::INDIRECT:
139                     case LocationTy::Kind::CONSTANT:
140                     case LocationTy::Kind::CONSTANTNDEX: {
141                         OPTIONAL_LOG_COMPILER(DEBUG) << "DwarfRegNum:" << loc.dwarfRegNum
142                                                      << " loc.OffsetOrSmallConstant:" << loc.offsetOrSmallConstant
143                                                      << " address:" << address
144                                                      << " instructionOffset:" << instructionOffset
145                                                      << " callsite:" << "  patchPointID :" << std::hex
146                                                      << pID << pc;
147                         uint16_t regNum = (loc.location == LocationTy::Kind::INDIRECT)
148                                           ? loc.dwarfRegNum
149                                           : LLVMStackMapType::INVALID_DWARF_REG;
150                         int offset = (loc.location == LocationTy::Kind::INDIRECT) ? loc.offsetOrSmallConstant : 0;
151                         LLVMStackMapType::DwarfRegAndOffsetType info(regNum, offset);
152                         callSiteInfo.emplace_back(info);
153                         break;
154                     }
155                     default: {
156                         LOG_ECMA(FATAL) << "this branch is unreachable";
157                         UNREACHABLE();
158                         break;
159                     }
160                 }
161             }
162         }
163         FilterCallSiteInfo(callSiteInfo);
164     };
165 
166     const size_t count = llvmStackMap_.stkSizeRecords.size();
167     for (size_t i = 0; i < count; i++) {
168         // relative offset
169         struct StkMapSizeRecordTy &sizeRec = llvmStackMap_.stkSizeRecords[i];
170         uintptr_t address = sizeRec.functionAddress;
171         uint64_t recordCount = sizeRec.recordCount;
172         fun2RecordNum_.emplace_back(std::make_pair(address, recordCount));
173         for (uint64_t k = 0; k < recordCount; k++) {
174             calStkMapRecordFunc(address, k);
175         }
176         recordNum += recordCount;
177     }
178 
179     stackMapInfo.AppendCallSiteInfo(pc2CallSiteInfo);
180     stackMapInfo.AppendDeoptInfo(deoptbundles);
181 }
182 
CalculateStackMap(std::unique_ptr<uint8_t[]> stackMapAddr)183 bool LLVMStackMapParser::CalculateStackMap(std::unique_ptr<uint8_t []> stackMapAddr)
184 {
185     if (!stackMapAddr) {
186         LOG_COMPILER(ERROR) << "stackMapAddr nullptr error ! ";
187         return false;
188     }
189     dataInfo_ = std::make_unique<DataInfo>(std::move(stackMapAddr));
190     llvmStackMap_.head = dataInfo_->Read<struct Header>();
191     uint32_t numFunctions, numConstants, numRecords;
192     numFunctions = dataInfo_->Read<uint32_t>();
193     numConstants = dataInfo_->Read<uint32_t>();
194     numRecords = dataInfo_->Read<uint32_t>();
195     for (uint32_t i = 0; i < numFunctions; i++) {
196         auto stkRecord = dataInfo_->Read<struct StkMapSizeRecordTy>();
197         llvmStackMap_.stkSizeRecords.push_back(stkRecord);
198     }
199 
200     for (uint32_t i = 0; i < numConstants; i++) {
201         auto val = dataInfo_->Read<struct ConstantsTy>();
202         llvmStackMap_.constants.push_back(val);
203     }
204     for (uint32_t i = 0; i < numRecords; i++) {
205         struct StkMapRecordTy stkSizeRecord;
206         auto head = dataInfo_->Read<struct StkMapRecordHeadTy>();
207         stkSizeRecord.head = head;
208         for (uint16_t j = 0; j < head.numLocations; j++) {
209             auto location = dataInfo_->Read<struct LocationTy>();
210             stkSizeRecord.locations.push_back(location);
211         }
212         while (dataInfo_->GetOffset() & 7) { // 7: 8 byte align
213             dataInfo_->Read<uint16_t>();
214         }
215         uint32_t numLiveOuts = dataInfo_->Read<uint32_t>();
216         if (numLiveOuts > 0) {
217             for (uint32_t j = 0; j < numLiveOuts; j++) {
218                 auto liveOut = dataInfo_->Read<struct LiveOutsTy>();
219                 stkSizeRecord.liveOuts.push_back(liveOut);
220             }
221         }
222         while (dataInfo_->GetOffset() & 7) { // 7: 8 byte align
223             dataInfo_->Read<uint16_t>();
224         }
225         llvmStackMap_.stkMapRecord.push_back(stkSizeRecord);
226     }
227     CalcCallSite();
228     return true;
229 }
230 
CalHeadSize() const231 uint32_t ARKCallsite::CalHeadSize() const
232 {
233     uint32_t headSize = sizeof(head);
234     return headSize;
235 }
236 
CalStackMapSize(Triple triple) const237 uint32_t ARKCallsite::CalStackMapSize(Triple triple) const
238 {
239     size_t stackmapSize = 0;
240     for (auto &x : stackmaps) {
241         std::vector<uint8_t> value;
242         size_t valueSize = 0;
243         LLVMStackMapType::EncodeRegAndOffset(value, valueSize, x.first, x.second, triple);
244         stackmapSize += value.size();
245     }
246     return stackmapSize;
247 }
248 
CalculateStackMap(std::unique_ptr<uint8_t[]> stackMapAddr,uintptr_t hostCodeSectionAddr,uintptr_t hostCodeSectionOffset)249 bool LLVMStackMapParser::CalculateStackMap(std::unique_ptr<uint8_t []> stackMapAddr,
250     uintptr_t hostCodeSectionAddr, uintptr_t hostCodeSectionOffset)
251 {
252     bool ret = CalculateStackMap(std::move(stackMapAddr));
253     if (!ret) {
254         return false;
255     }
256 
257     OPTIONAL_LOG_COMPILER(DEBUG) << "stackmap calculate update funcitonaddress ";
258 
259     for (size_t i = 0; i < llvmStackMap_.stkSizeRecords.size(); i++) {
260         uintptr_t hostAddr = llvmStackMap_.stkSizeRecords[i].functionAddress;
261         uintptr_t offset = hostAddr - hostCodeSectionAddr + hostCodeSectionOffset;
262         llvmStackMap_.stkSizeRecords[i].functionAddress = offset;
263         OPTIONAL_LOG_COMPILER(DEBUG) << std::dec << i << "th function " << std::hex << hostAddr << " ---> "
264                                      << " offset:" << offset;
265     }
266     stackMapInfo.PopCallSiteInfo();
267     stackMapInfo.PopDeoptInfo();
268     fun2RecordNum_.clear();
269     CalcCallSite();
270     return true;
271 }
272 }  // namespace panda::ecmascript::kungfu
273