1 /*
2 * Copyright (c) 2023 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 "ecmascript/compiler/aot_file/aot_file_info.h"
17
18 namespace panda::ecmascript {
Destroy()19 void AOTFileInfo::Destroy()
20 {
21 entryNum_ = 0;
22 moduleNum_ = 0;
23 totalCodeSize_ = 0;
24 entries_.clear();
25 des_.clear();
26 ExecutedMemoryAllocator::DestroyBuf(stubsMem_);
27 }
28
CalCallSiteInfo(uintptr_t retAddr, std::tuple<uint64_t, uint8_t *, int, CalleeRegAndOffsetVec> &ret, bool isInStub, bool isDeopt) const29 bool AOTFileInfo::CalCallSiteInfo(uintptr_t retAddr, std::tuple<uint64_t, uint8_t *, int, CalleeRegAndOffsetVec> &ret,
30 bool isInStub, bool isDeopt) const
31 {
32 uint64_t textStart = 0;
33 uint8_t *stackmapAddr = nullptr;
34 int delta = 0;
35 const auto &des = GetCodeUnits();
36
37 size_t len = des.size();
38 for (size_t i = 0; i < len; i++) {
39 auto &d = des[i];
40 uint64_t addr = d.GetSecAddr(ElfSecName::TEXT);
41 uint32_t size = d.GetSecSize(ElfSecName::TEXT);
42 if (retAddr < addr || retAddr >= addr + size) {
43 continue;
44 }
45
46 stackmapAddr = d.GetArkStackMapRawPtr();
47 ASSERT(stackmapAddr != nullptr);
48 textStart = addr;
49 CalleeRegAndOffsetVec calleeRegInfo;
50 if (!isInStub && !isDeopt) { // no need for getting funcEntryDes when not in stub nor in deopt
51 ret = std::make_tuple(textStart, stackmapAddr, delta, calleeRegInfo);
52 return true;
53 }
54
55 ASSERT(retAddr > 0);
56 auto it = GetFuncEntryDesWithCallsite(retAddr - 1, d.GetStartIndex(), d.GetFuncCount()); // -1: for pc
57 delta = it.fpDeltaPrevFrameSp_;
58 if (!isDeopt) { // no need for getting calleeRegInfo when in stub but not in deopt
59 ret = std::make_tuple(textStart, stackmapAddr, delta, calleeRegInfo);
60 return true;
61 }
62
63 StoreCalleeRegInfo(it.calleeRegisterNum_, it.CalleeReg2Offset_, calleeRegInfo);
64 ret = std::make_tuple(textStart, stackmapAddr, delta, calleeRegInfo);
65 return true;
66 }
67 return false;
68 }
69
GetFuncEntryDesWithCallsite(uintptr_t codeAddr, uint32_t startIndex, uint32_t funcCount) const70 AOTFileInfo::FuncEntryDes AOTFileInfo::GetFuncEntryDesWithCallsite(uintptr_t codeAddr, uint32_t startIndex,
71 uint32_t funcCount) const
72 {
73 const auto &funcEntryDes = GetStubs();
74
75 auto cmp = [](const AOTFileInfo::FuncEntryDes &a, const AOTFileInfo::FuncEntryDes &b) {
76 return a.codeAddr_ < b.codeAddr_;
77 };
78 auto s = funcEntryDes.begin() + startIndex;
79 auto t = funcEntryDes.begin() + startIndex + funcCount;
80 AOTFileInfo::FuncEntryDes target;
81 target.codeAddr_ = codeAddr;
82 auto it = std::upper_bound(s, t, target, cmp);
83 --it;
84 ASSERT(it != t);
85 ASSERT((it->codeAddr_ <= target.codeAddr_) && (target.codeAddr_ < it->codeAddr_ + it->funcSize_));
86 return *it;
87 }
88
StoreCalleeRegInfo(uint32_t calleeRegNum, int32_t *calleeReg2Offset, CalleeRegAndOffsetVec &calleeRegInfo) const89 void AOTFileInfo::StoreCalleeRegInfo(uint32_t calleeRegNum, int32_t *calleeReg2Offset,
90 CalleeRegAndOffsetVec &calleeRegInfo) const
91 {
92 for (uint32_t j = 0; j < calleeRegNum; j++) {
93 DwarfRegType reg = static_cast<DwarfRegType>(calleeReg2Offset[2 * j]);
94 OffsetType offset = static_cast<OffsetType>(calleeReg2Offset[2 * j + 1]);
95 DwarfRegAndOffsetType regAndOffset = std::make_pair(reg, offset);
96 calleeRegInfo.emplace_back(regAndOffset);
97 }
98 }
99 } // namespace panda::ecmascript
100