1388 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			Smali
		
	
	
	
			
		
		
	
	
			1388 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			Smali
		
	
	
	
| # Copyright (C) 2015 The Android Open Source Project
 | |
| #
 | |
| # Licensed under the Apache License, Version 2.0 (the "License");
 | |
| # you may not use this file except in compliance with the License.
 | |
| # You may obtain a copy of the License at
 | |
| #
 | |
| #      http://www.apache.org/licenses/LICENSE-2.0
 | |
| #
 | |
| # Unless required by applicable law or agreed to in writing, software
 | |
| # distributed under the License is distributed on an "AS IS" BASIS,
 | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| # See the License for the specific language governing permissions and
 | |
| # limitations under the License.
 | |
| 
 | |
| .class public LBuilder;
 | |
| 
 | |
| .super Ljava/lang/Object;
 | |
| 
 | |
| # Basic test case with two try blocks and three catch handlers, one of which
 | |
| # is shared by the two tries.
 | |
| 
 | |
| ## CHECK-START: int Builder.testMultipleTryCatch(int, int, int) builder (after)
 | |
| 
 | |
| ## CHECK:      name             "B0"
 | |
| ## CHECK:      successors       "<<BEnterTry1:B\d+>>"
 | |
| ## CHECK-DAG:  <<Minus1:i\d+>>  IntConstant -1
 | |
| ## CHECK-DAG:  <<Minus2:i\d+>>  IntConstant -2
 | |
| ## CHECK-DAG:  <<Minus3:i\d+>>  IntConstant -3
 | |
| 
 | |
| ## CHECK:  name             "<<BTry1:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>"
 | |
| ## CHECK:  successors       "<<BExitTry1:B\d+>>"
 | |
| ## CHECK:  DivZeroCheck
 | |
| 
 | |
| ## CHECK:  name             "<<BAdd:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry1>>"
 | |
| ## CHECK:  successors       "<<BEnterTry2:B\d+>>"
 | |
| ## CHECK:  Add
 | |
| 
 | |
| ## CHECK:  name             "<<BTry2:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry2>>"
 | |
| ## CHECK:  successors       "<<BExitTry2:B\d+>>"
 | |
| ## CHECK:  DivZeroCheck
 | |
| ## CHECK:  <<Div:i\d+>> Div
 | |
| 
 | |
| ## CHECK:  name             "<<BAfterTry2:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn:B\d+>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BReturn>>"
 | |
| ## CHECK:  predecessors     "<<BAfterTry2>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>" "<<BCatch3:B\d+>>"
 | |
| ## CHECK:  Phi [<<Div>>,<<Minus1>>,<<Minus2>>,<<Minus3>>]
 | |
| ## CHECK:  Return
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch1>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>" "<<BExitTry1>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch2>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry2>>" "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch3>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry1>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BTry1>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch1>>" "<<BCatch3>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry2>>"
 | |
| ## CHECK:  predecessors     "<<BAdd>>"
 | |
| ## CHECK:  successors       "<<BTry2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch2>>" "<<BCatch3>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry1>>"
 | |
| ## CHECK:  predecessors     "<<BTry1>>"
 | |
| ## CHECK:  successors       "<<BAdd>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch1>>" "<<BCatch3>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry2>>"
 | |
| ## CHECK:  predecessors     "<<BTry2>>"
 | |
| ## CHECK:  successors       "<<BAfterTry2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch2>>" "<<BCatch3>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| .method public static testMultipleTryCatch(III)I
 | |
|     .registers 3
 | |
| 
 | |
|     :try_start_1
 | |
|     div-int/2addr p0, p1
 | |
|     :try_end_1
 | |
|     .catch Ljava/lang/ArithmeticException; {:try_start_1 .. :try_end_1} :catch_arith
 | |
|     .catchall {:try_start_1 .. :try_end_1} :catch_other
 | |
| 
 | |
|     add-int/2addr p0, p0
 | |
| 
 | |
|     :try_start_2
 | |
|     div-int/2addr p0, p2
 | |
|     :try_end_2
 | |
|     .catch Ljava/lang/OutOfMemoryError; {:try_start_2 .. :try_end_2} :catch_mem
 | |
|     .catchall {:try_start_2 .. :try_end_2} :catch_other
 | |
| 
 | |
|     nop
 | |
| 
 | |
|     :return
 | |
|     return p0
 | |
| 
 | |
|     :catch_arith
 | |
|     const/4 p0, -0x1
 | |
|     goto :return
 | |
| 
 | |
|     :catch_mem
 | |
|     const/4 p0, -0x2
 | |
|     goto :return
 | |
| 
 | |
|     :catch_other
 | |
|     const/4 p0, -0x3
 | |
|     goto :return
 | |
| .end method
 | |
| 
 | |
| # Tests try-entry block when there are multiple entry points into the try block.
 | |
| 
 | |
| ## CHECK-START: int Builder.testMultipleEntries(int, int, int, int) builder (after)
 | |
| 
 | |
| ## CHECK:  name             "B0"
 | |
| ## CHECK:  successors       "<<BIf:B\d+>>"
 | |
| ## CHECK:  <<Minus1:i\d+>>  IntConstant -1
 | |
| 
 | |
| ## CHECK:  name             "<<BIf>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BSplit1:B\d+>>" "<<BThen:B\d+>>"
 | |
| ## CHECK:  If
 | |
| 
 | |
