class_table-inl.h revision fdd513d6c522841e82f1dc144d19a8d60269b9f7
1/*
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#ifndef ART_RUNTIME_CLASS_TABLE_INL_H_
18#define ART_RUNTIME_CLASS_TABLE_INL_H_
19
20#include "class_table.h"
21#include "oat_file.h"
22
23namespace art {
24
25template<class Visitor>
26void ClassTable::VisitRoots(Visitor& visitor) {
27  ReaderMutexLock mu(Thread::Current(), lock_);
28  for (ClassSet& class_set : classes_) {
29    for (TableSlot& table_slot : class_set) {
30      table_slot.VisitRoot(visitor);
31    }
32  }
33  for (GcRoot<mirror::Object>& root : strong_roots_) {
34    visitor.VisitRoot(root.AddressWithoutBarrier());
35  }
36  for (const OatFile* oat_file : oat_files_) {
37    for (GcRoot<mirror::Object>& root : oat_file->GetBssGcRoots()) {
38      visitor.VisitRootIfNonNull(root.AddressWithoutBarrier());
39    }
40  }
41}
42
43template<class Visitor>
44void ClassTable::VisitRoots(const Visitor& visitor) {
45  ReaderMutexLock mu(Thread::Current(), lock_);
46  for (ClassSet& class_set : classes_) {
47    for (TableSlot& table_slot : class_set) {
48      table_slot.VisitRoot(visitor);
49    }
50  }
51  for (GcRoot<mirror::Object>& root : strong_roots_) {
52    visitor.VisitRoot(root.AddressWithoutBarrier());
53  }
54  for (const OatFile* oat_file : oat_files_) {
55    for (GcRoot<mirror::Object>& root : oat_file->GetBssGcRoots()) {
56      visitor.VisitRootIfNonNull(root.AddressWithoutBarrier());
57    }
58  }
59}
60
61template <typename Visitor>
62bool ClassTable::Visit(Visitor& visitor) {
63  ReaderMutexLock mu(Thread::Current(), lock_);
64  for (ClassSet& class_set : classes_) {
65    for (TableSlot& table_slot : class_set) {
66      if (!visitor(table_slot.Read())) {
67        return false;
68      }
69    }
70  }
71  return true;
72}
73
74template <typename Visitor>
75bool ClassTable::Visit(const Visitor& visitor) {
76  ReaderMutexLock mu(Thread::Current(), lock_);
77  for (ClassSet& class_set : classes_) {
78    for (TableSlot& table_slot : class_set) {
79      if (!visitor(table_slot.Read())) {
80        return false;
81      }
82    }
83  }
84  return true;
85}
86
87template<ReadBarrierOption kReadBarrierOption>
88inline mirror::Class* ClassTable::TableSlot::Read() const {
89  const uint32_t before = data_.LoadRelaxed();
90  ObjPtr<mirror::Class> const before_ptr(ExtractPtr(before));
91  ObjPtr<mirror::Class> const after_ptr(
92      GcRoot<mirror::Class>(before_ptr).Read<kReadBarrierOption>());
93  if (kReadBarrierOption != kWithoutReadBarrier && before_ptr != after_ptr) {
94    // If another thread raced and updated the reference, do not store the read barrier updated
95    // one.
96    data_.CompareExchangeStrongRelease(before, Encode(after_ptr, MaskHash(before)));
97  }
98  return after_ptr.Ptr();
99}
100
101template<typename Visitor>
102inline void ClassTable::TableSlot::VisitRoot(const Visitor& visitor) const {
103  const uint32_t before = data_.LoadRelaxed();
104  ObjPtr<mirror::Class> before_ptr(ExtractPtr(before));
105  GcRoot<mirror::Class> root(before_ptr);
106  visitor.VisitRoot(root.AddressWithoutBarrier());
107  ObjPtr<mirror::Class> after_ptr(root.Read<kWithoutReadBarrier>());
108  if (before_ptr != after_ptr) {
109    // If another thread raced and updated the reference, do not store the read barrier updated
110    // one.
111    data_.CompareExchangeStrongRelease(before, Encode(after_ptr, MaskHash(before)));
112  }
113}
114
115inline ObjPtr<mirror::Class> ClassTable::TableSlot::ExtractPtr(uint32_t data) {
116  return reinterpret_cast<mirror::Class*>(data & ~kHashMask);
117}
118
119inline uint32_t ClassTable::TableSlot::Encode(ObjPtr<mirror::Class> klass, uint32_t hash_bits) {
120  DCHECK_LE(hash_bits, kHashMask);
121  return reinterpret_cast<uintptr_t>(klass.Ptr()) | hash_bits;
122}
123
124inline ClassTable::TableSlot::TableSlot(ObjPtr<mirror::Class> klass, uint32_t descriptor_hash)
125    : data_(Encode(klass, MaskHash(descriptor_hash))) {
126  if (kIsDebugBuild) {
127    std::string temp;
128    const uint32_t hash = ComputeModifiedUtf8Hash(klass->GetDescriptor(&temp));
129    CHECK_EQ(descriptor_hash, hash);
130  }
131}
132
133}  // namespace art
134
135#endif  // ART_RUNTIME_CLASS_TABLE_INL_H_
136