1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include "intern_table-inl.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include "base/hash_set.h"
20*795d594fSAndroid Build Coastguard Worker #include "common_runtime_test.h"
21*795d594fSAndroid Build Coastguard Worker #include "dex/utf.h"
22*795d594fSAndroid Build Coastguard Worker #include "gc_root-inl.h"
23*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
24*795d594fSAndroid Build Coastguard Worker #include "mirror/object.h"
25*795d594fSAndroid Build Coastguard Worker #include "mirror/string.h"
26*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
27*795d594fSAndroid Build Coastguard Worker
28*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
29*795d594fSAndroid Build Coastguard Worker
30*795d594fSAndroid Build Coastguard Worker class InternTableTest : public CommonRuntimeTest {
31*795d594fSAndroid Build Coastguard Worker protected:
InternTableTest()32*795d594fSAndroid Build Coastguard Worker InternTableTest() {
33*795d594fSAndroid Build Coastguard Worker use_boot_image_ = true; // Make the Runtime creation cheaper.
34*795d594fSAndroid Build Coastguard Worker }
35*795d594fSAndroid Build Coastguard Worker };
36*795d594fSAndroid Build Coastguard Worker
TEST_F(InternTableTest,Intern)37*795d594fSAndroid Build Coastguard Worker TEST_F(InternTableTest, Intern) {
38*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
39*795d594fSAndroid Build Coastguard Worker InternTable intern_table;
40*795d594fSAndroid Build Coastguard Worker StackHandleScope<4> hs(soa.Self());
41*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> foo_1(hs.NewHandle(intern_table.InternStrong(3, "foo")));
42*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> foo_2(hs.NewHandle(intern_table.InternStrong(3, "foo")));
43*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> foo_3(
44*795d594fSAndroid Build Coastguard Worker hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
45*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> bar(hs.NewHandle(intern_table.InternStrong(3, "bar")));
46*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(foo_1 != nullptr);
47*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(foo_2 != nullptr);
48*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(foo_3 != nullptr);
49*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(bar != nullptr);
50*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(foo_1.Get(), foo_2.Get());
51*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(foo_1->Equals("foo"));
52*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(foo_2->Equals("foo"));
53*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(foo_3->Equals("foo"));
54*795d594fSAndroid Build Coastguard Worker EXPECT_NE(foo_1.Get(), bar.Get());
55*795d594fSAndroid Build Coastguard Worker EXPECT_NE(foo_2.Get(), bar.Get());
56*795d594fSAndroid Build Coastguard Worker EXPECT_NE(foo_3.Get(), bar.Get());
57*795d594fSAndroid Build Coastguard Worker }
58*795d594fSAndroid Build Coastguard Worker
TEST_F(InternTableTest,Size)59*795d594fSAndroid Build Coastguard Worker TEST_F(InternTableTest, Size) {
60*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
61*795d594fSAndroid Build Coastguard Worker InternTable t;
62*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(0U, t.Size());
63*795d594fSAndroid Build Coastguard Worker t.InternStrong(3, "foo");
64*795d594fSAndroid Build Coastguard Worker StackHandleScope<1> hs(soa.Self());
65*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> foo(
66*795d594fSAndroid Build Coastguard Worker hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
67*795d594fSAndroid Build Coastguard Worker t.InternWeak(foo.Get());
68*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(1U, t.Size());
69*795d594fSAndroid Build Coastguard Worker t.InternStrong(3, "bar");
70*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(2U, t.Size());
71*795d594fSAndroid Build Coastguard Worker }
72*795d594fSAndroid Build Coastguard Worker
73*795d594fSAndroid Build Coastguard Worker // Check if table indexes match on 64 and 32 bit machines.
74*795d594fSAndroid Build Coastguard Worker // This is done by ensuring hash values are the same on every machine and limited to 32-bit wide.
75*795d594fSAndroid Build Coastguard Worker // Otherwise cross compilation can cause a table to be filled on host using one indexing algorithm
76*795d594fSAndroid Build Coastguard Worker // and later on a device with different sizeof(size_t) can use another indexing algorithm.
77*795d594fSAndroid Build Coastguard Worker // Thus the table may provide wrong data.
TEST_F(InternTableTest,CrossHash)78*795d594fSAndroid Build Coastguard Worker TEST_F(InternTableTest, CrossHash) {
79*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
80*795d594fSAndroid Build Coastguard Worker InternTable t;
81*795d594fSAndroid Build Coastguard Worker
82*795d594fSAndroid Build Coastguard Worker // A string that has a negative hash value.
83*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::String> str = mirror::String::AllocFromModifiedUtf8(soa.Self(), "00000000");
84*795d594fSAndroid Build Coastguard Worker // `String::GetHashCode()` ensures that the stored hash is calculated.
85*795d594fSAndroid Build Coastguard Worker int32_t hash = str->GetHashCode();
86*795d594fSAndroid Build Coastguard Worker ASSERT_LT(hash, 0);
87*795d594fSAndroid Build Coastguard Worker
88*795d594fSAndroid Build Coastguard Worker MutexLock mu(Thread::Current(), *Locks::intern_table_lock_);
89*795d594fSAndroid Build Coastguard Worker for (InternTable::Table::InternalTable& table : t.strong_interns_.tables_) {
90*795d594fSAndroid Build Coastguard Worker // The negative hash value shall be 32-bit wide on every host.
91*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(IsUint<32>(table.set_.hashfn_(GcRoot<mirror::String>(str))));
92*795d594fSAndroid Build Coastguard Worker }
93*795d594fSAndroid Build Coastguard Worker }
94*795d594fSAndroid Build Coastguard Worker
95*795d594fSAndroid Build Coastguard Worker class TestPredicate : public IsMarkedVisitor {
96*795d594fSAndroid Build Coastguard Worker public:
IsMarked(mirror::Object * s)97*795d594fSAndroid Build Coastguard Worker mirror::Object* IsMarked(mirror::Object* s) override REQUIRES_SHARED(Locks::mutator_lock_) {
98*795d594fSAndroid Build Coastguard Worker bool erased = false;
99*795d594fSAndroid Build Coastguard Worker for (auto it = expected_.begin(), end = expected_.end(); it != end; ++it) {
100*795d594fSAndroid Build Coastguard Worker if (*it == s) {
101*795d594fSAndroid Build Coastguard Worker expected_.erase(it);
102*795d594fSAndroid Build Coastguard Worker erased = true;
103*795d594fSAndroid Build Coastguard Worker break;
104*795d594fSAndroid Build Coastguard Worker }
105*795d594fSAndroid Build Coastguard Worker }
106*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(erased);
107*795d594fSAndroid Build Coastguard Worker return nullptr;
108*795d594fSAndroid Build Coastguard Worker }
109*795d594fSAndroid Build Coastguard Worker
Expect(const mirror::String * s)110*795d594fSAndroid Build Coastguard Worker void Expect(const mirror::String* s) {
111*795d594fSAndroid Build Coastguard Worker expected_.push_back(s);
112*795d594fSAndroid Build Coastguard Worker }
113*795d594fSAndroid Build Coastguard Worker
~TestPredicate()114*795d594fSAndroid Build Coastguard Worker ~TestPredicate() {
115*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(0U, expected_.size());
116*795d594fSAndroid Build Coastguard Worker }
117*795d594fSAndroid Build Coastguard Worker
118*795d594fSAndroid Build Coastguard Worker private:
119*795d594fSAndroid Build Coastguard Worker mutable std::vector<const mirror::String*> expected_;
120*795d594fSAndroid Build Coastguard Worker };
121*795d594fSAndroid Build Coastguard Worker
TEST_F(InternTableTest,SweepInternTableWeaks)122*795d594fSAndroid Build Coastguard Worker TEST_F(InternTableTest, SweepInternTableWeaks) {
123*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
124*795d594fSAndroid Build Coastguard Worker InternTable t;
125*795d594fSAndroid Build Coastguard Worker t.InternStrong(3, "foo");
126*795d594fSAndroid Build Coastguard Worker t.InternStrong(3, "bar");
127*795d594fSAndroid Build Coastguard Worker StackHandleScope<5> hs(soa.Self());
128*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> hello(
129*795d594fSAndroid Build Coastguard Worker hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "hello")));
130*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> world(
131*795d594fSAndroid Build Coastguard Worker hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "world")));
132*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> s0(hs.NewHandle(t.InternWeak(hello.Get())));
133*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> s1(hs.NewHandle(t.InternWeak(world.Get())));
134*795d594fSAndroid Build Coastguard Worker
135*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(4U, t.Size());
136*795d594fSAndroid Build Coastguard Worker
137*795d594fSAndroid Build Coastguard Worker // We should traverse only the weaks...
138*795d594fSAndroid Build Coastguard Worker TestPredicate p;
139*795d594fSAndroid Build Coastguard Worker p.Expect(s0.Get());
140*795d594fSAndroid Build Coastguard Worker p.Expect(s1.Get());
141*795d594fSAndroid Build Coastguard Worker {
142*795d594fSAndroid Build Coastguard Worker ReaderMutexLock mu(soa.Self(), *Locks::heap_bitmap_lock_);
143*795d594fSAndroid Build Coastguard Worker t.SweepInternTableWeaks(&p);
144*795d594fSAndroid Build Coastguard Worker }
145*795d594fSAndroid Build Coastguard Worker
146*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(2U, t.Size());
147*795d594fSAndroid Build Coastguard Worker
148*795d594fSAndroid Build Coastguard Worker // Just check that we didn't corrupt the map.
149*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> still_here(
150*795d594fSAndroid Build Coastguard Worker hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "still here")));
151*795d594fSAndroid Build Coastguard Worker t.InternWeak(still_here.Get());
152*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(3U, t.Size());
153*795d594fSAndroid Build Coastguard Worker }
154*795d594fSAndroid Build Coastguard Worker
TEST_F(InternTableTest,ContainsWeak)155*795d594fSAndroid Build Coastguard Worker TEST_F(InternTableTest, ContainsWeak) {
156*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
157*795d594fSAndroid Build Coastguard Worker auto ContainsWeak = [&](InternTable& t, ObjPtr<mirror::String> s)
158*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
159*795d594fSAndroid Build Coastguard Worker return t.LookupWeak(soa.Self(), s) == s;
160*795d594fSAndroid Build Coastguard Worker };
161*795d594fSAndroid Build Coastguard Worker
162*795d594fSAndroid Build Coastguard Worker {
163*795d594fSAndroid Build Coastguard Worker // Strongs are never weak.
164*795d594fSAndroid Build Coastguard Worker InternTable t;
165*795d594fSAndroid Build Coastguard Worker StackHandleScope<2> hs(soa.Self());
166*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternStrong(3, "foo")));
167*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(ContainsWeak(t, interned_foo_1.Get()));
168*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternStrong(3, "foo")));
169*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(ContainsWeak(t, interned_foo_2.Get()));
170*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get());
171*795d594fSAndroid Build Coastguard Worker }
172*795d594fSAndroid Build Coastguard Worker
173*795d594fSAndroid Build Coastguard Worker {
174*795d594fSAndroid Build Coastguard Worker // Weaks are always weak.
175*795d594fSAndroid Build Coastguard Worker InternTable t;
176*795d594fSAndroid Build Coastguard Worker StackHandleScope<4> hs(soa.Self());
177*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> foo_1(
178*795d594fSAndroid Build Coastguard Worker hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
179*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> foo_2(
180*795d594fSAndroid Build Coastguard Worker hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
181*795d594fSAndroid Build Coastguard Worker EXPECT_NE(foo_1.Get(), foo_2.Get());
182*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternWeak(foo_1.Get())));
183*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternWeak(foo_2.Get())));
184*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(ContainsWeak(t, interned_foo_2.Get()));
185*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get());
186*795d594fSAndroid Build Coastguard Worker }
187*795d594fSAndroid Build Coastguard Worker
188*795d594fSAndroid Build Coastguard Worker {
189*795d594fSAndroid Build Coastguard Worker // A weak can be promoted to a strong.
190*795d594fSAndroid Build Coastguard Worker InternTable t;
191*795d594fSAndroid Build Coastguard Worker StackHandleScope<3> hs(soa.Self());
192*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> foo(
193*795d594fSAndroid Build Coastguard Worker hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
194*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternWeak(foo.Get())));
195*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(ContainsWeak(t, interned_foo_1.Get()));
196*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternStrong(3, "foo")));
197*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(ContainsWeak(t, interned_foo_2.Get()));
198*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get());
199*795d594fSAndroid Build Coastguard Worker }
200*795d594fSAndroid Build Coastguard Worker
201*795d594fSAndroid Build Coastguard Worker {
202*795d594fSAndroid Build Coastguard Worker // Interning a weak after a strong gets you the strong.
203*795d594fSAndroid Build Coastguard Worker InternTable t;
204*795d594fSAndroid Build Coastguard Worker StackHandleScope<3> hs(soa.Self());
205*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> interned_foo_1(hs.NewHandle(t.InternStrong(3, "foo")));
206*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(ContainsWeak(t, interned_foo_1.Get()));
207*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> foo(
208*795d594fSAndroid Build Coastguard Worker hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
209*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> interned_foo_2(hs.NewHandle(t.InternWeak(foo.Get())));
210*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(ContainsWeak(t, interned_foo_2.Get()));
211*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(interned_foo_1.Get(), interned_foo_2.Get());
212*795d594fSAndroid Build Coastguard Worker }
213*795d594fSAndroid Build Coastguard Worker }
214*795d594fSAndroid Build Coastguard Worker
TEST_F(InternTableTest,LookupStrong)215*795d594fSAndroid Build Coastguard Worker TEST_F(InternTableTest, LookupStrong) {
216*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
217*795d594fSAndroid Build Coastguard Worker InternTable intern_table;
218*795d594fSAndroid Build Coastguard Worker StackHandleScope<3> hs(soa.Self());
219*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> foo(hs.NewHandle(intern_table.InternStrong(3, "foo")));
220*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> bar(hs.NewHandle(intern_table.InternStrong(3, "bar")));
221*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> foobar(hs.NewHandle(intern_table.InternStrong(6, "foobar")));
222*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(foo != nullptr);
223*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(bar != nullptr);
224*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(foobar != nullptr);
225*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(foo->Equals("foo"));
226*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(bar->Equals("bar"));
227*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(foobar->Equals("foobar"));
228*795d594fSAndroid Build Coastguard Worker ASSERT_NE(foo.Get(), bar.Get());
229*795d594fSAndroid Build Coastguard Worker ASSERT_NE(foo.Get(), foobar.Get());
230*795d594fSAndroid Build Coastguard Worker ASSERT_NE(bar.Get(), foobar.Get());
231*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::String> lookup_foo = intern_table.LookupStrong(soa.Self(), 3, "foo");
232*795d594fSAndroid Build Coastguard Worker EXPECT_OBJ_PTR_EQ(lookup_foo, foo.Get());
233*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::String> lookup_bar = intern_table.LookupStrong(soa.Self(), 3, "bar");
234*795d594fSAndroid Build Coastguard Worker EXPECT_OBJ_PTR_EQ(lookup_bar, bar.Get());
235*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::String> lookup_foobar = intern_table.LookupStrong(soa.Self(), 6, "foobar");
236*795d594fSAndroid Build Coastguard Worker EXPECT_OBJ_PTR_EQ(lookup_foobar, foobar.Get());
237*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::String> lookup_foox = intern_table.LookupStrong(soa.Self(), 4, "foox");
238*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(lookup_foox == nullptr);
239*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::String> lookup_fooba = intern_table.LookupStrong(soa.Self(), 5, "fooba");
240*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(lookup_fooba == nullptr);
241*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::String> lookup_foobaR = intern_table.LookupStrong(soa.Self(), 6, "foobaR");
242*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(lookup_foobaR == nullptr);
243*795d594fSAndroid Build Coastguard Worker // Try a hash conflict.
244*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(ComputeUtf16HashFromModifiedUtf8("foobar", 6),
245*795d594fSAndroid Build Coastguard Worker ComputeUtf16HashFromModifiedUtf8("foobbS", 6));
246*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::String> lookup_foobbS = intern_table.LookupStrong(soa.Self(), 6, "foobbS");
247*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(lookup_foobbS == nullptr);
248*795d594fSAndroid Build Coastguard Worker }
249*795d594fSAndroid Build Coastguard Worker
TEST_F(InternTableTest,InternStrongFrozenWeak)250*795d594fSAndroid Build Coastguard Worker TEST_F(InternTableTest, InternStrongFrozenWeak) {
251*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
252*795d594fSAndroid Build Coastguard Worker InternTable intern_table;
253*795d594fSAndroid Build Coastguard Worker StackHandleScope<1> hs(soa.Self());
254*795d594fSAndroid Build Coastguard Worker Handle<mirror::String> foo(
255*795d594fSAndroid Build Coastguard Worker hs.NewHandle(mirror::String::AllocFromModifiedUtf8(soa.Self(), "foo")));
256*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(foo != nullptr);
257*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::String> weak_foo = intern_table.InternWeak(foo.Get());
258*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(weak_foo == foo.Get());
259*795d594fSAndroid Build Coastguard Worker
260*795d594fSAndroid Build Coastguard Worker intern_table.AddNewTable();
261*795d594fSAndroid Build Coastguard Worker
262*795d594fSAndroid Build Coastguard Worker ObjPtr<mirror::String> strong_foo = intern_table.InternStrong(foo.Get());
263*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(strong_foo == foo.Get());
264*795d594fSAndroid Build Coastguard Worker }
265*795d594fSAndroid Build Coastguard Worker
266*795d594fSAndroid Build Coastguard Worker } // namespace art
267