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