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