1 /*
2 * Copyright (C) 2015 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 "unstarted_runtime.h"
18
19 #include <limits>
20 #include <locale>
21
22 #include "base/casts.h"
23 #include "base/memory_tool.h"
24 #include "class_linker.h"
25 #include "common_runtime_test.h"
26 #include "dex_instruction.h"
27 #include "handle.h"
28 #include "handle_scope-inl.h"
29 #include "interpreter/interpreter_common.h"
30 #include "mirror/class_loader.h"
31 #include "mirror/string-inl.h"
32 #include "runtime.h"
33 #include "scoped_thread_state_change.h"
34 #include "thread.h"
35 #include "transaction.h"
36
37 namespace art {
38 namespace interpreter {
39
40 class UnstartedRuntimeTest : public CommonRuntimeTest {
41 protected:
42 // Re-expose all UnstartedRuntime implementations so we don't need to declare a million
43 // test friends.
44
45 // Methods that intercept available libcore implementations.
46 #define UNSTARTED_DIRECT(Name, SigIgnored) \
47 static void Unstarted ## Name(Thread* self, \
48 ShadowFrame* shadow_frame, \
49 JValue* result, \
50 size_t arg_offset) \
51 SHARED_REQUIRES(Locks::mutator_lock_) { \
52 interpreter::UnstartedRuntime::Unstarted ## Name(self, shadow_frame, result, arg_offset); \
53 }
54 #include "unstarted_runtime_list.h"
55 UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT)
56 #undef UNSTARTED_RUNTIME_DIRECT_LIST
57 #undef UNSTARTED_RUNTIME_JNI_LIST
58 #undef UNSTARTED_DIRECT
59
60 // Methods that are native.
61 #define UNSTARTED_JNI(Name, SigIgnored) \
62 static void UnstartedJNI ## Name(Thread* self, \
63 ArtMethod* method, \
64 mirror::Object* receiver, \
65 uint32_t* args, \
66 JValue* result) \
67 SHARED_REQUIRES(Locks::mutator_lock_) { \
68 interpreter::UnstartedRuntime::UnstartedJNI ## Name(self, method, receiver, args, result); \
69 }
70 #include "unstarted_runtime_list.h"
UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)71 UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI)
72 #undef UNSTARTED_RUNTIME_DIRECT_LIST
73 #undef UNSTARTED_RUNTIME_JNI_LIST
74 #undef UNSTARTED_JNI
75
76 // Helpers for ArrayCopy.
77 //
78 // Note: as we have to use handles, we use StackHandleScope to transfer data. Hardcode a size
79 // of three everywhere. That is enough to test all cases.
80
81 static mirror::ObjectArray<mirror::Object>* CreateObjectArray(
82 Thread* self,
83 mirror::Class* component_type,
84 const StackHandleScope<3>& data)
85 SHARED_REQUIRES(Locks::mutator_lock_) {
86 Runtime* runtime = Runtime::Current();
87 mirror::Class* array_type = runtime->GetClassLinker()->FindArrayClass(self, &component_type);
88 CHECK(array_type != nullptr);
89 mirror::ObjectArray<mirror::Object>* result =
90 mirror::ObjectArray<mirror::Object>::Alloc(self, array_type, 3);
91 CHECK(result != nullptr);
92 for (size_t i = 0; i < 3; ++i) {
93 result->Set(static_cast<int32_t>(i), data.GetReference(i));
94 CHECK(!self->IsExceptionPending());
95 }
96 return result;
97 }
98
CheckObjectArray(mirror::ObjectArray<mirror::Object> * array,const StackHandleScope<3> & data)99 static void CheckObjectArray(mirror::ObjectArray<mirror::Object>* array,
100 const StackHandleScope<3>& data)
101 SHARED_REQUIRES(Locks::mutator_lock_) {
102 CHECK_EQ(array->GetLength(), 3);
103 CHECK_EQ(data.NumberOfReferences(), 3U);
104 for (size_t i = 0; i < 3; ++i) {
105 EXPECT_EQ(data.GetReference(i), array->Get(static_cast<int32_t>(i))) << i;
106 }
107 }
108
RunArrayCopy(Thread * self,ShadowFrame * tmp,bool expect_exception,mirror::ObjectArray<mirror::Object> * src,int32_t src_pos,mirror::ObjectArray<mirror::Object> * dst,int32_t dst_pos,int32_t length)109 void RunArrayCopy(Thread* self,
110 ShadowFrame* tmp,
111 bool expect_exception,
112 mirror::ObjectArray<mirror::Object>* src,
113 int32_t src_pos,
114 mirror::ObjectArray<mirror::Object>* dst,
115 int32_t dst_pos,
116 int32_t length)
117 SHARED_REQUIRES(Locks::mutator_lock_) {
118 JValue result;
119 tmp->SetVRegReference(0, src);
120 tmp->SetVReg(1, src_pos);
121 tmp->SetVRegReference(2, dst);
122 tmp->SetVReg(3, dst_pos);
123 tmp->SetVReg(4, length);
124 UnstartedSystemArraycopy(self, tmp, &result, 0);
125 bool exception_pending = self->IsExceptionPending();
126 EXPECT_EQ(exception_pending, expect_exception);
127 if (exception_pending) {
128 self->ClearException();
129 }
130 }
131
RunArrayCopy(Thread * self,ShadowFrame * tmp,bool expect_exception,mirror::Class * src_component_class,mirror::Class * dst_component_class,const StackHandleScope<3> & src_data,int32_t src_pos,const StackHandleScope<3> & dst_data,int32_t dst_pos,int32_t length,const StackHandleScope<3> & expected_result)132 void RunArrayCopy(Thread* self,
133 ShadowFrame* tmp,
134 bool expect_exception,
135 mirror::Class* src_component_class,
136 mirror::Class* dst_component_class,
137 const StackHandleScope<3>& src_data,
138 int32_t src_pos,
139 const StackHandleScope<3>& dst_data,
140 int32_t dst_pos,
141 int32_t length,
142 const StackHandleScope<3>& expected_result)
143 SHARED_REQUIRES(Locks::mutator_lock_) {
144 StackHandleScope<3> hs_misc(self);
145 Handle<mirror::Class> dst_component_handle(hs_misc.NewHandle(dst_component_class));
146
147 Handle<mirror::ObjectArray<mirror::Object>> src_handle(
148 hs_misc.NewHandle(CreateObjectArray(self, src_component_class, src_data)));
149
150 Handle<mirror::ObjectArray<mirror::Object>> dst_handle(
151 hs_misc.NewHandle(CreateObjectArray(self, dst_component_handle.Get(), dst_data)));
152
153 RunArrayCopy(self,
154 tmp,
155 expect_exception,
156 src_handle.Get(),
157 src_pos,
158 dst_handle.Get(),
159 dst_pos,
160 length);
161 CheckObjectArray(dst_handle.Get(), expected_result);
162 }
163
TestCeilFloor(bool ceil,Thread * self,ShadowFrame * tmp,double const test_pairs[][2],size_t num_pairs)164 void TestCeilFloor(bool ceil,
165 Thread* self,
166 ShadowFrame* tmp,
167 double const test_pairs[][2],
168 size_t num_pairs)
169 SHARED_REQUIRES(Locks::mutator_lock_) {
170 for (size_t i = 0; i < num_pairs; ++i) {
171 tmp->SetVRegDouble(0, test_pairs[i][0]);
172
173 JValue result;
174 if (ceil) {
175 UnstartedMathCeil(self, tmp, &result, 0);
176 } else {
177 UnstartedMathFloor(self, tmp, &result, 0);
178 }
179
180 ASSERT_FALSE(self->IsExceptionPending());
181
182 // We want precise results.
183 int64_t result_int64t = bit_cast<int64_t, double>(result.GetD());
184 int64_t expect_int64t = bit_cast<int64_t, double>(test_pairs[i][1]);
185 EXPECT_EQ(expect_int64t, result_int64t) << result.GetD() << " vs " << test_pairs[i][1];
186 }
187 }
188
189 // Prepare for aborts. Aborts assume that the exception class is already resolved, as the
190 // loading code doesn't work under transactions.
PrepareForAborts()191 void PrepareForAborts() SHARED_REQUIRES(Locks::mutator_lock_) {
192 mirror::Object* result = Runtime::Current()->GetClassLinker()->FindClass(
193 Thread::Current(),
194 Transaction::kAbortExceptionSignature,
195 ScopedNullHandle<mirror::ClassLoader>());
196 CHECK(result != nullptr);
197 }
198 };
199
TEST_F(UnstartedRuntimeTest,MemoryPeekByte)200 TEST_F(UnstartedRuntimeTest, MemoryPeekByte) {
201 Thread* self = Thread::Current();
202
203 ScopedObjectAccess soa(self);
204 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
205 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
206 const uint8_t* base_ptr = base_array;
207
208 JValue result;
209 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
210
211 for (int32_t i = 0; i < kBaseLen; ++i) {
212 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
213
214 UnstartedMemoryPeekByte(self, tmp, &result, 0);
215
216 EXPECT_EQ(result.GetB(), static_cast<int8_t>(base_array[i]));
217 }
218
219 ShadowFrame::DeleteDeoptimizedFrame(tmp);
220 }
221
TEST_F(UnstartedRuntimeTest,MemoryPeekShort)222 TEST_F(UnstartedRuntimeTest, MemoryPeekShort) {
223 Thread* self = Thread::Current();
224
225 ScopedObjectAccess soa(self);
226 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
227 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
228 const uint8_t* base_ptr = base_array;
229
230 JValue result;
231 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
232
233 int32_t adjusted_length = kBaseLen - sizeof(int16_t);
234 for (int32_t i = 0; i < adjusted_length; ++i) {
235 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
236
237 UnstartedMemoryPeekShort(self, tmp, &result, 0);
238
239 typedef int16_t unaligned_short __attribute__ ((aligned (1)));
240 const unaligned_short* short_ptr = reinterpret_cast<const unaligned_short*>(base_ptr + i);
241 EXPECT_EQ(result.GetS(), *short_ptr);
242 }
243
244 ShadowFrame::DeleteDeoptimizedFrame(tmp);
245 }
246
TEST_F(UnstartedRuntimeTest,MemoryPeekInt)247 TEST_F(UnstartedRuntimeTest, MemoryPeekInt) {
248 Thread* self = Thread::Current();
249
250 ScopedObjectAccess soa(self);
251 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
252 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
253 const uint8_t* base_ptr = base_array;
254
255 JValue result;
256 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
257
258 int32_t adjusted_length = kBaseLen - sizeof(int32_t);
259 for (int32_t i = 0; i < adjusted_length; ++i) {
260 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
261
262 UnstartedMemoryPeekInt(self, tmp, &result, 0);
263
264 typedef int32_t unaligned_int __attribute__ ((aligned (1)));
265 const unaligned_int* int_ptr = reinterpret_cast<const unaligned_int*>(base_ptr + i);
266 EXPECT_EQ(result.GetI(), *int_ptr);
267 }
268
269 ShadowFrame::DeleteDeoptimizedFrame(tmp);
270 }
271
TEST_F(UnstartedRuntimeTest,MemoryPeekLong)272 TEST_F(UnstartedRuntimeTest, MemoryPeekLong) {
273 Thread* self = Thread::Current();
274
275 ScopedObjectAccess soa(self);
276 constexpr const uint8_t base_array[] = "abcdefghijklmnop";
277 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t);
278 const uint8_t* base_ptr = base_array;
279
280 JValue result;
281 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
282
283 int32_t adjusted_length = kBaseLen - sizeof(int64_t);
284 for (int32_t i = 0; i < adjusted_length; ++i) {
285 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i)));
286
287 UnstartedMemoryPeekLong(self, tmp, &result, 0);
288
289 typedef int64_t unaligned_long __attribute__ ((aligned (1)));
290 const unaligned_long* long_ptr = reinterpret_cast<const unaligned_long*>(base_ptr + i);
291 EXPECT_EQ(result.GetJ(), *long_ptr);
292 }
293
294 ShadowFrame::DeleteDeoptimizedFrame(tmp);
295 }
296
TEST_F(UnstartedRuntimeTest,StringGetCharsNoCheck)297 TEST_F(UnstartedRuntimeTest, StringGetCharsNoCheck) {
298 Thread* self = Thread::Current();
299
300 ScopedObjectAccess soa(self);
301 StackHandleScope<2> hs(self);
302 // TODO: Actual UTF.
303 constexpr const char base_string[] = "abcdefghijklmnop";
304 Handle<mirror::String> h_test_string(hs.NewHandle(
305 mirror::String::AllocFromModifiedUtf8(self, base_string)));
306 constexpr int32_t kBaseLen = sizeof(base_string) / sizeof(char) - 1;
307 Handle<mirror::CharArray> h_char_array(hs.NewHandle(
308 mirror::CharArray::Alloc(self, kBaseLen)));
309 // A buffer so we can make sure we only modify the elements targetted.
310 uint16_t buf[kBaseLen];
311
312 JValue result;
313 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
314
315 for (int32_t start_index = 0; start_index < kBaseLen; ++start_index) {
316 for (int32_t count = 0; count <= kBaseLen; ++count) {
317 for (int32_t trg_offset = 0; trg_offset < kBaseLen; ++trg_offset) {
318 // Only do it when in bounds.
319 if (start_index + count <= kBaseLen && trg_offset + count <= kBaseLen) {
320 tmp->SetVRegReference(0, h_test_string.Get());
321 tmp->SetVReg(1, start_index);
322 tmp->SetVReg(2, count);
323 tmp->SetVRegReference(3, h_char_array.Get());
324 tmp->SetVReg(3, trg_offset);
325
326 // Copy the char_array into buf.
327 memcpy(buf, h_char_array->GetData(), kBaseLen * sizeof(uint16_t));
328
329 UnstartedStringCharAt(self, tmp, &result, 0);
330
331 uint16_t* data = h_char_array->GetData();
332
333 bool success = true;
334
335 // First segment should be unchanged.
336 for (int32_t i = 0; i < trg_offset; ++i) {
337 success = success && (data[i] == buf[i]);
338 }
339 // Second segment should be a copy.
340 for (int32_t i = trg_offset; i < trg_offset + count; ++i) {
341 success = success && (data[i] == buf[i - trg_offset + start_index]);
342 }
343 // Third segment should be unchanged.
344 for (int32_t i = trg_offset + count; i < kBaseLen; ++i) {
345 success = success && (data[i] == buf[i]);
346 }
347
348 EXPECT_TRUE(success);
349 }
350 }
351 }
352 }
353
354 ShadowFrame::DeleteDeoptimizedFrame(tmp);
355 }
356
TEST_F(UnstartedRuntimeTest,StringCharAt)357 TEST_F(UnstartedRuntimeTest, StringCharAt) {
358 Thread* self = Thread::Current();
359
360 ScopedObjectAccess soa(self);
361 // TODO: Actual UTF.
362 constexpr const char* base_string = "abcdefghijklmnop";
363 int32_t base_len = static_cast<int32_t>(strlen(base_string));
364 mirror::String* test_string = mirror::String::AllocFromModifiedUtf8(self, base_string);
365
366 JValue result;
367 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
368
369 for (int32_t i = 0; i < base_len; ++i) {
370 tmp->SetVRegReference(0, test_string);
371 tmp->SetVReg(1, i);
372
373 UnstartedStringCharAt(self, tmp, &result, 0);
374
375 EXPECT_EQ(result.GetI(), base_string[i]);
376 }
377
378 ShadowFrame::DeleteDeoptimizedFrame(tmp);
379 }
380
TEST_F(UnstartedRuntimeTest,StringInit)381 TEST_F(UnstartedRuntimeTest, StringInit) {
382 Thread* self = Thread::Current();
383 ScopedObjectAccess soa(self);
384 mirror::Class* klass = mirror::String::GetJavaLangString();
385 ArtMethod* method = klass->FindDeclaredDirectMethod("<init>", "(Ljava/lang/String;)V",
386 sizeof(void*));
387
388 // create instruction data for invoke-direct {v0, v1} of method with fake index
389 uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 };
390 const Instruction* inst = Instruction::At(inst_data);
391
392 JValue result;
393 ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, method, 0);
394 const char* base_string = "hello_world";
395 mirror::String* string_arg = mirror::String::AllocFromModifiedUtf8(self, base_string);
396 mirror::String* reference_empty_string = mirror::String::AllocFromModifiedUtf8(self, "");
397 shadow_frame->SetVRegReference(0, reference_empty_string);
398 shadow_frame->SetVRegReference(1, string_arg);
399
400 interpreter::DoCall<false, false>(method, self, *shadow_frame, inst, inst_data[0], &result);
401 mirror::String* string_result = reinterpret_cast<mirror::String*>(result.GetL());
402 EXPECT_EQ(string_arg->GetLength(), string_result->GetLength());
403 EXPECT_EQ(memcmp(string_arg->GetValue(), string_result->GetValue(),
404 string_arg->GetLength() * sizeof(uint16_t)), 0);
405
406 ShadowFrame::DeleteDeoptimizedFrame(shadow_frame);
407 }
408
409 // Tests the exceptions that should be checked before modifying the destination.
410 // (Doesn't check the object vs primitive case ATM.)
TEST_F(UnstartedRuntimeTest,SystemArrayCopyObjectArrayTestExceptions)411 TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTestExceptions) {
412 Thread* self = Thread::Current();
413 ScopedObjectAccess soa(self);
414 JValue result;
415 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
416
417 // Note: all tests are not GC safe. Assume there's no GC running here with the few objects we
418 // allocate.
419 StackHandleScope<2> hs_misc(self);
420 Handle<mirror::Class> object_class(
421 hs_misc.NewHandle(mirror::Class::GetJavaLangClass()->GetSuperClass()));
422
423 StackHandleScope<3> hs_data(self);
424 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
425 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
426 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
427
428 Handle<mirror::ObjectArray<mirror::Object>> array(
429 hs_misc.NewHandle(CreateObjectArray(self, object_class.Get(), hs_data)));
430
431 RunArrayCopy(self, tmp, true, array.Get(), -1, array.Get(), 0, 0);
432 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), -1, 0);
433 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 0, -1);
434 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 0, 4);
435 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 1, 3);
436 RunArrayCopy(self, tmp, true, array.Get(), 1, array.Get(), 0, 3);
437
438 mirror::ObjectArray<mirror::Object>* class_as_array =
439 reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(object_class.Get());
440 RunArrayCopy(self, tmp, true, class_as_array, 0, array.Get(), 0, 0);
441 RunArrayCopy(self, tmp, true, array.Get(), 0, class_as_array, 0, 0);
442
443 ShadowFrame::DeleteDeoptimizedFrame(tmp);
444 }
445
TEST_F(UnstartedRuntimeTest,SystemArrayCopyObjectArrayTest)446 TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) {
447 Thread* self = Thread::Current();
448 ScopedObjectAccess soa(self);
449 JValue result;
450 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
451
452 StackHandleScope<1> hs_object(self);
453 Handle<mirror::Class> object_class(
454 hs_object.NewHandle(mirror::Class::GetJavaLangClass()->GetSuperClass()));
455
456 // Simple test:
457 // [1,2,3]{1 @ 2} into [4,5,6] = [4,2,6]
458 {
459 StackHandleScope<3> hs_src(self);
460 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
461 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
462 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
463
464 StackHandleScope<3> hs_dst(self);
465 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
466 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
467 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
468
469 StackHandleScope<3> hs_expected(self);
470 hs_expected.NewHandle(hs_dst.GetReference(0));
471 hs_expected.NewHandle(hs_dst.GetReference(1));
472 hs_expected.NewHandle(hs_src.GetReference(1));
473
474 RunArrayCopy(self,
475 tmp,
476 false,
477 object_class.Get(),
478 object_class.Get(),
479 hs_src,
480 1,
481 hs_dst,
482 2,
483 1,
484 hs_expected);
485 }
486
487 // Simple test:
488 // [1,2,3]{1 @ 1} into [4,5,6] = [4,2,6] (with dst String[])
489 {
490 StackHandleScope<3> hs_src(self);
491 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
492 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2"));
493 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
494
495 StackHandleScope<3> hs_dst(self);
496 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
497 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
498 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
499
500 StackHandleScope<3> hs_expected(self);
501 hs_expected.NewHandle(hs_dst.GetReference(0));
502 hs_expected.NewHandle(hs_src.GetReference(1));
503 hs_expected.NewHandle(hs_dst.GetReference(2));
504
505 RunArrayCopy(self,
506 tmp,
507 false,
508 object_class.Get(),
509 mirror::String::GetJavaLangString(),
510 hs_src,
511 1,
512 hs_dst,
513 1,
514 1,
515 hs_expected);
516 }
517
518 // Simple test:
519 // [1,*,3] into [4,5,6] = [1,5,6] + exc
520 {
521 StackHandleScope<3> hs_src(self);
522 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1"));
523 hs_src.NewHandle(mirror::String::GetJavaLangString());
524 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3"));
525
526 StackHandleScope<3> hs_dst(self);
527 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4"));
528 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5"));
529 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6"));
530
531 StackHandleScope<3> hs_expected(self);
532 hs_expected.NewHandle(hs_src.GetReference(0));
533 hs_expected.NewHandle(hs_dst.GetReference(1));
534 hs_expected.NewHandle(hs_dst.GetReference(2));
535
536 RunArrayCopy(self,
537 tmp,
538 true,
539 object_class.Get(),
540 mirror::String::GetJavaLangString(),
541 hs_src,
542 0,
543 hs_dst,
544 0,
545 3,
546 hs_expected);
547 }
548
549 ShadowFrame::DeleteDeoptimizedFrame(tmp);
550 }
551
TEST_F(UnstartedRuntimeTest,IntegerParseIntTest)552 TEST_F(UnstartedRuntimeTest, IntegerParseIntTest) {
553 Thread* self = Thread::Current();
554 ScopedObjectAccess soa(self);
555
556 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
557
558 // Test string. Should be valid, and between minimal values of LONG_MIN and LONG_MAX (for all
559 // suffixes).
560 constexpr const char* test_string = "-2147483646";
561 constexpr int32_t test_values[] = {
562 6,
563 46,
564 646,
565 3646,
566 83646,
567 483646,
568 7483646,
569 47483646,
570 147483646,
571 2147483646,
572 -2147483646
573 };
574
575 static_assert(arraysize(test_values) == 11U, "test_values");
576 CHECK_EQ(strlen(test_string), 11U);
577
578 for (size_t i = 0; i <= 10; ++i) {
579 const char* test_value = &test_string[10 - i];
580
581 StackHandleScope<1> hs_str(self);
582 Handle<mirror::String> h_str(
583 hs_str.NewHandle(mirror::String::AllocFromModifiedUtf8(self, test_value)));
584 ASSERT_NE(h_str.Get(), nullptr);
585 ASSERT_FALSE(self->IsExceptionPending());
586
587 tmp->SetVRegReference(0, h_str.Get());
588
589 JValue result;
590 UnstartedIntegerParseInt(self, tmp, &result, 0);
591
592 ASSERT_FALSE(self->IsExceptionPending());
593 EXPECT_EQ(result.GetI(), test_values[i]);
594 }
595
596 ShadowFrame::DeleteDeoptimizedFrame(tmp);
597 }
598
599 // Right now the same as Integer.Parse
TEST_F(UnstartedRuntimeTest,LongParseLongTest)600 TEST_F(UnstartedRuntimeTest, LongParseLongTest) {
601 Thread* self = Thread::Current();
602 ScopedObjectAccess soa(self);
603
604 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
605
606 // Test string. Should be valid, and between minimal values of LONG_MIN and LONG_MAX (for all
607 // suffixes).
608 constexpr const char* test_string = "-2147483646";
609 constexpr int64_t test_values[] = {
610 6,
611 46,
612 646,
613 3646,
614 83646,
615 483646,
616 7483646,
617 47483646,
618 147483646,
619 2147483646,
620 -2147483646
621 };
622
623 static_assert(arraysize(test_values) == 11U, "test_values");
624 CHECK_EQ(strlen(test_string), 11U);
625
626 for (size_t i = 0; i <= 10; ++i) {
627 const char* test_value = &test_string[10 - i];
628
629 StackHandleScope<1> hs_str(self);
630 Handle<mirror::String> h_str(
631 hs_str.NewHandle(mirror::String::AllocFromModifiedUtf8(self, test_value)));
632 ASSERT_NE(h_str.Get(), nullptr);
633 ASSERT_FALSE(self->IsExceptionPending());
634
635 tmp->SetVRegReference(0, h_str.Get());
636
637 JValue result;
638 UnstartedLongParseLong(self, tmp, &result, 0);
639
640 ASSERT_FALSE(self->IsExceptionPending());
641 EXPECT_EQ(result.GetJ(), test_values[i]);
642 }
643
644 ShadowFrame::DeleteDeoptimizedFrame(tmp);
645 }
646
TEST_F(UnstartedRuntimeTest,Ceil)647 TEST_F(UnstartedRuntimeTest, Ceil) {
648 Thread* self = Thread::Current();
649 ScopedObjectAccess soa(self);
650
651 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
652
653 constexpr double nan = std::numeric_limits<double>::quiet_NaN();
654 constexpr double inf = std::numeric_limits<double>::infinity();
655 constexpr double ld1 = static_cast<double>((UINT64_C(1) << 53) - 1);
656 constexpr double ld2 = static_cast<double>(UINT64_C(1) << 55);
657 constexpr double test_pairs[][2] = {
658 { -0.0, -0.0 },
659 { 0.0, 0.0 },
660 { -0.5, -0.0 },
661 { -1.0, -1.0 },
662 { 0.5, 1.0 },
663 { 1.0, 1.0 },
664 { nan, nan },
665 { inf, inf },
666 { -inf, -inf },
667 { ld1, ld1 },
668 { ld2, ld2 }
669 };
670
671 TestCeilFloor(true /* ceil */, self, tmp, test_pairs, arraysize(test_pairs));
672
673 ShadowFrame::DeleteDeoptimizedFrame(tmp);
674 }
675
TEST_F(UnstartedRuntimeTest,Floor)676 TEST_F(UnstartedRuntimeTest, Floor) {
677 Thread* self = Thread::Current();
678 ScopedObjectAccess soa(self);
679
680 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
681
682 constexpr double nan = std::numeric_limits<double>::quiet_NaN();
683 constexpr double inf = std::numeric_limits<double>::infinity();
684 constexpr double ld1 = static_cast<double>((UINT64_C(1) << 53) - 1);
685 constexpr double ld2 = static_cast<double>(UINT64_C(1) << 55);
686 constexpr double test_pairs[][2] = {
687 { -0.0, -0.0 },
688 { 0.0, 0.0 },
689 { -0.5, -1.0 },
690 { -1.0, -1.0 },
691 { 0.5, 0.0 },
692 { 1.0, 1.0 },
693 { nan, nan },
694 { inf, inf },
695 { -inf, -inf },
696 { ld1, ld1 },
697 { ld2, ld2 }
698 };
699
700 TestCeilFloor(false /* floor */, self, tmp, test_pairs, arraysize(test_pairs));
701
702 ShadowFrame::DeleteDeoptimizedFrame(tmp);
703 }
704
TEST_F(UnstartedRuntimeTest,ToLowerUpper)705 TEST_F(UnstartedRuntimeTest, ToLowerUpper) {
706 Thread* self = Thread::Current();
707 ScopedObjectAccess soa(self);
708
709 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
710
711 std::locale c_locale("C");
712
713 // Check ASCII.
714 for (uint32_t i = 0; i < 128; ++i) {
715 bool c_upper = std::isupper(static_cast<char>(i), c_locale);
716 bool c_lower = std::islower(static_cast<char>(i), c_locale);
717 EXPECT_FALSE(c_upper && c_lower) << i;
718
719 // Check toLowerCase.
720 {
721 JValue result;
722 tmp->SetVReg(0, static_cast<int32_t>(i));
723 UnstartedCharacterToLowerCase(self, tmp, &result, 0);
724 ASSERT_FALSE(self->IsExceptionPending());
725 uint32_t lower_result = static_cast<uint32_t>(result.GetI());
726 if (c_lower) {
727 EXPECT_EQ(i, lower_result);
728 } else if (c_upper) {
729 EXPECT_EQ(static_cast<uint32_t>(std::tolower(static_cast<char>(i), c_locale)),
730 lower_result);
731 } else {
732 EXPECT_EQ(i, lower_result);
733 }
734 }
735
736 // Check toUpperCase.
737 {
738 JValue result2;
739 tmp->SetVReg(0, static_cast<int32_t>(i));
740 UnstartedCharacterToUpperCase(self, tmp, &result2, 0);
741 ASSERT_FALSE(self->IsExceptionPending());
742 uint32_t upper_result = static_cast<uint32_t>(result2.GetI());
743 if (c_upper) {
744 EXPECT_EQ(i, upper_result);
745 } else if (c_lower) {
746 EXPECT_EQ(static_cast<uint32_t>(std::toupper(static_cast<char>(i), c_locale)),
747 upper_result);
748 } else {
749 EXPECT_EQ(i, upper_result);
750 }
751 }
752 }
753
754 // Check abort for other things. Can't test all.
755
756 PrepareForAborts();
757
758 for (uint32_t i = 128; i < 256; ++i) {
759 {
760 JValue result;
761 tmp->SetVReg(0, static_cast<int32_t>(i));
762 Transaction transaction;
763 Runtime::Current()->EnterTransactionMode(&transaction);
764 UnstartedCharacterToLowerCase(self, tmp, &result, 0);
765 Runtime::Current()->ExitTransactionMode();
766 ASSERT_TRUE(self->IsExceptionPending());
767 ASSERT_TRUE(transaction.IsAborted());
768 }
769 {
770 JValue result;
771 tmp->SetVReg(0, static_cast<int32_t>(i));
772 Transaction transaction;
773 Runtime::Current()->EnterTransactionMode(&transaction);
774 UnstartedCharacterToUpperCase(self, tmp, &result, 0);
775 Runtime::Current()->ExitTransactionMode();
776 ASSERT_TRUE(self->IsExceptionPending());
777 ASSERT_TRUE(transaction.IsAborted());
778 }
779 }
780 for (uint64_t i = 256; i <= std::numeric_limits<uint32_t>::max(); i <<= 1) {
781 {
782 JValue result;
783 tmp->SetVReg(0, static_cast<int32_t>(i));
784 Transaction transaction;
785 Runtime::Current()->EnterTransactionMode(&transaction);
786 UnstartedCharacterToLowerCase(self, tmp, &result, 0);
787 Runtime::Current()->ExitTransactionMode();
788 ASSERT_TRUE(self->IsExceptionPending());
789 ASSERT_TRUE(transaction.IsAborted());
790 }
791 {
792 JValue result;
793 tmp->SetVReg(0, static_cast<int32_t>(i));
794 Transaction transaction;
795 Runtime::Current()->EnterTransactionMode(&transaction);
796 UnstartedCharacterToUpperCase(self, tmp, &result, 0);
797 Runtime::Current()->ExitTransactionMode();
798 ASSERT_TRUE(self->IsExceptionPending());
799 ASSERT_TRUE(transaction.IsAborted());
800 }
801 }
802
803 ShadowFrame::DeleteDeoptimizedFrame(tmp);
804 }
805
TEST_F(UnstartedRuntimeTest,Sin)806 TEST_F(UnstartedRuntimeTest, Sin) {
807 Thread* self = Thread::Current();
808 ScopedObjectAccess soa(self);
809
810 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
811
812 // Test an important value, PI/6. That's the one we see in practice.
813 constexpr uint64_t lvalue = UINT64_C(0x3fe0c152382d7365);
814 tmp->SetVRegLong(0, static_cast<int64_t>(lvalue));
815
816 JValue result;
817 UnstartedMathSin(self, tmp, &result, 0);
818
819 const uint64_t lresult = static_cast<uint64_t>(result.GetJ());
820 EXPECT_EQ(UINT64_C(0x3fdfffffffffffff), lresult);
821
822 ShadowFrame::DeleteDeoptimizedFrame(tmp);
823 }
824
TEST_F(UnstartedRuntimeTest,Cos)825 TEST_F(UnstartedRuntimeTest, Cos) {
826 Thread* self = Thread::Current();
827 ScopedObjectAccess soa(self);
828
829 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
830
831 // Test an important value, PI/6. That's the one we see in practice.
832 constexpr uint64_t lvalue = UINT64_C(0x3fe0c152382d7365);
833 tmp->SetVRegLong(0, static_cast<int64_t>(lvalue));
834
835 JValue result;
836 UnstartedMathCos(self, tmp, &result, 0);
837
838 const uint64_t lresult = static_cast<uint64_t>(result.GetJ());
839 EXPECT_EQ(UINT64_C(0x3febb67ae8584cab), lresult);
840
841 ShadowFrame::DeleteDeoptimizedFrame(tmp);
842 }
843
TEST_F(UnstartedRuntimeTest,Pow)844 TEST_F(UnstartedRuntimeTest, Pow) {
845 // Valgrind seems to get this wrong, actually. Disable for valgrind.
846 if (RUNNING_ON_MEMORY_TOOL != 0 && kMemoryToolIsValgrind) {
847 return;
848 }
849
850 Thread* self = Thread::Current();
851 ScopedObjectAccess soa(self);
852
853 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0);
854
855 // Test an important pair.
856 constexpr uint64_t lvalue1 = UINT64_C(0x4079000000000000);
857 constexpr uint64_t lvalue2 = UINT64_C(0xbfe6db6dc0000000);
858
859 tmp->SetVRegLong(0, static_cast<int64_t>(lvalue1));
860 tmp->SetVRegLong(2, static_cast<int64_t>(lvalue2));
861
862 JValue result;
863 UnstartedMathPow(self, tmp, &result, 0);
864
865 const uint64_t lresult = static_cast<uint64_t>(result.GetJ());
866 EXPECT_EQ(UINT64_C(0x3f8c5c51326aa7ee), lresult);
867
868 ShadowFrame::DeleteDeoptimizedFrame(tmp);
869 }
870
871 } // namespace interpreter
872 } // namespace art
873