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 "ecmascript/object_factory.h"
22 #include "gtest/gtest.h"
23
24 #include "assembler/assembly-emitter.h"
25 #include "assembler/assembly-parser.h"
26 #include "ecmascript/ecma_vm.h"
27 #include "ecmascript/js_thread.h"
28 #include "ecmascript/jspandafile/js_pandafile.h"
29 #include "ecmascript/jspandafile/js_pandafile_manager.h"
30 #include "ecmascript/jspandafile/method_literal.h"
31 #include "ecmascript/napi/include/jsnapi.h"
32 #include "ecmascript/pgo_profiler/pgo_profiler_decoder.h"
33 #include "ecmascript/pgo_profiler/pgo_profiler_info.h"
34 #include "ecmascript/pgo_profiler/pgo_profiler_manager.h"
35 #include "ecmascript/tests/test_helper.h"
36 #include "ecmascript/jspandafile/program_object.h"
37
38 using namespace panda;
39 using namespace panda::ecmascript;
40 using namespace panda::panda_file;
41 using namespace panda::pandasm;
42
43 namespace panda::test {
44 class PGOProfilerTest : public testing::Test {
45 public:
46 using ApGenMode = PGOProfilerEncoder::ApGenMode;
SetUpTestCase()47 static void SetUpTestCase()
48 {
49 GTEST_LOG_(INFO) << "SetUpTestCase";
50 }
51
TearDownTestCase()52 static void TearDownTestCase()
53 {
54 GTEST_LOG_(INFO) << "TearDownCase";
55 }
56
TearDown()57 void TearDown() override
58 {
59 vm_ = nullptr;
60 PGOProfilerManager::GetInstance()->Destroy();
61 }
62
63 protected:
CreateJSPandaFile(const char * source,const CString filename,std::vector<MethodLiteral * > & methodLiterals)64 std::shared_ptr<JSPandaFile> CreateJSPandaFile(const char *source, const CString filename,
65 std::vector<MethodLiteral *> &methodLiterals)
66 {
67 Parser parser;
68 const std::string fn = "SRC.abc"; // test file name : "SRC.abc"
69 auto res = parser.Parse(source, fn);
70
71 std::unique_ptr<const File> pfPtr = pandasm::AsmEmitter::Emit(res.Value());
72 JSPandaFileManager *pfManager = JSPandaFileManager::GetInstance();
73 std::shared_ptr<JSPandaFile> pf = pfManager->NewJSPandaFile(pfPtr.release(), filename);
74
75 const File *file = pf->GetPandaFile();
76 const uint8_t *typeDesc = utf::CStringAsMutf8("L_GLOBAL;");
77 File::EntityId classId = file->GetClassId(typeDesc);
78 EXPECT_TRUE(classId.IsValid());
79
80 ClassDataAccessor cda(*file, classId);
81 cda.EnumerateMethods([&](panda_file::MethodDataAccessor &mda) {
82 auto *methodLiteral = new MethodLiteral(mda.GetMethodId());
83 methodLiteral->Initialize(pf.get());
84 pf->SetMethodLiteralToMap(methodLiteral);
85 methodLiterals.push_back(methodLiteral);
86 });
87 return pf;
88 }
89
ExecuteAndLoadJSPandaFile(std::string profDir,std::string recordName)90 std::shared_ptr<JSPandaFile> ExecuteAndLoadJSPandaFile(std::string profDir, std::string recordName)
91 {
92 RuntimeOption option;
93 option.SetLogLevel(LOG_LEVEL::INFO);
94 option.SetEnableProfile(true);
95 option.SetProfileDir(profDir);
96 vm_ = JSNApi::CreateJSVM(option);
97 JSNApi::EnableUserUncaughtErrorHandler(vm_);
98
99 std::string targetAbcPath = TARGET_ABC_PATH + recordName + ".abc";
100 auto result = JSNApi::Execute(vm_, targetAbcPath, recordName, false);
101 EXPECT_TRUE(result);
102
103 std::shared_ptr<JSPandaFile> jsPandaFile =
104 JSPandaFileManager::GetInstance()->FindJSPandaFile(CString(targetAbcPath));
105
106 JSNApi::DestroyJSVM(vm_);
107 return jsPandaFile;
108 }
109
110 EcmaVM *vm_ = nullptr;
111 };
112
HWTEST_F_L0(PGOProfilerTest,Sample)113 HWTEST_F_L0(PGOProfilerTest, Sample)
114 {
115 const char *source = R"(
116 .language ECMAScript
117 .function void foo1(any a0, any a1, any a2) {}
118 )";
119 std::vector<MethodLiteral *> methodLiterals {};
120 std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler.abc", methodLiterals);
121 EXPECT_EQ(methodLiterals.size(), 1); // number of methods
122
123 mkdir("ark-profiler/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
124 RuntimeOption option;
125 option.SetEnableProfile(true);
126 option.SetProfileDir("ark-profiler/");
127 vm_ = JSNApi::CreateJSVM(option);
128 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
129 constPool->SetJSPandaFile(pf.get());
130 uint32_t checksum = 304293;
131 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
132 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
133
134 JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
135 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
136 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
137 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
138 func->SetModule(vm_->GetJSThread(), recordName);
139 vm_->GetPGOProfiler()->SetSaveTimestamp(std::chrono::system_clock::now());
140 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
141 JSNApi::DestroyJSVM(vm_);
142 // Loader
143 PGOProfilerDecoder loader("ark-profiler/modules.ap", 2);
144 CString expectRecordName = "test";
145 #if defined(SUPPORT_ENABLE_ASM_INTERP)
146 ASSERT_TRUE(loader.LoadAndVerify(checksum));
147 ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
148 #else
149 ASSERT_TRUE(!loader.LoadAndVerify(checksum));
150 ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
151 #endif
152 unlink("ark-profiler/modules.ap");
153 rmdir("ark-profiler/");
154 }
155
HWTEST_F_L0(PGOProfilerTest,Sample1)156 HWTEST_F_L0(PGOProfilerTest, Sample1)
157 {
158 const char *source = R"(
159 .language ECMAScript
160 .function void foo1(any a0, any a1, any a2) {
161 lda.str "helloworld"
162 return
163 }
164 .function void foo2(any a0, any a1, any a2) {}
165 .function void foo3(any a0, any a1, any a2) {}
166 )";
167 std::vector<MethodLiteral *> methodLiterals {};
168 std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler1.abc", methodLiterals);
169 EXPECT_EQ(methodLiterals.size(), 3); // number of methods
170
171 mkdir("ark-profiler1/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
172 RuntimeOption option;
173 option.SetEnableProfile(true);
174 option.SetProfileDir("ark-profiler1/");
175 vm_ = JSNApi::CreateJSVM(option);
176 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
177 constPool->SetJSPandaFile(pf.get());
178 uint32_t checksum = 304293;
179 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
180 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
181
182 JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
183 JSHandle<Method> method1 = vm_->GetFactory()->NewMethod(methodLiterals[1]);
184 JSHandle<Method> method2 = vm_->GetFactory()->NewMethod(methodLiterals[2]);
185 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
186 method1->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
187 method2->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
188
189 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
190 JSHandle<JSFunction> func1 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method1);
191 JSHandle<JSFunction> func2 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method2);
192 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
193 func->SetModule(vm_->GetJSThread(), recordName);
194 func1->SetModule(vm_->GetJSThread(), recordName);
195 func2->SetModule(vm_->GetJSThread(), recordName);
196 for (int i = 0; i < 5; i++) {
197 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
198 }
199 for (int i = 0; i < 50; i++) {
200 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func2.GetTaggedType());
201 }
202 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func1.GetTaggedType());
203 JSNApi::DestroyJSVM(vm_);
204
205 // Loader
206 PGOProfilerDecoder loader("ark-profiler1/modules.ap", 2);
207 CString expectRecordName = "test";
208 #if defined(SUPPORT_ENABLE_ASM_INTERP)
209 ASSERT_TRUE(loader.LoadAndVerify(checksum));
210 for (uint32_t idx = 0; idx < 3; idx++) {
211 loader.MatchAndMarkMethod(expectRecordName,
212 methodLiterals[idx]->GetMethodName(pf.get(), methodLiterals[idx]->GetMethodId()),
213 methodLiterals[idx]->GetMethodId());
214 }
215 ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
216 ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[2]->GetMethodId()));
217 ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
218 #else
219 ASSERT_TRUE(!loader.LoadAndVerify(checksum));
220 ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
221 #endif
222 unlink("ark-profiler1/modules.ap");
223 rmdir("ark-profiler1/");
224 }
225
HWTEST_F_L0(PGOProfilerTest,Sample2)226 HWTEST_F_L0(PGOProfilerTest, Sample2)
227 {
228 const char *source = R"(
229 .language ECMAScript
230 .function void foo1(any a0, any a1, any a2) {}
231 .function void foo2(any a0, any a1, any a2) {}
232 )";
233 std::vector<MethodLiteral *> methodLiterals {};
234 std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler2.abc", methodLiterals);
235 EXPECT_EQ(methodLiterals.size(), 2); // number of methods
236
237 mkdir("ark-profiler2/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
238 RuntimeOption option;
239 option.SetEnableProfile(true);
240 option.SetProfileDir("ark-profiler2/");
241 vm_ = JSNApi::CreateJSVM(option);
242 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
243 constPool->SetJSPandaFile(pf.get());
244 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
245 uint32_t checksum = 304293;
246 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
247
248 JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
249 JSHandle<Method> method1 = vm_->GetFactory()->NewMethod(methodLiterals[1]);
250
251 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
252 method1->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
253 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
254 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
255 func->SetModule(vm_->GetJSThread(), recordName);
256 JSHandle<JSFunction> func1 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method1);
257 JSHandle<JSTaggedValue> recordName1(vm_->GetFactory()->NewFromStdString("test1"));
258 func1->SetModule(vm_->GetJSThread(), recordName1);
259 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
260 for (int i = 0; i < 5; i++) {
261 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func1.GetTaggedType());
262 }
263 JSNApi::DestroyJSVM(vm_);
264
265 // Loader
266 PGOProfilerDecoder loader("ark-profiler2/modules.ap", 2);
267 CString expectRecordName = "test";
268 CString expectRecordName1 = "test1";
269 #if defined(SUPPORT_ENABLE_ASM_INTERP)
270 ASSERT_TRUE(loader.LoadAndVerify(checksum));
271 for (uint32_t idx = 0; idx < 2; idx++) {
272 loader.MatchAndMarkMethod(expectRecordName,
273 methodLiterals[idx]->GetMethodName(pf.get(), methodLiterals[idx]->GetMethodId()),
274 methodLiterals[idx]->GetMethodId());
275 loader.MatchAndMarkMethod(expectRecordName1,
276 methodLiterals[idx]->GetMethodName(pf.get(), methodLiterals[idx]->GetMethodId()),
277 methodLiterals[idx]->GetMethodId());
278 }
279 ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
280 #else
281 ASSERT_TRUE(!loader.LoadAndVerify(checksum));
282 ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
283 #endif
284 ASSERT_TRUE(loader.Match(expectRecordName1, methodLiterals[1]->GetMethodId()));
285 unlink("ark-profiler2/modules.ap");
286 rmdir("ark-profiler2/");
287 }
288
HWTEST_F_L0(PGOProfilerTest,DisEnableSample)289 HWTEST_F_L0(PGOProfilerTest, DisEnableSample)
290 {
291 const char *source = R"(
292 .language ECMAScript
293 .function void foo1(any a0, any a1, any a2) {}
294 )";
295 std::vector<MethodLiteral *> methodLiterals {};
296 std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler3.abc", methodLiterals);
297 EXPECT_EQ(methodLiterals.size(), 1); // number of methods
298 mkdir("ark-profiler3/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
299 RuntimeOption option;
300 option.SetEnableProfile(false);
301 option.SetProfileDir("ark-profiler3/");
302 vm_ = JSNApi::CreateJSVM(option);
303 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
304 constPool->SetJSPandaFile(pf.get());
305 uint32_t checksum = 304293;
306 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
307 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
308
309 JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
310
311 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
312 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
313 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
314 func->SetModule(vm_->GetJSThread(), recordName);
315 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
316 JSNApi::DestroyJSVM(vm_);
317
318 // Loader
319 PGOProfilerDecoder loader("ark-profiler3/modules.ap", 2);
320 // path is empty()
321 ASSERT_TRUE(!loader.LoadAndVerify(checksum));
322 CString expectRecordName = "test";
323 ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
324 rmdir("ark-profiler3/");
325 }
326
HWTEST_F_L0(PGOProfilerTest,PGOProfilerManagerInvalidPath)327 HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerInvalidPath)
328 {
329 RuntimeOption option;
330 option.SetEnableProfile(true);
331 option.SetProfileDir("ark-profiler4");
332 vm_ = JSNApi::CreateJSVM(option);
333 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
334 JSNApi::DestroyJSVM(vm_);
335 }
336
HWTEST_F_L0(PGOProfilerTest,PGOProfilerManagerInitialize)337 HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerInitialize)
338 {
339 RuntimeOption option;
340 option.SetEnableProfile(true);
341 // outDir is empty
342 option.SetProfileDir("");
343 vm_ = JSNApi::CreateJSVM(option);
344 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
345
346 JSNApi::DestroyJSVM(vm_);
347 }
348
HWTEST_F_L0(PGOProfilerTest,PGOProfilerManagerSample)349 HWTEST_F_L0(PGOProfilerTest, PGOProfilerManagerSample)
350 {
351 RuntimeOption option;
352 option.SetEnableProfile(true);
353 char currentPath[PATH_MAX + 2];
354 if (memset_s(currentPath, PATH_MAX, 1, PATH_MAX) != EOK) {
355 ASSERT_TRUE(false);
356 }
357 currentPath[PATH_MAX + 1] = '\0';
358 option.SetProfileDir(currentPath);
359 vm_ = JSNApi::CreateJSVM(option);
360 uint32_t checksum = 304293;
361 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
362 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
363
364 JSHandle<JSArray> array = vm_->GetFactory()->NewJSArray();
365 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, array.GetTaggedType());
366
367 // RecordName is hole
368 MethodLiteral *methodLiteral = new MethodLiteral(EntityId(61));
369 JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiteral);
370 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
371 func->SetModule(vm_->GetJSThread(), JSTaggedValue::Hole());
372 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
373 JSNApi::DestroyJSVM(vm_);
374
375 PGOProfilerDecoder loader("", 2);
376 // path is empty()
377 ASSERT_TRUE(loader.LoadAndVerify(checksum));
378 // path size greater than PATH_MAX
379 char path[PATH_MAX + 1] = {'0'};
380 PGOProfilerDecoder loader1(path, 4);
381 ASSERT_TRUE(!loader1.LoadAndVerify(checksum));
382 }
383
HWTEST_F_L0(PGOProfilerTest,PGOProfilerDoubleVM)384 HWTEST_F_L0(PGOProfilerTest, PGOProfilerDoubleVM)
385 {
386 const char *source = R"(
387 .language ECMAScript
388 .function void foo1(any a0, any a1, any a2) {}
389 .function void foo2(any a0, any a1, any a2) {}
390 )";
391 std::vector<MethodLiteral *> methodLiterals {};
392 std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler5.abc", methodLiterals);
393 EXPECT_EQ(methodLiterals.size(), 2); // number of methods
394 mkdir("ark-profiler5/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
395 RuntimeOption option;
396 option.SetEnableProfile(true);
397 // outDir is empty
398 option.SetProfileDir("ark-profiler5/");
399 vm_ = JSNApi::CreateJSVM(option);
400 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
401 constPool->SetJSPandaFile(pf.get());
402 uint32_t checksum = 304293;
403 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
404 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
405 // worker vm read profile enable from PGOProfilerManager singleton
406 option.SetEnableProfile(false);
407 auto vm2 = JSNApi::CreateJSVM(option);
408 JSHandle<ConstantPool> constPool2 = vm2->GetFactory()->NewConstantPool(4);
409 constPool2->SetJSPandaFile(pf.get());
410 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
411 ASSERT_TRUE(vm2 != nullptr) << "Cannot create Runtime";
412
413 JSHandle<Method> method = vm2->GetFactory()->NewMethod(methodLiterals[0]);
414 method->SetConstantPool(vm2->GetJSThread(), constPool2.GetTaggedValue());
415 JSHandle<JSFunction> func = vm2->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
416 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
417 func->SetModule(vm2->GetJSThread(), recordName);
418 vm2->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
419
420 JSHandle<Method> method1 = vm_->GetFactory()->NewMethod(methodLiterals[0]);
421 JSHandle<Method> method2 = vm_->GetFactory()->NewMethod(methodLiterals[1]);
422 method1->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
423 method2->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
424 JSHandle<JSFunction> func1 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method1);
425 JSHandle<JSFunction> func2 = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method2);
426 JSHandle<JSTaggedValue> recordName1(vm_->GetFactory()->NewFromStdString("test"));
427 func1->SetModule(vm_->GetJSThread(), recordName);
428 func2->SetModule(vm_->GetJSThread(), recordName);
429 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func1.GetTaggedType());
430 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func2.GetTaggedType());
431
432 JSNApi::DestroyJSVM(vm2);
433 JSNApi::DestroyJSVM(vm_);
434
435 PGOProfilerDecoder loader("ark-profiler5/profiler", 2);
436 mkdir("ark-profiler5/profiler", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
437 ASSERT_TRUE(!loader.LoadAndVerify(checksum));
438 CString expectRecordName = "test";
439 ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
440
441 PGOProfilerDecoder loader1("ark-profiler5/modules.ap", 2);
442 #if defined(SUPPORT_ENABLE_ASM_INTERP)
443 ASSERT_TRUE(loader1.LoadAndVerify(checksum));
444 ASSERT_TRUE(!loader1.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
445 #else
446 ASSERT_TRUE(!loader1.LoadAndVerify(checksum));
447 ASSERT_TRUE(loader1.Match(expectRecordName, methodLiterals[1]->GetMethodId()));
448 #endif
449
450 unlink("ark-profiler5/modules.ap");
451 rmdir("ark-profiler5/profiler");
452 rmdir("ark-profiler5/");
453 }
454
HWTEST_F_L0(PGOProfilerTest,PGOProfilerDecoderNoHotMethod)455 HWTEST_F_L0(PGOProfilerTest, PGOProfilerDecoderNoHotMethod)
456 {
457 const char *source = R"(
458 .language ECMAScript
459 .function void foo1(any a0, any a1, any a2) {}
460 )";
461 std::vector<MethodLiteral *> methodLiterals {};
462 std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler8.abc", methodLiterals);
463 EXPECT_EQ(methodLiterals.size(), 1); // number of methods
464 mkdir("ark-profiler8/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
465 RuntimeOption option;
466 option.SetEnableProfile(true);
467 option.SetProfileDir("ark-profiler8/");
468 vm_ = JSNApi::CreateJSVM(option);
469 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
470 constPool->SetJSPandaFile(pf.get());
471 uint32_t checksum = 304293;
472 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
473
474 JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
475
476 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
477 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
478 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
479 func->SetModule(vm_->GetJSThread(), recordName);
480 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
481 JSNApi::DestroyJSVM(vm_);
482
483 PGOProfilerDecoder loader("ark-profiler8/modules.ap", 2);
484 CString expectRecordName = "test";
485 #if defined(SUPPORT_ENABLE_ASM_INTERP)
486 ASSERT_TRUE(loader.LoadAndVerify(checksum));
487 ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
488 #else
489 ASSERT_TRUE(!loader.LoadAndVerify(checksum));
490 ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
491 #endif
492
493 unlink("ark-profiler8/modules.ap");
494 rmdir("ark-profiler8/");
495 }
496
HWTEST_F_L0(PGOProfilerTest,PGOProfilerPostTask)497 HWTEST_F_L0(PGOProfilerTest, PGOProfilerPostTask)
498 {
499 std::stringstream sourceStream;
500 sourceStream << " .language ECMAScript" << std::endl;
501 for (uint32_t funcIdx = 0; funcIdx < 100; funcIdx++) {
502 sourceStream << " .function void foo" << std::to_string(funcIdx) << "(any a0, any a1, any a2) {}" << std::endl;
503 }
504 std::vector<MethodLiteral *> methodLiterals {};
505 std::shared_ptr<JSPandaFile> pf =
506 CreateJSPandaFile(sourceStream.str().c_str(), "ark-profiler9.abc", methodLiterals);
507 EXPECT_EQ(methodLiterals.size(), 100); // number of methods
508 mkdir("ark-profiler9/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
509 RuntimeOption option;
510 option.SetEnableProfile(true);
511 option.SetProfileDir("ark-profiler9/");
512 vm_ = JSNApi::CreateJSVM(option);
513 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
514 constPool->SetJSPandaFile(pf.get());
515 uint32_t checksum = 304293;
516 PGOProfilerManager::GetInstance()->SetApGenMode(ApGenMode::OVERWRITE);
517 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
518
519 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
520 for (int i = 61; i < 91; i++) {
521 JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[i]);
522 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
523 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
524 func->SetModule(vm_->GetJSThread(), recordName);
525 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
526 if (i % 3 == 0) {
527 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
528 }
529 }
530
531 JSNApi::DestroyJSVM(vm_);
532
533 PGOProfilerDecoder loader("ark-profiler9/modules.ap", 2);
534 #if defined(SUPPORT_ENABLE_ASM_INTERP)
535 ASSERT_TRUE(loader.LoadAndVerify(checksum));
536 #else
537 ASSERT_TRUE(!loader.LoadAndVerify(checksum));
538 #endif
539 CString expectRecordName = "test";
540 for (int i = 0; i < 100; i++) {
541 EntityId methodId = methodLiterals[i]->GetMethodId();
542 loader.MatchAndMarkMethod(expectRecordName, methodLiterals[i]->GetMethodName(pf.get(), methodId), methodId);
543 }
544 for (int i = 61; i < 91; i++) {
545 if (i % 3 == 0) {
546 ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[i]->GetMethodId()));
547 } else {
548 #if defined(SUPPORT_ENABLE_ASM_INTERP)
549 ASSERT_TRUE(!loader.Match(expectRecordName, methodLiterals[i]->GetMethodId()));
550 #else
551 ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[i]->GetMethodId()));
552 #endif
553 }
554 }
555
556 unlink("ark-profiler9/modules.ap");
557 rmdir("ark-profiler9/");
558 }
559
HWTEST_F_L0(PGOProfilerTest,BinaryToText)560 HWTEST_F_L0(PGOProfilerTest, BinaryToText)
561 {
562 mkdir("ark-profiler7/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
563
564 std::fstream file("ark-profiler7/modules.ap",
565 std::fstream::binary | std::fstream::out | std::fstream::in | std::fstream::trunc);
566
567 PGOProfilerHeader *header = nullptr;
568 PGOProfilerHeader::Build(&header, PGOProfilerHeader::LastSize());
569 std::unique_ptr<PGOPandaFileInfos> pandaFileInfos = std::make_unique<PGOPandaFileInfos>();
570 std::unique_ptr<PGORecordDetailInfos> recordInfos = std::make_unique<PGORecordDetailInfos>(2);
571
572 RuntimeOption option;
573 vm_ = JSNApi::CreateJSVM(option);
574 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
575 pandaFileInfos->Sample(0x34556738);
576 std::shared_ptr<MethodLiteral> methodLiteral = std::make_shared<MethodLiteral>(EntityId(61));
577 auto *jsMethod =
578 Method::Cast(vm_->GetFactory()->NewMethod(methodLiteral.get(), MemSpaceType::NON_MOVABLE).GetTaggedValue());
579
580 ASSERT_TRUE(recordInfos->AddMethod("test", jsMethod, SampleMode::CALL_MODE, 1));
581 ASSERT_FALSE(recordInfos->AddMethod("test", jsMethod, SampleMode::CALL_MODE, 1));
582 ASSERT_FALSE(recordInfos->AddMethod("test", jsMethod, SampleMode::CALL_MODE, 1));
583
584 pandaFileInfos->ProcessToBinary(file, header->GetPandaInfoSection());
585 recordInfos->ProcessToBinary(nullptr, file, header);
586 header->ProcessToBinary(file);
587 PGOProfilerEncoder::AddChecksum(file);
588 file.close();
589
590 ASSERT_TRUE(PGOProfilerManager::GetInstance()->BinaryToText(
591 "ark-profiler7/modules.ap", "ark-profiler7/modules.text", 2));
592 JSNApi::DestroyJSVM(vm_);
593 unlink("ark-profiler7/modules.ap");
594 unlink("ark-profiler7/modules.text");
595 rmdir("ark-profiler7");
596 }
597
HWTEST_F_L0(PGOProfilerTest,TextToBinary)598 HWTEST_F_L0(PGOProfilerTest, TextToBinary)
599 {
600 mkdir("ark-profiler10/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
601
602 std::ofstream file("ark-profiler10/modules.text");
603 std::string result = "Profiler Version: 0.0.0.1\n";
604 file.write(result.c_str(), result.size());
605 result = "\nPanda file sumcheck list: [ 413775942 ]\n";
606 file.write(result.c_str(), result.size());
607 result = "\nrecordName: [ 1232/3/CALL_MODE/hello, 234/100/HOTNESS_MODE/h#ello1 ]\n";
608 file.write(result.c_str(), result.size());
609 file.close();
610
611 ASSERT_TRUE(PGOProfilerManager::GetInstance()->TextToBinary("ark-profiler10/modules.text", "ark-profiler10/", 2,
612 ApGenMode::MERGE));
613
614 PGOProfilerDecoder loader("ark-profiler10/modules.ap", 2);
615 ASSERT_TRUE(loader.LoadAndVerify(413775942));
616
617 unlink("ark-profiler10/modules.ap");
618 unlink("ark-profiler10/modules.text");
619 rmdir("ark-profiler10");
620 }
621
HWTEST_F_L0(PGOProfilerTest,FailResetProfilerInWorker)622 HWTEST_F_L0(PGOProfilerTest, FailResetProfilerInWorker)
623 {
624 const char *source = R"(
625 .language ECMAScript
626 .function void foo1(any a0, any a1, any a2) {}
627 )";
628 std::vector<MethodLiteral *> methodLiterals {};
629 std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler12.abc", methodLiterals);
630 EXPECT_EQ(methodLiterals.size(), 1); // number of methods
631 mkdir("ark-profiler12/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
632 RuntimeOption option;
633 // Although enableProfle is set in option, but it will not work when isWorker is set.
634 option.SetEnableProfile(true);
635 option.SetIsWorker();
636 option.SetProfileDir("ark-profiler12/");
637 // PgoProfiler is disabled as default.
638 vm_ = JSNApi::CreateJSVM(option);
639 uint32_t checksum = 304293;
640 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
641 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
642
643 JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
644
645 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
646 constPool->SetJSPandaFile(pf.get());
647 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
648 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
649 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
650 func->SetModule(vm_->GetJSThread(), recordName);
651 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
652 JSNApi::DestroyJSVM(vm_);
653
654 // Loader
655 PGOProfilerDecoder loader("ark-profiler12/modules.ap", 2);
656 // path is empty()
657 ASSERT_TRUE(!loader.LoadAndVerify(checksum));
658 CString expectRecordName = "test";
659 ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
660 rmdir("ark-profiler12/");
661 }
662
663 #if defined(SUPPORT_ENABLE_ASM_INTERP)
HWTEST_F_L0(PGOProfilerTest,ProfileCallTest)664 HWTEST_F_L0(PGOProfilerTest, ProfileCallTest)
665 {
666 mkdir("ark-profiler13/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
667 const char *targetRecordName = "call_test";
668 std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler13/", targetRecordName);
669 ASSERT_NE(jsPandaFile, nullptr);
670 uint32_t checksum = jsPandaFile->GetChecksum();
671
672 // Loader
673 PGOProfilerDecoder decoder("ark-profiler13/modules.ap", 1);
674 PGOProfilerDecoder decoder1("ark-profiler13/modules.ap", 10);
675 PGOProfilerDecoder decoder2("ark-profiler13/modules.ap", 11000);
676 ASSERT_TRUE(decoder.LoadAndVerify(checksum));
677 ASSERT_TRUE(decoder1.LoadAndVerify(checksum));
678 ASSERT_TRUE(decoder2.LoadAndVerify(checksum));
679 auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
680 for (auto iter : methodLiterals) {
681 auto methodLiteral = iter.second;
682 auto methodId = methodLiteral->GetMethodId();
683 auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
684 decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
685 decoder1.MatchAndMarkMethod(targetRecordName, methodName, methodId);
686 decoder2.MatchAndMarkMethod(targetRecordName, methodName, methodId);
687 ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
688 if (std::string(methodName) == "Test") {
689 ASSERT_TRUE(!decoder1.Match(targetRecordName, methodId));
690 ASSERT_TRUE(!decoder2.Match(targetRecordName, methodId));
691 } else {
692 ASSERT_TRUE(decoder1.Match(targetRecordName, methodId));
693 ASSERT_TRUE(decoder2.Match(targetRecordName, methodId));
694 }
695 }
696 unlink("ark-profiler13/modules.ap");
697 rmdir("ark-profiler13/");
698 }
699
HWTEST_F_L0(PGOProfilerTest,UseClassTypeTest)700 HWTEST_F_L0(PGOProfilerTest, UseClassTypeTest)
701 {
702 mkdir("ark-profiler14/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
703 const char *targetRecordName = "class_test";
704 std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler14/", targetRecordName);
705 ASSERT_NE(jsPandaFile, nullptr);
706 uint32_t checksum = jsPandaFile->GetChecksum();
707
708 // Loader
709 PGOProfilerDecoder decoder("ark-profiler14/modules.ap", 1);
710 ASSERT_TRUE(decoder.LoadAndVerify(checksum));
711 auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
712 for (auto iter : methodLiterals) {
713 auto methodLiteral = iter.second;
714 auto methodId = methodLiteral->GetMethodId();
715 auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
716 decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
717 ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
718 auto callback = [methodName, methodId](uint32_t offset, PGOType *type) {
719 ASSERT_NE(offset, 0);
720 if (type->IsScalarOpType()) {
721 } else if (type->IsRwOpType()) {
722 auto pgoRWOpType = *reinterpret_cast<PGORWOpType *>(type);
723 if (std::string(methodName) == "Foot" || std::string(methodName) == "Arm") {
724 ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
725 ASSERT_EQ(pgoRWOpType.GetObjectInfo(0).GetClassType(), ClassType(methodId.GetOffset()));
726 } else if (std::string(methodName) == "foo" || std::string(methodName) == "Body") {
727 ASSERT_TRUE(pgoRWOpType.GetCount() == 3);
728 }
729 } else {
730 ASSERT_TRUE(false);
731 }
732 };
733 decoder.GetTypeInfo(jsPandaFile.get(), targetRecordName, methodLiteral, callback);
734 }
735 unlink("ark-profiler14/modules.ap");
736 rmdir("ark-profiler14/");
737 }
738
HWTEST_F_L0(PGOProfilerTest,DefineClassTypeTest)739 HWTEST_F_L0(PGOProfilerTest, DefineClassTypeTest)
740 {
741 mkdir("ark-profiler15/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
742 const char *targetRecordName = "class_test";
743 std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler15/", targetRecordName);
744 ASSERT_NE(jsPandaFile, nullptr);
745 uint32_t checksum = jsPandaFile->GetChecksum();
746
747 // Loader
748 PGOProfilerDecoder decoder("ark-profiler15/modules.ap", 1);
749 ASSERT_TRUE(decoder.LoadAndVerify(checksum));
750 auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
751 for (auto iter : methodLiterals) {
752 auto methodLiteral = iter.second;
753 auto methodId = methodLiteral->GetMethodId();
754 auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
755 decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
756 ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
757 auto callback = [methodName, &decoder, jsPandaFile](uint32_t offset, PGOType *type) {
758 ASSERT_NE(offset, 0);
759 if (type->IsScalarOpType()) {
760 auto sampleType = *reinterpret_cast<PGOSampleType *>(type);
761 if (sampleType.IsClassType()) {
762 ASSERT_EQ(std::string(methodName), "func_main_0");
763 PGOHClassLayoutDesc *desc;
764 if (!decoder.GetHClassLayoutDesc(sampleType, &desc)) {
765 return;
766 }
767 ASSERT_EQ(desc->GetCtorLayoutDesc().size(), 3);
768 ASSERT_EQ(desc->GetPtLayoutDesc().size(), 1);
769 auto classId = EntityId(sampleType.GetClassType().GetClassType());
770 auto className = MethodLiteral::GetMethodName(jsPandaFile.get(), classId);
771 if (std::string(className) == "Arm") {
772 auto superClassId = EntityId(desc->GetSuperClassType().GetClassType());
773 auto superClassName = MethodLiteral::GetMethodName(jsPandaFile.get(), superClassId);
774 ASSERT_EQ(std::string(superClassName), "Body");
775 ASSERT_EQ(desc->GetLayoutDesc().size(), 3);
776 ASSERT_EQ(desc->GetLayoutDesc()[0].first, "x");
777 ASSERT_EQ(desc->GetLayoutDesc()[1].first, "y");
778 ASSERT_EQ(desc->GetLayoutDesc()[2].first, "t");
779 } else if (std::string(className) == "Foot") {
780 auto superClassId = EntityId(desc->GetSuperClassType().GetClassType());
781 auto superClassName = MethodLiteral::GetMethodName(jsPandaFile.get(), superClassId);
782 ASSERT_EQ(std::string(superClassName), "Body");
783 ASSERT_EQ(desc->GetLayoutDesc().size(), 4);
784 ASSERT_EQ(desc->GetLayoutDesc()[0].first, "x");
785 ASSERT_EQ(desc->GetLayoutDesc()[1].first, "y");
786 ASSERT_EQ(desc->GetLayoutDesc()[2].first, "u");
787 ASSERT_EQ(desc->GetLayoutDesc()[3].first, "v");
788 } else {
789 ASSERT_EQ(desc->GetSuperClassType().GetClassType(), 0);
790 ASSERT_EQ(desc->GetLayoutDesc().size(), 2);
791 ASSERT_EQ(desc->GetLayoutDesc()[0].first, "x");
792 ASSERT_EQ(desc->GetLayoutDesc()[1].first, "y");
793 }
794 }
795 }
796 };
797 decoder.GetTypeInfo(jsPandaFile.get(), targetRecordName, methodLiteral, callback);
798 }
799 unlink("ark-profiler15/modules.ap");
800 rmdir("ark-profiler15/");
801 }
802
HWTEST_F_L0(PGOProfilerTest,OpTypeTest)803 HWTEST_F_L0(PGOProfilerTest, OpTypeTest)
804 {
805 mkdir("ark-profiler16/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
806 const char *targetRecordName = "op_type_test";
807 std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler16/", targetRecordName);
808 ASSERT_NE(jsPandaFile, nullptr);
809 uint32_t checksum = jsPandaFile->GetChecksum();
810
811 // Loader
812 PGOProfilerDecoder decoder("ark-profiler16/modules.ap", 1);
813 ASSERT_TRUE(decoder.LoadAndVerify(checksum));
814 std::string types[17] = { "1", "1", "1", "5", "4", "4", "4", "4", "4", "4", "5", "4", "4", "1", "4", "5", "1" };
815 int index = 0;
816 auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
817 for (auto iter : methodLiterals) {
818 auto methodLiteral = iter.second;
819 auto methodId = methodLiteral->GetMethodId();
820 auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
821 decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
822 ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
823 auto callback = [methodName, types, &index](uint32_t offset, PGOType *type) {
824 ASSERT_NE(offset, 0);
825 if (type->IsScalarOpType()) {
826 auto sampleType = *reinterpret_cast<PGOSampleType *>(type);
827 if (sampleType.IsClassType()) {
828 return;
829 }
830 if (std::string(methodName) == "advance") {
831 ASSERT_EQ(sampleType.GetTypeString(), types[index++]);
832 }
833 }
834 };
835 decoder.GetTypeInfo(jsPandaFile.get(), targetRecordName, methodLiteral, callback);
836 }
837 unlink("ark-profiler16/modules.ap");
838 rmdir("ark-profiler16/");
839 }
840
HWTEST_F_L0(PGOProfilerTest,ArrayProfileTest)841 HWTEST_F_L0(PGOProfilerTest, ArrayProfileTest)
842 {
843 mkdir("ark-profiler18/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
844 const char *targetRecordName = "array_test";
845 std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler18/", targetRecordName);
846 ASSERT_NE(jsPandaFile, nullptr);
847 uint32_t checksum = jsPandaFile->GetChecksum();
848
849 // Loader
850 PGOProfilerDecoder decoder("ark-profiler18/modules.ap", 1);
851 ASSERT_TRUE(decoder.LoadAndVerify(checksum));
852 auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
853 for (auto iter : methodLiterals) {
854 auto methodLiteral = iter.second;
855 auto methodId = methodLiteral->GetMethodId();
856 auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
857 decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
858 ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
859 auto callback = [methodName, &decoder, jsPandaFile](uint32_t offset, PGOType *type) {
860 if (type->IsScalarOpType()) {
861 auto sampleType = *reinterpret_cast<PGOSampleType *>(type);
862 if (sampleType.IsClassType()) {
863 ASSERT_EQ(std::string(methodName), "func_main_0");
864 PGOHClassLayoutDesc *desc;
865 if (!decoder.GetHClassLayoutDesc(sampleType, &desc)) {
866 return;
867 }
868 ASSERT_EQ(desc->GetCtorLayoutDesc().size(), 0);
869 ASSERT_EQ(desc->GetPtLayoutDesc().size(), 0);
870 ASSERT_EQ(desc->GetLayoutDesc().size(), 1);
871 }
872 } else if (type->IsRwOpType()) {
873 auto pgoRWOpType = *reinterpret_cast<PGORWOpType *>(type);
874 if (std::string(methodName) == "foo") {
875 ASSERT_TRUE(pgoRWOpType.GetCount() == 3);
876 auto classType = PGOSampleType(pgoRWOpType.GetObjectInfo(0).GetClassType());
877 PGOHClassLayoutDesc *desc;
878 ASSERT_TRUE(decoder.GetHClassLayoutDesc(classType, &desc));
879 ASSERT_EQ(desc->GetElementsKind(), ElementsKind::NUMBER);
880
881 classType = PGOSampleType(pgoRWOpType.GetObjectInfo(1).GetClassType());
882 ASSERT_TRUE(decoder.GetHClassLayoutDesc(classType, &desc));
883 ASSERT_EQ(desc->GetElementsKind(), ElementsKind::HOLE_NUMBER);
884
885 classType = PGOSampleType(pgoRWOpType.GetObjectInfo(2).GetClassType());
886 ASSERT_TRUE(decoder.GetHClassLayoutDesc(classType, &desc));
887 ASSERT_EQ(desc->GetElementsKind(), ElementsKind::HOLE_TAGGED);
888 } else if (std::string(methodName) == "foo1") {
889 ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
890 auto classType = PGOSampleType(pgoRWOpType.GetObjectInfo(0).GetClassType());
891 PGOHClassLayoutDesc *desc;
892 ASSERT_TRUE(decoder.GetHClassLayoutDesc(classType, &desc));
893 ASSERT_EQ(desc->GetElementsKind(), ElementsKind::TAGGED);
894 }
895 }
896 };
897 decoder.GetTypeInfo(jsPandaFile.get(), targetRecordName, methodLiteral, callback);
898 }
899 unlink("ark-profiler18/modules.ap");
900 rmdir("ark-profiler18/");
901 }
902 #endif
903
HWTEST_F_L0(PGOProfilerTest,FileConsistencyCheck)904 HWTEST_F_L0(PGOProfilerTest, FileConsistencyCheck)
905 {
906 const char *source = R"(
907 .language ECMAScript
908 .function void foo1(any a0, any a1, any a2) {}
909 )";
910 std::vector<MethodLiteral *> methodLiterals {};
911 std::shared_ptr<JSPandaFile> pf = CreateJSPandaFile(source, "ark-profiler.abc", methodLiterals);
912 EXPECT_EQ(methodLiterals.size(), 1); // number of methods
913
914 mkdir("ark-profiler17/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
915 RuntimeOption option;
916 option.SetEnableProfile(true);
917 option.SetProfileDir("ark-profiler17/");
918 vm_ = JSNApi::CreateJSVM(option);
919 JSHandle<ConstantPool> constPool = vm_->GetFactory()->NewConstantPool(4);
920 constPool->SetJSPandaFile(pf.get());
921 uint32_t checksum = 304293;
922 PGOProfilerManager::GetInstance()->SamplePandaFileInfo(checksum);
923 ASSERT_TRUE(vm_ != nullptr) << "Cannot create Runtime";
924
925 JSHandle<Method> method = vm_->GetFactory()->NewMethod(methodLiterals[0]);
926 method->SetConstantPool(vm_->GetJSThread(), constPool.GetTaggedValue());
927 JSHandle<JSFunction> func = vm_->GetFactory()->NewJSFunction(vm_->GetGlobalEnv(), method);
928 JSHandle<JSTaggedValue> recordName(vm_->GetFactory()->NewFromStdString("test"));
929 func->SetModule(vm_->GetJSThread(), recordName);
930 vm_->GetPGOProfiler()->SetSaveTimestamp(std::chrono::system_clock::now());
931 vm_->GetPGOProfiler()->ProfileCall(JSTaggedValue::VALUE_UNDEFINED, func.GetTaggedType());
932 JSNApi::DestroyJSVM(vm_);
933
934 // write to corrupt the ap file's consistency
935 std::ofstream fWriter("ark-profiler17/modules.ap", std::fstream::app);
936
937 fWriter.write(reinterpret_cast<char *>(&checksum), sizeof(checksum));
938 fWriter.seekp(100);
939 fWriter.write(reinterpret_cast<char *>(&checksum), sizeof(checksum));
940 fWriter.close();
941
942 // Loader
943 PGOProfilerDecoder loader("ark-profiler17/modules.ap", 2);
944 CString expectRecordName = "test";
945 #if defined(SUPPORT_ENABLE_ASM_INTERP)
946 ASSERT_FALSE(loader.LoadAndVerify(checksum));
947 #else
948 ASSERT_TRUE(!loader.LoadAndVerify(checksum));
949 ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
950 #endif
951 unlink("ark-profiler17/modules.ap");
952 rmdir("ark-profiler17/");
953 }
954
955 #if defined(SUPPORT_ENABLE_ASM_INTERP)
HWTEST_F_L0(PGOProfilerTest,MergeApSelfTwice)956 HWTEST_F_L0(PGOProfilerTest, MergeApSelfTwice)
957 {
958 mkdir("ark-profiler18/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
959 const char *targetRecordName = "op_type_test";
960 std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler18/", targetRecordName);
961 ASSERT_NE(jsPandaFile, nullptr);
962
963 // Loader
964 PGOProfilerDecoder decoder("ark-profiler18/modules_merge.ap", 1);
965 PGOProfilerDecoder decoderSingle("ark-profiler18/modules.ap", 1);
966 ASSERT_TRUE(PGOProfilerManager::MergeApFiles("ark-profiler18/modules.ap:ark-profiler18/modules.ap",
967 "ark-profiler18/modules_merge.ap", 1, ApGenMode::OVERWRITE));
968 ASSERT_TRUE(decoder.LoadFull());
969 ASSERT_TRUE(decoderSingle.LoadFull());
970
971 auto doubleCount =
972 decoder.GetRecordDetailInfos().GetRecordInfos().begin()->second->GetMethodInfos().begin()->second->GetCount();
973 auto singleCount = decoderSingle.GetRecordDetailInfos()
974 .GetRecordInfos()
975 .begin()
976 ->second->GetMethodInfos()
977 .begin()
978 ->second->GetCount();
979 ASSERT_EQ(doubleCount, singleCount + singleCount);
980
981 unlink("ark-profiler18/modules.ap");
982 unlink("ark-profiler18/modules_merge.ap");
983 rmdir("ark-profiler18/");
984 }
985 #endif
986 } // namespace panda::test
987