summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler/jni/jni_compiler_test.cc213
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc107
-rw-r--r--test/MyClassNatives/MyClassNatives.java12
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);
}