1 /* 2 * Copyright (c) 2021 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 #ifndef ECMASCRIPT_MEM_MACHINE_CODE_H 16 #define ECMASCRIPT_MEM_MACHINE_CODE_H 17 18 #include "ecmascript/ecma_macros.h" 19 #include "ecmascript/js_tagged_value.h" 20 #include "ecmascript/mem/barriers.h" 21 #include "ecmascript/mem/tagged_object.h" 22 #include "ecmascript/mem/visitor.h" 23 #include "ecmascript/stackmap/ark_stackmap.h" 24 #include "ecmascript/method.h" 25 26 #include "libpandabase/macros.h" 27 28 namespace panda::ecmascript { 29 struct MachineCodeDesc { 30 uintptr_t rodataAddrBeforeText {0}; 31 size_t rodataSizeBeforeText {0}; 32 uintptr_t rodataAddrAfterText {0}; 33 size_t rodataSizeAfterText {0}; 34 35 uintptr_t codeAddr {0}; 36 size_t codeSize {0}; 37 uintptr_t funcEntryDesAddr {0}; 38 size_t funcEntryDesSize {0}; 39 uintptr_t stackMapAddr {0}; 40 size_t stackMapSize {0}; 41 }; 42 // JitCode object layout: 43 // +-----------------------------------+ 44 // | MarkWord | 8 bytes 45 // INS_SIZE_OFFSET +-----------------------------------+ 46 // | machine payload size | 4 bytes 47 // +-----------------------------------+ 48 // | FuncEntryDesc size | 4 bytes 49 // +-----------------------------------+ 50 // | instructions size | 4 bytes 51 // +-----------------------------------+ 52 // | stack map size | 4 bytes 53 // +-----------------------------------+ 54 // | func addr | 8 bytes 55 // PAYLOAD_OFFSET +-----------------------------------+ 56 // (8 byte align) | FuncEntryDesc | 57 // | ... | 58 // INSTR_OFFSET +-----------------------------------+ 59 // (16 byte align)| machine instructions(text) | 60 // | ... | 61 // STACKMAP_OFFSET +-----------------------------------+ 62 // | ArkStackMap | 63 // | ... | 64 // +-----------------------------------+ 65 class MachineCode : public TaggedObject { 66 public: 67 NO_COPY_SEMANTIC(MachineCode); 68 NO_MOVE_SEMANTIC(MachineCode); Cast(TaggedObject * object)69 static MachineCode *Cast(TaggedObject *object) 70 { 71 ASSERT(JSTaggedValue(object).IsMachineCodeObject()); 72 return static_cast<MachineCode *>(object); 73 } 74 75 static constexpr size_t INS_SIZE_OFFSET = TaggedObjectSize(); 76 ACCESSORS_PRIMITIVE_FIELD(PayLoadSizeInBytes, uint32_t, INS_SIZE_OFFSET, FUNCENTRYDESSIZE_OFFSET); 77 ACCESSORS_PRIMITIVE_FIELD(FuncEntryDesSize, uint32_t, FUNCENTRYDESSIZE_OFFSET, INSTRSIZ_OFFSET); 78 ACCESSORS_PRIMITIVE_FIELD(InstructionsSize, uint32_t, INSTRSIZ_OFFSET, STACKMAPSIZE_OFFSET); 79 ACCESSORS_PRIMITIVE_FIELD(StackMapSize, uint32_t, STACKMAPSIZE_OFFSET, FUNCADDR_OFFSET); 80 ACCESSORS_PRIMITIVE_FIELD(FuncAddr, uint64_t, FUNCADDR_OFFSET, PADDING_OFFSET); 81 ACCESSORS_PRIMITIVE_FIELD(Padding, uint64_t, PADDING_OFFSET, LAST_OFFSET); 82 DEFINE_ALIGN_SIZE(LAST_OFFSET); 83 static constexpr size_t PAYLOAD_OFFSET = SIZE; 84 static constexpr uint32_t DATA_ALIGN = 8; 85 static constexpr uint32_t TEXT_ALIGN = 16; 86 DECL_DUMP()87 DECL_DUMP() 88 89 uintptr_t GetFuncEntryDesAddress() const 90 { 91 uintptr_t paddingAddr = reinterpret_cast<const uintptr_t>(this) + PADDING_OFFSET; 92 return IsAligned(paddingAddr, TEXT_ALIGN) ? paddingAddr : reinterpret_cast<const uintptr_t>(this) + 93 PAYLOAD_OFFSET; 94 } 95 GetText()96 uintptr_t GetText() const 97 { 98 return GetFuncEntryDesAddress() + GetFuncEntryDesSize(); 99 } 100 GetStackMapAddress()101 uint8_t *GetStackMapAddress() const 102 { 103 return reinterpret_cast<uint8_t*>(GetText() + GetInstructionsSize()); 104 } 105 GetTextSize()106 size_t GetTextSize() const 107 { 108 return GetInstructionsSize(); 109 } 110 111 void SetData(const MachineCodeDesc *desc, JSHandle<Method> &method, size_t dataSize); 112 113 template <VisitType visitType> VisitRangeSlot(const EcmaObjectRangeVisitor & visitor)114 void VisitRangeSlot(const EcmaObjectRangeVisitor &visitor) 115 { 116 if (visitType == VisitType::ALL_VISIT) { 117 visitor(this, ObjectSlot(ToUintPtr(this)), 118 ObjectSlot(ToUintPtr(this) + GetMachineCodeObjectSize()), VisitObjectArea::RAW_DATA); 119 } 120 } 121 GetMachineCodeObjectSize()122 size_t GetMachineCodeObjectSize() 123 { 124 return SIZE + this->GetPayLoadSizeInBytes(); 125 } 126 GetInstructionSizeInBytes()127 uint32_t GetInstructionSizeInBytes() const 128 { 129 return GetPayLoadSizeInBytes(); 130 } 131 132 bool IsInText(const uintptr_t pc) const; 133 uintptr_t GetFuncEntryDes() const; 134 135 std::tuple<uint64_t, uint8_t *, int, kungfu::CalleeRegAndOffsetVec> CalCallSiteInfo(uintptr_t retAddr) const; 136 }; 137 } // namespace panda::ecmascript 138 #endif // ECMASCRIPT_MEM_MACHINE_CODE_H 139