| ## CHECK:  name             "<<BThen>>"
 | |
| ## CHECK:  predecessors     "<<BIf>>"
 | |
| ## CHECK:  successors       "<<BEnterTry1:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BTry1:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>"
 | |
| ## CHECK:  successors       "<<BExitTry1:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BTry2:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry2:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExitTry2:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BReturn:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BSplit3:B\d+>>" "<<BCatch:B\d+>>"
 | |
| ## CHECK:  Return
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry1>>"
 | |
| ## CHECK:  predecessors     "<<BThen>>"
 | |
| ## CHECK:  successors       "<<BTry1>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry2>>"
 | |
| ## CHECK:  predecessors     "<<BSplit1>>" "<<BSplit2:B\d+>>"
 | |
| ## CHECK:  successors       "<<BTry2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry1>>"
 | |
| ## CHECK:  predecessors     "<<BTry1>>"
 | |
| ## CHECK:  successors       "<<BSplit2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry2>>"
 | |
| ## CHECK:  predecessors     "<<BTry2>>"
 | |
| ## CHECK:  successors       "<<BSplit3>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit1>>"
 | |
| ## CHECK:  predecessors     "<<BIf>>"
 | |
| ## CHECK:  successors       "<<BEnterTry2>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit2>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry1>>"
 | |
| ## CHECK:  successors       "<<BEnterTry2>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit3>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| .method public static testMultipleEntries(IIII)I
 | |
|     .registers 4
 | |
| 
 | |
|     if-eqz p2, :else
 | |
| 
 | |
|     div-int/2addr p0, p1
 | |
| 
 | |
|     :try_start
 | |
|     div-int/2addr p0, p2
 | |
| 
 | |
|     :else
 | |
|     div-int/2addr p0, p3
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| 
 | |
|     :return
 | |
|     return p0
 | |
| 
 | |
|     :catch_all
 | |
|     const/4 p0, -0x1
 | |
|     goto :return
 | |
| 
 | |
| .end method
 | |
| 
 | |
| # Test that multiple try-exit blocks are generated if (normal) control flow can
 | |
| # jump out of the try block at multiple points.
 | |
| 
 | |
| ## CHECK-START: int Builder.testMultipleExits(int, int) builder (after)
 | |
| 
 | |
| ## CHECK:      name             "B0"
 | |
| ## CHECK:      successors       "<<BEnterTry:B\d+>>"
 | |
| ## CHECK-DAG:  <<Minus1:i\d+>>  IntConstant -1
 | |
| ## CHECK-DAG:  <<Minus2:i\d+>>  IntConstant -2
 | |
| 
 | |
| ## CHECK:  name             "<<BTry:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry>>"
 | |
| ## CHECK:  successors       "<<BExitTry1:B\d+>>" "<<BExitTry2:B\d+>>"
 | |
| ## CHECK:  <<Div:i\d+>> Div
 | |
| ## CHECK:  If
 | |
| 
 | |
| ## CHECK:  name             "<<BReturn:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BSplit:B\d+>>" "<<BThen:B\d+>>" "<<BCatch:B\d+>>"
 | |
| ## CHECK:  Phi [<<Div>>,<<Minus1>>,<<Minus2>>]
 | |
| ## CHECK:  Return
 | |
| 
 | |
| ## CHECK:  name             "<<BThen>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry1>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry>>" "<<BExitTry1>>" "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BTry>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry1>>"
 | |
| ## CHECK:  predecessors     "<<BTry>>"
 | |
| ## CHECK:  successors       "<<BThen>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry2>>"
 | |
| ## CHECK:  predecessors     "<<BTry>>"
 | |
| ## CHECK:  successors       "<<BSplit>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| .method public static testMultipleExits(II)I
 | |
|     .registers 2
 | |
| 
 | |
|     :try_start
 | |
|     div-int/2addr p0, p1
 | |
|     if-eqz p0, :then
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| 
 | |
|     :return
 | |
|     return p0
 | |
| 
 | |
|     :then
 | |
|     const/4 p0, -0x1
 | |
|     goto :return
 | |
| 
 | |
|     :catch_all
 | |
|     const/4 p0, -0x2
 | |
|     goto :return
 | |
| .end method
 | |
| 
 | |
| # Test that only one TryBoundary is inserted when an edge connects two different
 | |
| # try ranges.
 | |
| 
 | |
| ## CHECK-START: int Builder.testSharedBoundary(int, int, int) builder (after)
 | |
| 
 | |
| ## CHECK:      name             "B0"
 | |
| ## CHECK:      successors       "<<BEnter1:B\d+>>"
 | |
| ## CHECK-DAG:  <<Minus1:i\d+>>  IntConstant -1
 | |
| ## CHECK-DAG:  <<Minus2:i\d+>>  IntConstant -2
 | |
| 
 | |
| ## CHECK:  name             "<<BTry1:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnter1>>"
 | |
| ## CHECK:  successors       "<<BExit1:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BTry2:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnter2:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExit2:B\d+>>"
 | |
| ## CHECK:  <<Div:i\d+>> Div
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BReturn:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BSplit:B\d+>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>"
 | |
| ## CHECK:  Phi [<<Div>>,<<Minus1>>,<<Minus2>>]
 | |
| ## CHECK:  Return
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch1>>"
 | |
| ## CHECK:  predecessors     "<<BEnter1>>" "<<BExit1>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch2>>"
 | |
