diff options
-rw-r--r-- | compiler/jni/jni_compiler_test.cc | 213 | ||||
-rw-r--r-- | runtime/entrypoints/quick/quick_trampoline_entrypoints.cc | 107 | ||||
-rw-r--r-- | test/MyClassNatives/MyClassNatives.java | 12 |
3 files changed, 257 insertions, 75 deletions
diff --git a/compiler/jni/jni_compiler_test.cc b/compiler/jni/jni_compiler_test.cc index a0797f3147..6b5e55efa8 100644 --- a/compiler/jni/jni_compiler_test.cc +++ b/compiler/jni/jni_compiler_test.cc @@ -1278,4 +1278,217 @@ TEST_F(JniCompilerTest, WithoutImplementation) { EXPECT_TRUE(env_->ExceptionCheck() == JNI_TRUE); } +template <typename U, typename V> V convert(U in) { + DCHECK_LE(sizeof(U), sizeof(V)); + union { U u; V v; } tmp; + tmp.u = in; + return tmp.v; +} + +void Java_MyClassNatives_stackArgsIntsFirst(JNIEnv* env, jclass klass, jint i1, jint i2, jint i3, + jint i4, jint i5, jint i6, jint i7, jint i8, jint i9, + jint i10, jfloat f1, jfloat f2, jfloat f3, jfloat f4, + jfloat f5, jfloat f6, jfloat f7, jfloat f8, jfloat f9, + jfloat f10) { + 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); + EXPECT_EQ(i9, 9); + EXPECT_EQ(i10, 10); + + jint i11 = convert<jfloat, jint>(f1); + EXPECT_EQ(i11, 11); + jint i12 = convert<jfloat, jint>(f2); + EXPECT_EQ(i12, 12); + jint i13 = convert<jfloat, jint>(f3); + EXPECT_EQ(i13, 13); + jint i14 = convert<jfloat, jint>(f4); + EXPECT_EQ(i14, 14); + jint i15 = convert<jfloat, jint>(f5); + EXPECT_EQ(i15, 15); + jint i16 = convert<jfloat, jint>(f6); + EXPECT_EQ(i16, 16); + jint i17 = convert<jfloat, jint>(f7); + EXPECT_EQ(i17, 17); + jint i18 = convert<jfloat, jint>(f8); + EXPECT_EQ(i18, 18); + jint i19 = convert<jfloat, jint>(f9); + EXPECT_EQ(i19, 19); + jint i20 = convert<jfloat, jint>(f10); + EXPECT_EQ(i20, 20); +} + +TEST_F(JniCompilerTest, StackArgsIntsFirst) { + TEST_DISABLED_FOR_PORTABLE(); + SetUpForTest(true, "stackArgsIntsFirst", "(IIIIIIIIIIFFFFFFFFFF)V", + reinterpret_cast<void*>(&Java_MyClassNatives_stackArgsIntsFirst)); + + jint i1 = 1; + jint i2 = 2; + jint i3 = 3; + jint i4 = 4; + jint i5 = 5; + jint i6 = 6; + jint i7 = 7; + jint i8 = 8; + jint i9 = 9; + jint i10 = 10; + + jfloat f1 = convert<jint, jfloat>(11); + jfloat f2 = convert<jint, jfloat>(12); + jfloat f3 = convert<jint, jfloat>(13); + jfloat f4 = convert<jint, jfloat>(14); + jfloat f5 = convert<jint, jfloat>(15); + jfloat f6 = convert<jint, jfloat>(16); + jfloat f7 = convert<jint, jfloat>(17); + jfloat f8 = convert<jint, jfloat>(18); + jfloat f9 = convert<jint, jfloat>(19); + jfloat f10 = convert<jint, jfloat>(20); + + env_->CallStaticVoidMethod(jklass_, jmethod_, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, f1, f2, + f3, f4, f5, f6, f7, f8, f9, f10); +} + +void Java_MyClassNatives_stackArgsFloatsFirst(JNIEnv* env, jclass klass, jfloat f1, jfloat f2, + jfloat f3, jfloat f4, jfloat f5, jfloat f6, jfloat f7, + jfloat f8, jfloat f9, jfloat f10, jint i1, jint i2, + jint i3, jint i4, jint i5, jint i6, jint i7, jint i8, + jint i9, jint i10) { + 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); + EXPECT_EQ(i9, 9); + EXPECT_EQ(i10, 10); + + jint i11 = convert<jfloat, jint>(f1); + EXPECT_EQ(i11, 11); + jint i12 = convert<jfloat, jint>(f2); + EXPECT_EQ(i12, 12); + jint i13 = convert<jfloat, jint>(f3); + EXPECT_EQ(i13, 13); + jint i14 = convert<jfloat, jint>(f4); + EXPECT_EQ(i14, 14); + jint i15 = convert<jfloat, jint>(f5); + EXPECT_EQ(i15, 15); + jint i16 = convert<jfloat, jint>(f6); + EXPECT_EQ(i16, 16); + jint i17 = convert<jfloat, jint>(f7); + EXPECT_EQ(i17, 17); + jint i18 = convert<jfloat, jint>(f8); + EXPECT_EQ(i18, 18); + jint i19 = convert<jfloat, jint>(f9); + EXPECT_EQ(i19, 19); + jint i20 = convert<jfloat, jint>(f10); + EXPECT_EQ(i20, 20); +} + +TEST_F(JniCompilerTest, StackArgsFloatsFirst) { + TEST_DISABLED_FOR_PORTABLE(); + SetUpForTest(true, "stackArgsFloatsFirst", "(FFFFFFFFFFIIIIIIIIII)V", + reinterpret_cast<void*>(&Java_MyClassNatives_stackArgsFloatsFirst)); + + jint i1 = 1; + jint i2 = 2; + jint i3 = 3; + jint i4 = 4; + jint i5 = 5; + jint i6 = 6; + jint i7 = 7; + jint i8 = 8; + jint i9 = 9; + jint i10 = 10; + + jfloat f1 = convert<jint, jfloat>(11); + jfloat f2 = convert<jint, jfloat>(12); + jfloat f3 = convert<jint, jfloat>(13); + jfloat f4 = convert<jint, jfloat>(14); + jfloat f5 = convert<jint, jfloat>(15); + jfloat f6 = convert<jint, jfloat>(16); + jfloat f7 = convert<jint, jfloat>(17); + jfloat f8 = convert<jint, jfloat>(18); + jfloat f9 = convert<jint, jfloat>(19); + jfloat f10 = convert<jint, jfloat>(20); + + env_->CallStaticVoidMethod(jklass_, jmethod_, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, i1, i2, i3, + i4, i5, i6, i7, i8, i9, i10); +} + +void Java_MyClassNatives_stackArgsMixed(JNIEnv* env, jclass klass, jint i1, jfloat f1, jint i2, + jfloat f2, jint i3, jfloat f3, jint i4, jfloat f4, jint i5, + jfloat f5, jint i6, jfloat f6, jint i7, jfloat f7, jint i8, + jfloat f8, jint i9, jfloat f9, jint i10, jfloat f10) { + 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); + EXPECT_EQ(i9, 9); + EXPECT_EQ(i10, 10); + + jint i11 = convert<jfloat, jint>(f1); + EXPECT_EQ(i11, 11); + jint i12 = convert<jfloat, jint>(f2); + EXPECT_EQ(i12, 12); + jint i13 = convert<jfloat, jint>(f3); + EXPECT_EQ(i13, 13); + jint i14 = convert<jfloat, jint>(f4); + EXPECT_EQ(i14, 14); + jint i15 = convert<jfloat, jint>(f5); + EXPECT_EQ(i15, 15); + jint i16 = convert<jfloat, jint>(f6); + EXPECT_EQ(i16, 16); + jint i17 = convert<jfloat, jint>(f7); + EXPECT_EQ(i17, 17); + jint i18 = convert<jfloat, jint>(f8); + EXPECT_EQ(i18, 18); + jint i19 = convert<jfloat, jint>(f9); + EXPECT_EQ(i19, 19); + jint i20 = convert<jfloat, jint>(f10); + EXPECT_EQ(i20, 20); +} + +TEST_F(JniCompilerTest, StackArgsMixed) { + TEST_DISABLED_FOR_PORTABLE(); + SetUpForTest(true, "stackArgsMixed", "(IFIFIFIFIFIFIFIFIFIF)V", + reinterpret_cast<void*>(&Java_MyClassNatives_stackArgsMixed)); + + jint i1 = 1; + jint i2 = 2; + jint i3 = 3; + jint i4 = 4; + jint i5 = 5; + jint i6 = 6; + jint i7 = 7; + jint i8 = 8; + jint i9 = 9; + jint i10 = 10; + + jfloat f1 = convert<jint, jfloat>(11); + jfloat f2 = convert<jint, jfloat>(12); + jfloat f3 = convert<jint, jfloat>(13); + jfloat f4 = convert<jint, jfloat>(14); + jfloat f5 = convert<jint, jfloat>(15); + jfloat f6 = convert<jint, jfloat>(16); + jfloat f7 = convert<jint, jfloat>(17); + jfloat f8 = convert<jint, jfloat>(18); + jfloat f9 = convert<jint, jfloat>(19); + jfloat f10 = convert<jint, jfloat>(20); + + env_->CallStaticVoidMethod(jklass_, jmethod_, i1, f1, i2, f2, i3, f3, i4, f4, i5, f5, i6, f6, i7, + f7, i8, f8, i9, f9, i10, f10); +} + } // namespace art diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc index fcbcac2337..2b29591fbb 100644 --- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc +++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc @@ -250,6 +250,7 @@ class QuickArgumentVisitor { if ((kNumQuickFprArgs != 0) && (fpr_index_ + 1 < kNumQuickFprArgs + 1)) { return fpr_args_ + (fpr_index_ * kBytesPerFprSpillLocation); } + return stack_args_ + (stack_index_ * kBytesStackArgLocation); } } if (gpr_index_ < kNumQuickGprArgs) { @@ -283,6 +284,12 @@ class QuickArgumentVisitor { } void VisitArguments() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + // This implementation doesn't support reg-spill area for hard float + // ABI targets such as x86_64 and aarch64. So, for those targets whose + // 'kQuickSoftFloatAbi' is 'false': + // (a) 'stack_args_' should point to the first method's argument + // (b) whatever the argument type it is, the 'stack_index_' should + // be moved forward along with every visiting. gpr_index_ = 0; fpr_index_ = 0; stack_index_ = 0; @@ -290,10 +297,11 @@ class QuickArgumentVisitor { cur_type_ = Primitive::kPrimNot; is_split_long_or_double_ = false; Visit(); + if (!kQuickSoftFloatAbi || kNumQuickGprArgs == 0) { + stack_index_++; + } if (kNumQuickGprArgs > 0) { gpr_index_++; - } else { - stack_index_++; } } for (uint32_t shorty_index = 1; shorty_index < shorty_len_; ++shorty_index) { @@ -307,10 +315,11 @@ class QuickArgumentVisitor { case Primitive::kPrimInt: is_split_long_or_double_ = false; Visit(); + if (!kQuickSoftFloatAbi || kNumQuickGprArgs == gpr_index_) { + stack_index_++; + } if (gpr_index_ < kNumQuickGprArgs) { gpr_index_++; - } else { - stack_index_++; } break; case Primitive::kPrimFloat: @@ -325,9 +334,8 @@ class QuickArgumentVisitor { } else { if ((kNumQuickFprArgs != 0) && (fpr_index_ + 1 < kNumQuickFprArgs + 1)) { fpr_index_++; - } else { - stack_index_++; } + stack_index_++; } break; case Primitive::kPrimDouble: @@ -336,22 +344,23 @@ class QuickArgumentVisitor { is_split_long_or_double_ = (kBytesPerGprSpillLocation == 4) && ((gpr_index_ + 1) == kNumQuickGprArgs); Visit(); + if (!kQuickSoftFloatAbi || kNumQuickGprArgs == gpr_index_) { + if (kBytesStackArgLocation == 4) { + stack_index_+= 2; + } else { + CHECK_EQ(kBytesStackArgLocation, 8U); + stack_index_++; + } + } if (gpr_index_ < kNumQuickGprArgs) { gpr_index_++; if (kBytesPerGprSpillLocation == 4) { if (gpr_index_ < kNumQuickGprArgs) { gpr_index_++; - } else { + } else if (kQuickSoftFloatAbi) { stack_index_++; } } - } else { - if (kBytesStackArgLocation == 4) { - stack_index_+= 2; - } else { - CHECK_EQ(kBytesStackArgLocation, 8U); - stack_index_++; - } } } else { is_split_long_or_double_ = (kBytesPerFprSpillLocation == 4) && @@ -362,17 +371,14 @@ class QuickArgumentVisitor { if (kBytesPerFprSpillLocation == 4) { if ((kNumQuickFprArgs != 0) && (fpr_index_ + 1 < kNumQuickFprArgs + 1)) { fpr_index_++; - } else { - stack_index_++; } } + } + if (kBytesStackArgLocation == 4) { + stack_index_+= 2; } else { - if (kBytesStackArgLocation == 4) { - stack_index_+= 2; - } else { - CHECK_EQ(kBytesStackArgLocation, 8U); - stack_index_++; - } + CHECK_EQ(kBytesStackArgLocation, 8U); + stack_index_++; } } break; @@ -389,59 +395,10 @@ class QuickArgumentVisitor { CHECK_EQ(kNumQuickFprArgs, 0U); return (kNumQuickGprArgs * kBytesPerGprSpillLocation) + kBytesPerGprSpillLocation /* ArtMethod* */; } else { - size_t offset = kBytesPerGprSpillLocation; // Skip Method*. - size_t gprs_seen = 0; - size_t fprs_seen = 0; - if (!is_static && (gprs_seen < kNumQuickGprArgs)) { - gprs_seen++; - offset += kBytesStackArgLocation; - } - for (uint32_t i = 1; i < shorty_len; ++i) { - switch (shorty[i]) { - case 'Z': - case 'B': - case 'C': - case 'S': - case 'I': - case 'L': - if (gprs_seen < kNumQuickGprArgs) { - gprs_seen++; - offset += kBytesStackArgLocation; - } - break; - case 'J': - if (gprs_seen < kNumQuickGprArgs) { - gprs_seen++; - offset += 2 * kBytesStackArgLocation; - if (kBytesPerGprSpillLocation == 4) { - if (gprs_seen < kNumQuickGprArgs) { - gprs_seen++; - } - } - } - break; - case 'F': - if ((kNumQuickFprArgs != 0) && (fprs_seen + 1 < kNumQuickFprArgs + 1)) { - fprs_seen++; - offset += kBytesStackArgLocation; - } - break; - case 'D': - if ((kNumQuickFprArgs != 0) && (fprs_seen + 1 < kNumQuickFprArgs + 1)) { - fprs_seen++; - offset += 2 * kBytesStackArgLocation; - if (kBytesPerFprSpillLocation == 4) { - if ((kNumQuickFprArgs != 0) && (fprs_seen + 1 < kNumQuickFprArgs + 1)) { - fprs_seen++; - } - } - } - break; - default: - LOG(FATAL) << "Unexpected shorty character: " << shorty[i] << " in " << shorty; - } - } - return offset; + // For now, there is no reg-spill area for the targets with + // hard float ABI. So, the offset pointing to the first method's + // parameter ('this' for non-static methods) should be returned. + return kBytesPerGprSpillLocation; // Skip Method*. } } diff --git a/test/MyClassNatives/MyClassNatives.java b/test/MyClassNatives/MyClassNatives.java index 09f1783780..b5e0204ab8 100644 --- a/test/MyClassNatives/MyClassNatives.java +++ b/test/MyClassNatives/MyClassNatives.java @@ -80,4 +80,16 @@ class MyClassNatives { Object o248, Object o249, Object o250, Object o251, Object o252, Object o253); native void withoutImplementation(); + + native static void stackArgsIntsFirst(int i1, int i2, int i3, int i4, int i5, int i6, int i7, + int i8, int i9, int i10, float f1, float f2, float f3, float f4, float f5, float f6, + float f7, float f8, float f9, float f10); + + native static void stackArgsFloatsFirst(float f1, float f2, float f3, float f4, float f5, + float f6, float f7, float f8, float f9, float f10, int i1, int i2, int i3, int i4, int i5, + int i6, int i7, int i8, int i9, int i10); + + native static void stackArgsMixed(int i1, float f1, int i2, float f2, int i3, float f3, int i4, + 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); } |