refactor memory allocation to allow better detection and handling of low-memory conditions

This commit is contained in:
Joel Dice 2008-01-13 15:05:08 -07:00
parent e6aea41a88
commit 0298865efa
19 changed files with 490 additions and 377 deletions

View File

@ -8,9 +8,9 @@ namespace vm {
class Allocator { class Allocator {
public: public:
virtual ~Allocator() { } virtual ~Allocator() { }
virtual void* tryAllocate(unsigned size) = 0; virtual void* tryAllocate(void* context, unsigned size, bool executable) = 0;
virtual void* allocate(unsigned size) = 0; virtual void* allocate(void* context, unsigned size, bool executable) = 0;
virtual void free(const void* p, unsigned size) = 0; virtual void free(const void* p, unsigned size, bool executable) = 0;
}; };
} // namespace vm } // namespace vm

View File

@ -123,10 +123,11 @@ Java_java_lang_ClassLoader_defineClass
{ {
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
uint8_t* buffer = static_cast<uint8_t*>(t->m->system->allocate(length)); uint8_t* buffer = static_cast<uint8_t*>
(t->m->heap->allocate(t, length, false));
memcpy(buffer, &byteArrayBody(t, *b, offset), length); memcpy(buffer, &byteArrayBody(t, *b, offset), length);
object c = parseClass(t, buffer, length); object c = parseClass(t, buffer, length);
t->m->system->free(buffer, length); t->m->heap->free(buffer, length, false);
return makeLocalReference(t, c); return makeLocalReference(t, c);
} }

View File

