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