• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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