1 # Copyright (C) 2015 The Android Open Source Project 2 # 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 .class public LBuilder; 16 17 .super Ljava/lang/Object; 18 19 # Basic test case with two try blocks and three catch handlers, one of which 20 # is shared by the two tries. 21 22 ## CHECK-START: int Builder.testMultipleTryCatch(int, int, int) builder (after) 23 24 ## CHECK: name "B0" 25 ## CHECK: successors "<<BEnterTry1:B\d+>>" 26 ## CHECK-DAG: <<Minus1:i\d+>> IntConstant -1 27 ## CHECK-DAG: <<Minus2:i\d+>> IntConstant -2 28 ## CHECK-DAG: <<Minus3:i\d+>> IntConstant -3 29 30 ## CHECK: name "<<BTry1:B\d+>>" 31 ## CHECK: predecessors "<<BEnterTry1>>" 32 ## CHECK: successors "<<BExitTry1:B\d+>>" 33 ## CHECK: DivZeroCheck 34 35 ## CHECK: name "<<BAdd:B\d+>>" 36 ## CHECK: predecessors "<<BExitTry1>>" 37 ## CHECK: successors "<<BEnterTry2:B\d+>>" 38 ## CHECK: Add 39 40 ## CHECK: name "<<BTry2:B\d+>>" 41 ## CHECK: predecessors "<<BEnterTry2>>" 42 ## CHECK: successors "<<BExitTry2:B\d+>>" 43 ## CHECK: DivZeroCheck 44 ## CHECK: <<Div:i\d+>> Div 45 46 ## CHECK: name "<<BAfterTry2:B\d+>>" 47 ## CHECK: predecessors "<<BExitTry2>>" 48 ## CHECK: successors "<<BReturn:B\d+>>" 49 ## CHECK: Goto 50 51 ## CHECK: name "<<BReturn>>" 52 ## CHECK: predecessors "<<BAfterTry2>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>" "<<BCatch3:B\d+>>" 53 ## CHECK: Phi [<<Div>>,<<Minus1>>,<<Minus2>>,<<Minus3>>] 54 ## CHECK: Return 55 56 ## CHECK: name "<<BCatch1>>" 57 ## CHECK: predecessors "<<BEnterTry1>>" "<<BExitTry1>>" 58 ## CHECK: successors "<<BReturn>>" 59 ## CHECK: flags "catch_block" 60 ## CHECK: Goto 61 62 ## CHECK: name "<<BCatch2>>" 63 ## CHECK: predecessors "<<BEnterTry2>>" "<<BExitTry2>>" 64 ## CHECK: successors "<<BReturn>>" 65 ## CHECK: flags "catch_block" 66 ## CHECK: Goto 67 68 ## CHECK: name "<<BCatch3>>" 69 ## CHECK: predecessors "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>" 70 ## CHECK: successors "<<BReturn>>" 71 ## CHECK: flags "catch_block" 72 ## CHECK: Goto 73 74 ## CHECK: name "<<BEnterTry1>>" 75 ## CHECK: predecessors "B0" 76 ## CHECK: successors "<<BTry1>>" 77 ## CHECK: xhandlers "<<BCatch1>>" "<<BCatch3>>" 78 ## CHECK: TryBoundary kind:entry 79 80 ## CHECK: name "<<BEnterTry2>>" 81 ## CHECK: predecessors "<<BAdd>>" 82 ## CHECK: successors "<<BTry2>>" 83 ## CHECK: xhandlers "<<BCatch2>>" "<<BCatch3>>" 84 ## CHECK: TryBoundary kind:entry 85 86 ## CHECK: name "<<BExitTry1>>" 87 ## CHECK: predecessors "<<BTry1>>" 88 ## CHECK: successors "<<BAdd>>" 89 ## CHECK: xhandlers "<<BCatch1>>" "<<BCatch3>>" 90 ## CHECK: TryBoundary kind:exit 91 92 ## CHECK: name "<<BExitTry2>>" 93 ## CHECK: predecessors "<<BTry2>>" 94 ## CHECK: successors "<<BAfterTry2>>" 95 ## CHECK: xhandlers "<<BCatch2>>" "<<BCatch3>>" 96 ## CHECK: TryBoundary kind:exit 97 98 .method public static testMultipleTryCatch(III)I 99 .registers 3 100 101 :try_start_1 102 div-int/2addr p0, p1 103 :try_end_1 104 .catch Ljava/lang/ArithmeticException; {:try_start_1 .. :try_end_1} :catch_arith 105 .catchall {:try_start_1 .. :try_end_1} :catch_other 106 107 add-int/2addr p0, p0 108 109 :try_start_2 110 div-int/2addr p0, p2 111 :try_end_2 112 .catch Ljava/lang/OutOfMemoryError; {:try_start_2 .. :try_end_2} :catch_mem 113 .catchall {:try_start_2 .. :try_end_2} :catch_other 114 115 nop 116 117 :return 118 return p0 119 120 :catch_arith 121 const/4 p0, -0x1 122 goto :return 123 124 :catch_mem 125 const/4 p0, -0x2 126 goto :return 127 128 :catch_other 129 const/4 p0, -0x3 130 goto :return 131 .end method 132 133 # Tests try-entry block when there are multiple entry points into the try block. 134 135 ## CHECK-START: int Builder.testMultipleEntries(int, int, int, int) builder (after) 136 137 ## CHECK: name "B0" 138 ## CHECK: successors "<<BIf:B\d+>>" 139 ## CHECK: <<Minus1:i\d+>> IntConstant -1 140 141 ## CHECK: name "<<BIf>>" 142 ## CHECK: predecessors "B0" 143 ## CHECK: successors "<<BSplit1:B\d+>>" "<<BThen:B\d+>>" 144 ## CHECK: If 145 146 ## CHECK: name "<<BThen>>" 147 ## CHECK: predecessors "<<BIf>>" 148 ## CHECK: successors "<<BEnterTry1:B\d+>>" 149 ## CHECK: Div 150 151 ## CHECK: name "<<BTry1:B\d+>>" 152 ## CHECK: predecessors "<<BEnterTry1>>" 153 ## CHECK: successors "<<BExitTry1:B\d+>>" 154 ## CHECK: Div 155 156 ## CHECK: name "<<BTry2:B\d+>>" 157 ## CHECK: predecessors "<<BEnterTry2:B\d+>>" 158 ## CHECK: successors "<<BExitTry2:B\d+>>" 159 ## CHECK: Div 160 161 ## CHECK: name "<<BReturn:B\d+>>" 162 ## CHECK: predecessors "<<BSplit3:B\d+>>" "<<BCatch:B\d+>>" 163 ## CHECK: Return 164 165 ## CHECK: name "<<BCatch>>" 166 ## CHECK: predecessors "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>" 167 ## CHECK: successors "<<BReturn>>" 168 ## CHECK: flags "catch_block" 169 ## CHECK: Goto 170 171 ## CHECK: name "<<BEnterTry1>>" 172 ## CHECK: predecessors "<<BThen>>" 173 ## CHECK: successors "<<BTry1>>" 174 ## CHECK: xhandlers "<<BCatch>>" 175 ## CHECK: TryBoundary kind:entry 176 177 ## CHECK: name "<<BEnterTry2>>" 178 ## CHECK: predecessors "<<BSplit1>>" "<<BSplit2:B\d+>>" 179 ## CHECK: successors "<<BTry2>>" 180 ## CHECK: xhandlers "<<BCatch>>" 181 ## CHECK: TryBoundary kind:entry 182 183 ## CHECK: name "<<BExitTry1>>" 184 ## CHECK: predecessors "<<BTry1>>" 185 ## CHECK: successors "<<BSplit2>>" 186 ## CHECK: xhandlers "<<BCatch>>" 187 ## CHECK: TryBoundary kind:exit 188 189 ## CHECK: name "<<BExitTry2>>" 190 ## CHECK: predecessors "<<BTry2>>" 191 ## CHECK: successors "<<BSplit3>>" 192 ## CHECK: xhandlers "<<BCatch>>" 193 ## CHECK: TryBoundary kind:exit 194 195 ## CHECK: name "<<BSplit1>>" 196 ## CHECK: predecessors "<<BIf>>" 197 ## CHECK: successors "<<BEnterTry2>>" 198 ## CHECK: Goto 199 200 ## CHECK: name "<<BSplit2>>" 201 ## CHECK: predecessors "<<BExitTry1>>" 202 ## CHECK: successors "<<BEnterTry2>>" 203 ## CHECK: Goto 204 205 ## CHECK: name "<<BSplit3>>" 206 ## CHECK: predecessors "<<BExitTry2>>" 207 ## CHECK: successors "<<BReturn>>" 208 ## CHECK: Goto 209 210 .method public static testMultipleEntries(IIII)I 211 .registers 4 212 213 if-eqz p2, :else 214 215 div-int/2addr p0, p1 216 217 :try_start 218 div-int/2addr p0, p2 219 220 :else 221 div-int/2addr p0, p3 222 :try_end 223 .catchall {:try_start .. :try_end} :catch_all 224 225 :return 226 return p0 227 228 :catch_all 229 const/4 p0, -0x1 230 goto :return 231 232 .end method 233 234 # Test that multiple try-exit blocks are generated if (normal) control flow can 235 # jump out of the try block at multiple points. 236 237 ## CHECK-START: int Builder.testMultipleExits(int, int) builder (after) 238 239 ## CHECK: name "B0" 240 ## CHECK: successors "<<BEnterTry:B\d+>>" 241 ## CHECK-DAG: <<Minus1:i\d+>> IntConstant -1 242 ## CHECK-DAG: <<Minus2:i\d+>> IntConstant -2 243 244 ## CHECK: name "<<BTry:B\d+>>" 245 ## CHECK: predecessors "<<BEnterTry>>" 246 ## CHECK: successors "<<BExitTry1:B\d+>>" "<<BExitTry2:B\d+>>" 247 ## CHECK: <<Div:i\d+>> Div 248 ## CHECK: If 249 250 ## CHECK: name "<<BReturn:B\d+>>" 251 ## CHECK: predecessors "<<BSplit:B\d+>>" "<<BThen:B\d+>>" "<<BCatch:B\d+>>" 252 ## CHECK: Phi [<<Div>>,<<Minus1>>,<<Minus2>>] 253 ## CHECK: Return 254 255 ## CHECK: name "<<BThen>>" 256 ## CHECK: predecessors "<<BExitTry1>>" 257 ## CHECK: successors "<<BReturn>>" 258 ## CHECK: Goto 259 260 ## CHECK: name "<<BCatch>>" 261 ## CHECK: predecessors "<<BEnterTry>>" "<<BExitTry1>>" "<<BExitTry2>>" 262 ## CHECK: successors "<<BReturn>>" 263 ## CHECK: flags "catch_block" 264 ## CHECK: Goto 265 266 ## CHECK: name "<<BEnterTry>>" 267 ## CHECK: predecessors "B0" 268 ## CHECK: successors "<<BTry>>" 269 ## CHECK: xhandlers "<<BCatch>>" 270 ## CHECK: TryBoundary kind:entry 271 272 ## CHECK: name "<<BExitTry1>>" 273 ## CHECK: predecessors "<<BTry>>" 274 ## CHECK: successors "<<BThen>>" 275 ## CHECK: xhandlers "<<BCatch>>" 276 ## CHECK: TryBoundary kind:exit 277 278 ## CHECK: name "<<BExitTry2>>" 279 ## CHECK: predecessors "<<BTry>>" 280 ## CHECK: successors "<<BSplit>>" 281 ## CHECK: xhandlers "<<BCatch>>" 282 ## CHECK: TryBoundary kind:exit 283 284 ## CHECK: name "<<BSplit>>" 285 ## CHECK: predecessors "<<BExitTry2>>" 286 ## CHECK: successors "<<BReturn>>" 287 ## CHECK: Goto 288 289 .method public static testMultipleExits(II)I 290 .registers 2 291 292 :try_start 293 div-int/2addr p0, p1 294 if-eqz p0, :then 295 :try_end 296 .catchall {:try_start .. :try_end} :catch_all 297 298 :return 299 return p0 300 301 :then 302 const/4 p0, -0x1 303 goto :return 304 305 :catch_all 306 const/4 p0, -0x2 307 goto :return 308 .end method 309 310 # Test that only one TryBoundary is inserted when an edge connects two different 311 # try ranges. 312 313 ## CHECK-START: int Builder.testSharedBoundary(int, int, int) builder (after) 314 315 ## CHECK: name "B0" 316 ## CHECK: successors "<<BEnter1:B\d+>>" 317 ## CHECK-DAG: <<Minus1:i\d+>> IntConstant -1 318 ## CHECK-DAG: <<Minus2:i\d+>> IntConstant -2 319 320 ## CHECK: name "<<BTry1:B\d+>>" 321 ## CHECK: predecessors "<<BEnter1>>" 322 ## CHECK: successors "<<BExit1:B\d+>>" 323 ## CHECK: Div 324 325 ## CHECK: name "<<BTry2:B\d+>>" 326 ## CHECK: predecessors "<<BEnter2:B\d+>>" 327 ## CHECK: successors "<<BExit2:B\d+>>" 328 ## CHECK: <<Div:i\d+>> Div 329 ## CHECK: Goto 330 331 ## CHECK: name "<<BReturn:B\d+>>" 332 ## CHECK: predecessors "<<BSplit:B\d+>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>" 333 ## CHECK: Phi [<<Div>>,<<Minus1>>,<<Minus2>>] 334 ## CHECK: Return 335 336 ## CHECK: name "<<BCatch1>>" 337 ## CHECK: predecessors "<<BEnter1>>" "<<BExit1>>" 338 ## CHECK: successors "<<BReturn>>" 339 ## CHECK: flags "catch_block" 340 ## CHECK: Goto 341 342 ## CHECK: name "<<BCatch2>>" 343 ## CHECK: predecessors "<<BEnter2>>" "<<BExit2>>" 344 ## CHECK: successors "<<BReturn>>" 345 ## CHECK: flags "catch_block" 346 ## CHECK: Goto 347 348 ## CHECK: name "<<BEnter1>>" 349 ## CHECK: predecessors "B0" 350 ## CHECK: successors "<<BTry1>>" 351 ## CHECK: xhandlers "<<BCatch1>>" 352 ## CHECK: TryBoundary kind:entry 353 354 ## CHECK: name "<<BEnter2>>" 355 ## CHECK: predecessors "<<BExit1>>" 356 ## CHECK: successors "<<BTry2>>" 357 ## CHECK: xhandlers "<<BCatch2>>" 358 ## CHECK: TryBoundary kind:entry 359 360 ## CHECK: name "<<BExit1>>" 361 ## CHECK: predecessors "<<BTry1>>" 362 ## CHECK: successors "<<BEnter2>>" 363 ## CHECK: xhandlers "<<BCatch1>>" 364 ## CHECK: TryBoundary kind:exit 365 366 ## CHECK: name "<<BExit2>>" 367 ## CHECK: predecessors "<<BTry2>>" 368 ## CHECK: successors "<<BSplit>>" 369 ## CHECK: xhandlers "<<BCatch2>>" 370 ## CHECK: TryBoundary kind:exit 371 372 ## CHECK: name "<<BSplit>>" 373 ## CHECK: predecessors "<<BExit2>>" 374 ## CHECK: successors "<<BReturn>>" 375 ## CHECK: Goto 376 377 .method public static testSharedBoundary(III)I 378 .registers 3 379 380 :try_start_1 381 div-int/2addr p0, p1 382 :try_end_1 383 .catchall {:try_start_1 .. :try_end_1} :catch_all_1 384 385 :try_start_2 386 div-int/2addr p0, p2 387 :try_end_2 388 .catchall {:try_start_2 .. :try_end_2} :catch_all_2 389 390 :return 391 return p0 392 393 :catch_all_1 394 const/4 p0, -0x1 395 goto :return 396 397 :catch_all_2 398 const/4 p0, -0x2 399 goto :return 400 .end method 401 402 # Same as previous test, only the blocks are processed in the opposite order. 403 404 ## CHECK-START: int Builder.testSharedBoundary_Reverse(int, int, int) builder (after) 405 406 ## CHECK: name "B0" 407 ## CHECK: successors "<<BGoto:B\d+>>" 408 ## CHECK-DAG: <<Minus1:i\d+>> IntConstant -1 409 ## CHECK-DAG: <<Minus2:i\d+>> IntConstant -2 410 411 ## CHECK: name "<<BGoto>>" 412 ## CHECK: successors "<<BEnter2:B\d+>>" 413 ## CHECK: Goto 414 415 ## CHECK: name "<<BTry1:B\d+>>" 416 ## CHECK: predecessors "<<BEnter1:B\d+>>" 417 ## CHECK: successors "<<BExit1:B\d+>>" 418 ## CHECK: <<Div:i\d+>> Div 419 ## CHECK: Goto 420 421 ## CHECK: name "<<BTry2:B\d+>>" 422 ## CHECK: predecessors "<<BEnter2>>" 423 ## CHECK: successors "<<BExit2:B\d+>>" 424 ## CHECK: Div 425 ## CHECK: Goto 426 427 ## CHECK: name "<<BReturn:B\d+>>" 428 ## CHECK: predecessors "<<BSplit:B\d+>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>" 429 ## CHECK: Phi [<<Div>>,<<Minus1>>,<<Minus2>>] 430 ## CHECK: Return 431 432 ## CHECK: name "<<BCatch1>>" 433 ## CHECK: predecessors "<<BEnter1>>" "<<BExit1>>" 434 ## CHECK: successors "<<BReturn>>" 435 ## CHECK: flags "catch_block" 436 ## CHECK: Goto 437 438 ## CHECK: name "<<BCatch2>>" 439 ## CHECK: predecessors "<<BEnter2>>" "<<BExit2>>" 440 ## CHECK: successors "<<BReturn>>" 441 ## CHECK: flags "catch_block" 442 ## CHECK: Goto 443 444 ## CHECK: name "<<BEnter1>>" 445 ## CHECK: predecessors "<<BExit2>>" 446 ## CHECK: successors "<<BTry1>>" 447 ## CHECK: xhandlers "<<BCatch1>>" 448 ## CHECK: TryBoundary kind:entry 449 450 ## CHECK: name "<<BEnter2>>" 451 ## CHECK: predecessors "<<BGoto>>" 452 ## CHECK: successors "<<BTry2>>" 453 ## CHECK: xhandlers "<<BCatch2>>" 454 ## CHECK: TryBoundary kind:entry 455 456 ## CHECK: name "<<BExit1>>" 457 ## CHECK: predecessors "<<BTry1>>" 458 ## CHECK: successors "<<BSplit>>" 459 ## CHECK: xhandlers "<<BCatch1>>" 460 ## CHECK: TryBoundary kind:exit 461 462 ## CHECK: name "<<BExit2>>" 463 ## CHECK: predecessors "<<BTry2>>" 464 ## CHECK: successors "<<BEnter1>>" 465 ## CHECK: xhandlers "<<BCatch2>>" 466 ## CHECK: TryBoundary kind:exit 467 468 ## CHECK: name "<<BSplit>>" 469 ## CHECK: predecessors "<<BExit1>>" 470 ## CHECK: successors "<<BReturn>>" 471 ## CHECK: Goto 472 473 .method public static testSharedBoundary_Reverse(III)I 474 .registers 3 475 476 goto :try_start_2 477 478 :try_start_1 479 div-int/2addr p0, p1 480 goto :return 481 :try_end_1 482 .catchall {:try_start_1 .. :try_end_1} :catch_all_1 483 484 :try_start_2 485 div-int/2addr p0, p2 486 goto :try_start_1 487 :try_end_2 488 .catchall {:try_start_2 .. :try_end_2} :catch_all_2 489 490 :return 491 return p0 492 493 :catch_all_1 494 const/4 p0, -0x1 495 goto :return 496 497 :catch_all_2 498 const/4 p0, -0x2 499 goto :return 500 .end method 501 502 # Test that nested tries are split into non-overlapping blocks and TryBoundary 503 # blocks are correctly created between them. 504 505 ## CHECK-START: int Builder.testNestedTry(int, int, int, int) builder (after) 506 507 ## CHECK: name "B0" 508 ## CHECK-DAG: <<Minus1:i\d+>> IntConstant -1 509 ## CHECK-DAG: <<Minus2:i\d+>> IntConstant -2 510 511 ## CHECK: name "<<BTry1:B\d+>>" 512 ## CHECK: predecessors "<<BEnter1:B\d+>>" 513 ## CHECK: successors "<<BExit1:B\d+>>" 514 ## CHECK: Div 515 516 ## CHECK: name "<<BTry2:B\d+>>" 517 ## CHECK: predecessors "<<BEnter2:B\d+>>" 518 ## CHECK: successors "<<BExit2:B\d+>>" 519 ## CHECK: Div 520 ## CHECK: Goto 521 522 ## CHECK: name "<<BTry3:B\d+>>" 523 ## CHECK: predecessors "<<BEnter3:B\d+>>" 524 ## CHECK: successors "<<BExit3:B\d+>>" 525 ## CHECK: <<Div:i\d+>> Div 526 ## CHECK: Goto 527 528 ## CHECK: name "<<BReturn:B\d+>>" 529 ## CHECK: predecessors "<<BSplit:B\d+>>" "<<BCatchArith:B\d+>>" "<<BCatchAll:B\d+>>" 530 ## CHECK: Phi [<<Div>>,<<Minus1>>,<<Minus2>>] 531 ## CHECK: Return 532 533 ## CHECK: name "<<BCatchArith>>" 534 ## CHECK: predecessors "<<BEnter2>>" "<<BExit2>>" 535 ## CHECK: successors "<<BReturn>>" 536 ## CHECK: flags "catch_block" 537 ## CHECK: Goto 538 539 ## CHECK: name "<<BCatchAll>>" 540 ## CHECK: predecessors "<<BEnter1>>" "<<BEnter2>>" "<<BEnter3>>" "<<BExit1>>" "<<BExit2>>" "<<BExit3>>" 541 ## CHECK: successors "<<BReturn>>" 542 ## CHECK: flags "catch_block" 543 ## CHECK: Goto 544 545 ## CHECK: name "<<BEnter1>>" 546 ## CHECK: predecessors "B0" 547 ## CHECK: successors "<<BTry1>>" 548 ## CHECK: xhandlers "<<BCatchAll>>" 549 ## CHECK: TryBoundary kind:entry 550 551 ## CHECK: name "<<BEnter2>>" 552 ## CHECK: predecessors "<<BExit1>>" 553 ## CHECK: successors "<<BTry2>>" 554 ## CHECK: xhandlers "<<BCatchArith>>" "<<BCatchAll>>" 555 ## CHECK: TryBoundary kind:entry 556 557 ## CHECK: name "<<BEnter3>>" 558 ## CHECK: predecessors "<<BExit2>>" 559 ## CHECK: successors "<<BTry3>>" 560 ## CHECK: xhandlers "<<BCatchAll>>" 561 ## CHECK: TryBoundary kind:entry 562 563 ## CHECK: name "<<BExit1>>" 564 ## CHECK: predecessors "<<BTry1>>" 565 ## CHECK: successors "<<BEnter2>>" 566 ## CHECK: xhandlers "<<BCatchAll>>" 567 ## CHECK: TryBoundary kind:exit 568 569 ## CHECK: name "<<BExit2>>" 570 ## CHECK: predecessors "<<BTry2>>" 571 ## CHECK: successors "<<BEnter3>>" 572 ## CHECK: xhandlers "<<BCatchArith>>" "<<BCatchAll>>" 573 ## CHECK: TryBoundary kind:exit 574 575 ## CHECK: name "<<BExit3>>" 576 ## CHECK: predecessors "<<BTry3>>" 577 ## CHECK: successors "<<BSplit>>" 578 ## CHECK: xhandlers "<<BCatchAll>>" 579 ## CHECK: TryBoundary kind:exit 580 581 ## CHECK: name "<<BSplit>>" 582 ## CHECK: predecessors "<<BExit3>>" 583 ## CHECK: successors "<<BReturn>>" 584 ## CHECK: Goto 585 586 .method public static testNestedTry(IIII)I 587 .registers 4 588 589 :try_start_1 590 div-int/2addr p0, p1 591 592 :try_start_2 593 div-int/2addr p0, p2 594 :try_end_2 595 .catch Ljava/lang/ArithmeticException; {:try_start_2 .. :try_end_2} :catch_arith 596 597 div-int/2addr p0, p3 598 :try_end_1 599 .catchall {:try_start_1 .. :try_end_1} :catch_all 600 601 :return 602 return p0 603 604 :catch_arith 605 const/4 p0, -0x1 606 goto :return 607 608 :catch_all 609 const/4 p0, -0x2 610 goto :return 611 .end method 612 613 # Test control flow that enters a try block, leaves it and returns again. 614 615 ## CHECK-START: int Builder.testIncontinuousTry(int, int, int, int) builder (after) 616 617 ## CHECK: name "B0" 618 ## CHECK: <<Minus1:i\d+>> IntConstant -1 619 620 ## CHECK: name "<<BTry1:B\d+>>" 621 ## CHECK: predecessors "<<BEnterTry1:B\d+>>" 622 ## CHECK: successors "<<BExitTry1:B\d+>>" 623 ## CHECK: Div 624 ## CHECK: Goto 625 626 ## CHECK: name "<<BTry2:B\d+>>" 627 ## CHECK: predecessors "<<BEnterTry2:B\d+>>" 628 ## CHECK: successors "<<BExitTry2:B\d+>>" 629 ## CHECK: <<Div:i\d+>> Div 630 ## CHECK: Goto 631 632 ## CHECK: name "<<BReturn:B\d+>>" 633 ## CHECK: predecessors "<<BSplit:B\d+>>" "<<BCatch:B\d+>>" 634 ## CHECK: Phi [<<Div>>,<<Minus1>>] 635 ## CHECK: Return 636 637 ## CHECK: name "<<BOutside:B\d+>>" 638 ## CHECK: predecessors "<<BExitTry1>>" 639 ## CHECK: successors "<<BEnterTry2>>" 640 ## CHECK: Div 641 642 ## CHECK: name "<<BCatch>>" 643 ## CHECK: predecessors "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>" 644 ## CHECK: successors "<<BReturn>>" 645 ## CHECK: flags "catch_block" 646 ## CHECK: Goto 647 648 ## CHECK: name "<<BEnterTry1>>" 649 ## CHECK: predecessors "B0" 650 ## CHECK: successors "<<BTry1>>" 651 ## CHECK: xhandlers "<<BCatch>>" 652 ## CHECK: TryBoundary kind:entry 653 654 ## CHECK: name "<<BEnterTry2>>" 655 ## CHECK: predecessors "<<BOutside>>" 656 ## CHECK: successors "<<BTry2>>" 657 ## CHECK: xhandlers "<<BCatch>>" 658 ## CHECK: TryBoundary kind:entry 659 660 ## CHECK: name "<<BExitTry1>>" 661 ## CHECK: predecessors "<<BTry1>>" 662 ## CHECK: successors "<<BOutside>>" 663 ## CHECK: xhandlers "<<BCatch>>" 664 ## CHECK: TryBoundary kind:exit 665 666 ## CHECK: name "<<BExitTry2>>" 667 ## CHECK: predecessors "<<BTry2>>" 668 ## CHECK: successors "<<BSplit>>" 669 ## CHECK: xhandlers "<<BCatch>>" 670 ## CHECK: TryBoundary kind:exit 671 672 ## CHECK: name "<<BSplit>>" 673 ## CHECK: predecessors "<<BExitTry2>>" 674 ## CHECK: successors "<<BReturn>>" 675 ## CHECK: Goto 676 677 .method public static testIncontinuousTry(IIII)I 678 .registers 4 679 680 :try_start 681 div-int/2addr p0, p1 682 goto :outside 683 684 :inside 685 div-int/2addr p0, p3 686 :try_end 687 .catchall {:try_start .. :try_end} :catch_all 688 689 :return 690 return p0 691 692 :outside 693 div-int/2addr p0, p2 694 goto :inside 695 696 :catch_all 697 const/4 p0, -0x1 698 goto :return 699 .end method 700 701 ## CHECK-START: int Builder.testSwitchTryEnter(int, int, int, int) builder (after) 702 703 ## CHECK: name "B0" 704 ## CHECK: successors "<<BPSwitch0:B\d+>>" 705 706 ## CHECK: name "<<BPSwitch0>>" 707 ## CHECK: predecessors "B0" 708 ## CHECK: successors "<<BSplit1:B\d+>>" "<<BPSwitch1:B\d+>>" 709 ## CHECK: If 710 711 ## CHECK: name "<<BPSwitch1>>" 712 ## CHECK: predecessors "<<BPSwitch0>>" 713 ## CHECK: successors "<<BSplit2:B\d+>>" "<<BEnterTry1:B\d+>>" 714 ## CHECK: If 715 716 ## CHECK: name "<<BTry1:B\d+>>" 717 ## CHECK: predecessors "<<BEnterTry1>>" 718 ## CHECK: successors "<<BExitTry1:B\d+>>" 719 ## CHECK: Div 720 721 ## CHECK: name "<<BTry2:B\d+>>" 722 ## CHECK: predecessors "<<BEnterTry2:B\d+>>" 723 ## CHECK: successors "<<BExitTry2:B\d+>>" 724 ## CHECK: Div 725 726 ## CHECK: name "<<BOutside:B\d+>>" 727 ## CHECK: predecessors "<<BSplit2>>" "<<BSplit4:B\d+>>" 728 ## CHECK: successors "<<BReturn:B\d+>>" 729 ## CHECK: Div 730 731 ## CHECK: name "<<BReturn>>" 732 ## CHECK: predecessors "<<BOutside>>" "<<BCatch:B\d+>>" 733 ## CHECK: successors "<<BExit:B\d+>>" 734 ## CHECK: Return 735 736 ## CHECK: name "<<BExit>>" 737 ## CHECK: Exit 738 739 ## CHECK: name "<<BCatch>>" 740 ## CHECK: predecessors "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>" 741 ## CHECK: successors "<<BReturn>>" 742 ## CHECK: flags "catch_block" 743 ## CHECK: Goto 744 745 ## CHECK: name "<<BEnterTry1>>" 746 ## CHECK: predecessors "<<BPSwitch1>>" 747 ## CHECK: successors "<<BTry1>>" 748 ## CHECK: xhandlers "<<BCatch>>" 749 ## CHECK: TryBoundary kind:entry 750 751 ## CHECK: name "<<BEnterTry2>>" 752 ## CHECK: predecessors "<<BSplit1>>" "<<BSplit3:B\d+>>" 753 ## CHECK: successors "<<BTry2>>" 754 ## CHECK: xhandlers "<<BCatch>>" 755 ## CHECK: TryBoundary kind:entry 756 757 ## CHECK: name "<<BExitTry1>>" 758 ## CHECK: predecessors "<<BTry1>>" 759 ## CHECK: successors "<<BSplit3>>" 760 ## CHECK: xhandlers "<<BCatch>>" 761 ## CHECK: TryBoundary kind:exit 762 763 ## CHECK: name "<<BExitTry2>>" 764 ## CHECK: predecessors "<<BTry2>>" 765 ## CHECK: successors "<<BSplit4>>" 766 ## CHECK: xhandlers "<<BCatch>>" 767 ## CHECK: TryBoundary kind:exit 768 769 ## CHECK: name "<<BSplit1>>" 770 ## CHECK: predecessors "<<BPSwitch0>>" 771 ## CHECK: successors "<<BEnterTry2>>" 772 ## CHECK: Goto 773 774 ## CHECK: name "<<BSplit2>>" 775 ## CHECK: predecessors "<<BPSwitch1>>" 776 ## CHECK: successors "<<BOutside>>" 777 ## CHECK: Goto 778 779 ## CHECK: name "<<BSplit3>>" 780 ## CHECK: predecessors "<<BExitTry1>>" 781 ## CHECK: successors "<<BEnterTry2>>" 782 ## CHECK: Goto 783 784 ## CHECK: name "<<BSplit4>>" 785 ## CHECK: predecessors "<<BExitTry2>>" 786 ## CHECK: successors "<<BOutside>>" 787 ## CHECK: Goto 788 789 .method public static testSwitchTryEnter(IIII)I 790 .registers 4 791 792 packed-switch p0, :pswitch_data 793 794 :try_start 795 div-int/2addr p0, p1 796 797 :pswitch1 798 div-int/2addr p0, p2 799 goto :pswitch2 800 801 :pswitch_data 802 .packed-switch 0x0 803 :pswitch1 804 :pswitch2 805 .end packed-switch 806 :try_end 807 .catchall {:try_start .. :try_end} :catch_all 808 809 :pswitch2 810 div-int/2addr p0, p3 811 812 :catch_all 813 return p0 814 .end method 815 816 ## CHECK-START: int Builder.testSwitchTryExit(int, int, int, int) builder (after) 817 818 ## CHECK: name "B0" 819 ## CHECK: successors "<<BEnterTry1:B\d+>>" 820 821 ## CHECK: name "<<BPSwitch0:B\d+>>" 822 ## CHECK: predecessors "<<BEnterTry1>>" 823 ## CHECK: successors "<<BSplit1:B\d+>>" "<<BExitTry1:B\d+>>" 824 ## CHECK: If 825 826 ## CHECK: name "<<BPSwitch1:B\d+>>" 827 ## CHECK: predecessors "<<BExitTry1>>" 828 ## CHECK: successors "<<BSplit2:B\d+>>" "<<BEnterTry2:B\d+>>" 829 ## CHECK: If 830 831 ## CHECK: name "<<BTry1:B\d+>>" 832 ## CHECK: predecessors "<<BEnterTry2>>" 833 ## CHECK: successors "<<BTry2:B\d+>>" 834 ## CHECK: Div 835 836 ## CHECK: name "<<BTry2>>" 837 ## CHECK: predecessors "<<BSplit1>>" "<<BTry1>>" 838 ## CHECK: successors "<<BExitTry2:B\d+>>" 839 ## CHECK: Div 840 841 ## CHECK: name "<<BOutside:B\d+>>" 842 ## CHECK: predecessors "<<BSplit2>>" "<<BSplit3:B\d+>>" 843 ## CHECK: successors "<<BReturn:B\d+>>" 844 ## CHECK: Div 845 846 ## CHECK: name "<<BReturn>>" 847 ## CHECK: predecessors "<<BOutside>>" "<<BCatch:B\d+>>" 848 ## CHECK: successors "<<BExit:B\d+>>" 849 ## CHECK: Return 850 851 ## CHECK: name "<<BExit>>" 852 ## CHECK: Exit 853 854 ## CHECK: name "<<BCatch>>" 855 ## CHECK: predecessors "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>" 856 ## CHECK: successors "<<BReturn>>" 857 ## CHECK: flags "catch_block" 858 ## CHECK: Goto 859 860 ## CHECK: name "<<BEnterTry1>>" 861 ## CHECK: predecessors "B0" 862 ## CHECK: successors "<<BPSwitch0>>" 863 ## CHECK: xhandlers "<<BCatch>>" 864 ## CHECK: TryBoundary kind:entry 865 866 ## CHECK: name "<<BEnterTry2>>" 867 ## CHECK: predecessors "<<BPSwitch1>>" 868 ## CHECK: successors "<<BTry1>>" 869 ## CHECK: xhandlers "<<BCatch>>" 870 ## CHECK: TryBoundary kind:entry 871 872 ## CHECK: name "<<BExitTry1>>" 873 ## CHECK: predecessors "<<BPSwitch0>>" 874 ## CHECK: successors "<<BPSwitch1>>" 875 ## CHECK: xhandlers "<<BCatch>>" 876 ## CHECK: TryBoundary kind:exit 877 878 ## CHECK: name "<<BExitTry2>>" 879 ## CHECK: predecessors "<<BTry2>>" 880 ## CHECK: successors "<<BSplit3>>" 881 ## CHECK: xhandlers "<<BCatch>>" 882 ## CHECK: TryBoundary kind:exit 883 884 ## CHECK: name "<<BSplit1>>" 885 ## CHECK: predecessors "<<BPSwitch0>>" 886 ## CHECK: successors "<<BTry2>>" 887 ## CHECK: Goto 888 889 ## CHECK: name "<<BSplit2>>" 890 ## CHECK: predecessors "<<BPSwitch1>>" 891 ## CHECK: successors "<<BOutside>>" 892 ## CHECK: Goto 893 894 ## CHECK: name "<<BSplit3>>" 895 ## CHECK: predecessors "<<BExitTry2>>" 896 ## CHECK: successors "<<BOutside>>" 897 ## CHECK: Goto 898 899 .method public static testSwitchTryExit(IIII)I 900 .registers 4 901 902 :try_start 903 div-int/2addr p0, p1 904 packed-switch p0, :pswitch_data 905 906 div-int/2addr p0, p1 907 908 :pswitch1 909 div-int/2addr p0, p2 910 :try_end 911 .catchall {:try_start .. :try_end} :catch_all 912 913 :pswitch2 914 div-int/2addr p0, p3 915 916 :catch_all 917 return p0 918 919 :pswitch_data 920 .packed-switch 0x0 921 :pswitch1 922 :pswitch2 923 .end packed-switch 924 .end method 925 926 # Test that a TryBoundary is inserted between a Throw instruction and the exit 927 # block when covered by a try range. 928 929 ## CHECK-START: int Builder.testThrow(java.lang.Exception) builder (after) 930 931 ## CHECK: name "B0" 932 ## CHECK: successors "<<BEnterTry:B\d+>>" 933 ## CHECK: <<Minus1:i\d+>> IntConstant -1 934 935 ## CHECK: name "<<BTry:B\d+>>" 936 ## CHECK: predecessors "<<BEnterTry>>" 937 ## CHECK: successors "<<BExitTry:B\d+>>" 938 ## CHECK: Throw 939 940 ## CHECK: name "<<BCatch:B\d+>>" 941 ## CHECK: predecessors "<<BEnterTry>>" "<<BExitTry>>" 942 ## CHECK: successors "<<BExit:B\d+>>" 943 ## CHECK: flags "catch_block" 944 ## CHECK: Return [<<Minus1>>] 945 946 ## CHECK: name "<<BExit>>" 947 ## CHECK: predecessors "<<BExitTry>>" "<<BCatch>>" 948 ## CHECK: Exit 949 950 ## CHECK: name "<<BEnterTry>>" 951 ## CHECK: predecessors "B0" 952 ## CHECK: successors "<<BTry>>" 953 ## CHECK: xhandlers "<<BCatch>>" 954 ## CHECK: TryBoundary kind:entry 955 956 ## CHECK: name "<<BExitTry>>" 957 ## CHECK: predecessors "<<BTry>>" 958 ## CHECK: successors "<<BExit>>" 959 ## CHECK: xhandlers "<<BCatch>>" 960 ## CHECK: TryBoundary kind:exit 961 962 .method public static testThrow(Ljava/lang/Exception;)I 963 .registers 2 964 965 :try_start 966 throw p0 967 :try_end 968 .catchall {:try_start .. :try_end} :catch_all 969 970 :catch_all 971 const/4 v0, -0x1 972 return v0 973 .end method 974 975 # Test graph with a throw/catch loop. 976 977 ## CHECK-START: int Builder.testCatchLoop(int, int, int) builder (after) 978 979 ## CHECK: name "B0" 980 ## CHECK: successors "<<BSplit:B\d+>>" 981 982 ## CHECK: name "<<BTry:B\d+>>" 983 ## CHECK: predecessors "<<BEnterTry:B\d+>>" 984 ## CHECK: successors "<<BExitTry:B\d+>>" 985 ## CHECK: Div 986 987 ## CHECK: name "<<BReturn:B\d+>>" 988 ## CHECK: predecessors "<<BExitTry>>" 989 ## CHECK: successors "<<BExit:B\d+>>" 990 ## CHECK: Return 991 992 ## CHECK: name "<<BExit>>" 993 ## CHECK: predecessors "<<BReturn>>" 994 ## CHECK: Exit 995 996 ## CHECK: name "<<BCatch:B\d+>>" 997 ## CHECK: predecessors "<<BEnterTry>>" "<<BExitTry>>" 998 ## CHECK: successors "<<BEnterTry>>" 999 ## CHECK: flags "catch_block" 1000 ## CHECK: Goto 1001 1002 ## CHECK: name "<<BEnterTry>>" 1003 ## CHECK: predecessors "<<BSplit>>" "<<BCatch>>" 1004 ## CHECK: successors "<<BTry>>" 1005 ## CHECK: xhandlers "<<BCatch>>" 1006 ## CHECK: TryBoundary kind:entry 1007 1008 ## CHECK: name "<<BExitTry>>" 1009 ## CHECK: predecessors "<<BTry>>" 1010 ## CHECK: successors "<<BReturn>>" 1011 ## CHECK: xhandlers "<<BCatch>>" 1012 ## CHECK: TryBoundary kind:exit 1013 1014 ## CHECK: name "<<BSplit>>" 1015 ## CHECK: predecessors "B0" 1016 ## CHECK: successors "<<BEnterTry>>" 1017 ## CHECK: Goto 1018 1019 .method public static testCatchLoop(III)I 1020 .registers 4 1021 1022 :try_start 1023 :catch_all 1024 div-int/2addr p0, p2 1025 :try_end 1026 .catchall {:try_start .. :try_end} :catch_all 1027 1028 :return 1029 return p0 1030 .end method 1031 1032 # Test that handler edges are not split. In this scenario, the catch block is 1033 # only the handler of the try block. 1034 1035 ## CHECK-START: int Builder.testHandlerEdge1(int, int, int) builder (after) 1036 1037 ## CHECK: name "B0" 1038 ## CHECK: successors "<<BEnterTry1:B\d+>>" 1039 1040 ## CHECK: name "<<BTry1:B\d+>>" 1041 ## CHECK: predecessors "<<BEnterTry1>>" 1042 ## CHECK: successors "<<BExitTry1:B\d+>>" 1043 ## CHECK: Div 1044 1045 ## CHECK: name "<<BTry2:B\d+>>" 1046 ## CHECK: predecessors "<<BEnterTry2:B\d+>>" 1047 ## CHECK: successors "<<BExitTry2:B\d+>>" 1048 ## CHECK: Div 1049 1050 ## CHECK: name "<<BReturn:B\d+>>" 1051 ## CHECK: predecessors "<<BExitTry2>>" 1052 ## CHECK: successors "<<BExit:B\d+>>" 1053 ## CHECK: Return 1054 1055 ## CHECK: name "<<BExit>>" 1056 ## CHECK: predecessors "<<BReturn>>" 1057 ## CHECK: Exit 1058 1059 ## CHECK: name "<<BCatch:B\d+>>" 1060 ## CHECK: predecessors "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>" 1061 ## CHECK: successors "<<BEnterTry2>>" 1062 ## CHECK: flags "catch_block" 1063 ## CHECK: Goto 1064 1065 ## CHECK: name "<<BEnterTry1>>" 1066 ## CHECK: predecessors "B0" 1067 ## CHECK: successors "<<BTry1>>" 1068 ## CHECK: xhandlers "<<BCatch>>" 1069 ## CHECK: TryBoundary kind:entry 1070 1071 ## CHECK: name "<<BEnterTry2>>" 1072 ## CHECK: predecessors "<<BSplit:B\d+>>" "<<BCatch>>" 1073 ## CHECK: successors "<<BTry2>>" 1074 ## CHECK: xhandlers "<<BCatch>>" 1075 ## CHECK: TryBoundary kind:entry 1076 1077 ## CHECK: name "<<BExitTry1>>" 1078 ## CHECK: predecessors "<<BTry1>>" 1079 ## CHECK: successors "<<BSplit>>" 1080 ## CHECK: xhandlers "<<BCatch>>" 1081 ## CHECK: TryBoundary kind:exit 1082 1083 ## CHECK: name "<<BExitTry2>>" 1084 ## CHECK: predecessors "<<BTry2>>" 1085 ## CHECK: successors "<<BReturn>>" 1086 ## CHECK: xhandlers "<<BCatch>>" 1087 ## CHECK: TryBoundary kind:exit 1088 1089 ## CHECK: name "<<BSplit>>" 1090 ## CHECK: predecessors "<<BExitTry1>>" 1091 ## CHECK: successors "<<BEnterTry2>>" 1092 ## CHECK: Goto 1093 1094 .method public static testHandlerEdge1(III)I 1095 .registers 4 1096 1097 :try_start 1098 div-int/2addr p0, p1 1099 1100 :catch_all 1101 div-int/2addr p0, p2 1102 :try_end 1103 .catchall {:try_start .. :try_end} :catch_all 1104 1105 return p0 1106 .end method 1107 1108 # Test that handler edges are not split. In this scenario, the catch block is 1109 # the handler and also the successor of the try block. 1110 1111 ## CHECK-START: int Builder.testHandlerEdge2(int, int, int) builder (after) 1112 1113 ## CHECK: name "B0" 1114 ## CHECK: successors "<<BSplit1:B\d+>>" 1115 1116 ## CHECK: name "<<BTry1:B\d+>>" 1117 ## CHECK: predecessors "<<BEnterTry1:B\d+>>" 1118 ## CHECK: successors "<<BExitTry1:B\d+>>" 1119 ## CHECK: Div 1120 1121 ## CHECK: name "<<BTry2:B\d+>>" 1122 ## CHECK: predecessors "<<BEnterTry2:B\d+>>" 1123 ## CHECK: successors "<<BExitTry2:B\d+>>" 1124 ## CHECK: Div 1125 1126 ## CHECK: name "<<BReturn:B\d+>>" 1127 ## CHECK: predecessors "<<BExitTry2>>" 1128 ## CHECK: successors "<<BExit:B\d+>>" 1129 ## CHECK: Return 1130 1131 ## CHECK: name "<<BExit>>" 1132 ## CHECK: Exit 1133 1134 ## CHECK: name "<<BCatch2:B\d+>>" 1135 ## CHECK: predecessors "<<BEnterTry1>>" "<<BExitTry1>>" 1136 ## CHECK: successors "<<BEnterTry2>>" 1137 ## CHECK: flags "catch_block" 1138 1139 ## CHECK: name "<<BCatch1:B\d+>>" 1140 ## CHECK: predecessors "<<BEnterTry2>>" "<<BExitTry2>>" 1141 ## CHECK: successors "<<BEnterTry1>>" 1142 ## CHECK: flags "catch_block" 1143 1144 ## CHECK: name "<<BEnterTry1>>" 1145 ## CHECK: predecessors "<<BSplit1>>" "<<BCatch1>>" 1146 ## CHECK: successors "<<BTry1>>" 1147 ## CHECK: xhandlers "<<BCatch2>>" 1148 ## CHECK: TryBoundary kind:entry 1149 1150 ## CHECK: name "<<BEnterTry2>>" 1151 ## CHECK: predecessors "<<BSplit2:B\d+>>" "<<BCatch2>>" 1152 ## CHECK: successors "<<BTry2>>" 1153 ## CHECK: xhandlers "<<BCatch1>>" 1154 ## CHECK: TryBoundary kind:entry 1155 1156 ## CHECK: name "<<BExitTry1>>" 1157 ## CHECK: predecessors "<<BTry1>>" 1158 ## CHECK: successors "<<BSplit2>>" 1159 ## CHECK: xhandlers "<<BCatch2>>" 1160 ## CHECK: TryBoundary kind:exit 1161 1162 ## CHECK: name "<<BExitTry2>>" 1163 ## CHECK: predecessors "<<BTry2>>" 1164 ## CHECK: successors "<<BReturn>>" 1165 ## CHECK: xhandlers "<<BCatch1>>" 1166 ## CHECK: TryBoundary kind:exit 1167 1168 ## CHECK: name "<<BSplit1>>" 1169 ## CHECK: predecessors "B0" 1170 ## CHECK: successors "<<BEnterTry1>>" 1171 ## CHECK: Goto 1172 1173 ## CHECK: name "<<BSplit2>>" 1174 ## CHECK: predecessors "<<BExitTry1>>" 1175 ## CHECK: successors "<<BEnterTry2>>" 1176 ## CHECK: Goto 1177 1178 .method public static testHandlerEdge2(III)I 1179 .registers 4 1180 1181 :try_start_1 1182 :catch_all_1 1183 div-int/2addr p0, p1 1184 :try_end_1 1185 .catchall {:try_start_1 .. :try_end_1} :catch_all_2 1186 1187 :try_start_2 1188 :catch_all_2 1189 div-int/2addr p0, p2 1190 :try_end_2 1191 .catchall {:try_start_2 .. :try_end_2} :catch_all_1 1192 1193 return p0 1194 .end method 1195 1196 # Test graph with try/catch inside a loop. 1197 1198 ## CHECK-START: int Builder.testTryInLoop(int, int) builder (after) 1199 1200 ## CHECK: name "B0" 1201 ## CHECK: successors "<<BSplit1:B\d+>>" 1202 1203 ## CHECK: name "<<BTry:B\d+>>" 1204 ## CHECK: predecessors "<<BEnterTry:B\d+>>" 1205 ## CHECK: successors "<<BExitTry:B\d+>>" 1206 ## CHECK: Div 1207 1208 ## CHECK: name "<<BCatch:B\d+>>" 1209 ## CHECK: predecessors "<<BEnterTry>>" "<<BExitTry>>" 1210 ## CHECK: successors "<<BEnterTry>>" 1211 ## CHECK: flags "catch_block" 1212 1213 ## CHECK: name "<<BEnterTry>>" 1214 ## CHECK: predecessors "<<BSplit1>>" 1215 ## CHECK: successors "<<BTry>>" 1216 ## CHECK: xhandlers "<<BCatch>>" 1217 ## CHECK: TryBoundary kind:entry 1218 1219 ## CHECK: name "<<BExitTry>>" 1220 ## CHECK: predecessors "<<BTry>>" 1221 ## CHECK: successors "<<BSplit2:B\d+>>" 1222 ## CHECK: xhandlers "<<BCatch>>" 1223 ## CHECK: TryBoundary kind:exit 1224 1225 ## CHECK: name "<<BSplit1>>" 1226 ## CHECK: predecessors "B0" 1227 ## CHECK: successors "<<BEnterTry>>" 1228 ## CHECK: Goto 1229 1230 ## CHECK: name "<<BSplit2>>" 1231 ## CHECK: predecessors "<<BExitTry>>" 1232 ## CHECK: successors "<<BEnterTry>>" 1233 ## CHECK: Goto 1234 1235 .method public static testTryInLoop(II)I 1236 .registers 3 1237 1238 :try_start 1239 div-int/2addr p0, p1 1240 goto :try_start 1241 :try_end 1242 .catchall {:try_start .. :try_end} :catch_all 1243 1244 :catch_all 1245 goto :try_start 1246 .end method 1247 1248 # Test that a MOVE_RESULT instruction is placed into the same block as the 1249 # INVOKE it follows, even if there is a try boundary between them. 1250 1251 ## CHECK-START: int Builder.testMoveResult_Invoke(int, int, int) builder (after) 1252 ## CHECK-DAG: <<M1:i\d+>> IntConstant -1 1253 ## CHECK-DAG: <<Res:i\d+>> InvokeStaticOrDirect 1254 ## CHECK-DAG: <<Phi:i\d+>> Phi [<<Res>>,<<M1>>] 1255 ## CHECK-DAG: Return [<<Phi>>] 1256 1257 .method public static testMoveResult_Invoke(III)I 1258 .registers 3 1259 1260 :try_start 1261 invoke-static {p0, p1, p2}, LBuilder;->testCatchLoop(III)I 1262 :try_end 1263 .catchall {:try_start .. :try_end} :catch_all 1264 1265 move-result p0 1266 1267 :return 1268 return p0 1269 1270 :catch_all 1271 const/4 p0, -0x1 1272 goto :return 1273 .end method 1274 1275 # Test that a MOVE_RESULT instruction is placed into the same block as the 1276 # FILLED_NEW_ARRAY it follows, even if there is a try boundary between them. 1277 1278 ## CHECK-START: int[] Builder.testMoveResult_FilledNewArray(int, int, int) builder (after) 1279 ## CHECK-DAG: <<Arg1:i\d+>> ParameterValue 1280 ## CHECK-DAG: <<Arg2:i\d+>> ParameterValue 1281 ## CHECK-DAG: <<Arg3:i\d+>> ParameterValue 1282 ## CHECK-DAG: <<Null:l\d+>> NullConstant 1283 ## CHECK-DAG: <<Res:l\d+>> NewArray 1284 ## CHECK-DAG: ArraySet [<<Res>>,{{i\d+}},<<Arg1>>] 1285 ## CHECK-DAG: ArraySet [<<Res>>,{{i\d+}},<<Arg2>>] 1286 ## CHECK-DAG: ArraySet [<<Res>>,{{i\d+}},<<Arg3>>] 1287 ## CHECK-DAG: <<Phi:l\d+>> Phi [<<Res>>,<<Null>>] 1288 ## CHECK-DAG: Return [<<Phi>>] 1289 1290 .method public static testMoveResult_FilledNewArray(III)[I 1291 .registers 3 1292 1293 :try_start 1294 filled-new-array {p0, p1, p2}, [I 1295 :try_end 1296 .catchall {:try_start .. :try_end} :catch_all 1297 1298 move-result-object p0 1299 1300 :return 1301 return-object p0 1302 1303 :catch_all 1304 const/4 p0, 0x0 1305 goto :return 1306 .end method 1307 1308 # Test case for ReturnVoid inside a try block. Builder needs to move it outside 1309 # the try block so as to not split the ReturnVoid-Exit edge. 1310 # This invariant is enforced by GraphChecker. 1311 1312 .method public static testReturnVoidInTry(II)V 1313 .registers 2 1314 1315 :catch_all 1316 :try_start 1317 return-void 1318 :try_end 1319 .catchall {:try_start .. :try_end} :catch_all 1320 .end method 1321 1322 # Test case for Return inside a try block. Builder needs to move it outside the 1323 # try block so as to not split the Return-Exit edge. 1324 # This invariant is enforced by GraphChecker. 1325 1326 .method public static testReturnInTry(II)I 1327 .registers 2 1328 1329 :try_start 1330 div-int/2addr p0, p1 1331 return p0 1332 :try_end 1333 .catchall {:try_start .. :try_end} :catch_all 1334 1335 :catch_all 1336 const/4 v0, 0x0 1337 return v0 1338 .end method 1339 1340 # Test a (dead) try block which flows out of the method. The block will be 1341 # removed by DCE but needs to pass post-builder GraphChecker. 1342 1343 ## CHECK-START: int Builder.testDeadEndTry(int) builder (after) 1344 ## CHECK-NOT: TryBoundary is_exit:true 1345 1346 .method public static testDeadEndTry(I)I 1347 .registers 1 1348 1349 return p0 1350 1351 :catch_all 1352 nop 1353 1354 :try_start 1355 nop 1356 :try_end 1357 .catchall {:try_start .. :try_end} :catch_all 1358 .end method 1359 1360 # Test that a throw-catch loop on monitor-exit is eliminated. 1361 # Note that we do not test this until after DCE which merges trivially split blocks. 1362 1363 ## CHECK-START: int Builder.testSynchronized(java.lang.Object) dead_code_elimination (after) 1364 ## CHECK: flags "catch_block" 1365 ## CHECK-NOT: end_block 1366 ## CHECK: MonitorOperation kind:exit 1367 1368 .method public static testSynchronized(Ljava/lang/Object;)I 1369 .registers 2 1370 1371 monitor-enter p0 1372 1373 :try_start_9 1374 invoke-virtual {p0}, Ljava/lang/Object;->hashCode()I 1375 move-result v0 1376 1377 monitor-exit p0 1378 return v0 1379 1380 :catchall_11 1381 move-exception v0 1382 monitor-exit p0 1383 :try_end_15 1384 .catchall {:try_start_9 .. :try_end_15} :catchall_11 1385 1386 throw v0 1387 .end method 1388