@ -439,27 +439,27 @@ class Context {
Context(MyThread* t, object method, uint8_t* indirectCaller): Context(MyThread* t, object method, uint8_t* indirectCaller):
t(t), t(t),
zone(t->m->system, t->m->system, 16 * 1024), zone(t->m->system, t->m->heap, t, false, 16 * 1024),
c(makeCompiler(t->m->system, &zone, indirectCaller)), c(makeCompiler(t->m->system, t->m->heap, t, &zone, indirectCaller)),
method(method), method(method),
objectPool(0), objectPool(0),
traceLog(0), traceLog(0),
visitTable(makeVisitTable(t, &zone, method)), visitTable(makeVisitTable(t, &zone, method)),
rootTable(makeRootTable(t, &zone, method)), rootTable(makeRootTable(t, &zone, method)),
eventLog(t->m->system, 1024), eventLog(t->m->system, t->m->heap, t, 1024),
protector(this) protector(this)
{ } { }
Context(MyThread* t): Context(MyThread* t):
t(t), t(t),
zone(t->m->system, t->m->system, LikelyPageSizeInBytes), zone(t->m->system, t->m->heap, t, false, LikelyPageSizeInBytes),
c(makeCompiler(t->m->system, &zone, 0)), c(makeCompiler(t->m->system, t->m->heap, t, &zone, 0)),
method(0), method(0),
objectPool(0), objectPool(0),
traceLog(0), traceLog(0),
visitTable(0), visitTable(0),
rootTable(0), rootTable(0),
eventLog(t->m->system, 0), eventLog(t->m->system, t->m->heap, t, 0),
protector(this) protector(this)
{ } { }
@ -3644,7 +3644,7 @@ finish(MyThread* t, Context* context, const char* name)
unsigned size = count + singletonMaskSize(count); unsigned size = count + singletonMaskSize(count);
object result = allocate3 object result = allocate3
(t, codeAllocator(t), Machine::ImmortalAllocation, (t, codeAllocator(t), Machine::ImmortalAllocation,
SingletonBody + (size * BytesPerWord), true); SingletonBody + (size * BytesPerWord), true, true);
initSingleton(t, result, size, true); initSingleton(t, result, size, true);
mark(t, result, 0); mark(t, result, 0);
singletonMask(t, result)[0] = 1; singletonMask(t, result)[0] = 1;
@ -4349,21 +4349,22 @@ class SegFaultHandler: public System::SignalHandler {
class MyProcessor: public Processor { class MyProcessor: public Processor {
public: public:
MyProcessor(System* s): MyProcessor(System* s, Allocator* allocator):
s(s), s(s),
allocator(allocator),
defaultCompiled(0), defaultCompiled(0),
nativeCompiled(0), nativeCompiled(0),
addressTable(0), addressTable(0),
addressCount(0), addressCount(0),
indirectCaller(0), indirectCaller(0),
indirectCallerSize(0), indirectCallerSize(0),
codeAllocator(s, s->codeAllocator(), 64 * 1024) codeAllocator(s, allocator, 0, true, 64 * 1024)
{ } { }
virtual Thread* virtual Thread*
makeThread(Machine* m, object javaThread, Thread* parent) makeThread(Machine* m, object javaThread, Thread* parent)
{ {
MyThread* t = new (s->allocate(sizeof(MyThread))) MyThread* t = new (m->heap->allocate(parent, sizeof(MyThread), false))
MyThread(m, javaThread, parent); MyThread(m, javaThread, parent);
t->init(); t->init();
return t; return t;
@ -4501,8 +4502,9 @@ class MyProcessor: public Processor {
{ {
if (o) { if (o) {
MyThread* t = static_cast<MyThread*>(vmt); MyThread* t = static_cast<MyThread*>(vmt);
PROTECT(t, o);
Reference* r = new (t->m->system->allocate(sizeof(Reference))) Reference* r = new (t->m->heap->allocate(t, sizeof(Reference), false))
Reference(o, &(t->reference)); Reference(o, &(t->reference));
return &(r->target); return &(r->target);
@ -4611,7 +4613,7 @@ class MyProcessor: public Processor {
vm::dispose(t, t->reference); vm::dispose(t, t->reference);
} }
s->free(t, sizeof(*t)); t->m->heap->free(t, sizeof(*t), false);
} }
virtual void dispose() { virtual void dispose() {
@ -4619,10 +4621,11 @@ class MyProcessor: public Processor {
s->handleSegFault(0); s->handleSegFault(0);
s->free(this, sizeof(*this)); allocator->free(this, sizeof(*this), false);
} }
System* s; System* s;
Allocator* allocator;
object defaultCompiled; object defaultCompiled;
object nativeCompiled; object nativeCompiled;
object addressTable; object addressTable;
@ -4659,11 +4662,11 @@ processor(MyThread* t)
if (Verbose) { if (Verbose) {
logCompile(p->indirectCaller, c->codeSize(), 0, "indirect caller", 0); logCompile(p->indirectCaller, c->codeSize(), 0, "indirect caller", 0);
} }
}
p->segFaultHandler.m = t->m; p->segFaultHandler.m = t->m;
expect(t, t->m->system->success expect(t, t->m->system->success
(t->m->system->handleSegFault(&(p->segFaultHandler)))); (t->m->system->handleSegFault(&(p->segFaultHandler))));
}
} }
return p; return p;
} }
@ -4802,9 +4805,10 @@ codeAllocator(MyThread* t) {
namespace vm { namespace vm {
Processor* Processor*
makeProcessor(System* system) makeProcessor(System* system, Allocator* allocator)
{ {
return new (system->allocate(sizeof(MyProcessor))) MyProcessor(system); return new (allocator->allocate(0, sizeof(MyProcessor), false))
MyProcessor(system, allocator);
} }
} // namespace vm } // namespace vm

View File

@ -137,11 +137,12 @@ class RegisterData {
class Context { class Context {
public: public:
Context(System* s, Zone* zone, void* indirectCaller): Context(System* s, Allocator* allocator, void* allocatorContext, Zone* zone,
void* indirectCaller):
s(s), s(s),
constantPool(s, BytesPerWord * 32), constantPool(s, allocator, allocatorContext, BytesPerWord * 32),
plan(s, 1024), plan(s, allocator, allocatorContext, 1024),
code(s, 1024), code(s, allocator, allocatorContext, 1024),
zone(zone), zone(zone),
indirectCaller(reinterpret_cast<intptr_t>(indirectCaller)), indirectCaller(reinterpret_cast<intptr_t>(indirectCaller)),
segmentTable(0), segmentTable(0),
@ -2381,8 +2382,9 @@ writeCode(Context* c)
class MyCompiler: public Compiler { class MyCompiler: public Compiler {
public: public:
MyCompiler(System* s, Zone* zone, void* indirectCaller): MyCompiler(System* s, Allocator* allocator, void* allocatorContext,
c(s, zone, indirectCaller) Zone* zone, void* indirectCaller):
c(s, allocator, allocatorContext, zone, indirectCaller)
{ } { }
virtual Promise* machineIp(unsigned logicalIp) { virtual Promise* machineIp(unsigned logicalIp) {
@ -2868,10 +2870,11 @@ MyPromise::value(Compiler* compiler)
namespace vm { namespace vm {
Compiler* Compiler*
makeCompiler(System* system, Zone* zone, void* indirectCaller) makeCompiler(System* system, Allocator* allocator, void* allocatorContext,
Zone* zone, void* indirectCaller)
{ {
return new (zone->allocate(sizeof(MyCompiler))) return new (zone->allocate(sizeof(MyCompiler)))
MyCompiler(system, zone, indirectCaller); MyCompiler(system, allocator, allocatorContext, zone, indirectCaller);
} }
} // namespace v } // namespace v

View File

@ -141,7 +141,8 @@ class Compiler {
}; };
Compiler* Compiler*
makeCompiler(System* system, Zone* zone, void* indirectCaller); makeCompiler(System* system, Allocator* allocator, void* allocatorContext,
Zone* zone, void* indirectCaller);
} // namespace vm } // namespace vm

View File

@ -6,6 +6,20 @@ using namespace vm;
namespace { namespace {
void*
allocate(System* s, unsigned size)
{
void* p = s->tryAllocate(size, false);
if (p == 0) abort();
return p;
}
void
free(System* s, const void* p, unsigned size)
{
s->free(p, size, false);
}
const char* const char*
append(System* s, unsigned* length, const char* a, const char* b, append(System* s, unsigned* length, const char* a, const char* b,
const char* c) const char* c)
@ -14,7 +28,7 @@ append(System* s, unsigned* length, const char* a, const char* b,
unsigned bl = strlen(b); unsigned bl = strlen(b);
unsigned cl = strlen(c); unsigned cl = strlen(c);
*length = al + bl + cl; *length = al + bl + cl;
char* p = static_cast<char*>(s->allocate(*length + 1)); char* p = static_cast<char*>(allocate(s, *length + 1));
memcpy(p, a, al); memcpy(p, a, al);
memcpy(p + al, b, bl); memcpy(p + al, b, bl);
memcpy(p + al + bl, c, cl + 1); memcpy(p + al + bl, c, cl + 1);
@ -26,7 +40,7 @@ copy(System* s, unsigned* length, const char* a)
{ {
unsigned al = strlen(a); unsigned al = strlen(a);
*length = al; *length = al;
char* p = static_cast<char*>(s->allocate(*length + 1)); char* p = static_cast<char*>(allocate(s, *length + 1));
memcpy(p, a, al + 1); memcpy(p, a, al + 1);
return p; return p;
} }
@ -63,7 +77,7 @@ class DirectoryElement: public Element {
const char* file = append(s, &length, this->name, "/", name); const char* file = append(s, &length, this->name, "/", name);
System::Region* region; System::Region* region;
System::Status status = s->map(&region, file); System::Status status = s->map(&region, file);
s->free(file, length + 1); free(s, file, length + 1);
if (s->success(status)) { if (s->success(status)) {
return region; return region;
@ -76,13 +90,13 @@ class DirectoryElement: public Element {
unsigned length; unsigned length;
const char* file = append(s, &length, this->name, "/", name); const char* file = append(s, &length, this->name, "/", name);
System::FileType type = s->identify(file); System::FileType type = s->identify(file);
s->free(file, length + 1); free(s, file, length + 1);
return type != System::DoesNotExist; return type != System::DoesNotExist;
} }
virtual void dispose() { virtual void dispose() {
s->free(name, nameLength + 1); free(s, name, nameLength + 1);
s->free(this, sizeof(*this)); free(s, this, sizeof(*this));
} }
System* s; System* s;
@ -107,7 +121,7 @@ class PointerRegion: public System::Region {
} }
virtual void dispose() { virtual void dispose() {
s->free(this, sizeof(*this)); free(s, this, sizeof(*this));
} }
System* s; System* s;
@ -131,7 +145,7 @@ class DataRegion: public System::Region {
} }
virtual void dispose() { virtual void dispose() {
s->free(this, sizeof(*this) + length_); free(s, this, sizeof(*this) + length_);
} }
System* s; System* s;
@ -163,7 +177,7 @@ class JarIndex {
s(s), s(s),
capacity(capacity), capacity(capacity),
position(0), position(0),
nodes(static_cast<Node*>(s->allocate(sizeof(Node) * capacity))) nodes(static_cast<Node*>(allocate(s, sizeof(Node) * capacity)))
{ {
memset(table, 0, sizeof(Node*) * capacity); memset(table, 0, sizeof(Node*) * capacity);
} }
@ -220,7 +234,7 @@ class JarIndex {
static JarIndex* make(System* s, unsigned capacity) { static JarIndex* make(System* s, unsigned capacity) {
return new return new
(s->allocate(sizeof(JarIndex) + (sizeof(Node*) * capacity))) (allocate(s, sizeof(JarIndex) + (sizeof(Node*) * capacity)))
JarIndex(s, capacity); JarIndex(s, capacity);
} }
@ -276,13 +290,13 @@ class JarIndex {
const uint8_t* p = n->entry; const uint8_t* p = n->entry;
switch (compressionMethod(p)) { switch (compressionMethod(p)) {
case Stored: { case Stored: {
return new (s->allocate(sizeof(PointerRegion))) return new (allocate(s, sizeof(PointerRegion)))
PointerRegion(s, fileData(p), compressedSize(p)); PointerRegion(s, fileData(p), compressedSize(p));
} break; } break;
case Deflated: { case Deflated: {
DataRegion* region = new DataRegion* region = new
(s->allocate(sizeof(DataRegion) + uncompressedSize(p))) (allocate(s, sizeof(DataRegion) + uncompressedSize(p)))
DataRegion(s, uncompressedSize(p)); DataRegion(s, uncompressedSize(p));
z_stream zStream; memset(&zStream, 0, sizeof(z_stream)); z_stream zStream; memset(&zStream, 0, sizeof(z_stream));
@ -317,8 +331,8 @@ class JarIndex {
} }
void dispose() { void dispose() {
s->free(nodes, sizeof(Node) * capacity); free(s, nodes, sizeof(Node) * capacity);
s->free(this, sizeof(*this) + (sizeof(Node*) * capacity)); free(s, this, sizeof(*this) + (sizeof(Node*) * capacity));
} }
System* s; System* s;
@ -361,14 +375,14 @@ class JarElement: public Element {
} }
virtual void dispose() { virtual void dispose() {
s->free(name, nameLength + 1); free(s, name, nameLength + 1);
if (index) { if (index) {
index->dispose(); index->dispose();
} }
if (region) { if (region) {
region->dispose(); region->dispose();
} }
s->free(this, sizeof(*this)); free(s, this, sizeof(*this));
} }
System* s; System* s;
@ -396,7 +410,7 @@ class BuiltinElement: public JarElement {
unsigned size; unsigned size;
uint8_t* data = function(&size); uint8_t* data = function(&size);
if (data) { if (data) {
region = new (s->allocate(sizeof(PointerRegion))) region = new (allocate(s, sizeof(PointerRegion)))
PointerRegion(s, data, size); PointerRegion(s, data, size);
index = JarIndex::open(s, region); index = JarIndex::open(s, region);
} }
@ -444,30 +458,30 @@ parsePath(System* s, const char* path)
Element* e; Element* e;
if (*token.s == '[' and token.s[token.length - 1] == ']') { if (*token.s == '[' and token.s[token.length - 1] == ']') {
char* name = static_cast<char*>(s->allocate(token.length - 1)); char* name = static_cast<char*>(allocate(s, token.length - 1));
memcpy(name, token.s + 1, token.length - 1); memcpy(name, token.s + 1, token.length - 1);
name[token.length - 2] = 0; name[token.length - 2] = 0;
e = new (s->allocate(sizeof(BuiltinElement))) e = new (allocate(s, sizeof(BuiltinElement)))
BuiltinElement(s, name, token.length - 2); BuiltinElement(s, name, token.length - 2);
} else { } else {
char* name = static_cast<char*>(s->allocate(token.length + 1)); char* name = static_cast<char*>(allocate(s, token.length + 1));
memcpy(name, token.s, token.length); memcpy(name, token.s, token.length);
name[token.length] = 0; name[token.length] = 0;
switch (s->identify(name)) { switch (s->identify(name)) {
case System::File: { case System::File: {
e = new (s->allocate(sizeof(JarElement))) e = new (allocate(s, sizeof(JarElement)))
JarElement(s, name, token.length); JarElement(s, name, token.length);
} break; } break;
case System::Directory: { case System::Directory: {
e = new (s->allocate(sizeof(DirectoryElement))) e = new (allocate(s, sizeof(DirectoryElement)))
DirectoryElement(s, name, token.length); DirectoryElement(s, name, token.length);
} break; } break;
default: { default: {
s->free(name, token.length + 1); free(s, name, token.length + 1);
e = 0; e = 0;
} break; } break;
} }
@ -525,8 +539,8 @@ class MyFinder: public Finder {
e = e->next; e = e->next;
t->dispose(); t->dispose();
} }
system->free(pathString, pathStringLength + 1); free(system, pathString, pathStringLength + 1);
system->free(this, sizeof(*this)); free(system, this, sizeof(*this));
} }
System* system; System* system;
@ -542,7 +556,7 @@ namespace vm {
Finder* Finder*
makeFinder(System* s, const char* path) makeFinder(System* s, const char* path)
{ {
return new (s->allocate(sizeof(MyFinder))) MyFinder(s, path); return new (allocate(s, sizeof(MyFinder))) MyFinder(s, path);
} }
} // namespace vm } // namespace vm

View File

@ -3,6 +3,7 @@
#include "common.h" #include "common.h"
#include "system.h" #include "system.h"
#include "allocator.h"
namespace vm { namespace vm {

View File

@ -17,11 +17,29 @@ const unsigned Top = ~static_cast<unsigned>(0);
const unsigned InitialGen2CapacityInBytes = 4 * 1024 * 1024; const unsigned InitialGen2CapacityInBytes = 4 * 1024 * 1024;
const unsigned InitialTenuredFixieCeilingInBytes = 4 * 1024 * 1024; const unsigned InitialTenuredFixieCeilingInBytes = 4 * 1024 * 1024;
const unsigned MajorCollectionInterval = 16;
const bool Verbose = false; const bool Verbose = false;
const bool Verbose2 = false; const bool Verbose2 = false;
const bool Debug = false; const bool Debug = false;
const bool DebugFixies = false; const bool DebugFixies = false;
#define ACQUIRE(x) MutexLock MAKE_NAME(monitorLock_) (x)
class MutexLock {
public:
MutexLock(System::Mutex* m): m(m) {
m->acquire();
}
~MutexLock() {
m->release();
}
private:
System::Mutex* m;
};
class Context; class Context;
void NO_RETURN abort(Context*); void NO_RETURN abort(Context*);
@ -30,6 +48,9 @@ void assert(Context*, bool);
#endif #endif
System* system(Context*); System* system(Context*);
void* tryAllocate(Context* c, void* clientContext, unsigned size,
bool executable);
void free(Context* c, const void* p, unsigned size, bool executable);
inline void* inline void*
get(void* o, unsigned offsetInWords) get(void* o, unsigned offsetInWords)
@ -284,8 +305,9 @@ class Segment {
capacity_ = desired; capacity_ = desired;
while (data == 0) { while (data == 0) {
data = static_cast<uintptr_t*> data = static_cast<uintptr_t*>
(system(context)->tryAllocate (tryAllocate
((capacity_ + mapFootprint(capacity_)) * BytesPerWord)); (context, 0, (capacity_ + mapFootprint(capacity_)) * BytesPerWord,
false));
if (data == 0) { if (data == 0) {
if (capacity_ > minimum) { if (capacity_ > minimum) {
@ -323,8 +345,8 @@ class Segment {
void replaceWith(Segment* s) { void replaceWith(Segment* s) {
if (data) { if (data) {
system(context)->free free(context, data,
(data, (capacity() + mapFootprint(capacity())) * BytesPerWord); (capacity() + mapFootprint(capacity())) * BytesPerWord, false);
} }
data = s->data; data = s->data;
s->data = 0; s->data = 0;
@ -375,8 +397,8 @@ class Segment {
} }
void dispose() { void dispose() {
system(context)->free free(context, data,
(data, (capacity() + mapFootprint(capacity())) * BytesPerWord); (capacity() + mapFootprint(capacity())) * BytesPerWord, false);
data = 0; data = 0;
map = 0; map = 0;
} }
@ -468,9 +490,12 @@ free(Context* c, Fixie** fixies);
class Context { class Context {
public: public:
Context(System* system, Heap::Client* client): Context(System* system, unsigned limit):
system(system), system(system),
client(client), client(0),
count(0),
limit(limit),
lock(0),
ageMap(&gen1, max(1, log(TenureThreshold)), 1, 0, false), ageMap(&gen1, max(1, log(TenureThreshold)), 1, 0, false),
gen1(this, &ageMap, 0, 0), gen1(this, &ageMap, 0, 0),
@ -507,24 +532,38 @@ class Context {
markedFixies(0), markedFixies(0),
visitedFixies(0), visitedFixies(0),
majorCollectionCountdown(0),
lastCollectionTime(system->now()), lastCollectionTime(system->now()),
totalCollectionTime(0), totalCollectionTime(0),
totalTime(0) totalTime(0)
{ } {
if (not system->success(system->make(&lock))) {
system->abort();
}
}
void dispose() { void dispose() {
gen1.dispose(); gen1.dispose();
nextGen1.dispose(); nextGen1.dispose();
gen2.dispose(); gen2.dispose();
nextGen2.dispose(); nextGen2.dispose();
lock->dispose();
}
void disposeFixies() {
free(this, &tenuredFixies); free(this, &tenuredFixies);
free(this, &dirtyTenuredFixies); free(this, &dirtyTenuredFixies);
free(this, &fixies); free(this, &fixies);
client->dispose();
} }
System* system; System* system;
Heap::Client* client; Heap::Client* client;
unsigned count;
unsigned limit;
System::Mutex* lock;
Segment::Map ageMap; Segment::Map ageMap;
Segment gen1; Segment gen1;
@ -561,6 +600,8 @@ class Context {
Fixie* markedFixies; Fixie* markedFixies;
Fixie* visitedFixies; Fixie* visitedFixies;
unsigned majorCollectionCountdown;
int64_t lastCollectionTime; int64_t lastCollectionTime;
int64_t totalCollectionTime; int64_t totalCollectionTime;
int64_t totalTime; int64_t totalTime;
@ -706,7 +747,7 @@ free(Context* c, Fixie** fixies)
if (DebugFixies) { if (DebugFixies) {
fprintf(stderr, "free fixie %p\n", f); fprintf(stderr, "free fixie %p\n", f);
} }
c->system->free(f, f->totalSize()); free(c, f, f->totalSize(), false);
} }
} }
} }
@ -1459,6 +1500,17 @@ collect(Context* c, unsigned footprint)
} }
c->mode = Heap::MajorCollection; c->mode = Heap::MajorCollection;
} else if (c->mode == Heap::MinorCollection
and c->majorCollectionCountdown)
{
-- c->majorCollectionCountdown;
if (c->majorCollectionCountdown == 0) {
if (Verbose) {
fprintf(stderr, "countdown causes ");
}
c->mode = Heap::MajorCollection;
}
} }
int64_t then; int64_t then;
@ -1475,6 +1527,7 @@ collect(Context* c, unsigned footprint)
initNextGen1(c, footprint); initNextGen1(c, footprint);
if (c->mode == Heap::MajorCollection) { if (c->mode == Heap::MajorCollection) {
c->majorCollectionCountdown = MajorCollectionInterval;
initNextGen2(c); initNextGen2(c);
} }
@ -1525,9 +1578,63 @@ collect(Context* c, unsigned footprint)
} }
} }
void* tryAllocate(Context* c, void* clientContext, unsigned size,
bool executable)
{
ACQUIRE(c->lock);
if (clientContext and size + c->count >= c->limit) {
c->client->collect(clientContext, Heap::MajorCollection);
}
if (size + c->count < c->limit) {
void* p = c->system->tryAllocate(size, executable);
if (p) {
c->count += size;
return p;
}
}
return 0;
}
void free(Context* c, const void* p, unsigned size, bool executable) {
ACQUIRE(c->lock);
expect(c->system, c->count >= size);
c->system->free(p, size, executable);
c->count -= size;
}
void free_(Context* c, const void* p, unsigned size, bool executable) {
free(c, p, size, executable);
}
class MyHeap: public Heap { class MyHeap: public Heap {
public: public:
MyHeap(System* system, Heap::Client* client): c(system, client) { } MyHeap(System* system, unsigned limit):
c(system, limit)
{ }
virtual void setClient(Heap::Client* client) {
assert(&c, c.client == 0);
c.client = client;
}
virtual void* tryAllocate(void* clientContext, unsigned size,
bool executable)
{
return ::tryAllocate(&c, clientContext, size, executable);
}
virtual void* allocate(void* clientContext, unsigned size, bool executable) {
void* p = ::tryAllocate(&c, clientContext, size, executable);
expect(c.system, p);
return p;
}
virtual void free(const void* p, unsigned size, bool executable) {
free_(&c, p, size, executable);
}
virtual void collect(CollectionType type, unsigned footprint) { virtual void collect(CollectionType type, unsigned footprint) {
c.mode = type; c.mode = type;
@ -1535,19 +1642,21 @@ class MyHeap: public Heap {
::collect(&c, footprint); ::collect(&c, footprint);
} }
virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords, virtual void* allocateFixed(Allocator* allocator, void* clientContext,
bool objectMask, unsigned* totalInBytes) unsigned sizeInWords, bool objectMask,
unsigned* totalInBytes)
{ {
*totalInBytes = Fixie::totalSize(sizeInWords, objectMask); *totalInBytes = Fixie::totalSize(sizeInWords, objectMask);
return (new (allocator->allocate(*totalInBytes)) return (new (allocator->allocate(clientContext, *totalInBytes, false))
Fixie(sizeInWords, objectMask, &(c.fixies), false))->body(); Fixie(sizeInWords, objectMask, &(c.fixies), false))->body();
} }
virtual void* allocateImmortal(Allocator* allocator, unsigned sizeInWords, virtual void* allocateImmortal(Allocator* allocator, void* clientContext,
unsigned sizeInWords, bool executable,
bool objectMask, unsigned* totalInBytes) bool objectMask, unsigned* totalInBytes)
{ {
*totalInBytes = Fixie::totalSize(sizeInWords, objectMask); *totalInBytes = Fixie::totalSize(sizeInWords, objectMask);
return (new (allocator->allocate(*totalInBytes)) return (new (allocator->allocate(clientContext, *totalInBytes, executable))
Fixie(sizeInWords, objectMask, &(c.tenuredFixies), true))->body(); Fixie(sizeInWords, objectMask, &(c.tenuredFixies), true))->body();
} }
@ -1650,9 +1759,14 @@ class MyHeap: public Heap {
return c.mode; return c.mode;
} }
virtual void disposeFixies() {
c.disposeFixies();
}
virtual void dispose() { virtual void dispose() {
c.dispose(); c.dispose();
c.system->free(this, sizeof(*this)); assert(&c, c.count == 0);
c.system->free(this, sizeof(*this), false);
} }
Context c; Context c;
@ -1663,9 +1777,10 @@ class MyHeap: public Heap {
namespace vm { namespace vm {
Heap* Heap*
makeHeap(System* system, Heap::Client* client) makeHeap(System* system, unsigned limit)
{ {
return new (system->allocate(sizeof(MyHeap))) MyHeap(system, client); return new (system->tryAllocate(sizeof(MyHeap), false))
MyHeap(system, limit);
} }
} // namespace vm } // namespace vm

View File

@ -2,11 +2,11 @@
#define HEAP_H #define HEAP_H
#include "system.h" #include "system.h"
#include "zone.h" #include "allocator.h"
namespace vm { namespace vm {
class Heap { class Heap: public Allocator {
public: public:
enum CollectionType { enum CollectionType {
MinorCollection, MinorCollection,
@ -35,20 +35,23 @@ class Heap {
class Client { class Client {
public: public:
virtual ~Client() { } virtual ~Client() { }
virtual void collect(void* context, CollectionType type) = 0;
virtual void visitRoots(Visitor*) = 0; virtual void visitRoots(Visitor*) = 0;
virtual bool isFixed(void*) = 0; virtual bool isFixed(void*) = 0;
virtual unsigned sizeInWords(void*) = 0; virtual unsigned sizeInWords(void*) = 0;
virtual unsigned copiedSizeInWords(void*) = 0; virtual unsigned copiedSizeInWords(void*) = 0;
virtual void copy(void*, void*) = 0; virtual void copy(void*, void*) = 0;
virtual void walk(void*, Walker*) = 0; virtual void walk(void*, Walker*) = 0;
virtual void dispose() = 0;
}; };
virtual ~Heap() { } virtual ~Heap() { }
virtual void setClient(Client* client) = 0;
virtual void collect(CollectionType type, unsigned footprint) = 0; virtual void collect(CollectionType type, unsigned footprint) = 0;
virtual void* allocateFixed(Allocator* allocator, unsigned sizeInWords, virtual void* allocateFixed(Allocator* allocator, void* context,
bool objectMask, unsigned* totalInBytes) = 0; unsigned sizeInWords, bool objectMask,
virtual void* allocateImmortal(Allocator* allocator, unsigned sizeInWords, unsigned* totalInBytes) = 0;
virtual void* allocateImmortal(Allocator* allocator, void* context,
unsigned sizeInWords, bool executable,
bool objectMask, unsigned* totalInBytes) = 0; bool objectMask, unsigned* totalInBytes) = 0;
virtual bool needsMark(void* p) = 0; virtual bool needsMark(void* p) = 0;
virtual void mark(void* p, unsigned offset, unsigned count) = 0; virtual void mark(void* p, unsigned offset, unsigned count) = 0;
@ -56,10 +59,11 @@ class Heap {
virtual void* follow(void* p) = 0; virtual void* follow(void* p) = 0;
virtual Status status(void* p) = 0; virtual Status status(void* p) = 0;
virtual CollectionType collectionType() = 0; virtual CollectionType collectionType() = 0;
virtual void disposeFixies() = 0;
virtual void dispose() = 0; virtual void dispose() = 0;
}; };
Heap* makeHeap(System* system, Heap::Client* client); Heap* makeHeap(System* system, unsigned limit);
} // namespace vm } // namespace vm

View File

@ -2194,7 +2194,7 @@ interpret(Thread* t)
} goto loop; } goto loop;
case lushr: { case lushr: {
int64_t b = popLong(t); int64_t b = popInt(t);
uint64_t a = popLong(t); uint64_t a = popLong(t);
pushLong(t, a >> b); pushLong(t, a >> b);
@ -2812,14 +2812,14 @@ invoke(Thread* t, object method)
class MyProcessor: public Processor { class MyProcessor: public Processor {
public: public:
MyProcessor(System* s): MyProcessor(System* s, Allocator* allocator):
s(s) s(s), allocator(allocator)
{ } { }
virtual vm::Thread* virtual vm::Thread*
makeThread(Machine* m, object javaThread, vm::Thread* parent) makeThread(Machine* m, object javaThread, vm::Thread* parent)
{ {
Thread* t = new (s->allocate(sizeof(Thread))) Thread* t = new (m->heap->allocate(parent, sizeof(Thread), false))
Thread(m, javaThread, parent); Thread(m, javaThread, parent);
t->init(); t->init();
return t; return t;
@ -3016,14 +3016,15 @@ class MyProcessor: public Processor {
} }
virtual void dispose(vm::Thread* t) { virtual void dispose(vm::Thread* t) {
s->free(t, sizeof(Thread)); t->m->heap->free(t, sizeof(Thread), false);
} }
virtual void dispose() { virtual void dispose() {
s->free(this, sizeof(*this)); allocator->free(this, sizeof(*this), false);
} }
System* s; System* s;
Allocator* allocator;
}; };
} // namespace } // namespace
@ -3031,9 +3032,10 @@ class MyProcessor: public Processor {
namespace vm { namespace vm {
Processor* Processor*
makeProcessor(System* system) makeProcessor(System* system, Allocator* allocator)
{ {
return new (system->allocate(sizeof(MyProcessor))) MyProcessor(system); return new (allocator->allocate(0, sizeof(MyProcessor), false))
MyProcessor(system, allocator);
} }
} // namespace vm } // namespace vm

View File

@ -19,6 +19,7 @@ jint JNICALL
DestroyJavaVM(Machine* m) DestroyJavaVM(Machine* m)
{ {
System* s = m->system; System* s = m->system;
Heap* h = m->heap;
Processor* p = m->processor; Processor* p = m->processor;
Finder* f = m->finder; Finder* f = m->finder;
Thread* t = m->rootThread; Thread* t = m->rootThread;
@ -28,7 +29,9 @@ DestroyJavaVM(Machine* m)
t->exit(); t->exit();
m->dispose(); m->dispose();
h->disposeFixies();
p->dispose(); p->dispose();
h->dispose();
f->dispose(); f->dispose();
s->dispose(); s->dispose();
@ -88,7 +91,7 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
char* chars = static_cast<char*> char* chars = static_cast<char*>
(t->m->system->allocate(stringLength(t, *s) + 1)); (t->m->heap->allocate(t, stringLength(t, *s) + 1, false));
stringChars(t, *s, chars); stringChars(t, *s, chars);
if (isCopy) *isCopy = true; if (isCopy) *isCopy = true;
@ -98,7 +101,7 @@ GetStringUTFChars(Thread* t, jstring s, jboolean* isCopy)
void JNICALL void JNICALL
ReleaseStringUTFChars(Thread* t, jstring s, const char* chars) ReleaseStringUTFChars(Thread* t, jstring s, const char* chars)
{ {
t->m->system->free(chars, stringLength(t, *s) + 1); t->m->heap->free(chars, stringLength(t, *s) + 1, false);
} }
jsize JNICALL jsize JNICALL
@ -1106,7 +1109,7 @@ NewGlobalRef(Thread* t, jobject o)
ACQUIRE(t, t->m->referenceLock); ACQUIRE(t, t->m->referenceLock);
if (o) { if (o) {
Reference* r = new (t->m->system->allocate(sizeof(Reference))) Reference* r = new (t->m->heap->allocate(t, sizeof(Reference), false))
Reference(*o, &(t->m->jniReferences)); Reference(*o, &(t->m->jniReferences));
return &(r->target); return &(r->target);
@ -1251,7 +1254,7 @@ GetBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = booleanArrayLength(t, *array) * sizeof(jboolean); unsigned size = booleanArrayLength(t, *array) * sizeof(jboolean);
jboolean* p = static_cast<jboolean*>(t->m->system->allocate(size)); jboolean* p = static_cast<jboolean*>(t->m->heap->allocate(t, size, false));
if (size) { if (size) {
memcpy(p, &booleanArrayBody(t, *array, 0), size); memcpy(p, &booleanArrayBody(t, *array, 0), size);
} }
@ -1269,7 +1272,7 @@ GetByteArrayElements(Thread* t, jbyteArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = byteArrayLength(t, *array) * sizeof(jbyte); unsigned size = byteArrayLength(t, *array) * sizeof(jbyte);
jbyte* p = static_cast<jbyte*>(t->m->system->allocate(size)); jbyte* p = static_cast<jbyte*>(t->m->heap->allocate(t, size, false));
if (size) { if (size) {
memcpy(p, &byteArrayBody(t, *array, 0), size); memcpy(p, &byteArrayBody(t, *array, 0), size);
} }
@ -1287,7 +1290,7 @@ GetCharArrayElements(Thread* t, jcharArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = charArrayLength(t, *array) * sizeof(jchar); unsigned size = charArrayLength(t, *array) * sizeof(jchar);
jchar* p = static_cast<jchar*>(t->m->system->allocate(size)); jchar* p = static_cast<jchar*>(t->m->heap->allocate(t, size, false));
if (size) { if (size) {
memcpy(p, &charArrayBody(t, *array, 0), size); memcpy(p, &charArrayBody(t, *array, 0), size);
} }
@ -1305,7 +1308,7 @@ GetShortArrayElements(Thread* t, jshortArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = shortArrayLength(t, *array) * sizeof(jshort); unsigned size = shortArrayLength(t, *array) * sizeof(jshort);
jshort* p = static_cast<jshort*>(t->m->system->allocate(size)); jshort* p = static_cast<jshort*>(t->m->heap->allocate(t, size, false));
if (size) { if (size) {
memcpy(p, &shortArrayBody(t, *array, 0), size); memcpy(p, &shortArrayBody(t, *array, 0), size);
} }
@ -1323,7 +1326,7 @@ GetIntArrayElements(Thread* t, jintArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = intArrayLength(t, *array) * sizeof(jint); unsigned size = intArrayLength(t, *array) * sizeof(jint);
jint* p = static_cast<jint*>(t->m->system->allocate(size)); jint* p = static_cast<jint*>(t->m->heap->allocate(t, size, false));
if (size) { if (size) {
memcpy(p, &intArrayBody(t, *array, 0), size); memcpy(p, &intArrayBody(t, *array, 0), size);
} }
@ -1341,7 +1344,7 @@ GetLongArrayElements(Thread* t, jlongArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = longArrayLength(t, *array) * sizeof(jlong); unsigned size = longArrayLength(t, *array) * sizeof(jlong);
jlong* p = static_cast<jlong*>(t->m->system->allocate(size)); jlong* p = static_cast<jlong*>(t->m->heap->allocate(t, size, false));
if (size) { if (size) {
memcpy(p, &longArrayBody(t, *array, 0), size); memcpy(p, &longArrayBody(t, *array, 0), size);
} }
@ -1359,7 +1362,7 @@ GetFloatArrayElements(Thread* t, jfloatArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = floatArrayLength(t, *array) * sizeof(jfloat); unsigned size = floatArrayLength(t, *array) * sizeof(jfloat);
jfloat* p = static_cast<jfloat*>(t->m->system->allocate(size)); jfloat* p = static_cast<jfloat*>(t->m->heap->allocate(t, size, false));
if (size) { if (size) {
memcpy(p, &floatArrayBody(t, *array, 0), size); memcpy(p, &floatArrayBody(t, *array, 0), size);
} }
@ -1377,7 +1380,7 @@ GetDoubleArrayElements(Thread* t, jdoubleArray array, jboolean* isCopy)
ENTER(t, Thread::ActiveState); ENTER(t, Thread::ActiveState);
unsigned size = doubleArrayLength(t, *array) * sizeof(jdouble); unsigned size = doubleArrayLength(t, *array) * sizeof(jdouble);
jdouble* p = static_cast<jdouble*>(t->m->system->allocate(size)); jdouble* p = static_cast<jdouble*>(t->m->heap->allocate(t, size, false));
if (size) { if (size) {
memcpy(p, &doubleArrayBody(t, *array, 0), size); memcpy(p, &doubleArrayBody(t, *array, 0), size);
} }
@ -1404,7 +1407,7 @@ ReleaseBooleanArrayElements(Thread* t, jbooleanArray array, jboolean* p,
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->system->free(p, size); t->m->heap->free(p, size, false);
} }
} }
@ -1422,7 +1425,7 @@ ReleaseByteArrayElements(Thread* t, jbyteArray array, jbyte* p, jint mode)
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->system->free(p, size); t->m->heap->free(p, size, false);
} }
} }
@ -1440,7 +1443,7 @@ ReleaseCharArrayElements(Thread* t, jcharArray array, jchar* p, jint mode)
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->system->free(p, size); t->m->heap->free(p, size, false);
} }
} }
@ -1458,7 +1461,7 @@ ReleaseShortArrayElements(Thread* t, jshortArray array, jshort* p, jint mode)
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->system->free(p, size); t->m->heap->free(p, size, false);
} }
} }
@ -1476,7 +1479,7 @@ ReleaseIntArrayElements(Thread* t, jintArray array, jint* p, jint mode)
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->system->free(p, size); t->m->heap->free(p, size, false);
} }
} }
@ -1494,7 +1497,7 @@ ReleaseLongArrayElements(Thread* t, jlongArray array, jlong* p, jint mode)
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->system->free(p, size); t->m->heap->free(p, size, false);
} }
} }
@ -1512,7 +1515,7 @@ ReleaseFloatArrayElements(Thread* t, jfloatArray array, jfloat* p, jint mode)
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->system->free(p, size); t->m->heap->free(p, size, false);
} }
} }
@ -1531,7 +1534,7 @@ ReleaseDoubleArrayElements(Thread* t, jdoubleArray array, jdouble* p,
} }
if (mode == 0 or mode == JNI_ABORT) { if (mode == 0 or mode == JNI_ABORT) {
t->m->system->free(p, size); t->m->heap->free(p, size, false);
} }
} }
@ -1980,7 +1983,8 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
{ {
JDK1_1InitArgs* a = static_cast<JDK1_1InitArgs*>(args); JDK1_1InitArgs* a = static_cast<JDK1_1InitArgs*>(args);
System* s = makeSystem(a->maxHeapSize); System* s = makeSystem();
Heap* h = makeHeap(s, a->maxHeapSize);
unsigned size = sizeof(BUILTIN_CLASSPATH) + 1 + strlen(a->classpath); unsigned size = sizeof(BUILTIN_CLASSPATH) + 1 + strlen(a->classpath);
char classpath[size]; char classpath[size];
@ -1988,9 +1992,9 @@ JNI_CreateJavaVM(Machine** m, Thread** t, void* args)
BUILTIN_CLASSPATH, s->pathSeparator(), a->classpath); BUILTIN_CLASSPATH, s->pathSeparator(), a->classpath);
Finder* f = makeFinder(s, classpath); Finder* f = makeFinder(s, classpath);
Processor* p = makeProcessor(s); Processor* p = makeProcessor(s, h);
*m = new (s->allocate(sizeof(Machine))) Machine(s, f, p); *m = new (h->allocate(0, sizeof(Machine), false)) Machine(s, h, f, p);
if (a->properties) { if (a->properties) {
for (const char** p = a->properties; *p; ++p) { for (const char** p = a->properties; *p; ++p) {

View File

@ -482,9 +482,9 @@ void
postCollect(Thread* t) postCollect(Thread* t)
{ {
#ifdef VM_STRESS #ifdef VM_STRESS
t->m->system->free(t->defaultHeap, Thread::HeapSizeInBytes); t->allocator.free(t->defaultHeap, Thread::HeapSizeInBytes);
t->defaultHeap = static_cast<uintptr_t*> t->defaultHeap = static_cast<uintptr_t*>
(t->m->system->allocate(Thread::HeapSizeInBytes)); (t->allocator.allocate(Thread::HeapSizeInBytes));
#endif #endif
t->heap = t->defaultHeap; t->heap = t->defaultHeap;
@ -762,10 +762,11 @@ parsePool(Thread* t, Stream& s)
unsigned count = s.read2() - 1; unsigned count = s.read2() - 1;
object pool = makeSingleton(t, count); object pool = makeSingleton(t, count);
PROTECT(t, pool);
if (count) { if (count) {
uint32_t* index = static_cast<uint32_t*> uint32_t* index = static_cast<uint32_t*>
(t->m->system->allocate(count * 4)); (t->m->heap->allocate(t, count * 4, false));
for (unsigned i = 0; i < count; ++i) { for (unsigned i = 0; i < count; ++i) {
index[i] = s.position(); index[i] = s.position();
@ -807,13 +808,11 @@ parsePool(Thread* t, Stream& s)
unsigned end = s.position(); unsigned end = s.position();
PROTECT(t, pool);
for (unsigned i = 0; i < count;) { for (unsigned i = 0; i < count;) {
i += parsePoolEntry(t, s, index, pool, i); i += parsePoolEntry(t, s, index, pool, i);
} }
t->m->system->free(index, count * 4); t->m->heap->free(index, count * 4, false);
s.setPosition(end); s.setPosition(end);
} }
@ -1694,6 +1693,12 @@ class HeapClient: public Heap::Client {
postVisit(m->rootThread, v); postVisit(m->rootThread, v);
} }
virtual void collect(void* context, Heap::CollectionType type) {
Thread* t = static_cast<Thread*>(context);
ENTER(t, Thread::ExclusiveState);
collect(t, type);
}
virtual bool isFixed(void* p) { virtual bool isFixed(void* p) {
return objectFixed(m->rootThread, static_cast<object>(p)); return objectFixed(m->rootThread, static_cast<object>(p));
} }
@ -1757,8 +1762,8 @@ class HeapClient: public Heap::Client {
::walk(m->rootThread, w, o); ::walk(m->rootThread, w, o);
} }
virtual void dispose() { void dispose() {
m->system->free(this, sizeof(*this)); m->heap->free(this, sizeof(*this), false);
} }
private: private:
@ -1769,11 +1774,13 @@ class HeapClient: public Heap::Client {
namespace vm { namespace vm {
Machine::Machine(System* system, Finder* finder, Processor* processor): Machine::Machine(System* system, Heap* heap, Finder* finder,
Processor* processor):
vtable(&javaVMVTable), vtable(&javaVMVTable),
system(system), system(system),
heap(makeHeap(system, new (system->allocate(sizeof(HeapClient))) heapClient(new (heap->allocate(0, sizeof(HeapClient), false))
HeapClient(this))), HeapClient(this)),
heap(heap),
finder(finder), finder(finder),
processor(processor), processor(processor),
rootThread(0), rootThread(0),
@ -1803,6 +1810,8 @@ Machine::Machine(System* system, Finder* finder, Processor* processor):
unsafe(false), unsafe(false),
heapPoolIndex(0) heapPoolIndex(0)
{ {
heap->setClient(heapClient);
populateJNITables(&javaVMVTable, &jniEnvVTable); populateJNITables(&javaVMVTable, &jniEnvVTable);
if (not system->success(system->make(&localThread)) or if (not system->success(system->make(&localThread)) or
@ -1830,18 +1839,18 @@ Machine::dispose()
} }
for (Reference* r = jniReferences; r;) { for (Reference* r = jniReferences; r;) {
Reference* t = r; Reference* tmp = r;
r = r->next; r = r->next;
system->free(t, sizeof(*t)); heap->free(tmp, sizeof(*tmp), false);
} }
for (unsigned i = 0; i < heapPoolIndex; ++i) { for (unsigned i = 0; i < heapPoolIndex; ++i) {
system->free(heapPool[i], Thread::HeapSizeInBytes); heap->free(heapPool[i], Thread::HeapSizeInBytes, false);
} }
heap->dispose(); static_cast<HeapClient*>(heapClient)->dispose();
system->free(this, sizeof(*this)); heap->free(this, sizeof(*this), false);
} }
Thread::Thread(Machine* m, object javaThread, Thread* parent): Thread::Thread(Machine* m, object javaThread, Thread* parent):
@ -1859,7 +1868,8 @@ Thread::Thread(Machine* m, object javaThread, Thread* parent):
heapOffset(0), heapOffset(0),
protector(0), protector(0),
runnable(this), runnable(this),
defaultHeap(static_cast<uintptr_t*>(m->system->allocate(HeapSizeInBytes))), defaultHeap(static_cast<uintptr_t*>
(m->heap->allocate(parent, HeapSizeInBytes, false))),
heap(defaultHeap) heap(defaultHeap)
#ifdef VM_STRESS #ifdef VM_STRESS
, stress(false) , stress(false)
@ -1996,7 +2006,7 @@ Thread::dispose()
systemThread->dispose(); systemThread->dispose();
} }
m->system->free(defaultHeap, Thread::HeapSizeInBytes); m->heap->free(defaultHeap, Thread::HeapSizeInBytes, false);
m->processor->dispose(this); m->processor->dispose(this);
} }
@ -2145,15 +2155,15 @@ object
allocate2(Thread* t, unsigned sizeInBytes, bool objectMask) allocate2(Thread* t, unsigned sizeInBytes, bool objectMask)
{ {
return allocate3 return allocate3
(t, t->m->system, (t, t->m->heap,
ceiling(sizeInBytes, BytesPerWord) > Thread::HeapSizeInWords ? ceiling(sizeInBytes, BytesPerWord) > Thread::HeapSizeInWords ?
Machine::FixedAllocation : Machine::MovableAllocation, Machine::FixedAllocation : Machine::MovableAllocation,
sizeInBytes, objectMask); sizeInBytes, false, objectMask);
} }
object object
allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
unsigned sizeInBytes, bool objectMask) unsigned sizeInBytes, bool executable, bool objectMask)
{ {
ACQUIRE_RAW(t, t->m->stateLock); ACQUIRE_RAW(t, t->m->stateLock);
@ -2175,7 +2185,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
t->heap = 0; t->heap = 0;
if (t->m->heapPoolIndex < Machine::HeapPoolSize) { if (t->m->heapPoolIndex < Machine::HeapPoolSize) {
t->heap = static_cast<uintptr_t*> t->heap = static_cast<uintptr_t*>
(t->m->system->tryAllocate(Thread::HeapSizeInBytes)); (t->m->heap->tryAllocate(0, Thread::HeapSizeInBytes, false));
if (t->heap) { if (t->heap) {
t->m->heapPool[t->m->heapPoolIndex++] = t->heap; t->m->heapPool[t->m->heapPoolIndex++] = t->heap;
t->heapOffset += t->heapIndex; t->heapOffset += t->heapIndex;
@ -2198,7 +2208,7 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
unsigned total; unsigned total;
object o = static_cast<object> object o = static_cast<object>
(t->m->heap->allocateFixed (t->m->heap->allocateFixed
(allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total)); (allocator, t, ceiling(sizeInBytes, BytesPerWord), objectMask, &total));
cast<uintptr_t>(o, 0) = FixedMark; cast<uintptr_t>(o, 0) = FixedMark;
@ -2211,7 +2221,8 @@ allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
unsigned total; unsigned total;
object o = static_cast<object> object o = static_cast<object>
(t->m->heap->allocateImmortal (t->m->heap->allocateImmortal
(allocator, ceiling(sizeInBytes, BytesPerWord), objectMask, &total)); (allocator, t, ceiling(sizeInBytes, BytesPerWord),
executable, objectMask, &total));
cast<uintptr_t>(o, 0) = FixedMark; cast<uintptr_t>(o, 0) = FixedMark;
@ -2826,7 +2837,7 @@ collect(Thread* t, Heap::CollectionType type)
killZombies(t, m->rootThread); killZombies(t, m->rootThread);
for (unsigned i = 0; i < m->heapPoolIndex; ++i) { for (unsigned i = 0; i < m->heapPoolIndex; ++i) {
m->system->free(m->heapPool[i], Thread::HeapSizeInBytes); m->heap->free(m->heapPool[i], Thread::HeapSizeInBytes, false);
} }
m->heapPoolIndex = 0; m->heapPoolIndex = 0;

View File

@ -1111,7 +1111,7 @@ class Machine {
ImmortalAllocation ImmortalAllocation
}; };
Machine(System* system, Finder* finder, Processor* processor); Machine(System* system, Heap* heap, Finder* finder, Processor* processor);
~Machine() { ~Machine() {
dispose(); dispose();
@ -1125,6 +1125,7 @@ class Machine {
JavaVMVTable* vtable; JavaVMVTable* vtable;
System* system; System* system;
Heap::Client* heapClient;
Heap* heap; Heap* heap;
Finder* finder; Finder* finder;
Processor* processor; Processor* processor;
@ -1168,6 +1169,16 @@ threadInterrupted(Thread* t, object thread);
void void
enterActiveState(Thread* t); enterActiveState(Thread* t);
#ifdef VM_STRESS
inline void stress(Thread* t);
#else // not VM_STRESS
#define stress(t)
#endif // not VM_STRESS
class Thread { class Thread {
public: public:
enum State { enum State {
@ -1306,7 +1317,7 @@ dispose(Thread* t, Reference* r)
if (r->next) { if (r->next) {
r->next->handle = r->handle; r->next->handle = r->handle;
} }
t->m->system->free(r, sizeof(*r)); t->m->heap->free(r, sizeof(*r), false);
} }
void void
@ -1335,12 +1346,6 @@ stress(Thread* t)
} }
} }
#else // not VM_STRESS
inline void
stress(Thread*)
{ }
#endif // not VM_STRESS #endif // not VM_STRESS
inline void inline void
@ -1415,7 +1420,7 @@ allocate2(Thread* t, unsigned sizeInBytes, bool objectMask);
object object
allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type, allocate3(Thread* t, Allocator* allocator, Machine::AllocationType type,
unsigned sizeInBytes, bool objectMask); unsigned sizeInBytes, bool executable, bool objectMask);
inline object inline object
allocateSmall(Thread* t, unsigned sizeInBytes) allocateSmall(Thread* t, unsigned sizeInBytes)

View File

@ -108,6 +108,14 @@ run(void* r)
return 0; return 0;
} }
void*
allocate(System* s, unsigned size)
{
void* p = s->tryAllocate(size, false);
if (p == 0) abort();
return p;
}
const bool Verbose = false; const bool Verbose = false;
const unsigned Waiting = 1 << 0; const unsigned Waiting = 1 << 0;
@ -115,45 +123,6 @@ const unsigned Notified = 1 << 1;
class MySystem: public System { class MySystem: public System {
public: public:
class CodeAllocator: public Allocator {
public:
CodeAllocator(MySystem* s): s(s) { }
virtual void* tryAllocate(unsigned size) {
assert(s, size % LikelyPageSizeInBytes == 0);
#ifdef __x86_64__
void* p = mmap(0, size, PROT_EXEC | PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
if (p == MAP_FAILED) {
return 0;
} else {
return p;
}
#else
return s->tryAllocate(size);
#endif
}
virtual void* allocate(unsigned size) {
void* p = tryAllocate(size);
expect(s, p);
return p;
}
virtual void free(const void* p, unsigned size) {
#ifdef __x86_64__
int r UNUSED = munmap(const_cast<void*>(p), size);
assert(s, r == 0);
#else
s->free(p, size);
#endif
}
MySystem* s;
};
class Thread: public System::Thread { class Thread: public System::Thread {
public: public:
Thread(System* s, System::Runnable* r): Thread(System* s, System::Runnable* r):
@ -182,7 +151,7 @@ class MySystem: public System {
} }
virtual void dispose() { virtual void dispose() {
s->free(this, sizeof(*this)); s->free(this, sizeof(*this), false);
} }
pthread_t thread; pthread_t thread;
@ -194,6 +163,29 @@ class MySystem: public System {
unsigned flags; unsigned flags;
}; };
class Mutex: public System::Mutex {
public:
Mutex(System* s): s(s) {
pthread_mutex_init(&mutex, 0);
}
virtual void acquire() {
pthread_mutex_lock(&mutex);
}
virtual void release() {
pthread_mutex_unlock(&mutex);
}
virtual void dispose() {
pthread_mutex_destroy(&mutex);
s->free(this, sizeof(*this), false);
}
System* s;
pthread_mutex_t mutex;
};
class Monitor: public System::Monitor { class Monitor: public System::Monitor {
public: public:
Monitor(System* s): s(s), owner_(0), first(0), last(0), depth(0) { Monitor(System* s): s(s), owner_(0), first(0), last(0), depth(0) {
@ -377,7 +369,7 @@ class MySystem: public System {
virtual void dispose() { virtual void dispose() {
expect(s, owner_ == 0); expect(s, owner_ == 0);
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
s->free(this, sizeof(*this)); s->free(this, sizeof(*this), false);
} }
System* s; System* s;
@ -408,7 +400,7 @@ class MySystem: public System {
int r UNUSED = pthread_key_delete(key); int r UNUSED = pthread_key_delete(key);
expect(s, r == 0); expect(s, r == 0);
s->free(this, sizeof(*this)); s->free(this, sizeof(*this), false);
} }
System* s; System* s;
@ -435,7 +427,7 @@ class MySystem: public System {
if (start_) { if (start_) {
munmap(start_, length_); munmap(start_, length_);
} }
s->free(this, sizeof(*this)); s->free(this, sizeof(*this), false);
} }
System* s; System* s;
@ -483,10 +475,10 @@ class MySystem: public System {
} }
if (name_) { if (name_) {
s->free(name_, nameLength + 1); s->free(name_, nameLength + 1, false);
} }
s->free(this, sizeof(*this)); s->free(this, sizeof(*this), false);
} }
System* s; System* s;
@ -497,9 +489,7 @@ class MySystem: public System {
System::Library* next_; System::Library* next_;
}; };
MySystem(unsigned limit): limit(limit), count(0), codeAllocator_(this) { MySystem() {
pthread_mutex_init(&mutex, 0);
struct sigaction sa; struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction)); memset(&sa, 0, sizeof(struct sigaction));
sigemptyset(&(sa.sa_mask)); sigemptyset(&(sa.sa_mask));
@ -510,98 +500,65 @@ class MySystem: public System {
expect(this, rv == 0); expect(this, rv == 0);
} }
virtual void* tryAllocate(unsigned size) { virtual void* tryAllocate(unsigned size, bool executable) {
ACQUIRE(mutex); assert(this, (not executable) or (size % LikelyPageSizeInBytes == 0));
if (Verbose) { if (executable) {
fprintf(stderr, "try %d; count: %d; limit: %d\n", void* p = mmap(0, size, PROT_EXEC | PROT_READ | PROT_WRITE,
size, count, limit); MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
}
if (count + size > limit) { if (p == MAP_FAILED) {
return 0;
} else {
#ifndef NDEBUG
uintptr_t* up = static_cast<uintptr_t*>
(malloc(size + sizeof(uintptr_t)));
if (up == 0) {
return 0; return 0;
} else { } else {
*up = size;
count += *up;
return up + 1;
}
#else
void* p = malloc(size);
if (p == 0) {
return 0;
} else {
count += size;
return p; return p;
} }
#endif } else {
return malloc(size);
} }
} }
virtual void free(const void* p, unsigned size) { virtual void free(const void* p, unsigned size, bool executable) {
ACQUIRE(mutex);
if (Verbose) {
fprintf(stderr, "free %d; count: %d; limit: %d\n",
size, count, limit);
}
if (p) { if (p) {
#ifndef NDEBUG if (executable) {
const uintptr_t* up = static_cast<const uintptr_t*>(p) - 1; int r UNUSED = munmap(const_cast<void*>(p), size);
assert(this, r == 0);
if (*up != size) abort(); } else {
if (count < *up) abort(); ::free(const_cast<void*>(p));
}
count -= *up;
::free(const_cast<uintptr_t*>(up));
#else
if (count < size) abort();
count -= size;
::free(const_cast<void*>(p));
#endif
} }
} }
virtual Allocator* codeAllocator() {
return &codeAllocator_;
}
virtual bool success(Status s) { virtual bool success(Status s) {
return s == 0; return s == 0;
} }
virtual Status attach(Runnable* r) { virtual Status attach(Runnable* r) {
Thread* t = new (System::allocate(sizeof(Thread))) Thread(this, r); Thread* t = new (allocate(this, sizeof(Thread))) Thread(this, r);
t->thread = pthread_self(); t->thread = pthread_self();
r->attach(t); r->attach(t);
return 0; return 0;
} }
virtual Status start(Runnable* r) { virtual Status start(Runnable* r) {
Thread* t = new (System::allocate(sizeof(Thread))) Thread(this, r); Thread* t = new (allocate(this, sizeof(Thread))) Thread(this, r);
r->attach(t); r->attach(t);
int rv UNUSED = pthread_create(&(t->thread), 0, run, r); int rv UNUSED = pthread_create(&(t->thread), 0, run, r);
expect(this, rv == 0); expect(this, rv == 0);
return 0; return 0;
} }
virtual Status make(System::Mutex** m) {
*m = new (allocate(this, sizeof(Mutex))) Mutex(this);
return 0;
}
virtual Status make(System::Monitor** m) { virtual Status make(System::Monitor** m) {
*m = new (System::allocate(sizeof(Monitor))) Monitor(this); *m = new (allocate(this, sizeof(Monitor))) Monitor(this);
return 0; return 0;
} }
virtual Status make(System::Local** l) { virtual Status make(System::Local** l) {
*l = new (System::allocate(sizeof(Local))) Local(this); *l = new (allocate(this, sizeof(Local))) Local(this);
return 0; return 0;
} }
@ -640,7 +597,7 @@ class MySystem: public System {
if (r != -1) { if (r != -1) {
void* data = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0); void* data = mmap(0, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (data) { if (data) {
*region = new (allocate(sizeof(Region))) *region = new (allocate(this, sizeof(Region)))
Region(this, static_cast<uint8_t*>(data), s.st_size); Region(this, static_cast<uint8_t*>(data), s.st_size);
status = 0; status = 0;
} }
@ -690,13 +647,13 @@ class MySystem: public System {
char* n; char* n;
if (name) { if (name) {
n = static_cast<char*>(System::allocate(nameLength + 1)); n = static_cast<char*>(allocate(this, nameLength + 1));
memcpy(n, name, nameLength + 1); memcpy(n, name, nameLength + 1);
} else { } else {
n = 0; n = 0;
} }
*lib = new (System::allocate(sizeof(Library))) *lib = new (allocate(this, sizeof(Library)))
Library(this, p, n, nameLength, mapName, next); Library(this, p, n, nameLength, mapName, next);
return 0; return 0;
} else { } else {
@ -725,15 +682,8 @@ class MySystem: public System {
} }
virtual void dispose() { virtual void dispose() {
assert(this, count == 0);
pthread_mutex_destroy(&mutex);
::free(this); ::free(this);
} }
pthread_mutex_t mutex;
unsigned limit;
unsigned count;
CodeAllocator codeAllocator_;
}; };
} // namespace } // namespace
@ -741,9 +691,9 @@ class MySystem: public System {
namespace vm { namespace vm {
System* System*
makeSystem(unsigned heapSize) makeSystem()
{ {
return new (malloc(sizeof(MySystem))) MySystem(heapSize); return new (malloc(sizeof(MySystem))) MySystem();
} }
} // namespace vm } // namespace vm

View File

@ -134,7 +134,7 @@ class Processor {
}; };
Processor* Processor*
makeProcessor(System* system); makeProcessor(System* system, Allocator* allocator);
} // namespace vm } // namespace vm

View File

@ -2,11 +2,10 @@
#define SYSTEM_H #define SYSTEM_H
#include "common.h" #include "common.h"
#include "allocator.h"
namespace vm { namespace vm {
class System: public Allocator { class System {
public: public:
typedef intptr_t Status; typedef intptr_t Status;
@ -34,6 +33,14 @@ class System: public Allocator {
virtual void setInterrupted(bool v) = 0; virtual void setInterrupted(bool v) = 0;
}; };
class Mutex {
public:
virtual ~Mutex() { }
virtual void acquire() = 0;
virtual void release() = 0;
virtual void dispose() = 0;
};
class Monitor { class Monitor {
public: public:
virtual ~Monitor() { } virtual ~Monitor() { }
@ -83,10 +90,12 @@ class System: public Allocator {
virtual ~System() { } virtual ~System() { }
virtual Allocator* codeAllocator() = 0;
virtual bool success(Status) = 0; virtual bool success(Status) = 0;
virtual void* tryAllocate(unsigned size, bool executable) = 0;
virtual void free(const void* p, unsigned size, bool executable) = 0;
virtual Status attach(Runnable*) = 0; virtual Status attach(Runnable*) = 0;
virtual Status start(Runnable*) = 0; virtual Status start(Runnable*) = 0;
virtual Status make(Mutex**) = 0;
virtual Status make(Monitor**) = 0; virtual Status make(Monitor**) = 0;
virtual Status make(Local**) = 0; virtual Status make(Local**) = 0;
virtual Status handleSegFault(SignalHandler* handler) = 0; virtual Status handleSegFault(SignalHandler* handler) = 0;
@ -102,14 +111,6 @@ class System: public Allocator {
virtual void exit(int code) = 0; virtual void exit(int code) = 0;
virtual void abort() = 0; virtual void abort() = 0;
virtual void dispose() = 0; virtual void dispose() = 0;
virtual void* allocate(unsigned size) {
void* p = tryAllocate(size);
if (p == 0) {
abort();
}
return p;
}
}; };
inline void NO_RETURN inline void NO_RETURN
@ -146,7 +147,7 @@ assert(System* s, bool v)
#endif // not NDEBUG #endif // not NDEBUG
System* System*
makeSystem(unsigned heapSize); makeSystem();
} // namespace vm } // namespace vm

View File

@ -7,8 +7,11 @@ namespace vm {
class Vector { class Vector {
public: public:
Vector(System* s, unsigned minimumCapacity): Vector(System* s, Allocator* allocator, void* context,
unsigned minimumCapacity):
s(s), s(s),
allocator(allocator),
context(context),
data(0), data(0),
position(0), position(0),
capacity(0), capacity(0),
@ -21,7 +24,7 @@ class Vector {
void dispose() { void dispose() {
if (data and minimumCapacity >= 0) { if (data and minimumCapacity >= 0) {
s->free(data, capacity); allocator->free(data, capacity, false);
} }
} }
@ -40,10 +43,11 @@ class Vector {
unsigned newCapacity = max unsigned newCapacity = max
(position + space, max(minimumCapacity, capacity * 2)); (position + space, max(minimumCapacity, capacity * 2));
uint8_t* newData = static_cast<uint8_t*>(s->allocate(newCapacity)); uint8_t* newData = static_cast<uint8_t*>
(allocator->allocate(context, newCapacity, false));
if (data) { if (data) {
memcpy(newData, data, position); memcpy(newData, data, position);
s->free(data, capacity); allocator->free(data, capacity, false);
} }
data = newData; data = newData;
capacity = newCapacity; capacity = newCapacity;
@ -129,6 +133,8 @@ class Vector {
} }
System* s; System* s;
Allocator* allocator;
void* context;
uint8_t* data; uint8_t* data;
unsigned position; unsigned position;
unsigned capacity; unsigned capacity;

View File

@ -57,6 +57,14 @@ run(void* r)
return 0; return 0;
} }
void*
allocate(System* s, unsigned size)
{
void* p = s->tryAllocate(size, false);
if (p == 0) abort();
return p;
}
const bool Verbose = false; const bool Verbose = false;
const unsigned Waiting = 1 << 0; const unsigned Waiting = 1 << 0;
@ -99,7 +107,7 @@ class MySystem: public System {
CloseHandle(event); CloseHandle(event);
CloseHandle(mutex); CloseHandle(mutex);
CloseHandle(thread); CloseHandle(thread);
s->free(this, sizeof(*this)); s->free(this, sizeof(*this), false);
} }
HANDLE thread; HANDLE thread;
@ -111,6 +119,32 @@ class MySystem: public System {
unsigned flags; unsigned flags;
}; };
class Mutex: public System::Mutex {
public:
Mutex(System* s): s(s) {
mutex = CreateMutex(0, false, 0);
assert(s, mutex);
}
virtual void acquire() {
int r UNUSED = WaitForSingleObject(mutex, INFINITE);
assert(s, r == WAIT_OBJECT_0);
}
virtual void release() {
bool success UNUSED = ReleaseMutex(mutex);
assert(s, success);
}
virtual void dispose() {
CloseHandle(mutex);
s->free(this, sizeof(*this), false);
}
System* s;
HANDLE mutex;
};
class Monitor: public System::Monitor { class Monitor: public System::Monitor {
public: public:
Monitor(System* s): s(s), owner_(0), first(0), last(0), depth(0) { Monitor(System* s): s(s), owner_(0), first(0), last(0), depth(0) {
@ -309,7 +343,7 @@ class MySystem: public System {
virtual void dispose() { virtual void dispose() {
assert(s, owner_ == 0); assert(s, owner_ == 0);
CloseHandle(mutex); CloseHandle(mutex);
s->free(this, sizeof(*this)); s->free(this, sizeof(*this), false);
} }
System* s; System* s;
@ -340,7 +374,7 @@ class MySystem: public System {
bool r UNUSED = TlsFree(key); bool r UNUSED = TlsFree(key);
assert(s, r); assert(s, r);
s->free(this, sizeof(*this)); s->free(this, sizeof(*this), false);
} }
System* s; System* s;
@ -372,7 +406,7 @@ class MySystem: public System {
if (mapping) CloseHandle(mapping); if (mapping) CloseHandle(mapping);
if (file) CloseHandle(file); if (file) CloseHandle(file);
} }
system->free(this, sizeof(*this)); system->free(this, sizeof(*this), false);
} }
System* system; System* system;
@ -428,10 +462,10 @@ class MySystem: public System {
} }
if (name_) { if (name_) {
s->free(name_, nameLength+1); s->free(name_, nameLength + 1, false);
} }
s->free(this, sizeof(*this)); s->free(this, sizeof(*this), false);
} }
System* s; System* s;
@ -442,75 +476,17 @@ class MySystem: public System {
System::Library* next_; System::Library* next_;
}; };
MySystem(unsigned limit): limit(limit), count(0) { MySystem() {
mutex = CreateMutex(0, false, 0); mutex = CreateMutex(0, false, 0);
assert(this, mutex); assert(this, mutex);
} }
virtual void* tryAllocate(unsigned size) { virtual void* tryAllocate(unsigned size, bool) {
ACQUIRE(this, mutex); return malloc(size);
if (Verbose) {
fprintf(stderr, "try %d; count: %d; limit: %d\n",
size, count, limit);
}
if (count + size > limit) {
return 0;
} else {
#ifndef NDEBUG
uintptr_t* up = static_cast<uintptr_t*>
(malloc(size + sizeof(uintptr_t)));
if (up == 0) {
return 0;
} else {
*up = size;
count += *up;
return up + 1;
}
#else
void* p = malloc(size);
if (p == 0) {
return 0;
} else {
count += size;
return p;
}
#endif
}
} }
virtual void free(const void* p, unsigned size) { virtual void free(const void* p, unsigned, bool) {
ACQUIRE(this, mutex); if (p) ::free(const_cast<void*>(p));
if (Verbose) {
fprintf(stderr, "free %d; count: %d; limit: %d\n",
size, count, limit);
}
if (p) {
#ifndef NDEBUG
const uintptr_t* up = static_cast<const uintptr_t*>(p) - 1;
if (*up != size) abort();
if (count < *up) abort();
count -= *up;
::free(const_cast<uintptr_t*>(up));
#else
if (count < size) abort();
count -= size;
::free(const_cast<void*>(p));
#endif
}
}
virtual Allocator* codeAllocator() {
return this;
} }
virtual bool success(Status s) { virtual bool success(Status s) {
@ -518,7 +494,7 @@ class MySystem: public System {
} }
virtual Status attach(Runnable* r) { virtual Status attach(Runnable* r) {
Thread* t = new (System::allocate(sizeof(Thread))) Thread(this, r); Thread* t = new (allocate(this, sizeof(Thread))) Thread(this, r);
bool success UNUSED = DuplicateHandle bool success UNUSED = DuplicateHandle
(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), (GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(),
&(t->thread), 0, false, DUPLICATE_SAME_ACCESS); &(t->thread), 0, false, DUPLICATE_SAME_ACCESS);
@ -528,7 +504,7 @@ class MySystem: public System {
} }
virtual Status start(Runnable* r) { virtual Status start(Runnable* r) {
Thread* t = new (System::allocate(sizeof(Thread))) Thread(this, r); Thread* t = new (allocate(this, sizeof(Thread))) Thread(this, r);
r->attach(t); r->attach(t);
DWORD id; DWORD id;
t->thread = CreateThread(0, 0, run, r, 0, &id); t->thread = CreateThread(0, 0, run, r, 0, &id);
@ -536,13 +512,18 @@ class MySystem: public System {
return 0; return 0;
} }
virtual Status make(System::Mutex** m) {
*m = new (allocate(this, sizeof(Mutex))) Mutex(this);
return 0;
}
virtual Status make(System::Monitor** m) { virtual Status make(System::Monitor** m) {
*m = new (System::allocate(sizeof(Monitor))) Monitor(this); *m = new (allocate(this, sizeof(Monitor))) Monitor(this);
return 0; return 0;
} }
virtual Status make(System::Local** l) { virtual Status make(System::Local** l) {
*l = new (System::allocate(sizeof(Local))) Local(this); *l = new (allocate(this, sizeof(Local))) Local(this);
return 0; return 0;
} }
@ -579,7 +560,7 @@ class MySystem: public System {
if (mapping) { if (mapping) {
void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); void* data = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
if (data) { if (data) {
*region = new (allocate(sizeof(Region))) *region = new (allocate(this, sizeof(Region)))
Region(this, static_cast<uint8_t*>(data), size, file, mapping); Region(this, static_cast<uint8_t*>(data), size, file, mapping);
status = 0; status = 0;
} }
@ -639,13 +620,13 @@ class MySystem: public System {
char* n; char* n;
if (name) { if (name) {
n = static_cast<char*>(System::allocate(nameLength + 1)); n = static_cast<char*>(allocate(this, nameLength + 1));
memcpy(n, name, nameLength + 1); memcpy(n, name, nameLength + 1);
} else { } else {
n = 0; n = 0;
} }
*lib = new (System::allocate(sizeof(Library))) *lib = new (allocate(this, sizeof(Library)))
Library(this, handle, n, mapName, nameLength, next); Library(this, handle, n, mapName, nameLength, next);
return 0; return 0;
} else { } else {
@ -688,14 +669,11 @@ class MySystem: public System {
} }
virtual void dispose() { virtual void dispose() {
assert(this, count == 0);
CloseHandle(mutex); CloseHandle(mutex);
::free(this); ::free(this);
} }
HANDLE mutex; HANDLE mutex;
unsigned limit;
unsigned count;
}; };
} // namespace } // namespace
@ -703,9 +681,9 @@ class MySystem: public System {
namespace vm { namespace vm {
System* System*
makeSystem(unsigned heapSize) makeSystem()
{ {
return new (malloc(sizeof(MySystem))) MySystem(heapSize); return new (malloc(sizeof(MySystem))) MySystem();
} }
} // namespace vm } // namespace vm

View File

@ -17,9 +17,12 @@ class Zone: public Allocator {
uint8_t data[0]; uint8_t data[0];
}; };
Zone(System* s, Allocator* a, unsigned minimumFootprint): Zone(System* s, Allocator* allocator, void* context, bool executable,
unsigned minimumFootprint):
s(s), s(s),
a(a), allocator(allocator),
context(context),
executable(executable),
segment(0), segment(0),
position(0), position(0),
minimumFootprint(minimumFootprint < sizeof(Segment) ? 0 : minimumFootprint(minimumFootprint < sizeof(Segment) ? 0 :
@ -33,11 +36,11 @@ class Zone: public Allocator {
void dispose() { void dispose() {
for (Segment* seg = segment, *next; seg; seg = next) { for (Segment* seg = segment, *next; seg; seg = next) {
next = seg->next; next = seg->next;
a->free(seg, sizeof(Segment) + seg->size); allocator->free(seg, sizeof(Segment) + seg->size, executable);
} }
} }
bool ensure(unsigned space) { bool ensure(void* context, unsigned space, bool executable) {
if (segment == 0 or position + space > segment->size) { if (segment == 0 or position + space > segment->size) {
unsigned size = max unsigned size = max
(space, max (space, max
@ -48,10 +51,10 @@ class Zone: public Allocator {
size = (size + (LikelyPageSizeInBytes - 1)) size = (size + (LikelyPageSizeInBytes - 1))
& ~(LikelyPageSizeInBytes - 1); & ~(LikelyPageSizeInBytes - 1);
void* p = a->tryAllocate(size); void* p = allocator->tryAllocate(context, size, executable);
if (p == 0) { if (p == 0) {
size = space + sizeof(Segment); size = space + sizeof(Segment);
void* p = a->tryAllocate(size); void* p = allocator->tryAllocate(context, size, executable);
if (p == 0) { if (p == 0) {
return false; return false;
} }
@ -63,9 +66,11 @@ class Zone: public Allocator {
return true; return true;
} }
virtual void* tryAllocate(unsigned size) { virtual void* tryAllocate(void* context, unsigned size, bool executable) {
assert(s, executable == this->executable);
size = pad(size); size = pad(size);
if (ensure(size)) { if (ensure(context, size, executable)) {
void* r = segment->data + position; void* r = segment->data + position;
position += size; position += size;
return r; return r;
@ -74,19 +79,27 @@ class Zone: public Allocator {
} }
} }
virtual void* allocate(unsigned size) { virtual void* allocate(void* context, unsigned size, bool executable) {
void* p = tryAllocate(size); assert(s, executable == this->executable);
void* p = tryAllocate(context, size, executable);
expect(s, p); expect(s, p);
return p; return p;
} }
virtual void free(const void*, unsigned) { virtual void free(const void*, unsigned, bool) {
// not supported // not supported
abort(s); abort(s);
} }
void* allocate(unsigned size) {
return allocate(context, size, executable);
}
System* s; System* s;
Allocator* a; Allocator* allocator;
void* context;
bool executable;
Segment* segment; Segment* segment;
unsigned position; unsigned position;
unsigned minimumFootprint; unsigned minimumFootprint;