| ## CHECK:  predecessors     "<<BEnter2>>" "<<BExit2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BEnter1>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BTry1>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch1>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BEnter2>>"
 | |
| ## CHECK:  predecessors     "<<BExit1>>"
 | |
| ## CHECK:  successors       "<<BTry2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch2>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExit1>>"
 | |
| ## CHECK:  predecessors     "<<BTry1>>"
 | |
| ## CHECK:  successors       "<<BEnter2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch1>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BExit2>>"
 | |
| ## CHECK:  predecessors     "<<BTry2>>"
 | |
| ## CHECK:  successors       "<<BSplit>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch2>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit>>"
 | |
| ## CHECK:  predecessors     "<<BExit2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| .method public static testSharedBoundary(III)I
 | |
|     .registers 3
 | |
| 
 | |
|     :try_start_1
 | |
|     div-int/2addr p0, p1
 | |
|     :try_end_1
 | |
|     .catchall {:try_start_1 .. :try_end_1} :catch_all_1
 | |
| 
 | |
|     :try_start_2
 | |
|     div-int/2addr p0, p2
 | |
|     :try_end_2
 | |
|     .catchall {:try_start_2 .. :try_end_2} :catch_all_2
 | |
| 
 | |
|     :return
 | |
|     return p0
 | |
| 
 | |
|     :catch_all_1
 | |
|     const/4 p0, -0x1
 | |
|     goto :return
 | |
| 
 | |
|     :catch_all_2
 | |
|     const/4 p0, -0x2
 | |
|     goto :return
 | |
| .end method
 | |
| 
 | |
| # Same as previous test, only the blocks are processed in the opposite order.
 | |
| 
 | |
| ## CHECK-START: int Builder.testSharedBoundary_Reverse(int, int, int) builder (after)
 | |
| 
 | |
| ## CHECK:      name             "B0"
 | |
| ## CHECK:      successors       "<<BGoto:B\d+>>"
 | |
| ## CHECK-DAG:  <<Minus1:i\d+>>  IntConstant -1
 | |
| ## CHECK-DAG:  <<Minus2:i\d+>>  IntConstant -2
 | |
| 
 | |
| ## CHECK:  name             "<<BGoto>>"
 | |
| ## CHECK:  successors       "<<BEnter2:B\d+>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BTry1:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnter1:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExit1:B\d+>>"
 | |
| ## CHECK:  <<Div:i\d+>> Div
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BTry2:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnter2>>"
 | |
| ## CHECK:  successors       "<<BExit2:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BReturn:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BSplit:B\d+>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>"
 | |
| ## CHECK:  Phi [<<Div>>,<<Minus1>>,<<Minus2>>]
 | |
| ## CHECK:  Return
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch1>>"
 | |
| ## CHECK:  predecessors     "<<BEnter1>>" "<<BExit1>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch2>>"
 | |
| ## CHECK:  predecessors     "<<BEnter2>>" "<<BExit2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BEnter1>>"
 | |
| ## CHECK:  predecessors     "<<BExit2>>"
 | |
| ## CHECK:  successors       "<<BTry1>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch1>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BEnter2>>"
 | |
| ## CHECK:  predecessors     "<<BGoto>>"
 | |
| ## CHECK:  successors       "<<BTry2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch2>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExit1>>"
 | |
| ## CHECK:  predecessors     "<<BTry1>>"
 | |
| ## CHECK:  successors       "<<BSplit>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch1>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BExit2>>"
 | |
| ## CHECK:  predecessors     "<<BTry2>>"
 | |
| ## CHECK:  successors       "<<BEnter1>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch2>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit>>"
 | |
| ## CHECK:  predecessors     "<<BExit1>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| .method public static testSharedBoundary_Reverse(III)I
 | |
|     .registers 3
 | |
| 
 | |
|     goto :try_start_2
 | |
| 
 | |
|     :try_start_1
 | |
|     div-int/2addr p0, p1
 | |
|     goto :return
 | |
|     :try_end_1
 | |
|     .catchall {:try_start_1 .. :try_end_1} :catch_all_1
 | |
| 
 | |
|     :try_start_2
 | |
|     div-int/2addr p0, p2
 | |
|     goto :try_start_1
 | |
|     :try_end_2
 | |
|     .catchall {:try_start_2 .. :try_end_2} :catch_all_2
 | |
| 
 | |
|     :return
 | |
|     return p0
 | |
| 
 | |
|     :catch_all_1
 | |
|     const/4 p0, -0x1
 | |
|     goto :return
 | |
| 
 | |
|     :catch_all_2
 | |
|     const/4 p0, -0x2
 | |
|     goto :return
 | |
| .end method
 | |
| 
 | |
| # Test that nested tries are split into non-overlapping blocks and TryBoundary
 | |
| # blocks are correctly created between them.
 | |
| 
 | |
| ## CHECK-START: int Builder.testNestedTry(int, int, int, int) builder (after)
 | |
| 
 | |
| ## CHECK:      name             "B0"
 | |
| ## CHECK-DAG:  <<Minus1:i\d+>>  IntConstant -1
 | |
| ## CHECK-DAG:  <<Minus2:i\d+>>  IntConstant -2
 | |
| 
 | |
| ## CHECK:  name             "<<BTry1:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnter1:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExit1:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BTry2:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnter2:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExit2:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BTry3:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnter3:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExit3:B\d+>>"
 | |
