1cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier/*
2cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier * Copyright (C) 2015 The Android Open Source Project
3cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier *
4cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier * Licensed under the Apache License, Version 2.0 (the "License");
5cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier * you may not use this file except in compliance with the License.
6cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier * You may obtain a copy of the License at
7cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier *
8cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier *      http://www.apache.org/licenses/LICENSE-2.0
9cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier *
10cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier * Unless required by applicable law or agreed to in writing, software
11cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier * distributed under the License is distributed on an "AS IS" BASIS,
12cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier * See the License for the specific language governing permissions and
14cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier * limitations under the License.
15cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier */
16cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
172ff3b97500b717f69415ae474d5cfb1613cd15eeAndreas Gampe#include "class_table-inl.h"
18cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
195678db5b3a0275d04bc610236f89fac9f76b5b1eAndreas Gampe#include "base/stl_util.h"
20cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier#include "mirror/class-inl.h"
21c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe#include "oat_file.h"
22cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
23cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartiernamespace art {
24cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
251609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu ChartierClassTable::ClassTable() : lock_("Class loader classes", kClassLoaderClassesLock) {
2632cc9ee0cdffecb0ec8d80a7fd55d7dccae3a7eeMathieu Chartier  Runtime* const runtime = Runtime::Current();
2732cc9ee0cdffecb0ec8d80a7fd55d7dccae3a7eeMathieu Chartier  classes_.push_back(ClassSet(runtime->GetHashTableMinLoadFactor(),
2832cc9ee0cdffecb0ec8d80a7fd55d7dccae3a7eeMathieu Chartier                              runtime->GetHashTableMaxLoadFactor()));
29cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
30cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
31cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartiervoid ClassTable::FreezeSnapshot() {
321609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
33cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  classes_.push_back(ClassSet());
34cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
35cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
3628357fab628bd9b91749988b554977398caf9963Mathieu Chartierbool ClassTable::Contains(ObjPtr<mirror::Class> klass) {
371609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
38db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  TableSlot slot(klass);
39cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  for (ClassSet& class_set : classes_) {
40db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier    auto it = class_set.Find(slot);
41cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    if (it != class_set.end()) {
42cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier      return it->Read() == klass;
43cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    }
44cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  }
45cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return false;
46cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
47cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
4828357fab628bd9b91749988b554977398caf9963Mathieu Chartiermirror::Class* ClassTable::LookupByDescriptor(ObjPtr<mirror::Class> klass) {
491609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
50db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  TableSlot slot(klass);
51fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  for (ClassSet& class_set : classes_) {
52db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier    auto it = class_set.Find(slot);
53fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier    if (it != class_set.end()) {
54fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier      return it->Read();
55fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier    }
56fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  }
57fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  return nullptr;
58fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier}
59fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier
608de129774aeb8ad4ae0623e2d335cfd52e63f5c1Jayant Chowdhary// To take into account http://b/35845221
618de129774aeb8ad4ae0623e2d335cfd52e63f5c1Jayant Chowdhary#pragma clang diagnostic push
628de129774aeb8ad4ae0623e2d335cfd52e63f5c1Jayant Chowdhary#if __clang_major__ < 4
638de129774aeb8ad4ae0623e2d335cfd52e63f5c1Jayant Chowdhary#pragma clang diagnostic ignored "-Wunreachable-code"
648de129774aeb8ad4ae0623e2d335cfd52e63f5c1Jayant Chowdhary#endif
658de129774aeb8ad4ae0623e2d335cfd52e63f5c1Jayant Chowdhary
66cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartiermirror::Class* ClassTable::UpdateClass(const char* descriptor, mirror::Class* klass, size_t hash) {
671609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
68cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  // Should only be updating latest table.
6958c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  DescriptorHashPair pair(descriptor, hash);
7058c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  auto existing_it = classes_.back().FindWithHash(pair, hash);
71cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  if (kIsDebugBuild && existing_it == classes_.back().end()) {
72cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    for (const ClassSet& class_set : classes_) {
7358c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier      if (class_set.FindWithHash(pair, hash) != class_set.end()) {
74cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier        LOG(FATAL) << "Updating class found in frozen table " << descriptor;
75cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier      }
76cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    }
77cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    LOG(FATAL) << "Updating class not found " << descriptor;
78cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  }
79cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  mirror::Class* const existing = existing_it->Read();
80cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  CHECK_NE(existing, klass) << descriptor;
81cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  CHECK(!existing->IsResolved()) << descriptor;
822c64a837e62c2839521c89060b5bb0dcb237dddaVladimir Marko  CHECK_EQ(klass->GetStatus(), ClassStatus::kResolving) << descriptor;
83cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  CHECK(!klass->IsTemp()) << descriptor;
84cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  VerifyObject(klass);
85cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  // Update the element in the hash set with the new class. This is safe to do since the descriptor
86cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  // doesn't change.
8758c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  *existing_it = TableSlot(klass, hash);
88cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return existing;
89cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
90cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
918de129774aeb8ad4ae0623e2d335cfd52e63f5c1Jayant Chowdhary#pragma clang diagnostic pop
928de129774aeb8ad4ae0623e2d335cfd52e63f5c1Jayant Chowdhary
93c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Markosize_t ClassTable::CountDefiningLoaderClasses(ObjPtr<mirror::ClassLoader> defining_loader,
94c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko                                              const ClassSet& set) const {
95c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko  size_t count = 0;
96c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko  for (const TableSlot& root : set) {
97c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko    if (root.Read()->GetClassLoader() == defining_loader) {
98c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko      ++count;
99c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko    }
100c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko  }
101c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko  return count;
102c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko}
103c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko
104c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Markosize_t ClassTable::NumZygoteClasses(ObjPtr<mirror::ClassLoader> defining_loader) const {
1051609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
106cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  size_t sum = 0;
107cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  for (size_t i = 0; i < classes_.size() - 1; ++i) {
108c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko    sum += CountDefiningLoaderClasses(defining_loader, classes_[i]);
109cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  }
110cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return sum;
111cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
112cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
113c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Markosize_t ClassTable::NumNonZygoteClasses(ObjPtr<mirror::ClassLoader> defining_loader) const {
1141609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
115c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko  return CountDefiningLoaderClasses(defining_loader, classes_.back());
116cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
117cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
1188d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Markosize_t ClassTable::NumReferencedZygoteClasses() const {
1198d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko  ReaderMutexLock mu(Thread::Current(), lock_);
1208d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko  size_t sum = 0;
1218d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko  for (size_t i = 0; i < classes_.size() - 1; ++i) {
1228d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko    sum += classes_[i].Size();
1238d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko  }
1248d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko  return sum;
1258d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko}
1268d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko
1278d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Markosize_t ClassTable::NumReferencedNonZygoteClasses() const {
1288d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko  ReaderMutexLock mu(Thread::Current(), lock_);
1298d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko  return classes_.back().Size();
1308d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko}
1318d6768d47b66a688d35399d524ad5a5450e9d9d4Vladimir Marko
132cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartiermirror::Class* ClassTable::Lookup(const char* descriptor, size_t hash) {
13358c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  DescriptorHashPair pair(descriptor, hash);
134db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
135cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  for (ClassSet& class_set : classes_) {
13658c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    auto it = class_set.FindWithHash(pair, hash);
137cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    if (it != class_set.end()) {
138c5798bf82fc0ccd0bb90e0813d8e63df4d0576ccVladimir Marko      return it->Read();
139cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    }
140cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  }
141cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return nullptr;
142cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
143cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
144cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir MarkoObjPtr<mirror::Class> ClassTable::TryInsert(ObjPtr<mirror::Class> klass) {
145cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko  TableSlot slot(klass);
146cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko  WriterMutexLock mu(Thread::Current(), lock_);
147cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko  for (ClassSet& class_set : classes_) {
148cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko    auto it = class_set.Find(slot);
149cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko    if (it != class_set.end()) {
150cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko      return it->Read();
151cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko    }
152cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko  }
153cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko  classes_.back().Insert(slot);
154cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko  return klass;
155cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko}
156cd556b003adbb53739d4b3f43135e6a0ae69509aVladimir Marko
15728357fab628bd9b91749988b554977398caf9963Mathieu Chartiervoid ClassTable::Insert(ObjPtr<mirror::Class> klass) {
158db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  const uint32_t hash = TableSlot::HashDescriptor(klass);
1591609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
160db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  classes_.back().InsertWithHash(TableSlot(klass, hash), hash);
161cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
162cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
1636ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Markovoid ClassTable::CopyWithoutLocks(const ClassTable& source_table) {
1646ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Marko  if (kIsDebugBuild) {
1656ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Marko    for (ClassSet& class_set : classes_) {
1666ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Marko      CHECK(class_set.Empty());
1676ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Marko    }
1686ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Marko  }
1696ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Marko  for (const ClassSet& class_set : source_table.classes_) {
1706ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Marko    for (const TableSlot& slot : class_set) {
1716ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Marko      classes_.back().Insert(slot);
1726ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Marko    }
1736ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Marko  }
1746ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Marko}
1756ad2f6d0e17b8cd1fd20aeb1958196e856475e80Vladimir Marko
17628357fab628bd9b91749988b554977398caf9963Mathieu Chartiervoid ClassTable::InsertWithoutLocks(ObjPtr<mirror::Class> klass) {
177db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  const uint32_t hash = TableSlot::HashDescriptor(klass);
178db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  classes_.back().InsertWithHash(TableSlot(klass, hash), hash);
179496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier}
180496577fb4d6d7baea9c093d35d17e208c831bbcaMathieu Chartier
18128357fab628bd9b91749988b554977398caf9963Mathieu Chartiervoid ClassTable::InsertWithHash(ObjPtr<mirror::Class> klass, size_t hash) {
1821609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
18358c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  classes_.back().InsertWithHash(TableSlot(klass, hash), hash);
184cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
185cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
186cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartierbool ClassTable::Remove(const char* descriptor) {
18758c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  DescriptorHashPair pair(descriptor, ComputeModifiedUtf8Hash(descriptor));
188db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
189cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  for (ClassSet& class_set : classes_) {
19058c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    auto it = class_set.Find(pair);
191cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    if (it != class_set.end()) {
192cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier      class_set.Erase(it);
193cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier      return true;
194cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    }
195cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  }
196cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return false;
197cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
198cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
19958c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartieruint32_t ClassTable::ClassDescriptorHashEquals::operator()(const TableSlot& slot)
200cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    const {
201cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  std::string temp;
20258c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  return ComputeModifiedUtf8Hash(slot.Read()->GetDescriptor(&temp));
203cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
204cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
20558c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartierbool ClassTable::ClassDescriptorHashEquals::operator()(const TableSlot& a,
20658c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier                                                       const TableSlot& b) const {
20758c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  if (a.Hash() != b.Hash()) {
20858c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    std::string temp;
20958c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    DCHECK(!a.Read()->DescriptorEquals(b.Read()->GetDescriptor(&temp)));
21058c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    return false;
21158c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  }
212cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  std::string temp;
213cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return a.Read()->DescriptorEquals(b.Read()->GetDescriptor(&temp));
214cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
215cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
21658c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartierbool ClassTable::ClassDescriptorHashEquals::operator()(const TableSlot& a,
21758c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier                                                       const DescriptorHashPair& b) const {
21858c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  if (!a.MaskedHashEquals(b.second)) {
21958c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    DCHECK(!a.Read()->DescriptorEquals(b.first));
22058c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    return false;
22158c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  }
22258c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  return a.Read()->DescriptorEquals(b.first);
223cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
224cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
22558c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartieruint32_t ClassTable::ClassDescriptorHashEquals::operator()(const DescriptorHashPair& pair) const {
22658c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  return ComputeModifiedUtf8Hash(pair.first);
227cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
228cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
229bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartierbool ClassTable::InsertStrongRoot(ObjPtr<mirror::Object> obj) {
2301609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
231c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier  DCHECK(obj != nullptr);
232c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier  for (GcRoot<mirror::Object>& root : strong_roots_) {
233c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier    if (root.Read() == obj) {
23400310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier      return false;
23500310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier    }
23600310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier  }
237c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier  strong_roots_.push_back(GcRoot<mirror::Object>(obj));
238aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  // If `obj` is a dex cache associated with a new oat file with GC roots, add it to oat_files_.
239aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  if (obj->IsDexCache()) {
240bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier    const DexFile* dex_file = ObjPtr<mirror::DexCache>::DownCast(obj)->GetDexFile();
241aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    if (dex_file != nullptr && dex_file->GetOatDexFile() != nullptr) {
242aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko      const OatFile* oat_file = dex_file->GetOatDexFile()->GetOatFile();
2431b868498a176705b867e2572cc1bcbd58dbd62d6Mathieu Chartier      if (oat_file != nullptr && !oat_file->GetBssGcRoots().empty()) {
2441bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Marko        InsertOatFileLocked(oat_file);  // Ignore return value.
245aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko      }
246aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    }
247aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  }
24800310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier  return true;
24900310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier}
25000310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier
2511bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Markobool ClassTable::InsertOatFile(const OatFile* oat_file) {
2521bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Marko  WriterMutexLock mu(Thread::Current(), lock_);
2531bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Marko  return InsertOatFileLocked(oat_file);
2541bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Marko}
2551bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Marko
2561bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Markobool ClassTable::InsertOatFileLocked(const OatFile* oat_file) {
2571bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Marko  if (ContainsElement(oat_files_, oat_file)) {
2581bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Marko    return false;
2591bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Marko  }
2601bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Marko  oat_files_.push_back(oat_file);
2611bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Marko  return true;
2621bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Marko}
2631bc4b178590fa204265363a0207f1388e8bd6d15Vladimir Marko
264208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartiersize_t ClassTable::WriteToMemory(uint8_t* ptr) const {
2651609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
26641dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  ClassSet combined;
26741dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  // Combine all the class sets in case there are multiple, also adjusts load factor back to
26841dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  // default in case classes were pruned.
26941dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  for (const ClassSet& class_set : classes_) {
27058c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    for (const TableSlot& root : class_set) {
27141dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier      combined.Insert(root);
272208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier    }
273208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier  }
27441dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  const size_t ret = combined.WriteToMemory(ptr);
27541dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  // Sanity check.
27641dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  if (kIsDebugBuild && ptr != nullptr) {
27741dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier    size_t read_count;
27841dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier    ClassSet class_set(ptr, /*make copy*/false, &read_count);
27941dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier    class_set.Verify();
28041dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  }
281208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier  return ret;
282208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier}
283208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier
284208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartiersize_t ClassTable::ReadFromMemory(uint8_t* ptr) {
285208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier  size_t read_count = 0;
28688027bd6810b9a5b785dba5396eec5301e4540b2Mathieu Chartier  AddClassSet(ClassSet(ptr, /*make copy*/false, &read_count));
287208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier  return read_count;
288208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier}
289208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier
29088027bd6810b9a5b785dba5396eec5301e4540b2Mathieu Chartiervoid ClassTable::AddClassSet(ClassSet&& set) {
2911609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
29288027bd6810b9a5b785dba5396eec5301e4540b2Mathieu Chartier  classes_.insert(classes_.begin(), std::move(set));
29388027bd6810b9a5b785dba5396eec5301e4540b2Mathieu Chartier}
29488027bd6810b9a5b785dba5396eec5301e4540b2Mathieu Chartier
295c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartiervoid ClassTable::ClearStrongRoots() {
296c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
297aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  oat_files_.clear();
298c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier  strong_roots_.clear();
299c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier}
30058c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier
301db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu ChartierClassTable::TableSlot::TableSlot(ObjPtr<mirror::Class> klass)
302db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier    : TableSlot(klass, HashDescriptor(klass)) {}
303db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier
304db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartieruint32_t ClassTable::TableSlot::HashDescriptor(ObjPtr<mirror::Class> klass) {
30558c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  std::string temp;
306db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  return ComputeModifiedUtf8Hash(klass->GetDescriptor(&temp));
30758c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier}
30858c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier
309cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}  // namespace art
310