• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_LLVM_STACKMAP_TYPE_H
16 #define ECMASCRIPT_LLVM_STACKMAP_TYPE_H
17 
18 #include <iostream>
19 #include <memory>
20 #include <tuple>
21 #include <unordered_map>
22 #include <variant>
23 #include <vector>
24 #include "ecmascript/common.h"
25 #include "ecmascript/log_wrapper.h"
26 
27 namespace panda::ecmascript::kungfu {
28 using OffsetType = int32_t;
29 using DwarfRegType = uint16_t;
30 using LargeInt = int64_t;
31 using DwarfRegAndOffsetType = std::pair<DwarfRegType, OffsetType>;
32 using CallSiteInfo = std::vector<DwarfRegAndOffsetType>;
33 using Fun2InfoType = std::pair<uintptr_t, DwarfRegAndOffsetType>;
34 using Pc2CallSiteInfo = std::unordered_map<uintptr_t, CallSiteInfo>;
35 using FpDelta = std::pair<int, uint32_t>;
36 using Func2FpDelta = std::unordered_map<uintptr_t, FpDelta>; // value: fpDelta & funcSize
37 using ConstInfo = std::vector<OffsetType>;
38 using DeoptInfoType = std::vector<std::variant<OffsetType, LargeInt, DwarfRegAndOffsetType>>;
39 using Pc2Deopt = std::unordered_map<uintptr_t, DeoptInfoType>;
40 
41 struct Header {
42     uint8_t  stackmapversion; // Stack Map Version (current version is 3)
43     uint8_t  Reserved0; // Reserved (expected to be 0)
44     uint16_t Reserved1; // Reserved (expected to be 0)
PrintHeader45     void Print() const
46     {
47         LOG_COMPILER(DEBUG) << "----- head ----";
48         LOG_COMPILER(DEBUG) << "   version:" << static_cast<int>(stackmapversion);
49         LOG_COMPILER(DEBUG) << "+++++ head ++++";
50     }
51 };
52 
53 #pragma pack(1)
54 struct StkSizeRecordTy {
55     uintptr_t functionAddress;
56     uint64_t stackSize;
57     uint64_t recordCount;
PrintStkSizeRecordTy58     void Print() const
59     {
60         LOG_COMPILER(DEBUG) << "               functionAddress:0x" << std::hex << functionAddress;
61         LOG_COMPILER(DEBUG) << "               stackSize:0x" << std::hex << stackSize;
62         LOG_COMPILER(DEBUG) << "               recordCount:" << std::hex << recordCount;
63     }
64 };
65 #pragma pack()
66 
67 struct ConstantsTy {
68     uintptr_t LargeConstant;
PrintConstantsTy69     void Print() const
70     {
71         LOG_COMPILER(DEBUG) << "               LargeConstant:0x" << std::hex << LargeConstant;
72     }
73 };
74 
75 struct StkMapRecordHeadTy {
76     uint64_t PatchPointID;
77     uint32_t InstructionOffset;
78     uint16_t Reserved;
79     uint16_t NumLocations;
PrintStkMapRecordHeadTy80     void Print() const
81     {
82         LOG_COMPILER(DEBUG) << "               PatchPointID:0x" << std::hex << PatchPointID;
83         LOG_COMPILER(DEBUG) << "               instructionOffset:0x" << std::hex << InstructionOffset;
84         LOG_COMPILER(DEBUG) << "               Reserved:0x" << std::hex << Reserved;
85         LOG_COMPILER(DEBUG) << "               NumLocations:0x" << std::hex << NumLocations;
86     }
87 };
88 
89 struct  LocationTy {
90     enum class Kind: uint8_t {
91         REGISTER = 1,
92         DIRECT = 2,
93         INDIRECT = 3,
94         CONSTANT = 4,
95         CONSTANTNDEX = 5,
96     };
97     static constexpr int CONSTANT_FIRST_ELEMENT_INDEX = 3;
98     static constexpr int CONSTANT_DEOPT_CNT_INDEX = 2;
99     Kind location;
100     uint8_t Reserved_0;
101     uint16_t LocationSize;
102     uint16_t DwarfRegNum;
103     uint16_t Reserved_1;
104     OffsetType OffsetOrSmallConstant;
105 
106     std::string PUBLIC_API TypeToString(Kind loc) const;
107 
PrintLocationTy108     void Print() const
109     {
110         LOG_COMPILER(DEBUG)  << TypeToString(location);
111         LOG_COMPILER(DEBUG) << ", size:" << std::dec << LocationSize;
112         LOG_COMPILER(DEBUG) << "\tDwarfRegNum:" << DwarfRegNum;
113         LOG_COMPILER(DEBUG) << "\t OffsetOrSmallConstant:" << OffsetOrSmallConstant;
114     }
115 };
116 
117 struct LiveOutsTy {
118     DwarfRegType DwarfRegNum;
119     uint8_t Reserved;
120     uint8_t SizeinBytes;
PrintLiveOutsTy121     void Print() const
122     {
123         LOG_COMPILER(DEBUG) << "                  Dwarf RegNum:" << DwarfRegNum;
124         LOG_COMPILER(DEBUG) << "                  Reserved:" << Reserved;
125         LOG_COMPILER(DEBUG) << "                  SizeinBytes:" << SizeinBytes;
126     }
127 };
128 struct StkMapRecordTy {
129     struct StkMapRecordHeadTy head;
130     std::vector<struct LocationTy> Locations;
131     std::vector<struct LiveOutsTy> LiveOuts;
PrintStkMapRecordTy132     void Print() const
133     {
134         head.Print();
135         auto size = Locations.size();
136         for (size_t i = 0; i < size; i++) {
137             LOG_COMPILER(DEBUG) << "                   #" << std::dec << i << ":";
138             Locations[i].Print();
139         }
140         size = LiveOuts.size();
141         for (size_t i = 0; i < size; i++) {
142             LOG_COMPILER(DEBUG) << "               liveOuts[" << i << "] info:";
143         }
144     }
145 };
146 
147 class DataInfo {
148 public:
DataInfo(std::unique_ptr<uint8_t[]> data)149     explicit DataInfo(std::unique_ptr<uint8_t[]> data): data_(std::move(data)), offset_(0) {}
~DataInfo()150     ~DataInfo()
151     {
152         data_.reset();
153         offset_ = 0;
154     }
155     template<class T>
Read()156     T Read()
157     {
158         T t = *reinterpret_cast<const T*>(data_.get() + offset_);
159         offset_ += sizeof(T);
160         return t;
161     }
GetOffset()162     unsigned int GetOffset() const
163     {
164         return offset_;
165     }
166 private:
167     std::unique_ptr<uint8_t[]> data_ {nullptr};
168     unsigned int offset_ {0};
169 };
170 
171 struct LLVMStackMap {
172     struct Header head;
173     std::vector<struct StkSizeRecordTy> StkSizeRecords;
174     std::vector<struct ConstantsTy> Constants;
175     std::vector<struct StkMapRecordTy> StkMapRecord;
PrintLLVMStackMap176     void Print() const
177     {
178         head.Print();
179         for (size_t i = 0; i < StkSizeRecords.size(); i++) {
180             LOG_COMPILER(DEBUG) << "stkSizeRecord[" << i << "] info:";
181             StkSizeRecords[i].Print();
182         }
183         for (size_t i = 0; i < Constants.size(); i++) {
184             LOG_COMPILER(DEBUG) << "constants[" << i << "] info:";
185             Constants[i].Print();
186         }
187         for (size_t i = 0; i < StkMapRecord.size(); i++) {
188             LOG_COMPILER(DEBUG) << "StkMapRecord[" << i << "] info:";
189             StkMapRecord[i].Print();
190         }
191     }
192 };
193 } // namespace panda::ecmascript::kungfu
194 #endif  // ECMASCRIPT_LLVM_STACKMAP_TYPE_H