From 559b1cc279deb9299414ddd46595bb8bca7fa090 Mon Sep 17 00:00:00 2001 From: Lazar Trsic Date: Wed, 24 Jun 2015 16:30:21 +0200 Subject: [PATCH] [MIPS64] JNI Compiler: Sign-extend int function arguments MIPS n64 ABI differs from arm64. Arguments smaller than the 8B stack slot need to be sign-extended. Use combination (lw,sd), instead of (lw,sw) for 4B values. Change fixes software keyboard crash on mips64. Bug: 21555893 (cherry picked from commit f652d605753f1387e7797461b47116c5dcdf928d) Change-Id: I7574d37f6039e9e8c9e0047254be71d28d4c829a --- compiler/jni/jni_compiler_test.cc | 46 +++++++++++++++++++++++++++++++ compiler/utils/mips64/assembler_mips64.cc | 8 +++--- test/MyClassNatives/MyClassNatives.java | 3 ++ 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc index e98e5724d..f3bda2fa7 100644 --- a/compiler/jni/jni_compiler_test.cc +++ b/compiler/jni/jni_compiler_test.cc @@ -165,6 +165,7 @@ class JniCompilerTest : public CommonCompilerTest { void StackArgsIntsFirstImpl(); void StackArgsFloatsFirstImpl(); void StackArgsMixedImpl(); + void StackArgsSignExtendedMips64Impl(); JNIEnv* env_; jmethodID jmethod_; @@ -1715,4 +1716,49 @@ void JniCompilerTest::StackArgsMixedImpl() { JNI_TEST(StackArgsMixed) +void Java_MyClassNatives_stackArgsSignExtendedMips64(JNIEnv*, jclass, jint i1, jint i2, jint i3, + jint i4, jint i5, jint i6, jint i7, jint i8) { + EXPECT_EQ(i1, 1); + EXPECT_EQ(i2, 2); + EXPECT_EQ(i3, 3); + EXPECT_EQ(i4, 4); + EXPECT_EQ(i5, 5); + EXPECT_EQ(i6, 6); + EXPECT_EQ(i7, 7); + EXPECT_EQ(i8, -8); + +#if defined(__mips__) && defined(__LP64__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) + // Mips64 ABI requires that arguments passed through stack be sign-extended 8B slots. + // First 8 arguments are passed through registers, check i7 and i8. + uint32_t stack1_high = *(&i7 + 1); + uint32_t stack2_high = *(&i8 + 1); + + EXPECT_EQ(stack1_high, static_cast(0)); + EXPECT_EQ(stack2_high, static_cast(0xffffffff)); +#else + LOG(INFO) << "Skipping stackArgsSignExtendedMips64 as there is nothing to be done on " + << kRuntimeISA; + // Force-print to std::cout so it's also outside the logcat. + std::cout << "Skipping stackArgsSignExtendedMips64 as there is nothing to be done on " + << kRuntimeISA << std::endl; +#endif +} + +void JniCompilerTest::StackArgsSignExtendedMips64Impl() { + SetUpForTest(true, "stackArgsSignExtendedMips64", "(IIIIIIII)V", + reinterpret_cast(&Java_MyClassNatives_stackArgsSignExtendedMips64)); + jint i1 = 1; + jint i2 = 2; + jint i3 = 3; + jint i4 = 4; + jint i5 = 5; + jint i6 = 6; + jint i7 = 7; + jint i8 = -8; + + env_->CallStaticVoidMethod(jklass_, jmethod_, i1, i2, i3, i4, i5, i6, i7, i8); +} + +JNI_TEST(StackArgsSignExtendedMips64) + } // namespace art diff --git a/compiler/utils/mips64/assembler_mips64.cc b/compiler/utils/mips64/assembler_mips64.cc index a8b55d109..5e49b936f 100644 --- a/compiler/utils/mips64/assembler_mips64.cc +++ b/compiler/utils/mips64/assembler_mips64.cc @@ -839,7 +839,7 @@ void Mips64Assembler::Copy(FrameOffset dest, FrameOffset src, CHECK(size == 4 || size == 8) << size; if (size == 4) { LoadFromOffset(kLoadWord, scratch.AsGpuRegister(), SP, src.Int32Value()); - StoreToOffset(kStoreWord, scratch.AsGpuRegister(), SP, dest.Int32Value()); + StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value()); } else if (size == 8) { LoadFromOffset(kLoadDoubleword, scratch.AsGpuRegister(), SP, src.Int32Value()); StoreToOffset(kStoreDoubleword, scratch.AsGpuRegister(), SP, dest.Int32Value()); @@ -855,7 +855,7 @@ void Mips64Assembler::Copy(FrameOffset dest, ManagedRegister src_base, Offset sr if (size == 4) { LoadFromOffset(kLoadWord, scratch, src_base.AsMips64().AsGpuRegister(), src_offset.Int32Value()); - StoreToOffset(kStoreWord, scratch, SP, dest.Int32Value()); + StoreToOffset(kStoreDoubleword, scratch, SP, dest.Int32Value()); } else if (size == 8) { LoadFromOffset(kLoadDoubleword, scratch, src_base.AsMips64().AsGpuRegister(), src_offset.Int32Value()); @@ -871,7 +871,7 @@ void Mips64Assembler::Copy(ManagedRegister dest_base, Offset dest_offset, FrameO CHECK(size == 4 || size == 8) << size; if (size == 4) { LoadFromOffset(kLoadWord, scratch, SP, src.Int32Value()); - StoreToOffset(kStoreWord, scratch, dest_base.AsMips64().AsGpuRegister(), + StoreToOffset(kStoreDoubleword, scratch, dest_base.AsMips64().AsGpuRegister(), dest_offset.Int32Value()); } else if (size == 8) { LoadFromOffset(kLoadDoubleword, scratch, SP, src.Int32Value()); @@ -894,7 +894,7 @@ void Mips64Assembler::Copy(ManagedRegister dest, Offset dest_offset, CHECK(size == 4 || size == 8) << size; if (size == 4) { LoadFromOffset(kLoadWord, scratch, src.AsMips64().AsGpuRegister(), src_offset.Int32Value()); - StoreToOffset(kStoreWord, scratch, dest.AsMips64().AsGpuRegister(), dest_offset.Int32Value()); + StoreToOffset(kStoreDoubleword, scratch, dest.AsMips64().AsGpuRegister(), dest_offset.Int32Value()); } else if (size == 8) { LoadFromOffset(kLoadDoubleword, scratch, src.AsMips64().AsGpuRegister(), src_offset.Int32Value()); diff --git a/test/MyClassNatives/MyClassNatives.java b/test/MyClassNatives/MyClassNatives.java index 8b4a9a4a3..19c13f78d 100644 --- a/test/MyClassNatives/MyClassNatives.java +++ b/test/MyClassNatives/MyClassNatives.java @@ -94,6 +94,9 @@ class MyClassNatives { float f4, int i5, float f5, int i6, float f6, int i7, float f7, int i8, float f8, int i9, float f9, int i10, float f10); + native static void stackArgsSignExtendedMips64(int i1, int i2, int i3, int i4, int i5, int i6, + int i7, int i8); + static native double logD(double d); static native float logF(float f); static native boolean returnTrue(); -- 2.11.0