blob: 36eb1f6203a50be7278898dab13acd25f64fed92 [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
Elliott Hughes90a33692011-08-30 13:27:07 -07007#include "UniquePtr.h"
Brian Carlstrom4a289ed2011-08-16 17:17:49 -07008#include "file.h"
9#include "image.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070010#include "logging.h"
11#include "mspace.h"
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070012#include "os.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070013#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) {
Elliott Hughes90a33692011-08-30 13:27:07 -070018 UniquePtr<Space> space(new Space());
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070019 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);
Elliott Hughes90a33692011-08-30 13:27:07 -070029 UniquePtr<Space> space(new Space());
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070030 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;
Elliott Hughes90a33692011-08-30 13:27:07 -070066 UniquePtr<MemMap> mem_map(MemMap::Map(requested_base, length, prot));
67 if (mem_map.get() == 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) {
Elliott Hughes90a33692011-08-30 13:27:07 -070084 UniquePtr<File> file(OS::OpenFile(image_file_name, false));
85 if (file.get() == 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 }
Elliott Hughes90a33692011-08-30 13:27:07 -070093 UniquePtr<MemMap> map(MemMap::Map(image_header.GetBaseAddr(),
94 file->Length(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED,
95 file->Fd(), 0));
96 if (map.get() == NULL) {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070097 return false;
98 }
99 CHECK_EQ(image_header.GetBaseAddr(), map->GetAddress());
Brian Carlstroma663ea52011-08-19 23:33:41 -0700100 image_header_ = reinterpret_cast<ImageHeader*>(map->GetAddress());
101 DCHECK_EQ(0, memcmp(&image_header, image_header_, sizeof(ImageHeader)));
102
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700103 Init(map.release());
Carl Shapiro69759ea2011-07-21 18:13:35 -0700104 return true;
105}
106
Carl Shapiro69759ea2011-07-21 18:13:35 -0700107Object* Space::AllocWithoutGrowth(size_t num_bytes) {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700108 DCHECK(mspace_ != NULL);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700109 return reinterpret_cast<Object*>(mspace_calloc(mspace_, 1, num_bytes));
110}
111
112Object* Space::AllocWithGrowth(size_t num_bytes) {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700113 DCHECK(mspace_ != NULL);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700114 // Grow as much as possible within the mspace.
115 size_t max_allowed = maximum_size_;
116 mspace_set_max_allowed_footprint(mspace_, max_allowed);
117 // Try the allocation.
118 void* ptr = AllocWithoutGrowth(num_bytes);
119 // Shrink back down as small as possible.
120 size_t footprint = mspace_footprint(mspace_);
121 mspace_set_max_allowed_footprint(mspace_, footprint);
122 // Return the new allocation or NULL.
123 return reinterpret_cast<Object*>(ptr);
124}
125
126size_t Space::Free(void* ptr) {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700127 DCHECK(mspace_ != NULL);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700128 DCHECK(ptr != NULL);
129 size_t num_bytes = mspace_usable_size(mspace_, ptr);
130 mspace_free(mspace_, ptr);
131 return num_bytes;
132}
133
Carl Shapiro58551df2011-07-24 03:09:51 -0700134size_t Space::AllocationSize(const Object* obj) {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700135 DCHECK(mspace_ != NULL);
Carl Shapiro58551df2011-07-24 03:09:51 -0700136 return mspace_usable_size(mspace_, obj) + kChunkOverhead;
137}
138
Carl Shapiro69759ea2011-07-21 18:13:35 -0700139void Space::DontNeed(void* start, void* end, void* num_bytes) {
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700140 start = (void*)RoundUp((uintptr_t)start, kPageSize);
141 end = (void*)RoundDown((uintptr_t)end, kPageSize);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700142 if (start >= end) {
143 return;
144 }
145 size_t length = reinterpret_cast<byte*>(end) - reinterpret_cast<byte*>(start);
146 int result = madvise(start, length, MADV_DONTNEED);
147 if (result == -1) {
148 PLOG(WARNING) << "madvise failed";
149 } else {
150 *reinterpret_cast<size_t*>(num_bytes) += length;
151 }
152}
153
154void Space::Trim() {
155 CHECK(mspace_ != NULL);
156 mspace_trim(mspace_, 0);
157 size_t num_bytes_released = 0;
158 mspace_walk_free_pages(mspace_, DontNeed, &num_bytes_released);
159}
160
161size_t Space::MaxAllowedFootprint() {
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700162 DCHECK(mspace_ != NULL);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700163 return mspace_max_allowed_footprint(mspace_);
164}
165
166void Space::Grow(size_t new_size) {
Elliott Hughes53b61312011-08-12 18:28:20 -0700167 UNIMPLEMENTED(FATAL);
Carl Shapiro69759ea2011-07-21 18:13:35 -0700168}
169
170} // namespace art