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