1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2016 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 "class_table-inl.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include "art_field-inl.h"
20*795d594fSAndroid Build Coastguard Worker #include "art_method-inl.h"
21*795d594fSAndroid Build Coastguard Worker #include "class_linker-inl.h"
22*795d594fSAndroid Build Coastguard Worker #include "common_runtime_test.h"
23*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
24*795d594fSAndroid Build Coastguard Worker #include "gc/accounting/card_table-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "gc/heap.h"
26*795d594fSAndroid Build Coastguard Worker #include "handle_scope-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "mirror/class-alloc-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "obj_ptr.h"
29*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
30*795d594fSAndroid Build Coastguard Worker
31*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
32*795d594fSAndroid Build Coastguard Worker namespace mirror {
33*795d594fSAndroid Build Coastguard Worker
34*795d594fSAndroid Build Coastguard Worker class CollectRootVisitor {
35*795d594fSAndroid Build Coastguard Worker public:
CollectRootVisitor()36*795d594fSAndroid Build Coastguard Worker CollectRootVisitor() {}
37*795d594fSAndroid Build Coastguard Worker
38*795d594fSAndroid Build Coastguard Worker template <class MirrorType>
VisitRootIfNonNull(GcRoot<MirrorType> & root) const39*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void VisitRootIfNonNull(GcRoot<MirrorType>& root) const
40*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
41*795d594fSAndroid Build Coastguard Worker if (!root.IsNull()) {
42*795d594fSAndroid Build Coastguard Worker VisitRoot(root);
43*795d594fSAndroid Build Coastguard Worker }
44*795d594fSAndroid Build Coastguard Worker }
45*795d594fSAndroid Build Coastguard Worker
46*795d594fSAndroid Build Coastguard Worker template <class MirrorType>
VisitRootIfNonNull(mirror::CompressedReference<MirrorType> * root) const47*795d594fSAndroid Build Coastguard Worker ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<MirrorType>* root) const
48*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
49*795d594fSAndroid Build Coastguard Worker if (!root->IsNull()) {
50*795d594fSAndroid Build Coastguard Worker VisitRoot(root);
51*795d594fSAndroid Build Coastguard Worker }
52*795d594fSAndroid Build Coastguard Worker }
53*795d594fSAndroid Build Coastguard Worker
54*795d594fSAndroid Build Coastguard Worker template <class MirrorType>
VisitRoot(GcRoot<MirrorType> & root) const55*795d594fSAndroid Build Coastguard Worker void VisitRoot(GcRoot<MirrorType>& root) const REQUIRES_SHARED(Locks::mutator_lock_) {
56*795d594fSAndroid Build Coastguard Worker VisitRoot(root.AddressWithoutBarrier());
57*795d594fSAndroid Build Coastguard Worker }
58*795d594fSAndroid Build Coastguard Worker
59*795d594fSAndroid Build Coastguard Worker template <class MirrorType>
VisitRoot(mirror::CompressedReference<MirrorType> * root) const60*795d594fSAndroid Build Coastguard Worker void VisitRoot(mirror::CompressedReference<MirrorType>* root) const
61*795d594fSAndroid Build Coastguard Worker REQUIRES_SHARED(Locks::mutator_lock_) {
62*795d594fSAndroid Build Coastguard Worker roots_.insert(root->AsMirrorPtr());
63*795d594fSAndroid Build Coastguard Worker }
64*795d594fSAndroid Build Coastguard Worker
65*795d594fSAndroid Build Coastguard Worker mutable std::set<mirror::Object*> roots_;
66*795d594fSAndroid Build Coastguard Worker };
67*795d594fSAndroid Build Coastguard Worker
68*795d594fSAndroid Build Coastguard Worker
69*795d594fSAndroid Build Coastguard Worker class ClassTableTest : public CommonRuntimeTest {
70*795d594fSAndroid Build Coastguard Worker protected:
ClassTableTest()71*795d594fSAndroid Build Coastguard Worker ClassTableTest() {
72*795d594fSAndroid Build Coastguard Worker use_boot_image_ = true; // Make the Runtime creation cheaper.
73*795d594fSAndroid Build Coastguard Worker }
74*795d594fSAndroid Build Coastguard Worker };
75*795d594fSAndroid Build Coastguard Worker
TEST_F(ClassTableTest,ClassTable)76*795d594fSAndroid Build Coastguard Worker TEST_F(ClassTableTest, ClassTable) {
77*795d594fSAndroid Build Coastguard Worker ScopedObjectAccess soa(Thread::Current());
78*795d594fSAndroid Build Coastguard Worker jobject jclass_loader = LoadDex("XandY");
79*795d594fSAndroid Build Coastguard Worker VariableSizedHandleScope hs(soa.Self());
80*795d594fSAndroid Build Coastguard Worker Handle<ClassLoader> class_loader(hs.NewHandle(soa.Decode<ClassLoader>(jclass_loader)));
81*795d594fSAndroid Build Coastguard Worker const char* descriptor_x = "LX;";
82*795d594fSAndroid Build Coastguard Worker const char* descriptor_y = "LY;";
83*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_X = hs.NewHandle(FindClass(descriptor_x, class_loader));
84*795d594fSAndroid Build Coastguard Worker Handle<mirror::Class> h_Y = hs.NewHandle(FindClass(descriptor_y, class_loader));
85*795d594fSAndroid Build Coastguard Worker Handle<mirror::Object> obj_X = hs.NewHandle(h_X->AllocObject(soa.Self()));
86*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(obj_X != nullptr);
87*795d594fSAndroid Build Coastguard Worker ClassTable table;
88*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 0u);
89*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 0u);
90*795d594fSAndroid Build Coastguard Worker
91*795d594fSAndroid Build Coastguard Worker // Add h_X to the class table.
92*795d594fSAndroid Build Coastguard Worker table.Insert(h_X.Get());
93*795d594fSAndroid Build Coastguard Worker EXPECT_OBJ_PTR_EQ(table.LookupByDescriptor(h_X.Get()), h_X.Get());
94*795d594fSAndroid Build Coastguard Worker EXPECT_OBJ_PTR_EQ(table.Lookup(descriptor_x, ComputeModifiedUtf8Hash(descriptor_x)), h_X.Get());
95*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(table.Lookup("NOT_THERE", ComputeModifiedUtf8Hash("NOT_THERE")) == nullptr);
96*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 0u);
97*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 1u);
98*795d594fSAndroid Build Coastguard Worker
99*795d594fSAndroid Build Coastguard Worker // Create the zygote snapshot and ensure the accounting is correct.
100*795d594fSAndroid Build Coastguard Worker table.FreezeSnapshot();
101*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 1u);
102*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 0u);
103*795d594fSAndroid Build Coastguard Worker
104*795d594fSAndroid Build Coastguard Worker // Test inserting and related lookup functions.
105*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(table.LookupByDescriptor(h_Y.Get()) == nullptr);
106*795d594fSAndroid Build Coastguard Worker table.Insert(h_Y.Get());
107*795d594fSAndroid Build Coastguard Worker EXPECT_OBJ_PTR_EQ(table.LookupByDescriptor(h_X.Get()), h_X.Get());
108*795d594fSAndroid Build Coastguard Worker EXPECT_OBJ_PTR_EQ(table.LookupByDescriptor(h_Y.Get()), h_Y.Get());
109*795d594fSAndroid Build Coastguard Worker
110*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(table.NumZygoteClasses(class_loader.Get()), 1u);
111*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(table.NumNonZygoteClasses(class_loader.Get()), 1u);
112*795d594fSAndroid Build Coastguard Worker
113*795d594fSAndroid Build Coastguard Worker // Test adding / clearing strong roots.
114*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(table.InsertStrongRoot(obj_X.Get()));
115*795d594fSAndroid Build Coastguard Worker EXPECT_FALSE(table.InsertStrongRoot(obj_X.Get()));
116*795d594fSAndroid Build Coastguard Worker table.ClearStrongRoots();
117*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(table.InsertStrongRoot(obj_X.Get()));
118*795d594fSAndroid Build Coastguard Worker
119*795d594fSAndroid Build Coastguard Worker // Collect all the roots and make sure there is nothing missing.
120*795d594fSAndroid Build Coastguard Worker CollectRootVisitor roots;
121*795d594fSAndroid Build Coastguard Worker table.VisitRoots(roots);
122*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(roots.roots_.find(h_X.Get()) != roots.roots_.end());
123*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(roots.roots_.find(h_Y.Get()) != roots.roots_.end());
124*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(roots.roots_.find(obj_X.Get()) != roots.roots_.end());
125*795d594fSAndroid Build Coastguard Worker
126*795d594fSAndroid Build Coastguard Worker // Checks that vising only classes works.
127*795d594fSAndroid Build Coastguard Worker std::set<mirror::Class*> classes;
128*795d594fSAndroid Build Coastguard Worker table.Visit([&classes](ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
129*795d594fSAndroid Build Coastguard Worker classes.insert(klass.Ptr());
130*795d594fSAndroid Build Coastguard Worker return true;
131*795d594fSAndroid Build Coastguard Worker });
132*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(classes.find(h_X.Get()) != classes.end());
133*795d594fSAndroid Build Coastguard Worker EXPECT_TRUE(classes.find(h_Y.Get()) != classes.end());
134*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(classes.size(), 2u);
135*795d594fSAndroid Build Coastguard Worker classes.clear();
136*795d594fSAndroid Build Coastguard Worker table.Visit([&classes](ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
137*795d594fSAndroid Build Coastguard Worker classes.insert(klass.Ptr());
138*795d594fSAndroid Build Coastguard Worker // Return false to exit the Visit early.
139*795d594fSAndroid Build Coastguard Worker return false;
140*795d594fSAndroid Build Coastguard Worker });
141*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(classes.size(), 1u);
142*795d594fSAndroid Build Coastguard Worker
143*795d594fSAndroid Build Coastguard Worker // Test that reading a class set from memory works.
144*795d594fSAndroid Build Coastguard Worker ClassTable::ClassSet temp_set;
145*795d594fSAndroid Build Coastguard Worker table.Visit([&temp_set](ObjPtr<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_) {
146*795d594fSAndroid Build Coastguard Worker temp_set.insert(ClassTable::TableSlot(klass));
147*795d594fSAndroid Build Coastguard Worker return true;
148*795d594fSAndroid Build Coastguard Worker });
149*795d594fSAndroid Build Coastguard Worker const size_t count = temp_set.WriteToMemory(nullptr);
150*795d594fSAndroid Build Coastguard Worker std::unique_ptr<uint8_t[]> buffer(new uint8_t[count]());
151*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(temp_set.WriteToMemory(&buffer[0]), count);
152*795d594fSAndroid Build Coastguard Worker ClassTable table2;
153*795d594fSAndroid Build Coastguard Worker size_t count2 = table2.ReadFromMemory(&buffer[0]);
154*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(count, count2);
155*795d594fSAndroid Build Coastguard Worker // Strong roots are not serialized, only classes.
156*795d594fSAndroid Build Coastguard Worker EXPECT_OBJ_PTR_EQ(table2.LookupByDescriptor(h_X.Get()), h_X.Get());
157*795d594fSAndroid Build Coastguard Worker EXPECT_OBJ_PTR_EQ(table2.LookupByDescriptor(h_Y.Get()), h_Y.Get());
158*795d594fSAndroid Build Coastguard Worker
159*795d594fSAndroid Build Coastguard Worker // TODO: Add tests for UpdateClass, InsertOatFile.
160*795d594fSAndroid Build Coastguard Worker }
161*795d594fSAndroid Build Coastguard Worker
162*795d594fSAndroid Build Coastguard Worker } // namespace mirror
163*795d594fSAndroid Build Coastguard Worker } // namespace art
164