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