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