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