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