Implement art_quick_aput_object stubs for X86-64 and ARM64
Implement the aput_object stubs for 64b architectures and enable
their testing in stub_test.
Fix missing @PLT for x86.
Add automatic _local labels in function definitions in x86-64 so we
can make local jumps (instead of PLT hoops).
Change-Id: I614b88fd5966acd8a564b87c47d4c50ee605320c
diff --git a/runtime/arch/stub_test.cc b/runtime/arch/stub_test.cc
index 20dc53b..7027b32 100644
--- a/runtime/arch/stub_test.cc
+++ b/runtime/arch/stub_test.cc
@@ -122,13 +122,13 @@
"pushq $0\n\t" // 16B alignment padding
".cfi_adjust_cfa_offset 16\n\t"
"call *%%rax\n\t" // Call the stub
- "addq $16, %%rsp" // Pop nullptr and padding
- // ".cfi_adjust_cfa_offset -16\n\t"
+ "addq $16, %%rsp\n\t" // Pop nullptr and padding
+ ".cfi_adjust_cfa_offset -16\n\t"
: "=a" (result)
// Use the result from rax
: "D"(arg0), "S"(arg1), "d"(arg2), "a"(code)
// This places arg0 into rdi, arg1 into rsi, arg2 into rdx, and code into rax
- : "rcx", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"); // clobber all
+ : "rbx", "rcx", "rbp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"); // clobber all
// TODO: Should we clobber the other registers?
#else
LOG(WARNING) << "Was asked to invoke for an architecture I do not understand.";
@@ -273,7 +273,7 @@
}
-#if defined(__i386__) || defined(__arm__)
+#if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__x86_64__)
extern "C" void art_quick_aput_obj_with_null_and_bound_check(void);
// Do not check non-checked ones, we'd need handlers and stuff...
#endif
@@ -281,7 +281,7 @@
TEST_F(StubTest, APutObj) {
TEST_DISABLED_FOR_HEAP_REFERENCE_POISONING();
-#if defined(__i386__) || defined(__arm__)
+#if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || defined(__x86_64__)
Thread* self = Thread::Current();
// Create an object
ScopedObjectAccess soa(self);
@@ -296,7 +296,7 @@
// Build a string array of size 1
SirtRef<mirror::ObjectArray<mirror::Object> > array(soa.Self(),
- mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), ca.get(), 1));
+ mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), ca.get(), 10));
// Build a string -> should be assignable
SirtRef<mirror::Object> str_obj(soa.Self(),
@@ -308,7 +308,7 @@
// Play with it...
// 1) Success cases
- // 1.1) Assign str_obj to array[0]
+ // 1.1) Assign str_obj to array[0..3]
EXPECT_FALSE(self->IsExceptionPending());
@@ -316,13 +316,51 @@
reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
EXPECT_FALSE(self->IsExceptionPending());
+ EXPECT_EQ(str_obj.get(), array->Get(0));
- // 1.2) Assign null to array[0]
+ Invoke3(reinterpret_cast<size_t>(array.get()), 1U, reinterpret_cast<size_t>(str_obj.get()),
+ reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
+
+ EXPECT_FALSE(self->IsExceptionPending());
+ EXPECT_EQ(str_obj.get(), array->Get(1));
+
+ Invoke3(reinterpret_cast<size_t>(array.get()), 2U, reinterpret_cast<size_t>(str_obj.get()),
+ reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
+
+ EXPECT_FALSE(self->IsExceptionPending());
+ EXPECT_EQ(str_obj.get(), array->Get(2));
+
+ Invoke3(reinterpret_cast<size_t>(array.get()), 3U, reinterpret_cast<size_t>(str_obj.get()),
+ reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
+
+ EXPECT_FALSE(self->IsExceptionPending());
+ EXPECT_EQ(str_obj.get(), array->Get(3));
+
+ // 1.2) Assign null to array[0..3]
Invoke3(reinterpret_cast<size_t>(array.get()), 0U, reinterpret_cast<size_t>(nullptr),
reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
EXPECT_FALSE(self->IsExceptionPending());
+ EXPECT_EQ(nullptr, array->Get(0));
+
+ Invoke3(reinterpret_cast<size_t>(array.get()), 1U, reinterpret_cast<size_t>(nullptr),
+ reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
+
+ EXPECT_FALSE(self->IsExceptionPending());
+ EXPECT_EQ(nullptr, array->Get(1));
+
+ Invoke3(reinterpret_cast<size_t>(array.get()), 2U, reinterpret_cast<size_t>(nullptr),
+ reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
+
+ EXPECT_FALSE(self->IsExceptionPending());
+ EXPECT_EQ(nullptr, array->Get(2));
+
+ Invoke3(reinterpret_cast<size_t>(array.get()), 3U, reinterpret_cast<size_t>(nullptr),
+ reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
+
+ EXPECT_FALSE(self->IsExceptionPending());
+ EXPECT_EQ(nullptr, array->Get(3));
// TODO: Check _which_ exception is thrown. Then make 3) check that it's the right check order.
@@ -347,7 +385,7 @@
// 2.3) Index > 0
- Invoke3(reinterpret_cast<size_t>(array.get()), 1U, reinterpret_cast<size_t>(str_obj.get()),
+ Invoke3(reinterpret_cast<size_t>(array.get()), 10U, reinterpret_cast<size_t>(str_obj.get()),
reinterpret_cast<uintptr_t>(&art_quick_aput_obj_with_null_and_bound_check), self);
EXPECT_TRUE(self->IsExceptionPending());