| ## CHECK:  <<Div:i\d+>> Div
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BReturn:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BSplit:B\d+>>" "<<BCatchArith:B\d+>>" "<<BCatchAll:B\d+>>"
 | |
| ## CHECK:  Phi [<<Div>>,<<Minus1>>,<<Minus2>>]
 | |
| ## CHECK:  Return
 | |
| 
 | |
| ## CHECK:  name             "<<BCatchArith>>"
 | |
| ## CHECK:  predecessors     "<<BEnter2>>" "<<BExit2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BCatchAll>>"
 | |
| ## CHECK:  predecessors     "<<BEnter1>>" "<<BEnter2>>" "<<BEnter3>>" "<<BExit1>>" "<<BExit2>>" "<<BExit3>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BEnter1>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BTry1>>"
 | |
| ## CHECK:  xhandlers        "<<BCatchAll>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BEnter2>>"
 | |
| ## CHECK:  predecessors     "<<BExit1>>"
 | |
| ## CHECK:  successors       "<<BTry2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatchArith>>" "<<BCatchAll>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BEnter3>>"
 | |
| ## CHECK:  predecessors     "<<BExit2>>"
 | |
| ## CHECK:  successors       "<<BTry3>>"
 | |
| ## CHECK:  xhandlers        "<<BCatchAll>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExit1>>"
 | |
| ## CHECK:  predecessors     "<<BTry1>>"
 | |
| ## CHECK:  successors       "<<BEnter2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatchAll>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BExit2>>"
 | |
| ## CHECK:  predecessors     "<<BTry2>>"
 | |
| ## CHECK:  successors       "<<BEnter3>>"
 | |
| ## CHECK:  xhandlers        "<<BCatchArith>>" "<<BCatchAll>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BExit3>>"
 | |
| ## CHECK:  predecessors     "<<BTry3>>"
 | |
| ## CHECK:  successors       "<<BSplit>>"
 | |
| ## CHECK:  xhandlers        "<<BCatchAll>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit>>"
 | |
| ## CHECK:  predecessors     "<<BExit3>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| .method public static testNestedTry(IIII)I
 | |
|     .registers 4
 | |
| 
 | |
|     :try_start_1
 | |
|     div-int/2addr p0, p1
 | |
| 
 | |
|     :try_start_2
 | |
|     div-int/2addr p0, p2
 | |
|     :try_end_2
 | |
|     .catch Ljava/lang/ArithmeticException; {:try_start_2 .. :try_end_2} :catch_arith
 | |
| 
 | |
|     div-int/2addr p0, p3
 | |
|     :try_end_1
 | |
|     .catchall {:try_start_1 .. :try_end_1} :catch_all
 | |
| 
 | |
|     :return
 | |
|     return p0
 | |
| 
 | |
|     :catch_arith
 | |
|     const/4 p0, -0x1
 | |
|     goto :return
 | |
| 
 | |
|     :catch_all
 | |
|     const/4 p0, -0x2
 | |
|     goto :return
 | |
| .end method
 | |
| 
 | |
| # Test control flow that enters a try block, leaves it and returns again.
 | |
| 
 | |
| ## CHECK-START: int Builder.testIncontinuousTry(int, int, int, int) builder (after)
 | |
| 
 | |
| ## CHECK:  name             "B0"
 | |
| ## CHECK:  <<Minus1:i\d+>>  IntConstant -1
 | |
| 
 | |
| ## CHECK:  name             "<<BTry1:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExitTry1:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BTry2:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry2:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExitTry2:B\d+>>"
 | |
| ## CHECK:  <<Div:i\d+>> Div
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BReturn:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BSplit:B\d+>>" "<<BCatch:B\d+>>"
 | |
| ## CHECK:  Phi [<<Div>>,<<Minus1>>]
 | |
| ## CHECK:  Return
 | |
| 
 | |
| ## CHECK:  name             "<<BOutside:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry1>>"
 | |
| ## CHECK:  successors       "<<BEnterTry2>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry1>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BTry1>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry2>>"
 | |
| ## CHECK:  predecessors     "<<BOutside>>"
 | |
| ## CHECK:  successors       "<<BTry2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry1>>"
 | |
| ## CHECK:  predecessors     "<<BTry1>>"
 | |
| ## CHECK:  successors       "<<BOutside>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry2>>"
 | |
| ## CHECK:  predecessors     "<<BTry2>>"
 | |
| ## CHECK:  successors       "<<BSplit>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| .method public static testIncontinuousTry(IIII)I
 | |
|     .registers 4
 | |
| 
 | |
|     :try_start
 | |
|     div-int/2addr p0, p1
 | |
|     goto :outside
 | |
| 
 | |
|     :inside
 | |
|     div-int/2addr p0, p3
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| 
 | |
|     :return
 | |
|     return p0
 | |
| 
 | |
|     :outside
 | |
|     div-int/2addr p0, p2
 | |
|     goto :inside
 | |
| 
 | |
|     :catch_all
 | |
|     const/4 p0, -0x1
 | |
|     goto :return
 | |
| .end method
 | |
| 
 | |
| ## CHECK-START: int Builder.testSwitchTryEnter(int, int, int, int) builder (after)
 | |
| 
 | |
| ## CHECK:  name             "B0"
 | |
| ## CHECK:  successors       "<<BPSwitch0:B\d+>>"
 | |
| 
 | |
