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