1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <cstdio> 18 19 #include "art_field-inl.h" 20 #include "art_method-inl.h" 21 #include "base/callee_save_type.h" 22 #include "base/pointer_size.h" 23 #include "class_linker-inl.h" 24 #include "class_root-inl.h" 25 #include "common_runtime_test.h" 26 #include "entrypoints/quick/quick_entrypoints_enum.h" 27 #include "imt_conflict_table.h" 28 #include "jni/jni_internal.h" 29 #include "linear_alloc-inl.h" 30 #include "mirror/class-alloc-inl.h" 31 #include "mirror/string-inl.h" 32 #include "mirror/object_array-alloc-inl.h" 33 #include "scoped_thread_state_change-inl.h" 34 35 namespace art HIDDEN { 36 37 38 class StubTest : public CommonRuntimeTest { 39 protected: 40 // We need callee-save methods set up in the Runtime for exceptions. SetUp()41 void SetUp() override { 42 // Do the normal setup. 43 CommonRuntimeTest::SetUp(); 44 45 { 46 // Create callee-save methods 47 ScopedObjectAccess soa(Thread::Current()); 48 runtime_->SetInstructionSet(kRuntimeISA); 49 for (uint32_t i = 0; i < static_cast<uint32_t>(CalleeSaveType::kLastCalleeSaveType); ++i) { 50 CalleeSaveType type = CalleeSaveType(i); 51 if (!runtime_->HasCalleeSaveMethod(type)) { 52 runtime_->SetCalleeSaveMethod(runtime_->CreateCalleeSaveMethod(), type); 53 } 54 } 55 } 56 } 57 SetUpRuntimeOptions(RuntimeOptions * options)58 void SetUpRuntimeOptions(RuntimeOptions *options) override { 59 // Use a smaller heap 60 for (std::pair<std::string, const void*>& pair : *options) { 61 if (pair.first.find("-Xmx") == 0) { 62 pair.first = "-Xmx4M"; // Smallest we can go. 63 } 64 } 65 options->push_back(std::make_pair("-Xint", nullptr)); 66 } 67 68 // Helper function needed since TEST_F makes a new class. GetTlsPtr(Thread * self)69 Thread::tls_ptr_sized_values* GetTlsPtr(Thread* self) { 70 return &self->tlsPtr_; 71 } 72 73 public: Invoke3(size_t arg0,size_t arg1,size_t arg2,uintptr_t code,Thread * self)74 size_t Invoke3(size_t arg0, size_t arg1, size_t arg2, uintptr_t code, Thread* self) { 75 return Invoke3WithReferrer(arg0, arg1, arg2, code, self, nullptr); 76 } 77 78 // TODO: Set up a frame according to referrer's specs. Invoke3WithReferrer(size_t arg0,size_t arg1,size_t arg2,uintptr_t code,Thread * self,ArtMethod * referrer)79 size_t Invoke3WithReferrer(size_t arg0, size_t arg1, size_t arg2, uintptr_t code, Thread* self, 80 ArtMethod* referrer) { 81 return Invoke3WithReferrerAndHidden(arg0, arg1, arg2, code, self, referrer, 0); 82 } 83 84 // TODO: Set up a frame according to referrer's specs. Invoke3WithReferrerAndHidden(size_t arg0,size_t arg1,size_t arg2,uintptr_t code,Thread * self,ArtMethod * referrer,size_t hidden)85 size_t Invoke3WithReferrerAndHidden(size_t arg0, size_t arg1, size_t arg2, uintptr_t code, 86 Thread* self, ArtMethod* referrer, size_t hidden) { 87 // Push a transition back into managed code onto the linked list in thread. 88 ManagedStack fragment; 89 self->PushManagedStackFragment(&fragment); 90 91 size_t result; 92 size_t fpr_result = 0; 93 #if defined(__i386__) 94 // TODO: Set the thread? 95 #define PUSH(reg) "push " # reg "\n\t .cfi_adjust_cfa_offset 4\n\t" 96 #define POP(reg) "pop " # reg "\n\t .cfi_adjust_cfa_offset -4\n\t" 97 __asm__ __volatile__( 98 "movd %[hidden], %%xmm7\n\t" // This is a memory op, so do this early. If it is off of 99 // esp, then we won't be able to access it after spilling. 100 101 // Spill 6 registers. 102 PUSH(%%ebx) 103 PUSH(%%ecx) 104 PUSH(%%edx) 105 PUSH(%%esi) 106 PUSH(%%edi) 107 PUSH(%%ebp) 108 109 // Store the inputs to the stack, but keep the referrer up top, less work. 110 PUSH(%[referrer]) // Align stack. 111 PUSH(%[referrer]) // Store referrer 112 113 PUSH(%[arg0]) 114 PUSH(%[arg1]) 115 PUSH(%[arg2]) 116 PUSH(%[code]) 117 // Now read them back into the required registers. 118 POP(%%edi) 119 POP(%%edx) 120 POP(%%ecx) 121 POP(%%eax) 122 // Call is prepared now. 123 124 "call *%%edi\n\t" // Call the stub 125 "addl $8, %%esp\n\t" // Pop referrer and padding. 126 ".cfi_adjust_cfa_offset -8\n\t" 127 128 // Restore 6 registers. 129 POP(%%ebp) 130 POP(%%edi) 131 POP(%%esi) 132 POP(%%edx) 133 POP(%%ecx) 134 POP(%%ebx) 135 136 : "=a" (result) 137 // Use the result from eax 138 : [arg0] "r"(arg0), [arg1] "r"(arg1), [arg2] "r"(arg2), [code] "r"(code), 139 [referrer]"r"(referrer), [hidden]"m"(hidden) 140 // This places code into edi, arg0 into eax, arg1 into ecx, and arg2 into edx 141 : "memory", "xmm7"); // clobber. 142 #undef PUSH 143 #undef POP 144 #elif defined(__arm__) 145 __asm__ __volatile__( 146 "push {r1-r12, lr}\n\t" // Save state, 13*4B = 52B 147 ".cfi_adjust_cfa_offset 52\n\t" 148 "push {r9}\n\t" 149 ".cfi_adjust_cfa_offset 4\n\t" 150 "mov r9, %[referrer]\n\n" 151 "str r9, [sp, #-8]!\n\t" // Push referrer, +8B padding so 16B aligned 152 ".cfi_adjust_cfa_offset 8\n\t" 153 "ldr r9, [sp, #8]\n\t" 154 155 // Push everything on the stack, so we don't rely on the order. What a mess. :-( 156 "sub sp, sp, #24\n\t" 157 "str %[arg0], [sp]\n\t" 158 "str %[arg1], [sp, #4]\n\t" 159 "str %[arg2], [sp, #8]\n\t" 160 "str %[code], [sp, #12]\n\t" 161 "str %[self], [sp, #16]\n\t" 162 "str %[hidden], [sp, #20]\n\t" 163 "ldr r0, [sp]\n\t" 164 "ldr r1, [sp, #4]\n\t" 165 "ldr r2, [sp, #8]\n\t" 166 "ldr r3, [sp, #12]\n\t" 167 "ldr r9, [sp, #16]\n\t" 168 "ldr r12, [sp, #20]\n\t" 169 "add sp, sp, #24\n\t" 170 171 "blx r3\n\t" // Call the stub 172 "add sp, sp, #12\n\t" // Pop null and padding 173 ".cfi_adjust_cfa_offset -12\n\t" 174 "pop {r1-r12, lr}\n\t" // Restore state 175 ".cfi_adjust_cfa_offset -52\n\t" 176 "mov %[result], r0\n\t" // Save the result 177 : [result] "=r" (result) 178 // Use the result from r0 179 : [arg0] "r"(arg0), [arg1] "r"(arg1), [arg2] "r"(arg2), [code] "r"(code), [self] "r"(self), 180 [referrer] "r"(referrer), [hidden] "r"(hidden) 181 : "r0", "memory"); // clobber. 182 #elif defined(__aarch64__) 183 __asm__ __volatile__( 184 // Spill x0-x7 which we say we don't clobber. May contain args. 185 "sub sp, sp, #80\n\t" 186 ".cfi_adjust_cfa_offset 80\n\t" 187 "stp x0, x1, [sp]\n\t" 188 "stp x2, x3, [sp, #16]\n\t" 189 "stp x4, x5, [sp, #32]\n\t" 190 "stp x6, x7, [sp, #48]\n\t" 191 // To be extra defensive, store x20,x21. We do this because some of the stubs might make a 192 // transition into the runtime via the blr instruction below and *not* save x20. 193 "stp x20, x21, [sp, #64]\n\t" 194 195 "sub sp, sp, #16\n\t" // Reserve stack space, 16B aligned 196 ".cfi_adjust_cfa_offset 16\n\t" 197 "str %[referrer], [sp]\n\t" // referrer 198 199 // Push everything on the stack, so we don't rely on the order. What a mess. :-( 200 "sub sp, sp, #48\n\t" 201 ".cfi_adjust_cfa_offset 48\n\t" 202 // All things are "r" constraints, so direct str/stp should work. 203 "stp %[arg0], %[arg1], [sp]\n\t" 204 "stp %[arg2], %[code], [sp, #16]\n\t" 205 "stp %[self], %[hidden], [sp, #32]\n\t" 206 207 // Now we definitely have x0-x3 free, use it to garble d8 - d15 208 "movk x0, #0xfad0\n\t" 209 "movk x0, #0xebad, lsl #16\n\t" 210 "movk x0, #0xfad0, lsl #32\n\t" 211 "movk x0, #0xebad, lsl #48\n\t" 212 "fmov d8, x0\n\t" 213 "add x0, x0, 1\n\t" 214 "fmov d9, x0\n\t" 215 "add x0, x0, 1\n\t" 216 "fmov d10, x0\n\t" 217 "add x0, x0, 1\n\t" 218 "fmov d11, x0\n\t" 219 "add x0, x0, 1\n\t" 220 "fmov d12, x0\n\t" 221 "add x0, x0, 1\n\t" 222 "fmov d13, x0\n\t" 223 "add x0, x0, 1\n\t" 224 "fmov d14, x0\n\t" 225 "add x0, x0, 1\n\t" 226 "fmov d15, x0\n\t" 227 228 // Load call params into the right registers. 229 "ldp x0, x1, [sp]\n\t" 230 "ldp x2, x3, [sp, #16]\n\t" 231 "ldp x19, x17, [sp, #32]\n\t" 232 "add sp, sp, #48\n\t" 233 ".cfi_adjust_cfa_offset -48\n\t" 234 235 "blr x3\n\t" // Call the stub 236 "mov x8, x0\n\t" // Store result 237 "add sp, sp, #16\n\t" // Drop the quick "frame" 238 ".cfi_adjust_cfa_offset -16\n\t" 239 240 // Test d8 - d15. We can use x1 and x2. 241 "movk x1, #0xfad0\n\t" 242 "movk x1, #0xebad, lsl #16\n\t" 243 "movk x1, #0xfad0, lsl #32\n\t" 244 "movk x1, #0xebad, lsl #48\n\t" 245 "fmov x2, d8\n\t" 246 "cmp x1, x2\n\t" 247 "b.ne 1f\n\t" 248 "add x1, x1, 1\n\t" 249 250 "fmov x2, d9\n\t" 251 "cmp x1, x2\n\t" 252 "b.ne 1f\n\t" 253 "add x1, x1, 1\n\t" 254 255 "fmov x2, d10\n\t" 256 "cmp x1, x2\n\t" 257 "b.ne 1f\n\t" 258 "add x1, x1, 1\n\t" 259 260 "fmov x2, d11\n\t" 261 "cmp x1, x2\n\t" 262 "b.ne 1f\n\t" 263 "add x1, x1, 1\n\t" 264 265 "fmov x2, d12\n\t" 266 "cmp x1, x2\n\t" 267 "b.ne 1f\n\t" 268 "add x1, x1, 1\n\t" 269 270 "fmov x2, d13\n\t" 271 "cmp x1, x2\n\t" 272 "b.ne 1f\n\t" 273 "add x1, x1, 1\n\t" 274 275 "fmov x2, d14\n\t" 276 "cmp x1, x2\n\t" 277 "b.ne 1f\n\t" 278 "add x1, x1, 1\n\t" 279 280 "fmov x2, d15\n\t" 281 "cmp x1, x2\n\t" 282 "b.ne 1f\n\t" 283 284 "mov x9, #0\n\t" // Use x9 as flag, in clobber list 285 286 // Finish up. 287 "2:\n\t" 288 "ldp x0, x1, [sp]\n\t" // Restore stuff not named clobbered, may contain fpr_result 289 "ldp x2, x3, [sp, #16]\n\t" 290 "ldp x4, x5, [sp, #32]\n\t" 291 "ldp x6, x7, [sp, #48]\n\t" 292 "ldp x20, x21, [sp, #64]\n\t" 293 "add sp, sp, #80\n\t" // Free stack space, now sp as on entry 294 ".cfi_adjust_cfa_offset -80\n\t" 295 296 "str x9, %[fpr_result]\n\t" // Store the FPR comparison result 297 "mov %[result], x8\n\t" // Store the call result 298 299 "b 3f\n\t" // Goto end 300 301 // Failed fpr verification. 302 "1:\n\t" 303 "mov x9, #1\n\t" 304 "b 2b\n\t" // Goto finish-up 305 306 // End 307 "3:\n\t" 308 : [result] "=r" (result) 309 // Use the result from r0 310 : [arg0] "0"(arg0), [arg1] "r"(arg1), [arg2] "r"(arg2), [code] "r"(code), [self] "r"(self), 311 [referrer] "r"(referrer), [hidden] "r"(hidden), [fpr_result] "m" (fpr_result) 312 // X18 is a reserved register, cannot be clobbered. 313 // Leave one register unclobbered, which is needed for compiling with 314 // -fstack-protector-strong. According to AAPCS64 registers x9-x15 are caller-saved, 315 // which means we should unclobber one of the callee-saved registers that are unused. 316 // Here we use x20. 317 // http://b/72613441, Clang 7.0 asks for one more register, so we do not reserve x21. 318 : "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x19", 319 "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x30", 320 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", 321 "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", 322 "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", 323 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", 324 "memory"); 325 #elif defined(__x86_64__) && !defined(__APPLE__) 326 #define PUSH(reg) "pushq " # reg "\n\t .cfi_adjust_cfa_offset 8\n\t" 327 #define POP(reg) "popq " # reg "\n\t .cfi_adjust_cfa_offset -8\n\t" 328 // Note: Uses the native convention. We do a callee-save regimen by manually spilling and 329 // restoring almost all registers. 330 // TODO: Set the thread? 331 __asm__ __volatile__( 332 // Spill almost everything (except rax, rsp). 14 registers. 333 PUSH(%%rbx) 334 PUSH(%%rcx) 335 PUSH(%%rdx) 336 PUSH(%%rsi) 337 PUSH(%%rdi) 338 PUSH(%%rbp) 339 PUSH(%%r8) 340 PUSH(%%r9) 341 PUSH(%%r10) 342 PUSH(%%r11) 343 PUSH(%%r12) 344 PUSH(%%r13) 345 PUSH(%%r14) 346 PUSH(%%r15) 347 348 PUSH(%[referrer]) // Push referrer & 16B alignment padding 349 PUSH(%[referrer]) 350 351 // Now juggle the input registers. 352 PUSH(%[arg0]) 353 PUSH(%[arg1]) 354 PUSH(%[arg2]) 355 PUSH(%[hidden]) 356 PUSH(%[code]) 357 POP(%%r8) 358 POP(%%rax) 359 POP(%%rdx) 360 POP(%%rsi) 361 POP(%%rdi) 362 363 "call *%%r8\n\t" // Call the stub 364 "addq $16, %%rsp\n\t" // Pop null and padding 365 ".cfi_adjust_cfa_offset -16\n\t" 366 367 POP(%%r15) 368 POP(%%r14) 369 POP(%%r13) 370 POP(%%r12) 371 POP(%%r11) 372 POP(%%r10) 373 POP(%%r9) 374 POP(%%r8) 375 POP(%%rbp) 376 POP(%%rdi) 377 POP(%%rsi) 378 POP(%%rdx) 379 POP(%%rcx) 380 POP(%%rbx) 381 382 : "=a" (result) 383 // Use the result from rax 384 : [arg0] "r"(arg0), [arg1] "r"(arg1), [arg2] "r"(arg2), [code] "r"(code), 385 [referrer] "r"(referrer), [hidden] "r"(hidden) 386 // This places arg0 into rdi, arg1 into rsi, arg2 into rdx, and code into some other 387 // register. We can't use "b" (rbx), as ASAN uses this for the frame pointer. 388 : "memory"); // We spill and restore (almost) all registers, so only mention memory here. 389 #undef PUSH 390 #undef POP 391 #else 392 UNUSED(arg0, arg1, arg2, code, referrer, hidden); 393 LOG(WARNING) << "Was asked to invoke for an architecture I do not understand."; 394 result = 0; 395 #endif 396 // Pop transition. 397 self->PopManagedStackFragment(fragment); 398 399 fp_result = fpr_result; 400 EXPECT_EQ(0U, fp_result); 401 402 return result; 403 } 404 GetEntrypoint(Thread * self,QuickEntrypointEnum entrypoint)405 static uintptr_t GetEntrypoint(Thread* self, QuickEntrypointEnum entrypoint) { 406 int32_t offset; 407 offset = GetThreadOffset<kRuntimePointerSize>(entrypoint).Int32Value(); 408 return *reinterpret_cast<uintptr_t*>(reinterpret_cast<uint8_t*>(self) + offset); 409 } 410 411 protected: 412 size_t fp_result; 413 }; 414 415 TEST_F(StubTest,Memcpy)416 TEST_F(StubTest, Memcpy) { 417 #if defined(__i386__) || (defined(__x86_64__) && !defined(__APPLE__)) 418 Thread* self = Thread::Current(); 419 420 uint32_t orig[20]; 421 uint32_t trg[20]; 422 for (size_t i = 0; i < 20; ++i) { 423 orig[i] = i; 424 trg[i] = 0; 425 } 426 427 Invoke3(reinterpret_cast<size_t>(&trg[4]), reinterpret_cast<size_t>(&orig[4]), 428 10 * sizeof(uint32_t), StubTest::GetEntrypoint(self, kQuickMemcpy), self); 429 430 EXPECT_EQ(orig[0], trg[0]); 431 432 for (size_t i = 1; i < 4; ++i) { 433 EXPECT_NE(orig[i], trg[i]); 434 } 435 436 for (size_t i = 4; i < 14; ++i) { 437 EXPECT_EQ(orig[i], trg[i]); 438 } 439 440 for (size_t i = 14; i < 20; ++i) { 441 EXPECT_NE(orig[i], trg[i]); 442 } 443 444 // TODO: Test overlapping? 445 446 #else 447 LOG(INFO) << "Skipping memcpy as I don't know how to do that on " << kRuntimeISA; 448 // Force-print to std::cout so it's also outside the logcat. 449 std::cout << "Skipping memcpy as I don't know how to do that on " << kRuntimeISA << std::endl; 450 #endif 451 } 452 TEST_F(StubTest,LockObject)453 TEST_F(StubTest, LockObject) { 454 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 455 (defined(__x86_64__) && !defined(__APPLE__)) 456 static constexpr size_t kThinLockLoops = 100; 457 458 Thread* self = Thread::Current(); 459 460 const uintptr_t art_quick_lock_object = StubTest::GetEntrypoint(self, kQuickLockObject); 461 462 // Create an object 463 ScopedObjectAccess soa(self); 464 // garbage is created during ClassLinker::Init 465 466 StackHandleScope<2> hs(soa.Self()); 467 Handle<mirror::String> obj( 468 hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello, world!"))); 469 LockWord lock = obj->GetLockWord(false); 470 LockWord::LockState old_state = lock.GetState(); 471 EXPECT_EQ(LockWord::LockState::kUnlocked, old_state); 472 473 Invoke3(reinterpret_cast<size_t>(obj.Get()), 0U, 0U, art_quick_lock_object, self); 474 475 LockWord lock_after = obj->GetLockWord(false); 476 LockWord::LockState new_state = lock_after.GetState(); 477 EXPECT_EQ(LockWord::LockState::kThinLocked, new_state); 478 EXPECT_EQ(lock_after.ThinLockCount(), 0U); // Thin lock starts count at zero 479 480 for (size_t i = 1; i < kThinLockLoops; ++i) { 481 Invoke3(reinterpret_cast<size_t>(obj.Get()), 0U, 0U, art_quick_lock_object, self); 482 483 // Check we're at lock count i 484 485 LockWord l_inc = obj->GetLockWord(false); 486 LockWord::LockState l_inc_state = l_inc.GetState(); 487 EXPECT_EQ(LockWord::LockState::kThinLocked, l_inc_state); 488 EXPECT_EQ(l_inc.ThinLockCount(), i); 489 } 490 491 // Force a fat lock by running identity hashcode to fill up lock word. 492 Handle<mirror::String> obj2(hs.NewHandle( 493 mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello, world!"))); 494 495 obj2->IdentityHashCode(); 496 497 Invoke3(reinterpret_cast<size_t>(obj2.Get()), 0U, 0U, art_quick_lock_object, self); 498 499 LockWord lock_after2 = obj2->GetLockWord(false); 500 LockWord::LockState new_state2 = lock_after2.GetState(); 501 EXPECT_EQ(LockWord::LockState::kFatLocked, new_state2); 502 EXPECT_NE(lock_after2.FatLockMonitor(), static_cast<Monitor*>(nullptr)); 503 504 // Test done. 505 #else 506 LOG(INFO) << "Skipping lock_object as I don't know how to do that on " << kRuntimeISA; 507 // Force-print to std::cout so it's also outside the logcat. 508 std::cout << "Skipping lock_object as I don't know how to do that on " << kRuntimeISA << std::endl; 509 #endif 510 } 511 512 513 class RandGen { 514 public: RandGen(uint32_t seed)515 explicit RandGen(uint32_t seed) : val_(seed) {} 516 next()517 uint32_t next() { 518 val_ = val_ * 48271 % 2147483647 + 13; 519 return val_; 520 } 521 522 uint32_t val_; 523 }; 524 525 526 // NO_THREAD_SAFETY_ANALYSIS as we do not want to grab exclusive mutator lock for MonitorInfo. TestUnlockObject(StubTest * test)527 static void TestUnlockObject(StubTest* test) NO_THREAD_SAFETY_ANALYSIS { 528 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 529 (defined(__x86_64__) && !defined(__APPLE__)) 530 static constexpr size_t kThinLockLoops = 100; 531 532 Thread* self = Thread::Current(); 533 534 const uintptr_t art_quick_lock_object = StubTest::GetEntrypoint(self, kQuickLockObject); 535 const uintptr_t art_quick_unlock_object = StubTest::GetEntrypoint(self, kQuickUnlockObject); 536 // Create an object 537 ScopedObjectAccess soa(self); 538 // garbage is created during ClassLinker::Init 539 static constexpr size_t kNumberOfLocks = 10; // Number of objects = lock 540 StackHandleScope<kNumberOfLocks + 1> hs(self); 541 Handle<mirror::String> obj( 542 hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello, world!"))); 543 LockWord lock = obj->GetLockWord(false); 544 LockWord::LockState old_state = lock.GetState(); 545 EXPECT_EQ(LockWord::LockState::kUnlocked, old_state); 546 547 test->Invoke3(reinterpret_cast<size_t>(obj.Get()), 0U, 0U, art_quick_unlock_object, self); 548 // This should be an illegal monitor state. 549 EXPECT_TRUE(self->IsExceptionPending()); 550 self->ClearException(); 551 552 LockWord lock_after = obj->GetLockWord(false); 553 LockWord::LockState new_state = lock_after.GetState(); 554 EXPECT_EQ(LockWord::LockState::kUnlocked, new_state); 555 556 test->Invoke3(reinterpret_cast<size_t>(obj.Get()), 0U, 0U, art_quick_lock_object, self); 557 558 LockWord lock_after2 = obj->GetLockWord(false); 559 LockWord::LockState new_state2 = lock_after2.GetState(); 560 EXPECT_EQ(LockWord::LockState::kThinLocked, new_state2); 561 562 test->Invoke3(reinterpret_cast<size_t>(obj.Get()), 0U, 0U, art_quick_unlock_object, self); 563 564 LockWord lock_after3 = obj->GetLockWord(false); 565 LockWord::LockState new_state3 = lock_after3.GetState(); 566 EXPECT_EQ(LockWord::LockState::kUnlocked, new_state3); 567 568 // Stress test: 569 // Keep a number of objects and their locks in flight. Randomly lock or unlock one of them in 570 // each step. 571 572 RandGen r(0x1234); 573 574 constexpr size_t kIterations = 10000; // Number of iterations 575 constexpr size_t kMoveToFat = 1000; // Chance of 1:kMoveFat to make a lock fat. 576 577 size_t counts[kNumberOfLocks]; 578 bool fat[kNumberOfLocks]; // Whether a lock should be thin or fat. 579 Handle<mirror::String> objects[kNumberOfLocks]; 580 581 // Initialize = allocate. 582 for (size_t i = 0; i < kNumberOfLocks; ++i) { 583 counts[i] = 0; 584 fat[i] = false; 585 objects[i] = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "")); 586 } 587 588 for (size_t i = 0; i < kIterations; ++i) { 589 // Select which lock to update. 590 size_t index = r.next() % kNumberOfLocks; 591 592 // Make lock fat? 593 if (!fat[index] && (r.next() % kMoveToFat == 0)) { 594 fat[index] = true; 595 objects[index]->IdentityHashCode(); 596 597 LockWord lock_iter = objects[index]->GetLockWord(false); 598 LockWord::LockState iter_state = lock_iter.GetState(); 599 if (counts[index] == 0) { 600 EXPECT_EQ(LockWord::LockState::kHashCode, iter_state); 601 } else { 602 EXPECT_EQ(LockWord::LockState::kFatLocked, iter_state); 603 } 604 } else { 605 bool take_lock; // Whether to lock or unlock in this step. 606 if (counts[index] == 0) { 607 take_lock = true; 608 } else if (counts[index] == kThinLockLoops) { 609 take_lock = false; 610 } else { 611 // Randomly. 612 take_lock = r.next() % 2 == 0; 613 } 614 615 if (take_lock) { 616 test->Invoke3(reinterpret_cast<size_t>(objects[index].Get()), 0U, 0U, art_quick_lock_object, 617 self); 618 counts[index]++; 619 } else { 620 test->Invoke3(reinterpret_cast<size_t>(objects[index].Get()), 0U, 0U, 621 art_quick_unlock_object, self); 622 counts[index]--; 623 } 624 625 EXPECT_FALSE(self->IsExceptionPending()); 626 627 // Check the new state. 628 LockWord lock_iter = objects[index]->GetLockWord(true); 629 LockWord::LockState iter_state = lock_iter.GetState(); 630 if (fat[index]) { 631 // Abuse MonitorInfo. 632 EXPECT_EQ(LockWord::LockState::kFatLocked, iter_state) << index; 633 MonitorInfo info(objects[index].Get()); 634 EXPECT_EQ(counts[index], info.entry_count_) << index; 635 } else { 636 if (counts[index] > 0) { 637 EXPECT_EQ(LockWord::LockState::kThinLocked, iter_state); 638 EXPECT_EQ(counts[index] - 1, lock_iter.ThinLockCount()); 639 } else { 640 EXPECT_EQ(LockWord::LockState::kUnlocked, iter_state); 641 } 642 } 643 } 644 } 645 646 // Unlock the remaining count times and then check it's unlocked. Then deallocate. 647 // Go reverse order to correctly handle Handles. 648 for (size_t i = 0; i < kNumberOfLocks; ++i) { 649 size_t index = kNumberOfLocks - 1 - i; 650 size_t count = counts[index]; 651 while (count > 0) { 652 test->Invoke3(reinterpret_cast<size_t>(objects[index].Get()), 0U, 0U, art_quick_unlock_object, 653 self); 654 count--; 655 } 656 657 LockWord lock_after4 = objects[index]->GetLockWord(false); 658 LockWord::LockState new_state4 = lock_after4.GetState(); 659 EXPECT_TRUE(LockWord::LockState::kUnlocked == new_state4 660 || LockWord::LockState::kFatLocked == new_state4); 661 } 662 663 // Test done. 664 #else 665 UNUSED(test); 666 LOG(INFO) << "Skipping unlock_object as I don't know how to do that on " << kRuntimeISA; 667 // Force-print to std::cout so it's also outside the logcat. 668 std::cout << "Skipping unlock_object as I don't know how to do that on " << kRuntimeISA << std::endl; 669 #endif 670 } 671 TEST_F(StubTest,UnlockObject)672 TEST_F(StubTest, UnlockObject) { 673 // This will lead to monitor error messages in the log. 674 ScopedLogSeverity sls(LogSeverity::FATAL); 675 676 TestUnlockObject(this); 677 } 678 679 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 680 (defined(__x86_64__) && !defined(__APPLE__)) 681 extern "C" void art_quick_check_instance_of(void); 682 #endif 683 TEST_F(StubTest,CheckCast)684 TEST_F(StubTest, CheckCast) { 685 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 686 (defined(__x86_64__) && !defined(__APPLE__)) 687 Thread* self = Thread::Current(); 688 689 const uintptr_t art_quick_check_instance_of = 690 StubTest::GetEntrypoint(self, kQuickCheckInstanceOf); 691 692 // Find some classes. 693 ScopedObjectAccess soa(self); 694 // garbage is created during ClassLinker::Init 695 696 VariableSizedHandleScope hs(soa.Self()); 697 Handle<mirror::Class> klass_obj( 698 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"))); 699 Handle<mirror::Class> klass_str( 700 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/String;"))); 701 Handle<mirror::Class> klass_list( 702 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/util/List;"))); 703 Handle<mirror::Class> klass_cloneable( 704 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Cloneable;"))); 705 Handle<mirror::Class> klass_array_list( 706 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/util/ArrayList;"))); 707 Handle<mirror::Object> obj(hs.NewHandle(klass_obj->AllocObject(soa.Self()))); 708 Handle<mirror::String> string(hs.NewHandle( 709 mirror::String::AllocFromModifiedUtf8(soa.Self(), "ABCD"))); 710 Handle<mirror::Object> array_list(hs.NewHandle(klass_array_list->AllocObject(soa.Self()))); 711 712 EXPECT_FALSE(self->IsExceptionPending()); 713 714 Invoke3(reinterpret_cast<size_t>(obj.Get()), 715 reinterpret_cast<size_t>(klass_obj.Get()), 716 0U, 717 art_quick_check_instance_of, 718 self); 719 EXPECT_FALSE(self->IsExceptionPending()); 720 721 // Expected true: Test string instance of java.lang.String. 722 Invoke3(reinterpret_cast<size_t>(string.Get()), 723 reinterpret_cast<size_t>(klass_str.Get()), 724 0U, 725 art_quick_check_instance_of, 726 self); 727 EXPECT_FALSE(self->IsExceptionPending()); 728 729 // Expected true: Test string instance of java.lang.Object. 730 Invoke3(reinterpret_cast<size_t>(string.Get()), 731 reinterpret_cast<size_t>(klass_obj.Get()), 732 0U, 733 art_quick_check_instance_of, 734 self); 735 EXPECT_FALSE(self->IsExceptionPending()); 736 737 // Expected false: Test object instance of java.lang.String. 738 Invoke3(reinterpret_cast<size_t>(obj.Get()), 739 reinterpret_cast<size_t>(klass_str.Get()), 740 0U, 741 art_quick_check_instance_of, 742 self); 743 EXPECT_TRUE(self->IsExceptionPending()); 744 self->ClearException(); 745 746 Invoke3(reinterpret_cast<size_t>(array_list.Get()), 747 reinterpret_cast<size_t>(klass_list.Get()), 748 0U, 749 art_quick_check_instance_of, 750 self); 751 EXPECT_FALSE(self->IsExceptionPending()); 752 753 Invoke3(reinterpret_cast<size_t>(array_list.Get()), 754 reinterpret_cast<size_t>(klass_cloneable.Get()), 755 0U, 756 art_quick_check_instance_of, 757 self); 758 EXPECT_FALSE(self->IsExceptionPending()); 759 760 Invoke3(reinterpret_cast<size_t>(string.Get()), 761 reinterpret_cast<size_t>(klass_array_list.Get()), 762 0U, 763 art_quick_check_instance_of, 764 self); 765 EXPECT_TRUE(self->IsExceptionPending()); 766 self->ClearException(); 767 768 Invoke3(reinterpret_cast<size_t>(string.Get()), 769 reinterpret_cast<size_t>(klass_cloneable.Get()), 770 0U, 771 art_quick_check_instance_of, 772 self); 773 EXPECT_TRUE(self->IsExceptionPending()); 774 self->ClearException(); 775 776 #else 777 LOG(INFO) << "Skipping check_cast as I don't know how to do that on " << kRuntimeISA; 778 // Force-print to std::cout so it's also outside the logcat. 779 std::cout << "Skipping check_cast as I don't know how to do that on " << kRuntimeISA << std::endl; 780 #endif 781 } 782 TEST_F(StubTest,AllocObject)783 TEST_F(StubTest, AllocObject) { 784 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 785 (defined(__x86_64__) && !defined(__APPLE__)) 786 // This will lead to OOM error messages in the log. 787 ScopedLogSeverity sls(LogSeverity::FATAL); 788 789 // TODO: Check the "Unresolved" allocation stubs 790 791 Thread* self = Thread::Current(); 792 // Create an object 793 ScopedObjectAccess soa(self); 794 // garbage is created during ClassLinker::Init 795 796 StackHandleScope<2> hs(soa.Self()); 797 Handle<mirror::Class> c( 798 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"))); 799 800 // Play with it... 801 802 EXPECT_FALSE(self->IsExceptionPending()); 803 { 804 size_t result = Invoke3(reinterpret_cast<size_t>(c.Get()), 0u, 0U, 805 StubTest::GetEntrypoint(self, kQuickAllocObjectWithChecks), 806 self); 807 808 EXPECT_FALSE(self->IsExceptionPending()); 809 EXPECT_NE(reinterpret_cast<size_t>(nullptr), result); 810 ObjPtr<mirror::Object> obj = reinterpret_cast<mirror::Object*>(result); 811 EXPECT_OBJ_PTR_EQ(c.Get(), obj->GetClass()); 812 VerifyObject(obj); 813 } 814 815 { 816 size_t result = Invoke3(reinterpret_cast<size_t>(c.Get()), 0u, 0U, 817 StubTest::GetEntrypoint(self, kQuickAllocObjectResolved), 818 self); 819 820 EXPECT_FALSE(self->IsExceptionPending()); 821 EXPECT_NE(reinterpret_cast<size_t>(nullptr), result); 822 ObjPtr<mirror::Object> obj = reinterpret_cast<mirror::Object*>(result); 823 EXPECT_OBJ_PTR_EQ(c.Get(), obj->GetClass()); 824 VerifyObject(obj); 825 } 826 827 { 828 size_t result = Invoke3(reinterpret_cast<size_t>(c.Get()), 0u, 0U, 829 StubTest::GetEntrypoint(self, kQuickAllocObjectInitialized), 830 self); 831 832 EXPECT_FALSE(self->IsExceptionPending()); 833 EXPECT_NE(reinterpret_cast<size_t>(nullptr), result); 834 ObjPtr<mirror::Object> obj = reinterpret_cast<mirror::Object*>(result); 835 EXPECT_OBJ_PTR_EQ(c.Get(), obj->GetClass()); 836 VerifyObject(obj); 837 } 838 839 // Failure tests. 840 841 // Out-of-memory. 842 { 843 Runtime::Current()->GetHeap()->SetIdealFootprint(1 * GB); 844 845 // Array helps to fill memory faster. 846 Handle<mirror::Class> ca( 847 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;"))); 848 849 // Use arbitrary large amount for now. 850 static const size_t kMaxHandles = 1000000; 851 std::unique_ptr<StackHandleScope<kMaxHandles>> hsp(new StackHandleScope<kMaxHandles>(self)); 852 853 std::vector<Handle<mirror::Object>> handles; 854 // Start allocating with 128K 855 size_t length = 128 * KB / 4; 856 while (length > 10) { 857 Handle<mirror::Object> h(hsp->NewHandle<mirror::Object>( 858 mirror::ObjectArray<mirror::Object>::Alloc(soa.Self(), ca.Get(), length / 4))); 859 if (self->IsExceptionPending() || h == nullptr) { 860 self->ClearException(); 861 862 // Try a smaller length 863 length = length / 8; 864 // Use at most half the reported free space. 865 size_t mem = Runtime::Current()->GetHeap()->GetFreeMemory(); 866 if (length * 8 > mem) { 867 length = mem / 8; 868 } 869 } else { 870 handles.push_back(h); 871 } 872 } 873 LOG(INFO) << "Used " << handles.size() << " arrays to fill space."; 874 875 // Allocate simple objects till it fails. 876 while (!self->IsExceptionPending()) { 877 Handle<mirror::Object> h = hsp->NewHandle(c->AllocObject(soa.Self())); 878 if (!self->IsExceptionPending() && h != nullptr) { 879 handles.push_back(h); 880 } 881 } 882 self->ClearException(); 883 884 size_t result = Invoke3(reinterpret_cast<size_t>(c.Get()), 0u, 0U, 885 StubTest::GetEntrypoint(self, kQuickAllocObjectInitialized), 886 self); 887 EXPECT_TRUE(self->IsExceptionPending()); 888 self->ClearException(); 889 EXPECT_EQ(reinterpret_cast<size_t>(nullptr), result); 890 } 891 892 // Tests done. 893 #else 894 LOG(INFO) << "Skipping alloc_object as I don't know how to do that on " << kRuntimeISA; 895 // Force-print to std::cout so it's also outside the logcat. 896 std::cout << "Skipping alloc_object as I don't know how to do that on " << kRuntimeISA << std::endl; 897 #endif 898 } 899 TEST_F(StubTest,AllocObjectArray)900 TEST_F(StubTest, AllocObjectArray) { 901 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 902 (defined(__x86_64__) && !defined(__APPLE__)) 903 // TODO: Check the "Unresolved" allocation stubs 904 905 // This will lead to OOM error messages in the log. 906 ScopedLogSeverity sls(LogSeverity::FATAL); 907 908 Thread* self = Thread::Current(); 909 // Create an object 910 ScopedObjectAccess soa(self); 911 // garbage is created during ClassLinker::Init 912 913 StackHandleScope<1> hs(self); 914 Handle<mirror::Class> c( 915 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;"))); 916 917 // Play with it... 918 919 EXPECT_FALSE(self->IsExceptionPending()); 920 921 { 922 // We can use null in the second argument as we do not need a method here (not used in 923 // resolved/initialized cases) 924 size_t result = Invoke3(reinterpret_cast<size_t>(c.Get()), 10U, 925 reinterpret_cast<size_t>(nullptr), 926 StubTest::GetEntrypoint(self, kQuickAllocArrayResolved32), 927 self); 928 EXPECT_FALSE(self->IsExceptionPending()) << mirror::Object::PrettyTypeOf(self->GetException()); 929 EXPECT_NE(reinterpret_cast<size_t>(nullptr), result); 930 ObjPtr<mirror::Object> obj = reinterpret_cast<mirror::Object*>(result); 931 EXPECT_TRUE(obj->IsArrayInstance()); 932 EXPECT_TRUE(obj->IsObjectArray()); 933 EXPECT_OBJ_PTR_EQ(c.Get(), obj->GetClass()); 934 VerifyObject(obj); 935 ObjPtr<mirror::Array> array = reinterpret_cast<mirror::Array*>(result); 936 EXPECT_EQ(array->GetLength(), 10); 937 } 938 939 // Failure tests. 940 941 // Out-of-memory. 942 { 943 size_t result = Invoke3(reinterpret_cast<size_t>(c.Get()), 944 GB, // that should fail... 945 reinterpret_cast<size_t>(nullptr), 946 StubTest::GetEntrypoint(self, kQuickAllocArrayResolved32), 947 self); 948 949 EXPECT_TRUE(self->IsExceptionPending()); 950 self->ClearException(); 951 EXPECT_EQ(reinterpret_cast<size_t>(nullptr), result); 952 } 953 954 // Tests done. 955 #else 956 LOG(INFO) << "Skipping alloc_array as I don't know how to do that on " << kRuntimeISA; 957 // Force-print to std::cout so it's also outside the logcat. 958 std::cout << "Skipping alloc_array as I don't know how to do that on " << kRuntimeISA << std::endl; 959 #endif 960 } 961 962 TEST_F(StubTest,StringCompareTo)963 TEST_F(StubTest, StringCompareTo) { 964 // There is no StringCompareTo runtime entrypoint for __arm__ or __aarch64__. 965 #if defined(__i386__) || (defined(__x86_64__) && !defined(__APPLE__)) 966 // TODO: Check the "Unresolved" allocation stubs 967 968 Thread* self = Thread::Current(); 969 970 const uintptr_t art_quick_string_compareto = StubTest::GetEntrypoint(self, kQuickStringCompareTo); 971 972 ScopedObjectAccess soa(self); 973 // garbage is created during ClassLinker::Init 974 975 // Create some strings 976 // Use array so we can index into it and use a matrix for expected results 977 // Setup: The first half is standard. The second half uses a non-zero offset. 978 // TODO: Shared backing arrays. 979 const char* c[] = { "", "", "a", "aa", "ab", 980 "aacaacaacaacaacaac", // This one's under the default limit to go to __memcmp16. 981 "aacaacaacaacaacaacaacaacaacaacaacaac", // This one's over. 982 "aacaacaacaacaacaacaacaacaacaacaacaaca" }; // As is this one. We need a separate one to 983 // defeat object-equal optimizations. 984 static constexpr size_t kStringCount = arraysize(c); 985 986 StackHandleScope<kStringCount> hs(self); 987 Handle<mirror::String> s[kStringCount]; 988 989 for (size_t i = 0; i < kStringCount; ++i) { 990 s[i] = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), c[i])); 991 } 992 993 // TODO: wide characters 994 995 // Matrix of expectations. First component is first parameter. Note we only check against the 996 // sign, not the value. As we are testing random offsets, we need to compute this and need to 997 // rely on String::CompareTo being correct. 998 int32_t expected[kStringCount][kStringCount]; 999 for (size_t x = 0; x < kStringCount; ++x) { 1000 for (size_t y = 0; y < kStringCount; ++y) { 1001 expected[x][y] = s[x]->CompareTo(s[y].Get()); 1002 } 1003 } 1004 1005 // Play with it... 1006 1007 for (size_t x = 0; x < kStringCount; ++x) { 1008 for (size_t y = 0; y < kStringCount; ++y) { 1009 // Test string_compareto x y 1010 size_t result = Invoke3(reinterpret_cast<size_t>(s[x].Get()), 1011 reinterpret_cast<size_t>(s[y].Get()), 0U, 1012 art_quick_string_compareto, self); 1013 1014 EXPECT_FALSE(self->IsExceptionPending()); 1015 1016 // The result is a 32b signed integer 1017 union { 1018 size_t r; 1019 int32_t i; 1020 } conv; 1021 conv.r = result; 1022 int32_t e = expected[x][y]; 1023 EXPECT_TRUE(e == 0 ? conv.i == 0 : true) << "x=" << c[x] << " y=" << c[y] << " res=" << 1024 conv.r; 1025 EXPECT_TRUE(e < 0 ? conv.i < 0 : true) << "x=" << c[x] << " y=" << c[y] << " res=" << 1026 conv.r; 1027 EXPECT_TRUE(e > 0 ? conv.i > 0 : true) << "x=" << c[x] << " y=" << c[y] << " res=" << 1028 conv.r; 1029 } 1030 } 1031 1032 // TODO: Deallocate things. 1033 1034 // Tests done. 1035 #else 1036 LOG(INFO) << "Skipping string_compareto as I don't know how to do that on " << kRuntimeISA; 1037 // Force-print to std::cout so it's also outside the logcat. 1038 std::cout << "Skipping string_compareto as I don't know how to do that on " << kRuntimeISA << 1039 std::endl; 1040 #endif 1041 } 1042 1043 GetSetBooleanStatic(ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1044 static void GetSetBooleanStatic(ArtField* f, Thread* self, 1045 ArtMethod* referrer, StubTest* test) 1046 REQUIRES_SHARED(Locks::mutator_lock_) { 1047 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1048 (defined(__x86_64__) && !defined(__APPLE__)) 1049 constexpr size_t num_values = 5; 1050 uint8_t values[num_values] = { 0, 1, 2, 128, 0xFF }; 1051 1052 for (size_t i = 0; i < num_values; ++i) { 1053 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1054 static_cast<size_t>(values[i]), 1055 0U, 1056 StubTest::GetEntrypoint(self, kQuickSet8Static), 1057 self, 1058 referrer); 1059 1060 size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1061 0U, 0U, 1062 StubTest::GetEntrypoint(self, kQuickGetBooleanStatic), 1063 self, 1064 referrer); 1065 // Boolean currently stores bools as uint8_t, be more zealous about asserting correct writes/gets. 1066 EXPECT_EQ(values[i], static_cast<uint8_t>(res)) << "Iteration " << i; 1067 } 1068 #else 1069 UNUSED(f, self, referrer, test); 1070 LOG(INFO) << "Skipping set_boolean_static as I don't know how to do that on " << kRuntimeISA; 1071 // Force-print to std::cout so it's also outside the logcat. 1072 std::cout << "Skipping set_boolean_static as I don't know how to do that on " << kRuntimeISA << std::endl; 1073 #endif 1074 } GetSetByteStatic(ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1075 static void GetSetByteStatic(ArtField* f, Thread* self, ArtMethod* referrer, 1076 StubTest* test) 1077 REQUIRES_SHARED(Locks::mutator_lock_) { 1078 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1079 (defined(__x86_64__) && !defined(__APPLE__)) 1080 int8_t values[] = { -128, -64, 0, 64, 127 }; 1081 1082 for (size_t i = 0; i < arraysize(values); ++i) { 1083 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1084 static_cast<size_t>(values[i]), 1085 0U, 1086 StubTest::GetEntrypoint(self, kQuickSet8Static), 1087 self, 1088 referrer); 1089 1090 size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1091 0U, 0U, 1092 StubTest::GetEntrypoint(self, kQuickGetByteStatic), 1093 self, 1094 referrer); 1095 EXPECT_EQ(values[i], static_cast<int8_t>(res)) << "Iteration " << i; 1096 } 1097 #else 1098 UNUSED(f, self, referrer, test); 1099 LOG(INFO) << "Skipping set_byte_static as I don't know how to do that on " << kRuntimeISA; 1100 // Force-print to std::cout so it's also outside the logcat. 1101 std::cout << "Skipping set_byte_static as I don't know how to do that on " << kRuntimeISA << std::endl; 1102 #endif 1103 } 1104 1105 GetSetBooleanInstance(Handle<mirror::Object> * obj,ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1106 static void GetSetBooleanInstance(Handle<mirror::Object>* obj, ArtField* f, Thread* self, 1107 ArtMethod* referrer, StubTest* test) 1108 REQUIRES_SHARED(Locks::mutator_lock_) { 1109 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1110 (defined(__x86_64__) && !defined(__APPLE__)) 1111 uint8_t values[] = { 0, true, 2, 128, 0xFF }; 1112 1113 for (size_t i = 0; i < arraysize(values); ++i) { 1114 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1115 reinterpret_cast<size_t>(obj->Get()), 1116 static_cast<size_t>(values[i]), 1117 StubTest::GetEntrypoint(self, kQuickSet8Instance), 1118 self, 1119 referrer); 1120 1121 uint8_t res = f->GetBoolean(obj->Get()); 1122 EXPECT_EQ(values[i], res) << "Iteration " << i; 1123 1124 f->SetBoolean<false>(obj->Get(), res); 1125 1126 size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1127 reinterpret_cast<size_t>(obj->Get()), 1128 0U, 1129 StubTest::GetEntrypoint(self, kQuickGetBooleanInstance), 1130 self, 1131 referrer); 1132 EXPECT_EQ(res, static_cast<uint8_t>(res2)); 1133 } 1134 #else 1135 UNUSED(obj, f, self, referrer, test); 1136 LOG(INFO) << "Skipping set_boolean_instance as I don't know how to do that on " << kRuntimeISA; 1137 // Force-print to std::cout so it's also outside the logcat. 1138 std::cout << "Skipping set_boolean_instance as I don't know how to do that on " << kRuntimeISA << std::endl; 1139 #endif 1140 } GetSetByteInstance(Handle<mirror::Object> * obj,ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1141 static void GetSetByteInstance(Handle<mirror::Object>* obj, ArtField* f, 1142 Thread* self, ArtMethod* referrer, StubTest* test) 1143 REQUIRES_SHARED(Locks::mutator_lock_) { 1144 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1145 (defined(__x86_64__) && !defined(__APPLE__)) 1146 int8_t values[] = { -128, -64, 0, 64, 127 }; 1147 1148 for (size_t i = 0; i < arraysize(values); ++i) { 1149 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1150 reinterpret_cast<size_t>(obj->Get()), 1151 static_cast<size_t>(values[i]), 1152 StubTest::GetEntrypoint(self, kQuickSet8Instance), 1153 self, 1154 referrer); 1155 1156 int8_t res = f->GetByte(obj->Get()); 1157 EXPECT_EQ(res, values[i]) << "Iteration " << i; 1158 f->SetByte<false>(obj->Get(), ++res); 1159 1160 size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1161 reinterpret_cast<size_t>(obj->Get()), 1162 0U, 1163 StubTest::GetEntrypoint(self, kQuickGetByteInstance), 1164 self, 1165 referrer); 1166 EXPECT_EQ(res, static_cast<int8_t>(res2)); 1167 } 1168 #else 1169 UNUSED(obj, f, self, referrer, test); 1170 LOG(INFO) << "Skipping set_byte_instance as I don't know how to do that on " << kRuntimeISA; 1171 // Force-print to std::cout so it's also outside the logcat. 1172 std::cout << "Skipping set_byte_instance as I don't know how to do that on " << kRuntimeISA << std::endl; 1173 #endif 1174 } 1175 GetSetCharStatic(ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1176 static void GetSetCharStatic(ArtField* f, Thread* self, ArtMethod* referrer, 1177 StubTest* test) 1178 REQUIRES_SHARED(Locks::mutator_lock_) { 1179 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1180 (defined(__x86_64__) && !defined(__APPLE__)) 1181 uint16_t values[] = { 0, 1, 2, 255, 32768, 0xFFFF }; 1182 1183 for (size_t i = 0; i < arraysize(values); ++i) { 1184 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1185 static_cast<size_t>(values[i]), 1186 0U, 1187 StubTest::GetEntrypoint(self, kQuickSet16Static), 1188 self, 1189 referrer); 1190 1191 size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1192 0U, 0U, 1193 StubTest::GetEntrypoint(self, kQuickGetCharStatic), 1194 self, 1195 referrer); 1196 1197 EXPECT_EQ(values[i], static_cast<uint16_t>(res)) << "Iteration " << i; 1198 } 1199 #else 1200 UNUSED(f, self, referrer, test); 1201 LOG(INFO) << "Skipping set_char_static as I don't know how to do that on " << kRuntimeISA; 1202 // Force-print to std::cout so it's also outside the logcat. 1203 std::cout << "Skipping set_char_static as I don't know how to do that on " << kRuntimeISA << std::endl; 1204 #endif 1205 } GetSetShortStatic(ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1206 static void GetSetShortStatic(ArtField* f, Thread* self, 1207 ArtMethod* referrer, StubTest* test) 1208 REQUIRES_SHARED(Locks::mutator_lock_) { 1209 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1210 (defined(__x86_64__) && !defined(__APPLE__)) 1211 int16_t values[] = { -0x7FFF, -32768, 0, 255, 32767, 0x7FFE }; 1212 1213 for (size_t i = 0; i < arraysize(values); ++i) { 1214 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1215 static_cast<size_t>(values[i]), 1216 0U, 1217 StubTest::GetEntrypoint(self, kQuickSet16Static), 1218 self, 1219 referrer); 1220 1221 size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1222 0U, 0U, 1223 StubTest::GetEntrypoint(self, kQuickGetShortStatic), 1224 self, 1225 referrer); 1226 1227 EXPECT_EQ(static_cast<int16_t>(res), values[i]) << "Iteration " << i; 1228 } 1229 #else 1230 UNUSED(f, self, referrer, test); 1231 LOG(INFO) << "Skipping set_short_static as I don't know how to do that on " << kRuntimeISA; 1232 // Force-print to std::cout so it's also outside the logcat. 1233 std::cout << "Skipping set_short_static as I don't know how to do that on " << kRuntimeISA << std::endl; 1234 #endif 1235 } 1236 GetSetCharInstance(Handle<mirror::Object> * obj,ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1237 static void GetSetCharInstance(Handle<mirror::Object>* obj, ArtField* f, 1238 Thread* self, ArtMethod* referrer, StubTest* test) 1239 REQUIRES_SHARED(Locks::mutator_lock_) { 1240 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1241 (defined(__x86_64__) && !defined(__APPLE__)) 1242 uint16_t values[] = { 0, 1, 2, 255, 32768, 0xFFFF }; 1243 1244 for (size_t i = 0; i < arraysize(values); ++i) { 1245 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1246 reinterpret_cast<size_t>(obj->Get()), 1247 static_cast<size_t>(values[i]), 1248 StubTest::GetEntrypoint(self, kQuickSet16Instance), 1249 self, 1250 referrer); 1251 1252 uint16_t res = f->GetChar(obj->Get()); 1253 EXPECT_EQ(res, values[i]) << "Iteration " << i; 1254 f->SetChar<false>(obj->Get(), ++res); 1255 1256 size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1257 reinterpret_cast<size_t>(obj->Get()), 1258 0U, 1259 StubTest::GetEntrypoint(self, kQuickGetCharInstance), 1260 self, 1261 referrer); 1262 EXPECT_EQ(res, static_cast<uint16_t>(res2)); 1263 } 1264 #else 1265 UNUSED(obj, f, self, referrer, test); 1266 LOG(INFO) << "Skipping set_char_instance as I don't know how to do that on " << kRuntimeISA; 1267 // Force-print to std::cout so it's also outside the logcat. 1268 std::cout << "Skipping set_char_instance as I don't know how to do that on " << kRuntimeISA << std::endl; 1269 #endif 1270 } GetSetShortInstance(Handle<mirror::Object> * obj,ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1271 static void GetSetShortInstance(Handle<mirror::Object>* obj, ArtField* f, 1272 Thread* self, ArtMethod* referrer, StubTest* test) 1273 REQUIRES_SHARED(Locks::mutator_lock_) { 1274 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1275 (defined(__x86_64__) && !defined(__APPLE__)) 1276 int16_t values[] = { -0x7FFF, -32768, 0, 255, 32767, 0x7FFE }; 1277 1278 for (size_t i = 0; i < arraysize(values); ++i) { 1279 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1280 reinterpret_cast<size_t>(obj->Get()), 1281 static_cast<size_t>(values[i]), 1282 StubTest::GetEntrypoint(self, kQuickSet16Instance), 1283 self, 1284 referrer); 1285 1286 int16_t res = f->GetShort(obj->Get()); 1287 EXPECT_EQ(res, values[i]) << "Iteration " << i; 1288 f->SetShort<false>(obj->Get(), ++res); 1289 1290 size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1291 reinterpret_cast<size_t>(obj->Get()), 1292 0U, 1293 StubTest::GetEntrypoint(self, kQuickGetShortInstance), 1294 self, 1295 referrer); 1296 EXPECT_EQ(res, static_cast<int16_t>(res2)); 1297 } 1298 #else 1299 UNUSED(obj, f, self, referrer, test); 1300 LOG(INFO) << "Skipping set_short_instance as I don't know how to do that on " << kRuntimeISA; 1301 // Force-print to std::cout so it's also outside the logcat. 1302 std::cout << "Skipping set_short_instance as I don't know how to do that on " << kRuntimeISA << std::endl; 1303 #endif 1304 } 1305 GetSet32Static(ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1306 static void GetSet32Static(ArtField* f, Thread* self, ArtMethod* referrer, 1307 StubTest* test) 1308 REQUIRES_SHARED(Locks::mutator_lock_) { 1309 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1310 (defined(__x86_64__) && !defined(__APPLE__)) 1311 uint32_t values[] = { 0, 1, 2, 255, 32768, 1000000, 0xFFFFFFFF }; 1312 1313 for (size_t i = 0; i < arraysize(values); ++i) { 1314 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1315 static_cast<size_t>(values[i]), 1316 0U, 1317 StubTest::GetEntrypoint(self, kQuickSet32Static), 1318 self, 1319 referrer); 1320 1321 size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1322 0U, 0U, 1323 StubTest::GetEntrypoint(self, kQuickGet32Static), 1324 self, 1325 referrer); 1326 1327 EXPECT_EQ(res, values[i]) << "Iteration " << i; 1328 } 1329 #else 1330 UNUSED(f, self, referrer, test); 1331 LOG(INFO) << "Skipping set32static as I don't know how to do that on " << kRuntimeISA; 1332 // Force-print to std::cout so it's also outside the logcat. 1333 std::cout << "Skipping set32static as I don't know how to do that on " << kRuntimeISA << std::endl; 1334 #endif 1335 } 1336 1337 GetSet32Instance(Handle<mirror::Object> * obj,ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1338 static void GetSet32Instance(Handle<mirror::Object>* obj, ArtField* f, 1339 Thread* self, ArtMethod* referrer, StubTest* test) 1340 REQUIRES_SHARED(Locks::mutator_lock_) { 1341 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1342 (defined(__x86_64__) && !defined(__APPLE__)) 1343 uint32_t values[] = { 0, 1, 2, 255, 32768, 1000000, 0xFFFFFFFF }; 1344 1345 for (size_t i = 0; i < arraysize(values); ++i) { 1346 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1347 reinterpret_cast<size_t>(obj->Get()), 1348 static_cast<size_t>(values[i]), 1349 StubTest::GetEntrypoint(self, kQuickSet32Instance), 1350 self, 1351 referrer); 1352 1353 int32_t res = f->GetInt(obj->Get()); 1354 EXPECT_EQ(res, static_cast<int32_t>(values[i])) << "Iteration " << i; 1355 1356 res++; 1357 f->SetInt<false>(obj->Get(), res); 1358 1359 size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1360 reinterpret_cast<size_t>(obj->Get()), 1361 0U, 1362 StubTest::GetEntrypoint(self, kQuickGet32Instance), 1363 self, 1364 referrer); 1365 EXPECT_EQ(res, static_cast<int32_t>(res2)); 1366 } 1367 #else 1368 UNUSED(obj, f, self, referrer, test); 1369 LOG(INFO) << "Skipping set32instance as I don't know how to do that on " << kRuntimeISA; 1370 // Force-print to std::cout so it's also outside the logcat. 1371 std::cout << "Skipping set32instance as I don't know how to do that on " << kRuntimeISA << std::endl; 1372 #endif 1373 } 1374 1375 1376 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1377 (defined(__x86_64__) && !defined(__APPLE__)) 1378 set_and_check_static(uint32_t f_idx,ObjPtr<mirror::Object> val,Thread * self,ArtMethod * referrer,StubTest * test)1379 static void set_and_check_static(uint32_t f_idx, 1380 ObjPtr<mirror::Object> val, 1381 Thread* self, 1382 ArtMethod* referrer, 1383 StubTest* test) 1384 REQUIRES_SHARED(Locks::mutator_lock_) { 1385 StackHandleScope<1u> hs(self); 1386 Handle<mirror::Object> h_val = hs.NewHandle(val); 1387 test->Invoke3WithReferrer(static_cast<size_t>(f_idx), 1388 reinterpret_cast<size_t>(h_val.Get()), 1389 0U, 1390 StubTest::GetEntrypoint(self, kQuickSetObjStatic), 1391 self, 1392 referrer); 1393 1394 size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f_idx), 1395 0U, 1396 0U, 1397 StubTest::GetEntrypoint(self, kQuickGetObjStatic), 1398 self, 1399 referrer); 1400 1401 EXPECT_EQ(res, reinterpret_cast<size_t>(h_val.Get())) << "Value " << h_val.Get(); 1402 } 1403 #endif 1404 GetSetObjStatic(ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1405 static void GetSetObjStatic(ArtField* f, Thread* self, ArtMethod* referrer, 1406 StubTest* test) 1407 REQUIRES_SHARED(Locks::mutator_lock_) { 1408 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1409 (defined(__x86_64__) && !defined(__APPLE__)) 1410 set_and_check_static(f->GetDexFieldIndex(), nullptr, self, referrer, test); 1411 1412 // Allocate a string object for simplicity. 1413 ObjPtr<mirror::String> str = mirror::String::AllocFromModifiedUtf8(self, "Test"); 1414 set_and_check_static(f->GetDexFieldIndex(), str, self, referrer, test); 1415 1416 set_and_check_static(f->GetDexFieldIndex(), nullptr, self, referrer, test); 1417 #else 1418 UNUSED(f, self, referrer, test); 1419 LOG(INFO) << "Skipping setObjstatic as I don't know how to do that on " << kRuntimeISA; 1420 // Force-print to std::cout so it's also outside the logcat. 1421 std::cout << "Skipping setObjstatic as I don't know how to do that on " << kRuntimeISA << std::endl; 1422 #endif 1423 } 1424 1425 1426 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1427 (defined(__x86_64__) && !defined(__APPLE__)) set_and_check_instance(ArtField * f,ObjPtr<mirror::Object> trg,ObjPtr<mirror::Object> val,Thread * self,ArtMethod * referrer,StubTest * test)1428 static void set_and_check_instance(ArtField* f, 1429 ObjPtr<mirror::Object> trg, 1430 ObjPtr<mirror::Object> val, 1431 Thread* self, 1432 ArtMethod* referrer, 1433 StubTest* test) 1434 REQUIRES_SHARED(Locks::mutator_lock_) { 1435 StackHandleScope<2u> hs(self); 1436 Handle<mirror::Object> h_trg = hs.NewHandle(trg); 1437 Handle<mirror::Object> h_val = hs.NewHandle(val); 1438 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1439 reinterpret_cast<size_t>(h_trg.Get()), 1440 reinterpret_cast<size_t>(h_val.Get()), 1441 StubTest::GetEntrypoint(self, kQuickSetObjInstance), 1442 self, 1443 referrer); 1444 1445 size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1446 reinterpret_cast<size_t>(h_trg.Get()), 1447 0U, 1448 StubTest::GetEntrypoint(self, kQuickGetObjInstance), 1449 self, 1450 referrer); 1451 1452 EXPECT_EQ(res, reinterpret_cast<size_t>(h_val.Get())) << "Value " << h_val.Get(); 1453 1454 EXPECT_OBJ_PTR_EQ(h_val.Get(), f->GetObj(h_trg.Get())); 1455 } 1456 #endif 1457 GetSetObjInstance(Handle<mirror::Object> * obj,ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1458 static void GetSetObjInstance(Handle<mirror::Object>* obj, ArtField* f, 1459 Thread* self, ArtMethod* referrer, StubTest* test) 1460 REQUIRES_SHARED(Locks::mutator_lock_) { 1461 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1462 (defined(__x86_64__) && !defined(__APPLE__)) 1463 set_and_check_instance(f, obj->Get(), nullptr, self, referrer, test); 1464 1465 // Allocate a string object for simplicity. 1466 ObjPtr<mirror::String> str = mirror::String::AllocFromModifiedUtf8(self, "Test"); 1467 set_and_check_instance(f, obj->Get(), str, self, referrer, test); 1468 1469 set_and_check_instance(f, obj->Get(), nullptr, self, referrer, test); 1470 #else 1471 UNUSED(obj, f, self, referrer, test); 1472 LOG(INFO) << "Skipping setObjinstance as I don't know how to do that on " << kRuntimeISA; 1473 // Force-print to std::cout so it's also outside the logcat. 1474 std::cout << "Skipping setObjinstance as I don't know how to do that on " << kRuntimeISA << std::endl; 1475 #endif 1476 } 1477 1478 1479 // TODO: Complete these tests for 32b architectures 1480 GetSet64Static(ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1481 static void GetSet64Static(ArtField* f, Thread* self, ArtMethod* referrer, 1482 StubTest* test) 1483 REQUIRES_SHARED(Locks::mutator_lock_) { 1484 #if (defined(__x86_64__) && !defined(__APPLE__)) || defined(__aarch64__) 1485 uint64_t values[] = { 0, 1, 2, 255, 32768, 1000000, 0xFFFFFFFF, 0xFFFFFFFFFFFF }; 1486 1487 for (size_t i = 0; i < arraysize(values); ++i) { 1488 // 64 bit FieldSet stores the set value in the second register. 1489 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1490 values[i], 1491 0U, 1492 StubTest::GetEntrypoint(self, kQuickSet64Static), 1493 self, 1494 referrer); 1495 1496 size_t res = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1497 0U, 0U, 1498 StubTest::GetEntrypoint(self, kQuickGet64Static), 1499 self, 1500 referrer); 1501 1502 EXPECT_EQ(res, values[i]) << "Iteration " << i; 1503 } 1504 #else 1505 UNUSED(f, self, referrer, test); 1506 LOG(INFO) << "Skipping set64static as I don't know how to do that on " << kRuntimeISA; 1507 // Force-print to std::cout so it's also outside the logcat. 1508 std::cout << "Skipping set64static as I don't know how to do that on " << kRuntimeISA << std::endl; 1509 #endif 1510 } 1511 1512 GetSet64Instance(Handle<mirror::Object> * obj,ArtField * f,Thread * self,ArtMethod * referrer,StubTest * test)1513 static void GetSet64Instance(Handle<mirror::Object>* obj, ArtField* f, 1514 Thread* self, ArtMethod* referrer, StubTest* test) 1515 REQUIRES_SHARED(Locks::mutator_lock_) { 1516 #if (defined(__x86_64__) && !defined(__APPLE__)) || defined(__aarch64__) 1517 uint64_t values[] = { 0, 1, 2, 255, 32768, 1000000, 0xFFFFFFFF, 0xFFFFFFFFFFFF }; 1518 1519 for (size_t i = 0; i < arraysize(values); ++i) { 1520 test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1521 reinterpret_cast<size_t>(obj->Get()), 1522 static_cast<size_t>(values[i]), 1523 StubTest::GetEntrypoint(self, kQuickSet64Instance), 1524 self, 1525 referrer); 1526 1527 int64_t res = f->GetLong(obj->Get()); 1528 EXPECT_EQ(res, static_cast<int64_t>(values[i])) << "Iteration " << i; 1529 1530 res++; 1531 f->SetLong<false>(obj->Get(), res); 1532 1533 size_t res2 = test->Invoke3WithReferrer(static_cast<size_t>(f->GetDexFieldIndex()), 1534 reinterpret_cast<size_t>(obj->Get()), 1535 0U, 1536 StubTest::GetEntrypoint(self, kQuickGet64Instance), 1537 self, 1538 referrer); 1539 EXPECT_EQ(res, static_cast<int64_t>(res2)); 1540 } 1541 #else 1542 UNUSED(obj, f, self, referrer, test); 1543 LOG(INFO) << "Skipping set64instance as I don't know how to do that on " << kRuntimeISA; 1544 // Force-print to std::cout so it's also outside the logcat. 1545 std::cout << "Skipping set64instance as I don't know how to do that on " << kRuntimeISA << std::endl; 1546 #endif 1547 } 1548 TestFields(Thread * self,StubTest * test,Primitive::Type test_type)1549 static void TestFields(Thread* self, StubTest* test, Primitive::Type test_type) { 1550 // garbage is created during ClassLinker::Init 1551 1552 JNIEnv* env = Thread::Current()->GetJniEnv(); 1553 jclass jc = env->FindClass("AllFields"); 1554 CHECK(jc != nullptr); 1555 jobject o = env->AllocObject(jc); 1556 CHECK(o != nullptr); 1557 1558 ScopedObjectAccess soa(self); 1559 StackHandleScope<3> hs(self); 1560 Handle<mirror::Object> obj(hs.NewHandle(soa.Decode<mirror::Object>(o))); 1561 Handle<mirror::Class> c(hs.NewHandle(obj->GetClass())); 1562 // Need a method as a referrer 1563 ArtMethod* m = c->GetDirectMethod(0, kRuntimePointerSize); 1564 1565 // Play with it... 1566 1567 // Static fields. 1568 for (ArtField& f : c->GetSFields()) { 1569 Primitive::Type type = f.GetTypeAsPrimitiveType(); 1570 if (test_type != type) { 1571 continue; 1572 } 1573 switch (type) { 1574 case Primitive::Type::kPrimBoolean: 1575 GetSetBooleanStatic(&f, self, m, test); 1576 break; 1577 case Primitive::Type::kPrimByte: 1578 GetSetByteStatic(&f, self, m, test); 1579 break; 1580 case Primitive::Type::kPrimChar: 1581 GetSetCharStatic(&f, self, m, test); 1582 break; 1583 case Primitive::Type::kPrimShort: 1584 GetSetShortStatic(&f, self, m, test); 1585 break; 1586 case Primitive::Type::kPrimInt: 1587 GetSet32Static(&f, self, m, test); 1588 break; 1589 case Primitive::Type::kPrimLong: 1590 GetSet64Static(&f, self, m, test); 1591 break; 1592 case Primitive::Type::kPrimNot: 1593 // Don't try array. 1594 if (f.GetTypeDescriptor()[0] != '[') { 1595 GetSetObjStatic(&f, self, m, test); 1596 } 1597 break; 1598 default: 1599 break; // Skip. 1600 } 1601 } 1602 1603 // Instance fields. 1604 for (ArtField& f : c->GetIFields()) { 1605 Primitive::Type type = f.GetTypeAsPrimitiveType(); 1606 if (test_type != type) { 1607 continue; 1608 } 1609 switch (type) { 1610 case Primitive::Type::kPrimBoolean: 1611 GetSetBooleanInstance(&obj, &f, self, m, test); 1612 break; 1613 case Primitive::Type::kPrimByte: 1614 GetSetByteInstance(&obj, &f, self, m, test); 1615 break; 1616 case Primitive::Type::kPrimChar: 1617 GetSetCharInstance(&obj, &f, self, m, test); 1618 break; 1619 case Primitive::Type::kPrimShort: 1620 GetSetShortInstance(&obj, &f, self, m, test); 1621 break; 1622 case Primitive::Type::kPrimInt: 1623 GetSet32Instance(&obj, &f, self, m, test); 1624 break; 1625 case Primitive::Type::kPrimLong: 1626 GetSet64Instance(&obj, &f, self, m, test); 1627 break; 1628 case Primitive::Type::kPrimNot: 1629 // Don't try array. 1630 if (f.GetTypeDescriptor()[0] != '[') { 1631 GetSetObjInstance(&obj, &f, self, m, test); 1632 } 1633 break; 1634 default: 1635 break; // Skip. 1636 } 1637 } 1638 1639 // TODO: Deallocate things. 1640 } 1641 TEST_F(StubTest,Fields8)1642 TEST_F(StubTest, Fields8) { 1643 Thread* self = Thread::Current(); 1644 1645 self->TransitionFromSuspendedToRunnable(); 1646 LoadDex("AllFields"); 1647 bool started = runtime_->Start(); 1648 CHECK(started); 1649 1650 TestFields(self, this, Primitive::Type::kPrimBoolean); 1651 TestFields(self, this, Primitive::Type::kPrimByte); 1652 } 1653 TEST_F(StubTest,Fields16)1654 TEST_F(StubTest, Fields16) { 1655 Thread* self = Thread::Current(); 1656 1657 self->TransitionFromSuspendedToRunnable(); 1658 LoadDex("AllFields"); 1659 bool started = runtime_->Start(); 1660 CHECK(started); 1661 1662 TestFields(self, this, Primitive::Type::kPrimChar); 1663 TestFields(self, this, Primitive::Type::kPrimShort); 1664 } 1665 TEST_F(StubTest,Fields32)1666 TEST_F(StubTest, Fields32) { 1667 Thread* self = Thread::Current(); 1668 1669 self->TransitionFromSuspendedToRunnable(); 1670 LoadDex("AllFields"); 1671 bool started = runtime_->Start(); 1672 CHECK(started); 1673 1674 TestFields(self, this, Primitive::Type::kPrimInt); 1675 } 1676 TEST_F(StubTest,FieldsObj)1677 TEST_F(StubTest, FieldsObj) { 1678 Thread* self = Thread::Current(); 1679 1680 self->TransitionFromSuspendedToRunnable(); 1681 LoadDex("AllFields"); 1682 bool started = runtime_->Start(); 1683 CHECK(started); 1684 1685 TestFields(self, this, Primitive::Type::kPrimNot); 1686 } 1687 TEST_F(StubTest,Fields64)1688 TEST_F(StubTest, Fields64) { 1689 Thread* self = Thread::Current(); 1690 1691 self->TransitionFromSuspendedToRunnable(); 1692 LoadDex("AllFields"); 1693 bool started = runtime_->Start(); 1694 CHECK(started); 1695 1696 TestFields(self, this, Primitive::Type::kPrimLong); 1697 } 1698 1699 // Disabled, b/27991555 . 1700 // FIXME: Hacking the entry point to point to art_quick_to_interpreter_bridge is broken. 1701 // The bridge calls through to GetCalleeSaveMethodCaller() which looks up the pre-header 1702 // and gets a bogus OatQuickMethodHeader* pointing into our assembly code just before 1703 // the bridge and uses that to check for inlined frames, crashing in the process. TEST_F(StubTest,DISABLED_IMT)1704 TEST_F(StubTest, DISABLED_IMT) { 1705 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) || \ 1706 (defined(__x86_64__) && !defined(__APPLE__)) 1707 Thread* self = Thread::Current(); 1708 1709 ScopedObjectAccess soa(self); 1710 StackHandleScope<7> hs(self); 1711 1712 JNIEnv* env = Thread::Current()->GetJniEnv(); 1713 1714 // ArrayList 1715 1716 // Load ArrayList and used methods (JNI). 1717 jclass arraylist_jclass = env->FindClass("java/util/ArrayList"); 1718 ASSERT_NE(nullptr, arraylist_jclass); 1719 jmethodID arraylist_constructor = env->GetMethodID(arraylist_jclass, "<init>", "()V"); 1720 ASSERT_NE(nullptr, arraylist_constructor); 1721 jmethodID contains_jmethod = env->GetMethodID( 1722 arraylist_jclass, "contains", "(Ljava/lang/Object;)Z"); 1723 ASSERT_NE(nullptr, contains_jmethod); 1724 jmethodID add_jmethod = env->GetMethodID(arraylist_jclass, "add", "(Ljava/lang/Object;)Z"); 1725 ASSERT_NE(nullptr, add_jmethod); 1726 1727 // Get representation. 1728 ArtMethod* contains_amethod = jni::DecodeArtMethod(contains_jmethod); 1729 1730 // Patch up ArrayList.contains. 1731 if (contains_amethod->GetEntryPointFromQuickCompiledCode() == nullptr) { 1732 contains_amethod->SetEntryPointFromQuickCompiledCode(reinterpret_cast<void*>( 1733 StubTest::GetEntrypoint(self, kQuickQuickToInterpreterBridge))); 1734 } 1735 1736 // List 1737 1738 // Load List and used methods (JNI). 1739 jclass list_jclass = env->FindClass("java/util/List"); 1740 ASSERT_NE(nullptr, list_jclass); 1741 jmethodID inf_contains_jmethod = env->GetMethodID( 1742 list_jclass, "contains", "(Ljava/lang/Object;)Z"); 1743 ASSERT_NE(nullptr, inf_contains_jmethod); 1744 1745 // Get mirror representation. 1746 ArtMethod* inf_contains = jni::DecodeArtMethod(inf_contains_jmethod); 1747 1748 // Object 1749 1750 jclass obj_jclass = env->FindClass("java/lang/Object"); 1751 ASSERT_NE(nullptr, obj_jclass); 1752 jmethodID obj_constructor = env->GetMethodID(obj_jclass, "<init>", "()V"); 1753 ASSERT_NE(nullptr, obj_constructor); 1754 1755 // Create instances. 1756 1757 jobject jarray_list = env->NewObject(arraylist_jclass, arraylist_constructor); 1758 ASSERT_NE(nullptr, jarray_list); 1759 Handle<mirror::Object> array_list(hs.NewHandle(soa.Decode<mirror::Object>(jarray_list))); 1760 1761 jobject jobj = env->NewObject(obj_jclass, obj_constructor); 1762 ASSERT_NE(nullptr, jobj); 1763 Handle<mirror::Object> obj(hs.NewHandle(soa.Decode<mirror::Object>(jobj))); 1764 1765 // Invocation tests. 1766 1767 // 1. imt_conflict 1768 1769 // Contains. 1770 1771 // We construct the ImtConflictTable ourselves, as we cannot go into the runtime stub 1772 // that will create it: the runtime stub expects to be called by compiled code. 1773 LinearAlloc* linear_alloc = Runtime::Current()->GetLinearAlloc(); 1774 ArtMethod* conflict_method = Runtime::Current()->CreateImtConflictMethod(linear_alloc); 1775 ImtConflictTable* empty_conflict_table = 1776 Runtime::Current()->GetClassLinker()->CreateImtConflictTable(/*count=*/0u, linear_alloc); 1777 void* data = linear_alloc->Alloc( 1778 self, 1779 ImtConflictTable::ComputeSizeWithOneMoreEntry(empty_conflict_table, kRuntimePointerSize), 1780 LinearAllocKind::kNoGCRoots); 1781 ImtConflictTable* new_table = new (data) ImtConflictTable( 1782 empty_conflict_table, inf_contains, contains_amethod, kRuntimePointerSize); 1783 conflict_method->SetImtConflictTable(new_table, kRuntimePointerSize); 1784 1785 size_t result = 1786 Invoke3WithReferrerAndHidden(reinterpret_cast<size_t>(conflict_method), 1787 reinterpret_cast<size_t>(array_list.Get()), 1788 reinterpret_cast<size_t>(obj.Get()), 1789 StubTest::GetEntrypoint(self, kQuickQuickImtConflictTrampoline), 1790 self, 1791 contains_amethod, 1792 static_cast<size_t>(inf_contains->GetDexMethodIndex())); 1793 1794 ASSERT_FALSE(self->IsExceptionPending()); 1795 EXPECT_EQ(static_cast<size_t>(JNI_FALSE), result); 1796 1797 // Add object. 1798 1799 env->CallBooleanMethod(jarray_list, add_jmethod, jobj); 1800 1801 ASSERT_FALSE(self->IsExceptionPending()) << mirror::Object::PrettyTypeOf(self->GetException()); 1802 1803 // Contains. 1804 1805 result = 1806 Invoke3WithReferrerAndHidden(reinterpret_cast<size_t>(conflict_method), 1807 reinterpret_cast<size_t>(array_list.Get()), 1808 reinterpret_cast<size_t>(obj.Get()), 1809 StubTest::GetEntrypoint(self, kQuickQuickImtConflictTrampoline), 1810 self, 1811 contains_amethod, 1812 static_cast<size_t>(inf_contains->GetDexMethodIndex())); 1813 1814 ASSERT_FALSE(self->IsExceptionPending()); 1815 EXPECT_EQ(static_cast<size_t>(JNI_TRUE), result); 1816 1817 // 2. regular interface trampoline 1818 1819 result = Invoke3WithReferrer(static_cast<size_t>(inf_contains->GetDexMethodIndex()), 1820 reinterpret_cast<size_t>(array_list.Get()), 1821 reinterpret_cast<size_t>(obj.Get()), 1822 StubTest::GetEntrypoint(self, 1823 kQuickInvokeInterfaceTrampolineWithAccessCheck), 1824 self, contains_amethod); 1825 1826 ASSERT_FALSE(self->IsExceptionPending()); 1827 EXPECT_EQ(static_cast<size_t>(JNI_TRUE), result); 1828 1829 result = Invoke3WithReferrer( 1830 static_cast<size_t>(inf_contains->GetDexMethodIndex()), 1831 reinterpret_cast<size_t>(array_list.Get()), reinterpret_cast<size_t>(array_list.Get()), 1832 StubTest::GetEntrypoint(self, kQuickInvokeInterfaceTrampolineWithAccessCheck), self, 1833 contains_amethod); 1834 1835 ASSERT_FALSE(self->IsExceptionPending()); 1836 EXPECT_EQ(static_cast<size_t>(JNI_FALSE), result); 1837 #else 1838 LOG(INFO) << "Skipping imt as I don't know how to do that on " << kRuntimeISA; 1839 // Force-print to std::cout so it's also outside the logcat. 1840 std::cout << "Skipping imt as I don't know how to do that on " << kRuntimeISA << std::endl; 1841 #endif 1842 } 1843 TEST_F(StubTest,StringIndexOf)1844 TEST_F(StubTest, StringIndexOf) { 1845 #if defined(__arm__) || defined(__aarch64__) 1846 Thread* self = Thread::Current(); 1847 ScopedObjectAccess soa(self); 1848 // garbage is created during ClassLinker::Init 1849 1850 // Create some strings 1851 // Use array so we can index into it and use a matrix for expected results 1852 // Setup: The first half is standard. The second half uses a non-zero offset. 1853 // TODO: Shared backing arrays. 1854 const char* c_str[] = { "", "a", "ba", "cba", "dcba", "edcba", "asdfghjkl" }; 1855 static constexpr size_t kStringCount = arraysize(c_str); 1856 const char c_char[] = { 'a', 'b', 'c', 'd', 'e' }; 1857 static constexpr size_t kCharCount = arraysize(c_char); 1858 1859 StackHandleScope<kStringCount> hs(self); 1860 Handle<mirror::String> s[kStringCount]; 1861 1862 for (size_t i = 0; i < kStringCount; ++i) { 1863 s[i] = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), c_str[i])); 1864 } 1865 1866 // Matrix of expectations. First component is first parameter. Note we only check against the 1867 // sign, not the value. As we are testing random offsets, we need to compute this and need to 1868 // rely on String::CompareTo being correct. 1869 static constexpr size_t kMaxLen = 9; 1870 DCHECK_LE(strlen(c_str[kStringCount-1]), kMaxLen) << "Please fix the indexof test."; 1871 1872 // Last dimension: start, offset by 1. 1873 int32_t expected[kStringCount][kCharCount][kMaxLen + 3]; 1874 for (size_t x = 0; x < kStringCount; ++x) { 1875 for (size_t y = 0; y < kCharCount; ++y) { 1876 for (size_t z = 0; z <= kMaxLen + 2; ++z) { 1877 expected[x][y][z] = s[x]->FastIndexOf(c_char[y], static_cast<int32_t>(z) - 1); 1878 } 1879 } 1880 } 1881 1882 // Play with it... 1883 1884 for (size_t x = 0; x < kStringCount; ++x) { 1885 for (size_t y = 0; y < kCharCount; ++y) { 1886 for (size_t z = 0; z <= kMaxLen + 2; ++z) { 1887 int32_t start = static_cast<int32_t>(z) - 1; 1888 1889 // Test string_compareto x y 1890 size_t result = Invoke3(reinterpret_cast<size_t>(s[x].Get()), c_char[y], start, 1891 StubTest::GetEntrypoint(self, kQuickIndexOf), self); 1892 1893 EXPECT_FALSE(self->IsExceptionPending()); 1894 1895 // The result is a 32b signed integer 1896 union { 1897 size_t r; 1898 int32_t i; 1899 } conv; 1900 conv.r = result; 1901 1902 EXPECT_EQ(expected[x][y][z], conv.i) << "Wrong result for " << c_str[x] << " / " << 1903 c_char[y] << " @ " << start; 1904 } 1905 } 1906 } 1907 1908 // TODO: Deallocate things. 1909 1910 // Tests done. 1911 #else 1912 LOG(INFO) << "Skipping indexof as I don't know how to do that on " << kRuntimeISA; 1913 // Force-print to std::cout so it's also outside the logcat. 1914 std::cout << "Skipping indexof as I don't know how to do that on " << kRuntimeISA << std::endl; 1915 #endif 1916 } 1917 1918 // TODO: Exercise the ReadBarrierMarkRegX entry points. 1919 TEST_F(StubTest,ReadBarrier)1920 TEST_F(StubTest, ReadBarrier) { 1921 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) ||\ 1922 (defined(__x86_64__) && !defined(__APPLE__)) 1923 if (gUseReadBarrier) { 1924 Thread* self = Thread::Current(); 1925 1926 const uintptr_t readBarrierSlow = StubTest::GetEntrypoint(self, kQuickReadBarrierSlow); 1927 1928 // Create an object 1929 ScopedObjectAccess soa(self); 1930 // garbage is created during ClassLinker::Init 1931 1932 StackHandleScope<2> hs(soa.Self()); 1933 Handle<mirror::Class> c( 1934 hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;"))); 1935 1936 // Build an object instance 1937 Handle<mirror::Object> obj(hs.NewHandle(c->AllocObject(soa.Self()))); 1938 1939 EXPECT_FALSE(self->IsExceptionPending()); 1940 1941 size_t result = Invoke3(0U, reinterpret_cast<size_t>(obj.Get()), 1942 mirror::Object::ClassOffset().SizeValue(), readBarrierSlow, self); 1943 1944 EXPECT_FALSE(self->IsExceptionPending()); 1945 EXPECT_NE(reinterpret_cast<size_t>(nullptr), result); 1946 mirror::Class* klass = reinterpret_cast<mirror::Class*>(result); 1947 EXPECT_OBJ_PTR_EQ(klass, obj->GetClass()); 1948 return; 1949 } 1950 #endif 1951 LOG(INFO) << "Skipping read_barrier_slow"; 1952 // Force-print to std::cout so it's also outside the logcat. 1953 std::cout << "Skipping read_barrier_slow" << std::endl; 1954 } 1955 TEST_F(StubTest,ReadBarrierForRoot)1956 TEST_F(StubTest, ReadBarrierForRoot) { 1957 #if defined(__i386__) || defined(__arm__) || defined(__aarch64__) ||\ 1958 (defined(__x86_64__) && !defined(__APPLE__)) 1959 if (gUseReadBarrier) { 1960 Thread* self = Thread::Current(); 1961 1962 const uintptr_t readBarrierForRootSlow = 1963 StubTest::GetEntrypoint(self, kQuickReadBarrierForRootSlow); 1964 1965 // Create an object 1966 ScopedObjectAccess soa(self); 1967 // garbage is created during ClassLinker::Init 1968 1969 StackHandleScope<1> hs(soa.Self()); 1970 1971 Handle<mirror::String> obj( 1972 hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello, world!"))); 1973 1974 EXPECT_FALSE(self->IsExceptionPending()); 1975 1976 GcRoot<mirror::Class> root(GetClassRoot<mirror::String>()); 1977 size_t result = Invoke3(reinterpret_cast<size_t>(&root), 0U, 0U, readBarrierForRootSlow, self); 1978 1979 EXPECT_FALSE(self->IsExceptionPending()); 1980 EXPECT_NE(reinterpret_cast<size_t>(nullptr), result); 1981 mirror::Class* klass = reinterpret_cast<mirror::Class*>(result); 1982 EXPECT_OBJ_PTR_EQ(klass, obj->GetClass()); 1983 return; 1984 } 1985 #endif 1986 LOG(INFO) << "Skipping read_barrier_for_root_slow"; 1987 // Force-print to std::cout so it's also outside the logcat. 1988 std::cout << "Skipping read_barrier_for_root_slow" << std::endl; 1989 } 1990 1991 } // namespace art 1992