blob: c3d763c4fe96001e4424a5c5fdc5f816b17ff826 [file] [log] [blame]
Carl Shapiro69759ea2011-07-21 18:13:35 -07001// Copyright 2011 Google Inc. All Rights Reserved.
Carl Shapiro69759ea2011-07-21 18:13:35 -07002
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "space.h"
Carl Shapiro69759ea2011-07-21 18:13:35 -07004
5#include <sys/mman.h>
6
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07007#include "logging.h"
8#include "mspace.h"
9#include "scoped_ptr.h"
10#include "utils.h"
Carl Shapiro69759ea2011-07-21 18:13:35 -070011
12namespace art {
13
14Space* Space::Create(size_t startup_size, size_t maximum_size) {
15 scoped_ptr<Space> space(new Space(startup_size, maximum_size));
16 bool success = space->Init();
17 if (!success) {
18 return NULL;
19 } else {
20 return space.release();
21 }
22}
23
24void* Space::CreateMallocSpace(void* base,
25 size_t startup_size,
26 size_t maximum_size) {
27 errno = 0;
28 bool is_locked = false;
29 size_t commit_size = startup_size / 2;
30 void* msp = create_contiguous_mspace_with_base(commit_size, maximum_size,
31 is_locked, base);
32 if (msp != NULL) {
33 // Do not permit the heap grow past the starting size without our
34 // intervention.
35 mspace_set_max_allowed_footprint(msp, startup_size);
36 } else {
37 // There is no guarantee that errno has meaning when the call
38 // fails, but it often does.
39 PLOG(ERROR) << "create_contiguous_mspace_with_base failed";
40 }
41 return msp;
42}
43
44bool Space::Init() {
45 if (!(startup_size_ <= maximum_size_)) {
46 return false;
47 }
Brian Carlstromb0460ea2011-07-29 10:08:05 -070048 size_t length = RoundUp(maximum_size_, kPageSize);
Carl Shapiro69759ea2011-07-21 18:13:35 -070049 int prot = PROT_READ | PROT_WRITE;
50 int flags = MAP_PRIVATE | MAP_ANONYMOUS;
Brian Carlstromdb4d5402011-08-09 12:18:28 -070051 mem_map_.reset(MemMap::Map(length, prot, flags));
52 if (mem_map_ == NULL) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070053 PLOG(ERROR) << "mmap failed";
54 return false;
55 }
Brian Carlstromdb4d5402011-08-09 12:18:28 -070056 base_ = mem_map_->GetAddress();
Carl Shapiro69759ea2011-07-21 18:13:35 -070057 limit_ = base_ + length;
Brian Carlstromdb4d5402011-08-09 12:18:28 -070058 mspace_ = CreateMallocSpace(base_, startup_size_, maximum_size_);
Carl Shapiro69759ea2011-07-21 18:13:35 -070059 if (mspace_ == NULL) {
Brian Carlstromdb4d5402011-08-09 12:18:28 -070060 mem_map_->Unmap();
Carl Shapiro69759ea2011-07-21 18:13:35 -070061 return false;
62 }
63 return true;
64}
65
Brian Carlstromdb4d5402011-08-09 12:18:28 -070066Space::~Space() {}
Carl Shapiro69759ea2011-07-21 18:13:35 -070067
68Object* Space::AllocWithoutGrowth(size_t num_bytes) {
69 return reinterpret_cast<Object*>(mspace_calloc(mspace_, 1, num_bytes));
70}
71
72Object* Space::AllocWithGrowth(size_t num_bytes) {
73 // Grow as much as possible within the mspace.
74 size_t max_allowed = maximum_size_;
75 mspace_set_max_allowed_footprint(mspace_, max_allowed);
76 // Try the allocation.
77 void* ptr = AllocWithoutGrowth(num_bytes);
78 // Shrink back down as small as possible.
79 size_t footprint = mspace_footprint(mspace_);
80 mspace_set_max_allowed_footprint(mspace_, footprint);
81 // Return the new allocation or NULL.
82 return reinterpret_cast<Object*>(ptr);
83}
84
85size_t Space::Free(void* ptr) {
86 DCHECK(ptr != NULL);
87 size_t num_bytes = mspace_usable_size(mspace_, ptr);
88 mspace_free(mspace_, ptr);
89 return num_bytes;
90}
91
Carl Shapiro58551df2011-07-24 03:09:51 -070092size_t Space::AllocationSize(const Object* obj) {
93 return mspace_usable_size(mspace_, obj) + kChunkOverhead;
94}
95
Carl Shapiro69759ea2011-07-21 18:13:35 -070096void Space::DontNeed(void* start, void* end, void* num_bytes) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -070097 start = (void*)RoundUp((uintptr_t)start, kPageSize);
98 end = (void*)RoundDown((uintptr_t)end, kPageSize);
Carl Shapiro69759ea2011-07-21 18:13:35 -070099 if (start >= end) {
100 return;
101 }
102 size_t length = reinterpret_cast<byte*>(end) - reinterpret_cast<byte*>(start);
103 int result = madvise(start, length, MADV_DONTNEED);
104 if (result == -1) {
105 PLOG(WARNING) << "madvise failed";
106 } else {
107 *reinterpret_cast<size_t*>(num_bytes) += length;
108 }
109}
110
111void Space::Trim() {
112 CHECK(mspace_ != NULL);
113 mspace_trim(mspace_, 0);
114 size_t num_bytes_released = 0;
115 mspace_walk_free_pages(mspace_, DontNeed, &num_bytes_released);
116}
117
118size_t Space::MaxAllowedFootprint() {
119 return mspace_max_allowed_footprint(mspace_);
120}
121
122void Space::Grow(size_t new_size) {
Elliott Hughes53b61312011-08-12 18:28:20 -0700123 UNIMPLEMENTED(FATAL);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700124}
125
126} // namespace art