12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 167e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 177e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom#include "intern_table.h" 187e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 1921f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin#include "base/hash_set.h" 20a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstrom#include "common_runtime_test.h" 210225f8e2939a9340cb7dcebfcfe7996a2bd9bce9David Sehr#include "dex/utf.h" 22c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe#include "gc_root-inl.h" 23eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier#include "handle_scope-inl.h" 248cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe#include "mirror/object.h" 25e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "mirror/string.h" 260795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_thread_state_change-inl.h" 277e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 287e93b50433cde2a44d99212e8040299bde498546Brian Carlstromnamespace art { 297e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 30a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstromclass InternTableTest : public CommonRuntimeTest {}; 317e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 327e93b50433cde2a44d99212e8040299bde498546Brian CarlstromTEST_F(InternTableTest, Intern) { 3300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 347e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom InternTable intern_table; 35eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<4> hs(soa.Self()); 36eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo_1(hs.NewHandle(intern_table.InternStrong(3, "foo"))); 37eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo_2(hs.NewHandle(intern_table.InternStrong(3, "foo"))); 38eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo_3( 39eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"))); 40eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> bar(hs.NewHandle(intern_table.InternStrong(3, "bar"))); 41fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe ASSERT_TRUE(foo_1 != nullptr); 42fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe ASSERT_TRUE(foo_2 != nullptr); 43fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe ASSERT_TRUE(foo_3 != nullptr); 44fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe ASSERT_TRUE(bar != nullptr); 45cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko EXPECT_EQ(foo_1.Get(), foo_2.Get()); 467e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom EXPECT_TRUE(foo_1->Equals("foo")); 477e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom EXPECT_TRUE(foo_2->Equals("foo")); 487e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom EXPECT_TRUE(foo_3->Equals("foo")); 49eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_NE(foo_1.Get(), bar.Get()); 50eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_NE(foo_2.Get(), bar.Get()); 51eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_NE(foo_3.Get(), bar.Get()); 527e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom} 537e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 54cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott HughesTEST_F(InternTableTest, Size) { 5500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 56cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes InternTable t; 57cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes EXPECT_EQ(0U, t.Size()); 58cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes t.InternStrong(3, "foo"); 59eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<1> hs(soa.Self()); 60eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo( 61eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"))); 62eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier t.InternWeak(foo.Get()); 63cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes EXPECT_EQ(1U, t.Size()); 64cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes t.InternStrong(3, "bar"); 65cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes EXPECT_EQ(2U, t.Size()); 66cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes} 67cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 6821f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin// Check if table indexes match on 64 and 32 bit machines. 6921f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin// This is done by ensuring hash values are the same on every machine and limited to 32-bit wide. 7021f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin// Otherwise cross compilation can cause a table to be filled on host using one indexing algorithm 7121f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin// and later on a device with different sizeof(size_t) can use another indexing algorithm. 7221f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin// Thus the table may provide wrong data. 7321f2364f11a709c7c22320588abe2adc91c69b6aAlexey GrebenkinTEST_F(InternTableTest, CrossHash) { 7421f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin ScopedObjectAccess soa(Thread::Current()); 7521f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin InternTable t; 7621f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin 7721f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin // A string that has a negative hash value. 7821f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin GcRoot<mirror::String> str(mirror::String::AllocFromModifiedUtf8(soa.Self(), "00000000")); 7921f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin 8021f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin MutexLock mu(Thread::Current(), *Locks::intern_table_lock_); 8121f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin for (InternTable::Table::UnorderedSet& table : t.strong_interns_.tables_) { 8221f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin // The negative hash value shall be 32-bit wide on every host. 8321f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin ASSERT_TRUE(IsUint<32>(table.hashfn_(str))); 8421f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin } 8521f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin} 8621f2364f11a709c7c22320588abe2adc91c69b6aAlexey Grebenkin 8797509954404d031594b2ecbda607314d169d512eMathieu Chartierclass TestPredicate : public IsMarkedVisitor { 88410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes public: 89bdf7f1c3ab65ccb70f62db5ab31dba060632d458Andreas Gampe mirror::Object* IsMarked(mirror::Object* s) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { 90410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes bool erased = false; 9102e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier for (auto it = expected_.begin(), end = expected_.end(); it != end; ++it) { 92410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes if (*it == s) { 93410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes expected_.erase(it); 94410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes erased = true; 95410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes break; 96410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes } 97cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes } 98410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes EXPECT_TRUE(erased); 9997509954404d031594b2ecbda607314d169d512eMathieu Chartier return nullptr; 100cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes } 101410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes 1022dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers void Expect(const mirror::String* s) { 103410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes expected_.push_back(s); 104410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes } 105410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes 106410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes ~TestPredicate() { 107410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes EXPECT_EQ(0U, expected_.size()); 108410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes } 109410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes 110410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes private: 1112dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mutable std::vector<const mirror::String*> expected_; 112410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes}; 113cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 114c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott HughesTEST_F(InternTableTest, SweepInternTableWeaks) { 11500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 116cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes InternTable t; 117cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes t.InternStrong(3, "foo"); 118cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes t.InternStrong(3, "bar"); 119eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<5> hs(soa.Self()); 120eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> hello( 121eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello"))); 122eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> world( 123eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "world"))); 124eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> s0(hs.NewHandle(t.InternWeak(hello.Get()))); 125eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> s1(hs.NewHandle(t.InternWeak(world.Get()))); 126cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 127cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes EXPECT_EQ(4U, t.Size()); 128cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 129cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes // We should traverse only the weaks... 130410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes TestPredicate p; 131eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier p.Expect(s0.Get()); 132eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier p.Expect(s1.Get()); 13300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 1341f5393447b9f45be7918042d9ee7b521376de866Ian Rogers ReaderMutexLock mu(soa.Self(), *Locks::heap_bitmap_lock_); 13597509954404d031594b2ecbda607314d169d512eMathieu Chartier t.SweepInternTableWeaks(&p); 13600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 137cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 138cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes EXPECT_EQ(2U, t.Size()); 139cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 140e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes // Just check that we didn't corrupt the map. 141eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> still_here( 142eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "still here"))); 143eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier t.InternWeak(still_here.Get()); 144cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes EXPECT_EQ(3U, t.Size()); 145cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes} 146cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 147cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott HughesTEST_F(InternTableTest, ContainsWeak) { 14800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 149cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes { 150cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes // Strongs are never weak. 151cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes InternTable t; 152eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<2> hs(soa.Self()); 153eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternStrong(3, "foo"))); 154eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_FALSE(t.ContainsWeak(interned_foo_1.Get())); 155eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternStrong(3, "foo"))); 156eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_FALSE(t.ContainsWeak(interned_foo_2.Get())); 157eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get()); 158cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes } 159cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 160cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes { 161cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes // Weaks are always weak. 162cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes InternTable t; 163eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<4> hs(soa.Self()); 164eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo_1( 165eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"))); 166eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo_2( 167eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"))); 168eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_NE(foo_1.Get(), foo_2.Get()); 169eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternWeak(foo_1.Get()))); 170eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternWeak(foo_2.Get()))); 171eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_TRUE(t.ContainsWeak(interned_foo_2.Get())); 172eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get()); 173cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes } 174cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 175cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes { 176cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes // A weak can be promoted to a strong. 177cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes InternTable t; 178eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<3> hs(soa.Self()); 179eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo( 180eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"))); 181eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternWeak(foo.Get()))); 182eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_TRUE(t.ContainsWeak(interned_foo_1.Get())); 183eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternStrong(3, "foo"))); 184eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_FALSE(t.ContainsWeak(interned_foo_2.Get())); 185eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get()); 186cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes } 187cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 188cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes { 189cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes // Interning a weak after a strong gets you the strong. 190cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes InternTable t; 191eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<3> hs(soa.Self()); 192eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternStrong(3, "foo"))); 193eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_FALSE(t.ContainsWeak(interned_foo_1.Get())); 194eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo( 195eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"))); 196eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternWeak(foo.Get()))); 197eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_FALSE(t.ContainsWeak(interned_foo_2.Get())); 198eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get()); 199cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes } 200cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes} 201cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 202cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir MarkoTEST_F(InternTableTest, LookupStrong) { 203cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko ScopedObjectAccess soa(Thread::Current()); 204cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko InternTable intern_table; 205cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko StackHandleScope<3> hs(soa.Self()); 206cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko Handle<mirror::String> foo(hs.NewHandle(intern_table.InternStrong(3, "foo"))); 207cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko Handle<mirror::String> bar(hs.NewHandle(intern_table.InternStrong(3, "bar"))); 208cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko Handle<mirror::String> foobar(hs.NewHandle(intern_table.InternStrong(6, "foobar"))); 209fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe ASSERT_TRUE(foo != nullptr); 210fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe ASSERT_TRUE(bar != nullptr); 211fa4333dcb481e564f54726b4e6f8153612df835eAndreas Gampe ASSERT_TRUE(foobar != nullptr); 212cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko ASSERT_TRUE(foo->Equals("foo")); 213cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko ASSERT_TRUE(bar->Equals("bar")); 214cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko ASSERT_TRUE(foobar->Equals("foobar")); 215cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko ASSERT_NE(foo.Get(), bar.Get()); 216cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko ASSERT_NE(foo.Get(), foobar.Get()); 217cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko ASSERT_NE(bar.Get(), foobar.Get()); 2189e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier ObjPtr<mirror::String> lookup_foo = intern_table.LookupStrong(soa.Self(), 3, "foo"); 2199e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier EXPECT_OBJ_PTR_EQ(lookup_foo, foo.Get()); 2209e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier ObjPtr<mirror::String> lookup_bar = intern_table.LookupStrong(soa.Self(), 3, "bar"); 2219e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier EXPECT_OBJ_PTR_EQ(lookup_bar, bar.Get()); 2229e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier ObjPtr<mirror::String> lookup_foobar = intern_table.LookupStrong(soa.Self(), 6, "foobar"); 2239e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier EXPECT_OBJ_PTR_EQ(lookup_foobar, foobar.Get()); 2249e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier ObjPtr<mirror::String> lookup_foox = intern_table.LookupStrong(soa.Self(), 4, "foox"); 225cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko EXPECT_TRUE(lookup_foox == nullptr); 2269e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier ObjPtr<mirror::String> lookup_fooba = intern_table.LookupStrong(soa.Self(), 5, "fooba"); 227cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko EXPECT_TRUE(lookup_fooba == nullptr); 2289e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier ObjPtr<mirror::String> lookup_foobaR = intern_table.LookupStrong(soa.Self(), 6, "foobaR"); 229cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko EXPECT_TRUE(lookup_foobaR == nullptr); 230cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko // Try a hash conflict. 231cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko ASSERT_EQ(ComputeUtf16HashFromModifiedUtf8("foobar", 6), 232cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko ComputeUtf16HashFromModifiedUtf8("foobbS", 6)); 2339e868098b4a5d666570e3924518978d7abd3542eMathieu Chartier ObjPtr<mirror::String> lookup_foobbS = intern_table.LookupStrong(soa.Self(), 6, "foobbS"); 234cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko EXPECT_TRUE(lookup_foobbS == nullptr); 235cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko} 236cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko 2377e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom} // namespace art 238