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