• 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/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 
GetCallSiteInfoByPc(uintptr_t callSiteAddr) const44 const CallSiteInfo* LLVMStackMapParser::GetCallSiteInfoByPc(uintptr_t callSiteAddr) const
45 {
46     for (auto &pc2CallSiteInfo: pc2CallSiteInfoVec_) {
47         auto it = pc2CallSiteInfo.find(callSiteAddr);
48         if (it != pc2CallSiteInfo.end()) {
49             return &(it->second);
50         }
51     }
52     return nullptr;
53 }
54 
CalcCallSite()55 void LLVMStackMapParser::CalcCallSite()
56 {
57     uint64_t recordNum = 0;
58     Pc2CallSiteInfo pc2CallSiteInfo;
59     Pc2Deopt deoptbundles;
60     auto calStkMapRecordFunc =
61         [this, &recordNum, &pc2CallSiteInfo, &deoptbundles](uintptr_t address, uint32_t recordId) {
62         struct StkMapRecordHeadTy recordHead = llvmStackMap_.StkMapRecord[recordNum + recordId].head;
63         int lastDeoptIndex = -1;
64         for (int j = 0; j < recordHead.NumLocations; j++) {
65             struct LocationTy loc = llvmStackMap_.StkMapRecord[recordNum + recordId].Locations[j];
66             uint32_t instructionOffset = recordHead.InstructionOffset;
67             uintptr_t callsite = address + instructionOffset;
68             uint64_t  patchPointID = recordHead.PatchPointID;
69             if (j == LocationTy::CONSTANT_DEOPT_CNT_INDEX) {
70                 ASSERT(loc.location == LocationTy::Kind::CONSTANT);
71                 lastDeoptIndex = loc.OffsetOrSmallConstant + LocationTy::CONSTANT_DEOPT_CNT_INDEX;
72             }
73             if (loc.location == LocationTy::Kind::INDIRECT) {
74                 OPTIONAL_LOG_COMPILER(DEBUG) << "DwarfRegNum:" << loc.DwarfRegNum << " loc.OffsetOrSmallConstant:"
75                     << loc.OffsetOrSmallConstant << "address:" << address << " instructionOffset:" <<
76                     instructionOffset << " callsite:" << "  patchPointID :" << std::hex << patchPointID <<
77                     callsite;
78                 DwarfRegAndOffsetType info(loc.DwarfRegNum, loc.OffsetOrSmallConstant);
79                 auto it = pc2CallSiteInfo.find(callsite);
80                 if (j > lastDeoptIndex) {
81                     if (pc2CallSiteInfo.find(callsite) == pc2CallSiteInfo.end()) {
82                         pc2CallSiteInfo.insert(std::pair<uintptr_t, CallSiteInfo>(callsite, {info}));
83                     } else {
84                         it->second.emplace_back(info);
85                     }
86                 } else if (j >= LocationTy::CONSTANT_FIRST_ELEMENT_INDEX) {
87                     deoptbundles[callsite].push_back(info);
88                 }
89             } else if (loc.location == LocationTy::Kind::CONSTANT) {
90                 if (j >= LocationTy::CONSTANT_FIRST_ELEMENT_INDEX && j <= lastDeoptIndex) {
91                     deoptbundles[callsite].push_back(loc.OffsetOrSmallConstant);
92                 }
93             } else if (loc.location == LocationTy::Kind::DIRECT) {
94                 if (j >= LocationTy::CONSTANT_FIRST_ELEMENT_INDEX && j <= lastDeoptIndex) {
95                     DwarfRegAndOffsetType info(loc.DwarfRegNum, loc.OffsetOrSmallConstant);
96                     deoptbundles[callsite].push_back(info);
97                 }
98             } else if (loc.location == LocationTy::Kind::CONSTANTNDEX) {
99                 if (j >= LocationTy::CONSTANT_FIRST_ELEMENT_INDEX && j <= lastDeoptIndex) {
100                     LargeInt v = static_cast<LargeInt>(llvmStackMap_.
101                         Constants[loc.OffsetOrSmallConstant].LargeConstant);
102                     deoptbundles[callsite].push_back(v);
103                 }
104             } else {
105                 UNREACHABLE();
106             }
107         }
108     };
109     for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) {
110         // relative offset
111         uintptr_t address =  llvmStackMap_.StkSizeRecords[i].functionAddress;
112         uint64_t recordCount = llvmStackMap_.StkSizeRecords[i].recordCount;
113         fun2RecordNum_.emplace_back(std::make_pair(address, recordCount));
114         for (uint64_t k = 0; k < recordCount; k++) {
115             calStkMapRecordFunc(address, k);
116         }
117         recordNum += recordCount;
118     }
119     pc2CallSiteInfoVec_.emplace_back(pc2CallSiteInfo);
120     pc2DeoptVec_.emplace_back(deoptbundles);
121 }
122 
CalculateStackMap(std::unique_ptr<uint8_t[]> stackMapAddr)123 bool LLVMStackMapParser::CalculateStackMap(std::unique_ptr<uint8_t []> stackMapAddr)
124 {
125     if (!stackMapAddr) {
126         LOG_COMPILER(ERROR) << "stackMapAddr nullptr error ! ";
127         return false;
128     }
129     dataInfo_ = std::make_unique<DataInfo>(std::move(stackMapAddr));
130     llvmStackMap_.head = dataInfo_->Read<struct Header>();
131     uint32_t numFunctions, numConstants, numRecords;
132     numFunctions = dataInfo_->Read<uint32_t>();
133     numConstants = dataInfo_->Read<uint32_t>();
134     numRecords = dataInfo_->Read<uint32_t>();
135     for (uint32_t i = 0; i < numFunctions; i++) {
136         auto stkRecord = dataInfo_->Read<struct StkSizeRecordTy>();
137         llvmStackMap_.StkSizeRecords.push_back(stkRecord);
138     }
139 
140     for (uint32_t i = 0; i < numConstants; i++) {
141         auto val = dataInfo_->Read<struct ConstantsTy>();
142         llvmStackMap_.Constants.push_back(val);
143     }
144     for (uint32_t i = 0; i < numRecords; i++) {
145         struct StkMapRecordTy stkSizeRecord;
146         auto head = dataInfo_->Read<struct StkMapRecordHeadTy>();
147         stkSizeRecord.head = head;
148         for (uint16_t j = 0; j < head.NumLocations; j++) {
149             auto location = dataInfo_->Read<struct LocationTy>();
150             stkSizeRecord.Locations.push_back(location);
151         }
152         while (dataInfo_->GetOffset() & 7) { // 7: 8 byte align
153             dataInfo_->Read<uint16_t>();
154         }
155         uint32_t numLiveOuts = dataInfo_->Read<uint32_t>();
156         if (numLiveOuts > 0) {
157             for (uint32_t j = 0; j < numLiveOuts; j++) {
158                 auto liveOut = dataInfo_->Read<struct LiveOutsTy>();
159                 stkSizeRecord.LiveOuts.push_back(liveOut);
160             }
161         }
162         while (dataInfo_->GetOffset() & 7) { // 7: 8 byte align
163             dataInfo_->Read<uint16_t>();
164         }
165         llvmStackMap_.StkMapRecord.push_back(stkSizeRecord);
166     }
167     CalcCallSite();
168     return true;
169 }
170 
CalHeadSize() const171 uint32_t ARKCallsite::CalHeadSize() const
172 {
173     uint32_t headSize = sizeof(head);
174     return headSize;
175 }
176 
CalStackMapSize() const177 uint32_t ARKCallsite::CalStackMapSize() const
178 {
179     size_t stackmapSize = stackmaps.size() * (sizeof(OffsetType) + sizeof(DwarfRegType));
180     return stackmapSize;
181 }
182 
CalculateStackMap(std::unique_ptr<uint8_t[]> stackMapAddr,uintptr_t hostCodeSectionAddr)183 bool LLVMStackMapParser::CalculateStackMap(std::unique_ptr<uint8_t []> stackMapAddr,
184     uintptr_t hostCodeSectionAddr)
185 {
186     bool ret = CalculateStackMap(std::move(stackMapAddr));
187     if (!ret) {
188         return false;
189     }
190 
191     OPTIONAL_LOG_COMPILER(DEBUG) << "stackmap calculate update funcitonaddress ";
192 
193     for (size_t i = 0; i < llvmStackMap_.StkSizeRecords.size(); i++) {
194         uintptr_t hostAddr = llvmStackMap_.StkSizeRecords[i].functionAddress;
195         uintptr_t offset = hostAddr - hostCodeSectionAddr;
196         llvmStackMap_.StkSizeRecords[i].functionAddress = offset;
197         OPTIONAL_LOG_COMPILER(DEBUG) << std::dec << i << "th function " << std::hex << hostAddr << " ---> "
198                                      << " offset:" << offset;
199     }
200     pc2CallSiteInfoVec_.clear();
201     fun2RecordNum_.clear();
202     pc2DeoptVec_.clear();
203     CalcCallSite();
204     return true;
205 }
206 
CalculateFuncFpDelta(Func2FpDelta info,uint32_t moduleIndex)207 void LLVMStackMapParser::CalculateFuncFpDelta(Func2FpDelta info, uint32_t moduleIndex)
208 {
209     std::vector<Func2FpDelta> fun2FpDelta;
210     auto it = module2fun2FpDelta_.find(moduleIndex);
211     if (it != module2fun2FpDelta_.end()) {
212         fun2FpDelta = module2fun2FpDelta_.at(moduleIndex);
213     }
214     bool find = std::find(fun2FpDelta.begin(), fun2FpDelta.end(), info) == fun2FpDelta.end();
215     if (!info.empty() && find) {
216         fun2FpDelta.emplace_back(info);
217     }
218     module2fun2FpDelta_.erase(moduleIndex);
219     module2fun2FpDelta_[moduleIndex] = fun2FpDelta;
220 
221     std::set<uintptr_t> funAddr;
222     auto i = module2funAddr_.find(moduleIndex);
223     if (i != module2funAddr_.end()) {
224         funAddr = module2funAddr_.at(moduleIndex);
225         module2funAddr_.erase(moduleIndex);
226     }
227     for (auto &iterator: info) {
228         funAddr.insert(iterator.first);
229     }
230     module2funAddr_[moduleIndex] = funAddr;
231 }
232 }  // namespace panda::ecmascript::kungfu
233