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