• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/mem/machine_code.h"
17 #include "ecmascript/mem/assert_scope.h"
18 #include "ecmascript/compiler/aot_file/func_entry_des.h"
19 #include "ecmascript/stackmap/ark_stackmap.h"
20 #include "ecmascript/js_handle.h"
21 
22 namespace panda::ecmascript {
SetData(const MachineCodeDesc * desc,JSHandle<Method> & method,size_t dataSize)23 void MachineCode::SetData(const MachineCodeDesc *desc, JSHandle<Method> &method, size_t dataSize)
24 {
25     DISALLOW_GARBAGE_COLLECTION;
26     EntityId methodId = method->GetMethodId();
27 
28     size_t rodataSizeBeforeTextAlign = AlignUp(desc->rodataSizeBeforeText, MachineCode::TEXT_ALIGN);
29     size_t codeSizeAlign = AlignUp(desc->codeSize, MachineCode::DATA_ALIGN);
30     size_t rodataSizeAfterTextAlign = AlignUp(desc->rodataSizeAfterText, MachineCode::DATA_ALIGN);
31 
32     size_t funcEntryDesSizeAlign = desc->funcEntryDesSize;
33     SetFuncEntryDesSize(funcEntryDesSizeAlign);
34 
35     size_t instrSize = rodataSizeBeforeTextAlign + codeSizeAlign + rodataSizeAfterTextAlign;
36     SetInstructionsSize(instrSize);
37 
38     size_t stackMapSizeAlign = AlignUp(desc->stackMapSize, MachineCode::DATA_ALIGN);
39     SetStackMapSize(stackMapSizeAlign);
40 
41     ASSERT(dataSize == (funcEntryDesSizeAlign + instrSize + stackMapSizeAlign));
42     SetPayLoadSizeInBytes(dataSize);
43 
44     uint8_t *textStart = reinterpret_cast<uint8_t*>(GetText());
45     ASSERT(IsAligned(reinterpret_cast<uintptr_t>(textStart), TEXT_ALIGN));
46     uint8_t *pText = textStart;
47     if (rodataSizeBeforeTextAlign != 0) {
48         if (memcpy_s(pText, rodataSizeBeforeTextAlign,
49             reinterpret_cast<uint8_t*>(desc->rodataAddrBeforeText), desc->rodataSizeBeforeText) != EOK) {
50             LOG_JIT(ERROR) << "memcpy fail in copy jit code";
51             return;
52         }
53         pText += rodataSizeBeforeTextAlign;
54     }
55     if (memcpy_s(pText, codeSizeAlign, reinterpret_cast<uint8_t*>(desc->codeAddr), desc->codeSize) != EOK) {
56         LOG_JIT(ERROR) << "memcpy fail in copy jit code";
57         return;
58     }
59     pText += codeSizeAlign;
60     if (rodataSizeAfterTextAlign != 0) {
61         if (memcpy_s(pText, rodataSizeAfterTextAlign,
62             reinterpret_cast<uint8_t*>(desc->rodataAddrAfterText), desc->rodataSizeAfterText) != EOK) {
63             LOG_JIT(ERROR) << "memcpy fail in copy jit code";
64             return;
65         }
66     }
67 
68     uint8_t *stackmapAddr = GetStackMapAddress();
69     if (memcpy_s(stackmapAddr, desc->stackMapSize, reinterpret_cast<uint8_t*>(desc->stackMapAddr),
70         desc->stackMapSize) != EOK) {
71         LOG_JIT(ERROR) << "memcpy fail in copy jit stackmap";
72         return;
73     }
74 
75     FuncEntryDes *funcEntry = reinterpret_cast<FuncEntryDes*>(GetFuncEntryDesAddress());
76     if (memcpy_s(funcEntry, desc->funcEntryDesSize, reinterpret_cast<uint8_t*>(desc->funcEntryDesAddr),
77         desc->funcEntryDesSize) != EOK) {
78         LOG_JIT(ERROR) << "memcpy fail in copy jit funcEntry";
79         return;
80     }
81 
82     uint32_t cnt = desc->funcEntryDesSize / sizeof(FuncEntryDes);
83     ASSERT(cnt <= 2); // 2: jsfunction + deoptimize stub
84     for (uint32_t i = 0; i < cnt; i++) {
85         funcEntry->codeAddr_ += reinterpret_cast<uintptr_t>(textStart);
86         if (methodId == EntityId(funcEntry->indexInKindOrMethodId_)) {
87             SetFuncAddr(funcEntry->codeAddr_);
88         }
89         funcEntry++;
90     }
91 
92     CString methodName = method->GetRecordNameStr() + "." + CString(method->GetMethodName());
93     LOG_JIT(DEBUG) << "MachineCode :" << methodName << ", "  << " text addr:" <<
94         reinterpret_cast<void*>(GetText()) << ", size:" << instrSize  <<
95         ", stackMap addr:" << reinterpret_cast<void*>(stackmapAddr) << ", size:" << stackMapSizeAlign <<
96         ", funcEntry addr:" << reinterpret_cast<void*>(GetFuncEntryDesAddress()) << ", count:" << cnt;
97 
98     //todo
99     size_t pageSize = 4096;
100     uintptr_t startPage = reinterpret_cast<uintptr_t>(textStart) & ~(pageSize - 1);
101     uintptr_t endPage = (reinterpret_cast<uintptr_t>(textStart) + dataSize) & ~(pageSize - 1);
102     size_t protSize = (endPage == startPage) ? ((dataSize + pageSize - 1U) & (~(pageSize - 1))) :
103         (pageSize + ((dataSize + pageSize - 1U) & (~(pageSize - 1))));
104     PageProtect(reinterpret_cast<void*>(startPage), protSize, PAGE_PROT_EXEC_READWRITE);
105 }
106 
IsInText(const uintptr_t pc) const107 bool MachineCode::IsInText(const uintptr_t pc) const
108 {
109     uintptr_t textStart = GetText();
110     uintptr_t textEnd = textStart + GetTextSize();
111     return textStart <= pc && pc < textEnd;
112 }
113 
GetFuncEntryDes() const114 uintptr_t MachineCode::GetFuncEntryDes() const
115 {
116     uint32_t funcEntryCnt = GetFuncEntryDesSize() / sizeof(FuncEntryDes);
117     FuncEntryDes *funcEntryDes = reinterpret_cast<FuncEntryDes*>(GetFuncEntryDesAddress());
118     for (uint32_t i = 0; i < funcEntryCnt; i++) {
119         if (funcEntryDes->codeAddr_ == GetFuncAddr()) {
120             return reinterpret_cast<uintptr_t>(funcEntryDes);
121         }
122         funcEntryDes++;
123     }
124     UNREACHABLE();
125     return 0;
126 }
127 
CalCallSiteInfo(uintptr_t retAddr) const128 std::tuple<uint64_t, uint8_t*, int, kungfu::CalleeRegAndOffsetVec> MachineCode::CalCallSiteInfo(uintptr_t retAddr) const
129 {
130     uintptr_t textStart = GetText();
131     uint8_t *stackmapAddr = GetStackMapAddress();
132     ASSERT(stackmapAddr != nullptr);
133 
134     uint32_t funcEntryCnt = GetFuncEntryDesSize() / sizeof(FuncEntryDes);
135     FuncEntryDes *tmpFuncEntryDes = reinterpret_cast<FuncEntryDes*>(GetFuncEntryDesAddress());
136     FuncEntryDes *funcEntryDes = nullptr;
137     ASSERT(tmpFuncEntryDes != nullptr);
138     uintptr_t pc = retAddr - 1;  // -1: for pc
139     for (uint32_t i = 0; i < funcEntryCnt; i++) {
140         if (tmpFuncEntryDes->codeAddr_ <= pc && pc < (tmpFuncEntryDes->codeAddr_ + tmpFuncEntryDes->funcSize_)) {
141             funcEntryDes = tmpFuncEntryDes;
142             break;
143         }
144         tmpFuncEntryDes++;
145     }
146     ASSERT(funcEntryDes != nullptr);
147 
148     int delta = funcEntryDes->fpDeltaPrevFrameSp_;
149     kungfu::CalleeRegAndOffsetVec calleeRegInfo;
150     for (uint32_t j = 0; j < funcEntryDes->calleeRegisterNum_; j++) {
151         kungfu::LLVMStackMapType::DwarfRegType reg =
152             static_cast<kungfu::LLVMStackMapType::DwarfRegType>(funcEntryDes->CalleeReg2Offset_[2 * j]);
153         kungfu::LLVMStackMapType::OffsetType offset =
154             static_cast<kungfu::LLVMStackMapType::OffsetType>(funcEntryDes->CalleeReg2Offset_[2 * j + 1]);
155         kungfu::LLVMStackMapType::DwarfRegAndOffsetType regAndOffset = std::make_pair(reg, offset);
156         calleeRegInfo.emplace_back(regAndOffset);
157     }
158     auto ret = std::make_tuple(textStart, stackmapAddr, delta, calleeRegInfo);
159     return ret;
160 }
161 }  // namespace panda::ecmascript
162