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