corda/src/zone.h
Joel Dice 453ceb42ab implement lazy class/field/method resolution in JIT compiler
Unlike the interpreter, the JIT compiler tries to resolve all the
symbols referenced by a method when compiling that method.  However,
this can backfire if a symbol cannot be resolved: we end up throwing
an e.g. NoClassDefFoundError for code which may never be executed.
This is particularly troublesome for code which supports multiple
APIs, choosing one at runtime.

The solution is to defer to stub code for symbols which can't be
resolved at JIT compile time.  Such a stub will try again at runtime
to resolve the needed symbol and throw an appropriate error if it
still can't be found.
2011-03-15 18:07:13 -06:00

111 lines
2.3 KiB
C++

/* Copyright (c) 2008, Avian Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice appear
in all copies.
There is NO WARRANTY for this software. See license.txt for
details. */
#ifndef ZONE_H
#define ZONE_H
#include "system.h"
#include "allocator.h"
namespace vm {
class Zone: public Allocator {
public:
class Segment {
public:
Segment(Segment* next, unsigned size): next(next), size(size) { }
Segment* next;
uintptr_t size;
uint8_t data[0];
};
Zone(System* s, Allocator* allocator, unsigned minimumFootprint):
s(s),
allocator(allocator),
segment(0),
position(0),
minimumFootprint(minimumFootprint < sizeof(Segment) ? 0 :
minimumFootprint - sizeof(Segment))
{ }
~Zone() {
dispose();
}
void dispose() {
for (Segment* seg = segment, *next; seg; seg = next) {
next = seg->next;
allocator->free(seg, sizeof(Segment) + seg->size);
}
segment = 0;
}
bool ensure(unsigned space) {
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);
if (p == 0) {
size = space + sizeof(Segment);
void* p = allocator->tryAllocate(size);
if (p == 0) {
return false;
}
}
segment = new (p) Segment(segment, size - sizeof(Segment));
position = 0;
}
return true;
}
virtual void* tryAllocate(unsigned size) {
size = pad(size);
if (ensure(size)) {
void* r = segment->data + position;
position += size;
return r;
} else {
return 0;
}
}
virtual void* allocate(unsigned size) {
void* p = tryAllocate(size);
expect(s, p);
return p;
}
virtual void free(const void*, unsigned) {
// not supported
abort(s);
}
System* s;
Allocator* allocator;
void* context;
Segment* segment;
unsigned position;
unsigned minimumFootprint;
};
} // namespace vm
#endif//ZONE_H