blob: c636e3809fa0e3426054212aa7029bc50f3ef3e3 [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 Carlstrom4a289ed2011-08-16 17:17:49 -07007#include "file.h"
8#include "image.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07009#include "logging.h"
10#include "mspace.h"
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070011#include "os.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070012#include "scoped_ptr.h"
13#include "utils.h"
Carl Shapiro69759ea2011-07-21 18:13:35 -070014
15namespace art {
16
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070017Space* Space::Create(size_t initial_size, size_t maximum_size, byte* requested_base) {
18 scoped_ptr<Space> space(new Space());
19 bool success = space->Init(initial_size, maximum_size, requested_base);
Carl Shapiro69759ea2011-07-21 18:13:35 -070020 if (!success) {
21 return NULL;
22 } else {
23 return space.release();
24 }
25}
26
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070027Space* Space::Create(const char* image_file_name) {
28 CHECK(image_file_name != NULL);
29 scoped_ptr<Space> space(new Space());
30 bool success = space->Init(image_file_name);
31 if (!success) {
32 return NULL;
33 } else {
34 return space.release();
35 }
36}
37
38Space::~Space() {}
39
Carl Shapiro69759ea2011-07-21 18:13:35 -070040void* Space::CreateMallocSpace(void* base,
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070041 size_t initial_size,
Carl Shapiro69759ea2011-07-21 18:13:35 -070042 size_t maximum_size) {
43 errno = 0;
44 bool is_locked = false;
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070045 size_t commit_size = initial_size / 2;
Carl Shapiro69759ea2011-07-21 18:13:35 -070046 void* msp = create_contiguous_mspace_with_base(commit_size, maximum_size,
47 is_locked, base);
48 if (msp != NULL) {
49 // Do not permit the heap grow past the starting size without our
50 // intervention.
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070051 mspace_set_max_allowed_footprint(msp, initial_size);
Carl Shapiro69759ea2011-07-21 18:13:35 -070052 } else {
53 // There is no guarantee that errno has meaning when the call
54 // fails, but it often does.
55 PLOG(ERROR) << "create_contiguous_mspace_with_base failed";
56 }
57 return msp;
58}
59
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070060bool Space::Init(size_t initial_size, size_t maximum_size, byte* requested_base) {
61 if (!(initial_size <= maximum_size)) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070062 return false;
63 }
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070064 size_t length = RoundUp(maximum_size, kPageSize);
Carl Shapiro69759ea2011-07-21 18:13:35 -070065 int prot = PROT_READ | PROT_WRITE;
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070066 scoped_ptr<MemMap> mem_map(MemMap::Map(requested_base, length, prot));
67 if (mem_map == NULL) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070068 return false;
69 }
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070070 Init(mem_map.release());
71 maximum_size_ = maximum_size;
72 mspace_ = CreateMallocSpace(base_, initial_size, maximum_size);
73 return (mspace_ != NULL);
74}
75
76void Space::Init(MemMap* mem_map) {
77 mem_map_.reset(mem_map);
Brian Carlstromdb4d5402011-08-09 12:18:28 -070078 base_ = mem_map_->GetAddress();
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070079 limit_ = base_ + mem_map->GetLength();
80}
81
82
83bool Space::Init(const char* image_file_name) {
84 scoped_ptr<File> file(OS::OpenFile(image_file_name, false));
85 if (file == NULL) {
Carl Shapiro69759ea2011-07-21 18:13:35 -070086 return false;
87 }
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070088 ImageHeader image_header;
89 bool success = file->ReadFully(&image_header, sizeof(image_header));
90 if (!success || !image_header.IsValid()) {
91 return false;
92 }
93 scoped_ptr<MemMap> map(MemMap::Map(image_header.GetBaseAddr(),
94 file->Length(),
95 PROT_READ | PROT_WRITE,
96 MAP_PRIVATE | MAP_FIXED,
97 file->Fd(),
98 0));
99 if (map == NULL) {
100 return false;
101 }
102 CHECK_EQ(image_header.GetBaseAddr(), map->GetAddress());
Brian Carlstroma663ea52011-08-19 23:33:41 -0700103 image_header_ = reinterpret_cast<ImageHeader*>(map->GetAddress());
104 DCHECK_EQ(0, memcmp(&image_header, image_header_, sizeof(ImageHeader)));
105
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700106 Init(map.release());
Carl Shapiro69759ea2011-07-21 18:13:35 -0700107 return true;
108}
109
Carl Shapiro69759ea2011-07-21 18:13:35 -0700110Object* Space::AllocWithoutGrowth(size_t num_bytes) {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700111 DCHECK(mspace_ != NULL);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700112 return reinterpret_cast<Object*>(mspace_calloc(mspace_, 1, num_bytes));
113}
114
115Object* Space::AllocWithGrowth(size_t num_bytes) {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700116 DCHECK(mspace_ != NULL);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700117 // Grow as much as possible within the mspace.
118 size_t max_allowed = maximum_size_;
119 mspace_set_max_allowed_footprint(mspace_, max_allowed);
120 // Try the allocation.
121 void* ptr = AllocWithoutGrowth(num_bytes);
122 // Shrink back down as small as possible.
123 size_t footprint = mspace_footprint(mspace_);
124 mspace_set_max_allowed_footprint(mspace_, footprint);
125 // Return the new allocation or NULL.
126 return reinterpret_cast<Object*>(ptr);
127}
128
129size_t Space::Free(void* ptr) {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700130 DCHECK(mspace_ != NULL);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700131 DCHECK(ptr != NULL);
132 size_t num_bytes = mspace_usable_size(mspace_, ptr);
133 mspace_free(mspace_, ptr);
134 return num_bytes;
135}
136
Carl Shapiro58551df2011-07-24 03:09:51 -0700137size_t Space::AllocationSize(const Object* obj) {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700138 DCHECK(mspace_ != NULL);
Carl Shapiro58551df2011-07-24 03:09:51 -0700139 return mspace_usable_size(mspace_, obj) + kChunkOverhead;
140}
141
Carl Shapiro69759ea2011-07-21 18:13:35 -0700142void Space::DontNeed(void* start, void* end, void* num_bytes) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700143 start = (void*)RoundUp((uintptr_t)start, kPageSize);
144 end = (void*)RoundDown((uintptr_t)end, kPageSize);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700145 if (start >= end) {
146 return;
147 }
148 size_t length = reinterpret_cast<byte*>(end) - reinterpret_cast<byte*>(start);
149 int result = madvise(start, length, MADV_DONTNEED);
150 if (result == -1) {
151 PLOG(WARNING) << "madvise failed";
152 } else {
153 *reinterpret_cast<size_t*>(num_bytes) += length;
154 }
155}
156
157void Space::Trim() {
158 CHECK(mspace_ != NULL);
159 mspace_trim(mspace_, 0);
160 size_t num_bytes_released = 0;
161 mspace_walk_free_pages(mspace_, DontNeed, &num_bytes_released);
162}
163
164size_t Space::MaxAllowedFootprint() {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700165 DCHECK(mspace_ != NULL);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700166 return mspace_max_allowed_footprint(mspace_);
167}
168
169void Space::Grow(size_t new_size) {
Elliott Hughes53b61312011-08-12 18:28:20 -0700170 UNIMPLEMENTED(FATAL);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700171}
172
173} // namespace art