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
17cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier#include "class_table.h"
18cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
19cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier#include "mirror/class-inl.h"
20cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
21cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartiernamespace art {
22cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
231609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu ChartierClassTable::ClassTable() : lock_("Class loader classes", kClassLoaderClassesLock) {
2432cc9ee0cdffecb0ec8d80a7fd55d7dccae3a7eeMathieu Chartier  Runtime* const runtime = Runtime::Current();
2532cc9ee0cdffecb0ec8d80a7fd55d7dccae3a7eeMathieu Chartier  classes_.push_back(ClassSet(runtime->GetHashTableMinLoadFactor(),
2632cc9ee0cdffecb0ec8d80a7fd55d7dccae3a7eeMathieu Chartier                              runtime->GetHashTableMaxLoadFactor()));
27cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
28cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
29cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartiervoid ClassTable::FreezeSnapshot() {
301609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
31cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  classes_.push_back(ClassSet());
32cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
33cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
34cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartierbool ClassTable::Contains(mirror::Class* klass) {
351609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
36cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  for (ClassSet& class_set : classes_) {
37cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    auto it = class_set.Find(GcRoot<mirror::Class>(klass));
38cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    if (it != class_set.end()) {
39cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier      return it->Read() == klass;
40cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    }
41cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  }
42cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return false;
43cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
44cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
45fbc31087932a65e036a153afab3049dc5298656aMathieu Chartiermirror::Class* ClassTable::LookupByDescriptor(mirror::Class* klass) {
461609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
47fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  for (ClassSet& class_set : classes_) {
48fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier    auto it = class_set.Find(GcRoot<mirror::Class>(klass));
49fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier    if (it != class_set.end()) {
50fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier      return it->Read();
51fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier    }
52fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  }
53fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier  return nullptr;
54fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier}
55fbc31087932a65e036a153afab3049dc5298656aMathieu Chartier
56cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartiermirror::Class* ClassTable::UpdateClass(const char* descriptor, mirror::Class* klass, size_t hash) {
571609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
58cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  // Should only be updating latest table.
59cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  auto existing_it = classes_.back().FindWithHash(descriptor, hash);
60cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  if (kIsDebugBuild && existing_it == classes_.back().end()) {
61cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    for (const ClassSet& class_set : classes_) {
62cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier      if (class_set.FindWithHash(descriptor, hash) != class_set.end()) {
63cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier        LOG(FATAL) << "Updating class found in frozen table " << descriptor;
64cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier      }
65cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    }
66cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    LOG(FATAL) << "Updating class not found " << descriptor;
67cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  }
68cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  mirror::Class* const existing = existing_it->Read();
69cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  CHECK_NE(existing, klass) << descriptor;
70cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  CHECK(!existing->IsResolved()) << descriptor;
71cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusResolving) << descriptor;
72cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  CHECK(!klass->IsTemp()) << descriptor;
73cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  VerifyObject(klass);
74cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  // Update the element in the hash set with the new class. This is safe to do since the descriptor
75cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  // doesn't change.
76cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  *existing_it = GcRoot<mirror::Class>(klass);
77cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return existing;
78cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
79cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
80cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartiersize_t ClassTable::NumZygoteClasses() const {
811609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
82cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  size_t sum = 0;
83cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  for (size_t i = 0; i < classes_.size() - 1; ++i) {
84cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    sum += classes_[i].Size();
85cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  }
86cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return sum;
87cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
88cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
89cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartiersize_t ClassTable::NumNonZygoteClasses() const {
901609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
91cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return classes_.back().Size();
92cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
93cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
94cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartiermirror::Class* ClassTable::Lookup(const char* descriptor, size_t hash) {
951609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
96cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  for (ClassSet& class_set : classes_) {
97cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    auto it = class_set.FindWithHash(descriptor, hash);
98cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    if (it != class_set.end()) {
99cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier     return it->Read();
100cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    }
101cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  }
102cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return nullptr;
103cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
104cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
105cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartiervoid ClassTable::Insert(mirror::Class* klass) {
1061609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
107cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  classes_.back().Insert(GcRoot<mirror::Class>(klass));
108cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
109cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
1104e9c4e746617bad6a012d799d2f5cf9e01d24ea2Mathieu Chartiervoid ClassTable::InsertWithoutLocks(mirror::Class* klass) {
1114e9c4e746617bad6a012d799d2f5cf9e01d24ea2Mathieu Chartier  classes_.back().Insert(GcRoot<mirror::Class>(klass));
1124e9c4e746617bad6a012d799d2f5cf9e01d24ea2Mathieu Chartier}
1134e9c4e746617bad6a012d799d2f5cf9e01d24ea2Mathieu Chartier
114cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartiervoid ClassTable::InsertWithHash(mirror::Class* klass, size_t hash) {
1151609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
116cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  classes_.back().InsertWithHash(GcRoot<mirror::Class>(klass), hash);
117cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
118cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
119cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartierbool ClassTable::Remove(const char* descriptor) {
1201609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
121cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  for (ClassSet& class_set : classes_) {
122cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    auto it = class_set.Find(descriptor);
123cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    if (it != class_set.end()) {
124cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier      class_set.Erase(it);
125cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier      return true;
126cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    }
127cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  }
128cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return false;
129cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
130cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
131208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartieruint32_t ClassTable::ClassDescriptorHashEquals::operator()(const GcRoot<mirror::Class>& root)
132cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier    const {
133cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  std::string temp;
134cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return ComputeModifiedUtf8Hash(root.Read()->GetDescriptor(&temp));
135cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
136cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
137cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartierbool ClassTable::ClassDescriptorHashEquals::operator()(const GcRoot<mirror::Class>& a,
138cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier                                                       const GcRoot<mirror::Class>& b) const {
139cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  DCHECK_EQ(a.Read()->GetClassLoader(), b.Read()->GetClassLoader());
140cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  std::string temp;
141cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return a.Read()->DescriptorEquals(b.Read()->GetDescriptor(&temp));
142cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
143cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
144cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartierbool ClassTable::ClassDescriptorHashEquals::operator()(const GcRoot<mirror::Class>& a,
145cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier                                                       const char* descriptor) const {
146cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return a.Read()->DescriptorEquals(descriptor);
147cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
148cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
149208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartieruint32_t ClassTable::ClassDescriptorHashEquals::operator()(const char* descriptor) const {
150cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier  return ComputeModifiedUtf8Hash(descriptor);
151cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}
152cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier
153c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartierbool ClassTable::InsertStrongRoot(mirror::Object* obj) {
1541609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
155c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier  DCHECK(obj != nullptr);
156c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier  for (GcRoot<mirror::Object>& root : strong_roots_) {
157c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier    if (root.Read() == obj) {
15800310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier      return false;
15900310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier    }
16000310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier  }
161c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier  strong_roots_.push_back(GcRoot<mirror::Object>(obj));
16200310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier  return true;
16300310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier}
16400310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier
165208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartiersize_t ClassTable::WriteToMemory(uint8_t* ptr) const {
1661609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
16741dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  ClassSet combined;
16841dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  // Combine all the class sets in case there are multiple, also adjusts load factor back to
16941dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  // default in case classes were pruned.
17041dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  for (const ClassSet& class_set : classes_) {
17141dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier    for (const GcRoot<mirror::Class>& root : class_set) {
17241dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier      combined.Insert(root);
173208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier    }
174208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier  }
17541dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  const size_t ret = combined.WriteToMemory(ptr);
17641dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  // Sanity check.
17741dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  if (kIsDebugBuild && ptr != nullptr) {
17841dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier    size_t read_count;
17941dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier    ClassSet class_set(ptr, /*make copy*/false, &read_count);
18041dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier    class_set.Verify();
18141dc8cef5d1f86e3ade30b8aaf20d29d8d0c712bMathieu Chartier  }
182208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier  return ret;
183208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier}
184208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier
185208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartiersize_t ClassTable::ReadFromMemory(uint8_t* ptr) {
186208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier  size_t read_count = 0;
18788027bd6810b9a5b785dba5396eec5301e4540b2Mathieu Chartier  AddClassSet(ClassSet(ptr, /*make copy*/false, &read_count));
188208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier  return read_count;
189208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier}
190208a5cb383dd9dcd3461f89b74af5df67dc8d794Mathieu Chartier
19188027bd6810b9a5b785dba5396eec5301e4540b2Mathieu Chartiervoid ClassTable::AddClassSet(ClassSet&& set) {
1921609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
19388027bd6810b9a5b785dba5396eec5301e4540b2Mathieu Chartier  classes_.insert(classes_.begin(), std::move(set));
19488027bd6810b9a5b785dba5396eec5301e4540b2Mathieu Chartier}
19588027bd6810b9a5b785dba5396eec5301e4540b2Mathieu Chartier
196c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartiervoid ClassTable::ClearStrongRoots() {
197c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
198c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier  strong_roots_.clear();
199c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier}
200cc5ebdf29ea47e24e79279169e0192dfc08b38c8Mathieu Chartier}  // namespace art
201