You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
626 lines
18 KiB
626 lines
18 KiB
# 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 LRuntime;
|
|
.super Ljava/lang/Object;
|
|
|
|
# The following tests all share the same structure, signature and return values:
|
|
# - foo(false, false): normal path, returns 42
|
|
# - foo(true, false): exceptional path #1, returns 3
|
|
# - foo(false, true): exceptional path #2, returns 8
|
|
# - foo(true, true): undefined
|
|
|
|
|
|
# Test register allocation of 32-bit core intervals crossing catch block positions.
|
|
|
|
## CHECK-START: int Runtime.testUseAfterCatch_int(boolean, boolean) register (after)
|
|
## CHECK-NOT: Phi is_catch_phi:true
|
|
|
|
.method public static testUseAfterCatch_int(ZZ)I
|
|
.registers 6
|
|
|
|
sget-object v0, LRuntime;->intArray:[I
|
|
const/4 v1, 0
|
|
aget v1, v0, v1
|
|
const/4 v2, 1
|
|
aget v2, v0, v2
|
|
const/4 v3, 2
|
|
aget v3, v0, v3
|
|
|
|
:try_start
|
|
invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end
|
|
.catchall {:try_start .. :try_end} :catch_all
|
|
|
|
return v3 # Normal path return.
|
|
|
|
:catch_all
|
|
if-eqz p0, :second_throw
|
|
return v1 # Exceptional path #1 return.
|
|
|
|
:second_throw
|
|
return v2 # Exceptional path #2 return.
|
|
.end method
|
|
|
|
|
|
# Test register allocation of 64-bit core intervals crossing catch block positions.
|
|
|
|
# The sum of the low and high 32 bits treated as integers is returned to prove
|
|
# that both vregs allocated correctly.
|
|
|
|
## CHECK-START: int Runtime.testUseAfterCatch_long(boolean, boolean) register (after)
|
|
## CHECK-NOT: Phi is_catch_phi:true
|
|
|
|
.method public static testUseAfterCatch_long(ZZ)I
|
|
.registers 10
|
|
|
|
sget-object v0, LRuntime;->longArray:[J
|
|
const/4 v1, 0
|
|
aget-wide v1, v0, v1
|
|
const/4 v3, 1
|
|
aget-wide v3, v0, v3
|
|
const/4 v5, 2
|
|
aget-wide v5, v0, v5
|
|
|
|
:try_start
|
|
invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end
|
|
.catchall {:try_start .. :try_end} :catch_all
|
|
|
|
const v0, 32
|
|
ushr-long v7, v5, v0
|
|
long-to-int v5, v5
|
|
long-to-int v7, v7
|
|
add-int/2addr v5, v7
|
|
return v5 # Normal path return.
|
|
|
|
:catch_all
|
|
const v0, 32
|
|
if-eqz p0, :second_throw
|
|
|
|
ushr-long v7, v1, v0
|
|
long-to-int v1, v1
|
|
long-to-int v7, v7
|
|
add-int/2addr v1, v7
|
|
return v1 # Exceptional path #1 return.
|
|
|
|
:second_throw
|
|
ushr-long v7, v3, v0
|
|
long-to-int v3, v3
|
|
long-to-int v7, v7
|
|
add-int/2addr v3, v7
|
|
return v3 # Exceptional path #2 return.
|
|
.end method
|
|
|
|
|
|
# Test register allocation of 32-bit floating-point intervals crossing catch block positions.
|
|
|
|
## CHECK-START: int Runtime.testUseAfterCatch_float(boolean, boolean) register (after)
|
|
## CHECK-NOT: Phi is_catch_phi:true
|
|
|
|
.method public static testUseAfterCatch_float(ZZ)I
|
|
.registers 6
|
|
|
|
sget-object v0, LRuntime;->floatArray:[F
|
|
const/4 v1, 0
|
|
aget v1, v0, v1
|
|
const/4 v2, 1
|
|
aget v2, v0, v2
|
|
const/4 v3, 2
|
|
aget v3, v0, v3
|
|
|
|
:try_start
|
|
invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end
|
|
.catchall {:try_start .. :try_end} :catch_all
|
|
|
|
float-to-int v3, v3
|
|
return v3 # Normal path return.
|
|
|
|
:catch_all
|
|
if-eqz p0, :second_throw
|
|
float-to-int v1, v1
|
|
return v1 # Exceptional path #1 return.
|
|
|
|
:second_throw
|
|
float-to-int v2, v2
|
|
return v2 # Exceptional path #2 return.
|
|
.end method
|
|
|
|
|
|
# Test register allocation of 64-bit floating-point intervals crossing catch block positions.
|
|
|
|
## CHECK-START: int Runtime.testUseAfterCatch_double(boolean, boolean) register (after)
|
|
## CHECK-NOT: Phi is_catch_phi:true
|
|
|
|
.method public static testUseAfterCatch_double(ZZ)I
|
|
.registers 10
|
|
|
|
sget-object v0, LRuntime;->doubleArray:[D
|
|
const/4 v1, 0
|
|
aget-wide v1, v0, v1
|
|
const/4 v3, 1
|
|
aget-wide v3, v0, v3
|
|
const/4 v5, 2
|
|
aget-wide v5, v0, v5
|
|
|
|
:try_start
|
|
invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end
|
|
.catchall {:try_start .. :try_end} :catch_all
|
|
|
|
double-to-int v5, v5
|
|
return v5 # Normal path return.
|
|
|
|
:catch_all
|
|
if-eqz p0, :second_throw
|
|
double-to-int v1, v1
|
|
return v1 # Exceptional path #1 return.
|
|
|
|
:second_throw
|
|
double-to-int v3, v3
|
|
return v3 # Exceptional path #2 return.
|
|
.end method
|
|
|
|
|
|
# Test catch-phi runtime support for constant values.
|
|
|
|
# Register v0 holds different constants at two throwing instructions. Runtime is
|
|
# expected to load them from stack map and copy to the catch phi's location.
|
|
|
|
## CHECK-START: int Runtime.testCatchPhi_const(boolean, boolean) register (after)
|
|
## CHECK-DAG: <<Const3:i\d+>> IntConstant 3
|
|
## CHECK-DAG: <<Const8:i\d+>> IntConstant 8
|
|
## CHECK-DAG: Phi [<<Const3>>,<<Const8>>] is_catch_phi:true
|
|
|
|
.method public static testCatchPhi_const(ZZ)I
|
|
.registers 3
|
|
|
|
:try_start
|
|
const v0, 3
|
|
invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
|
|
const v0, 8
|
|
invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end
|
|
.catchall {:try_start .. :try_end} :catch_all
|
|
|
|
const v0, 42
|
|
return v0 # Normal path return.
|
|
|
|
:catch_all
|
|
return v0 # Exceptional path #1/#2 return.
|
|
.end method
|
|
|
|
|
|
# Test catch-phi runtime support for 32-bit values stored in core registers.
|
|
|
|
# Register v0 holds different integer values at two throwing instructions.
|
|
# Runtime is expected to find their location in the stack map and copy the value
|
|
# to the location of the catch phi.
|
|
|
|
## CHECK-START: int Runtime.testCatchPhi_int(boolean, boolean) register (after)
|
|
## CHECK-DAG: <<Val1:i\d+>> ArrayGet
|
|
## CHECK-DAG: <<Val2:i\d+>> ArrayGet
|
|
## CHECK-DAG: Phi [<<Val1>>,<<Val2>>] is_catch_phi:true
|
|
|
|
.method public static testCatchPhi_int(ZZ)I
|
|
.registers 6
|
|
|
|
sget-object v0, LRuntime;->intArray:[I
|
|
const/4 v1, 0
|
|
aget v1, v0, v1
|
|
const/4 v2, 1
|
|
aget v2, v0, v2
|
|
const/4 v3, 2
|
|
aget v3, v0, v3
|
|
|
|
:try_start
|
|
move v0, v1 # Set catch phi value
|
|
invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
|
|
move v0, v2 # Set catch phi value
|
|
invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end
|
|
.catchall {:try_start .. :try_end} :catch_all
|
|
|
|
return v3 # Normal path return.
|
|
|
|
:catch_all
|
|
return v0 # Exceptional path #1/#2 return.
|
|
.end method
|
|
|
|
|
|
# Test catch-phi runtime support for 64-bit values stored in core registers.
|
|
|
|
# Register pair (v0, v1) holds different long values at two throwing instructions.
|
|
# Runtime is expected to find their location in the stack map and copy the value
|
|
# to the location of the catch phi. The sum of the low and high 32 bits treated
|
|
# as integers is returned to prove that both vregs were copied.
|
|
|
|
# Note: values will be spilled on x86 because of too few callee-save core registers.
|
|
|
|
## CHECK-START: int Runtime.testCatchPhi_long(boolean, boolean) register (after)
|
|
## CHECK-DAG: <<Val1:j\d+>> ArrayGet
|
|
## CHECK-DAG: <<Val2:j\d+>> ArrayGet
|
|
## CHECK-DAG: Phi [<<Val1>>,<<Val2>>] is_catch_phi:true
|
|
|
|
.method public static testCatchPhi_long(ZZ)I
|
|
.registers 10
|
|
|
|
sget-object v0, LRuntime;->longArray:[J
|
|
const/4 v2, 0
|
|
aget-wide v2, v0, v2
|
|
const/4 v4, 1
|
|
aget-wide v4, v0, v4
|
|
const/4 v6, 2
|
|
aget-wide v6, v0, v6
|
|
|
|
:try_start
|
|
move-wide v0, v2 # Set catch phi value
|
|
invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
|
|
move-wide v0, v4 # Set catch phi value
|
|
invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end
|
|
.catchall {:try_start .. :try_end} :catch_all
|
|
|
|
const v2, 32
|
|
ushr-long v2, v6, v2
|
|
long-to-int v2, v2
|
|
long-to-int v6, v6
|
|
add-int/2addr v6, v2
|
|
return v6 # Normal path return.
|
|
|
|
:catch_all
|
|
const v2, 32
|
|
ushr-long v2, v0, v2
|
|
long-to-int v2, v2
|
|
long-to-int v0, v0
|
|
add-int/2addr v0, v2
|
|
return v0 # Exceptional path #1/#2 return.
|
|
.end method
|
|
|
|
|
|
# Test catch-phi runtime support for 32-bit values stored in FPU registers.
|
|
|
|
# Register v0 holds different float values at two throwing instructions. Runtime
|
|
# is expected to find their location in the stack map and copy the value to the
|
|
# location of the catch phi. The value is converted to int and returned.
|
|
|
|
# Note: values will be spilled on x86 as there are no callee-save FPU registers.
|
|
|
|
## CHECK-START: int Runtime.testCatchPhi_float(boolean, boolean) register (after)
|
|
## CHECK-DAG: <<Val1:f\d+>> ArrayGet
|
|
## CHECK-DAG: <<Val2:f\d+>> ArrayGet
|
|
## CHECK-DAG: Phi [<<Val1>>,<<Val2>>] is_catch_phi:true
|
|
|
|
.method public static testCatchPhi_float(ZZ)I
|
|
.registers 6
|
|
|
|
sget-object v0, LRuntime;->floatArray:[F
|
|
const/4 v1, 0
|
|
aget v1, v0, v1
|
|
const/4 v2, 1
|
|
aget v2, v0, v2
|
|
const/4 v3, 2
|
|
aget v3, v0, v3
|
|
|
|
:try_start
|
|
move v0, v1 # Set catch phi value
|
|
invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
|
|
move v0, v2 # Set catch phi value
|
|
invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end
|
|
.catchall {:try_start .. :try_end} :catch_all
|
|
|
|
float-to-int v3, v3
|
|
return v3 # Normal path return.
|
|
|
|
:catch_all
|
|
float-to-int v0, v0
|
|
return v0 # Exceptional path #1/#2 return.
|
|
.end method
|
|
|
|
|
|
# Test catch-phi runtime support for 64-bit values stored in FPU registers.
|
|
|
|
# Register pair (v0, v1) holds different double values at two throwing instructions.
|
|
# Runtime is expected to find their location in the stack map and copy the value
|
|
# to the location of the catch phi. The value is converted to int and returned.
|
|
# Values were chosen so that all 64 bits are used.
|
|
|
|
# Note: values will be spilled on x86 as there are no callee-save FPU registers.
|
|
|
|
## CHECK-START: int Runtime.testCatchPhi_double(boolean, boolean) register (after)
|
|
## CHECK-DAG: <<Val1:d\d+>> ArrayGet
|
|
## CHECK-DAG: <<Val2:d\d+>> ArrayGet
|
|
## CHECK-DAG: Phi [<<Val1>>,<<Val2>>] is_catch_phi:true
|
|
|
|
.method public static testCatchPhi_double(ZZ)I
|
|
.registers 10
|
|
|
|
sget-object v0, LRuntime;->doubleArray:[D
|
|
const/4 v2, 0
|
|
aget-wide v2, v0, v2
|
|
const/4 v4, 1
|
|
aget-wide v4, v0, v4
|
|
const/4 v6, 2
|
|
aget-wide v6, v0, v6
|
|
|
|
:try_start
|
|
move-wide v0, v2 # Set catch phi value
|
|
invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
|
|
move-wide v0, v4 # Set catch phi value
|
|
invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end
|
|
.catchall {:try_start .. :try_end} :catch_all
|
|
|
|
double-to-int v6, v6
|
|
return v6
|
|
|
|
:catch_all
|
|
double-to-int v0, v0
|
|
return v0
|
|
.end method
|
|
|
|
# Test catch-phi runtime support for 32-bit values stored on the stack.
|
|
|
|
# Register v0 holds different integer values at two throwing instructions.
|
|
# These values were forced to spill by an always-throwing try/catch after their
|
|
# definition. Runtime is expected to find their location in the stack map and
|
|
# copy the value to the location of the catch phi. The value is then returned.
|
|
|
|
## CHECK-START: int Runtime.testCatchPhi_singleSlot(boolean, boolean) register (after)
|
|
## CHECK: <<Val1:i\d+>> ArrayGet
|
|
## CHECK-NEXT: ParallelMove moves:[{{.*->}}{{\d+}}(sp)]
|
|
## CHECK: <<Val2:i\d+>> ArrayGet
|
|
## CHECK-NEXT: ParallelMove moves:[{{.*->}}{{\d+}}(sp)]
|
|
## CHECK: Phi [<<Val1>>,<<Val2>>] is_catch_phi:true
|
|
|
|
.method public static testCatchPhi_singleSlot(ZZ)I
|
|
.registers 6
|
|
|
|
sget-object v0, LRuntime;->intArray:[I
|
|
const/4 v1, 0
|
|
aget v1, v0, v1
|
|
const/4 v2, 1
|
|
aget v2, v0, v2
|
|
const/4 v3, 2
|
|
aget v3, v0, v3
|
|
|
|
# Insert a try/catch to force v1,v2,v3 to spill.
|
|
:try_start_spill
|
|
const/4 v0, 1
|
|
invoke-static {v0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end_spill
|
|
.catchall {:try_start_spill .. :try_end_spill} :catch_all_spill
|
|
return v0 # Unreachable
|
|
:catch_all_spill # Catch and continue
|
|
|
|
:try_start
|
|
move v0, v1 # Set catch phi value
|
|
invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
|
|
move v0, v2 # Set catch phi value
|
|
invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end
|
|
.catchall {:try_start .. :try_end} :catch_all
|
|
|
|
return v3 # Normal path return.
|
|
|
|
:catch_all
|
|
return v0 # Exceptional path #1/#2 return.
|
|
.end method
|
|
|
|
# Test catch-phi runtime support for 64-bit values stored on the stack.
|
|
|
|
# Register pair (v0, v1) holds different double values at two throwing instructions.
|
|
# These values were forced to spill by an always-throwing try/catch after their
|
|
# definition. Runtime is expected to find their location in the stack map and
|
|
# copy the value to the location of the catch phi. The value is converted to int
|
|
# and returned. Values were chosen so that all 64 bits are used.
|
|
|
|
## CHECK-START: int Runtime.testCatchPhi_doubleSlot(boolean, boolean) register (after)
|
|
## CHECK: <<Val1:d\d+>> ArrayGet
|
|
## CHECK-NEXT: ParallelMove moves:[{{.*->}}2x{{\d+}}(sp)]
|
|
## CHECK: <<Val2:d\d+>> ArrayGet
|
|
## CHECK-NEXT: ParallelMove moves:[{{.*->}}2x{{\d+}}(sp)]
|
|
## CHECK: Phi [<<Val1>>,<<Val2>>] is_catch_phi:true
|
|
|
|
.method public static testCatchPhi_doubleSlot(ZZ)I
|
|
.registers 10
|
|
|
|
sget-object v0, LRuntime;->doubleArray:[D
|
|
const/4 v2, 0
|
|
aget-wide v2, v0, v2
|
|
const/4 v4, 1
|
|
aget-wide v4, v0, v4
|
|
const/4 v6, 2
|
|
aget-wide v6, v0, v6
|
|
|
|
# Insert a try/catch to force (v2, v3), (v4, v5), (v6, v7) to spill.
|
|
:try_start_spill
|
|
const/4 v0, 1
|
|
invoke-static {v0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end_spill
|
|
.catchall {:try_start_spill .. :try_end_spill} :catch_all_spill
|
|
return v0 # Unreachable
|
|
:catch_all_spill # Catch and continue
|
|
|
|
:try_start
|
|
move-wide v0, v2 # Set catch phi value
|
|
invoke-static {p0}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
|
|
move-wide v0, v4 # Set catch phi value
|
|
invoke-static {p1}, LRuntime;->$noinline$ThrowIfTrue(Z)V
|
|
:try_end
|
|
.catchall {:try_start .. :try_end} :catch_all
|
|
|
|
double-to-int v6, v6
|
|
return v6 # Normal path return.
|
|
|
|
:catch_all
|
|
double-to-int v0, v0
|
|
return v0 # Exceptional path #1/#2 return.
|
|
.end method
|
|
|
|
|
|
|
|
# Helper methods and initialization.
|
|
|
|
.method public static $noinline$ThrowIfTrue(Z)V
|
|
.registers 2
|
|
if-nez p0, :throw
|
|
return-void
|
|
|
|
:throw
|
|
new-instance v0, Ljava/lang/Exception;
|
|
invoke-direct {v0}, Ljava/lang/Exception;-><init>()V
|
|
throw v0
|
|
.end method
|
|
|
|
.method public static constructor <clinit>()V
|
|
.registers 2
|
|
|
|
const/4 v1, 4
|
|
|
|
new-array v0, v1, [I
|
|
fill-array-data v0, :array_int
|
|
sput-object v0, LRuntime;->intArray:[I
|
|
|
|
new-array v0, v1, [J
|
|
fill-array-data v0, :array_long
|
|
sput-object v0, LRuntime;->longArray:[J
|
|
|
|
new-array v0, v1, [F
|
|
fill-array-data v0, :array_float
|
|
sput-object v0, LRuntime;->floatArray:[F
|
|
|
|
new-array v0, v1, [D
|
|
fill-array-data v0, :array_double
|
|
sput-object v0, LRuntime;->doubleArray:[D
|
|
|
|
return-void
|
|
|
|
:array_int
|
|
.array-data 4
|
|
0x03 # int 3
|
|
0x08 # int 8
|
|
0x2a # int 42
|
|
.end array-data
|
|
|
|
:array_long
|
|
.array-data 8
|
|
0x0000000100000002L # long (1 << 32) + 2
|
|
0x0000000500000003L # long (5 << 32) + 3
|
|
0x0000001e0000000cL # long (30 << 32) + 12
|
|
.end array-data
|
|
|
|
:array_float
|
|
.array-data 4
|
|
0x40400000 # float 3
|
|
0x41000000 # float 8
|
|
0x42280000 # float 42
|
|
.end array-data
|
|
|
|
:array_double
|
|
.array-data 8
|
|
0x400b333333333333L # double 3.4
|
|
0x4020cccccccccccdL # double 8.4
|
|
0x4045333333333333L # double 42.4
|
|
.end array-data
|
|
.end method
|
|
|
|
|
|
## CHECK-START-{ARM,ARM64}: int Runtime.testIntAddressCatch(int, int[]) GVN$after_arch (after)
|
|
## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<Offset:i\d+>> IntConstant 12
|
|
## CHECK-DAG: <<IndexParam:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<Array:l\d+>> ParameterValue
|
|
|
|
## CHECK-DAG: <<NullCh1:l\d+>> NullCheck [<<Array>>]
|
|
## CHECK-DAG: <<Length:i\d+>> ArrayLength
|
|
## CHECK-DAG: <<BoundsCh1:i\d+>> BoundsCheck [<<IndexParam>>,<<Length>>]
|
|
## CHECK-DAG: <<IntAddr1:i\d+>> IntermediateAddress [<<NullCh1>>,<<Offset>>]
|
|
## CHECK-DAG: ArrayGet [<<IntAddr1>>,<<BoundsCh1>>]
|
|
## CHECK-DAG: TryBoundary
|
|
|
|
## CHECK-DAG: <<Xplus1:i\d+>> Add [<<IndexParam>>,<<Const1>>]
|
|
## CHECK-DAG: <<BoundsCh2:i\d+>> BoundsCheck [<<Xplus1>>,<<Length>>]
|
|
## CHECK-DAG: ArrayGet [<<IntAddr1>>,<<BoundsCh2>>]
|
|
## CHECK-DAG: TryBoundary
|
|
|
|
## CHECK-DAG: <<Phi:i\d+>> Phi [<<Xplus1>>]
|
|
## CHECK-DAG: <<Phiplus1:i\d+>> Add [<<Phi>>,<<Const1>>]
|
|
## CHECK-DAG: <<BoundsCh3:i\d+>> BoundsCheck [<<Phiplus1>>,<<Length>>]
|
|
## CHECK-DAG: <<IntAddr3:i\d+>> IntermediateAddress [<<NullCh1>>,<<Offset>>]
|
|
## CHECK-DAG: ArrayGet [<<IntAddr3>>,<<BoundsCh3>>]
|
|
|
|
## CHECK-START-{ARM,ARM64}: int Runtime.testIntAddressCatch(int, int[]) GVN$after_arch (after)
|
|
## CHECK: NullCheck
|
|
## CHECK-NOT: NullCheck
|
|
|
|
## CHECK-START-{ARM,ARM64}: int Runtime.testIntAddressCatch(int, int[]) GVN$after_arch (after)
|
|
## CHECK: IntermediateAddress
|
|
## CHECK: IntermediateAddress
|
|
## CHECK-NOT: IntermediateAddress
|
|
|
|
## CHECK-START-{ARM,ARM64}: int Runtime.testIntAddressCatch(int, int[]) GVN$after_arch (after)
|
|
## CHECK: BoundsCheck
|
|
## CHECK: BoundsCheck
|
|
## CHECK: BoundsCheck
|
|
## CHECK-NOT: BoundsCheck
|
|
|
|
## CHECK-START-{ARM,ARM64}: int Runtime.testIntAddressCatch(int, int[]) GVN$after_arch (after)
|
|
## CHECK: ArrayGet
|
|
## CHECK: ArrayGet
|
|
## CHECK: ArrayGet
|
|
## CHECK-NOT: ArrayGet
|
|
.method public static testIntAddressCatch(I[I)I
|
|
.registers 4
|
|
aget v0, p1, p0
|
|
add-int v1, v0, v0
|
|
|
|
:try_start
|
|
const/4 v0, 0x1
|
|
add-int p0, p0, v0
|
|
aget v0, p1, p0
|
|
|
|
:try_end
|
|
.catch Ljava/lang/ArithmException; {:try_start .. :try_end} :catch_block
|
|
|
|
:return
|
|
add-int v1, v1, v0
|
|
return v1
|
|
|
|
:catch_block
|
|
const/4 v0, 0x1
|
|
add-int p0, p0, v0
|
|
aget v0, p1, p0
|
|
|
|
goto :return
|
|
.end method
|
|
|
|
.field public static intArray:[I
|
|
.field public static longArray:[J
|
|
.field public static floatArray:[F
|
|
.field public static doubleArray:[D
|