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
18namespace panda::ecmascript {
19void AOTFileInfo::Destroy()
20{
21    entryNum_ = 0;
22    moduleNum_ = 0;
23    totalCodeSize_ = 0;
24    entries_.clear();
25    des_.clear();
26    ExecutedMemoryAllocator::DestroyBuf(stubsMem_);
27}
28
29bool 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
70AOTFileInfo::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
89void 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