ARM64/x86-64: Fix mterp fill-array-data-payload pointer calculation.
Fix the pointer calculation to sign-extend the offset
instead of zero-extending it, just like we do for the switch
table pointer calculation. Clean up comments for the switch.
Test: Additional test in 412-new-array.
Change-Id: Ibb1d2d3fcb109f59280aca08de21e42edc4ce66b
diff --git a/runtime/interpreter/mterp/arm64/op_fill_array_data.S b/runtime/interpreter/mterp/arm64/op_fill_array_data.S
index f50d9e4..86fa6db 100644
--- a/runtime/interpreter/mterp/arm64/op_fill_array_data.S
+++ b/runtime/interpreter/mterp/arm64/op_fill_array_data.S
@@ -1,11 +1,11 @@
/* fill-array-data vAA, +BBBBBBBB */
EXPORT_PC
- FETCH w0, 1 // w0<- bbbb (lo)
- FETCH w1, 2 // w1<- BBBB (hi)
+ FETCH w0, 1 // x0<- 000000000000bbbb (lo)
+ FETCH_S x1, 2 // x1<- ssssssssssssBBBB (hi)
lsr w3, wINST, #8 // w3<- AA
- orr w1, w0, w1, lsl #16 // w1<- BBBBbbbb
+ orr x1, x0, x1, lsl #16 // x1<- ssssssssBBBBbbbb
GET_VREG w0, w3 // w0<- vAA (array object)
- add x1, xPC, w1, lsl #1 // w1<- PC + BBBBbbbb*2 (array data off.)
+ add x1, xPC, x1, lsl #1 // x1<- PC + ssssssssBBBBbbbb*2 (array data off.)
bl MterpFillArrayData // (obj, payload)
cbz w0, MterpPossibleException // exception?
FETCH_ADVANCE_INST 3 // advance rPC, load rINST
diff --git a/runtime/interpreter/mterp/arm64/op_packed_switch.S b/runtime/interpreter/mterp/arm64/op_packed_switch.S
index 4faa6d2..408e030 100644
--- a/runtime/interpreter/mterp/arm64/op_packed_switch.S
+++ b/runtime/interpreter/mterp/arm64/op_packed_switch.S
@@ -14,7 +14,7 @@
lsr w3, wINST, #8 // w3<- AA
orr x0, x0, x1, lsl #16 // x0<- ssssssssBBBBbbbb
GET_VREG w1, w3 // w1<- vAA
- add x0, xPC, x0, lsl #1 // x0<- PC + BBBBbbbb*2
+ add x0, xPC, x0, lsl #1 // x0<- PC + ssssssssBBBBbbbb*2
bl $func // w0<- code-unit branch offset
sxtw xINST, w0
b MterpCommonTakenBranchNoFlags
diff --git a/runtime/interpreter/mterp/out/mterp_arm64.S b/runtime/interpreter/mterp/out/mterp_arm64.S
index 79d3c9a..e318782 100644
--- a/runtime/interpreter/mterp/out/mterp_arm64.S
+++ b/runtime/interpreter/mterp/out/mterp_arm64.S
@@ -1050,12 +1050,12 @@
/* File: arm64/op_fill_array_data.S */
/* fill-array-data vAA, +BBBBBBBB */
EXPORT_PC
- FETCH w0, 1 // w0<- bbbb (lo)
- FETCH w1, 2 // w1<- BBBB (hi)
+ FETCH w0, 1 // x0<- 000000000000bbbb (lo)
+ FETCH_S x1, 2 // x1<- ssssssssssssBBBB (hi)
lsr w3, wINST, #8 // w3<- AA
- orr w1, w0, w1, lsl #16 // w1<- BBBBbbbb
+ orr x1, x0, x1, lsl #16 // x1<- ssssssssBBBBbbbb
GET_VREG w0, w3 // w0<- vAA (array object)
- add x1, xPC, w1, lsl #1 // w1<- PC + BBBBbbbb*2 (array data off.)
+ add x1, xPC, x1, lsl #1 // x1<- PC + ssssssssBBBBbbbb*2 (array data off.)
bl MterpFillArrayData // (obj, payload)
cbz w0, MterpPossibleException // exception?
FETCH_ADVANCE_INST 3 // advance rPC, load rINST
@@ -1145,7 +1145,7 @@
lsr w3, wINST, #8 // w3<- AA
orr x0, x0, x1, lsl #16 // x0<- ssssssssBBBBbbbb
GET_VREG w1, w3 // w1<- vAA
- add x0, xPC, x0, lsl #1 // x0<- PC + BBBBbbbb*2
+ add x0, xPC, x0, lsl #1 // x0<- PC + ssssssssBBBBbbbb*2
bl MterpDoPackedSwitch // w0<- code-unit branch offset
sxtw xINST, w0
b MterpCommonTakenBranchNoFlags
@@ -1170,7 +1170,7 @@
lsr w3, wINST, #8 // w3<- AA
orr x0, x0, x1, lsl #16 // x0<- ssssssssBBBBbbbb
GET_VREG w1, w3 // w1<- vAA
- add x0, xPC, x0, lsl #1 // x0<- PC + BBBBbbbb*2
+ add x0, xPC, x0, lsl #1 // x0<- PC + ssssssssBBBBbbbb*2
bl MterpDoSparseSwitch // w0<- code-unit branch offset
sxtw xINST, w0
b MterpCommonTakenBranchNoFlags
diff --git a/runtime/interpreter/mterp/out/mterp_x86_64.S b/runtime/interpreter/mterp/out/mterp_x86_64.S
index 9e2dcea..2f7b854 100644
--- a/runtime/interpreter/mterp/out/mterp_x86_64.S
+++ b/runtime/interpreter/mterp/out/mterp_x86_64.S
@@ -965,8 +965,8 @@
/* File: x86_64/op_fill_array_data.S */
/* fill-array-data vAA, +BBBBBBBB */
EXPORT_PC
- movl 2(rPC), %ecx # ecx <- BBBBbbbb
- leaq (rPC,%rcx,2), OUT_ARG1 # OUT_ARG1 <- PC + BBBBbbbb*2
+ movslq 2(rPC), %rcx # rcx <- ssssssssBBBBbbbb
+ leaq (rPC,%rcx,2), OUT_ARG1 # OUT_ARG1 <- PC + ssssssssBBBBbbbb*2
GET_VREG OUT_32_ARG0, rINSTq # OUT_ARG0 <- vAA (array object)
call SYMBOL(MterpFillArrayData) # (obj, payload)
testb %al, %al # 0 means an exception is thrown
@@ -1051,8 +1051,8 @@
* for: packed-switch, sparse-switch
*/
/* op vAA, +BBBB */
- movslq 2(rPC), OUT_ARG0 # rcx <- BBBBbbbb
- leaq (rPC,OUT_ARG0,2), OUT_ARG0 # rcx <- PC + BBBBbbbb*2
+ movslq 2(rPC), OUT_ARG0 # rcx <- ssssssssBBBBbbbb
+ leaq (rPC,OUT_ARG0,2), OUT_ARG0 # rcx <- PC + ssssssssBBBBbbbb*2
GET_VREG OUT_32_ARG1, rINSTq # eax <- vAA
call SYMBOL(MterpDoPackedSwitch)
testl %eax, %eax
@@ -1074,8 +1074,8 @@
* for: packed-switch, sparse-switch
*/
/* op vAA, +BBBB */
- movslq 2(rPC), OUT_ARG0 # rcx <- BBBBbbbb
- leaq (rPC,OUT_ARG0,2), OUT_ARG0 # rcx <- PC + BBBBbbbb*2
+ movslq 2(rPC), OUT_ARG0 # rcx <- ssssssssBBBBbbbb
+ leaq (rPC,OUT_ARG0,2), OUT_ARG0 # rcx <- PC + ssssssssBBBBbbbb*2
GET_VREG OUT_32_ARG1, rINSTq # eax <- vAA
call SYMBOL(MterpDoSparseSwitch)
testl %eax, %eax
diff --git a/runtime/interpreter/mterp/x86_64/op_fill_array_data.S b/runtime/interpreter/mterp/x86_64/op_fill_array_data.S
index 626bad4..7ea36a6 100644
--- a/runtime/interpreter/mterp/x86_64/op_fill_array_data.S
+++ b/runtime/interpreter/mterp/x86_64/op_fill_array_data.S
@@ -1,7 +1,7 @@
/* fill-array-data vAA, +BBBBBBBB */
EXPORT_PC
- movl 2(rPC), %ecx # ecx <- BBBBbbbb
- leaq (rPC,%rcx,2), OUT_ARG1 # OUT_ARG1 <- PC + BBBBbbbb*2
+ movslq 2(rPC), %rcx # rcx <- ssssssssBBBBbbbb
+ leaq (rPC,%rcx,2), OUT_ARG1 # OUT_ARG1 <- PC + ssssssssBBBBbbbb*2
GET_VREG OUT_32_ARG0, rINSTq # OUT_ARG0 <- vAA (array object)
call SYMBOL(MterpFillArrayData) # (obj, payload)
testb %al, %al # 0 means an exception is thrown
diff --git a/runtime/interpreter/mterp/x86_64/op_packed_switch.S b/runtime/interpreter/mterp/x86_64/op_packed_switch.S
index fdf5a50..148552f 100644
--- a/runtime/interpreter/mterp/x86_64/op_packed_switch.S
+++ b/runtime/interpreter/mterp/x86_64/op_packed_switch.S
@@ -9,8 +9,8 @@
* for: packed-switch, sparse-switch
*/
/* op vAA, +BBBB */
- movslq 2(rPC), OUT_ARG0 # rcx <- BBBBbbbb
- leaq (rPC,OUT_ARG0,2), OUT_ARG0 # rcx <- PC + BBBBbbbb*2
+ movslq 2(rPC), OUT_ARG0 # rcx <- ssssssssBBBBbbbb
+ leaq (rPC,OUT_ARG0,2), OUT_ARG0 # rcx <- PC + ssssssssBBBBbbbb*2
GET_VREG OUT_32_ARG1, rINSTq # eax <- vAA
call SYMBOL($func)
testl %eax, %eax
diff --git a/test/412-new-array/info.txt b/test/412-new-array/info.txt
index cb388b6..b5f834a 100644
--- a/test/412-new-array/info.txt
+++ b/test/412-new-array/info.txt
@@ -1 +1,3 @@
Simple tests for new-array, filled-new-array and fill-array-data.
+Regression test for the arm64 mterp miscalculating the fill-array-data-payload
+address, zero-extending a register instead of sign-extending.
diff --git a/test/412-new-array/smali/fill_array_data.smali b/test/412-new-array/smali/fill_array_data.smali
index 34776db..2b24e56 100644
--- a/test/412-new-array/smali/fill_array_data.smali
+++ b/test/412-new-array/smali/fill_array_data.smali
@@ -15,6 +15,21 @@
.end method
+.method public static intArrayFillInstructionAfterData([I)V
+ .registers 1
+ goto :FillInstruction
+
+:ArrayData
+ .array-data 4
+ 1 2 3 4 5
+ .end array-data
+
+:FillInstruction
+ fill-array-data v0, :ArrayData
+ return-void
+
+.end method
+
.method public static shortArray([S)V
.registers 1
diff --git a/test/412-new-array/src/Main.java b/test/412-new-array/src/Main.java
index b9c2a05..d95d2c5 100644
--- a/test/412-new-array/src/Main.java
+++ b/test/412-new-array/src/Main.java
@@ -259,6 +259,45 @@
}
{
+ Method m = c.getMethod("intArrayFillInstructionAfterData", int[].class);
+ int[] array = new int[7];
+ Object[] args = { array };
+ m.invoke(null, args);
+ assertEquals(7, array.length);
+ assertEquals(1, array[0]);
+ assertEquals(2, array[1]);
+ assertEquals(3, array[2]);
+ assertEquals(4, array[3]);
+ assertEquals(5, array[4]);
+ assertEquals(0, array[5]);
+ assertEquals(0, array[6]);
+
+ array = new int[2];
+ args[0] = array;
+ Throwable exception = null;
+ try {
+ m.invoke(null, args);
+ } catch (InvocationTargetException e) {
+ exception = e.getCause();
+ assertTrue(exception instanceof IndexOutOfBoundsException);
+ }
+ assertNotNull(exception);
+ exception = null;
+ // Test that nothing has been written to the array.
+ assertEquals(0, array[0]);
+ assertEquals(0, array[1]);
+
+ args[0] = null;
+ try {
+ m.invoke(null, args);
+ } catch (InvocationTargetException e) {
+ exception = e.getCause();
+ assertTrue(exception instanceof NullPointerException);
+ }
+ assertNotNull(exception);
+ }
+
+ {
Method m = c.getMethod("shortArray", short[].class);
short[] array = new short[7];
Object[] args = { array };