large_object_space.h revision 66e222aa48e6d2fe4c78a1df938364b82bc83e72
1/*
2 * Copyright (C) 2012 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_SPACE_LARGE_OBJECT_SPACE_H_
18#define ART_RUNTIME_GC_SPACE_LARGE_OBJECT_SPACE_H_
19
20#include "base/allocator.h"
21#include "dlmalloc_space.h"
22#include "safe_map.h"
23#include "space.h"
24
25#include <set>
26#include <vector>
27
28namespace art {
29namespace gc {
30namespace space {
31
32class AllocationInfo;
33
34// Abstraction implemented by all large object spaces.
35class LargeObjectSpace : public DiscontinuousSpace, public AllocSpace {
36 public:
37  SpaceType GetType() const OVERRIDE {
38    return kSpaceTypeLargeObjectSpace;
39  }
40  void SwapBitmaps();
41  void CopyLiveToMarked();
42  virtual void Walk(DlMallocSpace::WalkCallback, void* arg) = 0;
43  virtual ~LargeObjectSpace() {}
44
45  uint64_t GetBytesAllocated() OVERRIDE {
46    return num_bytes_allocated_;
47  }
48  uint64_t GetObjectsAllocated() OVERRIDE {
49    return num_objects_allocated_;
50  }
51  uint64_t GetTotalBytesAllocated() const {
52    return total_bytes_allocated_;
53  }
54  uint64_t GetTotalObjectsAllocated() const {
55    return total_objects_allocated_;
56  }
57  size_t FreeList(Thread* self, size_t num_ptrs, mirror::Object** ptrs) OVERRIDE;
58  // LargeObjectSpaces don't have thread local state.
59  void RevokeThreadLocalBuffers(art::Thread*) OVERRIDE {
60  }
61  void RevokeAllThreadLocalBuffers() OVERRIDE {
62  }
63  bool IsAllocSpace() const OVERRIDE {
64    return true;
65  }
66  AllocSpace* AsAllocSpace() OVERRIDE {
67    return this;
68  }
69  collector::ObjectBytePair Sweep(bool swap_bitmaps);
70  virtual bool CanMoveObjects() const OVERRIDE {
71    return false;
72  }
73  // Current address at which the space begins, which may vary as the space is filled.
74  byte* Begin() const {
75    return begin_;
76  }
77  // Current address at which the space ends, which may vary as the space is filled.
78  byte* End() const {
79    return end_;
80  }
81  // Current size of space
82  size_t Size() const {
83    return End() - Begin();
84  }
85  // Return true if we contain the specified address.
86  bool Contains(const mirror::Object* obj) const {
87    const byte* byte_obj = reinterpret_cast<const byte*>(obj);
88    return Begin() <= byte_obj && byte_obj < End();
89  }
90  void LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) OVERRIDE
91      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
92
93 protected:
94  explicit LargeObjectSpace(const std::string& name, byte* begin, byte* end);
95  static void SweepCallback(size_t num_ptrs, mirror::Object** ptrs, void* arg);
96
97  // Approximate number of bytes which have been allocated into the space.
98  uint64_t num_bytes_allocated_;
99  uint64_t num_objects_allocated_;
100  uint64_t total_bytes_allocated_;
101  uint64_t total_objects_allocated_;
102  // Begin and end, may change as more large objects are allocated.
103  byte* begin_;
104  byte* end_;
105
106  friend class Space;
107
108 private:
109  DISALLOW_COPY_AND_ASSIGN(LargeObjectSpace);
110};
111
112// A discontinuous large object space implemented by individual mmap/munmap calls.
113class LargeObjectMapSpace : public LargeObjectSpace {
114 public:
115  // Creates a large object space. Allocations into the large object space use memory maps instead
116  // of malloc.
117  static LargeObjectMapSpace* Create(const std::string& name);
118  // Return the storage space required by obj.
119  size_t AllocationSize(mirror::Object* obj, size_t* usable_size);
120  mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated,
121                        size_t* usable_size);
122  size_t Free(Thread* self, mirror::Object* ptr);
123  void Walk(DlMallocSpace::WalkCallback, void* arg) OVERRIDE LOCKS_EXCLUDED(lock_);
124  // TODO: disabling thread safety analysis as this may be called when we already hold lock_.
125  bool Contains(const mirror::Object* obj) const NO_THREAD_SAFETY_ANALYSIS;
126
127 protected:
128  explicit LargeObjectMapSpace(const std::string& name);
129  virtual ~LargeObjectMapSpace() {}
130
131  // Used to ensure mutual exclusion when the allocation spaces data structures are being modified.
132  mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
133  std::vector<mirror::Object*, TrackingAllocator<mirror::Object*, kAllocatorTagLOS>> large_objects_
134      GUARDED_BY(lock_);
135  typedef SafeMap<mirror::Object*, MemMap*, std::less<mirror::Object*>,
136      TrackingAllocator<std::pair<mirror::Object*, MemMap*>, kAllocatorTagLOSMaps>> MemMaps;
137  MemMaps mem_maps_ GUARDED_BY(lock_);
138};
139
140// A continuous large object space with a free-list to handle holes.
141class FreeListSpace FINAL : public LargeObjectSpace {
142 public:
143  static constexpr size_t kAlignment = kPageSize;
144
145  virtual ~FreeListSpace();
146  static FreeListSpace* Create(const std::string& name, byte* requested_begin, size_t capacity);
147  size_t AllocationSize(mirror::Object* obj, size_t* usable_size) OVERRIDE
148      EXCLUSIVE_LOCKS_REQUIRED(lock_);
149  mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated,
150                        size_t* usable_size) OVERRIDE;
151  size_t Free(Thread* self, mirror::Object* obj) OVERRIDE;
152  void Walk(DlMallocSpace::WalkCallback callback, void* arg) OVERRIDE LOCKS_EXCLUDED(lock_);
153  void Dump(std::ostream& os) const;
154
155 protected:
156  FreeListSpace(const std::string& name, MemMap* mem_map, byte* begin, byte* end);
157  size_t GetSlotIndexForAddress(uintptr_t address) const {
158    DCHECK(Contains(reinterpret_cast<mirror::Object*>(address)));
159    return (address - reinterpret_cast<uintptr_t>(Begin())) / kAlignment;
160  }
161  size_t GetSlotIndexForAllocationInfo(const AllocationInfo* info) const;
162  AllocationInfo* GetAllocationInfoForAddress(uintptr_t address);
163  const AllocationInfo* GetAllocationInfoForAddress(uintptr_t address) const;
164  uintptr_t GetAllocationAddressForSlot(size_t slot) const {
165    return reinterpret_cast<uintptr_t>(Begin()) + slot * kAlignment;
166  }
167  uintptr_t GetAddressForAllocationInfo(const AllocationInfo* info) const {
168    return GetAllocationAddressForSlot(GetSlotIndexForAllocationInfo(info));
169  }
170  // Removes header from the free blocks set by finding the corresponding iterator and erasing it.
171  void RemoveFreePrev(AllocationInfo* info) EXCLUSIVE_LOCKS_REQUIRED(lock_);
172
173  class SortByPrevFree {
174   public:
175    bool operator()(const AllocationInfo* a, const AllocationInfo* b) const;
176  };
177  typedef std::set<AllocationInfo*, SortByPrevFree,
178                   TrackingAllocator<AllocationInfo*, kAllocatorTagLOSFreeList>> FreeBlocks;
179
180  // There is not footer for any allocations at the end of the space, so we keep track of how much
181  // free space there is at the end manually.
182  std::unique_ptr<MemMap> mem_map_;
183  // Side table for allocation info, one per page.
184  std::unique_ptr<MemMap> allocation_info_map_;
185  AllocationInfo* allocation_info_;
186
187  Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
188  // Free bytes at the end of the space.
189  size_t free_end_ GUARDED_BY(lock_);
190  FreeBlocks free_blocks_ GUARDED_BY(lock_);
191};
192
193}  // namespace space
194}  // namespace gc
195}  // namespace art
196
197#endif  // ART_RUNTIME_GC_SPACE_LARGE_OBJECT_SPACE_H_
198