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 23using panda::panda_file::File; 24 25namespace panda::test { 26class OsrTest : public testing::Test { 27public: 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 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 } 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 53protected: 54 static constexpr size_t HOTNESS_THRESHOLD = 4; 55 56private: 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 63struct ScopeEvents { 64 ScopeEvents() 65 { 66 Events::Create<Events::MEMORY>(); 67 } 68 ~ScopeEvents() 69 { 70 Events::Destroy(); 71 } 72}; 73 74static 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 92TEST_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 107TEST_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 122static 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 145TEST_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 159TEST_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 173static 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 196TEST_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 210static 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 252TEST_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 268TEST_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 285TEST_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 306TEST_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 354static 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 388TEST_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 409TEST_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 429static 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 462TEST_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 482static 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 521TEST_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 544TEST_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 564static 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 604TEST_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 627TEST_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) 651TEST_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