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_test.h" 18 19 #include <limits> 20 #include <locale> 21 22 #include "base/casts.h" 23 #include "base/memory_tool.h" 24 #include "base/pointer_size.h" 25 #include "class_linker.h" 26 #include "class_root-inl.h" 27 #include "common_runtime_test.h" 28 #include "common_throws.h" 29 #include "dex/descriptors_names.h" 30 #include "dex/dex_instruction.h" 31 #include "handle.h" 32 #include "handle_scope-inl.h" 33 #include "interpreter_common.h" 34 #include "mirror/array-alloc-inl.h" 35 #include "mirror/class-alloc-inl.h" 36 #include "mirror/class_loader.h" 37 #include "mirror/object-inl.h" 38 #include "mirror/object_array-alloc-inl.h" 39 #include "mirror/object_array-inl.h" 40 #include "mirror/string-inl.h" 41 #include "runtime.h" 42 #include "runtime_intrinsics.h" 43 #include "scoped_thread_state_change-inl.h" 44 #include "shadow_frame-inl.h" 45 #include "thread.h" 46 #include "unstarted_runtime_list.h" 47 48 namespace art HIDDEN { 49 namespace interpreter { 50 51 class UnstartedRuntimeTest : public UnstartedRuntimeTestBase { 52 protected: 53 // Helpers for ArrayCopy. 54 // 55 // Note: as we have to use handles, we use StackHandleScope to transfer data. Hardcode a size 56 // of three everywhere. That is enough to test all cases. 57 CreateObjectArray(Thread * self,ObjPtr<mirror::Class> component_type,const StackHandleScope<3> & data)58 static ObjPtr<mirror::ObjectArray<mirror::Object>> CreateObjectArray( 59 Thread* self, 60 ObjPtr<mirror::Class> component_type, 61 const StackHandleScope<3>& data) 62 REQUIRES_SHARED(Locks::mutator_lock_) { 63 Runtime* runtime = Runtime::Current(); 64 ObjPtr<mirror::Class> array_type = 65 runtime->GetClassLinker()->FindArrayClass(self, component_type); 66 CHECK(array_type != nullptr); 67 ObjPtr<mirror::ObjectArray<mirror::Object>> result = 68 mirror::ObjectArray<mirror::Object>::Alloc(self, array_type, 3); 69 CHECK(result != nullptr); 70 for (size_t i = 0; i < 3; ++i) { 71 result->Set(static_cast<int32_t>(i), data.GetReference(i)); 72 CHECK(!self->IsExceptionPending()); 73 } 74 return result; 75 } 76 CheckObjectArray(ObjPtr<mirror::ObjectArray<mirror::Object>> array,const StackHandleScope<3> & data)77 static void CheckObjectArray(ObjPtr<mirror::ObjectArray<mirror::Object>> array, 78 const StackHandleScope<3>& data) 79 REQUIRES_SHARED(Locks::mutator_lock_) { 80 CHECK_EQ(array->GetLength(), 3); 81 CHECK_EQ(data.Size(), 3U); 82 for (size_t i = 0; i < 3; ++i) { 83 EXPECT_OBJ_PTR_EQ(data.GetReference(i), array->Get(static_cast<int32_t>(i))) << i; 84 } 85 } 86 RunArrayCopy(Thread * self,ShadowFrame * tmp,bool expect_exception,ObjPtr<mirror::ObjectArray<mirror::Object>> src,int32_t src_pos,ObjPtr<mirror::ObjectArray<mirror::Object>> dst,int32_t dst_pos,int32_t length)87 void RunArrayCopy(Thread* self, 88 ShadowFrame* tmp, 89 bool expect_exception, 90 ObjPtr<mirror::ObjectArray<mirror::Object>> src, 91 int32_t src_pos, 92 ObjPtr<mirror::ObjectArray<mirror::Object>> dst, 93 int32_t dst_pos, 94 int32_t length) 95 REQUIRES_SHARED(Locks::mutator_lock_) { 96 JValue result; 97 tmp->SetVRegReference(0, src); 98 tmp->SetVReg(1, src_pos); 99 tmp->SetVRegReference(2, dst); 100 tmp->SetVReg(3, dst_pos); 101 tmp->SetVReg(4, length); 102 UnstartedSystemArraycopy(self, tmp, &result, 0); 103 bool exception_pending = self->IsExceptionPending(); 104 EXPECT_EQ(exception_pending, expect_exception); 105 if (exception_pending) { 106 self->ClearException(); 107 } 108 } 109 RunArrayCopy(Thread * self,ShadowFrame * tmp,bool expect_exception,ObjPtr<mirror::Class> src_component_class,ObjPtr<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)110 void RunArrayCopy(Thread* self, 111 ShadowFrame* tmp, 112 bool expect_exception, 113 ObjPtr<mirror::Class> src_component_class, 114 ObjPtr<mirror::Class> dst_component_class, 115 const StackHandleScope<3>& src_data, 116 int32_t src_pos, 117 const StackHandleScope<3>& dst_data, 118 int32_t dst_pos, 119 int32_t length, 120 const StackHandleScope<3>& expected_result) 121 REQUIRES_SHARED(Locks::mutator_lock_) { 122 StackHandleScope<3> hs_misc(self); 123 Handle<mirror::Class> dst_component_handle(hs_misc.NewHandle(dst_component_class)); 124 125 Handle<mirror::ObjectArray<mirror::Object>> src_handle( 126 hs_misc.NewHandle(CreateObjectArray(self, src_component_class, src_data))); 127 128 Handle<mirror::ObjectArray<mirror::Object>> dst_handle( 129 hs_misc.NewHandle(CreateObjectArray(self, dst_component_handle.Get(), dst_data))); 130 131 RunArrayCopy(self, 132 tmp, 133 expect_exception, 134 src_handle.Get(), 135 src_pos, 136 dst_handle.Get(), 137 dst_pos, 138 length); 139 CheckObjectArray(dst_handle.Get(), expected_result); 140 } 141 TestCeilFloor(bool ceil,Thread * self,ShadowFrame * tmp,double const test_pairs[][2],size_t num_pairs)142 void TestCeilFloor(bool ceil, 143 Thread* self, 144 ShadowFrame* tmp, 145 double const test_pairs[][2], 146 size_t num_pairs) 147 REQUIRES_SHARED(Locks::mutator_lock_) { 148 for (size_t i = 0; i < num_pairs; ++i) { 149 tmp->SetVRegDouble(0, test_pairs[i][0]); 150 151 JValue result; 152 if (ceil) { 153 UnstartedMathCeil(self, tmp, &result, 0); 154 } else { 155 UnstartedMathFloor(self, tmp, &result, 0); 156 } 157 158 ASSERT_FALSE(self->IsExceptionPending()); 159 160 // We want precise results. 161 int64_t result_int64t = bit_cast<int64_t, double>(result.GetD()); 162 int64_t expect_int64t = bit_cast<int64_t, double>(test_pairs[i][1]); 163 EXPECT_EQ(expect_int64t, result_int64t) << result.GetD() << " vs " << test_pairs[i][1]; 164 } 165 } 166 }; 167 TEST_F(UnstartedRuntimeTest,MemoryPeekByte)168 TEST_F(UnstartedRuntimeTest, MemoryPeekByte) { 169 Thread* self = Thread::Current(); 170 171 ScopedObjectAccess soa(self); 172 constexpr const uint8_t base_array[] = "abcdefghijklmnop"; 173 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t); 174 const uint8_t* base_ptr = base_array; 175 176 JValue result; 177 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 178 179 for (int32_t i = 0; i < kBaseLen; ++i) { 180 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i))); 181 182 UnstartedMemoryPeekByte(self, tmp.get(), &result, 0); 183 184 EXPECT_EQ(result.GetB(), static_cast<int8_t>(base_array[i])); 185 } 186 } 187 TEST_F(UnstartedRuntimeTest,MemoryPeekShort)188 TEST_F(UnstartedRuntimeTest, MemoryPeekShort) { 189 Thread* self = Thread::Current(); 190 191 ScopedObjectAccess soa(self); 192 constexpr const uint8_t base_array[] = "abcdefghijklmnop"; 193 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t); 194 const uint8_t* base_ptr = base_array; 195 196 JValue result; 197 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 198 199 int32_t adjusted_length = kBaseLen - sizeof(int16_t); 200 for (int32_t i = 0; i < adjusted_length; ++i) { 201 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i))); 202 203 UnstartedMemoryPeekShort(self, tmp.get(), &result, 0); 204 205 using unaligned_short __attribute__((__aligned__(1))) = int16_t; 206 const unaligned_short* short_ptr = reinterpret_cast<const unaligned_short*>(base_ptr + i); 207 EXPECT_EQ(result.GetS(), *short_ptr); 208 } 209 } 210 TEST_F(UnstartedRuntimeTest,MemoryPeekInt)211 TEST_F(UnstartedRuntimeTest, MemoryPeekInt) { 212 Thread* self = Thread::Current(); 213 214 ScopedObjectAccess soa(self); 215 constexpr const uint8_t base_array[] = "abcdefghijklmnop"; 216 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t); 217 const uint8_t* base_ptr = base_array; 218 219 JValue result; 220 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 221 222 int32_t adjusted_length = kBaseLen - sizeof(int32_t); 223 for (int32_t i = 0; i < adjusted_length; ++i) { 224 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i))); 225 226 UnstartedMemoryPeekInt(self, tmp.get(), &result, 0); 227 228 using unaligned_int __attribute__((__aligned__(1))) = int32_t; 229 const unaligned_int* int_ptr = reinterpret_cast<const unaligned_int*>(base_ptr + i); 230 EXPECT_EQ(result.GetI(), *int_ptr); 231 } 232 } 233 TEST_F(UnstartedRuntimeTest,MemoryPeekLong)234 TEST_F(UnstartedRuntimeTest, MemoryPeekLong) { 235 Thread* self = Thread::Current(); 236 237 ScopedObjectAccess soa(self); 238 constexpr const uint8_t base_array[] = "abcdefghijklmnop"; 239 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t); 240 const uint8_t* base_ptr = base_array; 241 242 JValue result; 243 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 244 245 int32_t adjusted_length = kBaseLen - sizeof(int64_t); 246 for (int32_t i = 0; i < adjusted_length; ++i) { 247 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i))); 248 249 UnstartedMemoryPeekLong(self, tmp.get(), &result, 0); 250 251 using unaligned_long __attribute__((__aligned__(1))) = int64_t; 252 const unaligned_long* long_ptr = reinterpret_cast<const unaligned_long*>(base_ptr + i); 253 EXPECT_EQ(result.GetJ(), *long_ptr); 254 } 255 } 256 TEST_F(UnstartedRuntimeTest,StringGetCharsNoCheck)257 TEST_F(UnstartedRuntimeTest, StringGetCharsNoCheck) { 258 Thread* self = Thread::Current(); 259 260 ScopedObjectAccess soa(self); 261 StackHandleScope<2> hs(self); 262 // TODO: Actual UTF. 263 constexpr const char base_string[] = "abcdefghijklmnop"; 264 Handle<mirror::String> h_test_string(hs.NewHandle( 265 mirror::String::AllocFromModifiedUtf8(self, base_string))); 266 constexpr int32_t kBaseLen = sizeof(base_string) / sizeof(char) - 1; 267 Handle<mirror::CharArray> h_char_array(hs.NewHandle( 268 mirror::CharArray::Alloc(self, kBaseLen))); 269 // A buffer so we can make sure we only modify the elements targetted. 270 uint16_t buf[kBaseLen]; 271 272 JValue result; 273 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 274 275 for (int32_t start_index = 0; start_index < kBaseLen; ++start_index) { 276 for (int32_t count = 0; count <= kBaseLen; ++count) { 277 for (int32_t trg_offset = 0; trg_offset < kBaseLen; ++trg_offset) { 278 // Only do it when in bounds. 279 if (start_index + count <= kBaseLen && trg_offset + count <= kBaseLen) { 280 tmp->SetVRegReference(0, h_test_string.Get()); 281 tmp->SetVReg(1, start_index); 282 tmp->SetVReg(2, count); 283 tmp->SetVRegReference(3, h_char_array.Get()); 284 tmp->SetVReg(3, trg_offset); 285 286 // Copy the char_array into buf. 287 memcpy(buf, h_char_array->GetData(), kBaseLen * sizeof(uint16_t)); 288 289 UnstartedStringCharAt(self, tmp.get(), &result, 0); 290 291 uint16_t* data = h_char_array->GetData(); 292 293 bool success = true; 294 295 // First segment should be unchanged. 296 for (int32_t i = 0; i < trg_offset; ++i) { 297 success = success && (data[i] == buf[i]); 298 } 299 // Second segment should be a copy. 300 for (int32_t i = trg_offset; i < trg_offset + count; ++i) { 301 success = success && (data[i] == buf[i - trg_offset + start_index]); 302 } 303 // Third segment should be unchanged. 304 for (int32_t i = trg_offset + count; i < kBaseLen; ++i) { 305 success = success && (data[i] == buf[i]); 306 } 307 308 EXPECT_TRUE(success); 309 } 310 } 311 } 312 } 313 } 314 TEST_F(UnstartedRuntimeTest,StringCharAt)315 TEST_F(UnstartedRuntimeTest, StringCharAt) { 316 Thread* self = Thread::Current(); 317 318 ScopedObjectAccess soa(self); 319 // TODO: Actual UTF. 320 constexpr const char* base_string = "abcdefghijklmnop"; 321 int32_t base_len = static_cast<int32_t>(strlen(base_string)); 322 ObjPtr<mirror::String> test_string = mirror::String::AllocFromModifiedUtf8(self, base_string); 323 324 JValue result; 325 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 326 327 for (int32_t i = 0; i < base_len; ++i) { 328 tmp->SetVRegReference(0, test_string); 329 tmp->SetVReg(1, i); 330 331 UnstartedStringCharAt(self, tmp.get(), &result, 0); 332 333 EXPECT_EQ(result.GetI(), base_string[i]); 334 } 335 } 336 TEST_F(UnstartedRuntimeTest,StringInit)337 TEST_F(UnstartedRuntimeTest, StringInit) { 338 Thread* self = Thread::Current(); 339 ScopedObjectAccess soa(self); 340 ObjPtr<mirror::Class> klass = GetClassRoot<mirror::String>(); 341 ArtMethod* method = 342 klass->FindConstructor("(Ljava/lang/String;)V", class_linker_->GetImagePointerSize()); 343 ASSERT_TRUE(method != nullptr); 344 345 // create instruction data for invoke-direct {v0, v1} of method with fake index 346 uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 }; 347 348 JValue result; 349 UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, method, 0); 350 const char* base_string = "hello_world"; 351 StackHandleScope<2> hs(self); 352 Handle<mirror::String> string_arg = 353 hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, base_string)); 354 Handle<mirror::String> reference_empty_string = 355 hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "")); 356 shadow_frame->SetVRegReference(0, reference_empty_string.Get()); 357 shadow_frame->SetVRegReference(1, string_arg.Get()); 358 359 ArtMethod* factory = WellKnownClasses::StringInitToStringFactory(method); 360 interpreter::DoCall<false>(factory, 361 self, 362 *shadow_frame, 363 Instruction::At(inst_data), 364 inst_data[0], 365 /* string_init= */ true, 366 &result); 367 ObjPtr<mirror::String> string_result = down_cast<mirror::String*>(result.GetL()); 368 EXPECT_EQ(string_arg->GetLength(), string_result->GetLength()); 369 370 if (string_arg->IsCompressed() && string_result->IsCompressed()) { 371 EXPECT_EQ(memcmp(string_arg->GetValueCompressed(), string_result->GetValueCompressed(), 372 string_arg->GetLength() * sizeof(uint8_t)), 0); 373 } else if (!string_arg->IsCompressed() && !string_result->IsCompressed()) { 374 EXPECT_EQ(memcmp(string_arg->GetValue(), string_result->GetValue(), 375 string_arg->GetLength() * sizeof(uint16_t)), 0); 376 } else { 377 bool equal = true; 378 for (int i = 0; i < string_arg->GetLength(); ++i) { 379 if (string_arg->CharAt(i) != string_result->CharAt(i)) { 380 equal = false; 381 break; 382 } 383 } 384 EXPECT_EQ(equal, true); 385 } 386 } 387 388 // Tests the exceptions that should be checked before modifying the destination. 389 // (Doesn't check the object vs primitive case ATM.) TEST_F(UnstartedRuntimeTest,SystemArrayCopyObjectArrayTestExceptions)390 TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTestExceptions) { 391 Thread* self = Thread::Current(); 392 ScopedObjectAccess soa(self); 393 JValue result; 394 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 395 396 // Note: all tests are not GC safe. Assume there's no GC running here with the few objects we 397 // allocate. 398 StackHandleScope<3> hs_misc(self); 399 Handle<mirror::Class> object_class(hs_misc.NewHandle(GetClassRoot<mirror::Object>())); 400 401 StackHandleScope<3> hs_data(self); 402 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1")); 403 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2")); 404 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3")); 405 406 Handle<mirror::ObjectArray<mirror::Object>> array( 407 hs_misc.NewHandle(CreateObjectArray(self, object_class.Get(), hs_data))); 408 409 RunArrayCopy(self, tmp.get(), true, array.Get(), -1, array.Get(), 0, 0); 410 RunArrayCopy(self, tmp.get(), true, array.Get(), 0, array.Get(), -1, 0); 411 RunArrayCopy(self, tmp.get(), true, array.Get(), 0, array.Get(), 0, -1); 412 RunArrayCopy(self, tmp.get(), true, array.Get(), 0, array.Get(), 0, 4); 413 RunArrayCopy(self, tmp.get(), true, array.Get(), 0, array.Get(), 1, 3); 414 RunArrayCopy(self, tmp.get(), true, array.Get(), 1, array.Get(), 0, 3); 415 416 Handle<mirror::ObjectArray<mirror::Object>> class_as_array = 417 hs_misc.NewHandle(reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(object_class.Get())); 418 RunArrayCopy(self, tmp.get(), true, class_as_array.Get(), 0, array.Get(), 0, 0); 419 RunArrayCopy(self, tmp.get(), true, array.Get(), 0, class_as_array.Get(), 0, 0); 420 } 421 TEST_F(UnstartedRuntimeTest,SystemArrayCopyObjectArrayTest)422 TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) { 423 Thread* self = Thread::Current(); 424 ScopedObjectAccess soa(self); 425 JValue result; 426 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 427 428 // Simple test: 429 // [1,2,3]{1 @ 2} into [4,5,6] = [4,2,6] 430 { 431 StackHandleScope<3> hs_src(self); 432 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1")); 433 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2")); 434 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3")); 435 436 StackHandleScope<3> hs_dst(self); 437 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4")); 438 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5")); 439 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6")); 440 441 StackHandleScope<3> hs_expected(self); 442 hs_expected.NewHandle(hs_dst.GetReference(0)); 443 hs_expected.NewHandle(hs_dst.GetReference(1)); 444 hs_expected.NewHandle(hs_src.GetReference(1)); 445 446 RunArrayCopy(self, 447 tmp.get(), 448 false, 449 GetClassRoot<mirror::Object>(), 450 GetClassRoot<mirror::Object>(), 451 hs_src, 452 1, 453 hs_dst, 454 2, 455 1, 456 hs_expected); 457 } 458 459 // Simple test: 460 // [1,2,3]{1 @ 1} into [4,5,6] = [4,2,6] (with dst String[]) 461 { 462 StackHandleScope<3> hs_src(self); 463 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1")); 464 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2")); 465 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3")); 466 467 StackHandleScope<3> hs_dst(self); 468 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4")); 469 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5")); 470 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6")); 471 472 StackHandleScope<3> hs_expected(self); 473 hs_expected.NewHandle(hs_dst.GetReference(0)); 474 hs_expected.NewHandle(hs_src.GetReference(1)); 475 hs_expected.NewHandle(hs_dst.GetReference(2)); 476 477 RunArrayCopy(self, 478 tmp.get(), 479 false, 480 GetClassRoot<mirror::Object>(), 481 GetClassRoot<mirror::String>(), 482 hs_src, 483 1, 484 hs_dst, 485 1, 486 1, 487 hs_expected); 488 } 489 490 // Simple test: 491 // [1,*,3] into [4,5,6] = [1,5,6] + exc 492 { 493 StackHandleScope<3> hs_src(self); 494 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1")); 495 hs_src.NewHandle(GetClassRoot<mirror::String>()); 496 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3")); 497 498 StackHandleScope<3> hs_dst(self); 499 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4")); 500 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5")); 501 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6")); 502 503 StackHandleScope<3> hs_expected(self); 504 hs_expected.NewHandle(hs_src.GetReference(0)); 505 hs_expected.NewHandle(hs_dst.GetReference(1)); 506 hs_expected.NewHandle(hs_dst.GetReference(2)); 507 508 RunArrayCopy(self, 509 tmp.get(), 510 true, 511 GetClassRoot<mirror::Object>(), 512 GetClassRoot<mirror::String>(), 513 hs_src, 514 0, 515 hs_dst, 516 0, 517 3, 518 hs_expected); 519 } 520 } 521 TEST_F(UnstartedRuntimeTest,IntegerParseIntTest)522 TEST_F(UnstartedRuntimeTest, IntegerParseIntTest) { 523 Thread* self = Thread::Current(); 524 ScopedObjectAccess soa(self); 525 526 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 527 528 // Test string. Should be valid, and between minimal values of LONG_MIN and LONG_MAX (for all 529 // suffixes). 530 constexpr const char* test_string = "-2147483646"; 531 constexpr int32_t test_values[] = { 532 6, 533 46, 534 646, 535 3646, 536 83646, 537 483646, 538 7483646, 539 47483646, 540 147483646, 541 2147483646, 542 -2147483646 543 }; 544 545 static_assert(arraysize(test_values) == 11U, "test_values"); 546 CHECK_EQ(strlen(test_string), 11U); 547 548 for (size_t i = 0; i <= 10; ++i) { 549 const char* test_value = &test_string[10 - i]; 550 551 StackHandleScope<1> hs_str(self); 552 Handle<mirror::String> h_str( 553 hs_str.NewHandle(mirror::String::AllocFromModifiedUtf8(self, test_value))); 554 ASSERT_NE(h_str.Get(), nullptr); 555 ASSERT_FALSE(self->IsExceptionPending()); 556 557 tmp->SetVRegReference(0, h_str.Get()); 558 559 JValue result; 560 UnstartedIntegerParseInt(self, tmp.get(), &result, 0); 561 562 ASSERT_FALSE(self->IsExceptionPending()); 563 EXPECT_EQ(result.GetI(), test_values[i]); 564 } 565 } 566 567 // Right now the same as Integer.Parse TEST_F(UnstartedRuntimeTest,LongParseLongTest)568 TEST_F(UnstartedRuntimeTest, LongParseLongTest) { 569 Thread* self = Thread::Current(); 570 ScopedObjectAccess soa(self); 571 572 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 573 574 // Test string. Should be valid, and between minimal values of LONG_MIN and LONG_MAX (for all 575 // suffixes). 576 constexpr const char* test_string = "-2147483646"; 577 constexpr int64_t test_values[] = { 578 6, 579 46, 580 646, 581 3646, 582 83646, 583 483646, 584 7483646, 585 47483646, 586 147483646, 587 2147483646, 588 -2147483646 589 }; 590 591 static_assert(arraysize(test_values) == 11U, "test_values"); 592 CHECK_EQ(strlen(test_string), 11U); 593 594 for (size_t i = 0; i <= 10; ++i) { 595 const char* test_value = &test_string[10 - i]; 596 597 StackHandleScope<1> hs_str(self); 598 Handle<mirror::String> h_str( 599 hs_str.NewHandle(mirror::String::AllocFromModifiedUtf8(self, test_value))); 600 ASSERT_NE(h_str.Get(), nullptr); 601 ASSERT_FALSE(self->IsExceptionPending()); 602 603 tmp->SetVRegReference(0, h_str.Get()); 604 605 JValue result; 606 UnstartedLongParseLong(self, tmp.get(), &result, 0); 607 608 ASSERT_FALSE(self->IsExceptionPending()); 609 EXPECT_EQ(result.GetJ(), test_values[i]); 610 } 611 } 612 TEST_F(UnstartedRuntimeTest,Ceil)613 TEST_F(UnstartedRuntimeTest, Ceil) { 614 Thread* self = Thread::Current(); 615 ScopedObjectAccess soa(self); 616 617 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 618 619 constexpr double nan = std::numeric_limits<double>::quiet_NaN(); 620 constexpr double inf = std::numeric_limits<double>::infinity(); 621 constexpr double ld1 = static_cast<double>((UINT64_C(1) << 53) - 1); 622 constexpr double ld2 = static_cast<double>(UINT64_C(1) << 55); 623 constexpr double test_pairs[][2] = { 624 { -0.0, -0.0 }, 625 { 0.0, 0.0 }, 626 { -0.5, -0.0 }, 627 { -1.0, -1.0 }, 628 { 0.5, 1.0 }, 629 { 1.0, 1.0 }, 630 { nan, nan }, 631 { inf, inf }, 632 { -inf, -inf }, 633 { ld1, ld1 }, 634 { ld2, ld2 } 635 }; 636 637 TestCeilFloor(/* ceil= */ true, self, tmp.get(), test_pairs, arraysize(test_pairs)); 638 } 639 TEST_F(UnstartedRuntimeTest,Floor)640 TEST_F(UnstartedRuntimeTest, Floor) { 641 Thread* self = Thread::Current(); 642 ScopedObjectAccess soa(self); 643 644 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 645 646 constexpr double nan = std::numeric_limits<double>::quiet_NaN(); 647 constexpr double inf = std::numeric_limits<double>::infinity(); 648 constexpr double ld1 = static_cast<double>((UINT64_C(1) << 53) - 1); 649 constexpr double ld2 = static_cast<double>(UINT64_C(1) << 55); 650 constexpr double test_pairs[][2] = { 651 { -0.0, -0.0 }, 652 { 0.0, 0.0 }, 653 { -0.5, -1.0 }, 654 { -1.0, -1.0 }, 655 { 0.5, 0.0 }, 656 { 1.0, 1.0 }, 657 { nan, nan }, 658 { inf, inf }, 659 { -inf, -inf }, 660 { ld1, ld1 }, 661 { ld2, ld2 } 662 }; 663 664 TestCeilFloor(/* ceil= */ false, self, tmp.get(), test_pairs, arraysize(test_pairs)); 665 } 666 TEST_F(UnstartedRuntimeTest,ToLowerUpper)667 TEST_F(UnstartedRuntimeTest, ToLowerUpper) { 668 Thread* self = Thread::Current(); 669 ScopedObjectAccess soa(self); 670 671 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 672 673 std::locale c_locale("C"); 674 675 // Check ASCII. 676 for (uint32_t i = 0; i < 128; ++i) { 677 bool c_upper = std::isupper(static_cast<char>(i), c_locale); 678 bool c_lower = std::islower(static_cast<char>(i), c_locale); 679 EXPECT_FALSE(c_upper && c_lower) << i; 680 681 // Check toLowerCase. 682 { 683 JValue result; 684 tmp->SetVReg(0, static_cast<int32_t>(i)); 685 UnstartedCharacterToLowerCase(self, tmp.get(), &result, 0); 686 ASSERT_FALSE(self->IsExceptionPending()); 687 uint32_t lower_result = static_cast<uint32_t>(result.GetI()); 688 if (c_lower) { 689 EXPECT_EQ(i, lower_result); 690 } else if (c_upper) { 691 EXPECT_EQ(static_cast<uint32_t>(std::tolower(static_cast<char>(i), c_locale)), 692 lower_result); 693 } else { 694 EXPECT_EQ(i, lower_result); 695 } 696 } 697 698 // Check toUpperCase. 699 { 700 JValue result2; 701 tmp->SetVReg(0, static_cast<int32_t>(i)); 702 UnstartedCharacterToUpperCase(self, tmp.get(), &result2, 0); 703 ASSERT_FALSE(self->IsExceptionPending()); 704 uint32_t upper_result = static_cast<uint32_t>(result2.GetI()); 705 if (c_upper) { 706 EXPECT_EQ(i, upper_result); 707 } else if (c_lower) { 708 EXPECT_EQ(static_cast<uint32_t>(std::toupper(static_cast<char>(i), c_locale)), 709 upper_result); 710 } else { 711 EXPECT_EQ(i, upper_result); 712 } 713 } 714 } 715 } 716 TEST_F(UnstartedRuntimeTest,Sin)717 TEST_F(UnstartedRuntimeTest, Sin) { 718 Thread* self = Thread::Current(); 719 ScopedObjectAccess soa(self); 720 721 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 722 723 // Test an important value, PI/6. That's the one we see in practice. 724 constexpr uint64_t lvalue = UINT64_C(0x3fe0c152382d7365); 725 tmp->SetVRegLong(0, static_cast<int64_t>(lvalue)); 726 727 JValue result; 728 UnstartedMathSin(self, tmp.get(), &result, 0); 729 730 const uint64_t lresult = static_cast<uint64_t>(result.GetJ()); 731 EXPECT_EQ(UINT64_C(0x3fdfffffffffffff), lresult); 732 } 733 TEST_F(UnstartedRuntimeTest,Cos)734 TEST_F(UnstartedRuntimeTest, Cos) { 735 Thread* self = Thread::Current(); 736 ScopedObjectAccess soa(self); 737 738 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 739 740 // Test an important value, PI/6. That's the one we see in practice. 741 constexpr uint64_t lvalue = UINT64_C(0x3fe0c152382d7365); 742 tmp->SetVRegLong(0, static_cast<int64_t>(lvalue)); 743 744 JValue result; 745 UnstartedMathCos(self, tmp.get(), &result, 0); 746 747 const uint64_t lresult = static_cast<uint64_t>(result.GetJ()); 748 EXPECT_EQ(UINT64_C(0x3febb67ae8584cab), lresult); 749 } 750 TEST_F(UnstartedRuntimeTest,Pow)751 TEST_F(UnstartedRuntimeTest, Pow) { 752 Thread* self = Thread::Current(); 753 ScopedObjectAccess soa(self); 754 755 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 756 757 // Test an important pair. 758 constexpr uint64_t lvalue1 = UINT64_C(0x4079000000000000); 759 constexpr uint64_t lvalue2 = UINT64_C(0xbfe6db6dc0000000); 760 761 tmp->SetVRegLong(0, static_cast<int64_t>(lvalue1)); 762 tmp->SetVRegLong(2, static_cast<int64_t>(lvalue2)); 763 764 JValue result; 765 UnstartedMathPow(self, tmp.get(), &result, 0); 766 767 const uint64_t lresult = static_cast<uint64_t>(result.GetJ()); 768 EXPECT_EQ(UINT64_C(0x3f8c5c51326aa7ee), lresult); 769 } 770 TEST_F(UnstartedRuntimeTest,IsAnonymousClass)771 TEST_F(UnstartedRuntimeTest, IsAnonymousClass) { 772 Thread* self = Thread::Current(); 773 ScopedObjectAccess soa(self); 774 775 JValue result; 776 UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0); 777 778 ObjPtr<mirror::Class> class_klass = GetClassRoot<mirror::Class>(); 779 shadow_frame->SetVRegReference(0, class_klass); 780 UnstartedClassIsAnonymousClass(self, shadow_frame.get(), &result, 0); 781 EXPECT_EQ(result.GetZ(), 0); 782 783 jobject class_loader = LoadDex("Nested"); 784 StackHandleScope<1> hs(soa.Self()); 785 Handle<mirror::ClassLoader> loader( 786 hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); 787 ObjPtr<mirror::Class> c = class_linker_->FindClass(soa.Self(), "LNested$1;", loader); 788 ASSERT_TRUE(c != nullptr); 789 shadow_frame->SetVRegReference(0, c); 790 UnstartedClassIsAnonymousClass(self, shadow_frame.get(), &result, 0); 791 EXPECT_EQ(result.GetZ(), 1); 792 } 793 TEST_F(UnstartedRuntimeTest,GetDeclaringClass)794 TEST_F(UnstartedRuntimeTest, GetDeclaringClass) { 795 Thread* self = Thread::Current(); 796 ScopedObjectAccess soa(self); 797 798 JValue result; 799 UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0); 800 801 jobject class_loader = LoadDex("Nested"); 802 StackHandleScope<4> hs(self); 803 Handle<mirror::ClassLoader> loader( 804 hs.NewHandle(soa.Decode<mirror::ClassLoader>(class_loader))); 805 806 Handle<mirror::Class> nested_klass(hs.NewHandle( 807 class_linker_->FindClass(soa.Self(), "LNested;", loader))); 808 Handle<mirror::Class> inner_klass(hs.NewHandle( 809 class_linker_->FindClass(soa.Self(), "LNested$Inner;", loader))); 810 Handle<mirror::Class> anon_klass(hs.NewHandle( 811 class_linker_->FindClass(soa.Self(), "LNested$1;", loader))); 812 813 shadow_frame->SetVRegReference(0, nested_klass.Get()); 814 UnstartedClassGetDeclaringClass(self, shadow_frame.get(), &result, 0); 815 EXPECT_EQ(result.GetL(), nullptr); 816 817 shadow_frame->SetVRegReference(0, inner_klass.Get()); 818 UnstartedClassGetDeclaringClass(self, shadow_frame.get(), &result, 0); 819 EXPECT_EQ(result.GetL(), nested_klass.Get()); 820 821 shadow_frame->SetVRegReference(0, anon_klass.Get()); 822 UnstartedClassGetDeclaringClass(self, shadow_frame.get(), &result, 0); 823 EXPECT_EQ(result.GetL(), nullptr); 824 } 825 TEST_F(UnstartedRuntimeTest,ThreadLocalGet)826 TEST_F(UnstartedRuntimeTest, ThreadLocalGet) { 827 Thread* self = Thread::Current(); 828 ScopedObjectAccess soa(self); 829 830 JValue result; 831 UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0); 832 833 StackHandleScope<1> hs(self); 834 835 // Positive test. See that We get something for float conversion. 836 { 837 Handle<mirror::Class> floating_decimal = hs.NewHandle( 838 class_linker_->FindClass(self, 839 "Ljdk/internal/math/FloatingDecimal;", 840 ScopedNullHandle<mirror::ClassLoader>())); 841 ASSERT_TRUE(floating_decimal != nullptr); 842 ASSERT_TRUE(class_linker_->EnsureInitialized(self, floating_decimal, true, true)); 843 844 ArtMethod* caller_method = floating_decimal->FindClassMethod( 845 "getBinaryToASCIIBuffer", 846 "()Ljdk/internal/math/FloatingDecimal$BinaryToASCIIBuffer;", 847 class_linker_->GetImagePointerSize()); 848 // floating_decimal->DumpClass(LOG_STREAM(ERROR), mirror::Class::kDumpClassFullDetail); 849 ASSERT_TRUE(caller_method != nullptr); 850 ASSERT_TRUE(caller_method->IsDirect()); 851 ASSERT_TRUE(caller_method->GetDeclaringClass() == floating_decimal.Get()); 852 UniqueDeoptShadowFramePtr caller_frame = CreateShadowFrame(10, caller_method, 0); 853 shadow_frame->SetLink(caller_frame.get()); 854 855 UnstartedThreadLocalGet(self, shadow_frame.get(), &result, 0); 856 EXPECT_TRUE(result.GetL() != nullptr); 857 EXPECT_FALSE(self->IsExceptionPending()); 858 859 shadow_frame->ClearLink(); 860 } 861 } 862 TEST_F(UnstartedRuntimeTest,FloatConversion)863 TEST_F(UnstartedRuntimeTest, FloatConversion) { 864 Thread* self = Thread::Current(); 865 ScopedObjectAccess soa(self); 866 867 StackHandleScope<1> hs(self); 868 Handle<mirror::Class> double_class = hs.NewHandle( 869 class_linker_->FindClass(self, 870 "Ljava/lang/Double;", 871 ScopedNullHandle<mirror::ClassLoader>())); 872 ASSERT_TRUE(double_class != nullptr); 873 ASSERT_TRUE(class_linker_->EnsureInitialized(self, double_class, true, true)); 874 875 ArtMethod* method = double_class->FindClassMethod("toString", 876 "(D)Ljava/lang/String;", 877 class_linker_->GetImagePointerSize()); 878 ASSERT_TRUE(method != nullptr); 879 ASSERT_TRUE(method->IsDirect()); 880 ASSERT_TRUE(method->GetDeclaringClass() == double_class.Get()); 881 882 // create instruction data for invoke-direct {v0, v1} of method with fake index 883 uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 }; 884 885 JValue result; 886 UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, method, 0); 887 888 shadow_frame->SetVRegDouble(0, 1.23); 889 interpreter::DoCall<false>(method, 890 self, 891 *shadow_frame, 892 Instruction::At(inst_data), 893 inst_data[0], 894 /* string_init= */ false, 895 &result); 896 ObjPtr<mirror::String> string_result = down_cast<mirror::String*>(result.GetL()); 897 ASSERT_TRUE(string_result != nullptr); 898 899 std::string mod_utf = string_result->ToModifiedUtf8(); 900 EXPECT_EQ("1.23", mod_utf); 901 } 902 TEST_F(UnstartedRuntimeTest,LogManager)903 TEST_F(UnstartedRuntimeTest, LogManager) { 904 Thread* self = Thread::Current(); 905 ScopedObjectAccess soa(self); 906 907 StackHandleScope<1> hs(self); 908 Handle<mirror::Class> log_manager_class = hs.NewHandle(class_linker_->FindClass( 909 self, "Ljava/util/logging/LogManager;", ScopedNullHandle<mirror::ClassLoader>())); 910 ASSERT_TRUE(log_manager_class.Get() != nullptr); 911 ASSERT_TRUE(class_linker_->EnsureInitialized(self, log_manager_class, true, true)); 912 } 913 914 class UnstartedClassForNameTest : public UnstartedRuntimeTest { 915 public: 916 template <typename T> RunTest(T && runner)917 void RunTest(T&& runner) { 918 Thread* self = Thread::Current(); 919 ScopedObjectAccess soa(self); 920 921 // Ensure that Class is initialized. 922 CHECK(GetClassRoot<mirror::Class>()->IsInitialized()); 923 924 // A selection of classes from different core classpath components. 925 constexpr const char* kTestCases[] = { 926 "java.net.CookieManager", // From libcore. 927 "dalvik.system.ClassExt", // From libart. 928 }; 929 930 JValue result; 931 UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0); 932 933 for (const char* name : kTestCases) { 934 ObjPtr<mirror::String> name_string = mirror::String::AllocFromModifiedUtf8(self, name); 935 CHECK(name_string != nullptr); 936 CHECK(!self->IsExceptionPending()); 937 938 runner(self, shadow_frame.get(), name_string, &result); 939 940 CHECK(!self->IsExceptionPending()) << name << " " << self->GetException()->Dump(); 941 CHECK(result.GetL() != nullptr) << name; 942 } 943 } 944 }; 945 TEST_F(UnstartedClassForNameTest,ClassForName)946 TEST_F(UnstartedClassForNameTest, ClassForName) { 947 auto runner = [](Thread* self, 948 ShadowFrame* shadow_frame, 949 ObjPtr<mirror::String> name, 950 JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { 951 shadow_frame->SetVRegReference(0, name); 952 UnstartedClassForName(self, shadow_frame, result, 0); 953 }; 954 RunTest(runner); 955 } 956 TEST_F(UnstartedClassForNameTest,ClassForNameLong)957 TEST_F(UnstartedClassForNameTest, ClassForNameLong) { 958 auto runner = [](Thread* self, 959 ShadowFrame* shadow_frame, 960 ObjPtr<mirror::String> name, 961 JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { 962 shadow_frame->SetVRegReference(0, name); 963 shadow_frame->SetVReg(1, 0); 964 shadow_frame->SetVRegReference(2, nullptr); 965 UnstartedClassForNameLong(self, shadow_frame, result, 0); 966 }; 967 RunTest(runner); 968 } 969 TEST_F(UnstartedClassForNameTest,ClassForNameLongWithClassLoader)970 TEST_F(UnstartedClassForNameTest, ClassForNameLongWithClassLoader) { 971 Thread* self = Thread::Current(); 972 ScopedObjectAccess soa(self); 973 974 StackHandleScope<1> hs(self); 975 Handle<mirror::ClassLoader> boot_cp = hs.NewHandle(GetBootClassLoader()); 976 977 auto runner = [&](Thread* th, 978 ShadowFrame* shadow_frame, 979 ObjPtr<mirror::String> name, 980 JValue* result) REQUIRES_SHARED(Locks::mutator_lock_) { 981 shadow_frame->SetVRegReference(0, name); 982 shadow_frame->SetVReg(1, 0); 983 shadow_frame->SetVRegReference(2, boot_cp.Get()); 984 UnstartedClassForNameLong(th, shadow_frame, result, 0); 985 }; 986 RunTest(runner); 987 } 988 TEST_F(UnstartedRuntimeTest,ClassGetSignatureAnnotation)989 TEST_F(UnstartedRuntimeTest, ClassGetSignatureAnnotation) { 990 Thread* self = Thread::Current(); 991 ScopedObjectAccess soa(self); 992 993 StackHandleScope<1> hs(self); 994 Handle<mirror::Class> list_class = hs.NewHandle( 995 class_linker_->FindClass(self, 996 "Ljava/util/List;", 997 ScopedNullHandle<mirror::ClassLoader>())); 998 ASSERT_TRUE(list_class.Get() != nullptr); 999 ASSERT_TRUE(class_linker_->EnsureInitialized(self, list_class, true, true)); 1000 1001 JValue result; 1002 UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0); 1003 1004 shadow_frame->SetVRegReference(0, list_class.Get()); 1005 UnstartedClassGetSignatureAnnotation(self, shadow_frame.get(), &result, 0); 1006 ASSERT_TRUE(result.GetL() != nullptr); 1007 ASSERT_FALSE(self->IsExceptionPending()); 1008 1009 ASSERT_TRUE(result.GetL()->IsObjectArray()); 1010 ObjPtr<mirror::ObjectArray<mirror::Object>> array = 1011 result.GetL()->AsObjectArray<mirror::Object>(); 1012 std::ostringstream oss; 1013 for (int32_t i = 0; i != array->GetLength(); ++i) { 1014 ObjPtr<mirror::Object> elem = array->Get(i); 1015 ASSERT_TRUE(elem != nullptr); 1016 ASSERT_TRUE(elem->IsString()); 1017 oss << elem->AsString()->ToModifiedUtf8(); 1018 } 1019 std::string output_string = oss.str(); 1020 ASSERT_EQ(output_string, 1021 "<E:Ljava/lang/Object;>Ljava/lang/Object;Ljava/util/SequencedCollection<TE;>;" 1022 "Ljava/util/Collection<TE;>;"); 1023 } 1024 TEST_F(UnstartedRuntimeTest,ConstructorNewInstance0)1025 TEST_F(UnstartedRuntimeTest, ConstructorNewInstance0) { 1026 Thread* self = Thread::Current(); 1027 ScopedObjectAccess soa(self); 1028 1029 StackHandleScope<4> hs(self); 1030 1031 // Get Throwable. 1032 Handle<mirror::Class> throw_class = hs.NewHandle(GetClassRoot<mirror::Throwable>()); 1033 ASSERT_TRUE(class_linker_->EnsureInitialized(self, throw_class, true, true)); 1034 1035 // Get an input object. 1036 Handle<mirror::String> input = hs.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "abd")); 1037 1038 // Find the constructor. 1039 PointerSize pointer_size = class_linker_->GetImagePointerSize(); 1040 ArtMethod* throw_cons = throw_class->FindConstructor("(Ljava/lang/String;)V", pointer_size); 1041 ASSERT_TRUE(throw_cons != nullptr); 1042 Handle<mirror::Constructor> cons = hs.NewHandle((pointer_size == PointerSize::k64) 1043 ? mirror::Constructor::CreateFromArtMethod<PointerSize::k64>(self, throw_cons) 1044 : mirror::Constructor::CreateFromArtMethod<PointerSize::k32>(self, throw_cons)); 1045 ASSERT_TRUE(cons != nullptr); 1046 1047 Handle<mirror::ObjectArray<mirror::Object>> args = hs.NewHandle( 1048 mirror::ObjectArray<mirror::Object>::Alloc( 1049 self, GetClassRoot<mirror::ObjectArray<mirror::Object>>(class_linker_), 1)); 1050 ASSERT_TRUE(args != nullptr); 1051 args->Set(0, input.Get()); 1052 1053 // OK, we're ready now. 1054 JValue result; 1055 UniqueDeoptShadowFramePtr shadow_frame = CreateShadowFrame(10, nullptr, 0); 1056 shadow_frame->SetVRegReference(0, cons.Get()); 1057 shadow_frame->SetVRegReference(1, args.Get()); 1058 UnstartedConstructorNewInstance0(self, shadow_frame.get(), &result, 0); 1059 1060 ASSERT_TRUE(result.GetL() != nullptr); 1061 ASSERT_FALSE(self->IsExceptionPending()); 1062 1063 // Should be a new object. 1064 ASSERT_NE(result.GetL(), input.Get()); 1065 // Should be of type Throwable. 1066 ASSERT_OBJ_PTR_EQ(GetClassRoot<mirror::Throwable>(), result.GetL()->GetClass()); 1067 // Should have the right string. 1068 ObjPtr<mirror::String> result_msg = 1069 reinterpret_cast<mirror::Throwable*>(result.GetL())->GetDetailMessage(); 1070 EXPECT_OBJ_PTR_EQ(input.Get(), result_msg); 1071 } 1072 TEST_F(UnstartedRuntimeTest,IdentityHashCode)1073 TEST_F(UnstartedRuntimeTest, IdentityHashCode) { 1074 Thread* self = Thread::Current(); 1075 ScopedObjectAccess soa(self); 1076 UniqueDeoptShadowFramePtr tmp = CreateShadowFrame(10, nullptr, 0); 1077 1078 JValue result; 1079 UnstartedSystemIdentityHashCode(self, tmp.get(), &result, 0); 1080 1081 EXPECT_EQ(0, result.GetI()); 1082 ASSERT_FALSE(self->IsExceptionPending()); 1083 1084 ObjPtr<mirror::String> str = mirror::String::AllocFromModifiedUtf8(self, "abd"); 1085 tmp->SetVRegReference(0, str); 1086 UnstartedSystemIdentityHashCode(self, tmp.get(), &result, 0); 1087 EXPECT_NE(0, result.GetI()); 1088 EXPECT_EQ(str->IdentityHashCode(), result.GetI()); 1089 ASSERT_FALSE(self->IsExceptionPending()); 1090 } 1091 1092 } // namespace interpreter 1093 } // namespace art 1094