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