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