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