blob: 3ed1c9540d6de147237c499379fb6ae0a13b91a1 [file] [log] [blame]
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "class_table.h"
18
19#include "mirror/class-inl.h"
20
21namespace art {
22
23ClassTable::ClassTable() {
Mathieu Chartier32cc9ee2015-10-15 09:19:15 -070024 Runtime* const runtime = Runtime::Current();
25 classes_.push_back(ClassSet(runtime->GetHashTableMinLoadFactor(),
26 runtime->GetHashTableMaxLoadFactor()));
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070027}
28
29void ClassTable::FreezeSnapshot() {
30 classes_.push_back(ClassSet());
31}
32
33bool ClassTable::Contains(mirror::Class* klass) {
34 for (ClassSet& class_set : classes_) {
35 auto it = class_set.Find(GcRoot<mirror::Class>(klass));
36 if (it != class_set.end()) {
37 return it->Read() == klass;
38 }
39 }
40 return false;
41}
42
43mirror::Class* ClassTable::UpdateClass(const char* descriptor, mirror::Class* klass, size_t hash) {
44 // Should only be updating latest table.
45 auto existing_it = classes_.back().FindWithHash(descriptor, hash);
46 if (kIsDebugBuild && existing_it == classes_.back().end()) {
47 for (const ClassSet& class_set : classes_) {
48 if (class_set.FindWithHash(descriptor, hash) != class_set.end()) {
49 LOG(FATAL) << "Updating class found in frozen table " << descriptor;
50 }
51 }
52 LOG(FATAL) << "Updating class not found " << descriptor;
53 }
54 mirror::Class* const existing = existing_it->Read();
55 CHECK_NE(existing, klass) << descriptor;
56 CHECK(!existing->IsResolved()) << descriptor;
57 CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusResolving) << descriptor;
58 CHECK(!klass->IsTemp()) << descriptor;
59 VerifyObject(klass);
60 // Update the element in the hash set with the new class. This is safe to do since the descriptor
61 // doesn't change.
62 *existing_it = GcRoot<mirror::Class>(klass);
63 return existing;
64}
65
Mathieu Chartiere0671ce2015-07-28 17:23:28 -070066bool ClassTable::Visit(ClassVisitor* visitor) {
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070067 for (ClassSet& class_set : classes_) {
68 for (GcRoot<mirror::Class>& root : class_set) {
Mathieu Chartiere0671ce2015-07-28 17:23:28 -070069 if (!visitor->Visit(root.Read())) {
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -070070 return false;
71 }
72 }
73 }
74 return true;
75}
76
77size_t ClassTable::NumZygoteClasses() const {
78 size_t sum = 0;
79 for (size_t i = 0; i < classes_.size() - 1; ++i) {
80 sum += classes_[i].Size();
81 }
82 return sum;
83}
84
85size_t ClassTable::NumNonZygoteClasses() const {
86 return classes_.back().Size();
87}
88
89mirror::Class* ClassTable::Lookup(const char* descriptor, size_t hash) {
90 for (ClassSet& class_set : classes_) {
91 auto it = class_set.FindWithHash(descriptor, hash);
92 if (it != class_set.end()) {
93 return it->Read();
94 }
95 }
96 return nullptr;
97}
98
99void ClassTable::Insert(mirror::Class* klass) {
100 classes_.back().Insert(GcRoot<mirror::Class>(klass));
101}
102
103void ClassTable::InsertWithHash(mirror::Class* klass, size_t hash) {
104 classes_.back().InsertWithHash(GcRoot<mirror::Class>(klass), hash);
105}
106
107bool ClassTable::Remove(const char* descriptor) {
108 for (ClassSet& class_set : classes_) {
109 auto it = class_set.Find(descriptor);
110 if (it != class_set.end()) {
111 class_set.Erase(it);
112 return true;
113 }
114 }
115 return false;
116}
117
118std::size_t ClassTable::ClassDescriptorHashEquals::operator()(const GcRoot<mirror::Class>& root)
119 const {
120 std::string temp;
121 return ComputeModifiedUtf8Hash(root.Read()->GetDescriptor(&temp));
122}
123
124bool ClassTable::ClassDescriptorHashEquals::operator()(const GcRoot<mirror::Class>& a,
125 const GcRoot<mirror::Class>& b) const {
126 DCHECK_EQ(a.Read()->GetClassLoader(), b.Read()->GetClassLoader());
127 std::string temp;
128 return a.Read()->DescriptorEquals(b.Read()->GetDescriptor(&temp));
129}
130
131bool ClassTable::ClassDescriptorHashEquals::operator()(const GcRoot<mirror::Class>& a,
132 const char* descriptor) const {
133 return a.Read()->DescriptorEquals(descriptor);
134}
135
136std::size_t ClassTable::ClassDescriptorHashEquals::operator()(const char* descriptor) const {
137 return ComputeModifiedUtf8Hash(descriptor);
138}
139
Mathieu Chartier00310e02015-10-17 12:46:42 -0700140bool ClassTable::InsertDexFile(mirror::Object* dex_file) {
141 DCHECK(dex_file != nullptr);
142 for (GcRoot<mirror::Object>& root : dex_files_) {
143 if (root.Read() == dex_file) {
144 return false;
145 }
146 }
147 dex_files_.push_back(GcRoot<mirror::Object>(dex_file));
148 return true;
149}
150
Mathieu Chartiercc5ebdf2015-07-27 11:19:43 -0700151} // namespace art