1e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier/*
2e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier * Copyright (C) 2015 The Android Open Source Project
3e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier *
4e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier * Licensed under the Apache License, Version 2.0 (the "License");
5e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier * you may not use this file except in compliance with the License.
6e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier * You may obtain a copy of the License at
7e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier *
8e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier *      http://www.apache.org/licenses/LICENSE-2.0
9e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier *
10e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier * Unless required by applicable law or agreed to in writing, software
11e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier * distributed under the License is distributed on an "AS IS" BASIS,
12e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier * See the License for the specific language governing permissions and
14e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier * limitations under the License.
15e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier */
16e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
17e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier#ifndef ART_RUNTIME_CLASS_TABLE_INL_H_
18e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier#define ART_RUNTIME_CLASS_TABLE_INL_H_
19e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
20e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier#include "class_table.h"
21508fdf3eb53824f109c89f98484927085bdc43baAndreas Gampe
22508fdf3eb53824f109c89f98484927085bdc43baAndreas Gampe#include "gc_root-inl.h"
23aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko#include "oat_file.h"
24e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
25e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartiernamespace art {
26e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
27e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartiertemplate<class Visitor>
28e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartiervoid ClassTable::VisitRoots(Visitor& visitor) {
291609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
30e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  for (ClassSet& class_set : classes_) {
3158c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    for (TableSlot& table_slot : class_set) {
3258c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier      table_slot.VisitRoot(visitor);
33e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier    }
34e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  }
35c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier  for (GcRoot<mirror::Object>& root : strong_roots_) {
361aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartier    visitor.VisitRoot(root.AddressWithoutBarrier());
371aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartier  }
38aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  for (const OatFile* oat_file : oat_files_) {
39aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    for (GcRoot<mirror::Object>& root : oat_file->GetBssGcRoots()) {
40aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko      visitor.VisitRootIfNonNull(root.AddressWithoutBarrier());
41aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    }
42aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  }
43e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier}
44e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
45e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartiertemplate<class Visitor>
46e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartiervoid ClassTable::VisitRoots(const Visitor& visitor) {
471609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
48e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  for (ClassSet& class_set : classes_) {
4958c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    for (TableSlot& table_slot : class_set) {
5058c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier      table_slot.VisitRoot(visitor);
51e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier    }
52e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier  }
53c9dbb1df3b5c06ba122cacaf35b17cb53c6be3c6Mathieu Chartier  for (GcRoot<mirror::Object>& root : strong_roots_) {
5400310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier    visitor.VisitRoot(root.AddressWithoutBarrier());
5500310e0bb4ee541b99f0b687dbf5f706db2aabcaMathieu Chartier  }
56aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  for (const OatFile* oat_file : oat_files_) {
57aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    for (GcRoot<mirror::Object>& root : oat_file->GetBssGcRoots()) {
58aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko      visitor.VisitRootIfNonNull(root.AddressWithoutBarrier());
59aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko    }
60aad75c6d5bfab2dc8e30fc99fafe8cd2dc8b74d8Vladimir Marko  }
61e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier}
62e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
63ab2ce84d4995f05c38c5ebfefc6683b244a36260Alexey Grebenkintemplate <typename Visitor, ReadBarrierOption kReadBarrierOption>
641aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartierbool ClassTable::Visit(Visitor& visitor) {
651609e3a42051769f4a8be3b6731e7bb2f828b3bbMathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
661aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartier  for (ClassSet& class_set : classes_) {
6758c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    for (TableSlot& table_slot : class_set) {
68ab2ce84d4995f05c38c5ebfefc6683b244a36260Alexey Grebenkin      if (!visitor(table_slot.Read<kReadBarrierOption>())) {
69db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier        return false;
70db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier      }
71db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier    }
72db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  }
73db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  return true;
74db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier}
75db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier
76ab2ce84d4995f05c38c5ebfefc6683b244a36260Alexey Grebenkintemplate <typename Visitor, ReadBarrierOption kReadBarrierOption>
77db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartierbool ClassTable::Visit(const Visitor& visitor) {
78db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  ReaderMutexLock mu(Thread::Current(), lock_);
79db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier  for (ClassSet& class_set : classes_) {
80db70ce5e788404f36cb5dbb137c6a8f79f34a2a0Mathieu Chartier    for (TableSlot& table_slot : class_set) {
81ab2ce84d4995f05c38c5ebfefc6683b244a36260Alexey Grebenkin      if (!visitor(table_slot.Read<kReadBarrierOption>())) {
821aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartier        return false;
831aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartier      }
841aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartier    }
851aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartier  }
861aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartier  return true;
871aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartier}
881aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartier
8958c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartiertemplate<ReadBarrierOption kReadBarrierOption>
9058c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartierinline mirror::Class* ClassTable::TableSlot::Read() const {
9158c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  const uint32_t before = data_.LoadRelaxed();
9258c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  ObjPtr<mirror::Class> const before_ptr(ExtractPtr(before));
9358c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  ObjPtr<mirror::Class> const after_ptr(
9458c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier      GcRoot<mirror::Class>(before_ptr).Read<kReadBarrierOption>());
9558c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  if (kReadBarrierOption != kWithoutReadBarrier && before_ptr != after_ptr) {
9658c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    // If another thread raced and updated the reference, do not store the read barrier updated
9758c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    // one.
984557b3858a66aa20e42bce937e1f0620aad880a2Orion Hodson    data_.CompareAndSetStrongRelease(before, Encode(after_ptr, MaskHash(before)));
9958c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  }
10058c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  return after_ptr.Ptr();
10158c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier}
10258c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier
10358c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartiertemplate<typename Visitor>
10458c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartierinline void ClassTable::TableSlot::VisitRoot(const Visitor& visitor) const {
10558c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  const uint32_t before = data_.LoadRelaxed();
10658c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  ObjPtr<mirror::Class> before_ptr(ExtractPtr(before));
10758c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  GcRoot<mirror::Class> root(before_ptr);
10858c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  visitor.VisitRoot(root.AddressWithoutBarrier());
10958c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  ObjPtr<mirror::Class> after_ptr(root.Read<kWithoutReadBarrier>());
11058c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  if (before_ptr != after_ptr) {
11158c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    // If another thread raced and updated the reference, do not store the read barrier updated
11258c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    // one.
1134557b3858a66aa20e42bce937e1f0620aad880a2Orion Hodson    data_.CompareAndSetStrongRelease(before, Encode(after_ptr, MaskHash(before)));
11458c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  }
11558c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier}
11658c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier
11758c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartierinline ObjPtr<mirror::Class> ClassTable::TableSlot::ExtractPtr(uint32_t data) {
11858c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  return reinterpret_cast<mirror::Class*>(data & ~kHashMask);
11958c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier}
12058c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier
12158c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartierinline uint32_t ClassTable::TableSlot::Encode(ObjPtr<mirror::Class> klass, uint32_t hash_bits) {
12258c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  DCHECK_LE(hash_bits, kHashMask);
12358c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  return reinterpret_cast<uintptr_t>(klass.Ptr()) | hash_bits;
12458c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier}
12558c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier
12658c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartierinline ClassTable::TableSlot::TableSlot(ObjPtr<mirror::Class> klass, uint32_t descriptor_hash)
12758c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    : data_(Encode(klass, MaskHash(descriptor_hash))) {
12858c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  if (kIsDebugBuild) {
12958c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    std::string temp;
13058c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    const uint32_t hash = ComputeModifiedUtf8Hash(klass->GetDescriptor(&temp));
13158c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier    CHECK_EQ(descriptor_hash, hash);
13258c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier  }
13358c3f6a0d15a4340c0a11ab7fbc8c4b990c64b77Mathieu Chartier}
1341aa8ec2ccdd7bedb6d30d91c89f1e94ab23c4439Mathieu Chartier
13572041a0dcb5b7c133b79a1d6783a23039f2136bdMathieu Chartiertemplate <typename Filter>
13672041a0dcb5b7c133b79a1d6783a23039f2136bdMathieu Chartierinline void ClassTable::RemoveStrongRoots(const Filter& filter) {
13772041a0dcb5b7c133b79a1d6783a23039f2136bdMathieu Chartier  WriterMutexLock mu(Thread::Current(), lock_);
13872041a0dcb5b7c133b79a1d6783a23039f2136bdMathieu Chartier  strong_roots_.erase(std::remove_if(strong_roots_.begin(), strong_roots_.end(), filter),
13972041a0dcb5b7c133b79a1d6783a23039f2136bdMathieu Chartier                      strong_roots_.end());
14072041a0dcb5b7c133b79a1d6783a23039f2136bdMathieu Chartier}
14172041a0dcb5b7c133b79a1d6783a23039f2136bdMathieu Chartier
142e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier}  // namespace art
143e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier
144e4275c07e9852a6944f47efa9d0591fceb8e8e36Mathieu Chartier#endif  // ART_RUNTIME_CLASS_TABLE_INL_H_
145