unstarted_runtime_test.cc revision 85a098af5fc8d2dd0e39d61c9f93fc6257d631c5
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 "class_linker.h" 20#include "common_runtime_test.h" 21#include "dex_instruction.h" 22#include "handle.h" 23#include "handle_scope-inl.h" 24#include "interpreter/interpreter_common.h" 25#include "mirror/class_loader.h" 26#include "mirror/string-inl.h" 27#include "runtime.h" 28#include "scoped_thread_state_change.h" 29#include "thread.h" 30 31namespace art { 32namespace interpreter { 33 34class UnstartedRuntimeTest : public CommonRuntimeTest { 35 protected: 36 // Re-expose all UnstartedRuntime implementations so we don't need to declare a million 37 // test friends. 38 39 // Methods that intercept available libcore implementations. 40#define UNSTARTED_DIRECT(Name, SigIgnored) \ 41 static void Unstarted ## Name(Thread* self, \ 42 ShadowFrame* shadow_frame, \ 43 JValue* result, \ 44 size_t arg_offset) \ 45 SHARED_REQUIRES(Locks::mutator_lock_) { \ 46 interpreter::UnstartedRuntime::Unstarted ## Name(self, shadow_frame, result, arg_offset); \ 47 } 48#include "unstarted_runtime_list.h" 49 UNSTARTED_RUNTIME_DIRECT_LIST(UNSTARTED_DIRECT) 50#undef UNSTARTED_RUNTIME_DIRECT_LIST 51#undef UNSTARTED_RUNTIME_JNI_LIST 52#undef UNSTARTED_DIRECT 53 54 // Methods that are native. 55#define UNSTARTED_JNI(Name, SigIgnored) \ 56 static void UnstartedJNI ## Name(Thread* self, \ 57 ArtMethod* method, \ 58 mirror::Object* receiver, \ 59 uint32_t* args, \ 60 JValue* result) \ 61 SHARED_REQUIRES(Locks::mutator_lock_) { \ 62 interpreter::UnstartedRuntime::UnstartedJNI ## Name(self, method, receiver, args, result); \ 63 } 64#include "unstarted_runtime_list.h" 65 UNSTARTED_RUNTIME_JNI_LIST(UNSTARTED_JNI) 66#undef UNSTARTED_RUNTIME_DIRECT_LIST 67#undef UNSTARTED_RUNTIME_JNI_LIST 68#undef UNSTARTED_JNI 69 70 // Helpers for ArrayCopy. 71 // 72 // Note: as we have to use handles, we use StackHandleScope to transfer data. Hardcode a size 73 // of three everywhere. That is enough to test all cases. 74 75 static mirror::ObjectArray<mirror::Object>* CreateObjectArray( 76 Thread* self, 77 mirror::Class* component_type, 78 const StackHandleScope<3>& data) 79 SHARED_REQUIRES(Locks::mutator_lock_) { 80 Runtime* runtime = Runtime::Current(); 81 mirror::Class* array_type = runtime->GetClassLinker()->FindArrayClass(self, &component_type); 82 CHECK(array_type != nullptr); 83 mirror::ObjectArray<mirror::Object>* result = 84 mirror::ObjectArray<mirror::Object>::Alloc(self, array_type, 3); 85 CHECK(result != nullptr); 86 for (size_t i = 0; i < 3; ++i) { 87 result->Set(static_cast<int32_t>(i), data.GetReference(i)); 88 CHECK(!self->IsExceptionPending()); 89 } 90 return result; 91 } 92 93 static void CheckObjectArray(mirror::ObjectArray<mirror::Object>* array, 94 const StackHandleScope<3>& data) 95 SHARED_REQUIRES(Locks::mutator_lock_) { 96 CHECK_EQ(array->GetLength(), 3); 97 CHECK_EQ(data.NumberOfReferences(), 3U); 98 for (size_t i = 0; i < 3; ++i) { 99 EXPECT_EQ(data.GetReference(i), array->Get(static_cast<int32_t>(i))) << i; 100 } 101 } 102 103 void RunArrayCopy(Thread* self, 104 ShadowFrame* tmp, 105 bool expect_exception, 106 mirror::ObjectArray<mirror::Object>* src, 107 int32_t src_pos, 108 mirror::ObjectArray<mirror::Object>* dst, 109 int32_t dst_pos, 110 int32_t length) 111 SHARED_REQUIRES(Locks::mutator_lock_) { 112 JValue result; 113 tmp->SetVRegReference(0, src); 114 tmp->SetVReg(1, src_pos); 115 tmp->SetVRegReference(2, dst); 116 tmp->SetVReg(3, dst_pos); 117 tmp->SetVReg(4, length); 118 UnstartedSystemArraycopy(self, tmp, &result, 0); 119 bool exception_pending = self->IsExceptionPending(); 120 EXPECT_EQ(exception_pending, expect_exception); 121 if (exception_pending) { 122 self->ClearException(); 123 } 124 } 125 126 void RunArrayCopy(Thread* self, 127 ShadowFrame* tmp, 128 bool expect_exception, 129 mirror::Class* src_component_class, 130 mirror::Class* dst_component_class, 131 const StackHandleScope<3>& src_data, 132 int32_t src_pos, 133 const StackHandleScope<3>& dst_data, 134 int32_t dst_pos, 135 int32_t length, 136 const StackHandleScope<3>& expected_result) 137 SHARED_REQUIRES(Locks::mutator_lock_) { 138 StackHandleScope<3> hs_misc(self); 139 Handle<mirror::Class> dst_component_handle(hs_misc.NewHandle(dst_component_class)); 140 141 Handle<mirror::ObjectArray<mirror::Object>> src_handle( 142 hs_misc.NewHandle(CreateObjectArray(self, src_component_class, src_data))); 143 144 Handle<mirror::ObjectArray<mirror::Object>> dst_handle( 145 hs_misc.NewHandle(CreateObjectArray(self, dst_component_handle.Get(), dst_data))); 146 147 RunArrayCopy(self, 148 tmp, 149 expect_exception, 150 src_handle.Get(), 151 src_pos, 152 dst_handle.Get(), 153 dst_pos, 154 length); 155 CheckObjectArray(dst_handle.Get(), expected_result); 156 } 157}; 158 159TEST_F(UnstartedRuntimeTest, MemoryPeekByte) { 160 Thread* self = Thread::Current(); 161 162 ScopedObjectAccess soa(self); 163 constexpr const uint8_t base_array[] = "abcdefghijklmnop"; 164 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t); 165 const uint8_t* base_ptr = base_array; 166 167 JValue result; 168 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); 169 170 for (int32_t i = 0; i < kBaseLen; ++i) { 171 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i))); 172 173 UnstartedMemoryPeekByte(self, tmp, &result, 0); 174 175 EXPECT_EQ(result.GetB(), static_cast<int8_t>(base_array[i])); 176 } 177 178 ShadowFrame::DeleteDeoptimizedFrame(tmp); 179} 180 181TEST_F(UnstartedRuntimeTest, MemoryPeekShort) { 182 Thread* self = Thread::Current(); 183 184 ScopedObjectAccess soa(self); 185 constexpr const uint8_t base_array[] = "abcdefghijklmnop"; 186 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t); 187 const uint8_t* base_ptr = base_array; 188 189 JValue result; 190 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); 191 192 int32_t adjusted_length = kBaseLen - sizeof(int16_t); 193 for (int32_t i = 0; i < adjusted_length; ++i) { 194 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i))); 195 196 UnstartedMemoryPeekShort(self, tmp, &result, 0); 197 198 typedef int16_t unaligned_short __attribute__ ((aligned (1))); 199 const unaligned_short* short_ptr = reinterpret_cast<const unaligned_short*>(base_ptr + i); 200 EXPECT_EQ(result.GetS(), *short_ptr); 201 } 202 203 ShadowFrame::DeleteDeoptimizedFrame(tmp); 204} 205 206TEST_F(UnstartedRuntimeTest, MemoryPeekInt) { 207 Thread* self = Thread::Current(); 208 209 ScopedObjectAccess soa(self); 210 constexpr const uint8_t base_array[] = "abcdefghijklmnop"; 211 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t); 212 const uint8_t* base_ptr = base_array; 213 214 JValue result; 215 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); 216 217 int32_t adjusted_length = kBaseLen - sizeof(int32_t); 218 for (int32_t i = 0; i < adjusted_length; ++i) { 219 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i))); 220 221 UnstartedMemoryPeekInt(self, tmp, &result, 0); 222 223 typedef int32_t unaligned_int __attribute__ ((aligned (1))); 224 const unaligned_int* int_ptr = reinterpret_cast<const unaligned_int*>(base_ptr + i); 225 EXPECT_EQ(result.GetI(), *int_ptr); 226 } 227 228 ShadowFrame::DeleteDeoptimizedFrame(tmp); 229} 230 231TEST_F(UnstartedRuntimeTest, MemoryPeekLong) { 232 Thread* self = Thread::Current(); 233 234 ScopedObjectAccess soa(self); 235 constexpr const uint8_t base_array[] = "abcdefghijklmnop"; 236 constexpr int32_t kBaseLen = sizeof(base_array) / sizeof(uint8_t); 237 const uint8_t* base_ptr = base_array; 238 239 JValue result; 240 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); 241 242 int32_t adjusted_length = kBaseLen - sizeof(int64_t); 243 for (int32_t i = 0; i < adjusted_length; ++i) { 244 tmp->SetVRegLong(0, static_cast<int64_t>(reinterpret_cast<intptr_t>(base_ptr + i))); 245 246 UnstartedMemoryPeekLong(self, tmp, &result, 0); 247 248 typedef int64_t unaligned_long __attribute__ ((aligned (1))); 249 const unaligned_long* long_ptr = reinterpret_cast<const unaligned_long*>(base_ptr + i); 250 EXPECT_EQ(result.GetJ(), *long_ptr); 251 } 252 253 ShadowFrame::DeleteDeoptimizedFrame(tmp); 254} 255 256TEST_F(UnstartedRuntimeTest, StringGetCharsNoCheck) { 257 Thread* self = Thread::Current(); 258 259 ScopedObjectAccess soa(self); 260 StackHandleScope<2> hs(self); 261 // TODO: Actual UTF. 262 constexpr const char base_string[] = "abcdefghijklmnop"; 263 Handle<mirror::String> h_test_string(hs.NewHandle( 264 mirror::String::AllocFromModifiedUtf8(self, base_string))); 265 constexpr int32_t kBaseLen = sizeof(base_string) / sizeof(char) - 1; 266 Handle<mirror::CharArray> h_char_array(hs.NewHandle( 267 mirror::CharArray::Alloc(self, kBaseLen))); 268 // A buffer so we can make sure we only modify the elements targetted. 269 uint16_t buf[kBaseLen]; 270 271 JValue result; 272 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); 273 274 for (int32_t start_index = 0; start_index < kBaseLen; ++start_index) { 275 for (int32_t count = 0; count <= kBaseLen; ++count) { 276 for (int32_t trg_offset = 0; trg_offset < kBaseLen; ++trg_offset) { 277 // Only do it when in bounds. 278 if (start_index + count <= kBaseLen && trg_offset + count <= kBaseLen) { 279 tmp->SetVRegReference(0, h_test_string.Get()); 280 tmp->SetVReg(1, start_index); 281 tmp->SetVReg(2, count); 282 tmp->SetVRegReference(3, h_char_array.Get()); 283 tmp->SetVReg(3, trg_offset); 284 285 // Copy the char_array into buf. 286 memcpy(buf, h_char_array->GetData(), kBaseLen * sizeof(uint16_t)); 287 288 UnstartedStringCharAt(self, tmp, &result, 0); 289 290 uint16_t* data = h_char_array->GetData(); 291 292 bool success = true; 293 294 // First segment should be unchanged. 295 for (int32_t i = 0; i < trg_offset; ++i) { 296 success = success && (data[i] == buf[i]); 297 } 298 // Second segment should be a copy. 299 for (int32_t i = trg_offset; i < trg_offset + count; ++i) { 300 success = success && (data[i] == buf[i - trg_offset + start_index]); 301 } 302 // Third segment should be unchanged. 303 for (int32_t i = trg_offset + count; i < kBaseLen; ++i) { 304 success = success && (data[i] == buf[i]); 305 } 306 307 EXPECT_TRUE(success); 308 } 309 } 310 } 311 } 312 313 ShadowFrame::DeleteDeoptimizedFrame(tmp); 314} 315 316TEST_F(UnstartedRuntimeTest, StringCharAt) { 317 Thread* self = Thread::Current(); 318 319 ScopedObjectAccess soa(self); 320 // TODO: Actual UTF. 321 constexpr const char* base_string = "abcdefghijklmnop"; 322 int32_t base_len = static_cast<int32_t>(strlen(base_string)); 323 mirror::String* test_string = mirror::String::AllocFromModifiedUtf8(self, base_string); 324 325 JValue result; 326 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); 327 328 for (int32_t i = 0; i < base_len; ++i) { 329 tmp->SetVRegReference(0, test_string); 330 tmp->SetVReg(1, i); 331 332 UnstartedStringCharAt(self, tmp, &result, 0); 333 334 EXPECT_EQ(result.GetI(), base_string[i]); 335 } 336 337 ShadowFrame::DeleteDeoptimizedFrame(tmp); 338} 339 340TEST_F(UnstartedRuntimeTest, StringInit) { 341 Thread* self = Thread::Current(); 342 ScopedObjectAccess soa(self); 343 mirror::Class* klass = mirror::String::GetJavaLangString(); 344 ArtMethod* method = klass->FindDeclaredDirectMethod("<init>", "(Ljava/lang/String;)V", 345 sizeof(void*)); 346 347 // create instruction data for invoke-direct {v0, v1} of method with fake index 348 uint16_t inst_data[3] = { 0x2070, 0x0000, 0x0010 }; 349 const Instruction* inst = Instruction::At(inst_data); 350 351 JValue result; 352 ShadowFrame* shadow_frame = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, method, 0); 353 const char* base_string = "hello_world"; 354 mirror::String* string_arg = mirror::String::AllocFromModifiedUtf8(self, base_string); 355 mirror::String* reference_empty_string = mirror::String::AllocFromModifiedUtf8(self, ""); 356 shadow_frame->SetVRegReference(0, reference_empty_string); 357 shadow_frame->SetVRegReference(1, string_arg); 358 359 interpreter::DoCall<false, false>(method, self, *shadow_frame, inst, inst_data[0], &result); 360 mirror::String* string_result = reinterpret_cast<mirror::String*>(result.GetL()); 361 EXPECT_EQ(string_arg->GetLength(), string_result->GetLength()); 362 EXPECT_EQ(memcmp(string_arg->GetValue(), string_result->GetValue(), 363 string_arg->GetLength() * sizeof(uint16_t)), 0); 364 365 ShadowFrame::DeleteDeoptimizedFrame(shadow_frame); 366} 367 368// Tests the exceptions that should be checked before modifying the destination. 369// (Doesn't check the object vs primitive case ATM.) 370TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTestExceptions) { 371 Thread* self = Thread::Current(); 372 ScopedObjectAccess soa(self); 373 JValue result; 374 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); 375 376 // Note: all tests are not GC safe. Assume there's no GC running here with the few objects we 377 // allocate. 378 StackHandleScope<2> hs_misc(self); 379 Handle<mirror::Class> object_class( 380 hs_misc.NewHandle(mirror::Class::GetJavaLangClass()->GetSuperClass())); 381 382 StackHandleScope<3> hs_data(self); 383 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1")); 384 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2")); 385 hs_data.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3")); 386 387 Handle<mirror::ObjectArray<mirror::Object>> array( 388 hs_misc.NewHandle(CreateObjectArray(self, object_class.Get(), hs_data))); 389 390 RunArrayCopy(self, tmp, true, array.Get(), -1, array.Get(), 0, 0); 391 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), -1, 0); 392 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 0, -1); 393 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 0, 4); 394 RunArrayCopy(self, tmp, true, array.Get(), 0, array.Get(), 1, 3); 395 RunArrayCopy(self, tmp, true, array.Get(), 1, array.Get(), 0, 3); 396 397 mirror::ObjectArray<mirror::Object>* class_as_array = 398 reinterpret_cast<mirror::ObjectArray<mirror::Object>*>(object_class.Get()); 399 RunArrayCopy(self, tmp, true, class_as_array, 0, array.Get(), 0, 0); 400 RunArrayCopy(self, tmp, true, array.Get(), 0, class_as_array, 0, 0); 401 402 ShadowFrame::DeleteDeoptimizedFrame(tmp); 403} 404 405TEST_F(UnstartedRuntimeTest, SystemArrayCopyObjectArrayTest) { 406 Thread* self = Thread::Current(); 407 ScopedObjectAccess soa(self); 408 JValue result; 409 ShadowFrame* tmp = ShadowFrame::CreateDeoptimizedFrame(10, nullptr, nullptr, 0); 410 411 StackHandleScope<1> hs_object(self); 412 Handle<mirror::Class> object_class( 413 hs_object.NewHandle(mirror::Class::GetJavaLangClass()->GetSuperClass())); 414 415 // Simple test: 416 // [1,2,3]{1 @ 2} into [4,5,6] = [4,2,6] 417 { 418 StackHandleScope<3> hs_src(self); 419 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1")); 420 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2")); 421 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3")); 422 423 StackHandleScope<3> hs_dst(self); 424 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4")); 425 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5")); 426 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6")); 427 428 StackHandleScope<3> hs_expected(self); 429 hs_expected.NewHandle(hs_dst.GetReference(0)); 430 hs_expected.NewHandle(hs_dst.GetReference(1)); 431 hs_expected.NewHandle(hs_src.GetReference(1)); 432 433 RunArrayCopy(self, 434 tmp, 435 false, 436 object_class.Get(), 437 object_class.Get(), 438 hs_src, 439 1, 440 hs_dst, 441 2, 442 1, 443 hs_expected); 444 } 445 446 // Simple test: 447 // [1,2,3]{1 @ 1} into [4,5,6] = [4,2,6] (with dst String[]) 448 { 449 StackHandleScope<3> hs_src(self); 450 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1")); 451 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "2")); 452 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3")); 453 454 StackHandleScope<3> hs_dst(self); 455 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4")); 456 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5")); 457 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6")); 458 459 StackHandleScope<3> hs_expected(self); 460 hs_expected.NewHandle(hs_dst.GetReference(0)); 461 hs_expected.NewHandle(hs_src.GetReference(1)); 462 hs_expected.NewHandle(hs_dst.GetReference(2)); 463 464 RunArrayCopy(self, 465 tmp, 466 false, 467 object_class.Get(), 468 mirror::String::GetJavaLangString(), 469 hs_src, 470 1, 471 hs_dst, 472 1, 473 1, 474 hs_expected); 475 } 476 477 // Simple test: 478 // [1,*,3] into [4,5,6] = [1,5,6] + exc 479 { 480 StackHandleScope<3> hs_src(self); 481 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "1")); 482 hs_src.NewHandle(mirror::String::GetJavaLangString()); 483 hs_src.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "3")); 484 485 StackHandleScope<3> hs_dst(self); 486 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "4")); 487 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "5")); 488 hs_dst.NewHandle(mirror::String::AllocFromModifiedUtf8(self, "6")); 489 490 StackHandleScope<3> hs_expected(self); 491 hs_expected.NewHandle(hs_src.GetReference(0)); 492 hs_expected.NewHandle(hs_dst.GetReference(1)); 493 hs_expected.NewHandle(hs_dst.GetReference(2)); 494 495 RunArrayCopy(self, 496 tmp, 497 true, 498 object_class.Get(), 499 mirror::String::GetJavaLangString(), 500 hs_src, 501 0, 502 hs_dst, 503 0, 504 3, 505 hs_expected); 506 } 507 508 ShadowFrame::DeleteDeoptimizedFrame(tmp); 509} 510 511} // namespace interpreter 512} // namespace art 513