| ## CHECK:  name             "<<BPSwitch0>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BSplit1:B\d+>>" "<<BPSwitch1:B\d+>>"
 | |
| ## CHECK:  If
 | |
| 
 | |
| ## CHECK:  name             "<<BPSwitch1>>"
 | |
| ## CHECK:  predecessors     "<<BPSwitch0>>"
 | |
| ## CHECK:  successors       "<<BSplit2:B\d+>>" "<<BEnterTry1:B\d+>>"
 | |
| ## CHECK:  If
 | |
| 
 | |
| ## CHECK:  name             "<<BTry1:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>"
 | |
| ## CHECK:  successors       "<<BExitTry1:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BTry2:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry2:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExitTry2:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BOutside:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BSplit2>>" "<<BSplit4:B\d+>>"
 | |
| ## CHECK:  successors       "<<BReturn:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BReturn>>"
 | |
| ## CHECK:  predecessors     "<<BOutside>>" "<<BCatch:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExit:B\d+>>"
 | |
| ## CHECK:  Return
 | |
| 
 | |
| ## CHECK:  name             "<<BExit>>"
 | |
| ## CHECK:  Exit
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry1>>"
 | |
| ## CHECK:  predecessors     "<<BPSwitch1>>"
 | |
| ## CHECK:  successors       "<<BTry1>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry2>>"
 | |
| ## CHECK:  predecessors     "<<BSplit1>>" "<<BSplit3:B\d+>>"
 | |
| ## CHECK:  successors       "<<BTry2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry1>>"
 | |
| ## CHECK:  predecessors     "<<BTry1>>"
 | |
| ## CHECK:  successors       "<<BSplit3>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry2>>"
 | |
| ## CHECK:  predecessors     "<<BTry2>>"
 | |
| ## CHECK:  successors       "<<BSplit4>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit1>>"
 | |
| ## CHECK:  predecessors     "<<BPSwitch0>>"
 | |
| ## CHECK:  successors       "<<BEnterTry2>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit2>>"
 | |
| ## CHECK:  predecessors     "<<BPSwitch1>>"
 | |
| ## CHECK:  successors       "<<BOutside>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit3>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry1>>"
 | |
| ## CHECK:  successors       "<<BEnterTry2>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit4>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BOutside>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| .method public static testSwitchTryEnter(IIII)I
 | |
|     .registers 4
 | |
| 
 | |
|     packed-switch p0, :pswitch_data
 | |
| 
 | |
|     :try_start
 | |
|     div-int/2addr p0, p1
 | |
| 
 | |
|     :pswitch1
 | |
|     div-int/2addr p0, p2
 | |
|     goto :pswitch2
 | |
| 
 | |
|     :pswitch_data
 | |
|     .packed-switch 0x0
 | |
|         :pswitch1
 | |
|         :pswitch2
 | |
|     .end packed-switch
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| 
 | |
|     :pswitch2
 | |
|     div-int/2addr p0, p3
 | |
| 
 | |
|     :catch_all
 | |
|     return p0
 | |
| .end method
 | |
| 
 | |
| ## CHECK-START: int Builder.testSwitchTryExit(int, int, int, int) builder (after)
 | |
| 
 | |
| ## CHECK:  name             "B0"
 | |
| ## CHECK:  successors       "<<BEnterTry1:B\d+>>"
 | |
| 
 | |
| ## CHECK:  name             "<<BPSwitch0:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>"
 | |
| ## CHECK:  successors       "<<BSplit1:B\d+>>" "<<BExitTry1:B\d+>>"
 | |
| ## CHECK:  If
 | |
| 
 | |
| ## CHECK:  name             "<<BPSwitch1:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry1>>"
 | |
| ## CHECK:  successors       "<<BSplit2:B\d+>>" "<<BEnterTry2:B\d+>>"
 | |
| ## CHECK:  If
 | |
| 
 | |
| ## CHECK:  name             "<<BTry1:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry2>>"
 | |
| ## CHECK:  successors       "<<BTry2:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BTry2>>"
 | |
| ## CHECK:  predecessors     "<<BSplit1>>" "<<BTry1>>"
 | |
| ## CHECK:  successors       "<<BExitTry2:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BOutside:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BSplit2>>" "<<BSplit3:B\d+>>"
 | |
| ## CHECK:  successors       "<<BReturn:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BReturn>>"
 | |
| ## CHECK:  predecessors     "<<BOutside>>" "<<BCatch:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExit:B\d+>>"
 | |
| ## CHECK:  Return
 | |
| 
 | |
| ## CHECK:  name             "<<BExit>>"
 | |
| ## CHECK:  Exit
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry1>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BPSwitch0>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry2>>"
 | |
| ## CHECK:  predecessors     "<<BPSwitch1>>"
 | |
| ## CHECK:  successors       "<<BTry1>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry1>>"
 | |
| ## CHECK:  predecessors     "<<BPSwitch0>>"
 | |
| ## CHECK:  successors       "<<BPSwitch1>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry2>>"
 | |
| ## CHECK:  predecessors     "<<BTry2>>"
 | |
| ## CHECK:  successors       "<<BSplit3>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit1>>"
 | |
| ## CHECK:  predecessors     "<<BPSwitch0>>"
 | |
| ## CHECK:  successors       "<<BTry2>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit2>>"
 | |
| ## CHECK:  predecessors     "<<BPSwitch1>>"
 | |
