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