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