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 19a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstrom#include "common_runtime_test.h" 202dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object.h" 21eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier#include "handle_scope-inl.h" 22e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "mirror/string.h" 23e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers#include "scoped_thread_state_change.h" 247e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 257e93b50433cde2a44d99212e8040299bde498546Brian Carlstromnamespace art { 267e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 27a1ce1fef2d49d1d537776a5308ace7102a815fe5Brian Carlstromclass InternTableTest : public CommonRuntimeTest {}; 287e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 297e93b50433cde2a44d99212e8040299bde498546Brian CarlstromTEST_F(InternTableTest, Intern) { 3000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 317e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom InternTable intern_table; 32eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<4> hs(soa.Self()); 33eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo_1(hs.NewHandle(intern_table.InternStrong(3, "foo"))); 34eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo_2(hs.NewHandle(intern_table.InternStrong(3, "foo"))); 35eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo_3( 36eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"))); 37eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> bar(hs.NewHandle(intern_table.InternStrong(3, "bar"))); 387e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom EXPECT_TRUE(foo_1->Equals("foo")); 397e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom EXPECT_TRUE(foo_2->Equals("foo")); 407e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom EXPECT_TRUE(foo_3->Equals("foo")); 412cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier EXPECT_TRUE(foo_1.Get() != nullptr); 422cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier EXPECT_TRUE(foo_2.Get() != nullptr); 43eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_EQ(foo_1.Get(), foo_2.Get()); 44eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_NE(foo_1.Get(), bar.Get()); 45eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_NE(foo_2.Get(), bar.Get()); 46eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_NE(foo_3.Get(), bar.Get()); 477e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom} 487e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom 49cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott HughesTEST_F(InternTableTest, Size) { 5000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 51cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes InternTable t; 52cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes EXPECT_EQ(0U, t.Size()); 53cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes t.InternStrong(3, "foo"); 54eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<1> hs(soa.Self()); 55eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo( 56eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"))); 57eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier t.InternWeak(foo.Get()); 58cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes EXPECT_EQ(1U, t.Size()); 59cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes t.InternStrong(3, "bar"); 60cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes EXPECT_EQ(2U, t.Size()); 61cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes} 62cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 63c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughesclass TestPredicate { 64410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes public: 652dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers bool IsMarked(const mirror::Object* s) const { 66410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes bool erased = false; 6702e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier for (auto it = expected_.begin(), end = expected_.end(); it != end; ++it) { 68410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes if (*it == s) { 69410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes expected_.erase(it); 70410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes erased = true; 71410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes break; 72410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes } 73cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes } 74410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes EXPECT_TRUE(erased); 75c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes return false; 76cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes } 77410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes 782dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers void Expect(const mirror::String* s) { 79410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes expected_.push_back(s); 80410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes } 81410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes 82410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes ~TestPredicate() { 83410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes EXPECT_EQ(0U, expected_.size()); 84410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes } 85410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes 86410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes private: 872dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers mutable std::vector<const mirror::String*> expected_; 88410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes}; 89cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 9083c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartiermirror::Object* IsMarkedSweepingCallback(mirror::Object* object, void* arg) { 916aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier if (reinterpret_cast<TestPredicate*>(arg)->IsMarked(object)) { 926aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier return object; 936aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier } 946aa3df965395566ed6a4fec4af37c2b7577992e9Mathieu Chartier return nullptr; 95c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes} 96c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott Hughes 97c33a32bccc4c66ed82ce3a580b16636399385cb4Elliott HughesTEST_F(InternTableTest, SweepInternTableWeaks) { 9800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 99cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes InternTable t; 100cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes t.InternStrong(3, "foo"); 101cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes t.InternStrong(3, "bar"); 102eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<5> hs(soa.Self()); 103eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> hello( 104eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello"))); 105eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> world( 106eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "world"))); 107eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> s0(hs.NewHandle(t.InternWeak(hello.Get()))); 108eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> s1(hs.NewHandle(t.InternWeak(world.Get()))); 109cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 110cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes EXPECT_EQ(4U, t.Size()); 111cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 112cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes // We should traverse only the weaks... 113410c0c876f326e14c176a39ba21fc4dd3f7db8abElliott Hughes TestPredicate p; 114eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier p.Expect(s0.Get()); 115eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier p.Expect(s1.Get()); 11600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers { 1171f5393447b9f45be7918042d9ee7b521376de866Ian Rogers ReaderMutexLock mu(soa.Self(), *Locks::heap_bitmap_lock_); 11883c8ee000d525017ead8753fce6bc1020249b96aMathieu Chartier t.SweepInternTableWeaks(IsMarkedSweepingCallback, &p); 11900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 120cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 121cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes EXPECT_EQ(2U, t.Size()); 122cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 123e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes // Just check that we didn't corrupt the map. 124eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> still_here( 125eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "still here"))); 126eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier t.InternWeak(still_here.Get()); 127cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes EXPECT_EQ(3U, t.Size()); 128cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes} 129cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 130cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott HughesTEST_F(InternTableTest, ContainsWeak) { 13100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers ScopedObjectAccess soa(Thread::Current()); 132cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes { 133cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes // Strongs are never weak. 134cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes InternTable t; 135eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<2> hs(soa.Self()); 136eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternStrong(3, "foo"))); 137eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_FALSE(t.ContainsWeak(interned_foo_1.Get())); 138eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternStrong(3, "foo"))); 139eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_FALSE(t.ContainsWeak(interned_foo_2.Get())); 140eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get()); 141cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes } 142cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 143cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes { 144cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes // Weaks are always weak. 145cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes InternTable t; 146eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<4> hs(soa.Self()); 147eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo_1( 148eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"))); 149eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo_2( 150eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"))); 151eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_NE(foo_1.Get(), foo_2.Get()); 152eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternWeak(foo_1.Get()))); 153eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternWeak(foo_2.Get()))); 154eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_TRUE(t.ContainsWeak(interned_foo_2.Get())); 155eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get()); 156cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes } 157cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 158cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes { 159cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes // A weak can be promoted to a strong. 160cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes InternTable t; 161eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<3> hs(soa.Self()); 162eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo( 163eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"))); 164eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternWeak(foo.Get()))); 165eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_TRUE(t.ContainsWeak(interned_foo_1.Get())); 166eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternStrong(3, "foo"))); 167eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_FALSE(t.ContainsWeak(interned_foo_2.Get())); 168eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get()); 169cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes } 170cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 171cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes { 172cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes // Interning a weak after a strong gets you the strong. 173cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes InternTable t; 174eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier StackHandleScope<3> hs(soa.Self()); 175eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternStrong(3, "foo"))); 176eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_FALSE(t.ContainsWeak(interned_foo_1.Get())); 177eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> foo( 178eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo"))); 179eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternWeak(foo.Get()))); 180eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_FALSE(t.ContainsWeak(interned_foo_2.Get())); 181eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get()); 182cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes } 183cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes} 184cf4c6c41b0084dc4567ff709fb8ce9ebd72b26acElliott Hughes 1857e93b50433cde2a44d99212e8040299bde498546Brian Carlstrom} // namespace art 186