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/pgo_profiler/ap_file/pgo_method_type_set.h"
17 #include "ecmascript/pgo_profiler/ap_file/pgo_file_info.h"
18
19 namespace panda::ecmascript::pgo {
20 using StringHelper = base::StringHelper;
Merge(const PGOMethodTypeSet * info)21 void PGOMethodTypeSet::Merge(const PGOMethodTypeSet *info)
22 {
23 for (const auto &fromType : info->scalarOpTypeInfos_) {
24 auto iter = scalarOpTypeInfos_.find(fromType);
25 if (iter != scalarOpTypeInfos_.end()) {
26 const_cast<ScalarOpTypeInfo &>(*iter).Merge(fromType);
27 } else {
28 scalarOpTypeInfos_.emplace(fromType);
29 }
30 }
31 for (const auto &fromType : info->rwScalarOpTypeInfos_) {
32 auto iter = rwScalarOpTypeInfos_.find(fromType);
33 if (iter != rwScalarOpTypeInfos_.end()) {
34 const_cast<RWScalarOpTypeInfo &>(*iter).Merge(fromType);
35 } else {
36 rwScalarOpTypeInfos_.emplace(fromType);
37 }
38 }
39 for (const auto &fromType : info->objDefOpTypeInfos_) {
40 AddDefine(fromType.GetOffset(), fromType.GetType());
41 }
42 }
43
SkipFromBinary(void ** buffer)44 void PGOMethodTypeSet::SkipFromBinary(void **buffer)
45 {
46 uint32_t size = base::ReadBuffer<uint32_t>(buffer, sizeof(uint32_t));
47 for (uint32_t i = 0; i < size; i++) {
48 base::ReadBufferInSize<ScalarOpTypeInfo>(buffer);
49 }
50 }
51
ParseFromBinary(PGOContext & context,void ** buffer)52 bool PGOMethodTypeSet::ParseFromBinary(PGOContext &context, void **buffer)
53 {
54 PGOProfilerHeader *const header = context.GetHeader();
55 ASSERT(header != nullptr);
56 uint32_t size = base::ReadBuffer<uint32_t>(buffer, sizeof(uint32_t));
57 if (size > MAX_METHOD_TYPE_SIZE) {
58 return false;
59 }
60 for (uint32_t i = 0; i < size; i++) {
61 auto typeInfo = base::ReadBufferInSize<TypeInfoHeader>(buffer);
62 if (typeInfo->GetInfoType() == InfoType::OP_TYPE) {
63 auto *scalerInfo = reinterpret_cast<ScalarOpTypeInfoRef *>(typeInfo);
64 scalarOpTypeInfos_.emplace(scalerInfo->GetOffset(),
65 PGOSampleType::ConvertFrom(context, scalerInfo->GetType()));
66 } else if (typeInfo->GetInfoType() == InfoType::DEFINE_CLASS_TYPE) {
67 auto *defineInfo = reinterpret_cast<ObjDefOpTypeInfoRef *>(typeInfo);
68 PGODefineOpType type;
69 type.ConvertFrom(context, defineInfo->GetType());
70 ObjDefOpTypeInfo info(defineInfo->GetOffset(), type);
71 objDefOpTypeInfos_.emplace(info);
72 } else if (header->SupportUseHClassType() && typeInfo->GetInfoType() == InfoType::USE_HCLASS_TYPE) {
73 auto *opTypeInfo = reinterpret_cast<RWScalarOpTypeInfoRef *>(typeInfo);
74 RWScalarOpTypeInfo info(opTypeInfo->GetOffset());
75 info.ConvertFrom(context, *opTypeInfo);
76 for (int j = 0; j < info.GetCount(); j++) {
77 if (info.GetTypeRef().GetObjectInfo(j).GetProtoChainMarker() == ProtoChainMarker::EXSIT) {
78 auto protoChainRef = base::ReadBufferInSize<PGOProtoChainRef>(buffer);
79 auto protoChain = PGOProtoChain::ConvertFrom(context, protoChainRef);
80 const_cast<PGOObjectInfo &>(info.GetTypeRef().GetObjectInfo(j)).SetProtoChain(protoChain);
81 }
82 }
83 rwScalarOpTypeInfos_.emplace(info);
84 }
85 }
86 return true;
87 }
88
ProcessToBinary(PGOContext & context,std::stringstream & stream) const89 bool PGOMethodTypeSet::ProcessToBinary(PGOContext &context, std::stringstream &stream) const
90 {
91 uint32_t number = 0;
92 std::stringstream methodStream;
93 for (auto &typeInfo : scalarOpTypeInfos_) {
94 if (!typeInfo.GetType().IsNone()) {
95 PGOSampleTypeRef sampleTypeRef = PGOSampleTypeRef::ConvertFrom(context, typeInfo.GetType());
96 ScalarOpTypeInfoRef infoRef(typeInfo.GetOffset(), sampleTypeRef);
97 methodStream.write(reinterpret_cast<char *>(&infoRef), infoRef.Size());
98 number++;
99 }
100 }
101 for (auto &typeInfo : rwScalarOpTypeInfos_) {
102 if (typeInfo.GetCount() != 0) {
103 RWScalarOpTypeInfoRef infoRef(typeInfo.GetOffset());
104 infoRef.ConvertFrom(context, typeInfo);
105 methodStream.write(reinterpret_cast<char *>(&infoRef), infoRef.Size());
106 for (int i = 0; i < typeInfo.GetCount(); i++) {
107 if (typeInfo.GetTypeRef().GetObjectInfo(i).GetProtoChainMarker() == ProtoChainMarker::EXSIT) {
108 auto protoChain = typeInfo.GetTypeRef().GetObjectInfo(i).GetProtoChain();
109 auto protoChainRef = PGOProtoChainRef::ConvertFrom(context, protoChain);
110 methodStream.write(reinterpret_cast<char *>(protoChainRef), protoChainRef->Size());
111 PGOProtoChainRef::DeleteProtoChain(protoChainRef);
112 }
113 }
114 number++;
115 }
116 }
117
118 for (const auto &typeInfo : objDefOpTypeInfos_) {
119 PGODefineOpTypeRef typeRef;
120 typeRef.ConvertFrom(context, typeInfo.GetType());
121 ObjDefOpTypeInfoRef infoRef(typeInfo.GetOffset(), typeRef);
122 methodStream.write(reinterpret_cast<char *>(&infoRef), infoRef.Size());
123 number++;
124 }
125
126 stream.write(reinterpret_cast<char *>(&number), sizeof(uint32_t));
127 if (number > 0) {
128 stream << methodStream.rdbuf();
129 return true;
130 }
131 return false;
132 }
133
ParseFromText(const std::string & typeString)134 bool PGOMethodTypeSet::ParseFromText(const std::string &typeString)
135 {
136 std::vector<std::string> typeInfoVector = StringHelper::SplitString(typeString, DumpUtils::TYPE_SEPARATOR);
137 if (typeInfoVector.size() > 0) {
138 for (const auto &iter : typeInfoVector) {
139 std::vector<std::string> typeStrings = StringHelper::SplitString(iter, DumpUtils::BLOCK_START);
140 if (typeStrings.size() < METHOD_TYPE_INFO_COUNT) {
141 return false;
142 }
143
144 uint32_t offset = 0;
145 if (!StringHelper::StrToUInt32(typeStrings[METHOD_OFFSET_INDEX].c_str(), &offset)) {
146 return false;
147 }
148 uint32_t type = 0;
149 if (!StringHelper::StrToUInt32(typeStrings[METHOD_TYPE_INDEX].c_str(), &type)) {
150 return false;
151 }
152 scalarOpTypeInfos_.emplace(offset, PGOSampleType(type));
153 }
154 }
155 return true;
156 }
157
ProcessToText(std::string & text) const158 void PGOMethodTypeSet::ProcessToText(std::string &text) const
159 {
160 bool isFirst = true;
161 for (auto typeInfoIter : scalarOpTypeInfos_) {
162 if (typeInfoIter.GetType().IsNone()) {
163 continue;
164 }
165 if (isFirst) {
166 text += DumpUtils::ARRAY_START + DumpUtils::SPACE;
167 isFirst = false;
168 } else {
169 text += DumpUtils::TYPE_SEPARATOR + DumpUtils::SPACE;
170 }
171 text += std::to_string(typeInfoIter.GetOffset());
172 text += DumpUtils::BLOCK_START;
173 text += typeInfoIter.GetType().GetTypeString();
174 }
175 for (auto rwScalarOpTypeInfoIter : rwScalarOpTypeInfos_) {
176 if (rwScalarOpTypeInfoIter.GetCount() == 0) {
177 continue;
178 }
179 if (isFirst) {
180 text += DumpUtils::ARRAY_START + DumpUtils::SPACE;
181 isFirst = false;
182 } else {
183 text += DumpUtils::TYPE_SEPARATOR + DumpUtils::SPACE;
184 }
185 rwScalarOpTypeInfoIter.ProcessToText(text);
186 }
187 for (const auto &defTypeInfoIter : objDefOpTypeInfos_) {
188 if (isFirst) {
189 text += DumpUtils::ARRAY_START + DumpUtils::SPACE;
190 isFirst = false;
191 } else {
192 text += DumpUtils::TYPE_SEPARATOR + DumpUtils::SPACE;
193 }
194 defTypeInfoIter.ProcessToText(text);
195 }
196 if (!isFirst) {
197 text += (DumpUtils::SPACE + DumpUtils::ARRAY_END);
198 }
199 }
200
ProcessToJson(ProfileType::VariantVector & typeArray) const201 void PGOMethodTypeSet::ProcessToJson(ProfileType::VariantVector &typeArray) const
202 {
203 for (auto typeInfoIter : scalarOpTypeInfos_) {
204 if (typeInfoIter.GetType().IsNone()) {
205 continue;
206 }
207 ProfileType::StringMap type;
208 type.insert(std::make_pair(DumpJsonUtils::TYPE_OFFSET, std::to_string(typeInfoIter.GetOffset())));
209 typeInfoIter.GetType().GetTypeJson(type);
210 typeArray.push_back(type);
211 }
212 for (auto rwScalarOpTypeInfoIter : rwScalarOpTypeInfos_) {
213 if (rwScalarOpTypeInfoIter.GetCount() == 0) {
214 continue;
215 }
216 ProfileType::MapVector sameOffsetTypeArray;
217 rwScalarOpTypeInfoIter.ProcessToJson(sameOffsetTypeArray);
218 typeArray.push_back(sameOffsetTypeArray);
219 }
220 for (const auto &defTypeInfoIter : objDefOpTypeInfos_) {
221 std::vector<ProfileType::StringMap> sameOffsetTypeArray;
222 defTypeInfoIter.ProcessToJson(sameOffsetTypeArray);
223 typeArray.push_back(sameOffsetTypeArray);
224 }
225 }
226 } // namespace panda::ecmascript::pgo
227