1 /**
2 * Copyright (c) 2021-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 <fstream>
17 #include "unit_test.h"
18 #include "code_info/code_info_builder.h"
19 #include "codegen.h"
20 #include "panda_runner.h"
21 #include "events/events.h"
22
23 using panda::panda_file::File;
24
25 namespace panda::test {
26 class OsrTest : public testing::Test {
27 public:
OsrTest()28 OsrTest()
29 : default_compiler_non_optimizing_(compiler::options.IsCompilerNonOptimizing()),
30 default_compiler_inlining_(compiler::options.IsCompilerInlining()),
31 default_compiler_inlining_blacklist_(compiler::options.GetCompilerInliningBlacklist()),
32 default_compiler_regex_(compiler::options.GetCompilerRegex())
33 {
34 }
35
~OsrTest()36 ~OsrTest()
37 {
38 compiler::options.SetCompilerNonOptimizing(default_compiler_non_optimizing_);
39 compiler::options.SetCompilerInlining(default_compiler_inlining_);
40 compiler::options.SetCompilerInliningBlacklist(default_compiler_inlining_blacklist_);
41 compiler::options.SetCompilerRegex(default_compiler_regex_);
42 }
SetUp()43 void SetUp()
44 {
45 #ifndef PANDA_EVENTS_ENABLED
46 GTEST_SKIP();
47 #endif
48 if constexpr (!ArchTraits<RUNTIME_ARCH>::SUPPORT_OSR) {
49 GTEST_SKIP();
50 }
51 }
52
53 protected:
54 static constexpr size_t HOTNESS_THRESHOLD = 4;
55
56 private:
57 bool default_compiler_non_optimizing_;
58 bool default_compiler_inlining_;
59 arg_list_t default_compiler_inlining_blacklist_;
60 std::string default_compiler_regex_;
61 };
62
63 struct ScopeEvents {
ScopeEventspanda::test::ScopeEvents64 ScopeEvents()
65 {
66 Events::Create<Events::MEMORY>();
67 }
~ScopeEventspanda::test::ScopeEvents68 ~ScopeEvents()
69 {
70 Events::Destroy();
71 }
72 };
73
74 static constexpr auto OSR_IN_TOP_FRAME_SOURCE = R"(
75 .function i32 main() {
76 movi v0, 0
77 movi v1, 30
78 movi v2, 0
79 loop:
80 lda v0
81 jeq v1, exit
82 add2 v2
83 sta v2
84 inci v0, 1
85 jmp loop
86 exit:
87 lda v2
88 return
89 }
90 )";
91
TEST_F(OsrTest,OsrInTopFrameNonOptimizing)92 TEST_F(OsrTest, OsrInTopFrameNonOptimizing)
93 {
94 PandaRunner runner;
95 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
96 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
97 runner.GetCompilerOptions().SetCompilerNonOptimizing(true);
98
99 ScopeEvents scope_events;
100
101 runner.Run(OSR_IN_TOP_FRAME_SOURCE, 435);
102 auto events = Events::CastTo<Events::MEMORY>();
103 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
104 ASSERT_EQ(osr_events.size(), 1);
105 }
106
TEST_F(OsrTest,OsrInTopFrameOptimizing)107 TEST_F(OsrTest, OsrInTopFrameOptimizing)
108 {
109 PandaRunner runner;
110 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
111 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
112 runner.GetCompilerOptions().SetCompilerNonOptimizing(false);
113
114 ScopeEvents scope_events;
115
116 runner.Run(OSR_IN_TOP_FRAME_SOURCE, 435);
117 auto events = Events::CastTo<Events::MEMORY>();
118 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
119 ASSERT_EQ(osr_events.size(), 1);
120 }
121
122 static constexpr auto OSR_AFTER_IFRAME_SOURCE = R"(
123 .function i32 main() {
124 call f1
125 return
126 }
127
128 .function i32 f1() {
129 movi v0, 0
130 movi v1, 30
131 movi v2, 0
132 loop:
133 lda v0
134 jeq v1, exit
135 add2 v2
136 sta v2
137 inci v0, 1
138 jmp loop
139 exit:
140 lda v2
141 return
142 }
143 )";
144
TEST_F(OsrTest,OsrAfterIFrameNonOptimizing)145 TEST_F(OsrTest, OsrAfterIFrameNonOptimizing)
146 {
147 PandaRunner runner;
148 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
149 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
150 runner.GetCompilerOptions().SetCompilerNonOptimizing(true);
151
152 ScopeEvents scope_events;
153 runner.Run(OSR_AFTER_IFRAME_SOURCE, 435);
154 auto events = Events::CastTo<Events::MEMORY>();
155 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
156 ASSERT_EQ(osr_events.size(), 1);
157 }
158
TEST_F(OsrTest,OsrAfterIFrameOptimizing)159 TEST_F(OsrTest, OsrAfterIFrameOptimizing)
160 {
161 PandaRunner runner;
162 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
163 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
164 runner.GetCompilerOptions().SetCompilerNonOptimizing(false);
165
166 ScopeEvents scope_events;
167 runner.Run(OSR_AFTER_IFRAME_SOURCE, 435);
168 auto events = Events::CastTo<Events::MEMORY>();
169 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
170 ASSERT_EQ(osr_events.size(), 1);
171 }
172
173 static constexpr auto OSR_AFTER_IFRAME_RESTORE_ACC_AFTER_VOID = R"(
174 .function i32 main() {
175 call f1
176 return
177 }
178
179 .function void f1() {
180 movi v0, 0
181 movi v1, 30
182 movi v2, 0
183 loop:
184 lda v0
185 jeq v1, exit
186 add2 v2
187 sta v2
188 inci v0, 1
189 jmp loop
190 exit:
191 lda v2
192 return.void
193 }
194 )";
195
TEST_F(OsrTest,OsrAfterIFrameRestoreAccAfterVoid)196 TEST_F(OsrTest, OsrAfterIFrameRestoreAccAfterVoid)
197 {
198 PandaRunner runner;
199 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
200 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
201 runner.GetCompilerOptions().SetCompilerNonOptimizing(true);
202
203 ScopeEvents scope_events;
204 runner.Run(OSR_AFTER_IFRAME_RESTORE_ACC_AFTER_VOID, static_cast<ssize_t>0);
205 auto events = Events::CastTo<Events::MEMORY>();
206 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
207 ASSERT_EQ(osr_events.size(), 1);
208 }
209
210 static constexpr auto OSR_AFTER_CFRAME_SOURCE = R"(
211 .function i32 main() {
212 movi v0, 0
213 movi v1, 11
214 loop:
215 lda v1
216 jeq v0, exit
217 inci v0, 1
218 movi v2, 0
219 call f1, v2
220 jmp loop
221 exit:
222 movi v2, 1
223 call f1, v2
224 return
225 }
226
227 .function i32 f1(i32 a0) {
228 ldai 0
229 jeq a0, exit
230 call f2
231 exit:
232 return
233 }
234
235 .function i32 f2() {
236 movi v0, 0
237 movi v1, 30
238 movi v2, 0
239 loop:
240 lda v0
241 jeq v1, exit
242 add2 v2
243 sta v2
244 inci v0, 1
245 jmp loop
246 exit:
247 lda v2
248 return
249 }
250 )";
251
TEST_F(OsrTest,OsrAfterCFrameNonOptimizing)252 TEST_F(OsrTest, OsrAfterCFrameNonOptimizing)
253 {
254 PandaRunner runner;
255 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
256 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
257 runner.GetCompilerOptions().SetCompilerNonOptimizing(true);
258
259 ScopeEvents scope_events;
260 runner.Run(OSR_AFTER_CFRAME_SOURCE, 435);
261 auto events = Events::CastTo<Events::MEMORY>();
262 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
263 ASSERT_EQ(osr_events.size(), 1);
264 ASSERT_EQ(osr_events[0]->kind, events::OsrEntryKind::AFTER_CFRAME);
265 ASSERT_EQ(osr_events[0]->result, events::OsrEntryResult::SUCCESS);
266 }
267
TEST_F(OsrTest,OsrAfterCFrameOptimizing)268 TEST_F(OsrTest, OsrAfterCFrameOptimizing)
269 {
270 PandaRunner runner;
271 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
272 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
273 runner.GetCompilerOptions().SetCompilerNonOptimizing(false);
274 runner.GetCompilerOptions().SetCompilerInlining(false);
275
276 ScopeEvents scope_events;
277 runner.Run(OSR_AFTER_CFRAME_SOURCE, 435);
278 auto events = Events::CastTo<Events::MEMORY>();
279 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
280 ASSERT_EQ(osr_events.size(), 1);
281 ASSERT_EQ(osr_events[0]->kind, events::OsrEntryKind::AFTER_CFRAME);
282 ASSERT_EQ(osr_events[0]->result, events::OsrEntryResult::SUCCESS);
283 }
284
TEST_F(OsrTest,OsrAfterCFrameOptimizingWithInlining)285 TEST_F(OsrTest, OsrAfterCFrameOptimizingWithInlining)
286 {
287 PandaRunner runner;
288 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
289 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
290 runner.GetCompilerOptions().SetCompilerNonOptimizing(false);
291 runner.GetCompilerOptions().SetCompilerInlining(true);
292 runner.GetCompilerOptions().SetCompilerInliningBlacklist({"_GLOBAL::f2"});
293
294 ScopeEvents scope_events;
295 runner.Run(OSR_AFTER_CFRAME_SOURCE, 435);
296 auto events = Events::CastTo<Events::MEMORY>();
297 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
298 auto found = events->Find<events::EventsMemory::InlineEvent>(
299 [](const auto &event) { return event.caller == "_GLOBAL::main" && event.callee == "_GLOBAL::f1"; });
300 ASSERT_TRUE(found);
301 ASSERT_EQ(osr_events.size(), 1);
302 ASSERT_EQ(osr_events[0]->kind, events::OsrEntryKind::AFTER_CFRAME);
303 ASSERT_EQ(osr_events[0]->result, events::OsrEntryResult::SUCCESS);
304 }
305
TEST_F(OsrTest,MainOsrCatchThrow)306 TEST_F(OsrTest, MainOsrCatchThrow)
307 {
308 static constexpr auto source = R"(
309 .record panda.ArrayIndexOutOfBoundsException <external>
310
311 .function i32 main() {
312 movi v0, 0
313 movi v1, 15
314 newarr v1, v1, i32[]
315 movi v2, 20
316 loop:
317 try_begin:
318 lda v2
319 jeq v0, exit
320 inci v0, 1
321 lda v0
322 starr v1, v0
323 jmp loop
324 try_end:
325 exit:
326 ldai 1
327 return
328
329 catch_block1_begin:
330 ldai 123
331 return
332
333 .catch panda.ArrayIndexOutOfBoundsException, try_begin, try_end, catch_block1_begin
334 }
335 )";
336
337 PandaRunner runner;
338 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
339 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
340 runner.GetCompilerOptions().SetCompilerNonOptimizing(true);
341
342 ScopeEvents scope_events;
343 runner.Run(source, 123);
344 auto events = Events::CastTo<Events::MEMORY>();
345 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
346 ASSERT_EQ(osr_events.size(), 1);
347 ASSERT_EQ(osr_events[0]->kind, events::OsrEntryKind::TOP_FRAME);
348 ASSERT_EQ(osr_events[0]->result, events::OsrEntryResult::SUCCESS);
349 auto deopt_events = events->Select<events::EventsMemory::DeoptimizationEvent>();
350 ASSERT_EQ(deopt_events.size(), 1);
351 ASSERT_EQ(deopt_events[0]->after, events::DeoptimizationAfter::TOP);
352 }
353
354 static constexpr auto MAIN_OSR_CATCH_F1_THROW_SOURCE = R"(
355 .record panda.ArrayIndexOutOfBoundsException <external>
356
357 .function i32 main() {
358 movi v0, 0
359 movi v1, 15
360 newarr v1, v1, i32[]
361 movi v2, 20
362 loop:
363 try_begin:
364 lda v2
365 jeq v0, exit
366 inci v0, 1
367 call f1, v1, v0
368 jmp loop
369 try_end:
370 exit:
371 ldai 1
372 return
373
374 catch_block1_begin:
375 ldai 123
376 return
377
378 .catch panda.ArrayIndexOutOfBoundsException, try_begin, try_end, catch_block1_begin
379 }
380
381 .function void f1(i32[] a0, i32 a1) {
382 lda a1
383 starr a0, a1
384 return.void
385 }
386 )";
387
TEST_F(OsrTest,MainOsrCatchF1Throw)388 TEST_F(OsrTest, MainOsrCatchF1Throw)
389 {
390 PandaRunner runner;
391 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
392 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
393 runner.GetCompilerOptions().SetCompilerNonOptimizing(false);
394 runner.GetCompilerOptions().SetCompilerInlining(false);
395 runner.GetCompilerOptions().SetCompilerRegex("(?!_GLOBAL::f1).*");
396
397 ScopeEvents scope_events;
398 runner.Run(MAIN_OSR_CATCH_F1_THROW_SOURCE, 123);
399 auto events = Events::CastTo<Events::MEMORY>();
400 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
401 ASSERT_EQ(osr_events.size(), 1);
402 ASSERT_EQ(osr_events[0]->kind, events::OsrEntryKind::TOP_FRAME);
403 ASSERT_EQ(osr_events[0]->result, events::OsrEntryResult::SUCCESS);
404 auto deopt_events = events->Select<events::EventsMemory::DeoptimizationEvent>();
405 ASSERT_EQ(deopt_events.size(), 1);
406 ASSERT_EQ(deopt_events[0]->after, events::DeoptimizationAfter::TOP);
407 }
408
TEST_F(OsrTest,MainOsrCatchF1ThrowCompiled)409 TEST_F(OsrTest, MainOsrCatchF1ThrowCompiled)
410 {
411 PandaRunner runner;
412 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
413 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
414 runner.GetCompilerOptions().SetCompilerNonOptimizing(false);
415 runner.GetCompilerOptions().SetCompilerInlining(false);
416
417 ScopeEvents scope_events;
418 runner.Run(MAIN_OSR_CATCH_F1_THROW_SOURCE, 123);
419 auto events = Events::CastTo<Events::MEMORY>();
420 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
421 ASSERT_EQ(osr_events.size(), 1);
422 ASSERT_EQ(osr_events[0]->kind, events::OsrEntryKind::TOP_FRAME);
423 ASSERT_EQ(osr_events[0]->result, events::OsrEntryResult::SUCCESS);
424 auto exception_events = events->Select<events::EventsMemory::ExceptionEvent>();
425 ASSERT_EQ(exception_events.size(), 1);
426 ASSERT_EQ(exception_events[0]->type, events::ExceptionType::BOUND_CHECK);
427 }
428
429 static constexpr auto MAIN_CATCH_F1_OSR_THROW_SOURCE = R"(
430 .record panda.ArrayIndexOutOfBoundsException <external>
431
432 .function i32 main() {
433 movi v1, 15
434 newarr v1, v1, i32[]
435 try_begin:
436 call f1, v1
437 try_end:
438 ldai 1
439 return
440
441 catch_block1_begin:
442 ldai 123
443 return
444
445 .catch panda.ArrayIndexOutOfBoundsException, try_begin, try_end, catch_block1_begin
446 }
447
448 .function void f1(i32[] a0) {
449 movi v0, 0
450 movi v2, 20
451 loop:
452 lda v2
453 jeq v0, exit
454 inci v0, 1
455 starr a0, v0
456 jmp loop
457 exit:
458 return.void
459 }
460 )";
461
TEST_F(OsrTest,MainCatchF1OsrThrow)462 TEST_F(OsrTest, MainCatchF1OsrThrow)
463 {
464 PandaRunner runner;
465 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
466 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
467 runner.GetCompilerOptions().SetCompilerNonOptimizing(false);
468 runner.GetCompilerOptions().SetCompilerInlining(false);
469
470 ScopeEvents scope_events;
471 runner.Run(MAIN_CATCH_F1_OSR_THROW_SOURCE, 123);
472 auto events = Events::CastTo<Events::MEMORY>();
473 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
474 ASSERT_EQ(osr_events.size(), 1);
475 ASSERT_EQ(osr_events[0]->kind, events::OsrEntryKind::AFTER_IFRAME);
476 ASSERT_EQ(osr_events[0]->result, events::OsrEntryResult::SUCCESS);
477 auto exception_events = events->Select<events::EventsMemory::ExceptionEvent>();
478 ASSERT_EQ(exception_events.size(), 1);
479 ASSERT_EQ(exception_events[0]->type, events::ExceptionType::BOUND_CHECK);
480 }
481
482 static constexpr auto MAIN_CATCH_F1_OSR_F2_THROW_SOURCE = R"(
483 .record panda.ArrayIndexOutOfBoundsException <external>
484
485 .function i32 main() {
486 movi v1, 15
487 newarr v1, v1, i32[]
488 try_begin:
489 call f1, v1
490 try_end:
491 ldai 1
492 return
493
494 catch_block1_begin:
495 ldai 123
496 return
497
498 .catch panda.ArrayIndexOutOfBoundsException, try_begin, try_end, catch_block1_begin
499 }
500
501 .function void f1(i32[] a0) {
502 movi v0, 0
503 movi v2, 20
504 loop:
505 lda v2
506 jeq v0, exit
507 inci v0, 1
508 call f2, a0, v0
509 jmp loop
510 exit:
511 return.void
512 }
513
514 .function void f2(i32[] a0, i32 a1) {
515 lda a1
516 starr a0, a1
517 return.void
518 }
519 )";
520
TEST_F(OsrTest,MainCatchF1OsrF2Throw)521 TEST_F(OsrTest, MainCatchF1OsrF2Throw)
522 {
523 PandaRunner runner;
524 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
525 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
526 runner.GetCompilerOptions().SetCompilerNonOptimizing(false);
527 runner.GetCompilerOptions().SetCompilerInlining(false);
528 runner.GetCompilerOptions().SetCompilerRegex("(?!_GLOBAL::f2).*");
529
530 ScopeEvents scope_events;
531 runner.Run(MAIN_CATCH_F1_OSR_F2_THROW_SOURCE, 123);
532 auto events = Events::CastTo<Events::MEMORY>();
533 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
534 ASSERT_EQ(osr_events.size(), 1);
535 ASSERT_EQ(osr_events[0]->kind, events::OsrEntryKind::AFTER_IFRAME);
536 ASSERT_EQ(osr_events[0]->result, events::OsrEntryResult::SUCCESS);
537 auto deopt_events = events->Select<events::EventsMemory::DeoptimizationEvent>();
538 // Since f1 hasn't catch handler, it shouldn't be deoptimized
539 ASSERT_EQ(deopt_events.size(), 0);
540 auto exception_events = events->Select<events::EventsMemory::ExceptionEvent>();
541 ASSERT_EQ(exception_events.size(), 0);
542 }
543
TEST_F(OsrTest,MainCatchF1OsrF2ThrowCompiled)544 TEST_F(OsrTest, MainCatchF1OsrF2ThrowCompiled)
545 {
546 PandaRunner runner;
547 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
548 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
549 runner.GetCompilerOptions().SetCompilerNonOptimizing(false);
550 runner.GetCompilerOptions().SetCompilerInlining(false);
551
552 ScopeEvents scope_events;
553 runner.Run(MAIN_CATCH_F1_OSR_F2_THROW_SOURCE, 123);
554 auto events = Events::CastTo<Events::MEMORY>();
555 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
556 ASSERT_EQ(osr_events.size(), 1);
557 ASSERT_EQ(osr_events[0]->kind, events::OsrEntryKind::AFTER_IFRAME);
558 ASSERT_EQ(osr_events[0]->result, events::OsrEntryResult::SUCCESS);
559 auto exception_events = events->Select<events::EventsMemory::ExceptionEvent>();
560 ASSERT_EQ(exception_events.size(), 1);
561 ASSERT_EQ(exception_events[0]->type, events::ExceptionType::BOUND_CHECK);
562 }
563
564 static constexpr auto MAIN_F1_OSR_CATCH_F2_THROW_SOURCE = R"(
565 .record panda.ArrayIndexOutOfBoundsException <external>
566
567 .function i32 main() {
568 movi v1, 15
569 newarr v1, v1, i32[]
570 call f1, v1
571 return
572 }
573
574 .function i32 f1(i32[] a0) {
575 movi v0, 0
576 movi v2, 20
577 loop:
578 try_begin:
579 lda v2
580 jeq v0, exit
581 inci v0, 1
582 call f2, a0, v0
583 jmp loop
584 try_end:
585
586 exit:
587 ldai 1
588 return
589
590 catch_block1_begin:
591 ldai 123
592 return
593
594 .catch panda.ArrayIndexOutOfBoundsException, try_begin, try_end, catch_block1_begin
595 }
596
597 .function void f2(i32[] a0, i32 a1) {
598 lda a1
599 starr a0, a1
600 return.void
601 }
602 )";
603
TEST_F(OsrTest,MainF1OsrCatchF2Throw)604 TEST_F(OsrTest, MainF1OsrCatchF2Throw)
605 {
606 PandaRunner runner;
607 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
608 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
609 runner.GetCompilerOptions().SetCompilerNonOptimizing(false);
610 runner.GetCompilerOptions().SetCompilerInlining(false);
611 runner.GetCompilerOptions().SetCompilerRegex("(?!_GLOBAL::f2).*");
612
613 ScopeEvents scope_events;
614 runner.Run(MAIN_F1_OSR_CATCH_F2_THROW_SOURCE, 123);
615 auto events = Events::CastTo<Events::MEMORY>();
616 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
617 ASSERT_EQ(osr_events.size(), 1);
618 ASSERT_EQ(osr_events[0]->method_name, "_GLOBAL::f1");
619 ASSERT_EQ(osr_events[0]->kind, events::OsrEntryKind::AFTER_IFRAME);
620 ASSERT_EQ(osr_events[0]->result, events::OsrEntryResult::SUCCESS);
621 auto deopt_events = events->Select<events::EventsMemory::DeoptimizationEvent>();
622 ASSERT_EQ(deopt_events.size(), 1);
623 ASSERT_EQ(deopt_events[0]->method_name, "_GLOBAL::f1");
624 ASSERT_EQ(deopt_events[0]->after, events::DeoptimizationAfter::IFRAME);
625 }
626
TEST_F(OsrTest,MainF1OsrCatchF2ThrowCompiled)627 TEST_F(OsrTest, MainF1OsrCatchF2ThrowCompiled)
628 {
629 PandaRunner runner;
630 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(HOTNESS_THRESHOLD);
631 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
632 runner.GetCompilerOptions().SetCompilerNonOptimizing(false);
633 runner.GetCompilerOptions().SetCompilerInlining(false);
634
635 ScopeEvents scope_events;
636 runner.Run(MAIN_F1_OSR_CATCH_F2_THROW_SOURCE, 123);
637 auto events = Events::CastTo<Events::MEMORY>();
638 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
639 ASSERT_EQ(osr_events.size(), 1);
640 ASSERT_EQ(osr_events[0]->method_name, "_GLOBAL::f1");
641 ASSERT_EQ(osr_events[0]->kind, events::OsrEntryKind::AFTER_IFRAME);
642 ASSERT_EQ(osr_events[0]->result, events::OsrEntryResult::SUCCESS);
643 auto deopt_events = events->Select<events::EventsMemory::DeoptimizationEvent>();
644 auto exception_events = events->Select<events::EventsMemory::ExceptionEvent>();
645 ASSERT_EQ(exception_events.size(), 1);
646 ASSERT_EQ(exception_events[0]->method_name, "_GLOBAL::f2");
647 ASSERT_EQ(exception_events[0]->type, events::ExceptionType::BOUND_CHECK);
648 }
649
650 #if !defined(USE_ADDRESS_SANITIZER) && defined(PANDA_TARGET_AMD64)
TEST_F(OsrTest,BoundTest)651 TEST_F(OsrTest, BoundTest)
652 {
653 PandaRunner runner;
654 runner.GetRuntimeOptions().SetCompilerHotnessThreshold(0);
655 runner.GetRuntimeOptions().SetCompilerEnableJit(true);
656 runner.GetCompilerOptions().SetCompilerNonOptimizing(true);
657
658 PandaString start =
659 " .function i64 main(i64 a0) {"
660 " lda a0";
661
662 PandaString end =
663 " return "
664 " }"
665 " ";
666
667 std::stringstream text("");
668
669 uint64_t insts_per_byte = 32;
670 uint64_t max_bits_in_inst = GetInstructionSizeBits(RUNTIME_ARCH);
671 uint64_t inst_count = runner.GetCompilerOptions().GetCompilerMaxGenCodeSize() / (insts_per_byte * max_bits_in_inst);
672
673 for (uint64_t i = 0; i < inst_count; ++i) {
674 text << " addi 1\n";
675 }
676
677 std::string BoundTest = std::string(start) + std::string(text.str()) + std::string(end);
678
679 ScopeEvents scope_events;
680
681 runner.Run(BoundTest, 123);
682 auto events = Events::CastTo<Events::MEMORY>();
683 auto osr_events = events->Select<events::EventsMemory::OsrEntryEvent>();
684 ASSERT_EQ(osr_events.size(), 1);
685 }
686 #endif
687 } // namespace panda::test
688