blob: 217c2ee787908b3c9ca2d612961cc1f6643b9af5 [file] [log] [blame]
Carl Shapiro69759ea2011-07-21 18:13:35 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2// Author: cshapiro@google.com (Carl Shapiro)
3
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07004#include "space.h"
Carl Shapiro69759ea2011-07-21 18:13:35 -07005
6#include <sys/mman.h>
7
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07008#include "logging.h"
9#include "mspace.h"
10#include "scoped_ptr.h"
11#include "utils.h"
Carl Shapiro69759ea2011-07-21 18:13:35 -070012
13namespace art {
14
15Space* Space::Create(size_t startup_size, size_t maximum_size) {
16 scoped_ptr<Space> space(new Space(startup_size, maximum_size));
17 bool success = space->Init();
18 if (!success) {
19 return NULL;
20 } else {
21 return space.release();
22 }
23}
24
25void* Space::CreateMallocSpace(void* base,
26 size_t startup_size,
27 size_t maximum_size) {
28 errno = 0;
29 bool is_locked = false;
30 size_t commit_size = startup_size / 2;
31 void* msp = create_contiguous_mspace_with_base(commit_size, maximum_size,
32 is_locked, base);
33 if (msp != NULL) {
34 // Do not permit the heap grow past the starting size without our
35 // intervention.
36 mspace_set_max_allowed_footprint(msp, startup_size);
37 } else {
38 // There is no guarantee that errno has meaning when the call
39 // fails, but it often does.
40 PLOG(ERROR) << "create_contiguous_mspace_with_base failed";
41 }
42 return msp;
43}
44
45bool Space::Init() {
46 if (!(startup_size_ <= maximum_size_)) {
47 return false;
48 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -070049 size_t length = RoundUp(maximum_size_, kPageSize);
Carl Shapiro69759ea2011-07-21 18:13:35 -070050 int prot = PROT_READ | PROT_WRITE;
51 int flags = MAP_PRIVATE | MAP_ANONYMOUS;
52 void* base = mmap(NULL, length, prot, flags, -1, 0);
53 if (base == MAP_FAILED) {
54 PLOG(ERROR) << "mmap failed";
55 return false;
56 }
57 base_ = static_cast<byte*>(base);
58 limit_ = base_ + length;
59 mspace_ = CreateMallocSpace(base, startup_size_, maximum_size_);
60 if (mspace_ == NULL) {
61 munmap(base_, length);
62 return false;
63 }
64 return true;
65}
66
67Space::~Space() {
68 if (base_ == NULL) {
69 return;
70 }
71 int result = munmap(base_, limit_ - base_);
72 if (result == -1) {
73 PLOG(WARNING) << "munmap failed";
74 }
75}
76
77Object* Space::AllocWithoutGrowth(size_t num_bytes) {
78 return reinterpret_cast<Object*>(mspace_calloc(mspace_, 1, num_bytes));
79}
80
81Object* Space::AllocWithGrowth(size_t num_bytes) {
82 // Grow as much as possible within the mspace.
83 size_t max_allowed = maximum_size_;
84 mspace_set_max_allowed_footprint(mspace_, max_allowed);
85 // Try the allocation.
86 void* ptr = AllocWithoutGrowth(num_bytes);
87 // Shrink back down as small as possible.
88 size_t footprint = mspace_footprint(mspace_);
89 mspace_set_max_allowed_footprint(mspace_, footprint);
90 // Return the new allocation or NULL.
91 return reinterpret_cast<Object*>(ptr);
92}
93
94size_t Space::Free(void* ptr) {
95 DCHECK(ptr != NULL);
96 size_t num_bytes = mspace_usable_size(mspace_, ptr);
97 mspace_free(mspace_, ptr);
98 return num_bytes;
99}
100
Carl Shapiro58551df2011-07-24 03:09:51 -0700101size_t Space::AllocationSize(const Object* obj) {
102 return mspace_usable_size(mspace_, obj) + kChunkOverhead;
103}
104
Carl Shapiro69759ea2011-07-21 18:13:35 -0700105void Space::DontNeed(void* start, void* end, void* num_bytes) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700106 start = (void*)RoundUp((uintptr_t)start, kPageSize);
107 end = (void*)RoundDown((uintptr_t)end, kPageSize);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700108 if (start >= end) {
109 return;
110 }
111 size_t length = reinterpret_cast<byte*>(end) - reinterpret_cast<byte*>(start);
112 int result = madvise(start, length, MADV_DONTNEED);
113 if (result == -1) {
114 PLOG(WARNING) << "madvise failed";
115 } else {
116 *reinterpret_cast<size_t*>(num_bytes) += length;
117 }
118}
119
120void Space::Trim() {
121 CHECK(mspace_ != NULL);
122 mspace_trim(mspace_, 0);
123 size_t num_bytes_released = 0;
124 mspace_walk_free_pages(mspace_, DontNeed, &num_bytes_released);
125}
126
127size_t Space::MaxAllowedFootprint() {
128 return mspace_max_allowed_footprint(mspace_);
129}
130
131void Space::Grow(size_t new_size) {
Carl Shapiro58551df2011-07-24 03:09:51 -0700132 LOG(FATAL) << "Unimplemented";
Carl Shapiro69759ea2011-07-21 18:13:35 -0700133}
134
135} // namespace art