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