| ## CHECK:  successors       "<<BOutside>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit3>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BOutside>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| .method public static testSwitchTryExit(IIII)I
 | |
|     .registers 4
 | |
| 
 | |
|     :try_start
 | |
|     div-int/2addr p0, p1
 | |
|     packed-switch p0, :pswitch_data
 | |
| 
 | |
|     div-int/2addr p0, p1
 | |
| 
 | |
|     :pswitch1
 | |
|     div-int/2addr p0, p2
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| 
 | |
|     :pswitch2
 | |
|     div-int/2addr p0, p3
 | |
| 
 | |
|     :catch_all
 | |
|     return p0
 | |
| 
 | |
|     :pswitch_data
 | |
|     .packed-switch 0x0
 | |
|         :pswitch1
 | |
|         :pswitch2
 | |
|     .end packed-switch
 | |
| .end method
 | |
| 
 | |
| # Test that a TryBoundary is inserted between a Throw instruction and the exit
 | |
| # block when covered by a try range.
 | |
| 
 | |
| ## CHECK-START: int Builder.testThrow(java.lang.Exception) builder (after)
 | |
| 
 | |
| ## CHECK:  name             "B0"
 | |
| ## CHECK:  successors       "<<BEnterTry:B\d+>>"
 | |
| ## CHECK:  <<Minus1:i\d+>>  IntConstant -1
 | |
| 
 | |
| ## CHECK:  name             "<<BTry:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry>>"
 | |
| ## CHECK:  successors       "<<BExitTry:B\d+>>"
 | |
| ## CHECK:  Throw
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry>>" "<<BExitTry>>"
 | |
| ## CHECK:  successors       "<<BExit:B\d+>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Return [<<Minus1>>]
 | |
| 
 | |
| ## CHECK:  name             "<<BExit>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry>>" "<<BCatch>>"
 | |
| ## CHECK:  Exit
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BTry>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry>>"
 | |
| ## CHECK:  predecessors     "<<BTry>>"
 | |
| ## CHECK:  successors       "<<BExit>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| .method public static testThrow(Ljava/lang/Exception;)I
 | |
|     .registers 2
 | |
| 
 | |
|     :try_start
 | |
|     throw p0
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| 
 | |
|     :catch_all
 | |
|     const/4 v0, -0x1
 | |
|     return v0
 | |
| .end method
 | |
| 
 | |
| # Test graph with a throw/catch loop.
 | |
| 
 | |
| ## CHECK-START: int Builder.testCatchLoop(int, int, int) builder (after)
 | |
| 
 | |
| ## CHECK:  name             "B0"
 | |
| ## CHECK:  successors       "<<BSplit:B\d+>>"
 | |
| 
 | |
| ## CHECK:  name             "<<BTry:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExitTry:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BReturn:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry>>"
 | |
| ## CHECK:  successors       "<<BExit:B\d+>>"
 | |
| ## CHECK:  Return
 | |
| 
 | |
| ## CHECK:  name             "<<BExit>>"
 | |
| ## CHECK:  predecessors     "<<BReturn>>"
 | |
| ## CHECK:  Exit
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry>>" "<<BExitTry>>"
 | |
| ## CHECK:  successors       "<<BEnterTry>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry>>"
 | |
| ## CHECK:  predecessors     "<<BSplit>>" "<<BCatch>>"
 | |
| ## CHECK:  successors       "<<BTry>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry>>"
 | |
| ## CHECK:  predecessors     "<<BTry>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BEnterTry>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| .method public static testCatchLoop(III)I
 | |
|     .registers 4
 | |
| 
 | |
|     :try_start
 | |
|     :catch_all
 | |
|     div-int/2addr p0, p2
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| 
 | |
|     :return
 | |
|     return p0
 | |
| .end method
 | |
| 
 | |
| # Test that handler edges are not split. In this scenario, the catch block is
 | |
| # only the handler of the try block.
 | |
| 
 | |
| ## CHECK-START: int Builder.testHandlerEdge1(int, int, int) builder (after)
 | |
| 
 | |
| ## CHECK:  name             "B0"
 | |
| ## CHECK:  successors       "<<BEnterTry1:B\d+>>"
 | |
| 
 | |
| ## CHECK:  name             "<<BTry1:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>"
 | |
| ## CHECK:  successors       "<<BExitTry1:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BTry2:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry2:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExitTry2:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BReturn:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BExit:B\d+>>"
 | |
| ## CHECK:  Return
 | |
| 
 | |
| ## CHECK:  name             "<<BExit>>"
 | |
| ## CHECK:  predecessors     "<<BReturn>>"
 | |
| ## CHECK:  Exit
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BEnterTry2>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry1>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BTry1>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry2>>"
 | |
| ## CHECK:  predecessors     "<<BSplit:B\d+>>" "<<BCatch>>"
 | |
| ## CHECK:  successors       "<<BTry2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry1>>"
 | |
| ## CHECK:  predecessors     "<<BTry1>>"
 | |
| ## CHECK:  successors       "<<BSplit>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry2>>"
 | |
| ## CHECK:  predecessors     "<<BTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry1>>"
 | |
| ## CHECK:  successors       "<<BEnterTry2>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| .method public static testHandlerEdge1(III)I
 | |
|     .registers 4
 | |
| 
 | |
|     :try_start
 | |
|     div-int/2addr p0, p1
 | |
| 
 | |
|     :catch_all
 | |
|     div-int/2addr p0, p2
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| 
 | |
