read_barrier_table.h revision 2cd334ae2d4287216523882f0d298cf3901b7ab1
1/*
2 * Copyright (C) 2014 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_GC_ACCOUNTING_READ_BARRIER_TABLE_H_
18#define ART_RUNTIME_GC_ACCOUNTING_READ_BARRIER_TABLE_H_
19
20#include "base/mutex.h"
21#include "gc/space/space.h"
22#include "globals.h"
23#include "mem_map.h"
24
25namespace art {
26namespace gc {
27namespace accounting {
28
29// Used to decide whether to take the read barrier fast/slow paths for
30// kUseTableLookupReadBarrier. If an entry is set, take the read
31// barrier slow path. There's an entry per region.
32class ReadBarrierTable {
33 public:
34  ReadBarrierTable() {
35    size_t capacity = static_cast<size_t>(kHeapCapacity / kRegionSize);
36    DCHECK_EQ(kHeapCapacity / kRegionSize,
37              static_cast<uint64_t>(static_cast<size_t>(kHeapCapacity / kRegionSize)));
38    std::string error_msg;
39    MemMap* mem_map = MemMap::MapAnonymous("read barrier table", nullptr, capacity,
40                                           PROT_READ | PROT_WRITE, false, &error_msg);
41    CHECK(mem_map != nullptr && mem_map->Begin() != nullptr)
42        << "couldn't allocate read barrier table: " << error_msg;
43    mem_map_.reset(mem_map);
44  }
45  void ClearForSpace(space::ContinuousSpace* space) {
46    uint8_t* entry_start = EntryFromAddr(space->Begin());
47    uint8_t* entry_end = EntryFromAddr(space->Limit());
48    memset(reinterpret_cast<void*>(entry_start), 0, entry_end - entry_start);
49  }
50  void Clear(uint8_t* start_addr, uint8_t* end_addr) {
51    DCHECK(IsValidHeapAddr(start_addr)) << start_addr;
52    DCHECK(IsValidHeapAddr(end_addr)) << end_addr;
53    DCHECK(IsAligned<kRegionSize>(start_addr));
54    DCHECK(IsAligned<kRegionSize>(end_addr));
55    uint8_t* entry_start = EntryFromAddr(start_addr);
56    uint8_t* entry_end = EntryFromAddr(end_addr);
57    memset(reinterpret_cast<void*>(entry_start), 0, entry_end - entry_start);
58  }
59  bool IsSet(const void* heap_addr) const {
60    DCHECK(IsValidHeapAddr(heap_addr)) << heap_addr;
61    uint8_t entry_value = *EntryFromAddr(heap_addr);
62    DCHECK(entry_value == 0 || entry_value == kSetEntryValue);
63    return entry_value == kSetEntryValue;
64  }
65  void ClearAll() {
66    mem_map_->MadviseDontNeedAndZero();
67  }
68  void SetAll() {
69    memset(mem_map_->Begin(), kSetEntryValue, mem_map_->Size());
70  }
71  bool IsAllCleared() const {
72    for (uint32_t* p = reinterpret_cast<uint32_t*>(mem_map_->Begin());
73         p < reinterpret_cast<uint32_t*>(mem_map_->End()); ++p) {
74      if (*p != 0) {
75        return false;
76      }
77    }
78    return true;
79  }
80
81  // This should match RegionSpace::kRegionSize. static_assert'ed in concurrent_copying.h.
82  static constexpr size_t kRegionSize = 1 * MB;
83
84 private:
85  static constexpr uint64_t kHeapCapacity = 4ULL * GB;  // low 4gb.
86  static constexpr uint8_t kSetEntryValue = 0x01;
87
88  uint8_t* EntryFromAddr(const void* heap_addr) const {
89    DCHECK(IsValidHeapAddr(heap_addr)) << heap_addr;
90    uint8_t* entry_addr = mem_map_->Begin() + reinterpret_cast<uintptr_t>(heap_addr) / kRegionSize;
91    DCHECK(IsValidEntry(entry_addr)) << "heap_addr: " << heap_addr
92                                     << " entry_addr: " << reinterpret_cast<void*>(entry_addr);
93    return entry_addr;
94  }
95
96  bool IsValidHeapAddr(const void* heap_addr) const {
97#ifdef __LP64__
98    return reinterpret_cast<uint64_t>(heap_addr) < kHeapCapacity;
99#else
100    UNUSED(heap_addr);
101    return true;
102#endif
103  }
104
105  bool IsValidEntry(const uint8_t* entry_addr) const {
106    uint8_t* begin = mem_map_->Begin();
107    uint8_t* end = mem_map_->End();
108    return entry_addr >= begin && entry_addr < end;
109  }
110
111  std::unique_ptr<MemMap> mem_map_;
112};
113
114}  // namespace accounting
115}  // namespace gc
116}  // namespace art
117
118#endif  // ART_RUNTIME_GC_ACCOUNTING_READ_BARRIER_TABLE_H_
119