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