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
16 #include <cstdint>
17 #include <fstream>
18 #include <memory>
19 #include <sstream>
20 #include <string>
21 #include <unordered_map>
22 #include <utility>
23
24 #include "assembler/assembly-emitter.h"
25 #include "assembler/assembly-parser.h"
26 #include "gtest/gtest.h"
27
28 #include "ecmascript/base/file_header.h"
29 #include "ecmascript/ecma_vm.h"
30 #include "ecmascript/elements.h"
31 #include "ecmascript/js_symbol.h"
32 #include "ecmascript/js_thread.h"
33 #include "ecmascript/jspandafile/js_pandafile.h"
34 #include "ecmascript/jspandafile/js_pandafile_manager.h"
35 #include "ecmascript/jspandafile/method_literal.h"
36 #include "ecmascript/jspandafile/program_object.h"
37 #include "ecmascript/log_wrapper.h"
38 #include "ecmascript/napi/include/jsnapi.h"
39 #include "ecmascript/object_factory.h"
40 #include "ecmascript/pgo_profiler/ap_file/pgo_file_info.h"
41 #include "ecmascript/pgo_profiler/ap_file/pgo_method_type_set.h"
42 #include "ecmascript/pgo_profiler/pgo_context.h"
43 #include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
44 #include "ecmascript/pgo_profiler/pgo_profiler_encoder.h"
45 #include "ecmascript/pgo_profiler/pgo_profiler_info.h"
46 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
47 #include "ecmascript/pgo_profiler/pgo_utils.h"
48 #include "ecmascript/pgo_profiler/tests/pgo_context_mock.h"
49 #include "ecmascript/pgo_profiler/types/pgo_profile_type.h"
50 #include "ecmascript/pgo_profiler/types/pgo_profiler_type.h"
51 #include "ecmascript/platform/file.h"
52 #include "ecmascript/tests/test_helper.h"
53
54 using namespace panda;
55 using namespace panda::ecmascript;
56 using namespace panda::ecmascript::pgo;
57 using namespace panda::panda_file;
58 using namespace panda::pandasm;
59
60 namespace panda::test {
61 class PGOProfilerTest : public testing::Test {
62 public:
63 using ApGenMode = PGOProfilerEncoder::ApGenMode;
SetUpTestCase()64 static void SetUpTestCase()
65 {
66 GTEST_LOG_(INFO) << "SetUpTestCase";
67 }
68
TearDownTestCase()69 static void TearDownTestCase()
70 {
71 GTEST_LOG_(INFO) << "TearDownCase";
72 }
73
SetUp()74 void SetUp() override
75 {
76 strictMatch_ = PGOProfilerHeader::IsStrictMatch();
77 }
78
TearDown()79 void TearDown() override
80 {
81 DestroyJSPandaFile();
82 PGOProfilerManager::GetInstance()->SetDisablePGO(false);
83 PGOProfilerManager::GetInstance()->Destroy();
84 PGOProfilerHeader::SetStrictMatch(strictMatch_);
85 }
86
87 protected:
CreateJSPandaFile(const CString filename,std::vector<MethodLiteral * > & methodLiterals)88 void CreateJSPandaFile(const CString filename, std::vector<MethodLiteral *> &methodLiterals)
89 {
90 std::string targetAbcPath = std::string(TARGET_ABC_PATH) + filename.c_str();
91 auto pfPtr = panda_file::OpenPandaFileOrZip(targetAbcPath, panda_file::File::READ_WRITE);
92 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
93 pf_ = pfManager->NewJSPandaFile(pfPtr.release(), filename);
94
95 const File *file = pf_->GetPandaFile();
96 auto classes = pf_->GetClasses();
97
98 for (size_t i = 0; i < classes.Size(); i++) {
99 panda_file::File::EntityId classId(classes[i]);
100 if (!classId.IsValid() || pf_->IsExternal(classId)) {
101 continue;
102 }
103 ClassDataAccessor cda(*file, classId);
104 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
105 auto *methodLiteral = new MethodLiteral(mda.GetMethodId());
106 methodLiteral->Initialize(pf_.get());
107 pf_->SetMethodLiteralToMap(methodLiteral);
108 methodLiterals.push_back(methodLiteral);
109 });
110 }
111 }
112
CreateJSPandaFile(const char * source,const CString filename,std::vector<MethodLiteral * > & methodLiterals)113 void CreateJSPandaFile(const char *source, const CString filename, std::vector<MethodLiteral *> &methodLiterals)
114 {
115 Parser parser;
116 const std::string fn = "SRC.abc"; // test file name : "SRC.abc"
117 auto res = parser.Parse(source, fn);
118
119 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
120 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
121 pf_ = pfManager->NewJSPandaFile(pfPtr.release(), filename);
122
123 const File *file = pf_->GetPandaFile();
124 const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
125 File::EntityId classId = file->GetClassId(typeDesc);
126 EXPECT_TRUE(classId.IsValid());
127
128 ClassDataAccessor cda(*file, classId);
129 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
130 auto *methodLiteral = new MethodLiteral(mda.GetMethodId());
131 methodLiteral->Initialize(pf_.get());
132 pf_->SetMethodLiteralToMap(methodLiteral);
133 methodLiterals.push_back(methodLiteral);
134 });
135 }
136
ExecuteAndLoadJSPandaFile(std::string profDir,std::string recordName)137 void ExecuteAndLoadJSPandaFile(std::string profDir, std::string recordName)
138 {
139 RuntimeOption option;
140 option.SetEnableProfile(true);
141 option.SetProfileDir(profDir);
142 option.SetLogLevel(common::LOG_LEVEL::INFO);
143 vm_ = JSNApi::CreateJSVM(option);
144 JSNApi::EnableUserUncaughtErrorHandler(vm_);
145
146 std::string targetAbcPath = TARGET_ABC_PATH + recordName + ".abc";
147 auto result = JSNApi::Execute(vm_, targetAbcPath, recordName, false);
148 EXPECT_TRUE(result);
149
150 pf_ = JSPandaFileManager::GetInstance()->FindJSPandaFile(CString(targetAbcPath));
151
152 JSNApi::DestroyJSVM(vm_);
153 }
154
ParseRelatedPandaFileMethods(PGOProfilerDecoder & loader,std::unordered_map<std::string,std::unordered_map<std::string,std::vector<PGOMethodId>>> & methodIdInAp)155 void ParseRelatedPandaFileMethods(
156 PGOProfilerDecoder &loader,
157 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<PGOMethodId>>> &methodIdInAp)
158 {
159 std::shared_ptr<PGOAbcFilePool> abcFilePool = std::make_shared<PGOAbcFilePool>();
160 ASSERT_TRUE(loader.LoadFull(abcFilePool));
161 for (const auto &recordInfo : loader.GetRecordDetailInfos().GetRecordInfos()) {
162 auto recordProfile = recordInfo.first;
163 ASSERT_EQ(recordProfile.GetKind(), ProfileType::Kind::RecordClassId);
164 if (recordProfile.IsNone()) {
165 continue;
166 }
167 LOG_ECMA(ERROR) << "recordProfile: " << recordProfile.GetTypeString();
168 const auto *recordName =
169 loader.GetRecordDetailInfos().GetRecordPool()->GetName(recordProfile);
170 ASSERT(recordName != nullptr);
171 const auto abcNormalizedDesc =
172 JSPandaFile::GetNormalizedFileDesc(abcFilePool->GetEntry(recordProfile.GetAbcId())->GetData());
173 if (abcNormalizedDesc.empty()) {
174 continue;
175 }
176
177 const auto *info = recordInfo.second;
178 for (const auto &method : info->GetMethodInfos()) {
179 // add ap entry info
180 methodIdInAp[abcNormalizedDesc.c_str()][recordName].emplace_back(method.first);
181 }
182 };
183 }
184
CheckApMethods(std::unordered_map<std::string,std::unordered_map<std::string,std::vector<PGOMethodId>>> & methodIdInAp)185 void CheckApMethods(
186 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<PGOMethodId>>> &methodIdInAp)
187 {
188 for (auto abcIter = methodIdInAp.begin(); abcIter != methodIdInAp.end();) {
189 std::string fileName(abcIter->first.c_str());
190 auto lastDirToken = fileName.find_last_of('/');
191 if (lastDirToken != std::string::npos) {
192 fileName = fileName.substr(lastDirToken + 1);
193 }
194 std::unordered_map<std::string, std::vector<PGOMethodId>> &recordMethodList = abcIter->second;
195 CheckApMethodsInApFiles(fileName, recordMethodList);
196 if (recordMethodList.empty()) {
197 abcIter = methodIdInAp.erase(abcIter);
198 } else {
199 abcIter++;
200 }
201 }
202 ASSERT_TRUE(methodIdInAp.empty());
203 }
204
CheckApMethodsInApFiles(const std::string & fileName,std::unordered_map<std::string,std::vector<PGOMethodId>> & recordMethodList)205 void CheckApMethodsInApFiles(const std::string &fileName,
206 std::unordered_map<std::string, std::vector<PGOMethodId>> &recordMethodList)
207 {
208 RuntimeOption option;
209 vm_ = JSNApi::CreateJSVM(option);
210 std::vector<MethodLiteral *> methodLiterals {};
211 CreateJSPandaFile(fileName.c_str(), methodLiterals);
212 for (auto &methodLiteral : methodLiterals) {
213 auto methodName = MethodLiteral::GetRecordName(pf_.get(), methodLiteral->GetMethodId());
214 auto recordEntry = recordMethodList.find(methodName.c_str());
215 if (recordEntry == recordMethodList.end()) {
216 continue;
217 }
218 for (size_t index = 0; index < recordEntry->second.size(); ++index) {
219 if (!(recordEntry->second.at(index) == methodLiteral->GetMethodId())) {
220 continue;
221 }
222 // Remove matched entry
223 recordEntry->second.erase(recordEntry->second.begin() + index);
224 if (recordEntry->second.empty()) {
225 recordEntry = recordMethodList.erase(recordEntry);
226 }
227 break;
228 }
229 }
230 JSNApi::DestroyJSVM(vm_);
231 }
232
DestroyJSPandaFile()233 void DestroyJSPandaFile() {
234 RuntimeOption option;
235 vm_ = JSNApi::CreateJSVM(option);
236 JSPandaFileManager::GetInstance()->RemoveJSPandaFile(pf_.get());
237 pf_.reset();
238 JSNApi::DestroyJSVM(vm_);
239 }
240
241 static constexpr uint32_t DECODER_THRESHOLD = 2;
242 EcmaVM *vm_ = nullptr;
243 bool strictMatch_ = false;
244 std::shared_ptr<JSPandaFile> pf_;
245 };
246
HWTEST_F_L0(PGOProfilerTest,Sample)247 HWTEST_F_L0(PGOProfilerTest, Sample)
248 {
249 mkdir("ark-profiler/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
250 RuntimeOption option;
251 option.SetEnableProfile(true);
252 option.SetProfileDir("ark-profiler/");
253 vm_ = JSNApi::CreateJSVM(option);
254 std::vector<MethodLiteral *> methodLiterals {};
255 CreateJSPandaFile("sample_test.abc", methodLiterals);
256 vm_->GetJSThread()->ManagedCodeBegin();
257 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
258 constPool->SetJSPandaFile(pf_.get());
259 uint32_t checksum = 304293;
260 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler.abc");
261 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
262
263 JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
264 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
265 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
266 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
267 func->SetModule(vm_->GetJSThread(), recordName);
268 vm_->GetPGOProfiler()->SetSaveTimestamp(std::chrono::system_clock::now());
269 vm_->GetJSThread()->ManagedCodeEnd();
270 JSNApi::DestroyJSVM(vm_);
271 // Loader
272 PGOProfilerDecoder loader("ark-profiler/modules.ap", DECODER_THRESHOLD);
273 CString expectRecordName = "sample_test";
274 #if defined(SUPPORT_ENABLE_ASM_INTERP)
275 ASSERT_TRUE(loader.LoadAndVerify({{"ark-profiler.abc", checksum}}));
276 ASSERT_FALSE(loader.LoadAndVerify({{"ark-profiler.abc", 123456}}));
277 ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
278 #else
279 ASSERT_TRUE(!loader.LoadAndVerify({{"ark-profiler.abc", checksum}}));
280 ASSERT_FALSE(loader.LoadAndVerify({{"ark-profiler.abc", 123456}}));
281 ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
282 #endif
283 unlink("ark-profiler/modules.ap");
284 rmdir("ark-profiler/");
285 }
286
HWTEST_F_L0(PGOProfilerTest,Sample1)287 HWTEST_F_L0(PGOProfilerTest, Sample1)
288 {
289 mkdir("ark-profiler1/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
290 RuntimeOption option;
291 option.SetEnableProfile(true);
292 option.SetProfileDir("ark-profiler1/");
293 vm_ = JSNApi::CreateJSVM(option);
294 std::vector<MethodLiteral *> methodLiterals {};
295 CreateJSPandaFile("sample_test.abc", methodLiterals);
296 vm_->GetJSThread()->ManagedCodeBegin();
297 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
298 constPool->SetJSPandaFile(pf_.get());
299 uint32_t checksum = 304293;
300 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler1.abc");
301 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
302
303 JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
304 JSHandle<Method> method1 = vm_->GetFactory()->NewSMethod(methodLiterals[1]);
305 JSHandle<Method> method2 = vm_->GetFactory()->NewSMethod(methodLiterals[2]);
306 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
307 method1->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
308 method2->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
309
310 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
311 JSHandle<JSFunction> func1 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method1);
312 JSHandle<JSFunction> func2 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method2);
313 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
314 func->SetModule(vm_->GetJSThread(), recordName);
315 func1->SetModule(vm_->GetJSThread(), recordName);
316 func2->SetModule(vm_->GetJSThread(), recordName);
317 vm_->GetJSThread()->ManagedCodeEnd();
318 JSNApi::DestroyJSVM(vm_);
319
320 // Loader
321 PGOProfilerDecoder loader("ark-profiler1/modules.ap", DECODER_THRESHOLD);
322 CString expectRecordName = "sample_test";
323 #if defined(SUPPORT_ENABLE_ASM_INTERP)
324 ASSERT_TRUE(loader.LoadAndVerify({{"ark-profiler1.abc", checksum}}));
325 for (uint32_t idx = 0; idx < 3; idx++) {
326 loader.MatchAndMarkMethod(pf_.get(), expectRecordName,
327 methodLiterals[idx]->GetMethodName(pf_.get(), methodLiterals[idx]->GetMethodId()),
328 methodLiterals[idx]->GetMethodId());
329 }
330 ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
331 ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[2]->GetMethodId()));
332 ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[1]->GetMethodId()));
333 #else
334 ASSERT_TRUE(!loader.LoadAndVerify({{"ark-profiler1.abc", checksum}}));
335 ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[1]->GetMethodId()));
336 #endif
337 unlink("ark-profiler1/modules.ap");
338 rmdir("ark-profiler1/");
339 }
340
HWTEST_F_L0(PGOProfilerTest,Sample2)341 HWTEST_F_L0(PGOProfilerTest, Sample2)
342 {
343 mkdir("ark-profiler2/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
344 RuntimeOption option;
345 option.SetEnableProfile(true);
346 option.SetProfileDir("ark-profiler2/");
347 vm_ = JSNApi::CreateJSVM(option);
348 std::vector<MethodLiteral *> methodLiterals {};
349 CreateJSPandaFile("sample_test.abc", methodLiterals);
350 vm_->GetJSThread()->ManagedCodeBegin();
351 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
352 constPool->SetJSPandaFile(pf_.get());
353 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
354 uint32_t checksum = 304293;
355 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler2.abc");
356
357 JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
358 JSHandle<Method> method1 = vm_->GetFactory()->NewSMethod(methodLiterals[1]);
359
360 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
361 method1->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
362 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
363 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
364 func->SetModule(vm_->GetJSThread(), recordName);
365 JSHandle<JSFunction> func1 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method1);
366 JSHandle<JSTaggedValue> recordName1(vm_->GetFactory()->NewFromStdString("test1"));
367 func1->SetModule(vm_->GetJSThread(), recordName1);
368 vm_->GetJSThread()->ManagedCodeEnd();
369 JSNApi::DestroyJSVM(vm_);
370
371 // Loader
372 PGOProfilerDecoder loader("ark-profiler2/modules.ap", DECODER_THRESHOLD);
373 CString expectRecordName = "sample_test";
374 CString expectRecordName1 = "sample_test";
375 #if defined(SUPPORT_ENABLE_ASM_INTERP)
376 ASSERT_TRUE(loader.LoadAndVerify({{"ark-profiler2.abc", checksum}}));
377 for (uint32_t idx = 0; idx < 2; idx++) {
378 loader.MatchAndMarkMethod(pf_.get(), expectRecordName,
379 methodLiterals[idx]->GetMethodName(pf_.get(), methodLiterals[idx]->GetMethodId()),
380 methodLiterals[idx]->GetMethodId());
381 loader.MatchAndMarkMethod(pf_.get(), expectRecordName1,
382 methodLiterals[idx]->GetMethodName(pf_.get(), methodLiterals[idx]->GetMethodId()),
383 methodLiterals[idx]->GetMethodId());
384 }
385 ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
386 ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName1, methodLiterals[1]->GetMethodId()));
387 #else
388 ASSERT_TRUE(!loader.LoadAndVerify({{"ark-profiler2.abc", checksum}}));
389 ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
390 ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName1, methodLiterals[1]->GetMethodId()));
391 #endif
392 unlink("ark-profiler2/modules.ap");
393 rmdir("ark-profiler2/");
394 }
395
HWTEST_F_L0(PGOProfilerTest,DisEnableSample)396 HWTEST_F_L0(PGOProfilerTest, DisEnableSample)
397 {
398 mkdir("ark-profiler3/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
399 RuntimeOption option;
400 option.SetEnableProfile(false);
401 option.SetProfileDir("ark-profiler3/");
402 vm_ = JSNApi::CreateJSVM(option);
403 std::vector<MethodLiteral *> methodLiterals {};
404 CreateJSPandaFile("sample_test.abc", methodLiterals);
405 EXPECT_GE(methodLiterals.size(), 1);
406 vm_->GetJSThread()->ManagedCodeBegin();
407 JSPandaFileManager::GetInstance()->AddJSPandaFile(pf_);
408 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
409 constPool->SetJSPandaFile(pf_.get());
410 uint32_t checksum = pf_->GetChecksum();
411 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "sample_test.abc");
412 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
413
414 JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
415
416 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
417 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
418 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("sample_test"));
419 func->SetModule(vm_->GetJSThread(), recordName);
420 vm_->GetJSThread()->ManagedCodeEnd();
421 JSNApi::DestroyJSVM(vm_);
422
423 // Loader
424 ASSERT_FALSE(FileExist("ark-profiler3/modules.ap"));
425 PGOProfilerDecoder loader("ark-profiler3/modules.ap", DECODER_THRESHOLD);
426 ASSERT_TRUE(!loader.LoadAndVerify({{"sample_test.abc", checksum}}));
427 CString expectRecordName = "sample_test";
428 ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
429 rmdir("ark-profiler3/");
430 }
431
HWTEST_F_L0(PGOProfilerTest,PGOProfilerManagerInvalidPath)432 HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerInvalidPath)
433 {
434 RuntimeOption option;
435 option.SetEnableProfile(true);
436 option.SetProfileDir("ark-profiler4");
437 vm_ = JSNApi::CreateJSVM(option);
438 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
439 JSNApi::DestroyJSVM(vm_);
440 }
441
HWTEST_F_L0(PGOProfilerTest,PGOProfilerManagerInitialize)442 HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerInitialize)
443 {
444 RuntimeOption option;
445 option.SetEnableProfile(true);
446 // outDir is empty
447 option.SetProfileDir("");
448 vm_ = JSNApi::CreateJSVM(option);
449 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
450
451 JSNApi::DestroyJSVM(vm_);
452 }
453
HWTEST_F_L0(PGOProfilerTest,PGOProfilerManagerSample)454 HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerSample)
455 {
456 RuntimeOption option;
457 option.SetEnableProfile(true);
458 char currentPath[PATH_MAX + 2];
459 if (memset_s(currentPath, PATH_MAX, 1, PATH_MAX) != EOK) {
460 ASSERT_TRUE(false);
461 }
462 currentPath[PATH_MAX + 1] = '\0';
463 option.SetProfileDir(currentPath);
464 vm_ = JSNApi::CreateJSVM(option);
465 vm_->GetJSThread()->ManagedCodeBegin();
466 uint32_t checksum = 304293;
467 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "");
468 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
469
470 // RecordName is hole
471 MethodLiteral *methodLiteral = new MethodLiteral(EntityId(61));
472 JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiteral);
473 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
474 func->SetModule(vm_->GetJSThread(), JSTaggedValue::Hole());
475 vm_->GetJSThread()->ManagedCodeEnd();
476 JSNApi::DestroyJSVM(vm_);
477
478 PGOProfilerDecoder loader("", DECODER_THRESHOLD);
479 // path is empty()
480 ASSERT_TRUE(loader.LoadAndVerify({{"", checksum}}));
481 // path size greater than PATH_MAX
482 char path[PATH_MAX + 1] = {'0'};
483 PGOProfilerDecoder loader1(path, 4);
484 ASSERT_TRUE(!loader1.LoadAndVerify({{"", checksum}}));
485 }
486
HWTEST_F_L0(PGOProfilerTest,PGOProfilerDoubleVM)487 HWTEST_F_L0(PGOProfilerTest, PGOProfilerDoubleVM)
488 {
489 mkdir("ark-profiler5/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
490 RuntimeOption option;
491 option.SetEnableProfile(true);
492 // outDir is empty
493 option.SetProfileDir("ark-profiler5/");
494 vm_ = JSNApi::CreateJSVM(option);
495 std::vector<MethodLiteral *> methodLiterals {};
496 CreateJSPandaFile("sample_test.abc", methodLiterals);
497 EXPECT_GE(methodLiterals.size(), 2); // number of methods
498 vm_->GetJSThread()->ManagedCodeBegin();
499 JSPandaFileManager::GetInstance()->AddJSPandaFile(pf_);
500 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
501 constPool->SetJSPandaFile(pf_.get());
502 uint32_t checksum = pf_->GetChecksum();
503 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "sample_test.abc");
504 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
505 // worker vm read profile enable from PGOProfilerManager singleton
506 option.SetEnableProfile(false);
507
508 std::thread t1([&]() {
509 auto vm2 = JSNApi::CreateJSVM(option);
510 vm2->GetJSThread()->ManagedCodeBegin();
511 JSHandle<ConstantPool> constPool2 = vm2->GetFactory()->NewSConstantPool(4);
512 constPool2->SetJSPandaFile(pf_.get());
513 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "sample_test.abc");
514 ASSERT_TRUE(vm2 != nullptr) << "Cannot create Runtime";
515
516 JSHandle<Method> method = vm2->GetFactory()->NewSMethod(methodLiterals[0]);
517 method->SetConstantPool(vm2->GetJSThread(), constPool2.GetTaggedValue());
518 JSHandle<JSFunction> func = vm2->GetFactory()->NewJSFunction(vm2->GetGlobalEnv(), method);
519 JSHandle<JSTaggedValue> recordName(vm2->GetFactory()->NewFromStdString("sample_test"));
520 func->SetModule(vm2->GetJSThread(), recordName);
521 vm2->GetJSThread()->ManagedCodeEnd();
522 JSNApi::DestroyJSVM(vm2);
523 });
524 {
525 ecmascript::ThreadSuspensionScope scope(vm_->GetJSThread());
526 t1.join();
527 }
528 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("sample_test"));
529 JSHandle<Method> method1 = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
530 JSHandle<Method> method2 = vm_->GetFactory()->NewSMethod(methodLiterals[1]);
531 method1->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
532 method2->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
533 JSHandle<JSFunction> func1 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method1);
534 JSHandle<JSFunction> func2 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method2);
535 JSHandle<JSTaggedValue> recordName1(vm_->GetFactory()->NewFromStdString("sample_test"));
536 func1->SetModule(vm_->GetJSThread(), recordName);
537 func2->SetModule(vm_->GetJSThread(), recordName);
538
539 vm_->GetJSThread()->ManagedCodeEnd();
540 JSNApi::DestroyJSVM(vm_);
541
542 PGOProfilerDecoder loader("ark-profiler5/profiler", DECODER_THRESHOLD);
543 mkdir("ark-profiler5/profiler", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
544 ASSERT_TRUE(!loader.LoadAndVerify({{"sample_test.abc", checksum}}));
545 CString expectRecordName = "sample_test";
546 ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[1]->GetMethodId()));
547
548 PGOProfilerDecoder loader1("ark-profiler5/modules.ap", DECODER_THRESHOLD);
549 #if defined(SUPPORT_ENABLE_ASM_INTERP)
550 ASSERT_TRUE(loader1.LoadAndVerify({{"sample_test.abc", checksum}}));
551 ASSERT_TRUE(!loader1.Match(pf_.get(), expectRecordName, methodLiterals[1]->GetMethodId()));
552 #else
553 ASSERT_TRUE(!loader1.LoadAndVerify({{"sample_test.abc", checksum}}));
554 ASSERT_TRUE(loader1.Match(pf_.get(), expectRecordName, methodLiterals[1]->GetMethodId()));
555 #endif
556
557 unlink("ark-profiler5/modules.ap");
558 rmdir("ark-profiler5/profiler");
559 rmdir("ark-profiler5/");
560 }
561
HWTEST_F_L0(PGOProfilerTest,PGOProfilerDecoderNoHotMethod)562 HWTEST_F_L0(PGOProfilerTest, PGOProfilerDecoderNoHotMethod)
563 {
564 mkdir("ark-profiler8/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
565 RuntimeOption option;
566 option.SetEnableProfile(true);
567 option.SetProfileDir("ark-profiler8/");
568 vm_ = JSNApi::CreateJSVM(option);
569 std::vector<MethodLiteral *> methodLiterals {};
570 CreateJSPandaFile("sample_test.abc", methodLiterals);
571 EXPECT_GE(methodLiterals.size(), 1); // number of methods
572 vm_->GetJSThread()->ManagedCodeBegin();
573 JSPandaFileManager::GetInstance()->AddJSPandaFile(pf_);
574 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
575 constPool->SetJSPandaFile(pf_.get());
576 uint32_t checksum = pf_->GetChecksum();
577 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "sample_test.abc");
578
579 JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
580
581 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
582 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
583 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("sample_test"));
584 func->SetModule(vm_->GetJSThread(), recordName);
585 vm_->GetJSThread()->ManagedCodeEnd();
586 JSNApi::DestroyJSVM(vm_);
587
588 PGOProfilerDecoder loader("ark-profiler8/modules.ap", DECODER_THRESHOLD);
589 CString expectRecordName = "sample_test";
590 #if defined(SUPPORT_ENABLE_ASM_INTERP)
591 ASSERT_TRUE(loader.LoadAndVerify({{"sample_test.abc", checksum}}));
592 ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
593 #else
594 ASSERT_TRUE(!loader.LoadAndVerify({{"sample_test.abc", checksum}}));
595 ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
596 #endif
597
598 unlink("ark-profiler8/modules.ap");
599 rmdir("ark-profiler8/");
600 }
601
HWTEST_F_L0(PGOProfilerTest,PGOProfilerPostTask)602 HWTEST_F_L0(PGOProfilerTest, PGOProfilerPostTask)
603 {
604 std::stringstream sourceStream;
605 sourceStream << " .language ECMAScript" << std::endl;
606 for (uint32_t funcIdx = 0; funcIdx < 100; funcIdx++) {
607 sourceStream << " .function void foo" << std::to_string(funcIdx) << "(any a0, any a1, any a2) {}" << std::endl;
608 }
609 mkdir("ark-profiler9/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
610 RuntimeOption option;
611 option.SetEnableProfile(true);
612 option.SetProfileDir("ark-profiler9/");
613 vm_ = JSNApi::CreateJSVM(option);
614 std::vector<MethodLiteral *> methodLiterals {};
615 CreateJSPandaFile(sourceStream.str().c_str(), "ark-profiler9.abc", methodLiterals);
616 EXPECT_EQ(methodLiterals.size(), 100); // number of methods
617 vm_->GetJSThread()->ManagedCodeBegin();
618 JSPandaFileManager::GetInstance()->AddJSPandaFile(pf_);
619 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
620 constPool->SetJSPandaFile(pf_.get());
621 uint32_t checksum = pf_->GetChecksum();
622 PGOProfilerManager::GetInstance()->SetApGenMode(ApGenMode::OVERWRITE);
623 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "ark-profiler9.abc");
624
625 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("ark-profiler9.abc"));
626 for (int i = 61; i < 91; i++) {
627 JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[i]);
628 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
629 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
630 func->SetModule(vm_->GetJSThread(), recordName);
631 }
632
633 vm_->GetJSThread()->ManagedCodeEnd();
634 JSNApi::DestroyJSVM(vm_);
635
636 PGOProfilerDecoder loader("ark-profiler9/modules.ap", DECODER_THRESHOLD);
637 #if defined(SUPPORT_ENABLE_ASM_INTERP)
638 ASSERT_TRUE(loader.LoadAndVerify({{"ark-profiler9.abc", checksum}}));
639 #else
640 ASSERT_TRUE(!loader.LoadAndVerify({{"ark-profiler9.abc", checksum}}));
641 #endif
642 CString expectRecordName = "ark-profiler9.abc";
643 for (int i = 0; i < 100; i++) {
644 EntityId methodId = methodLiterals[i]->GetMethodId();
645 loader.MatchAndMarkMethod(pf_.get(), expectRecordName, methodLiterals[i]->GetMethodName(pf_.get(), methodId),
646 methodId);
647 }
648 for (int i = 61; i < 91; i++) {
649 #if defined(SUPPORT_ENABLE_ASM_INTERP)
650 if (i % 3 == 0) {
651 ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[i]->GetMethodId()));
652 } else {
653 ASSERT_TRUE(!loader.Match(pf_.get(), expectRecordName, methodLiterals[i]->GetMethodId()));
654 #else
655 if (i % 3 == 0) {
656 ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[i]->GetMethodId()));
657 } else {
658 ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[i]->GetMethodId()));
659 #endif
660 }
661 }
662
663 unlink("ark-profiler9/modules.ap");
664 rmdir("ark-profiler9/");
665 }
666
667 HWTEST_F_L0(PGOProfilerTest, FailResetProfilerInWorker)
668 {
669 mkdir("ark-profiler12/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
670 RuntimeOption option;
671 // Although enableProfile is set in option, but it will not work when isWorker is set.
672 option.SetEnableProfile(true);
673 option.SetIsWorker();
674 option.SetProfileDir("ark-profiler12/");
675 // PgoProfiler is disabled as default.
676 vm_ = JSNApi::CreateJSVM(option);
677 std::vector<MethodLiteral *> methodLiterals {};
678 CreateJSPandaFile("sample_test.abc", methodLiterals);
679 EXPECT_GE(methodLiterals.size(), 1); // number of methods
680 vm_->GetJSThread()->ManagedCodeBegin();
681 JSPandaFileManager::GetInstance()->AddJSPandaFile(pf_);
682 uint32_t checksum = pf_->GetChecksum();
683 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum, "sample_test.abc");
684 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
685
686 JSHandle<Method> method = vm_->GetFactory()->NewSMethod(methodLiterals[0]);
687
688 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewSConstantPool(4);
689 constPool->SetJSPandaFile(pf_.get());
690 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
691 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
692 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("sample_test"));
693 func->SetModule(vm_->GetJSThread(), recordName);
694 vm_->GetJSThread()->ManagedCodeEnd();
695 JSNApi::DestroyJSVM(vm_);
696
697 // Loader
698 ASSERT_FALSE(FileExist("ark-profiler12/modules.ap"));
699 PGOProfilerDecoder loader("ark-profiler12/modules.ap", DECODER_THRESHOLD);
700 ASSERT_TRUE(!loader.LoadAndVerify({{"sample_test.abc", checksum}}));
701 CString expectRecordName = "sample_test";
702 ASSERT_TRUE(loader.Match(pf_.get(), expectRecordName, methodLiterals[0]->GetMethodId()));
703 rmdir("ark-profiler12/");
704 }
705
706 #if defined(SUPPORT_ENABLE_ASM_INTERP)
707 HWTEST_F_L0(PGOProfilerTest, ProfileCallTest)
708 {
709 mkdir("ark-profiler13/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
710 const char *targetRecordName = "call_test";
711 ExecuteAndLoadJSPandaFile("ark-profiler13/", targetRecordName);
712 ASSERT_NE(pf_, nullptr);
713 uint32_t checksum = pf_->GetChecksum();
714 ;
715
716 // Loader
717 PGOProfilerDecoder decoder("ark-profiler13/modules.ap", 1);
718 PGOProfilerDecoder decoder1("ark-profiler13/modules.ap", 10);
719 PGOProfilerDecoder decoder2("ark-profiler13/modules.ap", 11000);
720 ASSERT_TRUE(decoder.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
721 ASSERT_TRUE(decoder1.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
722 ASSERT_TRUE(decoder2.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
723 auto methodLiterals = pf_->GetMethodLiteralMap();
724 for (auto iter : methodLiterals) {
725 auto methodLiteral = iter.second;
726 auto methodId = methodLiteral->GetMethodId();
727 auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
728 decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
729 decoder1.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
730 decoder2.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
731 // ASSERT_TRUE(decoder.Match(pf_.get(), targetRecordName, methodId))
732 if (std::string(methodName) == "Test") {
733 ASSERT_TRUE(decoder1.Match(pf_.get(), targetRecordName, methodId));
734 ASSERT_TRUE(decoder2.Match(pf_.get(), targetRecordName, methodId));
735 } else {
736 // ASSERT_TRUE(decoder1.Match(pf_.get(), targetRecordName, methodId))
737 // ASSERT_TRUE(decoder2.Match(pf_.get(), targetRecordName, methodId))
738 }
739 }
740 unlink("ark-profiler13/modules.ap");
741 rmdir("ark-profiler13/");
742 }
743
744 HWTEST_F_L0(PGOProfilerTest, UseClassTypeTest)
745 {
746 mkdir("ark-profiler14/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
747 const char *targetRecordName = "class_test";
748 ExecuteAndLoadJSPandaFile("ark-profiler14/", targetRecordName);
749 ASSERT_NE(pf_, nullptr);
750 uint32_t checksum = pf_->GetChecksum();
751
752 // Loader
753 PGOProfilerDecoder decoder("ark-profiler14/modules.ap", 1);
754 ASSERT_TRUE(decoder.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
755 auto methodLiterals = pf_->GetMethodLiteralMap();
756 for (auto iter : methodLiterals) {
757 auto methodLiteral = iter.second;
758 auto methodId = methodLiteral->GetMethodId();
759 auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
760 decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
761 ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
762 auto callback = [methodName](uint32_t offset, const PGOType *type) {
763 ASSERT_NE(offset, 0);
764 if (type->IsScalarOpType()) {
765 } else if (type->IsRwOpType()) {
766 auto pgoRWOpType = *reinterpret_cast<const PGORWOpType *>(type);
767 if (std::string(methodName) == "Foot" || std::string(methodName) == "Arm") {
768 ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
769 } else if (std::string(methodName) == "foo" || std::string(methodName) == "Body") {
770 ASSERT_TRUE(pgoRWOpType.GetCount() == 3);
771 }
772 } else {
773 ASSERT_TRUE(true);
774 }
775 };
776 decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral, callback);
777 }
778 unlink("ark-profiler14/modules.ap");
779 rmdir("ark-profiler14/");
780 }
781
782 HWTEST_F_L0(PGOProfilerTest, DefineClassTypeTest)
783 {
784 mkdir("ark-profiler15/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
785 const char *targetRecordName = "class_test";
786 ExecuteAndLoadJSPandaFile("ark-profiler15/", targetRecordName);
787 ASSERT_NE(pf_, nullptr);
788 uint32_t checksum = pf_->GetChecksum();
789
790 // Loader
791 PGOProfilerDecoder decoder("ark-profiler15/modules.ap", 1);
792 ASSERT_TRUE(decoder.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
793 auto methodLiterals = pf_->GetMethodLiteralMap();
794 for (auto iter : methodLiterals) {
795 auto methodLiteral = iter.second;
796 auto methodId = methodLiteral->GetMethodId();
797 auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
798 decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
799 ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
800 auto callback = [methodName, &decoder, jsPandaFile = pf_](uint32_t offset, const PGOType *type) {
801 ASSERT_NE(offset, 0);
802 if (type->IsScalarOpType()) {
803 auto sampleType = *reinterpret_cast<const PGOSampleType *>(type);
804 if (sampleType.IsProfileType()) {
805 ASSERT_EQ(std::string(methodName), "func_main_0");
806 PGOHClassTreeDesc *desc;
807 if (!decoder.GetHClassTreeDesc(sampleType, &desc)) {
808 return;
809 }
810 return;
811 auto classId = EntityId(sampleType.GetProfileType().GetId());
812 auto className = MethodLiteral::GetMethodName(jsPandaFile.get(), classId);
813 if (std::string(className) == "Arm") {
814 auto superClassId = EntityId(desc->GetProfileType().GetId());
815 auto superClassName = MethodLiteral::GetMethodName(jsPandaFile.get(), superClassId);
816 ASSERT_EQ(std::string(superClassName), "Body");
817 } else if (std::string(className) == "Foot") {
818 auto superClassId = EntityId(desc->GetProfileType().GetId());
819 auto superClassName = MethodLiteral::GetMethodName(jsPandaFile.get(), superClassId);
820 ASSERT_EQ(std::string(superClassName), "Body");
821 } else {
822 ASSERT_EQ(desc->GetProfileType().GetRaw(), 0);
823 }
824 }
825 }
826 };
827 decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral, callback);
828 }
829 unlink("ark-profiler15/modules.ap");
830 rmdir("ark-profiler15/");
831 }
832
833 HWTEST_F_L0(PGOProfilerTest, OpTypeTest)
834 {
835 mkdir("ark-profiler16/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
836 const char *targetRecordName = "op_type_test";
837 ExecuteAndLoadJSPandaFile("ark-profiler16/", targetRecordName);
838 ASSERT_NE(pf_, nullptr);
839 uint32_t checksum = pf_->GetChecksum();
840
841 // Loader
842 PGOProfilerDecoder decoder("ark-profiler16/modules.ap", 1);
843 ASSERT_TRUE(decoder.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
844 std::string types[17] = {"1", "5", "4", "4", "4", "4", "4", "4", "5", "4", "4", "1", "1", "4", "5", "1", "1"};
845 int index = 0;
846 auto methodLiterals = pf_->GetMethodLiteralMap();
847 for (auto iter : methodLiterals) {
848 auto methodLiteral = iter.second;
849 auto methodId = methodLiteral->GetMethodId();
850 auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
851 if (std::string(methodName) != "sun" && std::string(methodName) != "sun1") {
852 decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
853 ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
854 }
855 auto callback = [methodName, types, &index](uint32_t offset, const PGOType *type) {
856 ASSERT_NE(offset, 0);
857 if (type->IsScalarOpType()) {
858 auto sampleType = *reinterpret_cast<const PGOSampleType *>(type);
859 if (sampleType.IsProfileType()) {
860 return;
861 }
862 if (std::string(methodName) == "advance") {
863 if (sampleType.GetWeight() > 0) {
864 auto trueWeight = sampleType.GetWeight() >> 10;
865 auto falseWeight = sampleType.GetWeight() & 0x7FF;
866 auto primitiveType = sampleType.GetPrimitiveType();
867 ASSERT_GT(trueWeight, falseWeight);
868 ASSERT_EQ(static_cast<uint32_t>(primitiveType), PGOSampleType::IntType());
869 } else {
870 ASSERT_EQ(sampleType.GetTypeString(), types[index++]);
871 }
872 }
873 }
874 };
875 decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral, callback);
876 }
877 unlink("ark-profiler16/modules.ap");
878 rmdir("ark-profiler16/");
879 }
880
881 HWTEST_F_L0(PGOProfilerTest, ArrayProfileTest)
882 {
883 mkdir("ark-profiler18/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
884 const char *targetRecordName = "array_test";
885 ExecuteAndLoadJSPandaFile("ark-profiler18/", targetRecordName);
886 ASSERT_NE(pf_, nullptr);
887 uint32_t checksum = pf_->GetChecksum();
888
889 // Loader
890 PGOProfilerDecoder decoder("ark-profiler18/modules.ap", 1);
891 ASSERT_TRUE(decoder.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
892 auto methodLiterals = pf_->GetMethodLiteralMap();
893 for (auto iter : methodLiterals) {
894 auto methodLiteral = iter.second;
895 auto methodId = methodLiteral->GetMethodId();
896 auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
897 decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
898 ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
899 auto callback = [methodName, &decoder, jsPandaFile = pf_](uint32_t offset, const PGOType *type) {
900 if (type->IsScalarOpType()) {
901 auto sampleType = *reinterpret_cast<const PGOSampleType *>(type);
902 if (sampleType.IsProfileType()) {
903 ASSERT_EQ(std::string(methodName), "func_main_0");
904 PGOHClassTreeDesc *desc;
905 if (!decoder.GetHClassTreeDesc(sampleType, &desc)) {
906 return;
907 }
908 }
909 } else if (type->IsRwOpType()) {
910 auto pgoRWOpType = *reinterpret_cast<const PGORWOpType *>(type);
911 if (std::string(methodName) == "foo") {
912 ASSERT_TRUE(pgoRWOpType.GetCount() == 3);
913 auto classType = pgoRWOpType.GetObjectInfo(0).GetProfileType();
914 ASSERT_TRUE(classType.IsBuiltinsArray());
915 ASSERT_EQ(classType.GetElementsKindBeforeTransition(), ElementsKind::NUMBER);
916
917 classType = pgoRWOpType.GetObjectInfo(1).GetProfileType();
918 ASSERT_TRUE(classType.IsBuiltinsArray());
919 ASSERT_EQ(classType.GetElementsKindBeforeTransition(), ElementsKind::HOLE_INT);
920
921 classType = pgoRWOpType.GetObjectInfo(2).GetProfileType();
922 ASSERT_TRUE(classType.IsBuiltinsArray());
923 ASSERT_EQ(classType.GetElementsKindBeforeTransition(), ElementsKind::TAGGED);
924 } else if (std::string(methodName) == "foo1") {
925 ASSERT_TRUE(pgoRWOpType.GetCount() == 2);
926 auto classType = pgoRWOpType.GetObjectInfo(0).GetProfileType();
927 ASSERT_TRUE(classType.IsBuiltinsArray());
928 ASSERT_EQ(classType.GetElementsKindBeforeTransition(), ElementsKind::NUMBER);
929
930 classType = pgoRWOpType.GetObjectInfo(1).GetProfileType();
931 ASSERT_TRUE(classType.IsBuiltinsArray());
932 ASSERT_EQ(classType.GetElementsKindBeforeTransition(), ElementsKind::TAGGED);
933 } else if (std::string(methodName) == "foo2") {
934 ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
935 auto classType = pgoRWOpType.GetObjectInfo(0).GetProfileType();
936 ASSERT_TRUE(classType.IsBuiltinsArray());
937 ASSERT_EQ(classType.GetElementsKindBeforeTransition(), ElementsKind::HOLE_TAGGED);
938 }
939 }
940 };
941 decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral, callback);
942 }
943 unlink("ark-profiler18/modules.ap");
944 rmdir("ark-profiler18/");
945 }
946
947 HWTEST_F_L0(PGOProfilerTest, ObjectLiteralProfileTest)
948 {
949 mkdir("ark-profiler20/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
950 const char *targetRecordName = "object_literal";
951 ExecuteAndLoadJSPandaFile("ark-profiler20/", targetRecordName);
952 ASSERT_NE(pf_, nullptr);
953 uint32_t checksum = pf_->GetChecksum();
954
955 // Loader
956 PGOProfilerDecoder decoder("ark-profiler20/modules.ap", 1);
957 ASSERT_TRUE(decoder.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
958 auto methodLiterals = pf_->GetMethodLiteralMap();
959 for (auto iter : methodLiterals) {
960 auto methodLiteral = iter.second;
961 auto methodId = methodLiteral->GetMethodId();
962 auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
963 decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
964 ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
965 auto callback = [methodName, &decoder, jsPandaFile = pf_](uint32_t offset, const PGOType *type) {
966 if (type->IsScalarOpType()) {
967 auto sampleType = *reinterpret_cast<const PGOSampleType *>(type);
968 if (sampleType.IsProfileType()) {
969 ASSERT_EQ(std::string(methodName), "func_main_0");
970 PGOHClassTreeDesc *desc;
971 if (!decoder.GetHClassTreeDesc(sampleType, &desc)) {
972 return;
973 }
974 }
975 } else if (type->IsRwOpType()) {
976 auto pgoRWOpType = *reinterpret_cast<const PGORWOpType *>(type);
977 if (std::string(methodName) == "foo") {
978 ASSERT_TRUE(pgoRWOpType.GetCount() == 2);
979 auto classType = PGOSampleType(pgoRWOpType.GetObjectInfo(0).GetProfileType());
980 PGOHClassTreeDesc *desc;
981 ASSERT_TRUE(decoder.GetHClassTreeDesc(classType, &desc));
982
983 classType = PGOSampleType(pgoRWOpType.GetObjectInfo(1).GetProfileType());
984 ASSERT_TRUE(decoder.GetHClassTreeDesc(classType, &desc));
985 }
986 }
987 };
988 decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral, callback);
989 }
990 unlink("ark-profiler20/modules.ap");
991 rmdir("ark-profiler20/");
992 }
993
994 HWTEST_F_L0(PGOProfilerTest, ArraySizeProfileTest)
995 {
996 mkdir("ark-profiler21/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
997 const char *targetRecordName = "array_size_test";
998 ExecuteAndLoadJSPandaFile("ark-profiler21/", targetRecordName);
999 ASSERT_NE(pf_, nullptr);
1000 uint32_t checksum = pf_->GetChecksum();
1001
1002 // Loader
1003 PGOProfilerDecoder decoder("ark-profiler21/modules.ap", 1);
1004 ASSERT_TRUE(decoder.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
1005 auto methodLiterals = pf_->GetMethodLiteralMap();
1006 for (auto iter : methodLiterals) {
1007 auto methodLiteral = iter.second;
1008 auto methodId = methodLiteral->GetMethodId();
1009 auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
1010 decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
1011 ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
1012 auto callback = [methodName, jsPandaFile = pf_](uint32_t offset, const PGOType *type) {
1013 if (type->IsDefineOpType()) {
1014 auto defineOptype = reinterpret_cast<const PGODefineOpType *>(type);
1015 if (std::string(methodName) == "foo") {
1016 ASSERT_EQ(defineOptype->GetElementsLength(), 4);
1017 } else if (std::string(methodName) == "foo1") {
1018 ASSERT_EQ(defineOptype->GetElementsLength(), 12);
1019 } else if (std::string(methodName) == "foo2") {
1020 ASSERT_EQ(defineOptype->GetElementsLength(), 12);
1021 }
1022 }
1023 };
1024 decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral, callback);
1025 }
1026 unlink("ark-profiler21/modules.ap");
1027 rmdir("ark-profiler21/");
1028 }
1029
1030 HWTEST_F_L0(PGOProfilerTest, StringEqualProfileTest)
1031 {
1032 mkdir("ark-profiler22/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1033 const char *targetRecordName = "string_equal";
1034 ExecuteAndLoadJSPandaFile("ark-profiler22/", targetRecordName);
1035 ASSERT_NE(pf_, nullptr);
1036 uint32_t checksum = pf_->GetChecksum();
1037
1038 // Loader
1039 PGOProfilerDecoder decoder("ark-profiler22/modules.ap", 1);
1040 ASSERT_TRUE(decoder.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
1041 auto methodLiterals = pf_->GetMethodLiteralMap();
1042 for (auto iter : methodLiterals) {
1043 auto methodLiteral = iter.second;
1044 auto methodId = methodLiteral->GetMethodId();
1045 auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
1046 decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
1047 ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
1048 auto callback = [methodName, jsPandaFile = pf_](uint32_t offset, const PGOType *type) {
1049 if (type->IsScalarOpType()) {
1050 auto sampleType = *reinterpret_cast<const PGOSampleType *>(type);
1051 if (sampleType.IsProfileType()) {
1052 return;
1053 }
1054 if (std::string(methodName) == "foo1" || std::string(methodName) == "foo2") {
1055 auto primitiveType = sampleType.GetPrimitiveType();
1056 ASSERT_EQ(static_cast<uint32_t>(primitiveType), PGOSampleType::StringType());
1057 }
1058 }
1059 };
1060 decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral, callback);
1061 }
1062 unlink("ark-profiler22/modules.ap");
1063 rmdir("ark-profiler22/");
1064 }
1065
1066 HWTEST_F_L0(PGOProfilerTest, BuiltinsTest)
1067 {
1068 mkdir("ark-profiler23/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1069 const char *targetRecordName = "builtins_test";
1070 ExecuteAndLoadJSPandaFile("ark-profiler23/", targetRecordName);
1071 ASSERT_NE(pf_, nullptr);
1072 uint32_t checksum = pf_->GetChecksum();
1073
1074 // Loader
1075 PGOProfilerDecoder decoder("ark-profiler23/modules.ap", 1);
1076 ASSERT_TRUE(decoder.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
1077 auto methodLiterals = pf_->GetMethodLiteralMap();
1078 for (auto iter : methodLiterals) {
1079 auto methodLiteral = iter.second;
1080 auto methodId = methodLiteral->GetMethodId();
1081 auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
1082 if (std::string(methodName) != "ArrayList") {
1083 decoder.MatchAndMarkMethod(pf_.get(), targetRecordName, methodName, methodId);
1084 ASSERT_TRUE(!decoder.Match(pf_.get(), targetRecordName, methodId));
1085 }
1086 auto callback = [methodName](uint32_t offset, const PGOType *type) {
1087 ASSERT_NE(offset, 0);
1088 if (type->IsRwOpType() && std::string(methodName) == "A") {
1089 auto pgoRWOpType = *reinterpret_cast<const PGORWOpType *>(type);
1090 ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
1091 }
1092 };
1093 decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral, callback);
1094 }
1095 unlink("ark-profiler23/modules.ap");
1096 rmdir("ark-profiler23/");
1097 }
1098
1099 #endif
1100
1101 #if defined(SUPPORT_ENABLE_ASM_INTERP)
1102 HWTEST_F_L0(PGOProfilerTest, FileConsistencyCheck)
1103 {
1104 mkdir("ark-profiler17/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1105 const char *targetRecordName = "sample_test";
1106 ExecuteAndLoadJSPandaFile("ark-profiler17/", targetRecordName);
1107 ASSERT_NE(pf_, nullptr);
1108 uint32_t checksum = pf_->GetChecksum();
1109
1110 // write to corrupt the ap file's consistency
1111 std::ofstream fWriter("ark-profiler17/modules.ap", std::fstream::app);
1112
1113 fWriter.write(reinterpret_cast<char *>(&checksum), sizeof(checksum));
1114 fWriter.seekp(100);
1115 fWriter.write(reinterpret_cast<char *>(&checksum), sizeof(checksum));
1116 fWriter.close();
1117
1118 // Loader
1119 PGOProfilerDecoder loader("ark-profiler17/modules.ap", DECODER_THRESHOLD);
1120 ASSERT_FALSE(loader.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
1121 unlink("ark-profiler17/modules.ap");
1122 rmdir("ark-profiler17/");
1123 }
1124
1125 HWTEST_F_L0(PGOProfilerTest, MergeApSelfTwice)
1126 {
1127 mkdir("ark-profiler18/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1128 const char *targetRecordName = "op_type_test";
1129 ExecuteAndLoadJSPandaFile("ark-profiler18/", targetRecordName);
1130 ASSERT_NE(pf_, nullptr);
1131
1132 // Loader
1133 PGOProfilerDecoder decoder("ark-profiler18/modules_merge.ap", 1);
1134 PGOProfilerDecoder decoderSingle("ark-profiler18/modules.ap", 1);
1135 ASSERT_TRUE(PGOProfilerManager::MergeApFiles("ark-profiler18/modules.ap:ark-profiler18/modules.ap",
1136 "ark-profiler18/modules_merge.ap", 1, ApGenMode::OVERWRITE));
1137 ASSERT_TRUE(decoder.LoadFull());
1138 ASSERT_TRUE(decoderSingle.LoadFull());
1139
1140 auto doubleCount =
1141 decoder.GetRecordDetailInfos().GetRecordInfos().begin()->second->GetMethodInfos().begin()->second->GetCount();
1142 auto singleCount = decoderSingle.GetRecordDetailInfos()
1143 .GetRecordInfos()
1144 .begin()
1145 ->second->GetMethodInfos()
1146 .begin()
1147 ->second->GetCount();
1148 ASSERT_EQ(doubleCount, singleCount + singleCount);
1149
1150 unlink("ark-profiler18/modules.ap");
1151 unlink("ark-profiler18/modules_merge.ap");
1152 rmdir("ark-profiler18/");
1153 }
1154 #endif
1155
1156 HWTEST_F_L0(PGOProfilerTest, RuntimeMerge)
1157 {
1158 mkdir("ark-profiler19/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1159 ExecuteAndLoadJSPandaFile("ark-profiler19/", "truck");
1160 ExecuteAndLoadJSPandaFile("ark-profiler19/", "call_test");
1161 ExecuteAndLoadJSPandaFile("ark-profiler19/", "truck");
1162
1163 // Loader
1164 PGOProfilerDecoder loader("ark-profiler19/modules.ap", DECODER_THRESHOLD);
1165 CString expectRecordName = "sample_test";
1166 #if defined(SUPPORT_ENABLE_ASM_INTERP)
1167 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<PGOMethodId>>> methodIdInAp;
1168 ParseRelatedPandaFileMethods(loader, methodIdInAp);
1169 ASSERT_EQ(methodIdInAp.size(), 3);
1170 CheckApMethods(methodIdInAp);
1171 #else
1172 uint32_t checksum = pf_->GetChecksum();
1173 ASSERT_TRUE(!loader.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
1174 #endif
1175 unlink("ark-profiler19/modules.ap");
1176 rmdir("ark-profiler19/");
1177 }
1178
1179 HWTEST_F_L0(PGOProfilerTest, ProfdumpMerge)
1180 {
1181 mkdir("ark-profiler20/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1182
1183 ExecuteAndLoadJSPandaFile("ark-profiler20/merge_file_1.ap", "merge_file_1");
1184 ExecuteAndLoadJSPandaFile("ark-profiler20/merge_file_2.ap", "merge_file_2");
1185 ExecuteAndLoadJSPandaFile("ark-profiler20/merge_file_3.ap", "merge_file_3");
1186
1187 // Loader
1188 PGOProfilerDecoder loader("ark-profiler20/merged.ap", DECODER_THRESHOLD);
1189 ASSERT_TRUE(PGOProfilerManager::MergeApFiles(
1190 "ark-profiler20/merge_file_1.ap:ark-profiler20/merge_file_2.ap:ark-profiler20/merge_file_3.ap",
1191 "ark-profiler20/merged.ap", 1, ApGenMode::OVERWRITE));
1192
1193 CString expectRecordName = "sample_test";
1194 #if defined(SUPPORT_ENABLE_ASM_INTERP)
1195 std::unordered_map<std::string, std::unordered_map<std::string, std::vector<PGOMethodId>>> methodIdInAp;
1196 ParseRelatedPandaFileMethods(loader, methodIdInAp);
1197 ASSERT_EQ(methodIdInAp.size(), 3);
1198 CheckApMethods(methodIdInAp);
1199 #else
1200 uint32_t checksum = pf_->GetChecksum();
1201 ASSERT_TRUE(!loader.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
1202 #endif
1203 unlink("ark-profiler20/merge_file_1.ap");
1204 unlink("ark-profiler20/merge_file_2.ap");
1205 unlink("ark-profiler20/merge_file_3.ap");
1206 unlink("ark-profiler20/merged.ap");
1207 rmdir("ark-profiler20/");
1208 }
1209
1210 HWTEST_F_L0(PGOProfilerTest, ApVersionMatchCheck)
1211 {
1212 mkdir("ark-ApVersionMatchCheck/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1213 const char *targetRecordName = "sample_test";
1214 ExecuteAndLoadJSPandaFile("ark-ApVersionMatchCheck/", targetRecordName);
1215 ASSERT_NE(pf_, nullptr);
1216
1217 auto info = std::make_shared<PGOInfo>(DECODER_THRESHOLD);
1218 info->GetHeaderPtr()->SetVersion(PGOProfilerHeader::PROFILE_TYPE_WITH_ABC_ID_MINI_VERSION);
1219 PGOProfilerEncoder encoder("ark-ApVersionMatchCheck/modules.ap", PGOProfilerEncoder::ApGenMode::MERGE);
1220 encoder.Save(info);
1221
1222 PGOProfilerDecoder decoder("ark-ApVersionMatchCheck/modules.ap", DECODER_THRESHOLD);
1223 PGOProfilerHeader::SetStrictMatch(true);
1224 ASSERT_FALSE(decoder.LoadFull());
1225 PGOProfilerHeader::SetStrictMatch(false);
1226 ASSERT_TRUE(decoder.LoadFull());
1227
1228 unlink("ark-ApVersionMatchCheck/modules.ap");
1229 unlink("ark-ApVersionMatchCheck/");
1230 }
1231
1232 HWTEST_F_L0(PGOProfilerTest, TypedArrayOnHeap)
1233 {
1234 mkdir("ark-profiler24/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1235 const char *targetRecordName = "typedarray_length";
1236 ExecuteAndLoadJSPandaFile("ark-profiler24/", targetRecordName);
1237 ASSERT_NE(pf_, nullptr);
1238 uint32_t checksum = pf_->GetChecksum();
1239
1240 // Loader
1241 PGOProfilerDecoder decoder("ark-profiler24/modules.ap", 1);
1242 ASSERT_TRUE(decoder.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
1243 auto methodLiterals = pf_->GetMethodLiteralMap();
1244 for (auto iter : methodLiterals) {
1245 auto methodLiteral = iter.second;
1246 auto methodId = methodLiteral->GetMethodId();
1247 auto methodName = methodLiteral->GetMethodName(pf_.get(), methodId);
1248 auto callback = [methodName](uint32_t offset, const PGOType *type) {
1249 ASSERT_NE(offset, 0);
1250 if (type->IsRwOpType() && std::string(methodName) == "test") {
1251 auto pgoRWOpType = *reinterpret_cast<const PGORWOpType *>(type);
1252 ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
1253 }
1254 };
1255 decoder.GetTypeInfo(pf_.get(), targetRecordName, methodLiteral, callback);
1256 }
1257 unlink("ark-profiler24/modules.ap");
1258 rmdir("ark-profiler24/");
1259 }
1260
1261 HWTEST_F_L0(PGOProfilerTest, ProfileTypeConstructor)
1262 {
1263 mkdir("ark-profiler25/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1264 const char *targetRecordName = "typedarray_length";
1265 ExecuteAndLoadJSPandaFile("ark-profiler25/", targetRecordName);
1266 ASSERT_NE(pf_, nullptr);
1267 ApEntityId inValidId = 555;
1268 ApEntityId validId = 64;
1269 // Loader
1270 PGOProfilerDecoder decoder("ark-profiler25/modules.ap", 1);
1271 ASSERT_TRUE(decoder.LoadFull());
1272
1273 auto invalidRes = ProfileTypeRef(inValidId);
1274 auto expectFalse = ProfileType::CreateFromProfileTypeRef(decoder.GetRecordDetailInfos(), invalidRes);
1275 EXPECT_FALSE(expectFalse.has_value());
1276
1277 auto validRes = ProfileTypeRef(validId);
1278 auto expectTrue = ProfileType::CreateFromProfileTypeRef(decoder.GetRecordDetailInfos(), validRes);
1279 EXPECT_TRUE(expectTrue.has_value());
1280 unlink("ark-profiler25/modules.ap");
1281 rmdir("ark-profiler25/");
1282 }
1283
1284 HWTEST_F_L0(PGOProfilerTest, CompatibleWithAOTFileTest)
1285 {
1286 constexpr uint32_t CHECKSUM = 1;
1287 PGOProfilerDecoder decoder("", DECODER_THRESHOLD);
1288 EXPECT_TRUE(decoder.LoadAndVerify({{"", CHECKSUM}}));
1289 EXPECT_FALSE(decoder.IsCompatibleWithAOTFile());
1290 }
1291
1292 HWTEST_F_L0(PGOProfilerTest, ExternalMethodLiteralTest)
1293 {
1294 mkdir("ark-profiler26/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1295 const char *targetRecordName = "typedarray_length";
1296 ExecuteAndLoadJSPandaFile("ark-profiler26/", targetRecordName);
1297 ASSERT_NE(pf_, nullptr);
1298 uint32_t checksum = pf_->GetChecksum();
1299
1300 PGOProfilerDecoder decoder("ark-profiler26/modules.ap", DECODER_THRESHOLD);
1301 ASSERT_TRUE(decoder.LoadAndVerify({{pf_->GetNormalizedFileDesc(), checksum}}));
1302 auto callback = []([[maybe_unused]] uint32_t offset, [[maybe_unused]] const PGOType *type) { EXPECT_TRUE(false); };
1303 decoder.GetTypeInfo(pf_.get(), targetRecordName, nullptr, callback);
1304 unlink("ark-profiler26/modules.ap");
1305 rmdir("ark-profiler26/");
1306 }
1307
1308 HWTEST_F_L0(PGOProfilerTest, PGOObjectInfoOperatorLessThanTest)
1309 {
1310 constexpr uint64_t rawTypeLess = 0;
1311 constexpr uint64_t rawTypeGreater = 1;
1312
1313 ProfileType profileTypeLess(rawTypeLess);
1314 ProfileType profileTypeGreater(rawTypeGreater);
1315
1316 PGOObjectInfo objectInfoLess(profileTypeLess, profileTypeGreater, profileTypeGreater,
1317 profileTypeGreater, profileTypeGreater, profileTypeGreater, PGOSampleType());
1318 PGOObjectInfo objectInfoGreater(profileTypeGreater, profileTypeLess, profileTypeGreater,
1319 profileTypeGreater, profileTypeGreater, profileTypeGreater, PGOSampleType());
1320
1321 EXPECT_TRUE(objectInfoLess < objectInfoGreater);
1322 EXPECT_FALSE(objectInfoGreater < objectInfoLess);
1323 }
1324
1325 HWTEST_F_L0(PGOProfilerTest, PGODisableWithAOTFileWorkloadTest)
1326 {
1327 mkdir("ark-profiler27/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1328 std::ofstream fWriter("ark-profiler27/tmp.an", std::fstream::app);
1329 fWriter.close();
1330 const char *targetRecordName = "typedarray_length";
1331 std::string targetAbcPath = std::string(TARGET_ABC_PATH) + targetRecordName + ".abc";
1332 // Force set in advance to simulate AOT/JIT enable list check is passed in UT
1333 ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
1334 ecmascript::AnFileDataManager::GetInstance()->SetDir("ark-profiler27/tmp");
1335 RuntimeOption option;
1336 option.SetEnableProfile(true);
1337 option.SetProfileDir("ark-profiler27/");
1338 EcmaVM *ecmaVM = JSNApi::CreateJSVM(option);
1339 JSNApi::LoadAotFile(ecmaVM, "");
1340 EXPECT_TRUE(ecmaVM->IsEnablePGOProfiler());
1341 auto result = JSNApi::Execute(ecmaVM, targetAbcPath, targetRecordName, false);
1342 EXPECT_TRUE(result);
1343 JSNApi::DestroyJSVM(ecmaVM);
1344 EXPECT_TRUE(FileExist("ark-profiler27/modules.ap"));
1345 unlink("ark-profiler27/modules.ap");
1346 unlink("ark-profiler27/tmp.an");
1347 rmdir("ark-profiler27/");
1348 }
1349
1350 HWTEST_F_L0(PGOProfilerTest, PGODisableWithAOTFileAppTest)
1351 {
1352 mkdir("ark-profiler27/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1353 std::ofstream fWriter("ark-profiler27/tmp.an", std::fstream::app);
1354 fWriter.close();
1355 const char *targetRecordName = "typedarray_length";
1356 std::string targetAbcPath = std::string(TARGET_ABC_PATH) + targetRecordName + ".abc";
1357 // Force set in advance to simulate AOT/JIT enable list check is passed in UT
1358 ecmascript::AnFileDataManager::GetInstance()->SetEnable(true);
1359 ecmascript::AnFileDataManager::GetInstance()->SetDir("ark-profiler27/tmp");
1360 RuntimeOption option;
1361 EcmaVM *ecmaVM = JSNApi::CreateJSVM(option);
1362 option.SetEnableProfile(true);
1363 option.SetProfileDir("ark-profiler27/");
1364 JSNApi::PreFork(ecmaVM);
1365 JSNApi::PostFork(ecmaVM, option);
1366 EXPECT_TRUE(ecmaVM->IsEnablePGOProfiler());
1367 JSNApi::LoadAotFile(ecmaVM, "");
1368 EXPECT_FALSE(ecmaVM->IsEnablePGOProfiler());
1369 auto result = JSNApi::Execute(ecmaVM, targetAbcPath, targetRecordName, false);
1370 EXPECT_TRUE(result);
1371 JSNApi::DestroyJSVM(ecmaVM);
1372 EXPECT_FALSE(FileExist("ark-profiler27/modules.ap"));
1373 unlink("ark-profiler27/tmp.an");
1374 rmdir("ark-profiler27/");
1375 }
1376
1377 HWTEST_F_L0(PGOProfilerTest, PGODisableUnderAOTFailTest)
1378 {
1379 std::map<std::string, int32_t> mockAOTCompileStatusMap;
1380 mockAOTCompileStatusMap["module1"] = 0;
1381 mockAOTCompileStatusMap["module2"] = 1;
1382 mockAOTCompileStatusMap["module3"] = 4;
1383 RuntimeOption option;
1384 {
1385 // Not update existing setting when AOT compilation uninitialized or succeed
1386 EcmaVM *ecmaVM = JSNApi::CreateJSVM(option);
1387 RuntimeOption localOption = option;
1388 localOption.SetEnableProfile(true);
1389 localOption.SetAOTCompileStatusMap(mockAOTCompileStatusMap);
1390 JSNApi::PreFork(ecmaVM);
1391 JSNApi::PostFork(ecmaVM, localOption);
1392 EXPECT_FALSE(ecmaVM->GetJSOptions().GetAOTHasException());
1393 JSNApi::DestroyJSVM(ecmaVM);
1394 }
1395 {
1396 // Disable existing setting when AOT compilation failed
1397 EcmaVM *ecmaVM = JSNApi::CreateJSVM(option);
1398 RuntimeOption localOption = option;
1399 mockAOTCompileStatusMap["module4"] = 2;
1400 localOption.SetAOTCompileStatusMap(mockAOTCompileStatusMap);
1401 JSNApi::PreFork(ecmaVM);
1402 JSNApi::PostFork(ecmaVM, localOption);
1403 EXPECT_TRUE(ecmaVM->GetJSOptions().GetAOTHasException());
1404 JSNApi::DestroyJSVM(ecmaVM);
1405 }
1406 {
1407 // Disable existing setting when AOT compilation crashed
1408 EcmaVM *ecmaVM = JSNApi::CreateJSVM(option);
1409 RuntimeOption localOption = option;
1410 mockAOTCompileStatusMap["module4"] = 3;
1411 localOption.SetAOTCompileStatusMap(mockAOTCompileStatusMap);
1412 JSNApi::PreFork(ecmaVM);
1413 JSNApi::PostFork(ecmaVM, localOption);
1414 EXPECT_TRUE(ecmaVM->GetJSOptions().GetAOTHasException());
1415 JSNApi::DestroyJSVM(ecmaVM);
1416 }
1417 }
1418
1419 HWTEST_F_L0(PGOProfilerTest, AnChecksumTest)
1420 {
1421 AnFileDataManager *fileManager = AnFileDataManager::GetInstance();
1422 std::unordered_map<CString, uint32_t> testMap;
1423 testMap.emplace("test1.abc", 123456);
1424 fileManager->SafeMergeChecksumInfo(testMap);
1425 std::unordered_map<CString, uint32_t> fullMap;
1426 fullMap = fileManager->SafeGetfullFileNameToChecksumMap();
1427 ASSERT_FALSE(fullMap.empty());
1428 ASSERT_TRUE(fileManager->SafeCheckFilenameToChecksum("test1.abc", 123456));
1429 ASSERT_FALSE(fileManager->SafeCheckFilenameToChecksum("test1.abc", 654321));
1430 testMap.emplace("test2.abc", 456789);
1431 fileManager->SafeMergeChecksumInfo(testMap);
1432 fullMap = fileManager->SafeGetfullFileNameToChecksumMap();
1433 ASSERT_TRUE(fullMap.size() == 2);
1434 ASSERT_TRUE(fileManager->SafeCheckFilenameToChecksum("test2.abc", 456789));
1435 ASSERT_FALSE(fileManager->SafeCheckFilenameToChecksum("test2.abc", 987654));
1436 testMap["test1.abc"] = 123456789;
1437 fileManager->SafeMergeChecksumInfo(testMap);
1438 fullMap = fileManager->SafeGetfullFileNameToChecksumMap();
1439 ASSERT_TRUE(fullMap["test1.abc"] == static_cast<uint32_t>(-1));
1440 ASSERT_FALSE(fileManager->SafeCheckFilenameToChecksum("test1.abc", 123456789));
1441 ASSERT_TRUE(fileManager->SafeCheckFilenameToChecksum("test2.abc", 456789));
1442 fileManager->SafeDestroyAllData();
1443 }
1444
1445 HWTEST_F_L0(PGOProfilerTest, PgoChecksumTest)
1446 {
1447 mkdir("ark-pgoChecksumTest", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
1448 const char *targetRecordName = "sample_test";
1449 ExecuteAndLoadJSPandaFile("ark-pgoChecksumTest/", targetRecordName);
1450 ASSERT_TRUE(FileExist("ark-pgoChecksumTest/modules.ap"));
1451 ASSERT_NE(pf_, nullptr);
1452 PGOProfilerManager::GetInstance()->Initialize("ark-pgoChecksumTest/modules.ap", DECODER_THRESHOLD);
1453 PGOProfilerDecoder decoder0("ark-pgoChecksumTest/modules.ap", DECODER_THRESHOLD);
1454 auto info = std::make_shared<PGOInfo>(DECODER_THRESHOLD);
1455 decoder0.LoadFull();
1456 info->MergeSafe(decoder0.GetPandaFileInfos());
1457 auto& infos1 = info->GetPandaFileInfos();
1458 auto infos1AbcFilePool = decoder0.GetAbcFilePool();
1459 CString testabc1Name = "test1.abc";
1460 uint32_t testabc1Checksum = 123456;
1461 ApEntityId abcId1(0);
1462 infos1AbcFilePool->TryAdd(testabc1Name, abcId1);
1463 std::unordered_map<CString, uint32_t> fileNameToChecksumMap1;
1464 fileNameToChecksumMap1.emplace(pf_->GetNormalizedFileDesc(), pf_->GetChecksum());
1465 fileNameToChecksumMap1.emplace(testabc1Name, testabc1Checksum);
1466 infos1.Sample(123456, abcId1);
1467 ASSERT_TRUE(infos1.Checksum(fileNameToChecksumMap1, infos1AbcFilePool));
1468 fileNameToChecksumMap1.emplace("notExist.abc", 456789);
1469 ASSERT_TRUE(infos1.Checksum(fileNameToChecksumMap1, infos1AbcFilePool));
1470 // different checksum
1471 fileNameToChecksumMap1[testabc1Name] = 999999;
1472 ASSERT_FALSE(infos1.Checksum(fileNameToChecksumMap1, infos1AbcFilePool));
1473 // pandaFileInfos always keep old checksum
1474 infos1.Sample(999999, abcId1);
1475 ASSERT_FALSE(infos1.Checksum(fileNameToChecksumMap1, infos1AbcFilePool));
1476 unlink("ark-pgoChecksumTest/modules.ap");
1477 unlink("ark-pgoChecksumTest/");
1478 }
1479 } // namespace panda::test
1480