|     return p0
 | |
| .end method
 | |
| 
 | |
| # Test that handler edges are not split. In this scenario, the catch block is
 | |
| # the handler and also the successor of the try block.
 | |
| 
 | |
| ## CHECK-START: int Builder.testHandlerEdge2(int, int, int) builder (after)
 | |
| 
 | |
| ## CHECK:  name             "B0"
 | |
| ## CHECK:  successors       "<<BSplit1:B\d+>>"
 | |
| 
 | |
| ## CHECK:  name             "<<BTry1:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExitTry1:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BTry2:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry2:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExitTry2:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BReturn:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BExit:B\d+>>"
 | |
| ## CHECK:  Return
 | |
| 
 | |
| ## CHECK:  name             "<<BExit>>"
 | |
| ## CHECK:  Exit
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch2:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry1>>" "<<BExitTry1>>"
 | |
| ## CHECK:  successors       "<<BEnterTry2>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch1:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry2>>" "<<BExitTry2>>"
 | |
| ## CHECK:  successors       "<<BEnterTry1>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry1>>"
 | |
| ## CHECK:  predecessors     "<<BSplit1>>" "<<BCatch1>>"
 | |
| ## CHECK:  successors       "<<BTry1>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch2>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry2>>"
 | |
| ## CHECK:  predecessors     "<<BSplit2:B\d+>>" "<<BCatch2>>"
 | |
| ## CHECK:  successors       "<<BTry2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch1>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry1>>"
 | |
| ## CHECK:  predecessors     "<<BTry1>>"
 | |
| ## CHECK:  successors       "<<BSplit2>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch2>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry2>>"
 | |
| ## CHECK:  predecessors     "<<BTry2>>"
 | |
| ## CHECK:  successors       "<<BReturn>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch1>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit1>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BEnterTry1>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit2>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry1>>"
 | |
| ## CHECK:  successors       "<<BEnterTry2>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| .method public static testHandlerEdge2(III)I
 | |
|     .registers 4
 | |
| 
 | |
|     :try_start_1
 | |
|     :catch_all_1
 | |
|     div-int/2addr p0, p1
 | |
|     :try_end_1
 | |
|     .catchall {:try_start_1 .. :try_end_1} :catch_all_2
 | |
| 
 | |
|     :try_start_2
 | |
|     :catch_all_2
 | |
|     div-int/2addr p0, p2
 | |
|     :try_end_2
 | |
|     .catchall {:try_start_2 .. :try_end_2} :catch_all_1
 | |
| 
 | |
|     return p0
 | |
| .end method
 | |
| 
 | |
| # Test graph with try/catch inside a loop.
 | |
| 
 | |
| ## CHECK-START: int Builder.testTryInLoop(int, int) builder (after)
 | |
| 
 | |
| ## CHECK:  name             "B0"
 | |
| ## CHECK:  successors       "<<BSplit1:B\d+>>"
 | |
| 
 | |
| ## CHECK:  name             "<<BTry:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry:B\d+>>"
 | |
| ## CHECK:  successors       "<<BExitTry:B\d+>>"
 | |
| ## CHECK:  Div
 | |
| 
 | |
| ## CHECK:  name             "<<BCatch:B\d+>>"
 | |
| ## CHECK:  predecessors     "<<BEnterTry>>" "<<BExitTry>>"
 | |
| ## CHECK:  successors       "<<BEnterTry>>"
 | |
| ## CHECK:  flags            "catch_block"
 | |
| 
 | |
| ## CHECK:  name             "<<BEnterTry>>"
 | |
| ## CHECK:  predecessors     "<<BSplit1>>"
 | |
| ## CHECK:  successors       "<<BTry>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:entry
 | |
| 
 | |
| ## CHECK:  name             "<<BExitTry>>"
 | |
| ## CHECK:  predecessors     "<<BTry>>"
 | |
| ## CHECK:  successors       "<<BSplit2:B\d+>>"
 | |
| ## CHECK:  xhandlers        "<<BCatch>>"
 | |
| ## CHECK:  TryBoundary      kind:exit
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit1>>"
 | |
| ## CHECK:  predecessors     "B0"
 | |
| ## CHECK:  successors       "<<BEnterTry>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| ## CHECK:  name             "<<BSplit2>>"
 | |
| ## CHECK:  predecessors     "<<BExitTry>>"
 | |
| ## CHECK:  successors       "<<BEnterTry>>"
 | |
| ## CHECK:  Goto
 | |
| 
 | |
| .method public static testTryInLoop(II)I
 | |
|     .registers 3
 | |
| 
 | |
|     :try_start
 | |
|     div-int/2addr p0, p1
 | |
|     goto :try_start
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| 
 | |
|     :catch_all
 | |
|     goto :try_start
 | |
| .end method
 | |
| 
 | |
| # Test that a MOVE_RESULT instruction is placed into the same block as the
 | |
| # INVOKE it follows, even if there is a try boundary between them.
 | |
| 
 | |
| ## CHECK-START: int Builder.testMoveResult_Invoke(int, int, int) builder (after)
 | |
| ## CHECK-DAG:     <<M1:i\d+>>  IntConstant -1
 | |
| ## CHECK-DAG:     <<Res:i\d+>> InvokeStaticOrDirect
 | |
| ## CHECK-DAG:     <<Phi:i\d+>> Phi [<<Res>>,<<M1>>]
 | |
