corda/src/zone.h

110 lines
2.3 KiB
C
Raw Normal View History

2007-12-11 00:48:09 +00:00
#ifndef ZONE_H
#define ZONE_H
#include "system.h"
#include "allocator.h"
2007-12-11 00:48:09 +00:00
namespace vm {
class Zone: public Allocator {
2007-12-11 00:48:09 +00:00
public:
class Segment {
public:
Segment(Segment* next, unsigned size): next(next), size(size) { }
2007-12-11 00:48:09 +00:00
Segment* next;
uintptr_t size;
2007-12-11 00:48:09 +00:00
uint8_t data[0];
};
Zone(System* s, Allocator* allocator, bool executable,
unsigned minimumFootprint):
2007-12-11 00:48:09 +00:00
s(s),
allocator(allocator),
executable(executable),
2007-12-11 00:48:09 +00:00
segment(0),
position(0),
minimumFootprint(minimumFootprint < sizeof(Segment) ? 0 :
minimumFootprint - sizeof(Segment))
2007-12-11 00:48:09 +00:00
{ }
~Zone() {
dispose();
}
void dispose() {
for (Segment* seg = segment, *next; seg; seg = next) {
next = seg->next;
allocator->free(seg, sizeof(Segment) + seg->size, executable);
2007-12-11 00:48:09 +00:00
}
}
bool ensure(unsigned space, bool executable) {
if (segment == 0 or position + space > segment->size) {
unsigned size = max
(space, max
(minimumFootprint, segment == 0 ? 0 : segment->size * 2))
+ sizeof(Segment);
// pad to page size
size = (size + (LikelyPageSizeInBytes - 1))
& ~(LikelyPageSizeInBytes - 1);
void* p = allocator->tryAllocate(size, executable);
if (p == 0) {
size = space + sizeof(Segment);
void* p = allocator->tryAllocate(size, executable);
if (p == 0) {
return false;
}
}
segment = new (p) Segment(segment, size - sizeof(Segment));
2007-12-11 00:48:09 +00:00
position = 0;
}
return true;
2007-12-11 00:48:09 +00:00
}
virtual void* tryAllocate(unsigned size, bool executable) {
assert(s, executable == this->executable);
2007-12-11 00:48:09 +00:00
size = pad(size);
if (ensure(size, executable)) {
void* r = segment->data + position;
position += size;
return r;
} else {
return 0;
}
}
virtual void* allocate(unsigned size, bool executable) {
assert(s, executable == this->executable);
void* p = tryAllocate(size, executable);
expect(s, p);
return p;
}
virtual void free(const void*, unsigned, bool) {
// not supported
abort(s);
2007-12-11 00:48:09 +00:00
}
void* allocate(unsigned size) {
return allocate(size, executable);
}
2007-12-11 00:48:09 +00:00
System* s;
Allocator* allocator;
void* context;
bool executable;
2007-12-11 00:48:09 +00:00
Segment* segment;
unsigned position;
unsigned minimumFootprint;
2007-12-11 00:48:09 +00:00
};
} // namespace vm
#endif//ZONE_H