| Elliott Hughes | 2faa5f1 | 2012-01-30 14:42:07 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2011 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 | */ |
| Carl Shapiro | 894d0fa | 2011-06-30 14:48:49 -0700 | [diff] [blame] | 16 | |
| Elliott Hughes | 90a3369 | 2011-08-30 13:27:07 -0700 | [diff] [blame] | 17 | #include "object.h" |
| 18 | |
| 19 | #include <stdint.h> |
| 20 | #include <stdio.h> |
| Ian Rogers | 700a402 | 2014-05-19 16:49:03 -0700 | [diff] [blame] | 21 | #include <memory> |
| Elliott Hughes | 90a3369 | 2011-08-30 13:27:07 -0700 | [diff] [blame] | 22 | |
| Andreas Gampe | 8e0f043 | 2018-10-24 13:38:03 -0700 | [diff] [blame] | 23 | #include "array-alloc-inl.h" |
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 24 | #include "array-inl.h" |
| Brian Carlstrom | ea46f95 | 2013-07-30 01:26:50 -0700 | [diff] [blame] | 25 | #include "art_field-inl.h" |
| Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 26 | #include "art_method-inl.h" |
| Ian Rogers | 1f53934 | 2012-10-03 21:09:42 -0700 | [diff] [blame] | 27 | #include "asm_support.h" |
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 28 | #include "base/enums.h" |
| Andreas Gampe | 70f5fd0 | 2018-10-24 19:58:37 -0700 | [diff] [blame] | 29 | #include "class-alloc-inl.h" |
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 30 | #include "class-inl.h" |
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 31 | #include "class_linker-inl.h" |
| Andreas Gampe | 8cf9cb3 | 2017-07-19 09:28:38 -0700 | [diff] [blame] | 32 | #include "class_linker.h" |
| Vladimir Marko | 5868ada | 2020-05-12 11:50:34 +0100 | [diff] [blame] | 33 | #include "class_root-inl.h" |
| Brian Carlstrom | a1ce1fe | 2014-02-24 23:23:58 -0800 | [diff] [blame] | 34 | #include "common_runtime_test.h" |
| David Sehr | 9e734c7 | 2018-01-04 17:56:19 -0800 | [diff] [blame] | 35 | #include "dex/dex_file.h" |
| Mingyao Yang | 98d1cc8 | 2014-05-15 17:02:16 -0700 | [diff] [blame] | 36 | #include "entrypoints/entrypoint_utils-inl.h" |
| Ian Rogers | 1d54e73 | 2013-05-02 21:10:01 -0700 | [diff] [blame] | 37 | #include "gc/accounting/card_table-inl.h" |
| 38 | #include "gc/heap.h" |
| Ian Rogers | 1ff3c98 | 2014-08-12 02:30:58 -0700 | [diff] [blame] | 39 | #include "handle_scope-inl.h" |
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 40 | #include "iftable-inl.h" |
| Mathieu Chartier | 3f7f03c | 2016-09-26 11:39:52 -0700 | [diff] [blame] | 41 | #include "obj_ptr.h" |
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 42 | #include "object-inl.h" |
| Andreas Gampe | 52ecb65 | 2018-10-24 15:18:21 -0700 | [diff] [blame] | 43 | #include "object_array-alloc-inl.h" |
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 44 | #include "object_array-inl.h" |
| Mathieu Chartier | 0795f23 | 2016-09-27 18:43:30 -0700 | [diff] [blame] | 45 | #include "scoped_thread_state_change-inl.h" |
| Ian Rogers | b0fa5dc | 2014-04-28 16:47:08 -0700 | [diff] [blame] | 46 | #include "string-inl.h" |
| Carl Shapiro | 894d0fa | 2011-06-30 14:48:49 -0700 | [diff] [blame] | 47 | |
| 48 | namespace art { |
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 49 | namespace mirror { |
| Carl Shapiro | 894d0fa | 2011-06-30 14:48:49 -0700 | [diff] [blame] | 50 | |
| Brian Carlstrom | a1ce1fe | 2014-02-24 23:23:58 -0800 | [diff] [blame] | 51 | class ObjectTest : public CommonRuntimeTest { |
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 52 | protected: |
| Brian Carlstrom | 0a02d12 | 2013-09-06 15:42:40 -0700 | [diff] [blame] | 53 | void AssertString(int32_t expected_utf16_length, |
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 54 | const char* utf8_in, |
| 55 | const char* utf16_expected_le, |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 56 | int32_t expected_hash) |
| Andreas Gampe | bdf7f1c | 2016-08-30 16:38:47 -0700 | [diff] [blame] | 57 | REQUIRES_SHARED(Locks::mutator_lock_) { |
| Ian Rogers | 700a402 | 2014-05-19 16:49:03 -0700 | [diff] [blame] | 58 | std::unique_ptr<uint16_t[]> utf16_expected(new uint16_t[expected_utf16_length]); |
| Brian Carlstrom | 0a02d12 | 2013-09-06 15:42:40 -0700 | [diff] [blame] | 59 | for (int32_t i = 0; i < expected_utf16_length; i++) { |
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 60 | uint16_t ch = (((utf16_expected_le[i*2 + 0] & 0xff) << 8) | |
| 61 | ((utf16_expected_le[i*2 + 1] & 0xff) << 0)); |
| 62 | utf16_expected[i] = ch; |
| 63 | } |
| 64 | |
| Ian Rogers | 50b35e2 | 2012-10-04 10:09:15 -0700 | [diff] [blame] | 65 | Thread* self = Thread::Current(); |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 66 | StackHandleScope<1> hs(self); |
| 67 | Handle<String> string( |
| 68 | hs.NewHandle(String::AllocFromModifiedUtf8(self, expected_utf16_length, utf8_in))); |
| Brian Carlstrom | 0a02d12 | 2013-09-06 15:42:40 -0700 | [diff] [blame] | 69 | ASSERT_EQ(expected_utf16_length, string->GetLength()); |
| jessicahandojo | 3aaa37b | 2016-07-29 14:46:37 -0700 | [diff] [blame] | 70 | ASSERT_EQ(string->IsValueNull(), false); |
| Brian Carlstrom | 0a02d12 | 2013-09-06 15:42:40 -0700 | [diff] [blame] | 71 | // strlen is necessary because the 1-character string "\x00\x00" is interpreted as "" |
| 72 | ASSERT_TRUE(string->Equals(utf8_in) || (expected_utf16_length == 1 && strlen(utf8_in) == 0)); |
| Brian Carlstrom | 0a02d12 | 2013-09-06 15:42:40 -0700 | [diff] [blame] | 73 | for (int32_t i = 0; i < expected_utf16_length; i++) { |
| Jeff Hao | 848f70a | 2014-01-15 13:49:50 -0800 | [diff] [blame] | 74 | EXPECT_EQ(utf16_expected[i], string->CharAt(i)); |
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 75 | } |
| Ian Rogers | 0cfe1fb | 2011-08-26 03:29:44 -0700 | [diff] [blame] | 76 | EXPECT_EQ(expected_hash, string->GetHashCode()); |
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 77 | } |
| Andreas Gampe | c6ea7d0 | 2017-02-01 16:46:28 -0800 | [diff] [blame] | 78 | |
| 79 | template <class T> |
| Vladimir Marko | bcf1752 | 2018-06-01 13:14:32 +0100 | [diff] [blame] | 80 | ObjPtr<mirror::ObjectArray<T>> AllocObjectArray(Thread* self, size_t length) |
| Andreas Gampe | c6ea7d0 | 2017-02-01 16:46:28 -0800 | [diff] [blame] | 81 | REQUIRES_SHARED(Locks::mutator_lock_) { |
| 82 | return mirror::ObjectArray<T>::Alloc( |
| Vladimir Marko | b4eb1b1 | 2018-05-24 11:09:38 +0100 | [diff] [blame] | 83 | self, GetClassRoot(ClassRoot::kObjectArrayClass, class_linker_), length); |
| Andreas Gampe | c6ea7d0 | 2017-02-01 16:46:28 -0800 | [diff] [blame] | 84 | } |
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 85 | }; |
| Brian Carlstrom | a331b3c | 2011-07-18 17:47:56 -0700 | [diff] [blame] | 86 | |
| Ian Rogers | 68d8b42 | 2014-07-17 11:09:10 -0700 | [diff] [blame] | 87 | // Keep constants in sync. |
| 88 | TEST_F(ObjectTest, Constants) { |
| Ian Rogers | cdc1aaf | 2014-10-09 13:21:38 -0700 | [diff] [blame] | 89 | EXPECT_EQ(kObjectReferenceSize, sizeof(HeapReference<Object>)); |
| 90 | EXPECT_EQ(kObjectHeaderSize, sizeof(Object)); |
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 91 | EXPECT_EQ(ART_METHOD_QUICK_CODE_OFFSET_32, |
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 92 | ArtMethod::EntryPointFromQuickCompiledCodeOffset(PointerSize::k32). |
| 93 | Int32Value()); |
| Mathieu Chartier | e401d14 | 2015-04-22 13:56:20 -0700 | [diff] [blame] | 94 | EXPECT_EQ(ART_METHOD_QUICK_CODE_OFFSET_64, |
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 95 | ArtMethod::EntryPointFromQuickCompiledCodeOffset(PointerSize::k64). |
| 96 | Int32Value()); |
| Ian Rogers | 68d8b42 | 2014-07-17 11:09:10 -0700 | [diff] [blame] | 97 | } |
| 98 | |
| Brian Carlstrom | a331b3c | 2011-07-18 17:47:56 -0700 | [diff] [blame] | 99 | TEST_F(ObjectTest, IsInSamePackage) { |
| Carl Shapiro | 894d0fa | 2011-06-30 14:48:49 -0700 | [diff] [blame] | 100 | // Matches |
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 101 | EXPECT_TRUE(Class::IsInSamePackage("Ljava/lang/Object;", "Ljava/lang/Class;")); |
| 102 | EXPECT_TRUE(Class::IsInSamePackage("LFoo;", "LBar;")); |
| Carl Shapiro | 894d0fa | 2011-06-30 14:48:49 -0700 | [diff] [blame] | 103 | |
| 104 | // Mismatches |
| Ian Rogers | 6d4d9fc | 2011-11-30 16:24:48 -0800 | [diff] [blame] | 105 | EXPECT_FALSE(Class::IsInSamePackage("Ljava/lang/Object;", "Ljava/io/File;")); |
| 106 | EXPECT_FALSE(Class::IsInSamePackage("Ljava/lang/Object;", "Ljava/lang/reflect/Method;")); |
| Carl Shapiro | 894d0fa | 2011-06-30 14:48:49 -0700 | [diff] [blame] | 107 | } |
| 108 | |
| Elliott Hughes | 081be7f | 2011-09-18 16:50:26 -0700 | [diff] [blame] | 109 | TEST_F(ObjectTest, Clone) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 110 | ScopedObjectAccess soa(Thread::Current()); |
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 111 | StackHandleScope<2> hs(soa.Self()); |
| Andreas Gampe | c6ea7d0 | 2017-02-01 16:46:28 -0800 | [diff] [blame] | 112 | Handle<ObjectArray<Object>> a1(hs.NewHandle(AllocObjectArray<Object>(soa.Self(), 256))); |
| Elliott Hughes | 081be7f | 2011-09-18 16:50:26 -0700 | [diff] [blame] | 113 | size_t s1 = a1->SizeOf(); |
| Vladimir Marko | 3068d58 | 2019-05-28 16:39:29 +0100 | [diff] [blame] | 114 | ObjPtr<Object> clone = Object::Clone(a1, soa.Self()); |
| Elliott Hughes | 081be7f | 2011-09-18 16:50:26 -0700 | [diff] [blame] | 115 | EXPECT_EQ(s1, clone->SizeOf()); |
| 116 | EXPECT_TRUE(clone->GetClass() == a1->GetClass()); |
| 117 | } |
| 118 | |
| Brian Carlstrom | 578bbdc | 2011-07-21 14:07:47 -0700 | [diff] [blame] | 119 | TEST_F(ObjectTest, AllocObjectArray) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 120 | ScopedObjectAccess soa(Thread::Current()); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 121 | StackHandleScope<3> hs(soa.Self()); |
| Andreas Gampe | c6ea7d0 | 2017-02-01 16:46:28 -0800 | [diff] [blame] | 122 | Handle<ObjectArray<Object>> oa(hs.NewHandle(AllocObjectArray<Object>(soa.Self(), 2))); |
| Elliott Hughes | d8ddfd5 | 2011-08-15 14:32:53 -0700 | [diff] [blame] | 123 | EXPECT_EQ(2, oa->GetLength()); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 124 | EXPECT_TRUE(oa->Get(0) == nullptr); |
| 125 | EXPECT_TRUE(oa->Get(1) == nullptr); |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 126 | oa->Set<false>(0, oa.Get()); |
| 127 | EXPECT_TRUE(oa->Get(0) == oa.Get()); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 128 | EXPECT_TRUE(oa->Get(1) == nullptr); |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 129 | oa->Set<false>(1, oa.Get()); |
| 130 | EXPECT_TRUE(oa->Get(0) == oa.Get()); |
| 131 | EXPECT_TRUE(oa->Get(1) == oa.Get()); |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 132 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 133 | Handle<Class> aioobe = hs.NewHandle( |
| 134 | class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;")); |
| Elliott Hughes | 710a0cb | 2011-08-16 14:32:37 -0700 | [diff] [blame] | 135 | |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 136 | EXPECT_TRUE(oa->Get(-1) == nullptr); |
| Ian Rogers | 1f53934 | 2012-10-03 21:09:42 -0700 | [diff] [blame] | 137 | EXPECT_TRUE(soa.Self()->IsExceptionPending()); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 138 | EXPECT_OBJ_PTR_EQ(aioobe.Get(), soa.Self()->GetException()->GetClass()); |
| Ian Rogers | 1f53934 | 2012-10-03 21:09:42 -0700 | [diff] [blame] | 139 | soa.Self()->ClearException(); |
| Elliott Hughes | 710a0cb | 2011-08-16 14:32:37 -0700 | [diff] [blame] | 140 | |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 141 | EXPECT_TRUE(oa->Get(2) == nullptr); |
| Ian Rogers | 1f53934 | 2012-10-03 21:09:42 -0700 | [diff] [blame] | 142 | EXPECT_TRUE(soa.Self()->IsExceptionPending()); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 143 | EXPECT_OBJ_PTR_EQ(aioobe.Get(), soa.Self()->GetException()->GetClass()); |
| Ian Rogers | 1f53934 | 2012-10-03 21:09:42 -0700 | [diff] [blame] | 144 | soa.Self()->ClearException(); |
| Elliott Hughes | 710a0cb | 2011-08-16 14:32:37 -0700 | [diff] [blame] | 145 | |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 146 | ASSERT_TRUE(oa->GetClass() != nullptr); |
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 147 | Handle<mirror::Class> klass(hs.NewHandle(oa->GetClass())); |
| 148 | ASSERT_EQ(2U, klass->NumDirectInterfaces()); |
| Mathieu Chartier | 28bd2e4 | 2016-10-04 13:54:57 -0700 | [diff] [blame] | 149 | EXPECT_OBJ_PTR_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Cloneable;"), |
| Vladimir Marko | 19a4d37 | 2016-12-08 14:41:46 +0000 | [diff] [blame] | 150 | mirror::Class::GetDirectInterface(soa.Self(), klass.Get(), 0)); |
| Mathieu Chartier | 28bd2e4 | 2016-10-04 13:54:57 -0700 | [diff] [blame] | 151 | EXPECT_OBJ_PTR_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;"), |
| Vladimir Marko | 19a4d37 | 2016-12-08 14:41:46 +0000 | [diff] [blame] | 152 | mirror::Class::GetDirectInterface(soa.Self(), klass.Get(), 1)); |
| Carl Shapiro | 0e5d75d | 2011-07-06 18:28:37 -0700 | [diff] [blame] | 153 | } |
| 154 | |
| Elliott Hughes | 68f4fa0 | 2011-08-21 10:46:59 -0700 | [diff] [blame] | 155 | TEST_F(ObjectTest, AllocArray) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 156 | ScopedObjectAccess soa(Thread::Current()); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 157 | StackHandleScope<2> hs(soa.Self()); |
| 158 | MutableHandle<Class> c = hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[I")); |
| 159 | gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator(); |
| 160 | MutableHandle<Array> a = hs.NewHandle( |
| Vladimir Marko | 9b81ac3 | 2019-05-16 16:47:08 +0100 | [diff] [blame] | 161 | Array::Alloc(soa.Self(), c.Get(), 1, c->GetComponentSizeShift(), allocator_type)); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 162 | EXPECT_TRUE(c.Get() == a->GetClass()); |
| Ian Rogers | 6fac447 | 2014-02-25 17:01:10 -0800 | [diff] [blame] | 163 | EXPECT_EQ(1, a->GetLength()); |
| Elliott Hughes | 68f4fa0 | 2011-08-21 10:46:59 -0700 | [diff] [blame] | 164 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 165 | c.Assign(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;")); |
| Vladimir Marko | 9b81ac3 | 2019-05-16 16:47:08 +0100 | [diff] [blame] | 166 | a.Assign(Array::Alloc(soa.Self(), c.Get(), 1, c->GetComponentSizeShift(), allocator_type)); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 167 | EXPECT_TRUE(c.Get() == a->GetClass()); |
| Ian Rogers | 6fac447 | 2014-02-25 17:01:10 -0800 | [diff] [blame] | 168 | EXPECT_EQ(1, a->GetLength()); |
| Elliott Hughes | 68f4fa0 | 2011-08-21 10:46:59 -0700 | [diff] [blame] | 169 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 170 | c.Assign(class_linker_->FindSystemClass(soa.Self(), "[[Ljava/lang/Object;")); |
| Vladimir Marko | 9b81ac3 | 2019-05-16 16:47:08 +0100 | [diff] [blame] | 171 | a.Assign(Array::Alloc(soa.Self(), c.Get(), 1, c->GetComponentSizeShift(), allocator_type)); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 172 | EXPECT_TRUE(c.Get() == a->GetClass()); |
| Ian Rogers | 6fac447 | 2014-02-25 17:01:10 -0800 | [diff] [blame] | 173 | EXPECT_EQ(1, a->GetLength()); |
| 174 | } |
| 175 | |
| 176 | TEST_F(ObjectTest, AllocArray_FillUsable) { |
| 177 | ScopedObjectAccess soa(Thread::Current()); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 178 | StackHandleScope<2> hs(soa.Self()); |
| 179 | MutableHandle<Class> c = hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[B")); |
| 180 | gc::AllocatorType allocator_type = Runtime::Current()->GetHeap()->GetCurrentAllocator(); |
| 181 | MutableHandle<Array> a = hs.NewHandle( |
| Vladimir Marko | 9b81ac3 | 2019-05-16 16:47:08 +0100 | [diff] [blame] | 182 | Array::Alloc</*kIsInstrumented=*/ true, /*kFillUsable=*/ true>( |
| 183 | soa.Self(), c.Get(), 1, c->GetComponentSizeShift(), allocator_type)); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 184 | EXPECT_TRUE(c.Get() == a->GetClass()); |
| Ian Rogers | 6fac447 | 2014-02-25 17:01:10 -0800 | [diff] [blame] | 185 | EXPECT_LE(1, a->GetLength()); |
| 186 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 187 | c.Assign(class_linker_->FindSystemClass(soa.Self(), "[I")); |
| Vladimir Marko | 9b81ac3 | 2019-05-16 16:47:08 +0100 | [diff] [blame] | 188 | a.Assign(Array::Alloc</*kIsInstrumented=*/ true, /*kFillUsable=*/ true>( |
| 189 | soa.Self(), c.Get(), 2, c->GetComponentSizeShift(), allocator_type)); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 190 | EXPECT_TRUE(c.Get() == a->GetClass()); |
| Ian Rogers | 6fac447 | 2014-02-25 17:01:10 -0800 | [diff] [blame] | 191 | EXPECT_LE(2, a->GetLength()); |
| 192 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 193 | c.Assign(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;")); |
| Vladimir Marko | 9b81ac3 | 2019-05-16 16:47:08 +0100 | [diff] [blame] | 194 | a.Assign(Array::Alloc</*kIsInstrumented=*/ true, /*kFillUsable=*/ true>( |
| 195 | soa.Self(), c.Get(), 2, c->GetComponentSizeShift(), allocator_type)); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 196 | EXPECT_TRUE(c.Get() == a->GetClass()); |
| Ian Rogers | 6fac447 | 2014-02-25 17:01:10 -0800 | [diff] [blame] | 197 | EXPECT_LE(2, a->GetLength()); |
| 198 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 199 | c.Assign(class_linker_->FindSystemClass(soa.Self(), "[[Ljava/lang/Object;")); |
| Vladimir Marko | 9b81ac3 | 2019-05-16 16:47:08 +0100 | [diff] [blame] | 200 | a.Assign(Array::Alloc</*kIsInstrumented=*/ true, /*kFillUsable=*/ true>( |
| 201 | soa.Self(), c.Get(), 2, c->GetComponentSizeShift(), allocator_type)); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 202 | EXPECT_TRUE(c.Get() == a->GetClass()); |
| Ian Rogers | 6fac447 | 2014-02-25 17:01:10 -0800 | [diff] [blame] | 203 | EXPECT_LE(2, a->GetLength()); |
| Elliott Hughes | 68f4fa0 | 2011-08-21 10:46:59 -0700 | [diff] [blame] | 204 | } |
| 205 | |
| Elliott Hughes | 710a0cb | 2011-08-16 14:32:37 -0700 | [diff] [blame] | 206 | template<typename ArrayT> |
| 207 | void TestPrimitiveArray(ClassLinker* cl) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 208 | ScopedObjectAccess soa(Thread::Current()); |
| Andreas Gampe | c55bb39 | 2018-09-21 00:02:02 +0000 | [diff] [blame] | 209 | using T = typename ArrayT::ElementType; |
| Elliott Hughes | 710a0cb | 2011-08-16 14:32:37 -0700 | [diff] [blame] | 210 | |
| Vladimir Marko | bcf1752 | 2018-06-01 13:14:32 +0100 | [diff] [blame] | 211 | StackHandleScope<2> hs(soa.Self()); |
| 212 | Handle<ArrayT> a = hs.NewHandle(ArrayT::Alloc(soa.Self(), 2)); |
| Elliott Hughes | 710a0cb | 2011-08-16 14:32:37 -0700 | [diff] [blame] | 213 | EXPECT_EQ(2, a->GetLength()); |
| 214 | EXPECT_EQ(0, a->Get(0)); |
| 215 | EXPECT_EQ(0, a->Get(1)); |
| 216 | a->Set(0, T(123)); |
| 217 | EXPECT_EQ(T(123), a->Get(0)); |
| 218 | EXPECT_EQ(0, a->Get(1)); |
| 219 | a->Set(1, T(321)); |
| 220 | EXPECT_EQ(T(123), a->Get(0)); |
| 221 | EXPECT_EQ(T(321), a->Get(1)); |
| 222 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 223 | Handle<Class> aioobe = hs.NewHandle( |
| 224 | cl->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;")); |
| Elliott Hughes | 710a0cb | 2011-08-16 14:32:37 -0700 | [diff] [blame] | 225 | |
| 226 | EXPECT_EQ(0, a->Get(-1)); |
| Ian Rogers | 1f53934 | 2012-10-03 21:09:42 -0700 | [diff] [blame] | 227 | EXPECT_TRUE(soa.Self()->IsExceptionPending()); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 228 | EXPECT_OBJ_PTR_EQ(aioobe.Get(), soa.Self()->GetException()->GetClass()); |
| Ian Rogers | 1f53934 | 2012-10-03 21:09:42 -0700 | [diff] [blame] | 229 | soa.Self()->ClearException(); |
| Elliott Hughes | 710a0cb | 2011-08-16 14:32:37 -0700 | [diff] [blame] | 230 | |
| 231 | EXPECT_EQ(0, a->Get(2)); |
| Ian Rogers | 1f53934 | 2012-10-03 21:09:42 -0700 | [diff] [blame] | 232 | EXPECT_TRUE(soa.Self()->IsExceptionPending()); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 233 | EXPECT_OBJ_PTR_EQ(aioobe.Get(), soa.Self()->GetException()->GetClass()); |
| Ian Rogers | 1f53934 | 2012-10-03 21:09:42 -0700 | [diff] [blame] | 234 | soa.Self()->ClearException(); |
| Elliott Hughes | 710a0cb | 2011-08-16 14:32:37 -0700 | [diff] [blame] | 235 | } |
| 236 | |
| 237 | TEST_F(ObjectTest, PrimitiveArray_Boolean_Alloc) { |
| 238 | TestPrimitiveArray<BooleanArray>(class_linker_); |
| 239 | } |
| 240 | TEST_F(ObjectTest, PrimitiveArray_Byte_Alloc) { |
| 241 | TestPrimitiveArray<ByteArray>(class_linker_); |
| 242 | } |
| 243 | TEST_F(ObjectTest, PrimitiveArray_Char_Alloc) { |
| 244 | TestPrimitiveArray<CharArray>(class_linker_); |
| 245 | } |
| Elliott Hughes | 710a0cb | 2011-08-16 14:32:37 -0700 | [diff] [blame] | 246 | TEST_F(ObjectTest, PrimitiveArray_Int_Alloc) { |
| 247 | TestPrimitiveArray<IntArray>(class_linker_); |
| 248 | } |
| 249 | TEST_F(ObjectTest, PrimitiveArray_Long_Alloc) { |
| 250 | TestPrimitiveArray<LongArray>(class_linker_); |
| 251 | } |
| 252 | TEST_F(ObjectTest, PrimitiveArray_Short_Alloc) { |
| 253 | TestPrimitiveArray<ShortArray>(class_linker_); |
| 254 | } |
| 255 | |
| Vladimir Marko | 4d0f795 | 2020-05-06 13:02:19 +0100 | [diff] [blame] | 256 | TEST_F(ObjectTest, PointerArrayWriteRead) { |
| 257 | ScopedObjectAccess soa(Thread::Current()); |
| 258 | StackHandleScope<2> hs(soa.Self()); |
| 259 | |
| 260 | Handle<PointerArray> a32 = |
| 261 | hs.NewHandle(ObjPtr<PointerArray>::DownCast<Array>(IntArray::Alloc(soa.Self(), 1))); |
| 262 | ASSERT_TRUE(a32 != nullptr); |
| 263 | ASSERT_EQ(1, a32->GetLength()); |
| 264 | EXPECT_EQ(0u, (a32->GetElementPtrSize<uint32_t, PointerSize::k32>(0u))); |
| 265 | EXPECT_EQ(0u, (a32->GetElementPtrSizeUnchecked<uint32_t, PointerSize::k32>(0u))); |
| 266 | for (uint32_t value : { 0u, 1u, 0x7fffffffu, 0x80000000u, 0xffffffffu }) { |
| 267 | a32->SetElementPtrSize(0u, value, PointerSize::k32); |
| 268 | EXPECT_EQ(value, (a32->GetElementPtrSize<uint32_t, PointerSize::k32>(0u))); |
| 269 | EXPECT_EQ(value, (a32->GetElementPtrSizeUnchecked<uint32_t, PointerSize::k32>(0u))); |
| 270 | // Check that the value matches also when retrieved as `uint64_t`. |
| 271 | // This is a regression test for unintended sign-extension. b/155780442 |
| 272 | // (Using `uint64_t` rather than `uintptr_t`, so that the 32-bit test checks this too.) |
| 273 | EXPECT_EQ(value, (a32->GetElementPtrSize<uint64_t, PointerSize::k32>(0u))); |
| 274 | EXPECT_EQ(value, (a32->GetElementPtrSizeUnchecked<uint64_t, PointerSize::k32>(0u))); |
| 275 | } |
| 276 | |
| 277 | Handle<PointerArray> a64 = |
| 278 | hs.NewHandle(ObjPtr<PointerArray>::DownCast<Array>(LongArray::Alloc(soa.Self(), 1))); |
| 279 | ASSERT_TRUE(a64 != nullptr); |
| 280 | ASSERT_EQ(1, a64->GetLength()); |
| 281 | EXPECT_EQ(0u, (a64->GetElementPtrSize<uint32_t, PointerSize::k64>(0u))); |
| 282 | EXPECT_EQ(0u, (a64->GetElementPtrSizeUnchecked<uint32_t, PointerSize::k64>(0u))); |
| 283 | for (uint64_t value : { UINT64_C(0), |
| 284 | UINT64_C(1), |
| 285 | UINT64_C(0x7fffffff), |
| 286 | UINT64_C(0x80000000), |
| 287 | UINT64_C(0xffffffff), |
| 288 | UINT64_C(0x100000000), |
| 289 | UINT64_C(0x7fffffffffffffff), |
| 290 | UINT64_C(0x8000000000000000), |
| 291 | UINT64_C(0xffffffffffffffff) }) { |
| 292 | a64->SetElementPtrSize(0u, value, PointerSize::k64); |
| 293 | EXPECT_EQ(value, (a64->GetElementPtrSize<uint64_t, PointerSize::k64>(0u))); |
| 294 | EXPECT_EQ(value, (a64->GetElementPtrSizeUnchecked<uint64_t, PointerSize::k64>(0u))); |
| 295 | } |
| 296 | } |
| 297 | |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 298 | TEST_F(ObjectTest, PrimitiveArray_Double_Alloc) { |
| Andreas Gampe | c55bb39 | 2018-09-21 00:02:02 +0000 | [diff] [blame] | 299 | using ArrayT = DoubleArray; |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 300 | ScopedObjectAccess soa(Thread::Current()); |
| Andreas Gampe | c55bb39 | 2018-09-21 00:02:02 +0000 | [diff] [blame] | 301 | using T = typename ArrayT::ElementType; |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 302 | |
| Vladimir Marko | bcf1752 | 2018-06-01 13:14:32 +0100 | [diff] [blame] | 303 | StackHandleScope<2> hs(soa.Self()); |
| 304 | Handle<ArrayT> a = hs.NewHandle(ArrayT::Alloc(soa.Self(), 2)); |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 305 | EXPECT_EQ(2, a->GetLength()); |
| 306 | EXPECT_DOUBLE_EQ(0, a->Get(0)); |
| 307 | EXPECT_DOUBLE_EQ(0, a->Get(1)); |
| 308 | a->Set(0, T(123)); |
| 309 | EXPECT_DOUBLE_EQ(T(123), a->Get(0)); |
| 310 | EXPECT_DOUBLE_EQ(0, a->Get(1)); |
| 311 | a->Set(1, T(321)); |
| 312 | EXPECT_DOUBLE_EQ(T(123), a->Get(0)); |
| 313 | EXPECT_DOUBLE_EQ(T(321), a->Get(1)); |
| 314 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 315 | Handle<Class> aioobe = hs.NewHandle( |
| 316 | class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;")); |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 317 | |
| 318 | EXPECT_DOUBLE_EQ(0, a->Get(-1)); |
| 319 | EXPECT_TRUE(soa.Self()->IsExceptionPending()); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 320 | EXPECT_OBJ_PTR_EQ(aioobe.Get(), soa.Self()->GetException()->GetClass()); |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 321 | soa.Self()->ClearException(); |
| 322 | |
| 323 | EXPECT_DOUBLE_EQ(0, a->Get(2)); |
| 324 | EXPECT_TRUE(soa.Self()->IsExceptionPending()); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 325 | EXPECT_OBJ_PTR_EQ(aioobe.Get(), soa.Self()->GetException()->GetClass()); |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 326 | soa.Self()->ClearException(); |
| 327 | } |
| 328 | |
| 329 | TEST_F(ObjectTest, PrimitiveArray_Float_Alloc) { |
| Andreas Gampe | c55bb39 | 2018-09-21 00:02:02 +0000 | [diff] [blame] | 330 | using ArrayT = FloatArray; |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 331 | ScopedObjectAccess soa(Thread::Current()); |
| Andreas Gampe | c55bb39 | 2018-09-21 00:02:02 +0000 | [diff] [blame] | 332 | using T = typename ArrayT::ElementType; |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 333 | |
| Vladimir Marko | bcf1752 | 2018-06-01 13:14:32 +0100 | [diff] [blame] | 334 | StackHandleScope<2> hs(soa.Self()); |
| 335 | Handle<ArrayT> a = hs.NewHandle(ArrayT::Alloc(soa.Self(), 2)); |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 336 | EXPECT_FLOAT_EQ(2, a->GetLength()); |
| 337 | EXPECT_FLOAT_EQ(0, a->Get(0)); |
| 338 | EXPECT_FLOAT_EQ(0, a->Get(1)); |
| 339 | a->Set(0, T(123)); |
| 340 | EXPECT_FLOAT_EQ(T(123), a->Get(0)); |
| 341 | EXPECT_FLOAT_EQ(0, a->Get(1)); |
| 342 | a->Set(1, T(321)); |
| 343 | EXPECT_FLOAT_EQ(T(123), a->Get(0)); |
| 344 | EXPECT_FLOAT_EQ(T(321), a->Get(1)); |
| 345 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 346 | Handle<Class> aioobe = hs.NewHandle( |
| 347 | class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/ArrayIndexOutOfBoundsException;")); |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 348 | |
| 349 | EXPECT_FLOAT_EQ(0, a->Get(-1)); |
| 350 | EXPECT_TRUE(soa.Self()->IsExceptionPending()); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 351 | EXPECT_OBJ_PTR_EQ(aioobe.Get(), soa.Self()->GetException()->GetClass()); |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 352 | soa.Self()->ClearException(); |
| 353 | |
| 354 | EXPECT_FLOAT_EQ(0, a->Get(2)); |
| 355 | EXPECT_TRUE(soa.Self()->IsExceptionPending()); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 356 | EXPECT_OBJ_PTR_EQ(aioobe.Get(), soa.Self()->GetException()->GetClass()); |
| Ian Rogers | 647b1a8 | 2014-10-10 11:02:11 -0700 | [diff] [blame] | 357 | soa.Self()->ClearException(); |
| 358 | } |
| 359 | |
| 360 | |
| Ian Rogers | 64b6d14 | 2012-10-29 16:34:15 -0700 | [diff] [blame] | 361 | TEST_F(ObjectTest, CreateMultiArray) { |
| 362 | ScopedObjectAccess soa(Thread::Current()); |
| 363 | |
| Vladimir Marko | bcf1752 | 2018-06-01 13:14:32 +0100 | [diff] [blame] | 364 | StackHandleScope<4> hs(soa.Self()); |
| 365 | Handle<Class> int_class(hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "I"))); |
| 366 | Handle<Class> int_array_class = hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[I")); |
| Andreas Gampe | 5a4b8a2 | 2014-09-11 08:30:08 -0700 | [diff] [blame] | 367 | MutableHandle<IntArray> dims(hs.NewHandle(IntArray::Alloc(soa.Self(), 1))); |
| Sebastien Hertz | d2fe10a | 2014-01-15 10:20:56 +0100 | [diff] [blame] | 368 | dims->Set<false>(0, 1); |
| Vladimir Marko | bcf1752 | 2018-06-01 13:14:32 +0100 | [diff] [blame] | 369 | MutableHandle<Array> multi = hs.NewHandle(Array::CreateMultiArray(soa.Self(), int_class, dims)); |
| 370 | EXPECT_OBJ_PTR_EQ(int_array_class.Get(), multi->GetClass()); |
| Ian Rogers | 64b6d14 | 2012-10-29 16:34:15 -0700 | [diff] [blame] | 371 | EXPECT_EQ(1, multi->GetLength()); |
| 372 | |
| Sebastien Hertz | d2fe10a | 2014-01-15 10:20:56 +0100 | [diff] [blame] | 373 | dims->Set<false>(0, -1); |
| Vladimir Marko | bcf1752 | 2018-06-01 13:14:32 +0100 | [diff] [blame] | 374 | multi.Assign(Array::CreateMultiArray(soa.Self(), int_class, dims)); |
| Ian Rogers | 64b6d14 | 2012-10-29 16:34:15 -0700 | [diff] [blame] | 375 | EXPECT_TRUE(soa.Self()->IsExceptionPending()); |
| David Sehr | 709b070 | 2016-10-13 09:12:37 -0700 | [diff] [blame] | 376 | EXPECT_EQ(mirror::Class::PrettyDescriptor(soa.Self()->GetException()->GetClass()), |
| Ian Rogers | 64b6d14 | 2012-10-29 16:34:15 -0700 | [diff] [blame] | 377 | "java.lang.NegativeArraySizeException"); |
| 378 | soa.Self()->ClearException(); |
| 379 | |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 380 | dims.Assign(IntArray::Alloc(soa.Self(), 2)); |
| Ian Rogers | 64b6d14 | 2012-10-29 16:34:15 -0700 | [diff] [blame] | 381 | for (int i = 1; i < 20; ++i) { |
| 382 | for (int j = 0; j < 20; ++j) { |
| Sebastien Hertz | d2fe10a | 2014-01-15 10:20:56 +0100 | [diff] [blame] | 383 | dims->Set<false>(0, i); |
| 384 | dims->Set<false>(1, j); |
| Vladimir Marko | bcf1752 | 2018-06-01 13:14:32 +0100 | [diff] [blame] | 385 | multi.Assign(Array::CreateMultiArray(soa.Self(), int_class, dims)); |
| Vladimir Marko | dfc0de7 | 2019-04-01 10:57:55 +0100 | [diff] [blame] | 386 | ObjPtr<mirror::Class> expected_class = class_linker_->FindSystemClass(soa.Self(), "[[I"); |
| 387 | EXPECT_OBJ_PTR_EQ(multi->GetClass(), expected_class); |
| Ian Rogers | 64b6d14 | 2012-10-29 16:34:15 -0700 | [diff] [blame] | 388 | EXPECT_EQ(i, multi->GetLength()); |
| 389 | for (int k = 0; k < i; ++k) { |
| Vladimir Marko | bcf1752 | 2018-06-01 13:14:32 +0100 | [diff] [blame] | 390 | ObjPtr<Array> outer = multi->AsObjectArray<Array>()->Get(k); |
| 391 | EXPECT_OBJ_PTR_EQ(int_array_class.Get(), outer->GetClass()); |
| Ian Rogers | 64b6d14 | 2012-10-29 16:34:15 -0700 | [diff] [blame] | 392 | EXPECT_EQ(j, outer->GetLength()); |
| 393 | } |
| 394 | } |
| 395 | } |
| 396 | } |
| 397 | |
| Brian Carlstrom | b9edb84 | 2011-08-28 16:31:06 -0700 | [diff] [blame] | 398 | TEST_F(ObjectTest, StaticFieldFromCode) { |
| jeffhao | abcfde3 | 2011-09-29 15:05:18 -0700 | [diff] [blame] | 399 | // pretend we are trying to access 'Static.s0' from StaticsFromCode.<clinit> |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 400 | ScopedObjectAccess soa(Thread::Current()); |
| 401 | jobject class_loader = LoadDex("StaticsFromCode"); |
| Andreas Gampe | 81c6f8d | 2015-03-25 17:19:53 -0700 | [diff] [blame] | 402 | const DexFile* dex_file = GetFirstDexFile(class_loader); |
| Brian Carlstrom | 848a4b3 | 2011-09-04 11:29:27 -0700 | [diff] [blame] | 403 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 404 | StackHandleScope<3> hs(soa.Self()); |
| Mathieu Chartier | 0795f23 | 2016-09-27 18:43:30 -0700 | [diff] [blame] | 405 | Handle<mirror::ClassLoader> loader(hs.NewHandle(soa.Decode<ClassLoader>(class_loader))); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 406 | Handle<Class> klass = |
| 407 | hs.NewHandle(class_linker_->FindClass(soa.Self(), "LStaticsFromCode;", loader)); |
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 408 | ArtMethod* clinit = klass->FindClassInitializer(kRuntimePointerSize); |
| Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 409 | const dex::TypeId* klass_type_id = dex_file->FindTypeId("LStaticsFromCode;"); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 410 | ASSERT_TRUE(klass_type_id != nullptr); |
| Ian Rogers | 9b1a4f4 | 2011-11-14 18:35:10 -0800 | [diff] [blame] | 411 | |
| Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 412 | const dex::TypeId* type_type_id = dex_file->FindTypeId("Ljava/lang/Object;"); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 413 | ASSERT_TRUE(type_type_id != nullptr); |
| Ian Rogers | 9b1a4f4 | 2011-11-14 18:35:10 -0800 | [diff] [blame] | 414 | |
| Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 415 | const dex::StringId* name_str_id = dex_file->FindStringId("s0"); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 416 | ASSERT_TRUE(name_str_id != nullptr); |
| Ian Rogers | 9b1a4f4 | 2011-11-14 18:35:10 -0800 | [diff] [blame] | 417 | |
| Andreas Gampe | 3f1dcd3 | 2018-12-28 09:39:56 -0800 | [diff] [blame] | 418 | const dex::FieldId* field_id = dex_file->FindFieldId( |
| Ian Rogers | 9b1a4f4 | 2011-11-14 18:35:10 -0800 | [diff] [blame] | 419 | *klass_type_id, *name_str_id, *type_type_id); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 420 | ASSERT_TRUE(field_id != nullptr); |
| Ian Rogers | 9b1a4f4 | 2011-11-14 18:35:10 -0800 | [diff] [blame] | 421 | uint32_t field_idx = dex_file->GetIndexForFieldId(*field_id); |
| 422 | |
| Sebastien Hertz | d4beb6b | 2013-10-02 17:07:20 +0200 | [diff] [blame] | 423 | ArtField* field = FindFieldFromCode<StaticObjectRead, true>(field_idx, clinit, Thread::Current(), |
| Ian Rogers | ef7d42f | 2014-01-06 12:55:46 -0800 | [diff] [blame] | 424 | sizeof(HeapReference<Object>)); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 425 | ObjPtr<Object> s0 = field->GetObj(klass.Get()); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 426 | EXPECT_TRUE(s0 != nullptr); |
| Brian Carlstrom | b9edb84 | 2011-08-28 16:31:06 -0700 | [diff] [blame] | 427 | |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 428 | Handle<CharArray> char_array(hs.NewHandle(CharArray::Alloc(soa.Self(), 0))); |
| 429 | field->SetObj<false>(field->GetDeclaringClass(), char_array.Get()); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 430 | EXPECT_OBJ_PTR_EQ(char_array.Get(), field->GetObj(klass.Get())); |
| Brian Carlstrom | b9edb84 | 2011-08-28 16:31:06 -0700 | [diff] [blame] | 431 | |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 432 | field->SetObj<false>(field->GetDeclaringClass(), nullptr); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 433 | EXPECT_EQ(nullptr, field->GetObj(klass.Get())); |
| Brian Carlstrom | 9f30b38 | 2011-08-28 22:41:38 -0700 | [diff] [blame] | 434 | |
| Brian Carlstrom | ea46f95 | 2013-07-30 01:26:50 -0700 | [diff] [blame] | 435 | // TODO: more exhaustive tests of all 6 cases of ArtField::*FromCode |
| Brian Carlstrom | b9edb84 | 2011-08-28 16:31:06 -0700 | [diff] [blame] | 436 | } |
| 437 | |
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 438 | TEST_F(ObjectTest, String) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 439 | ScopedObjectAccess soa(Thread::Current()); |
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 440 | // Test the empty string. |
| 441 | AssertString(0, "", "", 0); |
| 442 | |
| 443 | // Test one-byte characters. |
| 444 | AssertString(1, " ", "\x00\x20", 0x20); |
| 445 | AssertString(1, "", "\x00\x00", 0); |
| 446 | AssertString(1, "\x7f", "\x00\x7f", 0x7f); |
| 447 | AssertString(2, "hi", "\x00\x68\x00\x69", (31 * 0x68) + 0x69); |
| 448 | |
| 449 | // Test two-byte characters. |
| 450 | AssertString(1, "\xc2\x80", "\x00\x80", 0x80); |
| 451 | AssertString(1, "\xd9\xa6", "\x06\x66", 0x0666); |
| 452 | AssertString(1, "\xdf\xbf", "\x07\xff", 0x07ff); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 453 | AssertString(3, "h\xd9\xa6i", "\x00\x68\x06\x66\x00\x69", |
| 454 | (31 * ((31 * 0x68) + 0x0666)) + 0x69); |
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 455 | |
| 456 | // Test three-byte characters. |
| 457 | AssertString(1, "\xe0\xa0\x80", "\x08\x00", 0x0800); |
| 458 | AssertString(1, "\xe1\x88\xb4", "\x12\x34", 0x1234); |
| 459 | AssertString(1, "\xef\xbf\xbf", "\xff\xff", 0xffff); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 460 | AssertString(3, "h\xe1\x88\xb4i", "\x00\x68\x12\x34\x00\x69", |
| 461 | (31 * ((31 * 0x68) + 0x1234)) + 0x69); |
| Narayan Kamath | a5afcfc | 2015-01-29 20:06:46 +0000 | [diff] [blame] | 462 | |
| 463 | // Test four-byte characters. |
| 464 | AssertString(2, "\xf0\x9f\x8f\xa0", "\xd8\x3c\xdf\xe0", (31 * 0xd83c) + 0xdfe0); |
| 465 | AssertString(2, "\xf0\x9f\x9a\x80", "\xd8\x3d\xde\x80", (31 * 0xd83d) + 0xde80); |
| 466 | AssertString(4, "h\xf0\x9f\x9a\x80i", "\x00\x68\xd8\x3d\xde\x80\x00\x69", |
| 467 | (31 * (31 * (31 * 0x68 + 0xd83d) + 0xde80) + 0x69)); |
| Brian Carlstrom | 0b138b2 | 2011-07-27 15:19:17 -0700 | [diff] [blame] | 468 | } |
| Jesse Wilson | cbe9fc0 | 2011-07-29 18:59:50 -0400 | [diff] [blame] | 469 | |
| Jesse Wilson | f7e85a5 | 2011-08-01 18:45:58 -0700 | [diff] [blame] | 470 | TEST_F(ObjectTest, StringEqualsUtf8) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 471 | ScopedObjectAccess soa(Thread::Current()); |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 472 | StackHandleScope<2> hs(soa.Self()); |
| 473 | Handle<String> string(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "android"))); |
| Carl Shapiro | 8860c0e | 2011-08-04 17:36:16 -0700 | [diff] [blame] | 474 | EXPECT_TRUE(string->Equals("android")); |
| 475 | EXPECT_FALSE(string->Equals("Android")); |
| 476 | EXPECT_FALSE(string->Equals("ANDROID")); |
| 477 | EXPECT_FALSE(string->Equals("")); |
| 478 | EXPECT_FALSE(string->Equals("and")); |
| 479 | EXPECT_FALSE(string->Equals("androids")); |
| Jesse Wilson | f7e85a5 | 2011-08-01 18:45:58 -0700 | [diff] [blame] | 480 | |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 481 | Handle<String> empty(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), ""))); |
| Carl Shapiro | 8860c0e | 2011-08-04 17:36:16 -0700 | [diff] [blame] | 482 | EXPECT_TRUE(empty->Equals("")); |
| 483 | EXPECT_FALSE(empty->Equals("a")); |
| Jesse Wilson | cbe9fc0 | 2011-07-29 18:59:50 -0400 | [diff] [blame] | 484 | } |
| 485 | |
| 486 | TEST_F(ObjectTest, StringEquals) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 487 | ScopedObjectAccess soa(Thread::Current()); |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 488 | StackHandleScope<3> hs(soa.Self()); |
| 489 | Handle<String> string(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "android"))); |
| 490 | Handle<String> string_2(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "android"))); |
| 491 | EXPECT_TRUE(string->Equals(string_2.Get())); |
| Carl Shapiro | 8860c0e | 2011-08-04 17:36:16 -0700 | [diff] [blame] | 492 | EXPECT_FALSE(string->Equals("Android")); |
| 493 | EXPECT_FALSE(string->Equals("ANDROID")); |
| 494 | EXPECT_FALSE(string->Equals("")); |
| 495 | EXPECT_FALSE(string->Equals("and")); |
| 496 | EXPECT_FALSE(string->Equals("androids")); |
| Jesse Wilson | cbe9fc0 | 2011-07-29 18:59:50 -0400 | [diff] [blame] | 497 | |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 498 | Handle<String> empty(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), ""))); |
| Carl Shapiro | 8860c0e | 2011-08-04 17:36:16 -0700 | [diff] [blame] | 499 | EXPECT_TRUE(empty->Equals("")); |
| 500 | EXPECT_FALSE(empty->Equals("a")); |
| 501 | } |
| 502 | |
| Ian Rogers | 64b6d14 | 2012-10-29 16:34:15 -0700 | [diff] [blame] | 503 | TEST_F(ObjectTest, StringCompareTo) { |
| 504 | ScopedObjectAccess soa(Thread::Current()); |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 505 | StackHandleScope<5> hs(soa.Self()); |
| 506 | Handle<String> string(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "android"))); |
| 507 | Handle<String> string_2(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "android"))); |
| 508 | Handle<String> string_3(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "Android"))); |
| 509 | Handle<String> string_4(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "and"))); |
| 510 | Handle<String> string_5(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), ""))); |
| 511 | EXPECT_EQ(0, string->CompareTo(string_2.Get())); |
| 512 | EXPECT_LT(0, string->CompareTo(string_3.Get())); |
| 513 | EXPECT_GT(0, string_3->CompareTo(string.Get())); |
| 514 | EXPECT_LT(0, string->CompareTo(string_4.Get())); |
| 515 | EXPECT_GT(0, string_4->CompareTo(string.Get())); |
| 516 | EXPECT_LT(0, string->CompareTo(string_5.Get())); |
| 517 | EXPECT_GT(0, string_5->CompareTo(string.Get())); |
| Ian Rogers | 64b6d14 | 2012-10-29 16:34:15 -0700 | [diff] [blame] | 518 | } |
| 519 | |
| jeffhao | 0ce1315 | 2012-03-27 19:45:50 -0700 | [diff] [blame] | 520 | TEST_F(ObjectTest, StringLength) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 521 | ScopedObjectAccess soa(Thread::Current()); |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 522 | StackHandleScope<1> hs(soa.Self()); |
| 523 | Handle<String> string(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "android"))); |
| jeffhao | 0ce1315 | 2012-03-27 19:45:50 -0700 | [diff] [blame] | 524 | EXPECT_EQ(string->GetLength(), 7); |
| 525 | EXPECT_EQ(string->GetUtfLength(), 7); |
| jeffhao | 0ce1315 | 2012-03-27 19:45:50 -0700 | [diff] [blame] | 526 | } |
| 527 | |
| Carl Shapiro | 8860c0e | 2011-08-04 17:36:16 -0700 | [diff] [blame] | 528 | TEST_F(ObjectTest, DescriptorCompare) { |
| Mathieu Chartier | 590fee9 | 2013-09-13 13:46:47 -0700 | [diff] [blame] | 529 | // Two classloaders conflicts in compile_time_class_paths_. |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 530 | ScopedObjectAccess soa(Thread::Current()); |
| Carl Shapiro | 8860c0e | 2011-08-04 17:36:16 -0700 | [diff] [blame] | 531 | ClassLinker* linker = class_linker_; |
| 532 | |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 533 | jobject jclass_loader_1 = LoadDex("ProtoCompare"); |
| 534 | jobject jclass_loader_2 = LoadDex("ProtoCompare2"); |
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 535 | StackHandleScope<4> hs(soa.Self()); |
| Mathieu Chartier | 0795f23 | 2016-09-27 18:43:30 -0700 | [diff] [blame] | 536 | Handle<ClassLoader> class_loader_1(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader_1))); |
| 537 | Handle<ClassLoader> class_loader_2(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader_2))); |
| Carl Shapiro | 8860c0e | 2011-08-04 17:36:16 -0700 | [diff] [blame] | 538 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 539 | Handle<Class> klass1 = |
| 540 | hs.NewHandle(linker->FindClass(soa.Self(), "LProtoCompare;", class_loader_1)); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 541 | ASSERT_TRUE(klass1 != nullptr); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 542 | Handle<Class> klass2 = |
| 543 | hs.NewHandle(linker->FindClass(soa.Self(), "LProtoCompare2;", class_loader_2)); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 544 | ASSERT_TRUE(klass2 != nullptr); |
| Carl Shapiro | 8860c0e | 2011-08-04 17:36:16 -0700 | [diff] [blame] | 545 | |
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 546 | ArtMethod* m1_1 = klass1->GetVirtualMethod(0, kRuntimePointerSize); |
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 547 | EXPECT_STREQ(m1_1->GetName(), "m1"); |
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 548 | ArtMethod* m2_1 = klass1->GetVirtualMethod(1, kRuntimePointerSize); |
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 549 | EXPECT_STREQ(m2_1->GetName(), "m2"); |
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 550 | ArtMethod* m3_1 = klass1->GetVirtualMethod(2, kRuntimePointerSize); |
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 551 | EXPECT_STREQ(m3_1->GetName(), "m3"); |
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 552 | ArtMethod* m4_1 = klass1->GetVirtualMethod(3, kRuntimePointerSize); |
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 553 | EXPECT_STREQ(m4_1->GetName(), "m4"); |
| Carl Shapiro | 8860c0e | 2011-08-04 17:36:16 -0700 | [diff] [blame] | 554 | |
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 555 | ArtMethod* m1_2 = klass2->GetVirtualMethod(0, kRuntimePointerSize); |
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 556 | EXPECT_STREQ(m1_2->GetName(), "m1"); |
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 557 | ArtMethod* m2_2 = klass2->GetVirtualMethod(1, kRuntimePointerSize); |
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 558 | EXPECT_STREQ(m2_2->GetName(), "m2"); |
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 559 | ArtMethod* m3_2 = klass2->GetVirtualMethod(2, kRuntimePointerSize); |
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 560 | EXPECT_STREQ(m3_2->GetName(), "m3"); |
| Andreas Gampe | 542451c | 2016-07-26 09:02:02 -0700 | [diff] [blame] | 561 | ArtMethod* m4_2 = klass2->GetVirtualMethod(3, kRuntimePointerSize); |
| Mathieu Chartier | bfd9a43 | 2014-05-21 17:43:44 -0700 | [diff] [blame] | 562 | EXPECT_STREQ(m4_2->GetName(), "m4"); |
| Jesse Wilson | cbe9fc0 | 2011-07-29 18:59:50 -0400 | [diff] [blame] | 563 | } |
| 564 | |
| Jesse Wilson | fd687c5 | 2011-08-04 19:27:35 -0700 | [diff] [blame] | 565 | TEST_F(ObjectTest, StringHashCode) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 566 | ScopedObjectAccess soa(Thread::Current()); |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 567 | StackHandleScope<3> hs(soa.Self()); |
| 568 | Handle<String> empty(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), ""))); |
| 569 | Handle<String> A(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "A"))); |
| 570 | Handle<String> ABC(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "ABC"))); |
| Brian Carlstrom | 40381fb | 2011-10-19 14:13:40 -0700 | [diff] [blame] | 571 | |
| 572 | EXPECT_EQ(0, empty->GetHashCode()); |
| 573 | EXPECT_EQ(65, A->GetHashCode()); |
| 574 | EXPECT_EQ(64578, ABC->GetHashCode()); |
| Jesse Wilson | fd687c5 | 2011-08-04 19:27:35 -0700 | [diff] [blame] | 575 | } |
| 576 | |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 577 | TEST_F(ObjectTest, InstanceOf) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 578 | ScopedObjectAccess soa(Thread::Current()); |
| 579 | jobject jclass_loader = LoadDex("XandY"); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 580 | StackHandleScope<10> hs(soa.Self()); |
| Mathieu Chartier | 0795f23 | 2016-09-27 18:43:30 -0700 | [diff] [blame] | 581 | Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader))); |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 582 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 583 | Handle<Class> X = hs.NewHandle(class_linker_->FindClass(soa.Self(), "LX;", class_loader)); |
| 584 | Handle<Class> Y = hs.NewHandle(class_linker_->FindClass(soa.Self(), "LY;", class_loader)); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 585 | ASSERT_TRUE(X != nullptr); |
| 586 | ASSERT_TRUE(Y != nullptr); |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 587 | |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 588 | Handle<Object> x(hs.NewHandle(X->AllocObject(soa.Self()))); |
| 589 | Handle<Object> y(hs.NewHandle(Y->AllocObject(soa.Self()))); |
| Andreas Gampe | fa4333d | 2017-02-14 11:10:34 -0800 | [diff] [blame] | 590 | ASSERT_TRUE(x != nullptr); |
| 591 | ASSERT_TRUE(y != nullptr); |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 592 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 593 | EXPECT_TRUE(x->InstanceOf(X.Get())); |
| 594 | EXPECT_FALSE(x->InstanceOf(Y.Get())); |
| 595 | EXPECT_TRUE(y->InstanceOf(X.Get())); |
| 596 | EXPECT_TRUE(y->InstanceOf(Y.Get())); |
| Brian Carlstrom | 5b8e4c8 | 2011-09-18 01:38:59 -0700 | [diff] [blame] | 597 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 598 | Handle<Class> java_lang_Class = |
| 599 | hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Class;")); |
| 600 | Handle<Class> Object_array_class = |
| 601 | hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;")); |
| Elliott Hughes | 92f14b2 | 2011-10-06 12:29:54 -0700 | [diff] [blame] | 602 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 603 | EXPECT_FALSE(java_lang_Class->InstanceOf(Object_array_class.Get())); |
| 604 | EXPECT_TRUE(Object_array_class->InstanceOf(java_lang_Class.Get())); |
| Elliott Hughes | 92f14b2 | 2011-10-06 12:29:54 -0700 | [diff] [blame] | 605 | |
| 606 | // All array classes implement Cloneable and Serializable. |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 607 | Handle<Object> array = |
| 608 | hs.NewHandle<Object>(ObjectArray<Object>::Alloc(soa.Self(), Object_array_class.Get(), 1)); |
| 609 | Handle<Class> java_lang_Cloneable = |
| 610 | hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Cloneable;")); |
| 611 | Handle<Class> java_io_Serializable = |
| 612 | hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;")); |
| 613 | EXPECT_TRUE(array->InstanceOf(java_lang_Cloneable.Get())); |
| 614 | EXPECT_TRUE(array->InstanceOf(java_io_Serializable.Get())); |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 615 | } |
| 616 | |
| 617 | TEST_F(ObjectTest, IsAssignableFrom) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 618 | ScopedObjectAccess soa(Thread::Current()); |
| 619 | jobject jclass_loader = LoadDex("XandY"); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 620 | StackHandleScope<5> hs(soa.Self()); |
| Mathieu Chartier | 0795f23 | 2016-09-27 18:43:30 -0700 | [diff] [blame] | 621 | Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader))); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 622 | Handle<Class> X = hs.NewHandle(class_linker_->FindClass(soa.Self(), "LX;", class_loader)); |
| 623 | Handle<Class> Y = hs.NewHandle(class_linker_->FindClass(soa.Self(), "LY;", class_loader)); |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 624 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 625 | EXPECT_TRUE(X->IsAssignableFrom(X.Get())); |
| 626 | EXPECT_TRUE(X->IsAssignableFrom(Y.Get())); |
| 627 | EXPECT_FALSE(Y->IsAssignableFrom(X.Get())); |
| 628 | EXPECT_TRUE(Y->IsAssignableFrom(Y.Get())); |
| Ian Rogers | d81871c | 2011-10-03 13:57:23 -0700 | [diff] [blame] | 629 | |
| 630 | // class final String implements CharSequence, .. |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 631 | Handle<Class> string = |
| 632 | hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/String;")); |
| 633 | Handle<Class> charseq = |
| 634 | hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/CharSequence;")); |
| Ian Rogers | d81871c | 2011-10-03 13:57:23 -0700 | [diff] [blame] | 635 | // Can String be assigned to CharSequence without a cast? |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 636 | EXPECT_TRUE(charseq->IsAssignableFrom(string.Get())); |
| Ian Rogers | d81871c | 2011-10-03 13:57:23 -0700 | [diff] [blame] | 637 | // Can CharSequence be assigned to String without a cast? |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 638 | EXPECT_FALSE(string->IsAssignableFrom(charseq.Get())); |
| Ian Rogers | d81871c | 2011-10-03 13:57:23 -0700 | [diff] [blame] | 639 | |
| 640 | // Primitive types are only assignable to themselves |
| 641 | const char* prims = "ZBCSIJFD"; |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 642 | std::vector<ObjPtr<Class>> prim_types(strlen(prims)); |
| Ian Rogers | d81871c | 2011-10-03 13:57:23 -0700 | [diff] [blame] | 643 | for (size_t i = 0; i < strlen(prims); i++) { |
| 644 | prim_types[i] = class_linker_->FindPrimitiveClass(prims[i]); |
| 645 | } |
| 646 | for (size_t i = 0; i < strlen(prims); i++) { |
| 647 | for (size_t j = 0; i < strlen(prims); i++) { |
| 648 | if (i == j) { |
| 649 | EXPECT_TRUE(prim_types[i]->IsAssignableFrom(prim_types[j])); |
| 650 | } else { |
| 651 | EXPECT_FALSE(prim_types[i]->IsAssignableFrom(prim_types[j])); |
| 652 | } |
| 653 | } |
| 654 | } |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 655 | } |
| 656 | |
| 657 | TEST_F(ObjectTest, IsAssignableFromArray) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 658 | ScopedObjectAccess soa(Thread::Current()); |
| 659 | jobject jclass_loader = LoadDex("XandY"); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 660 | StackHandleScope<14> hs(soa.Self()); |
| Mathieu Chartier | 0795f23 | 2016-09-27 18:43:30 -0700 | [diff] [blame] | 661 | Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader))); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 662 | Handle<Class> X = hs.NewHandle(class_linker_->FindClass(soa.Self(), "LX;", class_loader)); |
| 663 | Handle<Class> Y = hs.NewHandle(class_linker_->FindClass(soa.Self(), "LY;", class_loader)); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 664 | ASSERT_TRUE(X != nullptr); |
| 665 | ASSERT_TRUE(Y != nullptr); |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 666 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 667 | Handle<Class> YA = hs.NewHandle(class_linker_->FindClass(soa.Self(), "[LY;", class_loader)); |
| 668 | Handle<Class> YAA = hs.NewHandle(class_linker_->FindClass(soa.Self(), "[[LY;", class_loader)); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 669 | ASSERT_TRUE(YA != nullptr); |
| 670 | ASSERT_TRUE(YAA != nullptr); |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 671 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 672 | Handle<Class> XAA = hs.NewHandle(class_linker_->FindClass(soa.Self(), "[[LX;", class_loader)); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 673 | ASSERT_TRUE(XAA != nullptr); |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 674 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 675 | Handle<Class> O = hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Object;")); |
| 676 | Handle<Class> OA = |
| 677 | hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/Object;")); |
| 678 | Handle<Class> OAA = |
| 679 | hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[[Ljava/lang/Object;")); |
| 680 | Handle<Class> OAAA = |
| 681 | hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[[[Ljava/lang/Object;")); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 682 | ASSERT_TRUE(O != nullptr); |
| 683 | ASSERT_TRUE(OA != nullptr); |
| 684 | ASSERT_TRUE(OAA != nullptr); |
| 685 | ASSERT_TRUE(OAAA != nullptr); |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 686 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 687 | Handle<Class> S = |
| 688 | hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;")); |
| 689 | Handle<Class> SA = |
| 690 | hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[Ljava/io/Serializable;")); |
| 691 | Handle<Class> SAA = |
| 692 | hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[[Ljava/io/Serializable;")); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 693 | ASSERT_TRUE(S != nullptr); |
| 694 | ASSERT_TRUE(SA != nullptr); |
| 695 | ASSERT_TRUE(SAA != nullptr); |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 696 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 697 | Handle<Class> IA = hs.NewHandle(class_linker_->FindSystemClass(soa.Self(), "[I")); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 698 | ASSERT_TRUE(IA != nullptr); |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 699 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 700 | EXPECT_TRUE(YAA->IsAssignableFrom(YAA.Get())); // identity |
| 701 | EXPECT_TRUE(XAA->IsAssignableFrom(YAA.Get())); // element superclass |
| 702 | EXPECT_FALSE(YAA->IsAssignableFrom(XAA.Get())); |
| 703 | EXPECT_FALSE(Y->IsAssignableFrom(YAA.Get())); |
| 704 | EXPECT_FALSE(YA->IsAssignableFrom(YAA.Get())); |
| 705 | EXPECT_TRUE(O->IsAssignableFrom(YAA.Get())); // everything is an Object |
| 706 | EXPECT_TRUE(OA->IsAssignableFrom(YAA.Get())); |
| 707 | EXPECT_TRUE(OAA->IsAssignableFrom(YAA.Get())); |
| 708 | EXPECT_TRUE(S->IsAssignableFrom(YAA.Get())); // all arrays are Serializable |
| 709 | EXPECT_TRUE(SA->IsAssignableFrom(YAA.Get())); |
| 710 | EXPECT_FALSE(SAA->IsAssignableFrom(YAA.Get())); // unless Y was Serializable |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 711 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 712 | EXPECT_FALSE(IA->IsAssignableFrom(OA.Get())); |
| 713 | EXPECT_FALSE(OA->IsAssignableFrom(IA.Get())); |
| 714 | EXPECT_TRUE(O->IsAssignableFrom(IA.Get())); |
| Brian Carlstrom | f7ed11a | 2011-08-09 17:55:51 -0700 | [diff] [blame] | 715 | } |
| 716 | |
| Elliott Hughes | cdf5312 | 2011-08-19 15:46:09 -0700 | [diff] [blame] | 717 | TEST_F(ObjectTest, FindInstanceField) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 718 | ScopedObjectAccess soa(Thread::Current()); |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 719 | StackHandleScope<1> hs(soa.Self()); |
| 720 | Handle<String> s(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "ABC"))); |
| Andreas Gampe | fa4333d | 2017-02-14 11:10:34 -0800 | [diff] [blame] | 721 | ASSERT_TRUE(s != nullptr); |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 722 | ObjPtr<Class> c = s->GetClass(); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 723 | ASSERT_TRUE(c != nullptr); |
| Elliott Hughes | cdf5312 | 2011-08-19 15:46:09 -0700 | [diff] [blame] | 724 | |
| 725 | // Wrong type. |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 726 | EXPECT_TRUE(c->FindDeclaredInstanceField("count", "J") == nullptr); |
| 727 | EXPECT_TRUE(c->FindInstanceField("count", "J") == nullptr); |
| Elliott Hughes | cdf5312 | 2011-08-19 15:46:09 -0700 | [diff] [blame] | 728 | |
| 729 | // Wrong name. |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 730 | EXPECT_TRUE(c->FindDeclaredInstanceField("Count", "I") == nullptr); |
| 731 | EXPECT_TRUE(c->FindInstanceField("Count", "I") == nullptr); |
| Elliott Hughes | cdf5312 | 2011-08-19 15:46:09 -0700 | [diff] [blame] | 732 | |
| 733 | // Right name and type. |
| Brian Carlstrom | ea46f95 | 2013-07-30 01:26:50 -0700 | [diff] [blame] | 734 | ArtField* f1 = c->FindDeclaredInstanceField("count", "I"); |
| 735 | ArtField* f2 = c->FindInstanceField("count", "I"); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 736 | EXPECT_TRUE(f1 != nullptr); |
| 737 | EXPECT_TRUE(f2 != nullptr); |
| Elliott Hughes | cdf5312 | 2011-08-19 15:46:09 -0700 | [diff] [blame] | 738 | EXPECT_EQ(f1, f2); |
| 739 | |
| 740 | // TODO: check that s.count == 3. |
| 741 | |
| 742 | // Ensure that we handle superclass fields correctly... |
| Ian Rogers | 9837939 | 2014-02-24 16:53:16 -0800 | [diff] [blame] | 743 | c = class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/StringBuilder;"); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 744 | ASSERT_TRUE(c != nullptr); |
| Elliott Hughes | cdf5312 | 2011-08-19 15:46:09 -0700 | [diff] [blame] | 745 | // No StringBuilder.count... |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 746 | EXPECT_TRUE(c->FindDeclaredInstanceField("count", "I") == nullptr); |
| Elliott Hughes | cdf5312 | 2011-08-19 15:46:09 -0700 | [diff] [blame] | 747 | // ...but there is an AbstractStringBuilder.count. |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 748 | EXPECT_TRUE(c->FindInstanceField("count", "I") != nullptr); |
| Elliott Hughes | cdf5312 | 2011-08-19 15:46:09 -0700 | [diff] [blame] | 749 | } |
| 750 | |
| 751 | TEST_F(ObjectTest, FindStaticField) { |
| Ian Rogers | 00f7d0e | 2012-07-19 15:28:27 -0700 | [diff] [blame] | 752 | ScopedObjectAccess soa(Thread::Current()); |
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 753 | StackHandleScope<4> hs(soa.Self()); |
| Mathieu Chartier | eb8167a | 2014-05-07 15:43:14 -0700 | [diff] [blame] | 754 | Handle<String> s(hs.NewHandle(String::AllocFromModifiedUtf8(soa.Self(), "ABC"))); |
| Andreas Gampe | fa4333d | 2017-02-14 11:10:34 -0800 | [diff] [blame] | 755 | ASSERT_TRUE(s != nullptr); |
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 756 | Handle<Class> c(hs.NewHandle(s->GetClass())); |
| Andreas Gampe | fa4333d | 2017-02-14 11:10:34 -0800 | [diff] [blame] | 757 | ASSERT_TRUE(c != nullptr); |
| Elliott Hughes | cdf5312 | 2011-08-19 15:46:09 -0700 | [diff] [blame] | 758 | |
| 759 | // Wrong type. |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 760 | EXPECT_TRUE(c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "I") == nullptr); |
| 761 | EXPECT_TRUE(mirror::Class::FindStaticField( |
| Vladimir Marko | 19a4d37 | 2016-12-08 14:41:46 +0000 | [diff] [blame] | 762 | soa.Self(), c.Get(), "CASE_INSENSITIVE_ORDER", "I") == nullptr); |
| Elliott Hughes | cdf5312 | 2011-08-19 15:46:09 -0700 | [diff] [blame] | 763 | |
| 764 | // Wrong name. |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 765 | EXPECT_TRUE(c->FindDeclaredStaticField( |
| 766 | "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == nullptr); |
| Mathieu Chartier | f832284 | 2014-05-16 10:59:25 -0700 | [diff] [blame] | 767 | EXPECT_TRUE( |
| Vladimir Marko | 19a4d37 | 2016-12-08 14:41:46 +0000 | [diff] [blame] | 768 | mirror::Class::FindStaticField( |
| 769 | soa.Self(), c.Get(), "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == nullptr); |
| Elliott Hughes | cdf5312 | 2011-08-19 15:46:09 -0700 | [diff] [blame] | 770 | |
| 771 | // Right name and type. |
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 772 | ArtField* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;"); |
| Vladimir Marko | 19a4d37 | 2016-12-08 14:41:46 +0000 | [diff] [blame] | 773 | ArtField* f2 = mirror::Class::FindStaticField( |
| 774 | soa.Self(), c.Get(), "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;"); |
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 775 | EXPECT_TRUE(f1 != nullptr); |
| 776 | EXPECT_TRUE(f2 != nullptr); |
| Mathieu Chartier | c785344 | 2015-03-27 14:35:38 -0700 | [diff] [blame] | 777 | EXPECT_EQ(f1, f2); |
| Elliott Hughes | cdf5312 | 2011-08-19 15:46:09 -0700 | [diff] [blame] | 778 | |
| 779 | // TODO: test static fields via superclasses. |
| 780 | // TODO: test static fields via interfaces. |
| 781 | // TODO: test that interfaces trump superclasses. |
| 782 | } |
| 783 | |
| tony.ys_liu | 7380c31 | 2015-01-16 19:16:45 +0800 | [diff] [blame] | 784 | TEST_F(ObjectTest, IdentityHashCode) { |
| 785 | // Regression test for b/19046417 which had an infinite loop if the |
| 786 | // (seed & LockWord::kHashMask) == 0. seed 0 triggered the infinite loop since we did the check |
| 787 | // before the CAS which resulted in the same seed the next loop iteration. |
| 788 | mirror::Object::SetHashCodeSeed(0); |
| 789 | int32_t hash_code = mirror::Object::GenerateIdentityHashCode(); |
| 790 | EXPECT_NE(hash_code, 0); |
| 791 | } |
| 792 | |
| Mathieu Chartier | 3f7f03c | 2016-09-26 11:39:52 -0700 | [diff] [blame] | 793 | TEST_F(ObjectTest, ObjectPointer) { |
| 794 | ScopedObjectAccess soa(Thread::Current()); |
| 795 | jobject jclass_loader = LoadDex("XandY"); |
| 796 | StackHandleScope<2> hs(soa.Self()); |
| Mathieu Chartier | 0795f23 | 2016-09-27 18:43:30 -0700 | [diff] [blame] | 797 | Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader))); |
| Mathieu Chartier | 3f7f03c | 2016-09-26 11:39:52 -0700 | [diff] [blame] | 798 | Handle<mirror::Class> h_X( |
| 799 | hs.NewHandle(class_linker_->FindClass(soa.Self(), "LX;", class_loader))); |
| Mathieu Chartier | 3f7f03c | 2016-09-26 11:39:52 -0700 | [diff] [blame] | 800 | |
| Andreas Gampe | c73cb64 | 2017-02-22 10:11:30 -0800 | [diff] [blame] | 801 | if (kObjPtrPoisoning) { |
| 802 | ObjPtr<mirror::Object> null_ptr; |
| 803 | EXPECT_TRUE(null_ptr.IsNull()); |
| 804 | EXPECT_TRUE(null_ptr.IsValid()); |
| 805 | EXPECT_TRUE(null_ptr.Ptr() == nullptr); |
| 806 | EXPECT_TRUE(null_ptr == nullptr); |
| 807 | EXPECT_TRUE(null_ptr == null_ptr); |
| 808 | EXPECT_FALSE(null_ptr != null_ptr); |
| 809 | EXPECT_FALSE(null_ptr != nullptr); |
| 810 | null_ptr.AssertValid(); |
| 811 | ObjPtr<Class> X(h_X.Get()); |
| 812 | EXPECT_TRUE(!X.IsNull()); |
| 813 | EXPECT_TRUE(X.IsValid()); |
| 814 | EXPECT_TRUE(X.Ptr() != nullptr); |
| 815 | EXPECT_OBJ_PTR_EQ(h_X.Get(), X); |
| 816 | // FindClass may cause thread suspension, it should invalidate X. |
| 817 | ObjPtr<Class> Y(class_linker_->FindClass(soa.Self(), "LY;", class_loader)); |
| 818 | EXPECT_TRUE(!Y.IsNull()); |
| 819 | EXPECT_TRUE(Y.IsValid()); |
| 820 | EXPECT_TRUE(Y.Ptr() != nullptr); |
| Mathieu Chartier | 3f7f03c | 2016-09-26 11:39:52 -0700 | [diff] [blame] | 821 | |
| Andreas Gampe | c73cb64 | 2017-02-22 10:11:30 -0800 | [diff] [blame] | 822 | // Should IsNull be safe to call on null ObjPtr? I'll allow it for now. |
| 823 | EXPECT_TRUE(!X.IsNull()); |
| 824 | EXPECT_TRUE(!X.IsValid()); |
| 825 | // Make X valid again by copying out of handle. |
| 826 | X.Assign(h_X.Get()); |
| 827 | EXPECT_TRUE(!X.IsNull()); |
| 828 | EXPECT_TRUE(X.IsValid()); |
| 829 | EXPECT_OBJ_PTR_EQ(h_X.Get(), X); |
| Mathieu Chartier | 3f7f03c | 2016-09-26 11:39:52 -0700 | [diff] [blame] | 830 | |
| Andreas Gampe | c73cb64 | 2017-02-22 10:11:30 -0800 | [diff] [blame] | 831 | // Allow thread suspension to invalidate Y. |
| 832 | soa.Self()->AllowThreadSuspension(); |
| 833 | EXPECT_TRUE(!Y.IsNull()); |
| 834 | EXPECT_TRUE(!Y.IsValid()); |
| 835 | } else { |
| 836 | // Test unpoisoned. |
| 837 | ObjPtr<mirror::Object> unpoisoned; |
| 838 | EXPECT_TRUE(unpoisoned.IsNull()); |
| 839 | EXPECT_TRUE(unpoisoned.IsValid()); |
| 840 | EXPECT_TRUE(unpoisoned.Ptr() == nullptr); |
| 841 | EXPECT_TRUE(unpoisoned == nullptr); |
| 842 | EXPECT_TRUE(unpoisoned == unpoisoned); |
| 843 | EXPECT_FALSE(unpoisoned != unpoisoned); |
| 844 | EXPECT_FALSE(unpoisoned != nullptr); |
| Mathieu Chartier | 3f7f03c | 2016-09-26 11:39:52 -0700 | [diff] [blame] | 845 | |
| Andreas Gampe | c73cb64 | 2017-02-22 10:11:30 -0800 | [diff] [blame] | 846 | unpoisoned = h_X.Get(); |
| 847 | EXPECT_FALSE(unpoisoned.IsNull()); |
| 848 | EXPECT_TRUE(unpoisoned == h_X.Get()); |
| 849 | EXPECT_OBJ_PTR_EQ(unpoisoned, h_X.Get()); |
| 850 | } |
| Mathieu Chartier | 3f7f03c | 2016-09-26 11:39:52 -0700 | [diff] [blame] | 851 | } |
| 852 | |
| David Sehr | c431b9d | 2018-03-02 12:01:51 -0800 | [diff] [blame] | 853 | TEST_F(ObjectTest, PrettyTypeOf) { |
| 854 | ScopedObjectAccess soa(Thread::Current()); |
| 855 | EXPECT_EQ("null", mirror::Object::PrettyTypeOf(nullptr)); |
| 856 | |
| 857 | StackHandleScope<2> hs(soa.Self()); |
| 858 | Handle<mirror::String> s(hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), ""))); |
| 859 | EXPECT_EQ("java.lang.String", mirror::Object::PrettyTypeOf(s.Get())); |
| 860 | |
| 861 | Handle<mirror::ShortArray> a(hs.NewHandle(mirror::ShortArray::Alloc(soa.Self(), 2))); |
| 862 | EXPECT_EQ("short[]", mirror::Object::PrettyTypeOf(a.Get())); |
| 863 | |
| Vladimir Marko | e9987b0 | 2018-05-22 16:26:43 +0100 | [diff] [blame] | 864 | ObjPtr<mirror::Class> c = class_linker_->FindSystemClass(soa.Self(), "[Ljava/lang/String;"); |
| David Sehr | c431b9d | 2018-03-02 12:01:51 -0800 | [diff] [blame] | 865 | ASSERT_TRUE(c != nullptr); |
| Vladimir Marko | bcf1752 | 2018-06-01 13:14:32 +0100 | [diff] [blame] | 866 | ObjPtr<mirror::Object> o = mirror::ObjectArray<mirror::String>::Alloc(soa.Self(), c, 0); |
| David Sehr | c431b9d | 2018-03-02 12:01:51 -0800 | [diff] [blame] | 867 | EXPECT_EQ("java.lang.String[]", mirror::Object::PrettyTypeOf(o)); |
| 868 | EXPECT_EQ("java.lang.Class<java.lang.String[]>", mirror::Object::PrettyTypeOf(o->GetClass())); |
| 869 | } |
| 870 | |
| Ian Rogers | 2dd0e2c | 2013-01-24 12:42:14 -0800 | [diff] [blame] | 871 | } // namespace mirror |
| Carl Shapiro | 894d0fa | 2011-06-30 14:48:49 -0700 | [diff] [blame] | 872 | } // namespace art |