| ## CHECK-DAG:                  Return [<<Phi>>]
 | |
| 
 | |
| .method public static testMoveResult_Invoke(III)I
 | |
|     .registers 3
 | |
| 
 | |
|     :try_start
 | |
|     invoke-static {p0, p1, p2}, LBuilder;->testCatchLoop(III)I
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| 
 | |
|     move-result p0
 | |
| 
 | |
|     :return
 | |
|     return p0
 | |
| 
 | |
|     :catch_all
 | |
|     const/4 p0, -0x1
 | |
|     goto :return
 | |
| .end method
 | |
| 
 | |
| # Test that a MOVE_RESULT instruction is placed into the same block as the
 | |
| # FILLED_NEW_ARRAY it follows, even if there is a try boundary between them.
 | |
| 
 | |
| ## CHECK-START: int[] Builder.testMoveResult_FilledNewArray(int, int, int) builder (after)
 | |
| ## CHECK-DAG:     <<Arg1:i\d+>> ParameterValue
 | |
| ## CHECK-DAG:     <<Arg2:i\d+>> ParameterValue
 | |
| ## CHECK-DAG:     <<Arg3:i\d+>> ParameterValue
 | |
| ## CHECK-DAG:     <<Null:l\d+>> NullConstant
 | |
| ## CHECK-DAG:     <<Res:l\d+>>  NewArray
 | |
| ## CHECK-DAG:                   ArraySet   [<<Res>>,{{i\d+}},<<Arg1>>]
 | |
| ## CHECK-DAG:                   ArraySet   [<<Res>>,{{i\d+}},<<Arg2>>]
 | |
| ## CHECK-DAG:                   ArraySet   [<<Res>>,{{i\d+}},<<Arg3>>]
 | |
| ## CHECK-DAG:     <<Phi:l\d+>>  Phi [<<Res>>,<<Null>>]
 | |
| ## CHECK-DAG:                   Return [<<Phi>>]
 | |
| 
 | |
| .method public static testMoveResult_FilledNewArray(III)[I
 | |
|     .registers 3
 | |
| 
 | |
|     :try_start
 | |
|     filled-new-array {p0, p1, p2}, [I
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| 
 | |
|     move-result-object p0
 | |
| 
 | |
|     :return
 | |
|     return-object p0
 | |
| 
 | |
|     :catch_all
 | |
|     const/4 p0, 0x0
 | |
|     goto :return
 | |
| .end method
 | |
| 
 | |
| # Test case for ReturnVoid inside a try block. Builder needs to move it outside
 | |
| # the try block so as to not split the ReturnVoid-Exit edge.
 | |
| # This invariant is enforced by GraphChecker.
 | |
| 
 | |
| .method public static testReturnVoidInTry(II)V
 | |
|     .registers 2
 | |
| 
 | |
|     :catch_all
 | |
|     :try_start
 | |
|     return-void
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| .end method
 | |
| 
 | |
| # Test case for Return inside a try block. Builder needs to move it outside the
 | |
| # try block so as to not split the Return-Exit edge.
 | |
| # This invariant is enforced by GraphChecker.
 | |
| 
 | |
| .method public static testReturnInTry(II)I
 | |
|     .registers 2
 | |
| 
 | |
|     :try_start
 | |
|     div-int/2addr p0, p1
 | |
|     return p0
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| 
 | |
|     :catch_all
 | |
|     const/4 v0, 0x0
 | |
|     return v0
 | |
| .end method
 | |
| 
 | |
| # Test a (dead) try block which flows out of the method. The block will be
 | |
| # removed by DCE but needs to pass post-builder GraphChecker.
 | |
| 
 | |
| ## CHECK-START: int Builder.testDeadEndTry(int) builder (after)
 | |
| ## CHECK-NOT:     TryBoundary is_exit:true
 | |
| 
 | |
| .method public static testDeadEndTry(I)I
 | |
|     .registers 1
 | |
| 
 | |
|     return p0
 | |
| 
 | |
|     :catch_all
 | |
|     nop
 | |
| 
 | |
|     :try_start
 | |
|     nop
 | |
|     :try_end
 | |
|     .catchall {:try_start .. :try_end} :catch_all
 | |
| .end method
 | |
| 
 | |
| # Test that a throw-catch loop on monitor-exit is eliminated.
 | |
| # Note that we do not test this until after DCE which merges trivially split blocks.
 | |
| 
 | |
| ## CHECK-START: int Builder.testSynchronized(java.lang.Object) dead_code_elimination$initial (after)
 | |
| ## CHECK:      flags "catch_block"
 | |
| ## CHECK-NOT:  end_block
 | |
| ## CHECK:      MonitorOperation kind:exit
 | |
| 
 | |
| .method public static testSynchronized(Ljava/lang/Object;)I
 | |
|   .registers 2
 | |
| 
 | |
|   monitor-enter p0
 | |
| 
 | |
|   :try_start_9
 | |
|   invoke-virtual {p0}, Ljava/lang/Object;->hashCode()I
 | |
|   move-result v0
 | |
| 
 | |
|   monitor-exit p0
 | |
|   return v0
 | |
| 
 | |
|   :catchall_11
 | |
|   move-exception v0
 | |
|   monitor-exit p0
 | |
|   :try_end_15
 | |
|   .catchall {:try_start_9 .. :try_end_15} :catchall_11
 | |
| 
 | |
|   throw v0
 | |
| .end method
 |